:root{
    --bg:#ffffff;
    --bg-hover:#f7f9f9;
    --bg-elevated:#f7f9f9;
    --border:#eff3f4;
    --text:#0f1419;
    --text-secondary:#536471;
    --accent:#1d9bf0;
    --accent-hover:#1a8cd8;
    --accent-soft:#e8f5fe;
    --red:#f4212e;
    --red-soft:#fde8ea;
    --green:#00ba7c;
    --green-soft:#e5f9f2;
    --amber:#ffad1f;
    --amber-soft:#fff5e0;
    --radius-pill:9999px;
    --radius-card:16px;
    --header-bg:rgba(255,255,255,.9);
    color-scheme:light;
    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  }
  /* ---------- 다크 모드 팔레트 (X.com "Dim/Lights out" 톤 참고) ---------- */
  [data-theme="dark"]{
    --bg:#000000;
    --bg-hover:#16181c;
    --bg-elevated:#16181c;
    --border:#2f3336;
    --text:#e7e9ea;
    --text-secondary:#71767b;
    --accent:#1d9bf0;
    --accent-hover:#3ba9f5;
    --accent-soft:rgba(29,155,240,.16);
    --red:#f4212e;
    --red-soft:rgba(244,33,46,.16);
    --green:#00ba7c;
    --green-soft:rgba(0,186,124,.16);
    --amber:#ffad1f;
    --amber-soft:rgba(255,173,31,.16);
    --header-bg:rgba(0,0,0,.72);
    color-scheme:dark;
  }
  [data-theme="dark"] body{background:var(--bg);}
  html{background:var(--bg);scrollbar-gutter:stable;}
  *{box-sizing:border-box;}
  html,body{margin:0;padding:0;background:var(--bg);color:var(--text);transition:background-color .15s ease,color .15s ease;touch-action:manipulation;}
  body{font-size:15px;line-height:1.35;-webkit-font-smoothing:antialiased;}
  button{font-family:inherit;cursor:pointer;}
  input,textarea{font-family:inherit;}
  a{color:inherit;text-decoration:none;}
  ::selection{background:var(--accent-soft);}

  /* 주의: overflow-x:hidden을 html/body에 직접 걸면 iOS Safari에서
     position:fixed 요소(모바일 하단 네비게이션 바 등)가 뷰포트에 고정되지 않고
     문서 흐름을 따라가 버리는 유명한 버그가 발생함(스크롤을 맨 아래까지 내려야만
     보이는 증상). 그래서 overflow-x:hidden은 body 대신 #app 래퍼에 건다.
     또한, overflow-x만 hidden으로 주고 overflow-y를 손대지 않으면 스펙상 overflow-y의
     계산값이 'visible'에서 'auto'로 강제 승격되어(120번째 줄 부근 주석 참고) #app이 자기만의
     스크롤 컨테이너가 돼버림. 그러면 실제 스크롤이 일어나는 대상이 window가 아니라 #app이
     되어버려서, sticky 헤더가 엉뚱한 기준으로 붙거나 늘어져 보이고, 탭 전환 시 스크롤 위치를
     되돌리는 코드(resetScrollIfViewChanged 등)도 어긋나는 등 레이아웃이 전반적으로 이상해짐.
     그래서 가로축만 정말로 클리핑하고 세로축에는 스크롤 컨테이너를 만들지 않는
     overflow-x:clip을 쓴다(구형 브라우저를 위해 hidden을 폴백으로 먼저 선언). */
  #app{min-height:100vh;min-height:100dvh;overflow-x:hidden;overflow-x:clip;}

  /* ---------- Auth screen (X.com style, split layout) ---------- */
  .x-auth-wrap{min-height:100vh;display:flex;background:#000;}
  .x-auth-formside{flex:1 1 50%;display:flex;align-items:center;justify-content:center;padding:24px;min-width:0;}
  /* 이미지 없이 순수 검은색 배경. 로고에 마우스를 따라 기울어지는 3D 틸트 효과만 유지. */
  .x-auth-visual{flex:1 1 50%;display:flex;align-items:center;justify-content:center;background:#000;perspective:900px;transition:transform .6s ease-out;position:relative;overflow:hidden;transform-style:preserve-3d;}
  .x-auth-bigmark{height:min(42vw,510px);display:flex;align-items:center;justify-content:center;position:relative;z-index:2;}
  /* 글로우/애니메이션 제거 요청에 따라 잔상 복제 이미지(ghost)는 더 이상 쓰지 않음 */
  .x-auth-bigmark-ghost{display:none;}
  .x-auth-bigmark-main{position:relative;z-index:2;height:100%;display:flex;align-items:center;justify-content:center;}
  .x-auth-bigmark-main .brand-mark-img{}
  .x-auth-card{width:100%;max-width:380px;}
  .x-auth-logo{height:36px;display:flex;align-items:center;justify-content:center;margin-bottom:26px;perspective:500px;}
  .x-auth-logo .brand-mark-img{filter:drop-shadow(0 6px 12px rgba(0,0,0,.55));}
  .brand-mark-img{height:100%;width:auto;display:block;-webkit-user-drag:none;user-select:none;}
  .x-auth-title{font-size:29px;font-weight:800;color:#fff;text-align:center;margin:0 0 30px;letter-spacing:-0.01em;line-height:1.25;}
  .x-input-group{margin-bottom:14px;}
  .x-input-group label{display:block;font-size:12px;color:#71767b;margin-bottom:5px;padding-left:2px;}
  .x-input-group input{width:100%;padding:14px 12px;border:1px solid #333639;border-radius:4px;background:#000;color:#fff;font-size:16px;outline:none;transition:border-color .15s ease,box-shadow .15s ease;}
  .x-input-group input:focus{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent);}
  .x-input-group input::placeholder{color:#4b5155;}
  .x-err-msg{color:#f4212e;font-size:13px;margin:-4px 0 14px;}
  .x-btn-solid{width:100%;padding:13px;border:none;border-radius:9999px;background:#fff;color:#000;font-weight:800;font-size:16px;margin-top:8px;cursor:pointer;transition:background .15s ease;}
  .x-btn-solid:hover{background:#e6e6e6;}
  .x-btn-solid:disabled{opacity:.5;cursor:default;}
  .x-btn-outline{width:100%;padding:13px;border:1px solid #536471;border-radius:9999px;background:transparent;color:#fff;font-weight:800;font-size:16px;margin-top:12px;cursor:pointer;transition:background .15s ease;}
  .x-btn-outline:hover{background:rgba(239,243,244,.1);}
  @media (max-width:820px){
    .x-auth-visual{display:none;}
    .x-auth-formside{flex:1 1 100%;}
  }
  /* ---------- 로그인 성공 직후 스플래시 화면: 검정 배경 + 흰색 N 로고 애니메이션 ---------- */
  .splash-screen{position:fixed;inset:0;background:#000;display:flex;align-items:center;justify-content:center;z-index:9999;overflow:hidden;animation:splash-fade-in .4s ease-out both;}
  .splash-logo{height:min(24vw,220px);position:relative;z-index:1;perspective:900px;transform-style:preserve-3d;display:flex;align-items:center;justify-content:center;}
  .splash-logo .brand-mark-img{height:100%;width:auto;display:block;transform-style:preserve-3d;-webkit-user-drag:none;user-select:none;animation:splash-mark-intro .9s cubic-bezier(.22,.9,.28,1) both,splash-mark-breathe 3.2s ease-in-out 1s infinite;}
  @keyframes splash-fade-in{
    0%{opacity:0;}
    100%{opacity:1;}
  }
  @keyframes splash-mark-intro{
    0%{opacity:0;transform:scale(.35) translateZ(-260px);}
    65%{opacity:1;transform:scale(1.1) translateZ(40px);}
    100%{opacity:1;transform:scale(1) translateZ(0);}
  }
  @keyframes splash-mark-breathe{
    0%,100%{transform:scale(1);}
    50%{transform:scale(1.06);}
  }
  @media (prefers-reduced-motion:reduce){
    .splash-screen,.splash-logo .brand-mark-img{animation:none;}
  }
  /* ---------- 첫 로그인 온보딩 화면: 메뉴별 슬라이드 + 플랫 캐릭터 애니메이션 ---------- */
  .onboard-screen{min-height:100vh;display:flex;align-items:flex-start;align-items:safe center;justify-content:center;background:var(--bg-hover);padding:72px 20px 48px;overflow-y:auto;animation:onboard-fade-in .35s ease-out both;}
  .onboard-card{width:100%;max-width:400px;background:var(--bg-elevated);border:1px solid var(--border);border-radius:20px;padding:24px 22px 20px;box-shadow:0 20px 50px rgba(0,0,0,.08);}
  .onboard-logo{height:26px;display:flex;align-items:center;justify-content:center;margin-bottom:12px;}

  /* 진행 상황 점 */
  .onboard-dots{display:flex;justify-content:center;gap:7px;margin:20px 0;}
  .onboard-dot{width:6px;height:6px;border-radius:50%;background:var(--border);transition:transform .25s,background .25s,width .25s;cursor:pointer;}
  .onboard-dot.done{background:#000;opacity:.4;}
  .onboard-dot.active{background:#000;width:18px;border-radius:3px;}

  /* 슬라이드 뷰포트: 좌우 스와이프로 다음 메뉴 소개를 넘겨볼 수 있음.
     주의: overflow-x:hidden과 overflow-y:visible을 함께 쓰면 스펙상 visible이 auto(클리핑)로
     강제 변환되어 캐릭터 위 말풍선이 항상 잘리는 문제가 있었음. 슬라이드 진입 시 가로 이동폭이
     18px로 미미하고 opacity 페이드와 함께 일어나 티가 나지 않으므로, overflow 제한 자체를 없애
     세로 방향이 실제로 완전히 visible이 되도록 함.*/
  .onboard-slide-viewport{touch-action:pan-y;}
  .onboard-slide{display:flex;flex-direction:column;align-items:center;text-align:center;padding:14px 4px 6px;animation:onboard-slide-in .38s cubic-bezier(.22,.9,.28,1) both;}
  .onboard-char-stage{position:relative;width:132px;height:132px;margin-bottom:4px;cursor:pointer;}
  .onboard-char{width:100%;height:100%;overflow:visible;transition:transform .25s ease;}
  .onboard-char-stage:hover .onboard-char{transform:scale(1.07);}
  .onboard-slide-title{font-weight:800;font-size:18px;margin:5px 0 5px;letter-spacing:-.01em;}
  .onboard-slide-desc{font-size:13.5px;color:var(--text-secondary);line-height:1.55;max-width:280px;min-height:38px;}

  .onboard-nav{display:flex;align-items:center;justify-content:space-between;margin:14px 0 12px;font-size:13px;font-weight:700;}
  .onboard-nav-prev,.onboard-nav-skip{background:none;border:none;color:var(--text-secondary);cursor:pointer;padding:6px 2px;}
  .onboard-nav-prev:hover,.onboard-nav-skip:hover{color:var(--text);}
  .onboard-nav-prev.is-hidden{visibility:hidden;}
  .onboard-cta{width:100%;padding:13px;font-size:16px;}

  /* ---- 호버와 무관하게, 슬라이드가 보일 때 자동으로 떴다 사라지길 반복하는 캐릭터의 짧은 대사(말풍선).
     캐릭터 바로 위, 화살표 꼬리가 캐릭터에 닿을 정도로 최대한 가깝게 배치.
     플랫 디자인: 스케일/이동 없이 페이드만으로 나타났다 사라짐. */
  .onboard-char-stage::after{
    content:attr(data-msg);
    position:absolute;bottom:100%;left:50%;
    margin-bottom:0;
    max-width:130px;
    white-space:normal;
    text-align:center;
    transform:translateX(-50%);
    background:#0f1419;color:#fff;font-size:11.5px;font-weight:700;line-height:1.25;
    padding:5px 12px;border-radius:12px;
    opacity:0;pointer-events:none;z-index:5;
    animation:onboard-bubble-pop 3.6s ease-in-out .5s infinite;
  }
  .onboard-char-stage::before{
    content:'';position:absolute;bottom:100%;left:50%;
    margin-bottom:-2px;
    transform:translateX(-50%);
    border:4px solid transparent;border-top-color:#0f1419;
    opacity:0;pointer-events:none;z-index:5;
    animation:onboard-bubble-pop 3.6s ease-in-out .5s infinite;
  }
  .onboard-char-stage:hover::after,.onboard-char-stage:hover::before{animation-play-state:paused;opacity:1;}
  /* 캐릭터마다 SVG 내부 여백(캐릭터가 시작되는 높이)이 달라서, 타입별로 말풍선/화살표를
     끌어내려 실제 캐릭터 바로 위에 붙도록 보정. */
  .onboard-char-stage[data-char="feed"]::after{margin-bottom:-22px;}
  .onboard-char-stage[data-char="feed"]::before{margin-bottom:-28px;}
  .onboard-char-stage[data-char="coin"]::after{margin-bottom:-21px;}
  .onboard-char-stage[data-char="coin"]::before{margin-bottom:-27px;}
  .onboard-char-stage[data-char="shop"]::after{margin-bottom:-34px;}
  .onboard-char-stage[data-char="shop"]::before{margin-bottom:-40px;}
  .onboard-char-stage[data-char="dice"]::after{margin-bottom:-32px;}
  .onboard-char-stage[data-char="dice"]::before{margin-bottom:-38px;}
  .onboard-char-stage[data-char="mail"]::after{margin-bottom:-49px;}
  .onboard-char-stage[data-char="mail"]::before{margin-bottom:-55px;}
  @keyframes onboard-bubble-pop{
    0%{opacity:0;}
    14%{opacity:1;}
    72%{opacity:1;}
    90%{opacity:0;}
    100%{opacity:0;}
  }
  @media (prefers-reduced-motion:reduce){
    .onboard-char-stage::after,.onboard-char-stage::before{animation:none;opacity:1;}
  }

  /* ---- 공통 보조 모션: 그림자, 팔 흔들기 ---- */
  .oc-shadow{animation:oc-shadow 2.4s ease-in-out infinite;transform-origin:center;}
  @keyframes oc-shadow{0%,100%{transform:scale(1);opacity:.5;}50%{transform:scale(.82);opacity:.3;}}
  .oc-arm-l{animation:oc-wave-l 2.4s ease-in-out infinite;}
  .oc-arm-r{animation:oc-wave-r 2.4s ease-in-out infinite;}
  @keyframes oc-wave-l{0%,100%{transform:rotate(0deg);}50%{transform:rotate(-8deg);}}
  @keyframes oc-wave-r{0%,100%{transform:rotate(0deg);}50%{transform:rotate(8deg);}}

  /* ---- 게시물 피드: 통통 뜨며 화면 속 글이 채워지고, 알림 뱃지가 콩닥임 ---- */
  .oc-feed-bounce{animation:oc-feed-bob 2.4s ease-in-out infinite;transform-origin:100px 180px;}
  @keyframes oc-feed-bob{0%,100%{transform:translateY(0);}50%{transform:translateY(-8px);}}
  .oc-type-feed .oc-arm-l{transform-origin:62px 110px;}
  .oc-type-feed .oc-arm-r{transform-origin:138px 110px;}
  .oc-feed-line{stroke-dasharray:40;stroke-dashoffset:40;animation:oc-line-write 2.4s ease-in-out infinite;}
  .oc-feed-line-1{animation-delay:.1s;}
  .oc-feed-line-2{animation-delay:.5s;}
  @keyframes oc-line-write{0%{stroke-dashoffset:40;}30%,60%{stroke-dashoffset:0;}90%,100%{stroke-dashoffset:40;}}
  .oc-feed-ping{animation:oc-ping-pulse 1.5s ease-in-out infinite;transform-origin:134px 50px;}
  @keyframes oc-ping-pulse{0%,100%{transform:scale(1);}50%{transform:scale(1.25);}}
  .onboard-char-stage:hover .oc-feed-bounce{animation:oc-feed-bob-hover .55s ease-in-out infinite;}
  @keyframes oc-feed-bob-hover{0%,100%{transform:translateY(0) rotate(0deg);}50%{transform:translateY(-15px) rotate(4deg);}}
  .onboard-char-stage:hover .oc-feed-ping{animation:oc-ping-pulse .4s ease-in-out infinite;}

  /* ---- 포인트: 스스로 동전인 캐릭터가 튀어오르며 뒤집힘, 반짝임 추가 ---- */
  .oc-coin-hop{animation:oc-coin-hop 1.8s ease-in-out infinite;transform-origin:100px 178px;}
  @keyframes oc-coin-hop{0%,100%{transform:translateY(0) rotateY(0deg);}50%{transform:translateY(-14px) rotateY(180deg);}}
  .oc-type-coin .oc-arm-l{transform-origin:60px 108px;}
  .oc-type-coin .oc-arm-r{transform-origin:140px 108px;}
  .oc-coin-sparkle{animation:oc-sparkle-twinkle 1.6s ease-in-out infinite;transform-origin:154px 56px;}
  @keyframes oc-sparkle-twinkle{0%,100%{opacity:.3;transform:scale(.7) rotate(0deg);}50%{opacity:1;transform:scale(1.15) rotate(25deg);}}
  .onboard-char-stage:hover .oc-coin-hop{animation:oc-coin-hop-hover .55s ease-in-out infinite;}
  @keyframes oc-coin-hop-hover{0%,100%{transform:translateY(0) rotateY(0deg);}50%{transform:translateY(-22px) rotateY(360deg);}}
  .onboard-char-stage:hover .oc-coin-sparkle{animation:oc-sparkle-twinkle .5s ease-in-out infinite;}

  /* ---- 포인트샵: 상자가 살짝 들썩이고 뚜껑 리본이 팔랑임 ---- */
  .oc-shop-bounce{animation:oc-bob 2.6s ease-in-out infinite;transform-origin:100px 182px;}
  @keyframes oc-bob{0%,100%{transform:translateY(0);}50%{transform:translateY(-6px);}}
  .oc-type-shop .oc-arm-l{transform-origin:64px 128px;}
  .oc-type-shop .oc-arm-r{transform-origin:136px 128px;}
  .oc-shop-lid{animation:oc-lid-wiggle 2.2s ease-in-out infinite;transform-origin:100px 108px;}
  @keyframes oc-lid-wiggle{0%,100%{transform:rotate(0deg) translateY(0);}50%{transform:rotate(-4deg) translateY(-3px);}}
  .onboard-char-stage:hover .oc-shop-bounce{animation:oc-bob-fast .6s ease-in-out infinite;}
  @keyframes oc-bob-fast{0%,100%{transform:translateY(0);}50%{transform:translateY(-11px);}}
  .onboard-char-stage:hover .oc-shop-lid{animation:oc-lid-pop-hover .5s ease-in-out infinite;}
  @keyframes oc-lid-pop-hover{0%,100%{transform:rotate(0deg) translateY(0);}50%{transform:rotate(-16deg) translateY(-11px);}}

  /* ---- 미니게임: 주사위가 통통 구르며 회전 ---- */
  .oc-dice-roll{animation:oc-dice-roll 1.6s ease-in-out infinite;transform-origin:100px 154px;}
  @keyframes oc-dice-roll{0%,100%{transform:translateY(0) rotate(0deg);}30%{transform:translateY(-12px) rotate(-16deg);}55%{transform:translateY(0) rotate(10deg);}80%{transform:translateY(-4px) rotate(-4deg);}}
  .oc-type-dice .oc-arm-l{transform-origin:60px 118px;}
  .oc-type-dice .oc-arm-r{transform-origin:140px 118px;}
  .onboard-char-stage:hover .oc-dice-roll{animation:oc-dice-roll-hover .5s ease-in-out infinite;}
  @keyframes oc-dice-roll-hover{0%,100%{transform:translateY(0) rotate(0deg);}30%{transform:translateY(-20px) rotate(-32deg);}55%{transform:translateY(0) rotate(20deg);}80%{transform:translateY(-8px) rotate(-8deg);}}

  /* ---- DM: 편지봉투가 날개짓하며 두둥실 떠다님 ---- */
  .oc-mail-float{animation:oc-mail-float 2.4s ease-in-out infinite;transform-origin:100px 178px;}
  @keyframes oc-mail-float{0%,100%{transform:translateY(0);}50%{transform:translateY(-12px);}}
  .oc-mail-wing-l{animation:oc-flap-l 1s ease-in-out infinite;transform-origin:64px 106px;}
  .oc-mail-wing-r{animation:oc-flap-r 1s ease-in-out infinite;transform-origin:136px 106px;}
  @keyframes oc-flap-l{0%,100%{transform:rotate(0deg) scaleX(1);}50%{transform:rotate(14deg) scaleX(.82);}}
  @keyframes oc-flap-r{0%,100%{transform:rotate(0deg) scaleX(1);}50%{transform:rotate(-14deg) scaleX(.82);}}
  .oc-mail-flap{animation:oc-flap-open 2s ease-in-out infinite;transform-origin:100px 80px;}
  @keyframes oc-flap-open{0%,100%{transform:scaleY(1);}50%{transform:scaleY(.75);}}
  .onboard-char-stage:hover .oc-mail-float{animation:oc-mail-float-hover .6s ease-in-out infinite;}
  @keyframes oc-mail-float-hover{0%,100%{transform:translateY(0);}50%{transform:translateY(-20px);}}
  .onboard-char-stage:hover .oc-mail-wing-l{animation:oc-flap-l .32s ease-in-out infinite;}
  .onboard-char-stage:hover .oc-mail-wing-r{animation:oc-flap-r .32s ease-in-out infinite;}

  @keyframes onboard-fade-in{
    0%{opacity:0;}
    100%{opacity:1;}
  }
  @keyframes onboard-slide-in{
    0%{opacity:0;transform:translateX(18px);}
    100%{opacity:1;transform:translateX(0);}
  }
  @media (prefers-reduced-motion:reduce){
    .onboard-screen,.onboard-slide,.onboard-char *{animation:none !important;}
    .onboard-char-stage:hover .onboard-char{transform:none;}
  }
  .field{margin-bottom:14px;}
  .field label{display:block;font-size:12px;color:var(--text-secondary);margin-bottom:5px;font-weight:600;}
  .field input,.field textarea{width:100%;padding:11px 13px;border:1px solid var(--border);border-radius:10px;font-size:15px;background:var(--bg);color:var(--text);outline:none;}
  .field input:focus,.field textarea:focus{border-color:var(--accent);}
  .field textarea{resize:vertical;min-height:70px;}
  .btn{border:none;border-radius:var(--radius-pill);padding:11px 20px;font-weight:700;font-size:15px;}
  .btn-primary{background:var(--text);color:var(--bg);width:100%;}
  .btn-primary:hover{opacity:.88;}
  .btn-primary:disabled{opacity:.4;cursor:not-allowed;}
  .btn-accent{background:var(--accent);color:#fff;}
  .btn-accent:hover{background:var(--accent-hover);}
  .btn-ghost{background:transparent;color:var(--text);border:1px solid var(--border);}
  .btn-ghost:hover{background:var(--bg-hover);}
  .btn-sm{padding:6px 14px;font-size:13px;}
  .btn-icon{padding:8px;display:inline-flex;align-items:center;justify-content:center;}
  .btn-icon svg{display:block;}
  .err-msg{color:var(--red);font-size:13px;margin:-6px 0 12px;font-weight:600;}
  .auth-switch{text-align:center;font-size:13.5px;color:var(--text-secondary);margin:22px 0 0;}
  .auth-switch a{color:var(--accent);font-weight:700;cursor:pointer;}
  .auth-switch a:hover{text-decoration:underline;}

  .confirm-box{text-align:center;padding:36px 24px;border:1px solid var(--border);border-radius:20px;}
  .confirm-icon{width:56px;height:56px;border-radius:50%;background:var(--accent-soft);color:var(--accent);display:flex;align-items:center;justify-content:center;margin:0 auto 16px;font-size:26px;}
  .confirm-box h3{margin:0 0 8px;font-size:19px;}
  .confirm-box p{margin:0 0 20px;color:var(--text-secondary);font-size:14px;line-height:1.6;}

  /* ---------- App shell (X layout) ---------- */
  .shell{max-width:1140px;margin:0 auto;display:grid;grid-template-columns:88px 600px 350px;justify-content:center;min-height:100vh;min-height:100dvh;}
  @media (max-width:1000px){.shell{grid-template-columns:88px 1fr;}}
  @media (max-width:640px){.shell{grid-template-columns:1fr;}}

  .sidebar{border-right:1px solid var(--border);padding:8px 12px 8px 8px;display:flex;flex-direction:column;position:sticky;top:0;height:100vh;}
  .side-nav{display:flex;flex-direction:column;gap:2px;}
  .side-link{display:flex;align-items:center;justify-content:center;gap:0;padding:13px;border-radius:var(--radius-pill);font-size:19px;font-weight:600;color:var(--text);position:relative;}
  .side-link:hover{background:var(--bg-hover);}
  .side-link.active{font-weight:800;}
  .side-link .ic{width:38px;height:38px;display:flex;align-items:center;justify-content:center;flex-shrink:0;position:relative;}
  .side-link .ic svg{width:30px;height:30px;stroke-width:1.4;}
  /* 새 글/DM 알림 표시용 파란 점 배지. 아이콘 우상단에 겹쳐 그림 */
  .dot-badge{position:absolute;top:-2px;right:-2px;width:10px;height:10px;border-radius:50%;background:var(--accent);border:2px solid var(--bg);}
  .side-link span.label{display:none;}
  .side-logo-link{margin-bottom:10px;padding:12px;}
  .side-logo-img{height:30px;width:auto;display:block;}
  .inline-ic{display:inline-flex;vertical-align:-4px;margin-right:2px;}
  .inline-ic svg{display:block;}
  .post-actions .act{display:flex;align-items:center;gap:6px;}
  .post-actions .act svg{display:block;flex-shrink:0;}
  .confirm-icon svg{display:block;}
  .verified{display:inline-flex;vertical-align:-2px;}
  .side-link .badge{background:var(--accent);color:#fff;font-size:11px;font-weight:800;border-radius:999px;padding:1px 6px;position:absolute;top:4px;right:4px;margin-left:0;}
  .side-bottom{margin-top:auto;display:flex;flex-direction:column;align-items:center;gap:6px;}
  .side-theme-btn{color:var(--text-secondary);}
  .side-theme-btn:hover{background:var(--bg-hover);color:var(--accent);}
  .side-logout-btn{color:var(--text-secondary);}
  .side-logout-btn:hover{background:var(--red-soft);color:var(--red);}
  @media (max-width:640px){
    .sidebar{position:fixed;left:0;right:0;bottom:0;top:auto;height:auto;width:100%;flex-direction:row;align-items:center;border-right:none;border-top:1px solid var(--border);background:var(--bg);z-index:50;padding:6px 4px calc(6px + env(safe-area-inset-bottom,0px));}
    .side-nav{flex-direction:row;flex:1;justify-content:center;align-items:center;gap:14px;}
    .side-logo-link{display:none;}
    .side-bottom{display:none;}
    /* 프로필은 모바일 상단바의 프로필 메뉴로 이동했으므로 하단 탭바에서는 중복 노출하지 않음
       (데스크톱 사이드바에서는 계속 보여줌) */
    .side-link-profile{display:none;}
    .side-link .ic{width:29px;height:29px;}
    .side-link .ic svg{width:23px;height:23px;}
  }
  /* 메인 페이지 전용 모바일 상단바: 왼쪽 로고 홈버튼 · 오른쪽 프로필 메뉴(로그아웃 포함).
     데스크톱에서는 항상 숨김. */
  .mobile-topbar{display:none;}
  @media (max-width:640px){
    .mobile-topbar{
      display:flex;align-items:center;justify-content:space-between;
      position:fixed;top:0;left:0;right:0;z-index:50;
      padding:10px 14px;padding-top:calc(10px + env(safe-area-inset-top,0px));
      background:var(--bg);border-bottom:1px solid var(--border);
    }
    .mobile-topbar-profile-wrap{position:relative;display:flex;}
    .mobile-topbar-icon-btn{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:50%;border:none;background:transparent;cursor:pointer;color:var(--text);padding:0;}
    .mobile-topbar-icon-btn:hover{background:var(--bg-hover);}
    .mobile-topbar-icon-btn svg{width:23px;height:23px;}
    .mobile-topbar-logo-img{height:23px;width:auto;display:block;}
    .mobile-profile-menu{position:absolute;top:calc(100% + 8px);right:0;min-width:170px;background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--radius-card);padding:6px;display:none;flex-direction:column;gap:2px;z-index:60;box-shadow:0 8px 24px rgba(0,0,0,.15);}
    .mobile-profile-menu.open{display:flex;}
    .mobile-profile-menu-item{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:10px;border:none;background:transparent;font-size:13.5px;font-weight:700;color:var(--text);cursor:pointer;text-align:left;width:100%;}
    .mobile-profile-menu-item svg{width:17px;height:17px;flex-shrink:0;}
    .mobile-profile-menu-item:hover{background:var(--bg-hover);}
    .mobile-profile-menu-item.logout-item{color:var(--red);}
    .mobile-profile-menu-item.logout-item:hover{background:var(--red-soft);}
    /* 주의: scrim은 반드시 .mobile-topbar(z-index:50)보다 낮은 z-index를 가져야 함.
       그렇지 않으면 scrim이 상단바 스태킹 컨텍스트 전체를 덮어써서 프로필 메뉴 안의
       버튼 클릭이 막히는 버그가 생김(실제로 이 문제 때문에 프로필 메뉴가 "작동 안 함"). */
    .mobile-menu-scrim{position:fixed;inset:0;z-index:45;background:transparent;}
    .main-col-with-topbar{padding-top:54px;}
    .main-col-with-topbar .main-header{top:54px;}
  }
  /* 모든 아이콘 호버 애니메이션 (입체감 있는 통통 튀는 느낌) */
  .ic svg,.inline-ic svg,.verified svg,.post-actions .act svg,.btn-icon svg,.file-attach-btn svg,.icon-flat-btn svg,.back-link svg,.attach-chip svg{transition:transform .35s cubic-bezier(.34,1.56,.64,1),filter .35s ease;transform-origin:center;}
  .side-link:hover .ic svg{transform:scale(1.3) rotate(-12deg) translateY(-2px);filter:drop-shadow(0 4px 6px rgba(0,0,0,.18));}
  .inline-ic:hover svg{transform:scale(1.4) rotate(10deg);}
  .verified:hover svg{transform:scale(1.45) rotate(14deg);}
  .post-actions .act:hover svg{transform:scale(1.35) rotate(-12deg) translateY(-2px);filter:drop-shadow(0 3px 5px rgba(0,0,0,.16));}
  .btn-icon:hover svg{transform:scale(1.35) rotate(-20deg) translateY(-3px);filter:drop-shadow(0 4px 7px rgba(0,0,0,.22));}
  .file-attach-btn:hover svg{transform:scale(1.3) rotate(12deg) translateY(-1px);}
  .icon-flat-btn:hover svg{transform:scale(1.25) rotate(10deg) translateY(-1px);}
  .back-link:hover svg{transform:translateX(-6px) scale(1.2);}
  .attach-chip:hover svg{transform:scale(1.3) rotate(-10deg);}

  .avatar{width:40px;height:40px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-weight:800;color:#fff;font-size:16px;flex-shrink:0;position:relative;}
  .avatar-editable{cursor:pointer;}
  .avatar-edit-badge{position:absolute;bottom:-2px;right:-2px;width:18px;height:18px;border-radius:50%;background:var(--text);color:var(--bg);display:flex;align-items:center;justify-content:center;border:2px solid var(--bg);}
  .avatar-edit-badge svg{width:10px;height:10px;}
  .avatar-sm{width:34px;height:34px;font-size:13px;}
  .avatar-lg{width:72px;height:72px;font-size:26px;}

  .who{display:flex;flex-direction:column;overflow:hidden;}
  .who .name{font-weight:800;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  .who .handle{color:var(--text-secondary);font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}

  .main-col{border-right:1px solid var(--border);min-height:100vh;max-width:100%;overflow-x:hidden;overflow-x:clip;}
  @media (max-width:1000px){.main-col{border-right:none;}}
  /* 하단 고정 네비게이션 바(.sidebar)의 실제 높이는 아이콘/패딩(약 64px)에 더해
     노치/홈 인디케이터가 있는 기기의 safe-area-inset-bottom만큼 더 커진다.
     이 padding-bottom이 64px로 고정돼 있으면 그 safe-area만큼 하단 콘텐츠가
     네비게이션 바에 가려지는 문제가 생기므로, 반드시 safe-area-inset-bottom을 더해줘야 함. */
  @media (max-width:640px){.main-col{padding-bottom:calc(68px + env(safe-area-inset-bottom,0px));}}
  .main-header{position:sticky;top:0;background:var(--header-bg);backdrop-filter:blur(8px);border-bottom:1px solid var(--border);padding:14px 16px;z-index:5;}
  .main-header h2{margin:0;font-size:19px;font-weight:800;}
  .main-header .sub{color:var(--text-secondary);font-size:12.5px;margin-top:1px;}

  .composer{padding:14px 16px;border-bottom:8px solid var(--bg-elevated);}
  .composer-row{display:flex;gap:15px;}
  .composer textarea{flex:1;border:none;resize:none;font-size:17px;outline:none;min-height:70px;color:var(--text);background:transparent;}
  .composer-meta{display:flex;align-items:center;gap:8px;margin-top:8px;flex-wrap:wrap;}
  .composer-send-inline{margin-left:auto;}
  .file-attach-btn{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border);border-radius:999px;padding:7px 14px;font-size:13px;font-weight:600;color:var(--text-secondary);cursor:pointer;}
  .file-attach-btn:hover{background:var(--bg-hover);color:var(--accent);border-color:var(--accent);}
  .attach-preview{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;}
  .attach-chip{display:inline-flex;align-items:center;gap:6px;background:var(--bg-elevated);border-radius:999px;padding:6px 12px;font-size:12.5px;color:var(--text);max-width:260px;}
  .attach-chip .fname{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  .attach-chip .x{cursor:pointer;color:var(--text-secondary);font-weight:800;margin-left:2px;}
  .attach-chip .x:hover{color:var(--red);}
  .attach-thumb{position:relative;width:68px;height:68px;border-radius:12px;overflow:hidden;background:var(--bg-elevated);flex-shrink:0;}
  .attach-thumb img{width:100%;height:100%;object-fit:cover;display:block;}
  .attach-thumb-edit{position:absolute;bottom:3px;right:3px;width:22px;height:22px;border-radius:50%;background:rgba(0,0,0,.65);color:#fff;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;}
  .attach-thumb-edit:hover{background:rgba(0,0,0,.85);}
  .attach-thumb-edit svg{width:13px;height:13px;}
  .attach-thumb-remove{position:absolute;top:3px;right:3px;width:18px;height:18px;border-radius:50%;background:rgba(0,0,0,.6);color:#fff;border:none;font-size:11px;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;padding:0;}
  /* ---------- 여러 장 이미지 첨부 미리보기 ---------- */
  .attach-multi-grid{display:flex;flex-wrap:wrap;gap:8px;}
  .attach-multi-item{position:relative;width:68px;height:68px;border-radius:12px;overflow:hidden;background:var(--bg-elevated);flex-shrink:0;}
  .attach-multi-item img{width:100%;height:100%;object-fit:cover;display:block;}
  .attach-multi-count{width:100%;font-size:12px;color:var(--text-secondary);margin-top:2px;}
  /* ---------- 피드에 여러 장 이미지가 있을 때 대표 이미지 위 "1/N" 배지 ---------- */
  .post-media-count-badge{position:absolute;top:10px;right:10px;background:rgba(0,0,0,.65);color:#fff;font-size:12px;font-weight:700;padding:3px 9px;border-radius:999px;pointer-events:none;}
  .lightbox-nav-btn{position:fixed;top:50%;transform:translateY(-50%);width:44px;height:44px;border-radius:50%;border:none;background:rgba(255,255,255,.12);color:#fff;font-size:20px;cursor:pointer;z-index:210;display:flex;align-items:center;justify-content:center;}
  .lightbox-nav-btn:hover{background:rgba(255,255,255,.22);}
  .lightbox-nav-btn.prev{left:16px;}
  .lightbox-nav-btn.next{right:16px;}
  .lightbox-counter{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:rgba(255,255,255,.12);color:#fff;font-size:13px;font-weight:600;padding:6px 14px;border-radius:999px;z-index:210;}

  /* ---------- 썸네일 편집기(크롭/확대축소) ---------- */
  .cropper-viewport{width:260px;height:260px;margin:6px auto 0;border-radius:16px;overflow:hidden;background:#000;position:relative;cursor:grab;touch-action:none;}
  .cropper-viewport:active{cursor:grabbing;}
  .cropper-viewport img{position:absolute;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;pointer-events:none;max-width:none;}
  .cropper-zoom{width:100%;margin-top:14px;accent-color:var(--text);}
  .icon-value-btn{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border);border-radius:999px;padding:7px 14px;font-size:13px;font-weight:700;color:var(--text-secondary);cursor:pointer;background:var(--bg);transition:background .15s ease,color .15s ease,border-color .15s ease,transform .1s ease;}
  .icon-value-btn:hover{background:var(--bg-hover);color:var(--accent);border-color:var(--accent);}
  .icon-value-btn:active{transform:scale(.95);}
  .icon-value-btn svg{width:15px;height:15px;}
  .icon-flat-btn{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:none;background:none;border-radius:50%;color:var(--text-secondary);cursor:pointer;transition:background .15s ease,color .15s ease,transform .1s ease;}
  .icon-flat-btn:hover{background:var(--bg-hover);color:var(--accent);}
  .icon-flat-btn:active{transform:scale(.9);}
  .icon-flat-btn.is-set{color:var(--accent);}
  .icon-flat-btn svg{width:18px;height:18px;}
  .icon-flat-btn-send{width:38px;height:38px;background:#000;color:#fff;}
  .icon-flat-btn-send:hover{background:#000;color:#fff;opacity:.85;}
  .icon-flat-btn-send:disabled{opacity:.4;cursor:default;}
  .icon-flat-btn-send:disabled:hover{background:#000;}
  .side-theme-btn,.side-logout-btn{width:38px;height:38px;}
  .side-theme-btn svg,.side-logout-btn svg{width:30px;height:30px;}
  .btn-black{background:#000;color:#fff;}
  .btn-black:hover{background:#262626;}

  .post{padding:14px 16px;border-bottom:1px solid var(--border);display:flex;gap:12px;}
  .post-pinned{background:var(--accent-soft);}
  .post:hover{background:rgba(0,0,0,0.015);}
  .post-body{flex:1;min-width:0;}
  .post-headline{display:flex;align-items:center;gap:6px;font-size:14.5px;flex-wrap:wrap;}
  .author-link{cursor:pointer;transition:transform .35s cubic-bezier(.34,1.56,.64,1),opacity .2s ease,box-shadow .35s ease;}
  .avatar.author-link:hover{transform:scale(1.15) rotate(-6deg);box-shadow:0 5px 12px rgba(0,0,0,.2);}
  .name-group.author-link{display:inline-flex;align-items:center;gap:4px;border-radius:6px;}
  .name-group.author-link:hover{opacity:.7;transform:translateY(-1px);}
  .name-group.author-link:hover .name{text-decoration:underline;}
  .post-headline .name{font-weight:800;}
  .post-headline .handle,.post-headline .dot,.post-headline .time{color:var(--text-secondary);}
  .verified{color:var(--accent);font-size:13px;}
  .post-text{margin:2px 0 8px;font-size:15px;white-space:pre-wrap;word-break:break-word;}
  .post-media{border:1px solid var(--border);border-radius:16px;overflow:hidden;margin-top:15px;margin-bottom:8px;position:relative;}
  .post-media img,.post-media video{width:100%;display:block;max-height:460px;object-fit:cover;background:#000;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;pointer-events:auto;}
  .media-expand-btn{position:absolute;right:10px;bottom:10px;width:32px;height:32px;border-radius:50%;border:none;background:rgba(0,0,0,.55);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;backdrop-filter:blur(2px);transition:background .15s ease,transform .15s ease;}
  .media-expand-btn:hover{background:rgba(0,0,0,.75);transform:scale(1.08);}
  .media-expand-btn svg{width:15px;height:15px;}
  .media-lightbox-overlay{position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.92);display:flex;align-items:center;justify-content:center;}
  .media-lightbox-scroll{max-width:100vw;max-height:100vh;overflow:auto;display:flex;align-items:center;justify-content:center;}
  .media-lightbox-scroll img{display:block;width:auto;height:auto;max-width:none;max-height:none;-webkit-user-select:none;user-select:none;-webkit-touch-callout:none;}
  .media-lightbox-scroll video{display:block;width:auto;height:auto;max-width:96vw;max-height:96vh;}
  .media-lightbox-close{position:fixed;top:16px;right:20px;width:40px;height:40px;border-radius:50%;border:none;background:rgba(255,255,255,.12);color:#fff;font-size:18px;cursor:pointer;z-index:210;}
  .media-lightbox-close:hover{background:rgba(255,255,255,.22);}
  .post-locked{background:linear-gradient(135deg,#f4f4f5,#e9e9ec);display:flex;align-items:center;justify-content:center;min-height:220px;padding:24px;}
  [data-theme="dark"] .post-locked{background:linear-gradient(135deg,#20242a,#16181c);}
  [data-theme="dark"] .avatar{box-shadow:0 0 0 1px rgba(255,255,255,.12);}
  .post-locked-inner{text-align:center;}
  .post-actions{display:flex;gap:36px;color:var(--text-secondary);font-size:13px;margin-top:4px;}
  .post-actions .act{display:flex;align-items:center;gap:6px;}
  .post-actions .act.likeable{cursor:pointer;}
  .post-actions .act.likeable:hover{color:var(--red);}
  .post-actions .act.liked{color:var(--red);font-weight:700;}

  .empty{padding:60px 24px;text-align:center;color:var(--text-secondary);}
  .empty .big{font-size:22px;font-weight:800;color:var(--text);margin-bottom:8px;}

  .right-col{padding:12px;position:sticky;top:0;height:100vh;overflow-y:auto;}
  @media (max-width:1000px){.right-col{display:none;}}
  .panel{background:var(--bg-elevated);border-radius:var(--radius-card);padding:14px;margin-bottom:14px;}
  /* ---------- 관리자 통계 대시보드 ----------
     auto-fill+minmax는 일부 모바일 브라우저에서 트랙 개수/너비 계산이 꼬여 그리드 전체가
     화면 폭보다 넓게 그려지는 문제가 있어서, 화면 폭 구간별로 컬럼 수를 명시적으로 고정함. */
  .stats-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:14px 16px 0;max-width:100%;}
  @media (min-width:520px){.stats-cards{grid-template-columns:repeat(3,minmax(0,1fr));}}
  .stats-card{background:var(--bg-elevated);border-radius:14px;padding:14px;min-width:0;}
  .stats-card-value{font-size:20px;font-weight:800;}
  .stats-card-label{font-size:12px;color:var(--text-secondary);margin-top:2px;}
  .stats-section{padding:18px 16px 0;max-width:100%;}
  .stats-section-title{font-size:14px;font-weight:800;margin-bottom:10px;}
  .stats-section-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;padding:0 16px;}
  @media (max-width:720px){.stats-section-row{grid-template-columns:1fr;}}
  .stats-chart{display:flex;align-items:flex-end;gap:6px;height:110px;padding:10px;background:var(--bg-elevated);border-radius:14px;overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%;}
  .stats-bar-col{flex:1 1 26px;min-width:26px;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;}
  .stats-bar{width:100%;max-width:20px;background:var(--accent);border-radius:4px 4px 0 0;min-height:2px;}
  .stats-bar-label{font-size:11.5px;color:var(--text-secondary);margin-top:4px;white-space:nowrap;}
  .stats-table{background:var(--bg-elevated);border-radius:14px;overflow:hidden;max-width:100%;}
  .stats-table-row{display:flex;align-items:center;gap:10px;padding:10px 14px;border-bottom:1px solid var(--border);}
  .stats-table-row:last-child{border-bottom:none;}
  .stats-rank{font-weight:800;color:var(--text-secondary);width:16px;flex-shrink:0;}
  .stats-table-main{flex:1;font-weight:600;font-size:13.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}
  .stats-table-sub{font-size:12.5px;color:var(--text-secondary);display:flex;align-items:center;gap:4px;flex-shrink:0;}
  .stats-table-sub svg{width:14px;height:14px;}
  .panel h4{margin:0 0 10px;font-size:17px;font-weight:800;}
  .status-row{display:flex;justify-content:space-between;align-items:center;padding:8px 0;border-top:1px solid var(--border);font-size:13.5px;}
  .status-row:first-of-type{border-top:none;}
  .pill{padding:3px 10px;border-radius:999px;font-size:12px;font-weight:800;}
  .pill-active{background:var(--green-soft);color:var(--green);}
  .pill-warn{background:var(--amber-soft);color:#996a00;}
  .pill-danger{background:var(--red-soft);color:var(--red);}
  .pill-pending{background:var(--accent-soft);color:var(--accent);}
  .pill-muted{background:var(--border);color:var(--text-secondary);}
  .pill-grade{background:var(--amber-soft);color:#996a00;letter-spacing:.02em;}

  /* ---- 출석체크 플랫 아이콘 버튼 (프로필 페이지) ---- */
  .checkin-row{display:flex;align-items:center;justify-content:space-between;gap:14px;}
  .checkin-title{font-weight:800;font-size:14px;}
  .checkin-sub{color:var(--text-secondary);font-size:12.5px;margin-top:2px;}
  .checkin-flat-btn{
    flex-shrink:0;width:52px;height:52px;border-radius:14px;
    border:1.5px solid var(--border);background:var(--bg);color:var(--text);
    display:flex;align-items:center;justify-content:center;cursor:pointer;
    transition:background .15s ease,border-color .15s ease,color .15s ease,transform .1s ease;
  }
  .checkin-flat-btn:hover{background:#0f1419;border-color:#0f1419;color:#fff;}
  .checkin-flat-btn:active{transform:scale(.93);}
  .checkin-flat-btn.is-done{background:var(--green-soft);border-color:var(--green-soft);color:var(--green);cursor:default;}
  .checkin-flat-btn.is-done:hover{background:var(--green-soft);border-color:var(--green-soft);color:var(--green);}
  .checkin-flat-btn:disabled{cursor:default;}

  /* Admin management pages */
  .list-wide{padding:0;}
  .req-card,.member-card{padding:14px 16px;border-bottom:1px solid var(--border);}
  .req-top{display:flex;justify-content:space-between;align-items:flex-start;gap:10px;}
  .req-name{font-weight:800;font-size:15.5px;}
  .req-meta{color:var(--text-secondary);font-size:12.5px;margin-top:2px;}
  .req-msg{margin:10px 0;font-size:14px;background:var(--bg-elevated);padding:10px 12px;border-radius:10px;}
  .row-actions{display:flex;gap:8px;margin-top:8px;flex-wrap:wrap;}

  .cred-box{background:var(--text);color:var(--bg);border-radius:12px;padding:14px 16px;margin-top:10px;font-size:13.5px;}
  .cred-box code{background:rgba(128,128,128,.25);padding:2px 7px;border-radius:6px;font-weight:700;}

  .member-grid-top{display:flex;justify-content:space-between;align-items:center;gap:10px;flex-wrap:wrap;}
  .member-left{display:flex;gap:10px;align-items:center;}
  .member-name{font-weight:800;font-size:15px;}
  .member-sub{color:var(--text-secondary);font-size:12.5px;}
  .expiry-line{font-size:13px;margin-top:6px;color:var(--text-secondary);}

  /* Points shop */
  .shop-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:14px;padding:16px;}
  .shop-card{border:1px solid var(--border);border-radius:var(--radius-card);overflow:hidden;display:flex;flex-direction:column;background:var(--bg);}
  .shop-card-img{width:100%;aspect-ratio:1/1;background:var(--bg-elevated);overflow:hidden;}
  .shop-card-img img,.shop-card-img video{width:100%;height:100%;object-fit:cover;display:block;background:#000;}
  .shop-card-noimg{display:flex;align-items:center;justify-content:center;color:var(--text-secondary);}
  .shop-card-body{padding:12px;display:flex;flex-direction:column;gap:6px;flex:1;}
  .shop-card-name{font-weight:800;font-size:14.5px;}
  .shop-card-desc{font-size:12.5px;color:var(--text-secondary);line-height:1.4;}
  .shop-stock{font-size:11.5px;color:var(--text-secondary);}
  .shop-card-foot{display:flex;justify-content:space-between;align-items:center;margin-top:auto;padding-top:6px;}
  .shop-price{display:inline-flex;align-items:center;gap:4px;font-weight:800;color:var(--accent);font-size:14px;}

  /* 미니게임 */
  .game-card{padding:16px;border-bottom:8px solid var(--bg-elevated);}
  .game-choice-row{display:flex;flex-wrap:wrap;gap:8px;}
  .game-choice-row-wrap{gap:6px;}
  .game-choice-btn{min-width:56px;text-align:center;}
  .game-choice-btn-sm{min-width:38px;padding:6px 0;font-size:13px;}
  .game-result-row{margin-top:12px;padding:10px 12px;border-radius:var(--radius-card);background:var(--bg-elevated);font-size:13.5px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
  .game-result-empty{color:var(--text-secondary);}
  .game-limit-banner{margin:0 16px 8px;padding:9px 12px;border-radius:var(--radius-card);background:var(--accent-soft);color:var(--accent);font-size:12.5px;font-weight:700;}
  .game-limit-banner-full{background:var(--red-soft);color:var(--red);}
  .game-limit-banner-free{margin:0 16px 12px;background:var(--green-soft);color:var(--green);}
  .game-limit-banner-free-used{margin:0 16px 12px;background:var(--border);color:var(--text-secondary);}

  /* DM */
  .dm-shell{display:flex;height:calc(100vh);}
  .dm-list{width:100%;max-width:100%;}
  .dm-thread-item{display:flex;gap:10px;padding:12px 16px;border-bottom:1px solid var(--border);align-items:center;}
  .dm-thread-item:hover{background:var(--bg-hover);}
  .dm-thread-item .prev{color:var(--text-secondary);font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  .unread-dot{width:9px;height:9px;border-radius:50%;background:var(--accent);flex-shrink:0;}

  /* DM 화면 전체(.main-col)를 뷰포트에 딱 맞는 flex 세로 레이아웃으로 고정해서
     페이지 자체는 스크롤되지 않고, 메시지 목록(.dm-messages)만 내부 스크롤되게 함.
     이렇게 하면 입력창(.dm-input-bar)은 항상 레이아웃의 마지막 줄에 자연스럽게 고정되어
     화면을 스크롤하지 않아도 늘 보인다(모바일 상단바/하단 네비 높이는 .main-col의
     기존 padding-top/padding-bottom이 이미 확보해 줌). */
  /* height:100vh는 모바일 브라우저에서 주소창이 보였다 사라졌다 하는 것과 무관하게
     "주소창이 완전히 사라졌을 때 기준"의 큰 값으로 계산되는 경우가 많아서, 페이지를
     처음 열었을 때(주소창이 아직 보이는 상태)는 이 박스가 실제 화면보다 더 크게 잡혀
     버린다. 그 결과 위쪽(헤더)이나 아래쪽(입력창)이 화면 밖으로 밀려나서 스크롤을
     해야만 보이는 문제가 생김. 100dvh(동적 뷰포트 높이)를 지원하는 브라우저에서는
     실제 보이는 화면 높이 기준으로 다시 계산되므로, 스크롤 없이 헤더/입력창이 항상
     화면 안에 보이게 된다. (100dvh 미지원 브라우저는 앞의 100vh로 자동 대체됨) */
  /* 주의: 공용 .main-col{min-height:100vh} 규칙이 남아있으면, 아래에서 아무리
     height를 100dvh로 줄여도 min-height가 더 큰 100vh 쪽을 강제로 다시 끌어올려서
     이 fix 자체가 무효화된다(실제로 이전 시도가 반영되지 않았던 원인). 그래서
     min-height를 0으로 명시적으로 초기화해서 height(100dvh)가 그대로 적용되게 함. */
  .dm-page{display:flex;flex-direction:column;min-height:0;height:100vh;height:100dvh;overflow:hidden;overscroll-behavior:none;}
  /* .dm-page 자체가 스크롤되지 않는 자체완결 레이아웃이라 헤더가 "고정(sticky)"될
     필요가 없는데도 공용 .main-header 규칙의 position:sticky + top:54px가 남아있으면
     일부 모바일 브라우저에서 sticky 오프셋만큼 헤더 위에 불필요한 여백이 생기는
     현상이 있어, DM 화면 헤더는 sticky를 끄고 일반 흐름으로 배치함. */
  .dm-page .main-header{flex-shrink:0;position:static;top:auto;}
  /* 관리자 DM 대화창 헤더: "← DM 목록 / 닉네임 / @닉네임" 3줄짜리 헤더 대신
     뒤로가기 아이콘 + 이름 한 줄로 최소화해서 채팅 영역을 최대한 가리지 않게 함. */
  .main-header.dm-thread-header{display:flex;align-items:center;gap:8px;padding:8px 14px;}
  .back-icon-btn{display:flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:50%;border:none;background:transparent;color:var(--text);cursor:pointer;flex-shrink:0;padding:0;}
  .back-icon-btn:hover{background:var(--bg-hover);}
  .back-icon-btn svg{width:20px;height:20px;display:block;}
  .dm-thread-header-info{display:flex;align-items:baseline;gap:6px;overflow:hidden;white-space:nowrap;min-width:0;}
  .dm-thread-header-name{font-weight:800;font-size:15.5px;color:var(--text);overflow:hidden;text-overflow:ellipsis;}
  .dm-thread-header-handle{color:var(--text-secondary);font-size:12.5px;flex-shrink:0;}
  .dm-thread{display:flex;flex-direction:column;flex:1;min-height:0;}
  .dm-notice{align-self:center;display:flex;align-items:flex-start;gap:8px;flex-shrink:0;background:#0f1419;color:#ffffff;font-size:12.5px;line-height:1.5;padding:9px 16px;border-radius:14px;max-width:92%;margin-bottom:4px;}
  .dm-notice svg{flex-shrink:0;margin-top:1px;}
  .dm-messages{flex:1;min-height:0;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:10px;}
  .bubble{max-width:72%;padding:10px 14px;border-radius:18px;font-size:14.5px;line-height:1.4;word-break:break-word;}
  .bubble.me{align-self:flex-end;background:var(--accent);color:#fff;border-bottom-right-radius:4px;}
  .bubble.them{align-self:flex-start;background:var(--bg-elevated);color:var(--text);border-bottom-left-radius:4px;}
  .bubble-time{font-size:10.5px;opacity:.7;margin-top:3px;display:block;}
  .bubble-row{display:flex;flex-direction:column;}
  .bubble-row.me{align-items:flex-end;}
  .bubble-row.them{align-items:flex-start;}
  .bubble-line{display:flex;align-items:flex-end;gap:4px;position:relative;max-width:100%;}
  .bubble-row.me .bubble-line{flex-direction:row-reverse;}

  /* 이모지 단독 메시지: 배경 박스 없이 크게 표시 + 등장 애니메이션 */
  @keyframes bubbleEmojiPop{
    0%{transform:scale(.25);opacity:0;}
    65%{transform:scale(1.18);opacity:1;}
    100%{transform:scale(1);opacity:1;}
  }
  .bubble.bubble-emoji,
  .bubble.bubble-emoji.me,
  .bubble.bubble-emoji.them{background:none;color:inherit;padding:0;border-radius:0;box-shadow:none;font-size:46px;line-height:1.15;animation:bubbleEmojiPop .4s cubic-bezier(.34,1.56,.64,1);}
  .bubble.bubble-image{padding:4px;}
  .dm-image{display:block;width:220px;max-width:60vw;max-height:280px;object-fit:cover;border-radius:14px;cursor:zoom-in;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;}
  .dm-image-caption{padding:6px 6px 0;white-space:pre-wrap;word-break:break-word;}
  .bubble.bubble-image .bubble-time{padding:0 4px;}

  .react-trigger-wrap{position:relative;flex-shrink:0;}
  .react-trigger{border:none;background:var(--bg-elevated);border-radius:50%;width:24px;height:24px;font-size:15px;font-weight:700;line-height:1;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-secondary);transition:transform .15s ease,background .15s ease;}
  .react-trigger:hover{background:var(--border);transform:scale(1.2) rotate(-6deg);}
  .react-trigger:active{transform:scale(0.85);}
  .react-popup{position:fixed;z-index:150;padding:6px;display:grid;grid-template-columns:repeat(4,1fr);gap:2px;width:150px;}
  .reaction-badges{display:flex;gap:3px;margin-top:2px;}
  .reaction-badge{background:var(--bg-elevated);border-radius:999px;font-size:12px;line-height:1.3;padding:1px 7px;display:inline-block;cursor:pointer;transition:transform .15s ease,background .15s ease;}
  .reaction-badge:hover{transform:scale(1.25) rotate(-4deg);background:var(--bg-hover);}
  .reaction-badge:active{transform:scale(0.9);}
  /* position:relative는 이모지 팝업(.emoji-popup, position:absolute)의 기준점.
     flex-shrink:0으로 메시지 목록이 늘어나도 입력창 자체는 줄어들지 않고
     .dm-page 레이아웃의 맨 아래 줄에 항상 고정되어 보인다(네비게이션 바처럼). */
  .dm-input-bar{display:flex;gap:8px;padding:12px 16px;border-top:1px solid var(--border);position:relative;flex-shrink:0;background:var(--bg);}
  .dm-input-bar input{flex:1;border:1px solid var(--border);border-radius:999px;padding:10px 16px;font-size:14.5px;outline:none;}
  .dm-input-bar input:focus{border-color:var(--accent);}
  #dm-attach-preview.attach-preview{flex-shrink:0;}
  .emoji-toggle-btn{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;border:none;background:none;border-radius:50%;color:var(--text-secondary);font-size:18px;line-height:1;cursor:pointer;transition:transform .15s ease,background .15s ease,color .15s ease;}
  .emoji-toggle-btn:hover{background:var(--bg-hover);color:var(--accent);transform:scale(1.15) rotate(-8deg);}
  .emoji-toggle-btn:active{transform:scale(0.85);}
  .emoji-popup{position:absolute;bottom:56px;left:16px;z-index:20;background:var(--bg);border:1px solid var(--border);border-radius:16px;box-shadow:0 8px 24px rgba(0,0,0,.15);padding:10px;grid-template-columns:repeat(7,1fr);gap:4px;width:270px;max-height:220px;overflow-y:auto;}
  .emoji-btn{border:none;background:none;font-size:20px;line-height:1;padding:6px;border-radius:8px;cursor:pointer;transition:transform .15s ease,background .15s ease;}
  .emoji-btn:hover{background:var(--bg-hover);transform:scale(1.3) rotate(-8deg);}
  .emoji-btn:active{transform:scale(0.8);}

  /* 이모지/이모티콘 클릭 시 재생되는 팝 애니메이션 (JS에서 클래스를 토글해 실행) */
  @keyframes emojiPop{
    0%{transform:scale(1) rotate(0deg);}
    30%{transform:scale(1.5) rotate(-12deg);}
    55%{transform:scale(0.85) rotate(10deg);}
    75%{transform:scale(1.15) rotate(-4deg);}
    100%{transform:scale(1) rotate(0deg);}
  }
  .emoji-pop{animation:emojiPop .45s cubic-bezier(.34,1.56,.64,1);}
  .back-link{display:inline-flex;align-items:center;gap:4px;color:var(--accent);font-weight:700;font-size:13.5px;padding:12px 16px 0;}

  .modal-overlay{position:fixed;inset:0;background:rgba(15,20,25,.5);display:flex;align-items:center;justify-content:center;z-index:100;padding:20px;}
  /* 게시물 수정 모달 위에서 이미지 썸네일을 다시 편집할 때(기존 이미지 편집) 크롭 창이
     게시물 수정 모달 뒤에 가려지지 않도록 더 높은 z-index를 준다. */
  .cropper-overlay{z-index:300;}
  .modal-box{background:var(--bg-elevated);color:var(--text);border-radius:18px;padding:22px;max-width:420px;width:100%;}
  .modal-box h4{margin:0 0 6px;}
  .modal-box p{color:var(--text-secondary);font-size:13.5px;margin:0 0 16px;}

  /* 미니게임 허브(게임 선택 화면): 그림자·그라데이션 없이 단색 배경과 테두리만 쓰는
     플랫 디자인. 아이콘 아래 게임 이름을 함께 노출해 어떤 게임인지 바로 알 수 있게 함.
     너비는 .modal-box 기본값을 그대로 따라 다른 메뉴의 모달과 같은 폭을 유지함. */
  .games-menu-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin-top:2px;}
  .games-menu-tile{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;width:100%;padding:16px 6px;background:var(--bg);border:2px solid var(--border);border-radius:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease;}
  .games-menu-tile:hover{background:var(--accent-soft);border-color:var(--accent);}
  .games-menu-tile:active{background:var(--accent-soft);}
  .games-menu-icon{width:44px;height:44px;border-radius:10px;background:var(--bg-elevated);display:flex;align-items:center;justify-content:center;font-size:22px;flex-shrink:0;}
  .games-menu-tile:hover .games-menu-icon{background:var(--bg);}
  .games-menu-name{font-size:12px;font-weight:700;color:var(--text);line-height:1.3;text-align:center;word-break:keep-all;}

  .icon-pick-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(84px,1fr));gap:10px;max-height:340px;overflow-y:auto;padding:2px;}
  .icon-pick-card{border:2px solid var(--border);border-radius:14px;padding:8px 6px;display:flex;flex-direction:column;align-items:center;gap:6px;cursor:pointer;text-align:center;transition:border-color .15s,transform .1s;}
  .icon-pick-card:hover{border-color:var(--accent);transform:translateY(-1px);}
  .icon-pick-card.is-selected{border-color:var(--accent);background:var(--accent-soft);}
  .icon-pick-thumb{width:52px;height:52px;border-radius:50%;overflow:hidden;background:var(--bg-elevated);}
  .icon-pick-thumb img{width:100%;height:100%;object-fit:cover;display:block;}
  .icon-pick-name{font-size:11.5px;font-weight:700;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%;}
  .toast{position:fixed;bottom:24px;left:50%;transform:translateX(-50%);background:var(--text);color:var(--bg);padding:12px 20px;border-radius:999px;font-size:13.5px;font-weight:600;z-index:200;box-shadow:0 8px 24px rgba(0,0,0,.25);}

  /* ---------- 화면 보호 (스크린샷/캡처 억제 · 완벽 차단은 불가능한 보조 수단) ---------- */
  .shell,.x-auth-wrap{-webkit-user-select:none;-ms-user-select:none;user-select:none;-webkit-touch-callout:none;}
  .shell input,.shell textarea,.x-auth-wrap input,.x-auth-wrap textarea{-webkit-user-select:text;-ms-user-select:text;user-select:text;-webkit-touch-callout:default;}
  img,video{-webkit-user-drag:none;user-drag:none;}
  .media-watermark{position:absolute;inset:0;pointer-events:none;overflow:hidden;display:flex;align-items:center;justify-content:center;opacity:.28;}
  .media-watermark span{display:block;text-align:center;transform:rotate(-18deg);font-size:15px;font-weight:600;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.5);white-space:nowrap;}
  body.screen-blurred #app{filter:blur(26px);transition:filter .12s ease;}
  /* 주의: 아래를 filter:blur(0)으로 두면 시각적으로는 블러가 없어 보여도, CSS 스펙상
     filter 값이 none이 아니면 그 요소가 position:fixed 자손의 위치 기준(containing block)을
     뷰포트에서 자기 자신으로 바꿔버림. 그 결과 #app 안에 있는 position:fixed 요소(모바일
     하단 네비게이션 바 등)가 화면에 고정되지 않고 #app의 문서 흐름을 따라가서, 콘텐츠가
     길어지면 그만큼 밀려나 스크롤해야만 보이는 문제가 생김. none으로 두면 이 문제가 없고,
     블러 처리(.screen-blurred일 때 blur(26px))도 none → blur(26px)로 정상적으로 전환/애니메이션됨. */
  #app{filter:none;transition:filter .2s ease;}
  @media print{ body{display:none !important;} }
  video::-webkit-media-controls-fullscreen-button{display:none !important;}
