/* ==========================================================================
   COC Live AI - Warm Coffeehouse Craft
   Two surfaces, one system: a 1920x1080 host screen read from across the room,
   and a 375-430px phone companion held under the table.

   No frameworks. No CDNs. No webfonts. No remote assets of any kind:
   this must work on a coffee shop's dead WiFi.

   Order of this file is load-bearing (specificity depends on it):
     1  reset, tokens, base, scrollbars, focus
     2  typography primitives
     3  buttons (variants, then :disabled)
     4  form controls
     5  panel, row, pill
     6  shared components (seg, memberrow, aibox, queue, handbtn, voteopt, timers)
     7  .phone scope
     8  .host scope
     9  empty states
     10 keyframes
     11 media queries
     12 .hidden  (last, always)
   ========================================================================== */

/* ==========================================================================
   1. RESET + TOKENS
   ========================================================================== */

*{ box-sizing:border-box; margin:0; }

:root{
  /* ---- surfaces: bean to crema ---- */
  --bg:            #100C09;
  --bg-2:          #16110C;
  --bg-deep:       #0B0806;   /* scroll wells: transcript, queue, aibox interior */
  --panel:         #1B1410;
  --panel2:        #241B15;   /* inset: inputs, secondary buttons, seg rows, queue rows */
  --panel3:        #2E231B;   /* hover / raised */
  --panel-hi:      #372A1F;   /* pressed */

  /* ---- hairlines ---- */
  --line:          #3A2C22;
  --line-soft:     #2A2019;
  --line-strong:   #4E3A2B;
  --sheen:         rgba(255,240,220,.05);   /* 1px inset top highlight, the "glaze" */

  /* ---- ink ---- */
  --text:          #F5EDE2;
  --text-2:        #DCCDBA;
  --muted:         #B39A82;
  --muted-2:       #8A7461;

  /* ---- COPPER: act, now, your turn, attention ---- */
  --accent:        #E0913F;
  --accent-hi:     #F3AE5F;
  --accent-dim:    #A66A27;
  --accent-wash:   #3A2A16;
  --accent-ink:    #1A1006;

  /* ---- SAGE: live, on, good, play ---- */
  --green:         #63C08C;
  --green-hi:      #7ED0A3;
  --green-dim:     #3E9A6B;
  --green-wash:    #16291F;
  --green-ink:     #06180F;

  /* ---- CHILI: stop, over, offline ---- */
  --red:           #E0574B;
  --red-hi:        #F07C6F;
  --red-btn:       #C4453A;
  --red-dim:       #7A2E27;
  --red-wash:      #2E1512;
  --red-ink:       #FFF3F0;

  /* ---- SLATE BLUE: the machine. Nothing else, ever. ---- */
  --ai:            #7FC0EA;
  --ai-hi:         #9FD2F2;
  --ai-bg:         #16202A;
  --ai-bg-2:       #1D2B36;
  --ai-line:       #2E4756;
  --ai-text:       #E6EFF5;
  --ai-glow:       rgba(127,192,234,.22);

  --focus:         #F3AE5F;

  /* ---- type stacks: system only ---- */
  --font-ui:      system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI",
                  Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-display: Georgia, "Iowan Old Style", Charter, "Bitstream Charter",
                  "Sitka Text", Cambria, "Palatino Linotype", "Times New Roman", serif;
  --font-num:     ui-rounded, "SF Pro Rounded", "Segoe UI Variable Display",
                  "Segoe UI", system-ui, -apple-system, Roboto, sans-serif;
  --font-mono:    ui-monospace, "Cascadia Mono", "SF Mono", Consolas,
                  "Liberation Mono", monospace;

  /* ---- type scale ---- */
  --fs-slug:11.5px; --fs-xs:12.5px; --fs-sm:14px;  --fs-base:16px; --fs-md:18px;
  --fs-lg:21px;     --fs-xl:26px;   --fs-2xl:32px; --fs-3xl:46px;  --fs-4xl:52px;
  --fs-timer-phone:84px; --fs-timer-host:180px;

  /* ---- spacing ---- */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:20px; --s6:24px;
  --s7:32px; --s8:40px; --s9:56px; --s10:72px;

  /* ---- radius ---- */
  --r-sm:8px; --r-md:12px; --r-lg:16px; --r-xl:20px; --radius:16px; --r-pill:999px;

  /* ---- elevation: three devices, no more ---- */
  --sh-lift:  0 2px 0 rgba(0,0,0,.35);
  --sh-pop:   0 6px 18px rgba(0,0,0,.45);
  --sh-ember: 0 0 0 1px var(--accent-dim), 0 0 28px -6px rgba(224,145,63,.55);
  --sh-ai:    0 10px 34px -20px var(--ai-glow);

  /* ---- motion ---- */
  --t-fast:110ms; --t-mid:180ms; --t-slow:300ms;
  --ease: cubic-bezier(.2,.7,.3,1);
}

html{ color-scheme: dark; }

body{
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--fs-base);
  line-height: 1.5;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Ambient lamplight: copper from the upper left, a trace of sage lower right.
   This is the only ambient effect in the system. Do not add a second. */
body::before{
  content:""; position:fixed; inset:0; pointer-events:none; z-index:0;
  background:
    radial-gradient(1100px 700px at 18% -10%, rgba(224,145,63,.055), transparent 60%),
    radial-gradient(900px 600px at 100% 110%, rgba(99,192,140,.030), transparent 55%);
}
body > *{ position:relative; z-index:1; }

::selection{ background: var(--accent); color: var(--accent-ink); }

