/* SJ 통번역 — "말이 빛이 되는 방송실" 다크 스테이지.
   자막 2층 명도 체계는 설계 불변식: 회색층(유동) 낮은 명도, 검정층(refined, 불변) 최대 명도.
   모든 상시 모션은 transform/opacity 전용(GPU), prefers-reduced-motion 폴백 필수. */
:root {
  --bg: #0a0c11;
  --panel: rgba(19, 23, 31, .72);
  --panel-solid: #14171d;
  --edge: #232833;
  --edge-soft: rgba(255, 255, 255, .06);
  --fg-strong: #f5f7fa;      /* refined 번역 */
  --fg-fluid: #7d8594;       /* interim·committed(회색층) */
  --fg-orig: #9aa3b2;        /* refined 원문 */
  --fg-orig-fluid: #5b626e;
  --accent: #e6a23c;
  --accent-deep: #8a6423;
  --ok: #3ecf8e;
  --warn: #e6a23c;
  --err: #ef5350;
  --idle: #566070;
  /* 언어 색: 명도는 단계(회색층·검정층)에 예약되어 있으므로 언어는 색상으로만 구분한다 */
  /* 언어 색 — public/app.js 의 LANGS[].hex 와 같은 값이어야 한다 */
  --lang-en: #5aa9ff;
  --lang-ko: #e6a23c;
  --lang-vi: #3ecf8e;
  --lang-zh: #c77dff;
  --lang-ja: #ff8fa3;
  --lang-sw: #3ec8d8;
  --lang-id: #7ee081;
  --lang-ms: #f2c94c;
  --lang-th: #ffb84d;
  --lang-es: #ff9f68;
  --lang-ru: #9aa7ff;
  --lang-tl: #5fd0a8;
  --lang-ar: #d6b45e;
  --lang-fr: #6fb8ff;
  --lang-de: #b8b8c8;
  --lang-mn: #e08fd8;
  --lang-my: #c9a06a;
  --lang-ne: #8fd0e0;
  --lang-uz: #a8c96f;
  --cap-scale: 1;                        /* 자막 크기 배율(시청자 선택, 저장됨) */
  --orig-fs: clamp(13px, 2.1vw, 21px);
  --tr-fs: clamp(21px, 3.9vw, 42px);
  --serif: "Gowun Batang", "Nanum Myeongjo", serif;
  --sans: "IBM Plex Sans KR", "Pretendard", "Malgun Gothic", "Apple SD Gothic Neo", sans-serif;
  --mono: "IBM Plex Mono", Consolas, monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  background: var(--bg);
  color: var(--fg-strong);
  font-family: var(--sans);
  display: flex; flex-direction: column;
  overflow: hidden;
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* ── 배경 무대: 오로라 블롭 + 필름 그레인 (블러 필터 없이 그라데이션만 — 폰 GPU 배려) ── */
#fx { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
#fx .blob { position: absolute; border-radius: 50%; will-change: transform; }
#fx .blob.a {
  width: 70vmax; height: 70vmax; left: -22vmax; top: -30vmax;
  background: radial-gradient(circle, rgba(230, 162, 60, .13) 0%, rgba(230, 162, 60, .05) 38%, transparent 68%);
  animation: drift-a 52s ease-in-out infinite alternate;
}
#fx .blob.b {
  width: 80vmax; height: 80vmax; right: -30vmax; bottom: -36vmax;
  background: radial-gradient(circle, rgba(43, 66, 120, .20) 0%, rgba(43, 66, 120, .07) 40%, transparent 70%);
  animation: drift-b 64s ease-in-out infinite alternate;
}
#fx .blob.c {
  width: 46vmax; height: 46vmax; left: 30vw; top: 46vh;
  background: radial-gradient(circle, rgba(62, 207, 142, .05) 0%, transparent 62%);
  animation: drift-c 47s ease-in-out infinite alternate;
}
@keyframes drift-a { from { transform: translate(0, 0) scale(1); } to { transform: translate(9vw, 7vh) scale(1.12); } }
@keyframes drift-b { from { transform: translate(0, 0) scale(1.08); } to { transform: translate(-8vw, -6vh) scale(1); } }
@keyframes drift-c { from { transform: translate(0, 0); } to { transform: translate(-10vw, -8vh) scale(1.18); } }
#fx .grain {
  position: absolute; inset: 0; opacity: .05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
}
#topbar, #banner, #gate, main, #hostbar { position: relative; z-index: 1; }

