:root{
  --bg:#0f1115; --bg2:#171a21; --bg3:#1f232c; --line:#2b3039;
  --tx:#e8eaed; --tx2:#9aa0aa; --tx3:#6b7280;
  --accent:#ff4d4d; --ok:#22c55e; --warn:#f59e0b;
  --radius:12px;
}
*{box-sizing:border-box}
html,body{height:100%}
/* 시청자 화면(index.html)만 앱처럼 화면에 고정합니다.
   이게 없으면 문서 전체가 위아래로 출렁이고(iOS 바운스),
   티커를 옆으로 밀 때 페이지까지 같이 끌려갑니다.
   관리자 페이지는 일반 문서처럼 스크롤돼야 해서 .shell 에만 겁니다. */
body.shell{overflow:hidden;overscroll-behavior:none}
body{
  margin:0; background:var(--bg); color:var(--tx);
  -webkit-text-size-adjust:100%;
  /* 프리텐다드를 CDN에서 불러옵니다 (각 html 의 <link>).
     못 받아오면 아래 순서대로 시스템 한글 글꼴로 넘어갑니다. */
  font-family:"Pretendard Variable","Pretendard","Apple SD Gothic Neo","Malgun Gothic",system-ui,sans-serif;
  font-size:15px; line-height:1.5; -webkit-font-smoothing:antialiased;
}
button{font-family:inherit;cursor:pointer;border:0;border-radius:8px}
/* 글자 크기가 16px 보다 작으면 아이폰 사파리가 입력칸을 누르는 순간
   화면을 제멋대로 확대합니다. 그러면 페이지가 화면보다 넓어져서
   좌우로 밀리고 가장자리가 잘립니다. 그래서 정확히 16px 로 둡니다. */