*{ scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
*::-webkit-scrollbar{ width:10px; height:10px; }
*::-webkit-scrollbar-track{ background: transparent; }
*::-webkit-scrollbar-thumb{
  background: var(--line-strong); border-radius: var(--r-pill);
  border: 3px solid transparent; background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover{ background: #61492F; background-clip: content-box; }

:focus-visible{
  outline:3px solid var(--focus); outline-offset:2px; border-radius: var(--r-sm);
}

/* ==========================================================================
   2. TYPOGRAPHY PRIMITIVES
   ========================================================================== */

h1, h2, h3{ font-weight:700; line-height:1.2; }

.muted{ color: var(--muted); }

label.small{
  display:block; margin: var(--s4) 0 var(--s2);
  font-family: var(--font-ui); font-size: var(--fs-slug); font-weight:700;
  text-transform:uppercase; letter-spacing:.12em; color: var(--muted);
}

a{ color: var(--accent); text-underline-offset:3px; }
a:hover{ color: var(--accent-hi); }

/* ==========================================================================
   3. BUTTONS  (variants, then :disabled last so it beats their fills)
   ========================================================================== */

button{
  font-family: var(--font-ui);
  font-size: var(--fs-base); font-weight:600; line-height:1.2;
  border:1px solid var(--line-strong); border-radius: var(--r-md);
  padding:12px 18px; min-height:44px;
  background: var(--panel2); color: var(--text);
  cursor:pointer; white-space:nowrap;
  display:inline-flex; align-items:center; justify-content:center; gap: var(--s2);
  box-shadow: var(--sh-lift), inset 0 1px 0 var(--sheen);
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              transform var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
button:hover{ background: var(--panel3); border-color:#5A4433; }
button:active{ transform: translateY(1px); box-shadow:none; background: var(--panel-hi); }
button:focus-visible{ outline:3px solid var(--focus); outline-offset:2px; }

/* The two-stop, ~10% lightness gradient is what makes copper read as metal
   rather than orange flat fill. Do not increase the delta. */
button.primary{
  background: linear-gradient(180deg, var(--accent-hi), var(--accent));
  color: var(--accent-ink); border-color:#C6772A; font-weight:700;
}
button.primary:hover{
  background: linear-gradient(180deg,#F8BC74,var(--accent-hi)); border-color: var(--accent-hi);
}
button.primary:active{ background: var(--accent-dim); }

button.good{
  background: linear-gradient(180deg, var(--green-hi), var(--green));
  color: var(--green-ink); border-color: var(--green-dim); font-weight:700;
}
button.good:hover{ background: linear-gradient(180deg,#8EDCAF,#6ECB98); }
button.good:active{ background: var(--green-dim); }

button.danger{
  background: linear-gradient(180deg,#D4564A, var(--red-btn));
  color: var(--red-ink); border-color:#9E3229; font-weight:700;
}
button.danger:hover{ background: linear-gradient(180deg,#E4665A,#D0503F); }
button.danger:active{ background: var(--red-dim); }

button:disabled, button[disabled]{
  opacity:.42; cursor:default; transform:none;
  background: var(--panel2); background-image:none;
  border:1px dashed var(--line-soft); color: var(--muted-2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.02);
}
button:disabled:hover{ background: var(--panel2); border-color: var(--line-soft); }

/* ==========================================================================
   4. FORM CONTROLS
   ========================================================================== */

input, select, textarea{
  font-family: var(--font-ui); font-size: var(--fs-base); line-height:1.4;
  background: var(--bg-deep); color: var(--text);
  border:1px solid var(--line); border-radius: var(--r-md);
  padding:12px 14px; width:100%; min-height:46px;
  box-shadow: inset 0 1px 2px rgba(0,0,0,.28);
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease),
              background var(--t-fast) var(--ease);
}
input::placeholder, textarea::placeholder{ color: var(--muted-2); opacity:1; }
input:hover, select:hover, textarea:hover{ border-color: var(--line-strong); }
input:focus, select:focus, textarea:focus{
  outline:none; background: var(--panel2); border-color: var(--accent);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.28), 0 0 0 3px rgba(224,145,63,.24);
}
textarea{ min-height:80px; resize:vertical; line-height:1.5; }
input[type=number]{
  font-family: var(--font-num);
  font-variant-numeric: tabular-nums; font-feature-settings:"tnum" 1;
}
/* Leave the native select chrome alone: the CSS caret trick is fragile
   across platforms and buys nothing here. */
select{ cursor:pointer; }

.memberpick{
  display:flex; flex-wrap:wrap; gap: var(--s2);
  max-height:170px; overflow-y:auto; overscroll-behavior:contain;
}
.memberpick label{
  display:inline-flex; align-items:center; gap:6px;
  background: var(--panel2); border:1px solid var(--line);
  padding:7px 12px; border-radius: var(--r-pill);
  font-size: var(--fs-sm); color: var(--text-2);
  cursor:pointer; user-select:none;
  max-width:200px; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.memberpick label:hover{ background: var(--panel3); border-color: var(--line-strong); }
/* Which speakers are in the round is worth seeing at a glance, so the chip
   highlight is carried by a class host.js toggles on change, with the :has()
   form kept alongside it for anything that sets the checkbox another way. */
.memberpick label.on,
.memberpick label:has(input:checked){
  background: var(--accent-wash); border-color: var(--accent); color: var(--accent);
  font-weight:700;
}
/* width:auto here is load-bearing: the global input{width:100%} would
   otherwise blow the chip apart. */
.memberpick input{
  width:16px; height:16px; min-height:0; flex:0 0 auto;
  margin:0; padding:0; accent-color: var(--accent); box-shadow:none;
}

/* ==========================================================================
   5. PANEL, ROW, PILL
   ========================================================================== */

.panel{
  position:relative;
  background: var(--panel);
  border:1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--s4);
  box-shadow: inset 0 1px 0 var(--sheen);
  overflow-wrap: anywhere;
}

/* Every panel heading looks identical: a quiet label plate, never content.
   This demotion is what lets the timer, the queue and the speaker dominate. */
.panel > h3{
  font-family: var(--font-ui);
  font-size: var(--fs-slug); font-weight:700;
  letter-spacing:.16em; text-transform:uppercase;
  color: var(--muted);
  display:flex; align-items:center; gap: var(--s2);
  margin:0 0 var(--s3);
  padding-bottom: var(--s2);
  border-bottom:1px solid var(--line-soft);
}
.panel > h3::before{
  content:""; flex:0 0 3px; height:12px; border-radius:2px;
  background: var(--line-strong);
}
.panel > h3 .pill{ margin-left:auto; }

.row{ display:flex; gap: var(--s2); align-items:center; flex-wrap:wrap; }
.row > *{ flex:1 1 0; min-width:0; }   /* min-width:0 is load-bearing */
/* Buttons keep nowrap labels, so they get an auto basis: they still grow to
   fill the line, but a row of three long labels wraps instead of clipping. */
.row > button{ flex:1 1 auto; }
.row > .fix{ flex:0 0 auto; }

.panel > .row{ margin-top: var(--s3); }
.panel > .row:first-child, .panel > h3 + .row{ margin-top:0; }

.pill{
  display:inline-flex; align-items:center; gap:6px;
  font-family: var(--font-ui); font-size: var(--fs-xs); font-weight:700;
  letter-spacing:.1em; text-transform:uppercase;
  padding:4px 11px 4px 9px; border-radius: var(--r-pill);
  background: var(--panel3); color: var(--text-2);
  border:1px solid var(--line); white-space:nowrap;
}
.pill::before{
  content:""; width:7px; height:7px; border-radius:50%;
  background: currentColor; flex:0 0 7px;
}
.pill.live  { background: var(--green-wash);  color: var(--green);  border-color:#2C5A42; }
.pill.paused{ background: var(--accent-wash); color: var(--accent); border-color: var(--accent-dim); }
.pill.off   { background: var(--red-wash);    color: var(--red);    border-color:#5C2A24; }
.pill.live::before{ animation: lamp 1.8s var(--ease) infinite; }

#aiBusyPill{ background: var(--ai-bg-2); color: var(--ai); border-color: var(--ai-line); }
#aiBusyPill::before{ animation: lamp 900ms var(--ease) infinite; }

/* labels, not states: no lamp */
#modePill::before, #inboxBox .pill::before{ display:none; }
#modePill, #inboxBox .pill{ padding:4px 10px; }
#connPill{ min-width:112px; justify-content:center; }

/* ==========================================================================
   6. SHARED COMPONENTS
   ========================================================================== */

/* ---- transcript / answer / inbox rows ------------------------------------ */
.seg{
  background: var(--panel2);
  border:1px solid var(--line-soft); border-radius: var(--r-sm);
  box-shadow: inset 3px 0 0 var(--line-strong);
  padding:10px 14px;
  font-family: var(--font-ui); font-size: var(--fs-md); line-height:1.5;
  color: var(--text-2);
  overflow-wrap:anywhere;
}
.seg .who{
  color: var(--accent); font-weight:700; margin-right: var(--s2);
  white-space:nowrap; max-width:30ch; overflow:hidden; text-overflow:ellipsis;
  display:inline-block; vertical-align:bottom;
}
.seg .txt{ color: var(--text-2); overflow-wrap:anywhere; }

/* ---- member rows --------------------------------------------------------- */
.memberrow{
  display:flex; justify-content:space-between; align-items:center; gap: var(--s3);
  padding:9px 0; border-bottom:1px solid var(--line-soft);
  font-size: var(--fs-base);
}
.memberrow:last-child{ border-bottom:0; }
.memberrow > span:first-child{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.memberrow > span.muted{
  flex:0 0 auto; font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums; font-feature-settings:"tnum" 1;
}

/* ---- the machine speaks -------------------------------------------------- */
.aibox{
  background: linear-gradient(180deg, var(--ai-bg-2) 0%, var(--ai-bg) 90px);
  color: var(--ai-text);
  border:1px solid var(--ai-line);
  border-left:4px solid var(--ai);
  border-radius: var(--radius);
  padding: var(--s4);
  font-family: var(--font-display);
  font-size: var(--fs-base); line-height:1.55;
  max-height:340px; overflow-y:auto; overscroll-behavior:contain;
  overflow-wrap:anywhere; text-wrap:pretty; hyphens:auto;
  position:relative;
  box-shadow: var(--sh-ai), inset 0 1px 0 rgba(190,220,240,.06);
  scrollbar-color: var(--ai-line) transparent;
  mask-image: linear-gradient(180deg,#000 calc(100% - 28px), transparent);
  -webkit-mask-image: linear-gradient(180deg,#000 calc(100% - 28px), transparent);
}
/* sticky kind label: on a 900-character recap the operator still sees "RECAP" */
.aibox .kind{
  position:sticky; top:0; z-index:1;
  margin: calc(var(--s4) * -1) calc(var(--s4) * -1) var(--s3);
  padding: var(--s2) var(--s4);
  background: var(--ai-bg-2);
  border-bottom:1px solid var(--ai-line);
  font-family: var(--font-ui); font-size: var(--fs-slug); font-weight:700;
  text-transform:uppercase; letter-spacing:.16em; color: var(--ai);
  display:flex; align-items:center; gap: var(--s2);
}
.aibox .kind::before{ content:"\25D7"; color: var(--ai-hi); font-size:12px; line-height:1; }
.aibox .muted{ color:#7A94A6; }
.aibox > div:last-child{ animation: fade-up var(--t-slow) var(--ease) both; }

/* ---- raised-hand queue --------------------------------------------------- */
.queueitem{
  display:flex; align-items:center; gap: var(--s4);
  background: var(--panel2);
  border:1px solid var(--line-soft); border-radius: var(--r-md);
  padding:10px 14px; margin-bottom:0;      /* containers use gap */
  font-size: var(--fs-2xl);
  box-shadow: inset 3px 0 0 var(--line-strong), inset 0 1px 0 var(--sheen);
  transition: background var(--t-mid) var(--ease), border-color var(--t-mid) var(--ease);
  min-width:0;
}
.qnum{
  flex:0 0 44px; height:44px; border-radius:50%;
  background: var(--panel); border:1px solid var(--line-strong);
  color: var(--muted);
  font-family: var(--font-num); font-weight:800; font-size:20px;
  font-variant-numeric: tabular-nums; font-feature-settings:"tnum" 1;
  display:flex; align-items:center; justify-content:center;
}
/* min-width:0 is MANDATORY: flex children default to min-width:auto and will
   refuse to shrink, pushing .qwait off the row. */
.qname{
  flex:1 1 auto; min-width:0;
  font-family: var(--font-ui); font-weight:800; letter-spacing:-.01em;
  color: var(--text-2);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.qwait{
  flex:0 0 auto; font-size: var(--fs-xs); font-weight:600; letter-spacing:.05em;
  color: var(--muted-2);
  font-variant-numeric: tabular-nums; font-feature-settings:"tnum" 1;
}

.queueitem.first{
  background: linear-gradient(180deg,#42301A 0%, var(--accent-wash) 100%);
  border-color: var(--accent);
  font-size: var(--fs-3xl);
  padding:14px 16px;
  box-shadow: var(--sh-ember), inset 3px 0 0 var(--accent),
              inset 0 1px 0 rgba(255,225,190,.10);
  animation: ember 3.2s ease-in-out infinite;
}
.queueitem.first .qnum{
  background: linear-gradient(180deg, var(--accent-hi), var(--accent));
  color: var(--accent-ink); border-color:#C6772A;
  flex:0 0 56px; height:56px; font-size:26px;
}
.queueitem.first .qname{ color:#FFF1DE; }
.queueitem.first .qwait{ color: var(--accent); font-size: var(--fs-sm); }

/* ---- my place in line ---------------------------------------------------- */
.queuepos{
  text-align:center; font-family: var(--font-ui);
  font-size: var(--fs-md); font-weight:800;
  padding: var(--s4); border-radius: var(--r-md); margin-bottom: var(--s3);
  background: var(--panel2); border:1px solid var(--accent-dim);
  color: var(--accent);
  transition: background var(--t-mid) var(--ease), color var(--t-mid) var(--ease);
}
.queuepos.next{
  font-size:24px; font-weight:800;
  padding: var(--s5);
  /* outlined, not filled: the filled copper look is reserved for the actual
     tap target (the hand button right below this banner) */
  background: var(--panel2);
  color: var(--accent-hi, #F2A95E);
  border:2px solid var(--accent);
  box-shadow:none;
  animation: ember-border 2.4s ease-in-out infinite;
}
@keyframes ember-border{
  0%,100%{ border-color: var(--accent); }
  50%{ border-color: var(--accent-hi, #F2A95E); }
}
/* the roundtable-order variant is informational: quieter than the hand banner */
.queuepos.sub{
  font-size: var(--fs-md); font-weight:700;
  padding: var(--s3);
  margin-bottom:0;
}

/* ---- raise hand: the biggest tap target in the app ----------------------- */
.handbtn{
  position:relative; overflow:hidden;
  width:100%; min-height:72px;
  font-size: var(--fs-md); font-weight:800; letter-spacing:-.01em;
  border-radius: var(--r-lg);
}
.handbtn:not(.primary){
  background: linear-gradient(180deg, var(--panel3), var(--panel2));
  border:1px solid var(--line-strong); color: var(--text);
}
.handbtn:not(.primary)::after{
  content:""; position:absolute; inset:0; border-radius:inherit; pointer-events:none;
  box-shadow: inset 0 -24px 32px -28px var(--accent);
}
.handbtn:active{ transform: scale(.98); }

/* ---- vote options (AFTER button so :disabled here wins) ------------------ */
.voteopt{
  width:100%; margin-top: var(--s2);
  min-height:56px; padding:16px 18px;
  text-align:left; justify-content:flex-start;
  font-size: var(--fs-md); font-weight:600;
  white-space:normal; line-height:1.35;
  background: var(--panel2); border:1px solid var(--line-strong);
  display:flex; align-items:center; gap: var(--s3);
}
.voteopt::before{
  content:""; flex:0 0 20px; height:20px; border-radius:50%;
  border:2px solid var(--line-strong); background:transparent;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.voteopt:hover:not(:disabled){ border-color: var(--accent); background: var(--panel3); }
.voteopt.chosen{
  outline:none;
  background: var(--accent-wash); border-color: var(--accent); color:#FFF1DE;
  box-shadow: inset 0 1px 0 var(--sheen), 0 0 0 1px var(--accent);
}
.voteopt.chosen::before{
  border-color: var(--accent); background: var(--accent);
  box-shadow: inset 0 0 0 4px var(--accent-wash);   /* donut = filled radio */
}
/* A closed vote is a results readout, not a broken control. opacity:1 is
   deliberate: the tally "(3)" is appended to the label and must stay readable. */
.voteopt:disabled{
  opacity:1; cursor:default; transform:none;
  background: var(--panel2); background-image:none;
  border:1px solid var(--line-soft); border-style:solid;
  color: var(--text-2);
  box-shadow: var(--sh-lift), inset 0 1px 0 var(--sheen);
}
.voteopt:disabled::before{ opacity:.35; }
.voteopt:disabled.chosen{ color: var(--accent); border-color: var(--accent-dim); }

/* ---- countdowns ---------------------------------------------------------- */
.hosttimer, .bigtimer{
  font-family: var(--font-num); font-weight:700;
  font-variant-numeric: tabular-nums; font-feature-settings:"tnum" 1;
  text-align:center;
  color: var(--text);
  transition: color var(--t-mid) var(--ease), text-shadow var(--t-mid) var(--ease);
}
.hosttimer{
  font-size: var(--fs-timer-host); line-height:.92; letter-spacing:-.03em;
  padding: var(--s3) 0 var(--s2); margin:0;
  text-shadow:0 0 60px rgba(245,237,226,.08);
}
.bigtimer{
  font-size: var(--fs-timer-phone); line-height:1; letter-spacing:-.02em;
  padding: var(--s2) 0;
}
.hosttimer.warn, .bigtimer.warn{
  color: var(--accent);
  text-shadow:0 0 44px rgba(224,145,63,.35);
  animation: tick-warn 1s steps(1,end) infinite;
}
.hosttimer.over, .bigtimer.over{
  color: var(--red);
  text-shadow:0 0 52px rgba(224,87,75,.42);
  animation: over-pulse 1.2s ease-in-out infinite;
}

/* ==========================================================================
   7. PHONE  (375 - 430px)
   ========================================================================== */

.phone{
  max-width:460px; margin:0 auto; width:100%;
  padding: var(--s4);
  padding-top: calc(var(--s4) + env(safe-area-inset-top, 0px));
  padding-bottom: calc(var(--s10) + env(safe-area-inset-bottom, 0px));
  display:flex; flex-direction:column; gap: var(--s4);
}
.phone header{
  position:sticky; top:0; z-index:20;
  display:flex; justify-content:space-between; align-items:center; gap: var(--s3);
  margin: calc(var(--s4) * -1) calc(var(--s4) * -1) 0;
  padding: var(--s3) var(--s4);
  background: var(--bg);
  background: linear-gradient(180deg, var(--bg) 78%, rgba(16,12,9,0));
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-bottom:1px solid var(--line-soft);
}
#groupName{
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight:700;
  line-height:1.2; letter-spacing:-.005em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.phone .panel{ padding: var(--s4); }
.phone button, .phone input, .phone select, .phone textarea{ min-height:48px; }
.phone input, .phone select, .phone textarea{ font-size:16px; }  /* stops iOS focus zoom */
.phone .panel > h3{ margin-bottom: var(--s3); }
/* 48px is the floor for ordinary controls, but these two are the whole point
   of the screen and must beat it on specificity, not just declaration order. */
.phone .handbtn{ min-height:72px; }
.phone .voteopt{ min-height:56px; }

/* The phone's rail: only the offline case is worth announcing. "Connected" is
   the expected state and does not need a banner. Attribute driven for the same
   reason as the host rail; app.js sets it inside setPill(). */
body[data-conn="off"]::after{
  content:""; position:fixed; inset:0 0 auto 0; height:3px; z-index:40;
  background: var(--red); pointer-events:none;
}

/* ---- join screen --------------------------------------------------------- */
#joinView{
  margin-top:6vh; padding: var(--s6) var(--s5) var(--s5);
  border-color: var(--line-strong);
  box-shadow: var(--sh-pop), inset 0 1px 0 var(--sheen);
}
#joinView h3{
  display:block;
  font-family: var(--font-display); font-size:28px; font-weight:700;
  text-transform:none; letter-spacing:-.01em; color: var(--text);
  border-bottom:0; padding-bottom:0; margin-bottom: var(--s2);
}
#joinView h3::before{ display:none; }
#joinView h3::after{
  content:"First name only. The invite code is on the big screen.";
  display:block; margin-top: var(--s2);
  font: 400 var(--fs-sm)/1.45 var(--font-ui);
  letter-spacing:0; text-transform:none; color: var(--muted);
}
#codeInput{
  font-family: var(--font-mono); font-size:20px;
  letter-spacing:.2em; text-transform:uppercase; text-align:center;
}
#joinBtn{ width:100%; margin-top: var(--s4); min-height:56px; font-size: var(--fs-md); font-weight:800; }

/* ---- main shell ---------------------------------------------------------- */
#mainView{ display:flex; flex-direction:column; gap: var(--s4); }
/* Information order: live activity first. #statusPanel stays on top, your
   turn timer beats everything, then whichever vote/game is open, THEN the
   hand-raise block. Panels keep their DOM order otherwise. */
#mainView > #statusPanel{ order:0; }
#mainView > #turnPanel{ order:1; }
#mainView > #rtPos{ order:2; }
#mainView > #votePanel, #mainView > #roundPanel, #mainView > #mapPanel{ order:3; }
#mainView > #handPanel{ order:4; }
#mainView > #aiPanel{ order:5; }
#mainView > #suggestPanel{ order:6; }
#mainView > .panel:last-child{ order:7; }  /* members */
#mapOptions{ margin-top:8px; }
#mapResult{ margin-top:10px; font-weight:700; }
#mapScore{ margin-top:4px; }


#meName{ font-family: var(--font-display); font-size:18px; font-weight:700; }
#topicLine{
  font-size: var(--fs-sm); color: var(--muted);
  overflow-wrap:anywhere; text-wrap:balance; margin-top: var(--s2);
}
#statusPanel .linkrow{ margin-top: var(--s2); }
#renameLink, #signoutLink{
  font-size: var(--fs-sm); display:inline-block; padding:12px 0;  /* 45px hit area */
  text-underline-offset:3px;
}
#signoutLink{ color: var(--muted); }
#toastLine{ font-size: var(--fs-sm); min-height:1.4em; margin-top: var(--s2); }
/* Fixed to the viewport: the ack must be visible however far you scrolled. */
#toastLine:not(:empty){
  position:fixed; left:12px; right:12px;
  bottom:calc(12px + env(safe-area-inset-bottom));
  z-index:50;
  color: var(--green); background: var(--green-wash);
  border-radius: var(--r-sm); padding:6px 10px;
}

/* ---- A. your turn -------------------------------------------------------- */
#turnPanel{
  text-align:center; padding: var(--s5) var(--s4);
  animation: panel-in var(--t-slow) var(--ease) both;
}
.phone #turnWho{
  font-family: var(--font-display); font-size:19px; color: var(--muted);
  letter-spacing:.01em; margin-bottom: var(--s2);
}
#turnPanel.mine{
  background: linear-gradient(180deg, var(--accent-wash), var(--panel));
  border-color: var(--accent);
  box-shadow: var(--sh-ember), inset 0 1px 0 var(--sheen);
  animation: panel-in var(--t-slow) var(--ease) both,
             ember 2.6s ease-in-out var(--t-slow) infinite;
}
.phone #turnPanel.mine #turnWho{
  color: var(--accent-hi); font-size:23px; font-weight:700;
  letter-spacing:.05em; text-transform:uppercase;
}
#turnPanel.mine .bigtimer{ font-size:92px; color: var(--text); }
#turnPanel:not(.mine) .bigtimer{ font-size:64px; color: var(--text-2); }
#turnPanel.mine .bigtimer.warn, #turnPanel:not(.mine) .bigtimer.warn{ color: var(--accent); }
#turnPanel.mine .bigtimer.over, #turnPanel:not(.mine) .bigtimer.over{ color: var(--red); }

/* ---- B. hand + queue ----------------------------------------------------- */
#queueList{
  display:flex; flex-direction:column; gap: var(--s2);
  margin-top: var(--s3);
}
.phone .queueitem{ font-size: var(--fs-base); padding:10px 12px; gap: var(--s3); }
.phone .queueitem.first{ font-size: var(--fs-md); animation:none; }
.phone .qnum{ flex:0 0 32px; height:32px; font-size:15px; }
.phone .queueitem.first .qnum{ flex:0 0 38px; height:38px; font-size:18px; }
.phone .queueitem.first .qwait{ font-size: var(--fs-xs); }
.phone #queueList .queueitem:nth-child(n+6) .qwait{ display:none; }

/* ---- C. vote ------------------------------------------------------------- */
#votePanel{
  border-left:3px solid var(--accent);
  animation: panel-in var(--t-slow) var(--ease) both;
}
#voteQuestion{
  display:block;
  font-family: var(--font-display); font-size:23px; line-height:1.3; font-weight:700;
  color: var(--text); text-wrap:balance; overflow-wrap:anywhere;
  text-transform:none; letter-spacing:0;
  border-bottom:0; padding-bottom:0; margin-bottom: var(--s3);
}
#voteQuestion::before{
  content:"VOTE"; display:block; margin-bottom: var(--s2);
  font: 700 var(--fs-slug)/1 var(--font-ui);
  letter-spacing:.16em; color: var(--accent);
  flex:none; height:auto; width:auto; background:none; border-radius:0;
}
#voteStatus{ font-size: var(--fs-sm); min-height:1.4em; margin-top: var(--s3); }

/* ---- D. game round ------------------------------------------------------- */
#roundPanel{
  border-left:3px solid var(--green);
  animation: panel-in var(--t-slow) var(--ease) both;
}
#roundQuestion{
  display:block;
  font-family: var(--font-display); font-size:23px; line-height:1.3; font-weight:700;
  color: var(--text); text-wrap:balance; overflow-wrap:anywhere;
  text-transform:none; letter-spacing:0;
  border-bottom:0; padding-bottom:0; margin-bottom: var(--s2);
}
#roundQuestion::before{
  content:"GAME ROUND"; display:block; margin-bottom: var(--s2);
  font: 700 var(--fs-slug)/1 var(--font-ui);
  letter-spacing:.16em; color: var(--green);
  flex:none; height:auto; width:auto; background:none; border-radius:0;
}
#roundAskedBy{
  font-size: var(--fs-xs); text-transform:uppercase;
  letter-spacing:.08em; color: var(--muted-2); margin-bottom: var(--s3);
}
#answerInput{ min-height:88px; resize:vertical; line-height:1.45; }
#answerBtn{ width:100%; margin-top: var(--s2); }
#answerStatus{ font-size: var(--fs-sm); color: var(--green); min-height:1.4em; margin-top: var(--s2); }
#roundReveal{ display:flex; flex-direction:column; gap: var(--s2); }
#roundReveal:not(:empty){ margin-top: var(--s3); }
#roundReveal .seg{
  background: var(--green-wash); border-left:3px solid var(--green-dim);
  box-shadow:none; font-size: var(--fs-base);
}
#roundReveal .seg .who{ color: var(--green); }

/* ---- E. the AI spoke ----------------------------------------------------- */
#aiPanel{
  font-size: var(--fs-base); max-height:260px;
  box-shadow: var(--sh-pop);
  animation: fade-up var(--t-slow) var(--ease) both;
}

/* ---- suggest ------------------------------------------------------------- */
#suggestQ, #suggestOpts{ margin-top: var(--s2); }
#suggestBtn{ width:100%; margin-top: var(--s3); }
#suggestStatus{ font-size: var(--fs-sm); min-height:1.4em; margin-top: var(--s2); }

/* ---- errors -------------------------------------------------------------- */
#pinError, #joinError{
  color: var(--red); font-size: var(--fs-sm); font-weight:600;
  min-height:1.4em; margin-top: var(--s2);
}
#joinError:not(:empty), #pinError:not(:empty){
  background: var(--red-wash); border-radius: var(--r-sm); padding:8px 10px;
}