/* ── 상단바: 유리 패널 ── */
#topbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 18px;
  background: var(--panel);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--edge-soft);
}
.brand { display: flex; align-items: center; gap: 10px; }
.brand .sig { flex: 0 0 auto; display: block; }
/* Back to the first screen (room list), on host and guest pages alike (2026-10-12). */
.home-link {
  font-size: 12.5px; color: var(--fg); text-decoration: none; white-space: nowrap;
  border: 1px solid var(--edge); border-radius: 999px; padding: 4px 11px;
}
.home-link:hover { border-color: var(--accent); }
.home-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.home-link.armed { border-color: var(--err); color: var(--err); }
.wordmark, .mode { white-space: nowrap; }
/* Phones: the back button takes the wordmark's place; the logo stays. */
@media (max-width: 440px) { .brand .wordmark { display: none; } }
.wordmark { font-family: var(--serif); font-weight: 700; font-size: 18px; letter-spacing: .01em; }
.mode {
  font-family: var(--mono); font-size: 11.5px; color: var(--accent); font-weight: 500;
  border: 1px solid var(--accent-deep); border-radius: 999px; padding: 3px 10px;
  letter-spacing: .06em;
}
/* ── 룸 배지 + 룸 패널 ── */
.room-badge {
  background: rgba(230, 162, 60, .1); border: 1px solid var(--accent-deep); border-radius: 999px;
  color: var(--accent); font-family: var(--sans); font-size: 12px; font-weight: 500;
  padding: 4px 11px; cursor: default; max-width: 40vw; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.room-badge { cursor: pointer; }
.room-badge:hover { filter: brightness(1.15); }
#roomPanel { position: fixed; inset: 0; z-index: 40; background: rgba(6, 8, 12, .62); display: flex;
  align-items: flex-start; justify-content: center; padding: 76px 16px 16px; }
.rp-card { width: min(460px, 100%); background: var(--panel-solid); border: 1px solid var(--edge);
  border-radius: 14px; padding: 18px; box-shadow: 0 18px 50px rgba(0, 0, 0, .5); }
.rp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.rp-head b { font-size: 14px; letter-spacing: .02em; }
.rp-x { background: transparent; border: 1px solid var(--edge); border-radius: 7px; color: var(--fg-orig);
  font-family: var(--sans); font-size: 12px; padding: 5px 10px; cursor: pointer; }
.rp-list { display: flex; flex-direction: column; gap: 7px; max-height: 46vh; overflow-y: auto; }
.rp-item { display: flex; align-items: center; gap: 8px; }
.rp-go { flex: 1; text-align: left; background: transparent; border: 1px solid var(--edge);
  border-left: 3px solid var(--edge); border-radius: 9px; padding: 9px 12px; cursor: pointer;
  color: var(--fg-strong); font-family: var(--sans); }
.rp-go:hover { background: rgba(255, 255, 255, .04); }
.rp-go.on { border-left-color: var(--accent); background: rgba(230, 162, 60, .08); }
.rp-go b { display: block; font-size: 14px; font-weight: 700; }
.rp-go i { font-style: normal; font-size: 11px; color: var(--fg-orig-fluid); font-family: var(--mono); }
.rp-copy { background: transparent; border: 1px solid var(--edge); border-radius: 7px; color: var(--fg-orig);
  font-family: var(--sans); font-size: 12px; padding: 7px 10px; cursor: pointer; white-space: nowrap; }
.rp-copy:hover { color: var(--fg-strong); }
.rp-new { display: flex; gap: 8px; margin-top: 14px; }
.rp-new input { flex: 1; background: #0e1116; border: 1px solid var(--edge); border-radius: 8px;
  color: var(--fg-strong); font-family: var(--sans); font-size: 13px; padding: 9px 11px; }
.rp-new button { background: var(--accent); border: none; border-radius: 8px; color: #1a1205;
  font-family: var(--sans); font-size: 13px; font-weight: 700; padding: 9px 15px; cursor: pointer; }
.rp-note { font-size: 11.5px; color: var(--fg-orig-fluid); line-height: 1.55; margin-top: 13px; }