input,textarea,select{
  background:var(--bg3); border:1px solid var(--line); color:var(--tx);
  border-radius:8px; padding:10px 12px; width:100%;
  font-family:inherit; font-size:16px;
}
input:focus,textarea:focus{outline:2px solid #3b82f6;outline-offset:-1px}
.btn{background:#2f3542;color:var(--tx);padding:10px 16px;font-weight:600;font-size:14px}
.btn:hover{background:#3a4150}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn-primary{background:var(--accent);color:#fff}
.btn-primary:hover{background:#ff6161}
/* 후원하기는 전송 버튼과 같은 색이라 구분이 안 돼서,
   노란 바탕에 검은 글씨로 따로 뚝 떼어놨습니다. */
#btnDonate2{background:#ffc400;color:#1a1200;font-weight:800}
#btnDonate2:hover{background:#ffd43b}
.btn-ok{background:var(--ok);color:#06240f}
.btn-ghost{background:transparent;border:1px solid var(--line);color:var(--tx2)}
.muted{color:var(--tx2)}
.small{font-size:13px}
.tiny{font-size:12px}
.err{color:#ff8080;font-size:13px;margin-top:8px;min-height:16px}

/* ---------- 레이아웃 ----------
   영상이 있으면 PC 는 좌우로, 폰은 영상이 위에 고정되고 아래로 채팅이 옵니다.
   영상이 없으면 예전처럼 채팅만 가운데 놓입니다. */
/* 100vh 는 아이폰에서 '주소창이 없을 때의 높이'라 실제 화면보다 큽니다.
   그래서 아래쪽이 주소창에 가리고, 스크롤할 때마다 화면이 출렁입니다.
   100dvh 는 주소창 크기에 맞춰 따라가므로 출렁임이 없습니다.
   (dvh 를 모르는 옛 브라우저는 윗줄 100vh 를 씁니다) */
.page{display:flex;height:100vh;height:100dvh;max-width:1400px;margin:0 auto}
.page .video{display:none}
.page.has-video .video{
  flex:1 1 auto;min-width:0;min-height:0;display:flex;flex-direction:column;
  background:#000;padding:14px;gap:10px
}
.vwrap{width:100%;aspect-ratio:16/9;flex:0 0 auto}
.vwrap iframe{display:block;width:100%;height:100%;border:0;border-radius:10px;background:#000}

/* 채널 영상 목록 */
.vlist{
  flex:1 1 auto;min-height:0;overflow-y:auto;display:grid;gap:10px;
  grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
  /* 이게 없으면 행 높이가 컨테이너에 맞춰 균등 분배되어 카드가 납작하게 눌립니다 */
  grid-auto-rows:max-content;align-content:start
}
.vlist::-webkit-scrollbar{width:9px}
.vlist::-webkit-scrollbar-thumb{background:#2f3542;border-radius:9px}
.vcard{cursor:pointer;border-radius:9px;overflow:hidden;background:#12151b;border:1px solid transparent}
.vcard:hover{border-color:#3a4150}
.vcard.now{border-color:var(--accent)}
.vcard img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover;background:#1f232c}
.vcard .t{
  padding:7px 9px 9px;font-size:12.5px;line-height:1.4;color:var(--tx);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.8em
}
.vcard .t.dim{color:var(--tx3)}
.vbar{
  flex:0 0 auto;display:none;width:100%;padding:9px;font-size:13px;font-weight:700;
  background:var(--bg3);color:var(--tx2);border:1px solid var(--line)
}
.vbar:hover{background:#2a2f39;color:var(--tx)}
/* 영상 접고 펴기 — 뚝 사라지지 않고 위아래로 미끄러집니다 (좁은 화면 기준).
   PC 는 영상이 채팅 왼쪽에 붙으므로 위아래로 미는 게 말이 안 돼 살짝 번지게만 합니다. */
.page.has-video .video{transition:max-height .26s cubic-bezier(.2,.85,.3,1), opacity .2s ease}
.page.has-video .video.slide{max-height:0;opacity:0;overflow:hidden}
.video.has-list .vbar{display:block}
.video.list-mode .vwrap{display:none}
.video:not(.list-mode) .vlist{display:none}

/* width:100% 가 없으면 세로 배치일 때 margin:0 auto 가 이겨서
   채팅창이 내용 너비만큼 쪼그라듭니다. */
.app{display:flex;flex-direction:column;height:100%;min-height:0;flex:1 1 auto;width:100%;max-width:860px;margin:0 auto;border-left:1px solid var(--line);border-right:1px solid var(--line)}
.page.has-video .app{flex:0 0 400px;max-width:400px;margin:0}

@media (max-width:900px){
  .page{flex-direction:column}
  /* 영상 영역이 아무리 커도 채팅에 260px 은 남겨둡니다.
     (머리줄 48 + 입력칸 90 + 채팅 120 정도) 화면이 짧은 폰에서 영상이 자리를
     다 먹고 채팅이 두세 줄만 남던 문제를 이 한 줄이 막습니다. */
  .page.has-video .video{
    flex:0 0 auto;padding:0;gap:0;position:sticky;top:0;z-index:5;overflow:hidden;
    max-height:min(92vh, calc(100dvh - 260px))
  }
  .page.has-video .vwrap{border-radius:0}
  .page.has-video .vwrap iframe{border-radius:0}
  .page.has-video .app{flex:1 1 auto;max-width:none;width:100%;min-height:0}
  /* 목록을 펼칠 땐 고정을 풀고 높이를 제한해 채팅이 가려지지 않게 합니다 */
  .video.list-mode{position:static}
  /* 목록 높이를 화면의 52% 로 못박아 두면 짧은 폰에서 채팅을 다 먹습니다.
     위에서 영상 영역 전체를 이미 묶어뒀으니, 목록은 남는 만큼만 쓰고 안에서 스크롤합니다. */
  /* 목록 높이를 화면의 52% 로 못박아 두면 짧은 폰에서 채팅을 다 먹습니다.
     '화면의 절반' 과 '채팅 몫 340px 을 뺀 나머지' 중 작은 쪽을 씁니다.
     그래서 긴 폰이든 짧은 폰이든 채팅에 300px 안팎이 늘 남습니다. */
  .vlist{
    padding:10px;min-height:0;
    max-height:min(52vh, calc(100dvh - 340px));
    grid-template-columns:repeat(auto-fill,minmax(145px,1fr))
  }
}
header.top{
  display:flex;align-items:center;gap:10px;padding:12px 16px;
  background:var(--bg2);border-bottom:1px solid var(--line);flex:0 0 auto;
}
header.top h1{font-size:16px;margin:0;font-weight:700;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dot{width:8px;height:8px;border-radius:50%;background:var(--tx3);flex:0 0 auto}
.dot.on{background:var(--ok);box-shadow:0 0 8px var(--ok)}
.icon-btn{background:transparent;color:var(--tx2);font-size:18px;padding:4px 8px;line-height:1}
.icon-btn:hover{color:var(--tx)}
/* 🏆 후원 순위 — 따로 단추를 두지 않고 채팅창 오른쪽 구석에 늘 뗠 있습니다.
   머리글을 누르면 접혀서 작은 알약만 남습니다. */
#rankDock{
  /* 상단 후원 카드가 떠 있으면 그 높이(--pinh)만큼 내려가 겹치지 않습니다 */
  position:absolute;top:calc(10px + var(--pinh, 0px));right:12px;z-index:3;width:214px;
  transition:top .22s cubic-bezier(.2,.85,.3,1);
  background:rgba(15,17,21,.93);border:1px solid var(--line);border-radius:12px;
  box-shadow:0 10px 30px rgba(0,0,0,.5);overflow:hidden;
}
#rankDock.min{width:auto}
.app.replying #rankDock{display:none}            /* 답글 볼 땐 가리지 않게 */
/* 머리글의 🏆·화살표를 아래 줄의 메달·금액과 같은 세로선에 맞춥니다
   (목록 여백 8 + 줄 안쪽 여백 11 = 19). 안 맞추면 한 칸씩 어긋나 보입니다. */
#rankDock .rhandle{
  display:flex;align-items:center;gap:9px;width:100%;padding:9px 19px 8px 17px;
  background:transparent;color:var(--tx2);font-weight:800;font-size:12.5px;line-height:1.2;
}
#rankDock .rhandle:hover{background:#1b1f27;color:var(--tx)}
#rankDock .rtitle{flex:1;display:flex;align-items:center;gap:6px;min-width:0;white-space:nowrap}
#rankDock .rtitle .ic{font-size:20px;line-height:1;position:relative}
/* 접어두면 트로피만 남으므로 더 큼직하게 — 그래야 거기 뭐가 있는지 눈에 띕니다 */
#rankDock.min .rtitle .ic{font-size:23px}
/* 순위가 바뀌면 트로피가 한 번 흔들립니다 */
@keyframes trophyShake{
  0%,100%{transform:rotate(0)}
  14%{transform:rotate(-17deg) scale(1.12)}
  28%{transform:rotate(15deg)  scale(1.12)}
  42%{transform:rotate(-12deg) scale(1.08)}
  56%{transform:rotate(9deg)   scale(1.05)}
  72%{transform:rotate(-5deg)}
}
#rankDock .rtitle .ic.shake{animation:trophyShake .7s ease-in-out}
/* 접어둔 사이에 순위가 바뀌었으면 빨간 점. 펴서 확인하면 사라집니다. */
#rankDock.unseen .rtitle .ic::after{
  content:'';position:absolute;top:-2px;right:-3px;width:8px;height:8px;
  border-radius:50%;background:#ff3b30;box-shadow:0 0 0 2px var(--bg)
}
#rankDock.min .rtitle .tx{display:none}
#rankDock .rchev{
  width:15px;height:15px;flex:0 0 auto;
  fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;
  transform:rotate(180deg);transition:transform .18s ease;
}
#rankDock.min .rchev{transform:none}
/* 줄 사이, 머리글 아래, 판 바닥 — 빈칸을 전부 8px 로 맞춥니다.
   예전에는 줄의 margin(7) + 목록 gap(5) 이 겹쳐 12px, 바닥은 15px 이라 들쭉날쭉했습니다. */
#rankDock #rankList{display:flex;flex-direction:column;gap:8px;padding:0 8px 8px}
#rankDock .rankrow{margin-bottom:0}
#rankDock.min #rankList{display:none}
#rankDock .nobody{color:var(--tx3);font-size:11.5px;line-height:1.5;padding:2px 2px 4px}
/* 좁은 판이라 줄을 작게 줄입니다.
   이름과 금액을 한 줄에 두면 '시닉하다' 가 '시…' 로 잘립니다. 금액을 아랫줄로
   내려서 이름이 판 폭을 통째로 씁니다. 그래도 긴 이름은 줄바꿈해 끝까지 보여줍니다. */
#rankDock .rankrow{
  display:grid;grid-template-columns:auto 1fr;
  grid-template-areas:"rk name" "rk amt";
  align-items:center;column-gap:9px;row-gap:2px;padding:8px 11px
}
#rankDock .rankrow .rk{grid-area:rk;font-size:17px;min-width:23px;line-height:1}
#rankDock .rankrow .rmid{grid-area:name}
#rankDock .rankrow .rn{font-size:12.5px;line-height:1.3;white-space:normal;overflow:visible;overflow-wrap:anywhere}
#rankDock .rankrow .rc{font-size:10.5px}
/* 금액은 닉네임과 같은 세로선에서 시작합니다 (왼쪽 맞춤) */
#rankDock .rankrow .ramt{grid-area:amt;font-size:13px;line-height:1.25;text-align:left}
/* 접어두었을 땐 트로피가 숨 쉬듯 움직여서 여기 뭐가 있다고 알려줍니다 */
#rankDock.min .rtitle .ic{
  animation:auraBeat 2.4s ease-in-out infinite;
  filter:drop-shadow(0 0 6px rgba(255,196,0,.75));
}
@keyframes auraBeat{
  0%,100%{transform:scale(1)}
  50%    {transform:scale(1.12)}
}
/* 순위판은 PC 에서도 채팅 '위에 뜨는 판'입니다. 펴도 채팅 폭을 건드리지 않습니다 —
   예전에는 자리를 비워주느라 채팅이 옆으로 밀렸는데, 그게 더 거슬렸습니다. */
@media (max-width:480px){
  #rankDock{top:calc(8px + var(--pinh, 0px));right:8px;width:198px}
}
/* 영상 접기/펴기 — 아래 화살표면 내려서 보고, 위 화살표면 접어 올립니다 */
#btnVideo{
  padding:4px 11px;line-height:0;
  background:var(--bg3);border:1px solid var(--line);border-radius:999px;color:var(--tx2)
}
#btnVideo svg{
  width:18px;height:18px;display:block;
  fill:none;stroke:currentColor;stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;
  transition:transform .18s ease
}
#btnVideo.up svg{transform:rotate(180deg)}
#btnVideo:hover{background:#2a2f39;color:var(--tx);border-color:#3a4150}

/* ---------- 연결 장애 안내 ---------- */
#netbar{
  flex:0 0 auto;display:none;padding:10px 14px;text-align:center;
  background:#3a2a05;color:#ffd166;font-size:13.5px;font-weight:600;
  border-bottom:1px solid #6b4a00;line-height:1.5;
}
#netbar.show{display:block}

/* ---------- 상단 고정 티커 ---------- */
#ticker{
  flex:0 0 auto;display:none;gap:8px;padding:8px 12px 6px;overflow-x:auto;overflow-y:hidden;
  background:#0b0d11;border-bottom:1px solid var(--line);
  cursor:grab;scrollbar-width:thin;scrollbar-color:#454d5c transparent;
  overscroll-behavior-x:contain;
}
#ticker.show{display:flex}
#ticker.dragging{cursor:grabbing;user-select:none}
#ticker::-webkit-scrollbar{height:7px}
#ticker::-webkit-scrollbar-thumb{background:#454d5c;border-radius:7px}
#ticker::-webkit-scrollbar-thumb:hover{background:#5a6474}
#ticker::-webkit-scrollbar-track{background:transparent}
.tick{
  position:relative;flex:0 0 auto;display:flex;align-items:center;gap:7px;
  padding:5px 11px 9px;border-radius:999px;cursor:pointer;
  font-size:13px;font-weight:700;white-space:nowrap;animation:pop .3s ease
}
.tick:hover{filter:brightness(1.12)}
.tick.sel{box-shadow:0 0 0 2px #fff inset}
.tick .cd{position:absolute;left:10px;right:10px;bottom:4px;height:2px;border-radius:2px;background:rgba(0,0,0,.3);overflow:hidden}
.tick .cd i{display:block;height:100%;background:rgba(255,255,255,.9)}

/* ---------- 상단에 펼쳐진 슈퍼챗 ---------- */
/* 상단 고정 후원 카드 — 채팅창 '위에 덮어쓰는' 팝업입니다.
   예전에는 채팅 위쪽에 끼워 넣어서, 카드가 뜰 때마다 채팅이 통째로 아래로 밀렸습니다. */
#scpin{
  position:absolute;left:0;right:0;top:0;z-index:6;display:none;
  border-bottom:1px solid var(--line);box-shadow:0 10px 24px rgba(0,0,0,.45)
}
#scpin.show{display:block;animation:dropDown .22s cubic-bezier(.2,.85,.3,1)}
/* 티커 칩을 누르면 그 아래로 주르륵 내려옵니다 */
@keyframes dropDown{ from{transform:translateY(-100%);opacity:.5} to{transform:none;opacity:1} }
#scpin .ph{display:flex;align-items:center;gap:8px;padding:9px 13px;font-weight:800}
#scpin .ph .n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px}
#scpin .ph .a{font-size:15px;font-weight:900;letter-spacing:-.2px}
#scpin .ph .px{background:transparent;color:inherit;opacity:.55;font-size:13px;line-height:1;padding:4px 0 4px 8px;font-weight:700}
#scpin .ph .px:hover{opacity:1}
#scpin .pb{padding:9px 13px 4px;font-size:14.5px;color:#fff;word-break:break-word;max-height:5.4em;overflow-y:auto}
/* 상단 카드의 추천·답글 줄. 카드 배경을 그대로 쓰므로 바탕색은 주지 않습니다. */
#scpin .pinacts{padding:6px 13px 2px;background:none}
#scpin .pinacts .sc-act{background:rgba(255,255,255,.14);color:#fff}
#scpin .pinacts .sc-act:hover{background:rgba(255,255,255,.26)}
#scpin .pinacts .sc-act.on{background:#fff;color:#111}
/* 남은 시간 글자를 뺀 만큼 막대가 가로를 다 씁니다. 조금 더 굵게 해서 눈에 띄게. */
#scpin .pt{display:flex;align-items:center;padding:7px 13px 10px}
#scpin .bar{flex:1;height:5px;border-radius:3px;background:rgba(255,255,255,.18);overflow:hidden}
#scpin .bar i{display:block;height:100%;background:rgba(255,255,255,.85);transition:width .9s linear}
#scpin .pt span{white-space:nowrap}

/* ---------- 채팅 로그 ---------- */
#log{flex:1 1 auto;min-height:0;overflow-y:auto;padding:12px 14px;display:flex;flex-direction:column;gap:7px}
/* flex 항목은 기본적으로 줄어듭니다. 이걸 막지 않으면 메시지가 쌓일 때
   스크롤되는 대신 카드와 글자가 납작하게 눌립니다. */
#log > *{flex:0 0 auto}
#log::-webkit-scrollbar{width:9px}
#log::-webkit-scrollbar-thumb{background:#2f3542;border-radius:9px}
.msg{word-break:break-word;animation:fade .18s ease}
/* 이름 색이 곧 신분입니다.
   회색 = 로그인 안 한 익명 / 하늘색 = 구글 로그인 / 그 외 색 = 로그인한 후원자 / 노랑 = 👑 */
.msg .nick{font-weight:700;color:#8ab4f8;margin-right:6px}
.msg .nick.anon{color:var(--tx3);font-weight:600}
.msg.admin .nick{color:#ffd166}
.msg .bdg{width:18px;height:18px;margin-right:5px;vertical-align:-4px;border-radius:5px}
#rList .msg .bdg,#rTarget .msg .bdg{width:17px;height:17px}
.nickbar .dim{color:var(--tx3)}
/* 구글 로그인 단추 */
.gbtn{display:flex;align-items:center;justify-content:center;gap:9px;width:100%;
  background:#fff;color:#1f1f1f;font-weight:800;font-size:14.5px;padding:12px}
.gbtn:hover{background:#eceff1}
.gbtn svg{width:20px;height:20px;flex:0 0 auto;display:block}
/* 로그인 창은 네 덩어리뿐입니다 — 제목 / 한 줄 설명 / 로그인 / 나중에.
   위아래 여백을 같게 둬야 가운데가 비어 보이지 않습니다. */
#nickLoginBox .gsub{margin:0 0 18px;line-height:1.5}
#nickLoginBox .actions{margin-top:10px}
#nickLoginBox .err:empty{display:none}
#nickLoginBox .err{margin-top:10px}
.msg .del{opacity:0;background:transparent;color:var(--tx3);font-size:11px;padding:0 4px}
.msg:hover .del{opacity:1}
.sys{color:var(--tx3);font-size:13px;text-align:center;padding:4px 0}

/* ---------- 슈퍼챗 카드 ---------- */
.sc{border-radius:var(--radius);overflow:hidden;margin:5px 0;animation:pop .3s cubic-bezier(.2,1.4,.4,1);box-shadow:0 4px 16px rgba(0,0,0,.4)}
.sc-head{display:flex;align-items:center;gap:8px;padding:9px 13px;font-weight:800}
.sc-head .sc-nick{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px}
.sc-head .sc-amt{font-size:15px;font-weight:900;letter-spacing:-.2px}
.sc-body{padding:9px 13px;font-size:14.5px;word-break:break-word}
/* 후원 카드 '안'의 단추 줄 — 유튜브와 같은 👍 추천 / 💬 답글.
   배경색은 카드 본문과 같은 색을 app.js 가 직접 칠합니다 (등급마다 다르므로). */
.sc-acts{display:flex;gap:8px;padding:2px 13px 11px}
/* 메시지 없는 후원은 본문 칸이 아예 없어서, 단추가 색띠에 딱 붙어 답답해 보입니다.
   본문이 있는 카드와 같은 간격이 되도록 위쪽을 띄워줍니다. */
.sc-acts.nomsg{padding-top:10px}
.sc-act{display:inline-flex;align-items:center;gap:6px;background:rgba(255,255,255,.1);
  color:#fff;border-radius:999px;padding:5px 12px;font-size:13px;font-weight:700;line-height:1}
.sc-act:hover{background:rgba(255,255,255,.2)}
.sc-act.on{background:#fff;color:#111}
.sc-act .n{font-variant-numeric:tabular-nums}
.sc-act .n:empty{display:none}
/* 공개 채팅에 뜨는 답글 표시 — "@누구 💬" 칩.
   색은 그 후원의 등급색으로 app.js 가 칠합니다. 아래 색은 후원을 아직 못 찾았을 때만 쓰입니다. */
.rchip{display:inline-flex;align-items:center;gap:4px;margin-right:6px;padding:1px 7px;
  border-radius:999px;background:var(--bg3);color:var(--tx2);font-size:12px;font-weight:700;
  max-width:46%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:baseline}
.rchip:hover{filter:brightness(1.15)}
/* 답글 화면 */
/* 채팅창과 답글창이 같은 자리를 쓰므로 한 상자에 담습니다 */
.logwrap{flex:1 1 auto;min-height:0;position:relative;display:flex;flex-direction:column;overflow:hidden}
#replyPane{display:none;flex:1;min-height:0;flex-direction:column;background:var(--bg)}
/* 답글창은 오른쪽에서 밀려 들어오고, 닫을 땐 오른쪽으로 밀려 나갑니다.
   손가락으로 오른쪽으로 쓸어 닫는 동작과 방향이 같아야 자연스럽습니다. */
@keyframes slideInR{ from{transform:translateX(100%)} to{transform:none} }
@keyframes slideOutR{ from{transform:none} to{transform:translateX(100%)} }
.app.replying #replyPane{animation:slideInR .24s cubic-bezier(.2,.85,.3,1)}
/* 여는 규칙(.app.replying #replyPane)보다 더 구체적이어야 덮습니다 */
.app.replying #replyPane.closing{animation:slideOutR .2s cubic-bezier(.4,0,.8,.4) forwards}
.app.replying #log{display:none}          /* 폰: 채팅창 자리를 대신 차지 */
.app.replying #replyPane{display:flex}
/* 티커와 상단 카드는 '폰에서만' 숨깁니다. PC 는 답글창이 그 위에 뜨므로 그대로 둡니다.
   예전엔 PC 쪽에서 display:revert 로 되살렸는데, revert 는 우리 CSS 가 아니라
   브라우저 기본값(block)으로 돌아가서 티커 칩이 가로로 안 눕고 줄줄이 쌓였습니다. */
@media (max-width:480px){
  .app.replying #ticker,.app.replying #scpin{display:none}
}
/* PC 는 유튜브처럼 채팅창 '위에' 떠 있는 창으로 띄웁니다.
   뒤 채팅이 계속 흐르는 게 보여야 방이 살아있는 느낌이 납니다. */
@media (min-width:481px){
  .app.replying #log{display:flex}
  /* PC 는 화면 '가운데' 팝업으로 띄웁니다. 아래쪽에 붙여두면 입력칸과 겹쳐 보여
     채팅창 일부처럼 읽혔습니다. 가운데에 뜨면 지금 보는 게 답글이라는 게 분명합니다. */
  #replyPane{
    position:absolute;left:0;right:0;margin-inline:auto;
    width:min(680px, calc(100% - 32px));
    min-height:min(460px, calc(100% - 32px));
    top:50%;bottom:auto;transform:translateY(-50%);
    max-height:calc(100% - 32px);flex:0 1 auto;
    border:1px solid var(--line);border-radius:16px;
    background:var(--bg2);box-shadow:0 18px 50px rgba(0,0,0,.6);
  }
  /* 가운데로 띄우느라 transform 에 translateY(-50%) 가 들어가 있으므로,
     미끄러지는 움직임에도 그 값을 같이 써야 합니다. 안 그러면 가운데가 풀립니다. */
  @keyframes slideInRC { from{transform:translate(100%,-50%)} to{transform:translate(0,-50%)} }
  @keyframes slideOutRC{ from{transform:translate(0,-50%)} to{transform:translate(100%,-50%)} }
  .app.replying #replyPane{animation:slideInRC .24s cubic-bezier(.2,.85,.3,1)}
  .app.replying #replyPane.closing{animation:slideOutRC .2s cubic-bezier(.4,0,.8,.4) forwards}
  /* 입력칸이 떠 있는 창 안으로 들어왔을 때 (app.js 가 옮깁니다) */
  #replyPane > .composer{background:transparent;border-radius:0 0 15px 15px}
}
.rhead{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line)}
.rhead h2{flex:1;margin:0;font-size:17px;font-weight:800;text-align:center}
.rbody{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;padding:8px 10px}
#rList{margin-top:6px}
/* 답글이 하나도 없을 때 — 빈 화면을 그냥 두면 고장난 줄 압니다 */
#rList .empty{text-align:center;padding:30px 24px 26px}
#rList .empty .ic{font-size:40px;line-height:1;opacity:.5;margin-bottom:12px}
#rList .empty p{margin:0;color:var(--tx2);font-size:14px;font-weight:700;line-height:1.5}
#rList .empty p.sub{margin-top:5px;color:var(--tx3);font-size:12.5px;font-weight:500}

/* ---------- 입력창 ---------- */
.composer{flex:0 0 auto;border-top:1px solid var(--line);background:var(--bg2);padding:10px 12px}
.composer .row{display:flex;gap:8px;align-items:flex-end}
/* 입력칸과 단추 높이를 38px 로 못박습니다. 그냥 두면 글자만 있는 '전송'(37.3)보다
   이모지가 든 '후원하기'(39.1)가 더 커서, 줄이 미세하게 들쭉날쭉해 보입니다. */
.composer .row .btn{white-space:nowrap;flex:0 0 auto;height:38px;padding-top:0;padding-bottom:0;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;line-height:1}
/* 이모지는 글자와 다른 글꼴에서 옵니다. 한 덩어리로 두면 이모지의 위아래 여유가
   글자 줄까지 끌어내려서 1.8px 쯤 아래로 쏠립니다. 따로 떼어 각자 가운데에 둡니다. */
.composer .row .btn .emo{display:block;font-size:15px;line-height:1}
/* 💸 는 글자와 달리 왼쪽에 2px 쯤 빈 테두리를 달고 나옵니다. 여백을 똑같이 16px 로 주면
   왼쪽만 18px 처럼 보입니다. 그만큼 덜어서 눈에 보이는 좌우를 맞춥니다. */
.composer .row #btnDonate2{padding-left:14px}
/* 유튜브와 같은 방식 — 입력칸 오른쪽 자리 하나를 두 단추가 나눠 씁니다.
   아무것도 안 썼으면 '후원하기', 한 글자라도 쓰면 그 자리에 '전송'이 들어옵니다. */
.composer .row #btnSend{display:none}
.composer.typing .row #btnSend{display:inline-flex}
.composer.typing .row #btnDonate2{display:none}
/* 답글 화면에서는 후원하기를 아예 숨깁니다 (유튜브 답글창과 같습니다).
   글을 쓰면 전송만 뜹니다. */
.app.replying #btnDonate2{display:none}
.composer textarea{resize:none;height:38px;max-height:120px;padding:8px 12px}
.composer .cnt{font-size:11px;color:var(--tx3);text-align:right;margin-top:3px;height:14px}
.nickbar{display:flex;align-items:center;gap:8px;margin-bottom:8px;font-size:13px;color:var(--tx2)}
.nickbar b{color:var(--tx)}

/* ---------- 모달 ---------- */
.modal{position:fixed;inset:0;background:rgba(0,0,0,.72);display:none;align-items:center;justify-content:center;padding:16px;z-index:60}
.modal.show{display:flex}
.sheet{background:var(--bg2);border:1px solid var(--line);border-radius:16px;padding:20px;width:100%;max-width:420px;max-height:90vh;overflow-y:auto;animation:pop .22s ease}
.sheet h2{margin:0 0 4px;font-size:18px}
.sheet .f{margin-top:14px}
.sheet .f label{display:block;font-size:13px;color:var(--tx2);margin-bottom:5px;font-weight:600}
/* 후원 창에서 시청자가 직접 채워야 하는 칸 — 주변 설명글보다 밝게 띄워 눈에 바로 들어오게 */
/* 후원 창 맨 위 인사 — 제목 대신 이 문장이 첫인상입니다 */
.sheet .thanks{margin:2px 0 20px;font-size:21px;line-height:1.45;font-weight:800;color:var(--tx);letter-spacing:-.02em}
/* 폰은 화면이 좁아 왼쪽 정렬하면 두 줄 끝이 들쪽날쪽해 보입니다.
   가운데로 모아 한 덩어리로 읽히게 합니다. */
@media (max-width:480px){
  .sheet .thanks{font-size:19px;text-align:center;line-height:1.5;margin:6px 0 22px}
}
.sheet .f label.hl{color:#fff;font-weight:800;font-size:14px}
.sheet .f label.hl .tiny{color:var(--tx3);font-weight:600}
.amt-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px}
.amt-chips button{background:var(--bg3);border:1px solid var(--line);color:var(--tx2);font-size:12.5px;padding:6px 11px;font-weight:600}
.amt-chips button:hover,.amt-chips button.sel{background:var(--accent);color:#fff;border-color:var(--accent)}
/* 결제 방법 — 바로 위 금액 칩과 똑같이 흘려서 같은 줄맞춤으로 읽히게 합니다.
   폭을 억지로 늘리지 않습니다. 늘려 놓으면 폰에서 줄이 넘어갈 때
   마지막 하나만 한 줄을 통째로 차지해 혼자 길쭉해집니다.
   다만 '하나만 고르는' 칸이라 hover 에는 색을 채우지 않습니다 —
   채우면 지금 고른 것이 어느 쪽인지 헷갈립니다. */
.pay-ways{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px}
.pay-ways button{background:var(--bg3);border:1px solid var(--line);
  color:var(--tx2);font-size:12.5px;padding:8px 12px;font-weight:700;white-space:nowrap}
.pay-ways button:hover{border-color:var(--accent);color:var(--tx)}
.pay-ways button.sel{background:var(--accent);color:#fff;border-color:var(--accent)}
.tier-preview{margin-top:10px;border-radius:10px;overflow:hidden}
.actions{display:flex;gap:8px;margin-top:18px}
.actions .btn{flex:1}
/* 결제 전 고지. 작게 두되 읽을 수는 있어야 해서 11.5px 아래로는 내리지 않습니다. */
.legalnote{margin:11px 0 0;font-size:11.5px;line-height:1.55;color:var(--tx3);text-align:center}
.legalnote a{color:var(--tx2);text-decoration:underline;text-underline-offset:2px}
.legalnote a:hover{color:var(--tx)}

/* ---------- 짧은 폰: 창이 한 화면에 들어오게 ---------- */
/* 화면이 짧으면 후원 창이 넘쳐서 안에 스크롤이 생겼습니다.
   글자는 거의 그대로 두고(입력칸 16px 은 iOS 가 화면을 제멋대로
   확대하지 않게 하는 선이라 못 줄입니다) 칸과 칸 사이 빈자리만
   단계적으로 좁힙니다.
   '결제 방법' 칸이 생기면서 창이 60px 쯤 길어졌습니다. 그만큼 네 단계를
   통째로 위로 올렸습니다 (780·660·580·500 → 840·740·650·560). */
@media (max-height:840px){
  .modal{padding:10px}
  .sheet{padding:16px;max-height:calc(100dvh - 20px)}
  .sheet .thanks{margin:0 0 14px;font-size:18px;line-height:1.4}
  .sheet .f{margin-top:11px}
  .sheet .f label{margin-bottom:4px}
  .sheet input,.sheet textarea{padding:8px 11px}
  .amt-chips{gap:5px;margin-top:6px}
  .amt-chips button{padding:5px 10px}
  .pay-ways{gap:5px;margin-top:6px}
  .pay-ways button{padding:7px 9px}
  .tier-preview{margin-top:7px}
  .actions{margin-top:13px}
}
@media (max-height:740px){
  .sheet{padding:13px}
  .sheet .thanks{margin:0 0 10px;font-size:16.5px}
  .sheet .f{margin-top:8px}
  .sheet .f label{font-size:12.5px}
  .sheet input,.sheet textarea{padding:7px 10px}
  .amt-chips button{padding:4px 9px;font-size:12px}
  .pay-ways button{padding:6px 8px;font-size:12px}
  .sheet .sc-head{padding:7px 11px}
  .sheet .sc-body{padding:7px 11px;font-size:13.5px}
  .actions{margin-top:10px}
  .actions .btn{padding:9px 16px}
}
/* 아주 작은 화면 — 여기서부턴 설명글과 쓸데없는 높이도 내주고
   입력칸·단추만 남깁니다. */
@media (max-height:650px){
  .sheet .thanks{font-size:15px;margin:0 0 8px;line-height:1.35}
  .sheet .f{margin-top:7px}
  #donStep1 .f label:not(.hl){display:none}
  #donStep1 .tier-preview{margin-top:0}
  #dMsg{height:44px}
  .amt-chips button{font-size:11.5px;padding:4px 8px}
  .pay-ways button{font-size:11.5px;padding:5px 9px}
  .sheet .sc-head{padding:6px 10px}
  .sheet .sc-body{padding:6px 10px;font-size:13px}
  .actions{margin-top:9px}
  .actions .btn{padding:8px 14px;font-size:13.5px}
}
@media (max-height:580px){
  /* 여기부터는 미리보기를 접습니다. 미리보기 카드 하나가 90px 인데,
     그걸 남겨두면 아래 단추가 화면 밖으로 밀려서 스크롤이 생깁니다.
     색과 모양은 후원이 올라가면 채팅창에서 바로 보입니다. */
  #previewBox{display:none}
  .modal{padding:6px}
  .sheet{padding:11px}
  .sheet .thanks{font-size:13.5px;margin:0 0 6px}
  .sheet .f{margin-top:6px}
  .sheet input,.sheet textarea{padding:6px 9px}
  #dMsg{height:38px}
  .amt-chips{margin-top:5px;gap:4px}
  .pay-ways{margin-top:5px;gap:4px}
  .sheet .sc-head,.sheet .sc-body{padding:5px 9px}
}
/* 가로로 눕힌 폰처럼 자리가 정말 없을 때 한 번 더 조입니다.
   인사말('이 채널이 유지되는 건…')은 접습니다 — 후원하기를 눌러서 열린 창이니
   제목이 없어도 뭘 하는 창인지 압니다. 대신 결제 전 고지는 절대 줄이지 않습니다. */
@media (max-height:490px){
  .sheet .thanks{display:none}
  .sheet .f{margin-top:5px}
  #dMsg{height:32px}
  .amt-chips button{padding:3px 7px;font-size:11px}
  .pay-ways button{padding:4px 8px;font-size:11px}
  .actions{margin-top:8px}
  .legalnote{margin-top:8px;line-height:1.45}
}
.bankbox{background:#0b0d11;border:1px dashed var(--line);border-radius:10px;padding:14px;margin-top:12px}
.bankbox .kv{display:flex;justify-content:space-between;gap:10px;padding:4px 0;font-size:14px}
.bankbox .kv span:first-child{color:var(--tx2)}
.bankbox .kv span:last-child{font-weight:700;text-align:right;word-break:break-all}
.codebox{background:#1a1205;border:1px solid #6b4a00;border-radius:10px;padding:13px;margin-top:12px}
/* 금액은 같은 글꼴을 쓰되, 숫자 폭만 고정해 자리가 띄지 않게 합니다 */
/* 자간을 벌려두면 '2,021원' 이 숫자 하나하나로 흩어져 보입니다. 살짝 조여 한 덩어리로 읽히게 합니다. */
.codebox .big{font-size:24px;font-weight:800;letter-spacing:-.4px;color:#ffd166;font-variant-numeric:tabular-nums}
.codebox .payrow{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 9px;margin-top:5px}
.codebox .payrow .tiny{color:var(--tx2);white-space:nowrap}
.statusbox{margin-top:12px;padding:11px 13px;border-radius:10px;background:var(--bg3);font-size:13.5px;font-weight:600}
.statusbox.wait{color:#ffd166}
.statusbox.done{color:#4ade80}

@keyframes fade{from{opacity:0}to{opacity:1}}
@keyframes pop{from{opacity:0;transform:scale(.94) translateY(6px)}to{opacity:1;transform:none}}

@media (max-width:600px){
  .app{border:0}
}

/* ---------- 좁은 화면 (폰) ----------
   헤더에 버튼이 네 개라, 그냥 두면 방 제목이 '뻑..' 으로 뭉개집니다.
   버튼을 줄이고 제목에 최소 너비를 줘서 제목이 먼저 살아남게 합니다. */
@media (max-width:480px){
  header.top{gap:6px;padding:10px 12px}
  header.top h1{font-size:15px;min-width:84px}
  .icon-btn{padding:4px 5px;font-size:17px}
  #btnVideo{padding:4px 9px}
  #btnVideo svg{width:17px;height:17px}
  .crown{font-size:12px;padding:6px 8px}
  .crown .cl{display:none}                 /* 아이콘만 남깁니다 */
  /* 단추 바뀌는 규칙은 위(기본)에 있습니다. 여기선 좁은 화면 크기만 맞춥니다.
     (textarea 가 기본 width:100% 라 flex 로 다시 잡아줘야 합니다) */
  .composer .row{flex-wrap:nowrap}
  .composer .row textarea{width:auto;flex:1 1 0;min-width:0}
  /* 좁은 화면에선 좌우만 줄입니다. 위아래는 높이 38px 에 맡깁니다.
     왼쪽이 2px 적은 건 💸 가 달고 나오는 빈 테두리만큼 덜어낸 것입니다. */
  .composer .row #btnDonate2{padding-left:11px;padding-right:13px}
}

/* ---------- 관리자 ---------- */
.adm{max-width:900px;margin:0 auto;padding:18px 16px 60px}
.adm h1{font-size:20px;margin:0 0 16px}
.card{background:var(--bg2);border:1px solid var(--line);border-radius:var(--radius);padding:16px;margin-bottom:14px}
.card h3{margin:0 0 12px;font-size:15px;display:flex;align-items:center;gap:8px}
.badge{background:var(--accent);color:#fff;font-size:11px;font-weight:800;padding:2px 7px;border-radius:999px}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.req{border:1px solid var(--line);border-radius:10px;padding:12px;margin-bottom:9px;background:var(--bg3)}
.req .top{display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.req .code{font-weight:800;color:#ffd166;background:#1a1205;border:1px solid #6b4a00;padding:2px 8px;border-radius:6px;font-size:14px;font-variant-numeric:tabular-nums}
.req .amt{font-weight:900;font-size:16px}
.req .btns{display:flex;gap:7px;margin-top:10px}
.req .btns .btn{padding:7px 14px;font-size:13px}
.login{max-width:360px;margin:12vh auto;padding:0 16px}
@media (max-width:600px){.grid2{grid-template-columns:1fr}}

/* 관리자 설정의 목록 입력칸 — 세로로만 늘어나게 둡니다 */
.card textarea{resize:vertical;line-height:1.6;min-height:52px}

/* 시청자 화면에서 관리자로 로그인했을 때 뜨는 표시 (누르면 로그아웃) */
.crown{
  background:#3a2d00; color:#ffd166; border:1px solid #6b5400;
  padding:6px 10px; border-radius:999px; font-size:13px; font-weight:700;
  font-family:inherit; white-space:nowrap;
}
.crown:hover{background:#4a3900}
.crown.off{background:#2a2d33;color:var(--tx3);border-color:var(--line)}
.crown.off:hover{background:#343840}

/* ---------- 키보드가 올라와 화면이 짧아졌을 때 ----------
   폰에서 입력칸을 누르면 키보드가 화면 절반을 먹습니다 (안드로이드는
   화면 자체가 줄어듭니다). 그대로 두면 영상이 남은 공간을 다 차지해서
   정작 입력칸과 채팅이 화면 밖으로 밀려납니다.
   그래서 세로가 짧아지면 영상을 작게 접습니다. */
@media (max-width:900px) and (max-height:560px){
  .page.has-video .vwrap{aspect-ratio:auto;height:28vh;min-height:96px}
  .page.has-video .vbar{padding:5px;font-size:12px}
  /* 펼쳐둔 후원 카드는 접습니다. 글 쓰는 동안은 입력칸이 먼저입니다.
     (위쪽 티커는 그대로 남아서 눌러 다시 펼칠 수 있습니다) */
  #scpin.show{display:none}
  .nickbar{margin-bottom:5px;font-size:12px}
  .composer{padding:8px 12px}
  .composer .cnt{display:none}
  .composer .row #btnDonate2{padding-left:6px;padding-right:8px}
  #ticker{padding-top:4px;padding-bottom:4px}
}

/* 안쪽 스크롤 영역이 끝까지 가도 바깥(페이지)으로 넘겨주지 않게 막습니다.
   티커를 옆으로 미는데 페이지가 같이 끌려가던 원인입니다. */
#log,#ticker,.vlist,#scpin .pb,.sheet{overscroll-behavior:contain}

/* 복사가 막힌 환경에서 계좌번호를 길게 눌러 선택할 수 있게 합니다 */
.kv .pick{user-select:text;-webkit-user-select:text}

/* ---------- 채팅창에서 바로 관리 (관리자만) ----------
   유튜브처럼 단추를 늘어놓지 않고, 채팅을 누르면 메뉴가 뜨는 방식입니다.
   채팅이 빠르게 올라갈 때 단추가 밀리면서 잘못 누르는 일을 막아줍니다. */
#log.modon .msg{cursor:pointer;border-radius:6px}
#log.modon .msg:hover{background:#1b1f27}
#log.modon .msg:active{background:#232833}

.modsheet{max-width:340px}
.modwho{
  font-size:16px;margin:0 0 4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.modlist{display:flex;flex-direction:column;gap:7px;margin-top:14px}
.modlist #modBanBox{display:flex;flex-direction:column;gap:7px}
.modbtn{
  width:100%;text-align:left;background:var(--bg3);color:var(--tx);
  padding:13px 14px;border-radius:9px;font-size:14.5px;font-weight:600;
  border:1px solid var(--line);font-family:inherit
}
.modbtn:hover{background:#2a2f39;border-color:#3a4150}
.modbtn.danger{color:#ff9a9a}
.modbtn.danger:hover{background:#3a1d1d;border-color:#6b2a2a}

/* ---------- 후원 순위 ---------- */
.rankrow{
  display:flex;align-items:center;gap:11px;padding:11px 12px;margin-bottom:7px;
  background:var(--bg3);border:1px solid var(--line);border-radius:10px
}
.rankrow.first{border-color:#6b5400;background:#2a2206}
.rankrow .rk{font-size:17px;min-width:26px;text-align:center;font-weight:800;color:var(--tx2)}
.rankrow .rmid{flex:1;min-width:0;display:flex;align-items:baseline;gap:4px}
.rankrow .rn{font-weight:700;font-size:14.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* 12시간 안에 넣은 횟수. 이름에 묻히지 않게 흐리게, 이름이 길어도 안 잘리게 따로 둡니다 */
.rankrow .rc{flex:0 0 auto;font-size:12px;font-weight:600;color:var(--tx3)}
.rankrow .ramt{font-weight:800;font-size:15px;white-space:nowrap;font-variant-numeric:tabular-nums}
.rankrow.first .ramt{color:#ffd166}