/* ---- host PIN gate (reuses .phone) --------------------------------------- */
#pinView{ max-width:420px; margin:12vh auto 0; }
#pinView .panel{ padding: var(--s6); }
#pinView h2{ font-family: var(--font-display); font-size:26px; margin-bottom: var(--s3); }
#pinInput{
  font-family: var(--font-mono); font-size:26px;
  letter-spacing:.35em; text-align:center;
}
#pinBtn{ width:100%; margin-top: var(--s4); min-height:52px; font-weight:800; }

/* ==========================================================================
   8. HOST  (1920 x 1080 target, usable from 1280 up)
   ========================================================================== */

.host{
  display:grid;
  grid-template-columns: 360px minmax(0,1fr) 460px;
  gap: var(--s3);
  padding: var(--s4) var(--s3) var(--s3);   /* 16px top clears the tally rail */
  height:100vh;
  overflow:hidden;                          /* the page never scrolls; columns do */
  background: linear-gradient(180deg, var(--bg-2) 0%, var(--bg) 340px) fixed;
}
@supports (height:100dvh){ .host{ height:100dvh; } }

.host .col{
  display:flex; flex-direction:column; gap: var(--s3);
  min-height:0;                             /* REQUIRED or inner overflow never engages */
  overflow-y:auto; overflow-x:hidden;
  overscroll-behavior:contain;
  padding-right:2px;
}
/* the middle column must not scroll as a whole; only #transcript does */
.host .col:nth-child(2){ overflow-y:auto; }  /* budgeted to never engage; safety net, not a feature */