.pills { display: flex; gap: 8px; flex-wrap: wrap; }
.pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12px; color: var(--fg-orig);
  background: rgba(25, 29, 37, .8); border: 1px solid var(--edge);
  padding: 4px 11px; border-radius: 999px;
}
.pill .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--idle); transition: background .2s ease, box-shadow .2s ease; }
.pill[data-state="ok"] .dot { background: var(--ok); box-shadow: 0 0 8px rgba(62, 207, 142, .7); animation: breathe 2.4s ease-in-out infinite; }
.pill[data-state="warn"] .dot { background: var(--warn); box-shadow: 0 0 8px rgba(230, 162, 60, .6); }
.pill[data-state="err"] .dot { background: var(--err); box-shadow: 0 0 8px rgba(239, 83, 80, .6); }
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
.controls { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.controls button {
  font: inherit; font-size: 13px; font-weight: 700;
  color: var(--fg-strong); background: rgba(38, 42, 53, .85);
  border: 1px solid var(--edge); border-radius: 9px;
  padding: 7px 16px; cursor: pointer;
  transition: filter .15s ease, transform .15s ease;
}
.controls button.primary { background: var(--accent); border-color: var(--accent); color: #1a1205; }
.controls button.ghost { background: transparent; }
.controls button:disabled { opacity: .4; cursor: default; }
.controls button:not(:disabled):hover { filter: brightness(1.12); transform: translateY(-1px); }
.controls input[type="text"], .controls select {
  font: inherit; font-size: 13px; color: var(--fg-strong);
  background: rgba(25, 29, 37, .85); border: 1px solid var(--edge); border-radius: 9px;
  padding: 6px 10px; width: 110px;
}
.controls select { width: auto; }
.tts-wrap { font-size: 12px; color: var(--fg-orig); display: inline-flex; gap: 6px; align-items: center; }
/* Read-aloud notes (voice substitution, natural-voice status, the host's half-duplex note), round 3: one line of their own
   under the whole header row (a full-width item of #topbar, last in order), the notes run on in it. They are outside the
   controls row, so they never widen it (two notes used to push the controls under the logo) and never change its
   alignment (rows jumped left and right as a note came and went). */
/* Korean notes wrap between words, never inside one («읽는 / 동안은», not «읽는 동 / 안은»); a very long token (a voice
   name, a URL) may still break anywhere rather than widen the header on a 360 px phone. */
/* Each note is an item of its own (.tts-item: every note app.js puts in #ttsNote, and #ttsMicNote), 2026-10-16: the line
   wraps between notes. The «·» between two notes sits in the gap after a note (desktop, notes right-aligned) or before it
   (phones, left-aligned). The note that ends a right-aligned line or starts a left-aligned one has its «·» outside the
   box, where overflow clips it, so no line starts (or ends) with a separator. */
.tts-notes { --note-gap: 1.3em; flex: 1 0 100%; order: 9; margin-top: -8px; font-size: 11px; line-height: 1.45; text-align: right;
             display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: flex-start; column-gap: var(--note-gap);
             overflow: hidden; word-break: keep-all; overflow-wrap: anywhere; }
.tts-notes:not(:has(.tts-note:not([hidden]))) { display: none; }
.tts-note { font-size: 11px; color: var(--fg-orig); opacity: .8; word-break: keep-all; overflow-wrap: anywhere; min-width: 0; }
#ttsNote:not([hidden]) { display: flex; flex-wrap: wrap; justify-content: inherit; column-gap: var(--note-gap); }
.tts-item { position: relative; min-width: 0; }
.tts-item::after { content: '·'; position: absolute; top: 0; right: calc(var(--note-gap) / -2); transform: translateX(50%);
                   color: var(--fg-orig); }
/* Read-aloud group and «번역 시작 · 종료» (2026-10-15): no box of their own, their parts sit in the controls row like before.
   Only the host phone screen gives them boxes (simple-mode section below). */
.read-group, .run-group { display: contents; }
/* This device is reading a line aloud and its microphone pauses meanwhile (echo guard): the label and the host's
   half-duplex note quietly say so. */
#ttsWrap, #ttsMicNote { transition: color .2s ease, opacity .2s ease; }
body.host.echo-hold #ttsWrap,
body.host.echo-hold #ttsMicNote { color: var(--accent); opacity: 1; }
.pill[data-state="pause"] .dot { background: var(--fg-orig); box-shadow: none; }

/* ── 배너 ── */
#banner {
  display: none;
  padding: 8px 18px; font-size: 13px;
  background: rgba(58, 43, 22, .9); color: #f0c98a; border-bottom: 1px solid #57431f;
}
#banner.show { display: block; }
/* 알림 안의 행동 버튼(새 창에서 열기·주소 복사) */
#banner .banner-act { margin: 2px 0 2px 10px; padding: 4px 11px; font: inherit; font-size: 12.5px; color: #1a1205; background: #f0c98a; border: 0; border-radius: 999px; cursor: pointer; }
.gate-hint { margin-top: 4px; font-size: 12.5px; color: var(--fg-orig); }

/* ── 비밀번호 게이트: 파형이 흐르는 입장 무대 ── */
#gate {
  position: fixed; inset: 0; z-index: 50;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 90% at 50% 10%, #10141d 0%, var(--bg) 58%);
  overflow: hidden;
}
.gate-wave {
  position: absolute; left: 50%; top: 74%;
  width: min(1200px, 160vw); transform: translate(-50%, -50%);
  opacity: 1; pointer-events: none;
}
.gate-wave .w1 { stroke: var(--accent); stroke-dasharray: 6 14; animation: wave-flow 3.2s linear infinite; }
.gate-wave .w2 { stroke: var(--fg-orig-fluid); stroke-dasharray: 3 9; animation: wave-flow 5.1s linear infinite reverse; opacity: .6; }
@keyframes wave-flow { to { stroke-dashoffset: -200; } }
.gate-card {
  position: relative;
  width: min(360px, 88vw);
  background: rgba(19, 23, 31, .82);
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  border: 1px solid var(--edge-soft); border-radius: 18px;
  padding: 34px 28px 26px; text-align: center;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .5);
  animation: card-in .5s cubic-bezier(.2, .9, .3, 1.2) both;
}
@keyframes card-in { from { opacity: 0; transform: translateY(22px) scale(.97); } }
.gate-brand { font-family: var(--serif); font-weight: 700; font-size: 24px; letter-spacing: .01em; }
.gate-tag { margin-top: 8px; font-size: 13.5px; color: var(--fg-orig); }
.gate-tag em { font-style: normal; color: var(--accent); font-weight: 700; }
.gate-sub { font-size: 12.5px; color: var(--fg-orig-fluid); margin: 20px 0 12px; }
#gateForm { display: flex; gap: 8px; }
#gatePass {
  flex: 1; min-width: 0;
  font: inherit; font-size: 17px; text-align: center; letter-spacing: .28em;
  color: var(--fg-strong); background: rgba(12, 14, 19, .85);
  border: 1px solid var(--edge); border-radius: 10px; padding: 11px 12px;
  transition: border-color .2s ease;
}
#gatePass:focus { border-color: var(--accent-deep); }
#gateForm button {
  font: inherit; font-size: 14px; font-weight: 700; color: #1a1205;
  background: var(--accent); border: 1px solid var(--accent); border-radius: 10px;
  padding: 11px 20px; cursor: pointer;
  transition: filter .15s ease;
}
#gateForm button:hover { filter: brightness(1.1); }
.gate-err { min-height: 18px; margin-top: 12px; font-size: 12px; color: var(--err); }
.gate-remember { display: inline-flex; align-items: center; gap: 7px; margin-top: 12px;
  font-size: 12px; color: var(--fg-orig); cursor: pointer; }
#gate.shake .gate-card { animation: shake .4s ease; }
@keyframes shake { 20% { transform: translateX(-7px); } 45% { transform: translateX(6px); } 70% { transform: translateX(-4px); } 90% { transform: translateX(2px); } }

/* ── 자막 무대 ── */
#scroll { flex: 1; overflow-y: auto; scroll-behavior: auto; position: relative; }   /* 부드러운 이동은 새 줄이 붙을 때만(autoscroll) */
#lines {
  min-height: 100%;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: clamp(14px, 2.4vh, 26px);
  padding: 22px clamp(16px, 5vw, 64px) 30px;
  max-width: 1400px; margin: 0 auto; width: 100%;
}
/* 줄 순서: 번역(크게) → 인식한 원문(작게) → 보조 자막. 읽는 사람은 자기 언어를 먼저 보고, 그 아래에서 원문을 확인한다(사용자 지시 9/4) */
.line { line-height: 1.42; position: relative; padding-left: 13px; display: flex; flex-direction: column; }
.line .tr { order: 1; }
.line .orig { order: 2; }
.line .aux { order: 3; }
/* 언어 막대: 위 절반 = 지금 보고 있는 자막 언어, 아래 절반 = 원문 언어(줄 순서와 같게) */
.line::before {
  content: ''; position: absolute; left: 0; top: 3px; bottom: 3px; width: 3px; border-radius: 2px;
  background: linear-gradient(180deg, var(--l2, var(--l1, var(--edge))) 0 50%, var(--l1, var(--edge)) 50% 100%);
}
.line .orig {
  font-size: calc(var(--orig-fs) * var(--cap-scale));
  color: var(--fg-orig-fluid);
  margin-top: 4px;
  overflow-wrap: anywhere;
}
/* 언어 칩: 원문 → 자막 (예: EN → KO). 전광판·자막 띠에서는 감춘다 */
.line .lt {
  display: inline-block; margin-right: 8px; padding: 1px 6px;
  font-family: var(--mono); font-size: 10px; font-weight: 500; letter-spacing: .04em;
  color: var(--l1, var(--idle)); border: 1px solid currentColor; border-radius: 3px;
  opacity: .8; white-space: nowrap; vertical-align: 1px;
}
.line .tr {
  font-size: calc(var(--tr-fs) * var(--cap-scale));
  font-weight: 700;
  color: var(--fg-fluid);
  overflow-wrap: anywhere;
  transition: color .25s ease;
}
/* 보조 자막(영어 병기): 주 자막 아래 한 단 작게. 명도는 검정층 원칙을 따르되 주 자막에 양보한다 */
.line .aux {
  margin-top: 3px;
  font-size: calc(var(--tr-fs) * var(--cap-scale) * 0.62);
  font-weight: 500;
  color: var(--fg-orig-fluid);
  overflow-wrap: anywhere;
}
.line.stage-refined .aux { color: var(--fg-orig); }
.line .aux .ac {
  display: inline-block; margin-right: 7px; padding: 0 5px;
  font-family: var(--mono); font-size: 9px; font-weight: 500; letter-spacing: .04em;
  color: var(--l3, var(--idle)); border: 1px solid currentColor; border-radius: 3px;
  opacity: .75; white-space: nowrap; vertical-align: 1px;
}
.line .aux[hidden] { display: none !important; }
/* 회색층: interim = committed 동일 톤(설계문서 §4 — 상태 전이를 색 점프로 노출하지 않는다) */
.line.stage-interim .tr .p { opacity: .75; }
/* 검정층: 불변 */
.line.stage-refined .orig { color: var(--fg-orig); }
.line.stage-refined .tr { color: var(--fg-strong); }
@keyframes line-in { from { opacity: 0; transform: translateY(14px); } }
@keyframes refine-glow {
  0% { text-shadow: 0 0 0 rgba(230, 162, 60, 0); }
  35% { text-shadow: 0 0 26px rgba(230, 162, 60, .38); }
  100% { text-shadow: 0 0 0 rgba(230, 162, 60, 0); }
}
.warn-badge {
  display: inline-block; vertical-align: middle;
  margin-left: 10px; padding: 2px 8px;
  font-size: 11px; font-weight: 700;
  color: var(--warn); border: 1px solid var(--warn); border-radius: 6px;
  opacity: .9;
  animation: badge-in .5s ease both;
}
@keyframes badge-in { from { opacity: 0; transform: scale(.8); } to { opacity: .9; transform: scale(1); } }