/* ---- tally rail: is the mic hot, from anywhere in the room ---------------
   Driven by data-rail, which host.js mirrors from the same state that already
   sets #listenPill and #aiBusyPill. The elegant version of this is
   `.host:has(#listenPill.live)::before`, but that stakes the single most
   glanceable element on the screen on :has() support plus correct
   pseudo-element invalidation. One attribute assignment is deterministic
   everywhere, adds no DOM, and cannot silently strand the rail on the wrong
   colour. :has() is still used below where it is only an enhancement. */
.host::before{
  content:""; position:fixed; inset:0 0 auto 0; height:4px; z-index:50;
  background: var(--line);
  transition: background var(--t-slow) var(--ease), box-shadow var(--t-slow) var(--ease);
}
.host[data-rail="live"]::before  { background: var(--green); box-shadow:0 0 18px -2px var(--green); }
.host[data-rail="paused"]::before{ background: var(--accent); }
.host[data-rail="off"]::before   { background: var(--red-dim); }
/* the machine outranks everything: if the AI is thinking, the rail is blue */
.host[data-rail="ai"]::before{ background: var(--ai); box-shadow:0 0 18px -2px var(--ai); }

/* the copper tick marks the two room-facing columns */
.host .col:nth-child(2) .panel > h3::before,
.host .col:nth-child(3) > .panel:first-child > h3::before{ background: var(--accent); }

.host .pill{ font-size: var(--fs-sm); padding:5px 14px; }
.host .memberrow{ font-size: var(--fs-md); padding:11px 0; }

/* room-facing controls are bigger than the operator rack */
.host .col:nth-child(n+2) button{ font-size: var(--fs-md); padding:14px 20px; min-height:52px; }

/* -------------------------------------------------------------------------
   Left column, 360px: the operator's rack. Read at 60cm, deliberately
   recessive. Nothing here may exceed 20px except #inviteCode.
   ------------------------------------------------------------------------- */
.host .col:first-child{ font-size: var(--fs-sm); }
.host .col:first-child button{ font-size: var(--fs-base); min-height:44px; padding:10px 14px; }
.host .panel .row + .row{ margin-top: var(--s2); }

#qr img{
  width:100%; aspect-ratio:1; object-fit:contain; display:block;
  background:#F7F1E8;                 /* cream, not pure white: still scans, warmer */
  padding:12px; border-radius: var(--r-md);
  image-rendering: pixelated;         /* an anti-aliased QR is a QR phones fail to read */
  box-shadow:0 0 0 1px var(--line);
  min-height:300px;
}
#qrImg:not([src]){ background: var(--panel2); border:1px dashed var(--line); }
#joinUrl{
  font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--muted-2);
  text-align:center; word-break:break-all; margin-top: var(--s2);
}
#inviteCode{
  font-family: var(--font-mono); font-size:26px; font-weight:700;
  letter-spacing:.18em; color: var(--accent);
  background: var(--accent-wash);
  border:1px dashed var(--accent-dim); border-radius: var(--r-sm);
  padding:4px 10px;
}
#inviteCode:empty{ display:none; }   /* no empty ticket stub before config loads */
#rotateCode{ flex:0 0 auto; margin-left:auto; }