/* 대기 화면: 첫 자막 전 숨쉬는 링 */
#idle {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px;
  pointer-events: none;
}
#scroll:has(.line) #idle { display: none; }
#idle .ring { position: relative; width: 92px; height: 92px; }
#idle .ring::before, #idle .ring::after {
  content: ""; position: absolute; inset: 0; border-radius: 50%;
  border: 1.5px solid var(--accent-deep);
}
#idle .ring::before { animation: ring-pulse 3.2s ease-out infinite; }
#idle .ring::after { animation: ring-pulse 3.2s ease-out 1.6s infinite; }
@keyframes ring-pulse { 0% { transform: scale(.55); opacity: .9; } 100% { transform: scale(1.25); opacity: 0; } }
#idle .ring .core {
  position: absolute; inset: 32px; border-radius: 50%;
  background: radial-gradient(circle, rgba(230, 162, 60, .8), rgba(230, 162, 60, .12) 70%);
  animation: breathe 3.2s ease-in-out infinite;
}
#idle .t1 { font-family: var(--serif); font-weight: 700; font-size: 17px; color: var(--fg-orig); }
#idle .t2 { font-size: 12.5px; color: var(--fg-orig-fluid); }

/* ── 하단(호스트): 유리 콘솔 + 실시간 파형 ── */
#hostbar {
  display: none; align-items: center; gap: 18px;
  padding: 10px 18px;
  background: var(--panel);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  border-top: 1px solid var(--edge-soft);
}
#micWave { flex: 0 0 auto; width: 220px; height: 36px; border-radius: 6px; background: rgba(12, 14, 19, .6); }
.wave-label { font-size: 10.5px; color: var(--fg-orig-fluid); letter-spacing: .08em; }
.join { margin-left: auto; display: flex; align-items: center; gap: 14px; }
/* 완전무료 모드: 표준/무료 전환 링크 + 브라우저 내장 인식용 언어 토글 */
.engine-link {
  font-size: 12px; color: var(--fg-orig); text-decoration: none;
  border: 1px solid var(--edge); border-radius: 9px; padding: 6px 12px;
  white-space: nowrap; transition: filter .15s ease;
}
.engine-link:hover { filter: brightness(1.25); color: var(--fg-strong); }
.lang-tog { gap: 4px; }
.lang-tog button { padding: 7px 10px; }
.join-label { font-size: 11px; color: var(--fg-orig-fluid); }
.join-url { font-family: var(--mono); font-size: 12.5px; color: var(--fg-orig); word-break: break-all; }
#qr { border-radius: 8px; background: #fff; padding: 4px; }

/* 뷰어에서는 호스트 요소 숨김. 고급(adv) 전용 요소는 /host?adv=1 에서만 */
.host-only, .adv-only { display: none; }
body.host .host-only { display: inline-flex; }
body.host .view-lang-wrap { display: none; }   /* 자막 언어 선택은 시청자 전용 */
body.host #hostbar { display: flex; }
body.host .controls .host-only { display: inline-block; }
body.adv .adv-only { display: inline-flex; }
body.adv .controls .adv-only { display: inline-block; }

/* ── 전광판(모니터 팝업): 자막만 크게, 컨트롤 전부 숨김. 더블클릭 = 전체화면 ── */
body.display #topbar, body.display #banner, body.display #hostbar { display: none; }
body.display #lines { max-width: none; padding: 3vh 5vw 5vh; gap: 3.2vh; }
body.display { --orig-fs: clamp(16px, 2.6vw, 30px); --tr-fs: clamp(30px, 5.6vw, 76px); }
body.display .line .tr { line-height: 1.32; }
body.display .line .lt, body.strip .line .lt,
body.display .line .aux .ac, body.strip .line .aux .ac { display: none; }
body.display #idle .t2 { display: none; }

body.display #scroll, body.strip #scroll { scrollbar-width: none; }
body.display #scroll::-webkit-scrollbar, body.strip #scroll::-webkit-scrollbar { display: none; }