#sttInfo{
  font-size: var(--fs-xs); color: var(--muted-2); line-height:1.5;
  border-top:1px solid var(--line-soft); padding-top: var(--s3); margin-top: var(--s3);
  min-height:1.2em;
}

#rtSeconds{ max-width:120px; }        /* a 3-digit field must not span the column */
#turnStart{ flex:1.5 1 auto; font-weight:700; }
#roundClear{ color: var(--muted); }
#voteOpts{ margin-top: var(--s2); }

/* -------------------------------------------------------------------------
   Middle column, 1052px at 1920: the room
   ------------------------------------------------------------------------- */

/* 1. THE STAGE: #turnWho + #hostTimer + #rtProgress. Fixed, never squeezed. */
.host .col:nth-child(2) > .panel:first-child,
#stagePanel{
  flex:0 0 auto; min-height:376px;
  display:flex; flex-direction:column; justify-content:center;
  padding: var(--s6) var(--s6) var(--s5);
  background: radial-gradient(120% 140% at 50% -30%, #241A12 0%, var(--panel) 62%);
  border-color: var(--line-strong);
}
/* #turnWho carries class="muted" in the markup and the JS never removes it.
   The ID selector outranks .muted, so this wins. Do not build state on .muted. */
.host #turnWho{
  font-family: var(--font-display);
  font-size: var(--fs-4xl); font-weight:700; line-height:1.1;
  color: var(--text);
  text-align:center; text-wrap:balance; overflow-wrap:anywhere;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  margin-bottom: var(--s2);
}
#rtProgress{
  font-size: var(--fs-sm); color: var(--muted); text-align:center; line-height:1.6;
  max-width:820px; margin: var(--s2) auto 0;
  border-top:1px solid var(--line-soft); padding-top: var(--s3);
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;
  overflow-wrap:anywhere; min-height:1.6em;
}

/* 2. ROUND BOARD: grows to content, caps, then scrolls */
#roundBoard, #voteBoard{ flex:0 1 auto; min-height:110px; max-height:300px; overflow-y:auto; overscroll-behavior:contain; }
#roundBoardQ, #voteBoardQ{
  display:block;
  font-size: var(--fs-xl); font-weight:700; letter-spacing:0;
  text-transform:none; color: var(--text);
  border-bottom:2px solid var(--accent-dim); padding-bottom: var(--s2);
  margin-bottom: var(--s3);
  overflow-wrap:anywhere;
}
#roundBoardQ::before, #voteBoardQ::before{ display:none; }
#roundBoardStatus, #voteBoardStatus{ font-size: var(--fs-md); color: var(--muted); margin-bottom: var(--s3); }
#roundBoardAnswers{ display:grid; grid-template-columns:1fr 1fr; gap: var(--s2); }
#roundBoardAnswers .seg{
  font-size:20px; padding:12px 16px;
  background: var(--green-wash); border-left:3px solid var(--green-dim);
  box-shadow:none;
}
#roundBoardAnswers .seg .who{ color: var(--green); }

/* vote board rows: option label at seg scale, proportional tally bar, count */
#voteBoardOpts{ display:flex; flex-direction:column; gap: var(--s2); }
#voteBoardOpts .voterow{
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.2fr) auto;
  align-items:center; gap: var(--s3);
  font-size:20px; padding:12px 16px;
  background: var(--panel2); border-left:3px solid var(--line-strong);
  border-radius: var(--r-sm);
}
#voteBoardOpts .voterow .vopt{ font-weight:600; overflow-wrap:anywhere; }
#voteBoardOpts .voterow .vbar{ height:10px; border-radius:999px; background: var(--bg-deep); overflow:hidden; }
#voteBoardOpts .voterow .vfill{
  height:100%; border-radius:inherit; background: var(--accent);
  transition: width var(--t-mid) var(--ease);
}
#voteBoardOpts .voterow .vcount{
  font-family: var(--font-num); font-weight:700;
  font-variant-numeric: tabular-nums; min-width:2ch; text-align:right;
}
#voteBoardOpts .voterow.winner{ background: var(--green-wash); border-left-color: var(--green); }
#voteBoardOpts .voterow.winner .vfill{ background: var(--green); }

/* 2b. AI PANEL: shrinks before the transcript does. When a turn, a board and
   long AI text all fight for the column, the AI text area compresses and
   scrolls internally; the input rows and the transcript stay usable. */
#aiPanelHost{ flex:0 1 auto; min-height:0; display:flex; flex-direction:column; }
#aiPanelHost .aibox{ flex:0 1 auto; min-height:56px; overflow-y:auto; }
#aiPanelHost .row{ flex:0 0 auto; }

/* 3. TRANSCRIPT: takes the rest of the column */
.host .col:nth-child(2) > .panel:last-child,
#transcriptPanel{
  flex:1 1 auto; min-height:150px; display:flex; flex-direction:column;
}
#transcript{
  flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain;
  display:flex; flex-direction:column; gap: var(--s2);
  background: var(--bg-deep);
  border:1px solid var(--line-soft); border-radius: var(--r-md);
  padding: var(--s3);
  scroll-behavior:smooth;
  mask-image: linear-gradient(180deg, transparent 0, #000 18px);
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 18px);
}
/* only the transcript animates on append; it is append-only */
#transcript .seg{ flex:0 0 auto; animation: seg-in 260ms var(--ease) both; }
#transcript .seg:last-child{
  background: var(--panel3); color: var(--text);
  box-shadow: inset 3px 0 0 var(--accent);
}
/* everything else that reuses .seg is a full rebuild: it must not animate */
#roundBoardAnswers .seg, #roundReveal .seg, #inboxBox .seg{ animation:none; }

/* -------------------------------------------------------------------------
   Right column, 460px: the queue and the voice
   ------------------------------------------------------------------------- */
.host .col:nth-child(3) > .panel:first-child{
  flex:1 1 auto; min-height:230px; display:flex; flex-direction:column;
  border-color: var(--accent-dim);
  background: linear-gradient(180deg, #221913 0%, var(--panel) 120px);
}
#queueBox{
  display:flex; flex-direction:column; gap: var(--s2);
  flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain;
  padding-right:4px;
  mask-image: linear-gradient(180deg,#000 calc(100% - 22px), transparent);
  -webkit-mask-image: linear-gradient(180deg,#000 calc(100% - 22px), transparent);
}
#queueBox .queueitem{ flex:0 0 auto; }
#callNext{ margin-top: var(--s3); width:100%; min-height:56px; font-size:20px; font-weight:700; }

/* density tiering for a long queue: .first NEVER shrinks */
.host #queueBox .queueitem:nth-child(n+7){ padding:6px 14px; font-size: var(--fs-xl); }
.host #queueBox .queueitem:nth-child(n+7) .qnum{ flex:0 0 34px; height:34px; font-size:16px; }
.host #queueBox .queueitem:nth-child(n+7) .qwait{ display:none; }
.host #queueBox:has(.queueitem:nth-child(11)) .queueitem:not(.first){ font-size: var(--fs-md); padding:5px 12px; }
.host #queueBox:has(.queueitem:nth-child(11)) .queueitem:not(.first) .qnum{ flex:0 0 30px; height:30px; font-size:14px; }

/* AI panel: hierarchy rank 6, must be readable from the couch.
   max-height is load-bearing: the right column scrolls, so an uncapped AI
   panel would push the queue off screen. */
#aiBox{ font-size: var(--fs-xl); line-height:1.45; max-height:400px; padding: var(--s5); }
#aiBox .kind{ margin: calc(var(--s5) * -1) calc(var(--s5) * -1) var(--s4); padding: var(--s2) var(--s5); }
#askInput{ font-size: var(--fs-base); }

/* An always-on red slab beside the AI text is noise. An outlined one is a
   labelled kill switch you can find without it shouting. */
#stopTtsBtn{
  background:transparent; background-image:none;
  color: var(--red); border:1px solid var(--red-dim); font-weight:700;
  box-shadow:none;
}
#stopTtsBtn:hover{ background: var(--red-wash); border-color: var(--red); }

/* inbox: host.js sets inline marginBottom:6px per item, so no container gap */
#inboxBox{
  max-height:300px; overflow-y:auto; overscroll-behavior:contain;
  font-size: var(--fs-sm); color: var(--muted-2);
}
#inboxBox .seg{
  font-size: var(--fs-base);
  box-shadow: inset 3px 0 0 var(--accent-dim);
}
#inboxBox .seg .who{ color: var(--text); }
#inboxBox .row button{ min-height:36px; font-size: var(--fs-sm); padding:8px 14px; }

#memberBox{ max-height:320px; overflow-y:auto; overscroll-behavior:contain; }
#saveBtn{ width:100%; margin-top: var(--s3); }
#toast{ font-size: var(--fs-xs); color: var(--muted); min-height:1.4em; margin-top: var(--s2); }
#toast:not(:empty){
  color: var(--green); background: var(--green-wash);
  border:1px solid #2C5A42; border-radius: var(--r-sm);
  padding:6px 10px;
}

/* ==========================================================================
   9. EMPTY STATES
   ========================================================================== */

.qempty,
#transcript:empty::before,
#memberBox:empty::before, #memberList:empty::before,
#roundBoardAnswers:empty::before{
  display:block; text-align:center;
  color: var(--muted-2); font-family: var(--font-display); font-style:italic;
  font-size: var(--fs-base); line-height:1.6;
  padding: var(--s5) var(--s4);
  border:1px dashed var(--line); border-radius: var(--r-md);
}
.qempty{
  display:flex; align-items:center; justify-content:center; gap: var(--s3);
  min-height:96px;
}
.qempty::before{ content:"\270B"; font-size:26px; opacity:.32; font-style:normal; }
.host .qempty{ font-size: var(--fs-md); }
.phone .qempty{ font-size: var(--fs-sm); min-height:64px; padding: var(--s4); }

#transcript:empty::before{
  content:"Nothing heard yet. Press Start listening.";
  margin:auto; max-width:34ch; font-size:20px; border:0;
}
#memberBox:empty::before{ content:"Nobody has joined yet. Point a phone at the QR code."; }
#memberList:empty::before{ content:"Just you at the table so far."; }
#roundBoardAnswers:empty::before{ content:"Answers stay hidden until you press Reveal."; grid-column:1 / -1; }
.memberpick:empty::before{
  content:"Members appear here once they join.";
  color: var(--muted-2); font-size: var(--fs-sm); font-style:italic;
}
/* inbox writes bare text with no child nodes, so :empty never matches */
#inboxBox:not(:has(.seg)){
  display:flex; align-items:center; min-height:72px;
  padding: var(--s4); border:1px dashed var(--line-soft); border-radius: var(--r-md);
  font-family: var(--font-display); font-style:italic;
}
#inboxBox .seg{ font-family: var(--font-ui); font-style:normal; color: var(--text-2); }

/* ==========================================================================
   10. KEYFRAMES  (seven, each carries information)
   ==========================================================================
   Restart rule: ember's 0% and 100% frames are identical, because
   .queueitem.first is a brand new element on every queue rebuild and its
   animation restarts at 0%. Never give a sustained animation to a re-created
   element unless its first and last frames match. */

@keyframes lamp      { 0%,100%{ opacity:1 }   50%{ opacity:.3 } }
@keyframes tick-warn { 0%,49%{ opacity:1 }    50%,100%{ opacity:.82 } }
@keyframes over-pulse{ 0%,100%{ color:var(--red); transform:scale(1) }
                       50%    { color:var(--red-hi); transform:scale(1.015) } }
@keyframes ember     { 0%,100%{ box-shadow:0 0 0 1px var(--accent-dim), 0 0 22px -8px rgba(224,145,63,.45) }
                       50%    { box-shadow:0 0 0 1px var(--accent),     0 0 40px -4px rgba(224,145,63,.75) } }
@keyframes seg-in    { from{ opacity:0; transform:translateY(6px) }  to{ opacity:1; transform:none } }
@keyframes fade-up   { from{ opacity:0; transform:translateY(8px) }  to{ opacity:1; transform:none } }
@keyframes panel-in  { from{ opacity:0; transform:translateY(10px) } to{ opacity:1; transform:none } }

/* ==========================================================================
   11. MEDIA QUERIES
   ========================================================================== */

@media (max-width:1599px){
  .host{ grid-template-columns: 320px minmax(0,1fr) 400px; }
  .host{ --fs-timer-host:132px; --fs-4xl:38px; --fs-3xl:34px; --fs-2xl:24px; }
  .host #queueBox{ max-height:380px; }
  #aiBox{ font-size: var(--fs-lg); max-height:320px; }
}

@media (max-width:1280px){
  .host{ grid-template-columns: 300px minmax(0,1fr) 360px; --fs-timer-host:104px; }
  .host #stagePanel{ min-height:300px; }
}

@media (max-width:1100px){
  .host{ grid-template-columns:1fr; height:auto; overflow:visible; --fs-timer-host:88px; }
  .host .col, .host .col:nth-child(2){ overflow:visible; height:auto; }
  .host #stagePanel{ min-height:0; }
  #roundBoardAnswers{ grid-template-columns:1fr; }
}

/* phone, 375 - 430px: the real target */
@media (max-width:460px){
  .phone{ padding-left: var(--s3); padding-right: var(--s3); }
  .phone header{
    margin-left: calc(var(--s3) * -1); margin-right: calc(var(--s3) * -1);
    padding-left: var(--s3); padding-right: var(--s3);
  }
  .phone .panel{ padding: var(--s3); }
  #joinView{ padding: var(--s5) var(--s4) var(--s4); }
}