/* ── 자막 띠(strip): 하단 캡션 밴드 — OBS 브라우저 소스·빔 하단 배치용 ── */
body.strip #topbar, body.strip #banner, body.strip #hostbar, body.strip #idle, body.strip #fx { display: none; }
body.strip { background: #000; }
body.strip #lines { max-width: none; padding: 10px 4vw 16px; gap: 8px; }
body.strip .line { text-align: center; }
body.strip { --orig-fs: clamp(13px, 1.8vw, 20px); --tr-fs: clamp(24px, 3.6vw, 46px); }
body.strip .line .orig { margin-bottom: 2px; }
body.strip .line .tr { line-height: 1.3; }

@media (max-width: 620px) {
  #topbar { padding: 8px 10px; gap: 8px; }
  .tts-notes { margin-top: -3px; text-align: left; justify-content: flex-start; }   /* under the reading controls, which start at the left here */
  .tts-item::after { right: auto; left: calc(var(--note-gap) / -2); transform: translateX(-50%); }   /* «·» before a note */
  .join { display: none; }
  #micWave { width: 150px; }
  #lines { padding-bottom: 18px; }
  .gate-wave { opacity: .55; }
}
@media (prefers-reduced-motion: reduce) {
  #fx .blob, #idle .ring::before, #idle .ring::after, #idle .ring .core,
  .pill[data-state="ok"] .dot, .gate-wave .w1, .gate-wave .w2 { animation: none !important; }
  .line, .line .tr { animation: none !important; }   /* 인라인 등장·글로우도 무력화 */
  .line .tr { transition: none; }
  #scroll { scroll-behavior: auto; }
  .gate-card { animation-duration: .01s; }
}

/* ── 앞문 대시보드 ────────────────────────────────────────────────
   게이트와 같은 무대 위에 선다. 처음 여는 사람이 볼 것은 «어느 통역에 들어갈까» 하나뿐이다. */
#board {
  position: fixed; inset: 0; z-index: 51;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 90% at 50% 10%, #10141d 0%, var(--bg) 58%);
  padding: 20px; overflow: auto;
}
.board-card {
  width: min(560px, 100%);
  background: rgba(18, 21, 28, .92); border: 1px solid var(--edge);
  border-radius: 16px; padding: 22px 22px 18px;
}
.board-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 16px; }
.board-new {
  font: inherit; font-size: 13px; font-weight: 700; white-space: nowrap;
  color: #1a1205; background: var(--accent); border: 1px solid var(--accent);
  border-radius: 10px; padding: 9px 14px; cursor: pointer;
}
.board-list { display: flex; flex-direction: column; gap: 8px; }
.board-row {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  font: inherit; color: var(--fg-strong);
  background: rgba(12, 14, 19, .8); border: 1px solid var(--edge);
  border-radius: 12px; padding: 13px 14px; cursor: pointer;
}
.board-row:hover { border-color: var(--accent); }
.board-row .bn { flex: 1; min-width: 0; }
.board-row .bt { font-size: 15px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-row .bs { font-size: 12px; color: var(--fg-orig); margin-top: 3px; }
.board-row .bl { font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 999px; white-space: nowrap; }
.board-row .bl[data-on="1"] { color: #1a1205; background: var(--accent); }
.board-row .bl[data-on="0"] { color: var(--fg-orig); border: 1px solid var(--edge); }
.board-empty { font-size: 13px; color: var(--fg-orig); padding: 18px 2px; text-align: center; }
.board-form { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
.board-f { display: flex; flex-direction: column; gap: 5px; font-size: 12px; color: var(--fg-orig); }
.board-f input {
  font: inherit; font-size: 15px; color: var(--fg-strong);
  background: rgba(12, 14, 19, .85); border: 1px solid var(--edge);
  border-radius: 10px; padding: 10px 12px;
}
.board-actions { display: flex; gap: 8px; }
.board-actions button {
  font: inherit; font-size: 14px; font-weight: 700;
  color: #1a1205; background: var(--accent); border: 1px solid var(--accent);
  border-radius: 10px; padding: 10px 16px; cursor: pointer;
}
.board-actions .board-ghost { color: var(--fg-orig); background: transparent; border-color: var(--edge); }
.board-opt { color: var(--fg-orig); opacity: .75; font-weight: 400; }

/* 통역 언어쌍 고르기 — 두 칸과 그 사이 기호 하나. 고르는 즉시 아래 한 줄로 설명한다. */
.board-flabel { display: block; }
.board-langrow { display: flex; align-items: center; gap: 8px; }
.board-lang {
  flex: 1; min-width: 0;
  font: inherit; font-size: 15px; color: var(--fg-strong);
  background: rgba(12, 14, 19, .85); border: 1px solid var(--edge);
  border-radius: 10px; padding: 10px 12px; cursor: pointer;
}
.board-langmid { flex: 0 0 auto; color: var(--fg-orig); opacity: .7; font-size: 15px; }
.board-note { color: var(--fg-orig); opacity: .8; line-height: 1.5; }
/* 목록 행의 언어쌍 배지 */
.board-pair {
  display: inline-block; margin-left: 6px; padding: 1px 7px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: .02em;
  color: var(--fg-orig); border: 1px solid var(--edge);
}

/* 세션 행: 본체 + 호스트 전용 삭제 */
.board-item { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.board-item .board-row { flex: 1; min-width: 0; }
.board-del {
  font: inherit; font-size: 12px; font-weight: 700; white-space: nowrap;
  color: var(--fg-orig); background: transparent;
  border: 1px solid var(--edge); border-radius: 10px; padding: 9px 12px; cursor: pointer;
}
.board-del[data-armed="1"] { color: #1a1205; background: #e07b6a; border-color: #e07b6a; }
.board-del.board-keep { color: var(--fg-orig); background: transparent; border-color: var(--edge); }
.board-note { flex: 1 0 100%; font-size: 11px; color: var(--fg-orig); padding: 0 2px 2px; }


/* ── 앞문(호스트): 기능 → 언어 ─────────────────────────────────
   처음 여는 사람이 고를 것은 «무엇을 통역할까» 둘 중 하나다. 그다음 언어 두 칸. */
#fnPick {
  position: fixed; inset: 0; z-index: 52;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(120% 90% at 50% 10%, #10141d 0%, var(--bg) 58%);
  padding: 20px; overflow: auto;
}
.fn-card {
  width: min(640px, 100%);
  background: rgba(18, 21, 28, .92); border: 1px solid var(--edge);
  border-radius: 16px; padding: 24px 24px 20px;
}
.fn-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 4px; }
.fn-opt {
  font: inherit; text-align: left; color: var(--fg-strong);
  background: rgba(255, 255, 255, .03); border: 1px solid var(--edge); border-radius: 14px;
  padding: 20px 18px 18px; cursor: pointer; display: flex; flex-direction: column; gap: 9px; min-height: 140px;
  transition: border-color .15s, transform .15s, background .15s;
}
.fn-opt:hover { border-color: var(--accent); background: rgba(230, 162, 60, .06); transform: translateY(-1px); }
.fn-opt b { font-family: var(--serif); font-weight: 700; font-size: 19px; letter-spacing: .01em; }
.fn-opt span { font-size: 12.5px; color: var(--fg-orig); line-height: 1.55; }
#fnStep2 { display: flex; flex-direction: column; gap: 10px; }
#fnStep2 .board-lang { width: 100%; }
.board-headbtns { display: flex; gap: 8px; align-items: center; }
.board-back {
  font: inherit; font-size: 12.5px; white-space: nowrap; color: var(--fg-orig);
  background: transparent; border: 1px solid var(--edge); border-radius: 10px; padding: 8px 12px; cursor: pointer;
}
.board-back:hover { border-color: var(--accent); color: var(--fg-strong); }
@media (max-width: 560px) { .fn-grid { grid-template-columns: 1fr; } }

/* ── 웹 영상 실시간 통역 패널(호스트 ?fn=video) ─────────────────── */
#videoPanel { display: none; }
body.video #videoPanel {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 18px 8px; border-bottom: 1px solid var(--edge-soft);
  background: var(--panel); position: relative; z-index: 1;
}
.vp-row { display: flex; gap: 8px; }
.vp-row input {
  flex: 1; min-width: 0; font: inherit; font-size: 14px; color: var(--fg-strong);
  background: rgba(255, 255, 255, .04); border: 1px solid var(--edge); border-radius: 10px; padding: 9px 12px;
}
.vp-row input:focus { border-color: var(--accent-deep); outline: none; }
.vp-row button {
  font: inherit; font-size: 13px; font-weight: 700; color: #1a1205;
  background: var(--accent); border: 1px solid var(--accent); border-radius: 10px; padding: 9px 16px; cursor: pointer;
}
.vp-row button:disabled { opacity: .5; cursor: default; }
.vp-player {
  width: min(100%, calc(40vh * 16 / 9)); aspect-ratio: 16 / 9; margin: 0 auto;
  background: #000; border-radius: 12px; overflow: hidden;
}
.vp-player iframe { width: 100%; height: 100%; display: block; border: 0; }
.vp-foot { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.vp-note { font-size: 12.5px; color: var(--fg-orig); line-height: 1.5; flex: 1 1 320px; }
.vp-note[data-kind="err"] { color: var(--err); }
.vp-note[data-kind="ok"] { color: var(--ok); }
.vp-methods { display: flex; align-items: center; gap: 6px; }
.vp-mlabel { font-size: 11.5px; color: var(--fg-orig-fluid); margin-right: 2px; }
.vp-m {
  font: inherit; font-size: 12px; color: var(--fg-orig); background: transparent;
  border: 1px solid var(--edge); border-radius: 999px; padding: 5px 11px; cursor: pointer;
}
.vp-m[data-on="1"] { color: #1a1205; background: var(--accent); border-color: var(--accent); }
.vp-m:disabled { opacity: .35; cursor: default; }
body.video #hostbar .wave-label::after { content: " · 영상"; color: var(--fg-orig-fluid); }
/* 자동감지 방에서 목표 언어로 말한 줄 — 원문 줄은 접는다(같은 글 두 번 금지) */
.line .orig.same { display: none; }


/* ── 심플 모드(기본) — 보이는 조작은 셋: 웹 영상 인식 · 번역 시작 · 종료 ────────
   상태 알약·함께 보기·자막 크기·룸 배지·엔진/고급/회의록 링크·파형·방식 칩은 ?adv=1 에서만.
   Exception (2026-10-15): «읽어주기» is shown to hosts and guests alike (rules further down). */
body.simple .pills,
body.simple #langTog,
body.simple .tts-wrap:not(.view-lang-wrap),
body.simple label:has(#auxLang),
body.simple #roomBadge,
body.simple #engineLink,
body.simple #advLink,
body.simple #minLink,
body.simple #micWave,
body.simple .wave-label,
body.simple .vp-methods { display: none !important; }
body.simple .controls button.primary { padding: 9px 18px; font-size: 14px; }
/* 시청자는 글자 크기를 직접 키울 수 있어야 한다 — 폰 화면·시력은 사람마다 다르다 */
body.simple:not(.host) .tts-wrap:has(#capSize) { display: inline-flex !important; }
/* Reading aloud and the natural voice (beta, 2026-10-12) are on the simple screen for guests and, since 2026-10-15, hosts
   (a one-device face-to-face host reads the other side aloud). The voice picker shows only while reading is on. */
body.simple .tts-wrap:has(#ttsSel),
body.simple #ttsVoiceWrap:not([hidden]) { display: inline-flex !important; }
/* Host phone: «번역 시작 · 종료» stay on the first row next to the logo; reading gets the row below. */
@media (max-width: 620px) {
  body.host.simple .controls { display: contents; }
  body.host.simple .run-group { display: inline-flex; gap: 8px; align-items: center; margin-left: auto; }   /* the two never split */
  body.host.simple .read-group {
    order: 2; flex: 1 0 100%; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 8px;
  }
  body.host.simple .read-group select { padding: 6px 8px; }   /* «읽어주기» and «목소리» share one row on a 390 px phone */
}
/* 360 px phones (many Android phones): the back button, the logo, the language pair and «번역 시작 · 종료» still fit on
   one row once the gaps and button padding shrink a little. Up to 389 px since the lows round (2026-10-16): at 381-388 px
   (e.g. 384 px phones) «번역 시작 · 종료» used to drop to a row of their own. */
@media (max-width: 389px) {
  body.host.simple #topbar { gap: 6px; }
  body.host.simple .brand { gap: 6px; }
  body.host.simple .home-link { padding: 4px 9px; }
  body.host.simple .mode { padding: 3px 7px; letter-spacing: .02em; }
  body.host.simple .run-group { gap: 6px; }
  body.host.simple .run-group button { padding: 8px 12px; }
}
/* 360-389 px phones with reading on (lows round, 2026-10-16): «읽어주기» and «목소리 (베타)» need about 361 px side by side,
   so the picker took a row of its own and the header grew from 97 to 173 px. Slightly tighter gaps and select padding
   and 1 px smaller dim labels bring the pair to about 334 px at 360 (measured with the longest Malay voice name; the
   chosen value keeps its 13 px). If a device's font is wider, the picker simply wraps below as before. */
@media (max-width: 389px) {
  body.host.simple .read-group { gap: 6px; }
  body.host.simple .read-group .tts-wrap { gap: 4px; font-size: 11px; }
  body.host.simple .read-group select { padding: 6px 4px 6px 6px; }
}


/* ── 마이크 여러 개(호스트, 오프라인) ─────────────────────────── */
.mic-link { cursor: pointer; }
body.video #micLink { display: none !important; }
.rp-headbtns { display: flex; gap: 6px; }
.mic-row { display: flex; align-items: center; gap: 10px; padding: 8px 4px; border-bottom: 1px solid var(--edge-soft); cursor: pointer; }
.mic-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); }
.mic-label { flex: 1; min-width: 0; font-size: 13px; color: var(--fg-strong); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mic-name { width: 130px; font: inherit; font-size: 12.5px; color: var(--fg-strong); background: rgba(255, 255, 255, .04); border: 1px solid var(--edge); border-radius: 8px; padding: 6px 9px; }
.mic-name:disabled { opacity: .35; }
/* 화자 이름표: 자막 줄 앞. 이름이 둘 이상 보일 때만 붙는다 */
.line .who {
  display: inline-block; margin-right: 8px; padding: 1px 8px; vertical-align: middle;
  font-size: calc(var(--tr-fs) * var(--cap-scale) * 0.42); font-weight: 700; letter-spacing: .02em;
  color: var(--accent); border: 1px solid var(--accent-deep); border-radius: 999px; opacity: .9;
}


/* ── 세션 목록(게스트): 새로 고침·다른 코드 입력 ────────────────── */
/* 심플 모드에서도 시청자의 세션 이름은 보인다 — 목록으로 돌아가는 유일한 손잡이 */
body.simple:not(.host) #roomBadge { display: inline-block !important; }
.board-other { display: flex; gap: 8px; margin-top: 14px; }
.board-other input {
  flex: 1; min-width: 0; font: inherit; font-size: 14px; color: var(--fg-strong);
  background: rgba(255, 255, 255, .04); border: 1px solid var(--edge); border-radius: 10px; padding: 9px 12px;
}
.board-other button {
  font: inherit; font-size: 13px; font-weight: 700; color: #1a1205;
  background: var(--accent); border: 1px solid var(--accent); border-radius: 10px; padding: 9px 16px; cursor: pointer;
}