@media (max-width:390px){
  :root{ --fs-timer-phone:74px; }
  #turnPanel.mine .bigtimer{ font-size:80px; }
  #turnPanel:not(.mine) .bigtimer{ font-size:58px; }
  #groupName{ font-size: var(--fs-md); }
  #joinView h3{ font-size:25px; }
  #voteQuestion, #roundQuestion{ font-size:21px; }
}

@media (max-width:340px){
  :root{ --fs-timer-phone:62px; }
  #turnPanel.mine .bigtimer{ font-size:66px; }
}

/* Every animated state also carries a static colour, border or shadow change,
   so switching motion off loses no information. */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.001ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
    scroll-behavior:auto !important;
  }
  .queueitem.first{ box-shadow:0 0 0 2px var(--accent), inset 3px 0 0 var(--accent); }
  .queuepos.next, #turnPanel.mine{ box-shadow:0 0 0 2px var(--accent); }
  .hosttimer.warn, .bigtimer.warn{ text-decoration:underline; text-underline-offset:14px; }
}

@media print{
  .host{ display:block; height:auto; overflow:visible; }
  .host .col, .host .col:nth-child(2){ overflow:visible; }
  body::before, .host::before{ display:none; }
}

/* ==========================================================================
   11a. Fit-on-one-screen density pass (1080p)
   The middle column and the hands-raised queue are read from across the room
   and stay big. The left column is the operator console -- only the host
   reads it, from arm's length -- so it gets dense enough that nothing in the
   dashboard has to be scrolled to during a meeting.
   ========================================================================== */
.host .col:first-child .panel{ padding: var(--s3); }
.host .col:first-child h3{ font-size:.78rem; margin-bottom:6px; }
.host .col:first-child label.small{ font-size:.68rem; margin:6px 0 2px; }
.host .col:first-child input,
.host .col:first-child select{ padding:7px 10px; font-size:.9rem; }
.host .col:first-child button{ padding:8px 12px; font-size:.85rem; min-height:0; }
.host .col:first-child .row{ gap:6px; margin-top:6px; }
.host .col:first-child .memberpick{ gap:4px; max-height:96px; overflow-y:auto; }
.host .col:first-child .memberpick label{ padding:4px 8px; font-size:.8rem; }
.host .col:first-child #sttInfo{ font-size:.72rem; line-height:1.35; }

/* The sidebar QR only has to be scannable from a seat at the table; the
   "Show big QR" button throws a full-screen one on the TV for the room. */
/* min-height:300px on the base rule is what kept this panel huge. */
#qr img{ width:150px; height:auto; min-height:0; max-width:100%; display:block; margin:0 auto; padding:8px; }
#joinUrl{ font-size:.68rem; }

/* The queue is the priority in this column, but it must not push the panels
   below it off the bottom when eight hands go up at once. */

/* Reference lists: cap them and let them scroll inside instead of pushing
   the panels below them off the bottom of the screen. */
#memberBox{ max-height:78px; overflow-y:auto; }
#inboxBox{ max-height:110px; overflow-y:auto; }
#preparedBox{ max-height:150px; overflow-y:auto; }
.host #aiBox{ max-height:175px; }

/* Stage collapses when no turn is running: an empty 180px timer is wasted
   space, and the AI panel beneath it is what the host actually uses. */
/* min-height:376px (and 300px inside the host media query) is what kept the
   empty stage full-size, so both have to be beaten here. */
#stagePanel.idle .hosttimer{ display:none; }
.host #stagePanel.idle{ min-height:0; padding: var(--s3) var(--s4); }
#stagePanel.idle #turnWho{ font-size:1.05rem; opacity:.8; }
#stagePanel.idle #rtProgress{ font-size:.85rem; }

/* AI moderator now lives in the wide middle column. */
#aiPanelHost .row{ margin-top:8px; }
#aiPanelHost #askInput{ flex:1 1 auto; }
#aiPanelHost #autoSecs{ width:70px; text-align:center; }
#autoRow{ align-items:center; }

/* Voices heard -> put names to diarization labels */
.voicerow{ display:flex; align-items:center; gap:8px; padding:4px 0; }
.voicerow .vlabel{ flex:1 1 auto; font-weight:700; }
.voicerow .vmeta{ flex:0 0 auto; font-size:.75rem; }
.voicerow select{ flex:0 0 130px; padding:5px 8px; font-size:.85rem; }
#voicesBox{ max-height:132px; overflow-y:auto; }
#voicesHint{ font-size:.7rem; font-weight:400; }

/* Activity switcher (Roundtable / Vote / Game) */
.host .segswitch{ gap:6px; margin:0; }
.host .segswitch button{ flex:1 1 0; padding:9px 6px; font-size:.85rem; }

/* Full-screen join overlay: the QR big enough to scan from anywhere. */
#joinOverlay{
  position:fixed; inset:0; z-index:9600;
  background:var(--bg, #14100d);
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:18px;
  cursor:pointer;
}
#joinOverlay img{ width:min(52vh,560px); height:auto; border-radius:16px; background:#fff; padding:14px; }
#joinOverlayCode{ font-size:clamp(2rem,6vh,4rem); letter-spacing:.22em; font-weight:700; }
#joinOverlayUrl{ font-size:clamp(1rem,2.2vh,1.5rem); color:var(--muted); }
#joinOverlayHint{ font-size:1rem; color:var(--muted); }

/* ==========================================================================
   11a2. Phone attention nudge: unmissable, brief, self-dismissing
   ========================================================================== */
#nudgeOverlay{
  position:fixed; inset:0; z-index:9800;
  display:flex; align-items:center; justify-content:center;
  background:rgba(224,145,63,.94);
  animation: nudgeflash .45s ease-in-out 3;
  cursor:pointer;
}
#nudgeText{
  color:#1a1208; font-size:clamp(1.6rem,8vw,2.6rem); font-weight:800;
  text-align:center; padding:0 24px; line-height:1.2;
}
@keyframes nudgeflash{ 0%,100%{ opacity:1; } 50%{ opacity:.55; } }
@media (prefers-reduced-motion: reduce){ #nudgeOverlay{ animation:none; } }

/* ==========================================================================
   11b. Connection banner + diagnostics overlay
   ========================================================================== */
#connStatus{
  position:fixed; top:12px; left:50%; transform:translateX(-50%);
  z-index:9000; font-size:1rem; padding:8px 18px;
  box-shadow:0 6px 24px rgba(0,0,0,.6);
}
#diagPanel{
  position:fixed; inset:4vh 6vw; z-index:9500;
  background:var(--panel, #1f1915); border:1px solid #3d332a; border-radius:14px;
  padding:16px; display:flex; flex-direction:column; gap:10px;
  box-shadow:0 20px 60px rgba(0,0,0,.7);
}
#diagPanel pre{
  flex:1; overflow:auto; margin:0; font-size:.78rem; line-height:1.45;
  white-space:pre-wrap; word-break:break-word;
}
#diagPanel .lvl-error{ color:#ff8f8f; }
#diagPanel .lvl-warn{ color:#ffc978; }
#diagPanel .lvl-info{ color:#9fd8b4; }
#diagPanel .lvl-debug{ color:#9d8b79; }

/* ==========================================================================
   12. .hidden  -- last, so nothing can out-order it
   ========================================================================== */
.hidden{ display:none !important; }
