/* SAH — Festo2 Fadé app layer.
   Loads AFTER shared/tokens.css and shared/components.css and does one job:
   dress the markup host.js and player.js actually emit in the "Sahra" design
   system, at the right scale for the screen it is on.

   TWO SCALES, ONE FILE.
     body.host  — the display. TV type scale (--h-*), nothing below 32px at
                  1080p, enforced with max(px, vmin) so a 720p stick keeps the
                  floor and a 4K panel keeps the angular size.
     body.phone — the controller. Phone scale (--p-*), 16px floor on every
                  input or iOS Safari auto-zooms on focus and the layout
                  lurches mid-answer.

   The retired cedar/coral pair is gone: it sat on the red-green axis, which
   is exactly the axis ~8% of men cannot separate. Semantics are now amber
   (brand/primary/score), aqua (success/submitted/safe) and rummen
   (urgency/error/critical) — the blue-yellow axis, plus a luminance step.

   Logical properties only. No left/right/margin-left anywhere, so Arabic/RTL
   is a `dir` attribute later, not a rewrite.

   KNOWN DEVIATION: body.host does NOT use the `.tv` root from tokens.css.
   `.tv` is `100dvh; overflow: hidden` — a real display that never scrolls.
   Under the current one-socket protocol this same page is also the host's own
   play surface (they type answers and vote here), so it must still scroll or
   the lobby with twelve players is unreachable. The TV field and the TV type
   scale are applied here; the non-scrolling root lands with the
   display/controller split. */

/* `hidden` must beat any display we set. .banner, .rename and .timer-bar are
   all flex or block, and an author `display` silently defeats the UA's
   [hidden] { display: none } — which is why an empty banner painted as a bare
   ⟳ box and the rename form was open before anyone asked for it. */
[hidden] { display: none !important; }

/* ── ROOTS ─────────────────────────────────────────────────────────────── */

body.host {
  min-block-size: 100dvh;
  padding-block: var(--s-6) var(--s-8);
  padding-inline: var(--sv-4);
  background: var(--c-bg-tv);
  font-size: var(--h-xs);
  position: relative;
  isolation: isolate;
  overflow-x: clip;               /* the field below bleeds past the edge */
}

/* The Sahra field: jacaranda dusk over sea-ink, one warm bulb's worth of
   aqua rising off the floor. Static, one layer, composited. */
body.host::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(120vmin 80vmin at 78% -10%, rgb(138 107 240 / 0.20), transparent 62%),
    radial-gradient( 90vmin 70vmin at  8% 108%, rgb( 69 224 196 / 0.10), transparent 60%);
}

.wrap {
  inline-size: 100%;
  max-inline-size: 680px;
  margin-inline: auto;
}
.host .wrap { max-inline-size: min(1180px, 100%); }

/* ── TOPBAR ────────────────────────────────────────────────────────────── */

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-4);
  inline-size: 100%;
  margin-block-end: var(--s-6);
}
/* Balances the sound button so the title stays optically centred. A class,
   not an inline style: server/security.js notes that host/ and player/ carry
   no inline styles, which is what lets style-src drop 'unsafe-inline' once
   views.js is refactored. */
.topbar__spacer { min-inline-size: 48px; }
.topbar .back {
  color: var(--c-text-2); font-size: var(--p-xs);
  text-decoration: none; font-weight: 700;
}
.topbar .back:hover { color: var(--c-text); }
.topbar .title { font-family: var(--font-display); font-size: var(--p-lg); font-weight: 800; }
.host .topbar .back  { font-size: var(--h-xs); }
.host .topbar .title { font-size: var(--h-sm); }

.soundbtn {
  min-inline-size: 44px; min-block-size: 44px; border-radius: 50%;
  background: var(--glass-clear); border: 1px solid var(--glass-rim);
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  cursor: pointer;
  font-size: var(--p-lg); line-height: 1; padding: var(--s-1);
  color: var(--c-text-2);
  transition: opacity var(--dur-micro), transform var(--dur-micro);
  touch-action: manipulation;
}
.soundbtn:hover  { color: var(--c-text); }
.soundbtn:active { transform: scale(0.9); }
/* Muted is NOT signalled by opacity alone — the glyph itself changes
   (🔊 / 🔇), which is the channel that survives a bad TV and a bad eye. */
.soundbtn.off { color: var(--c-text-dim); }
.host .soundbtn { font-size: var(--h-sm); color: var(--c-text-2); }

/* ── ROOM CODE ─────────────────────────────────────────────────────────── */

.codebox { text-align: center; margin-block-end: var(--s-6); }
.codebox .label {
  font-size: var(--p-xs); text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--c-text-2); font-weight: 700;
}
.host .codebox .label { font-size: var(--h-sm); }

.codebox .code {
  font-family: var(--font-mono);
  font-size: var(--p-2xl);
  font-weight: 800;
  letter-spacing: 0.22em;          /* the ONE place letter-spacing is allowed:
                                      a Latin-only token, never Arabic text  */
  color: var(--c-amber);           /* 11.41:1 on the TV field                */
  line-height: 1.05;
  direction: ltr; unicode-bidi: isolate;   /* a code never mirrors           */
  font-variant-numeric: tabular-nums;
  animation: pop-in var(--dur-enter) var(--ease-pop) both;
}
.host .codebox .code { font-size: var(--h-code); letter-spacing: 0.15em; }

.codebox .joinurl { color: var(--c-text-2); font-size: var(--p-sm); }
.host .codebox .joinurl { font-size: var(--h-sm); }

.joinrow {
  display: flex; align-items: stretch; justify-content: center;
  gap: var(--s-2); margin-block-start: var(--s-4); flex-wrap: wrap;
}
.joinrow .joinlink {
  display: inline-flex; align-items: center; gap: var(--s-2);
  min-block-size: 48px;
  background: var(--c-surface); border: 2px solid var(--c-line-loud);
  border-radius: var(--r-pill);
  padding-block: var(--s-3); padding-inline: var(--s-5);
  color: var(--c-text); font-size: var(--p-sm); font-weight: 600;
  text-decoration: none; overflow-wrap: anywhere;
  direction: ltr;
  transition: border-color var(--dur-fast), background var(--dur-fast);
}
.joinrow .joinlink:hover { border-color: var(--c-aqua); background: var(--c-surface-2); }
.host .joinrow .joinlink { font-size: var(--h-md); }

.joinrow .copy {
  font: inherit; font-size: var(--p-sm); font-weight: 700; cursor: pointer;
  min-block-size: 48px;
  background: transparent; border: 2px solid var(--c-line-loud); color: var(--c-text-2);
  border-radius: var(--r-pill); padding-block: var(--s-3); padding-inline: var(--s-4);
  transition: border-color var(--dur-fast), color var(--dur-fast);
  touch-action: manipulation;
}
.joinrow .copy:hover { border-color: var(--c-text-2); color: var(--c-text); }
/* Copied is aqua AND a tick — never the colour on its own. */
.joinrow .copy.done { border-color: var(--c-aqua); color: var(--c-aqua); }
.host .joinrow .copy { font-size: var(--h-xs); }

/* ── PACK PICKER ───────────────────────────────────────────────────────── */

.packs {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--s-3); margin-block: var(--s-2) var(--s-1);
}
.pack {
  background: var(--c-surface); border: 2px solid var(--c-line-loud);
  border-radius: var(--r-md); padding: var(--s-4); cursor: pointer;
  text-align: center; font: inherit; color: var(--c-text);
  transition: border-color var(--dur-fast), background var(--dur-fast),
              transform var(--dur-fast) var(--ease-pop);
  touch-action: manipulation;
}
.pack:hover  { border-color: var(--c-text-2); background: var(--c-surface-2); }
.pack:active { transform: scale(0.98); }
/* Selected: aqua border + tint + a ✓ on the title. Three channels. */
.pack.on { border-color: var(--c-aqua); background: var(--c-aqua-tint); }
.pack.on .name { color: var(--c-aqua); }
.pack.on .name::before { content: '✓ '; }
/* The 18+ pack is rummen AND carries the literal string "18+" in its copy. */
.pack.adult.on { border-color: var(--c-rummen); background: var(--c-rummen-tint); }
.pack.adult.on .name { color: var(--c-rummen); }

.pack .name  { font-family: var(--font-display); font-size: var(--p-xl); font-weight: 800; }
.pack .blurb { color: var(--c-text-2); font-size: var(--p-xs); margin-block-start: var(--s-1);
               line-height: 1.4; }
.pack .count { color: var(--c-text-2); font-size: var(--p-2xs); margin-block-start: var(--s-2);
               text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700;
               font-variant-numeric: tabular-nums; }
.host .pack .name  { font-size: var(--h-md); }
.host .pack .blurb { font-size: var(--h-xs); }
.host .pack .count { font-size: var(--h-xs); }

.packlabel {
  text-align: center; color: var(--c-text-2); font-size: var(--p-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.1em;
  margin-block: var(--s-5) var(--s-3);
}
.host .packlabel { font-size: var(--h-sm); }
[dir="rtl"] .packlabel, [dir="rtl"] .codebox .label, [dir="rtl"] .pack .count {
  text-transform: none; letter-spacing: 0;     /* Arabic is cursive: never both */
}

/* ── RENAME ────────────────────────────────────────────────────────────── */

.rename { display: flex; gap: var(--s-2); margin-block-start: var(--s-4); }
.rename input { flex: 1; }
.namebtn {
  background: none; border: 0; cursor: pointer; font: inherit;
  font-size: var(--p-sm); color: var(--c-text-2); text-decoration: underline;
  padding: var(--s-2); margin-block-start: var(--s-2);
  min-block-size: 44px;                         /* the touch floor            */
  touch-action: manipulation;
}
.namebtn:hover { color: var(--c-text); }
.host .namebtn { font-size: var(--h-xs); }

/* ── STATUS / BANNER / ERROR ───────────────────────────────────────────── */

.status {
  text-align: center; color: var(--c-text-2); font-size: var(--p-sm);
  min-block-size: 20px; margin-block-start: var(--s-4);
}
.host .status { font-size: var(--h-xs); }

.banner {
  position: sticky; inset-block-start: 0; z-index: var(--z-banner);
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  background: var(--c-amber-tint);
  border: 1px solid var(--c-amber);
  color: var(--c-amber);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-sm);
  font-size: var(--p-sm); font-weight: 600;
  text-align: center;
  margin-block-end: var(--s-4);
  animation: banner-drop var(--dur-swap) var(--ease-out) both;
}
.banner::before { content: '⟳ '; }               /* glyph, not colour alone   */
.host .banner { font-size: var(--h-sm); border-width: 0.25vmin; }

.error {
  color: var(--c-rummen); font-size: var(--p-sm); text-align: center;
  min-block-size: 20px; font-weight: 600;
}
.error:not(:empty)::before { content: '⚠ '; }    /* glyph, not colour alone   */
.host .error { font-size: var(--h-xs); }

/* ── CARDS / LISTS ─────────────────────────────────────────────────────── */

.card {
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  padding: var(--s-5);
  box-shadow: var(--shadow-card);
}

.list {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: var(--s-2);
}
.list li {
  display: flex; align-items: center; gap: var(--s-2);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: var(--r-md);
  padding: var(--s-3) var(--s-4);
  font-size: var(--p-md);
  unicode-bidi: plaintext;                       /* Arabizi + Latin + emoji   */
  overflow-wrap: anywhere;                       /* a 40-char unbroken string */
  animation: pop-in var(--dur-fast) var(--ease-pop) both;
}
/* On the display, a 1.23:1 fill step is invisible through a projector — the
   loud border is what makes a card a card, not the fill. */
.host .list li {
  font-size: var(--h-lg);
  border: 0.2vmin solid var(--c-line-loud);
  border-radius: var(--rv-md);
  padding: var(--sv-2) var(--sv-3);
  box-shadow: var(--shadow-card);
  animation-duration: var(--dur-enter);
}
/* A disconnected player: 40% AND the "disconnected" tag. */
.list li.dim { opacity: 0.4; }
.list li .tag {
  flex: none;
  font-size: var(--p-xs); font-weight: 700;
  padding: 2px var(--s-2); border-radius: var(--r-pill);
  background: var(--c-surface-2); color: var(--c-text-dim);
  margin-inline-start: auto;
}
.host .list li .tag { font-size: var(--h-xs); color: var(--c-text-2); }
.list li .crown { color: var(--c-amber); margin-inline-start: var(--s-2); flex: none; }
.host .list li .crown { font-size: var(--h-md); }

/* ── BALLOT ────────────────────────────────────────────────────────────── */

.choices li {
  cursor: pointer;
  min-block-size: 64px;
  background: var(--glass-clear);
  border-color: var(--glass-rim);
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  transition: transform var(--dur-fast) var(--ease-pop),
              border-color var(--dur-fast), background var(--dur-fast),
              opacity var(--dur-fast);
  touch-action: manipulation;
  animation-delay: calc(var(--i, 0) * var(--stagger-phone));
}
.host .choices li { animation-delay: calc(var(--i, 0) * var(--stagger-tv)); }
.choices li:hover  { border-color: var(--c-text-2); filter: brightness(1.12); }
.choices li:active { transform: scale(0.98); }
/* Chosen: aqua border + tint + a ✓ badge + scale, and the rest go inert.
   Four channels, because "which one did I pick" must be answerable in
   greyscale, at arm's length, in a dark room. */
.choices li::before {
  content: '';
  flex: none; inline-size: 26px; block-size: 26px; border-radius: 50%;
  border: 2px solid var(--c-line-loud);
  display: grid; place-items: center;
  font-size: var(--p-sm); color: transparent; line-height: 1;
}
.host .choices li::before { inline-size: 3vmin; block-size: 3vmin; }
.choices li.chosen {
  border-color: var(--c-aqua); background: var(--c-aqua-tint);
  transform: scale(1.02);
}
.choices li.chosen::before {
  content: '✓';
  background: var(--c-aqua); border-color: var(--c-aqua); color: var(--c-ink);
}
.choices.locked li { pointer-events: none; }
.choices.locked li:not(.chosen) { opacity: 0.4; }

/* ── RESULTS ───────────────────────────────────────────────────────────── */

.result { display: flex; align-items: flex-start; gap: var(--s-4); }
.result .votes {
  flex: none; min-inline-size: 2.5ch; text-align: center;
  font-family: var(--font-display); font-weight: 800;
  color: var(--c-amber); font-size: var(--p-xl);
  font-variant-numeric: tabular-nums;
}
.host .result .votes { font-size: var(--h-xl); }
.result .who {
  display: block; color: var(--c-aqua); font-size: var(--p-xs);
  margin-block-start: var(--s-1); unicode-bidi: plaintext;
}
.host .result .who { font-size: var(--h-md); }
/* Zero votes: desaturated AND dimmed AND the count goes quiet. */
.result.zero { opacity: 0.66; filter: grayscale(0.85); }
.result.zero .votes { color: var(--c-text-2); }

.scorerow { display: flex; justify-content: space-between; align-items: center; gap: var(--s-3); }
.scorerow .pts {
  font-family: var(--font-display); font-weight: 800; color: var(--c-amber);
  font-variant-numeric: tabular-nums; flex: none;
}
/* "You" is aqua AND the row says "(you)" in words. */
.scorerow.you { border-color: var(--c-aqua); }

/* ── PROMPT / PHASE ────────────────────────────────────────────────────── */

.round {
  text-align: center; color: var(--c-text-2); font-size: var(--p-xs);
  text-transform: uppercase; letter-spacing: 0.1em; font-weight: 700;
  margin-block-end: var(--s-2);
  font-variant-numeric: tabular-nums;
}
.host .round { font-size: var(--h-sm); }
[dir="rtl"] .round { text-transform: none; letter-spacing: 0; }

.phase {
  text-align: center; font-size: var(--p-xl); font-weight: 700;
  font-family: var(--font-display);
  margin-block-end: var(--s-4);
}
.host .phase { font-size: var(--h-md); }

/* The prompt is the game, not decoration: full-contrast text, biggest thing
   on the display after the room code. */
.prompt {
  text-align: center;
  font-family: var(--font-display);
  font-size: var(--p-lg);
  font-weight: 700;
  line-height: 1.25;
  color: var(--c-text);
  margin: 0 0 var(--s-5);
  letter-spacing: 0;
  text-wrap: balance;
  unicode-bidi: plaintext;
  overflow-wrap: anywhere;
  animation: pop-in var(--dur-enter) var(--ease-pop) both;
}
.host .prompt { font-size: var(--h-xl); line-height: 1.22; max-inline-size: 78vw;
                margin-inline: auto; }

.progress {
  text-align: center; color: var(--c-text-2); font-size: var(--p-sm);
  margin-block-start: var(--s-4); font-variant-numeric: tabular-nums;
}
.host .progress { font-size: var(--h-sm); }

/* Dots are the fast channel the room reads at 3 m; the count next to them is
   the accurate one and the only one a screen reader can use. Keep both. */
.dots {
  display: flex; justify-content: center; gap: var(--s-2);
  margin-block-start: var(--s-3); direction: ltr;   /* progress, not text     */
}
.dots i {
  inline-size: 10px; block-size: 10px; border-radius: 50%;
  background: var(--c-surface-2);
  border: 2px solid var(--c-line-loud);             /* empty dots must show   */
  display: block;
  transition: background var(--dur-swap) var(--ease-smooth);
}
.dots i.done { background: var(--c-aqua); border-color: var(--c-aqua); }
.host .dots { gap: var(--sv-1); }
.host .dots i { inline-size: 1.6vmin; block-size: 1.6vmin; border-width: 0.25vmin; }

.winner {
  text-align: center; font-family: var(--font-display);
  font-size: var(--p-2xl); font-weight: 800;
  color: var(--c-amber); margin-block: var(--s-4) var(--s-5);
  unicode-bidi: plaintext;
  animation: pop-in var(--dur-enter) var(--ease-pop) both;
}
.host .winner { font-size: var(--h-2xl); }

/* ── TIMER ─────────────────────────────────────────────────────────────── */
/* The ring and the bar live in shared/components.css; what is here is where
   they SIT and the phone's numeral, which is the channel that survives with
   no colour vision at all. */

.timer-slot {
  display: flex; justify-content: center; align-items: center;
  margin-block-end: var(--s-4);
}
.host .timer-slot .timer-ring { --ring-size: min(18vmin, 180px); }

.timer-line {
  display: flex; align-items: baseline; justify-content: center; gap: var(--s-2);
  margin-block-end: var(--s-3);
  font-size: var(--p-xs); color: var(--c-text-dim);
  text-transform: uppercase; letter-spacing: 0.08em;
}
[dir="rtl"] .timer-line { text-transform: none; letter-spacing: 0; }
.timer-num {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--p-xl); color: var(--c-aqua);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0; text-transform: none;
  direction: ltr;                                  /* a clock does not mirror */
}
/* Colour AND weight AND a glyph — never the colour on its own. */
.timer-num.is-warning  { color: var(--c-amber); }
.timer-num.is-critical { color: var(--c-rummen); }
.timer-num.is-critical::after { content: ' ⏱'; }
.timer-num.is-expired  { font-size: var(--p-md); }

/* ── DEGENERATE ROUNDS ─────────────────────────────────────────────────── */
/* The server can now end a round with nothing to show: nobody answered, or
   exactly one person did and a ballot of one is not an election. An empty
   results screen reads as a crash. Say what happened instead. */

.degen {
  text-align: center;
  background: var(--c-surface);
  border: 2px dashed var(--c-line-loud);
  border-radius: var(--r-lg);
  padding: var(--s-6) var(--s-5);
  margin-block-end: var(--s-5);
  animation: pop-in var(--dur-fast) var(--ease-pop) both;
}
.host .degen { border-width: 0.3vmin; border-radius: var(--rv-lg); padding: var(--sv-3); }
.degen__glyph { font-size: var(--p-3xl); line-height: 1; }
.host .degen__glyph { font-size: var(--h-2xl); }
.degen__head {
  font-family: var(--font-display); font-weight: 800;
  font-size: var(--p-xl); color: var(--c-amber);
  margin-block-start: var(--s-2);
  text-wrap: balance;
}
.host .degen__head { font-size: var(--h-xl); }
.degen__sub {
  font-size: var(--p-md); color: var(--c-text-2);
  margin-block-start: var(--s-2); text-wrap: balance;
}
.host .degen__sub { font-size: var(--h-md); }
.degen__quote {
  display: block;
  margin-block-start: var(--s-4);
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--p-lg); color: var(--c-text);
  unicode-bidi: plaintext; overflow-wrap: anywhere;
}
.host .degen__quote { font-size: var(--h-lg); }
.degen__who { display: block; margin-block-start: var(--s-2);
              font-size: var(--p-sm); color: var(--c-aqua); unicode-bidi: plaintext; }
.host .degen__who { font-size: var(--h-md); }

/* ── CONTROLS ──────────────────────────────────────────────────────────── */

/* .btn is the platform glass standard (shared/components.css). Nothing here
   restyles its body; only the phone/TV size variants below.               */
/* Disabled must stay READABLE and must carry its reason (.hint below it) —
   never a silently dead button, never 40% opacity on a fill. */
.btn:disabled {
  background: var(--glass-clear); box-shadow: var(--glass-shadow); color: var(--c-text-disabled);
  border-color: var(--c-line); cursor: not-allowed;
  transform: none; filter: none;
}
.btn-block { inline-size: 100%; }
.btn-gold  { --tint: var(--c-amber); color: var(--c-ink); }
.host .btn { font-size: var(--h-xs); min-block-size: max(64px, 6vmin);
             padding-inline: var(--s-7); }

/* The force-skip escape hatch. Deliberately NOT a primary button and
   deliberately not next to one: it is ghost + rummen + a ⚠ + a two-step arm,
   because a mistimed tap here cuts a live round short for everyone. */
.skipbar {
  margin-block-start: var(--s-6);
  padding-block-start: var(--s-4);
  border-block-start: 1px dashed var(--c-line);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-2);
}
.btn-skip {
  background: var(--glass-clear);
  box-shadow: var(--glass-shadow);
  color: var(--c-text-2);
  border: 1px solid var(--glass-rim);
  font-size: var(--p-sm);
  min-block-size: 44px;
  padding-inline: var(--s-4);
}
.btn-skip:hover { background: var(--glass-clear); filter: brightness(1.15); color: var(--c-text); }
.btn-skip::before { content: '⚠ '; }
/* Armed: now it looks dangerous, because now one more tap does the thing. */
.btn-skip.armed {
  border-color: var(--c-rummen); color: var(--c-rummen);
  background: var(--c-rummen-tint);
}
.host .btn-skip { font-size: var(--h-xs); min-block-size: max(56px, 5vmin); }

.hostbar {
  margin-block-start: var(--s-6);
  padding-block-start: var(--s-5);
  border-block-start: 1px dashed var(--c-line);
  display: flex; flex-direction: column; gap: var(--s-2); align-items: center;
}
.hostbar .hint { color: var(--c-text-2); font-size: var(--p-xs); text-align: center; }
.host .hostbar .hint { font-size: var(--h-xs); }

/* ── INPUTS ────────────────────────────────────────────────────────────── */
/* 16px is a hard floor, not a taste: below it iOS Safari zooms the page on
   focus and the whole layout lurches while someone is mid-answer. */

textarea, input {
  font: inherit; font-size: var(--p-sm); inline-size: 100%;
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-md);
  border: 2px solid var(--c-line-loud);
  background: var(--c-bg); color: var(--c-text);
  transition: border-color var(--dur-fast) var(--ease-smooth);
}
textarea {
  min-block-size: 112px; resize: vertical;
  unicode-bidi: plaintext;        /* one answer can be Arabic + English +
                                     Arabizi + emoji. Never lock dir.        */
  text-align: start;
  overflow-wrap: anywhere;
}
textarea:focus, input:focus { outline: none; border-color: var(--c-aqua); }
.host textarea, .host input { font-size: var(--h-xs); padding: var(--sv-2); }

.counter {
  text-align: end; color: var(--c-text-dim); font-size: var(--p-xs);
  margin-block-start: var(--s-2); font-variant-numeric: tabular-nums;
}
.counter.warn { color: var(--c-amber); }
.counter.near { color: var(--c-rummen); }
.host .counter { font-size: var(--h-xs); color: var(--c-text-2); }

.field { margin-block-end: var(--s-4); }
.field label {
  display: block; font-size: var(--p-xs); font-weight: 700; color: var(--c-text-dim);
  text-transform: uppercase; letter-spacing: 0.06em; margin-block-end: var(--s-2);
}
[dir="rtl"] .field label { text-transform: none; letter-spacing: 0; }

#roomCodeInput {
  text-align: center; text-transform: uppercase;
  letter-spacing: 0.3em; font-size: var(--p-2xl); font-weight: 800;
  font-family: var(--font-mono); color: var(--c-amber);
  background: var(--c-surface);
  direction: ltr;
}

/* ── UTILITIES ─────────────────────────────────────────────────────────── */

.center { text-align: center; }
.muted  { color: var(--c-text-2); font-size: var(--p-sm); }
.host .muted { font-size: var(--h-sm); }
.dim    { color: var(--c-text-2); }
.stack  { display: flex; flex-direction: column; gap: var(--s-4); }
.mt     { margin-block-start: var(--s-5); }

.shake { animation: shake 300ms var(--ease-smooth); }

/* --- QR join panel ---------------------------------------------------------
   Dark modules on a light plate, never inverted onto the brand background:
   scanners expect dark-on-light and many refuse the inverse. The plate also
   guarantees the 4-module quiet zone survives whatever sits behind it —
   cropping that margin is the commonest reason a code will not scan. */
.qrpanel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 22px;
}
.qrplate {
  background: var(--c-cream, #FFF4DC);
  border-radius: 18px;
  padding: 14px;
  line-height: 0; /* kill the inline-SVG descender gap */
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.35);
}
.qrplate svg {
  display: block;
  width: min(34vmin, 300px);
  height: auto;
}
.qrhint {
  font-size: max(18px, 2.4vmin);
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--dim);
  text-transform: uppercase;
}

/* ── YOUR CHARACTER (phone) ────────────────────────────────────────────── */
/* Players choose one available mascot on join. The phone
   shows the 256px avatar.png ONLY — never a sprite sheet — so it stays light
   on a cheap phone and mobile data. One small idle float on the big one;
   nothing on the phone ever makes a sound or vibrates. */
.topbar__me {
  min-inline-size: 48px; block-size: 48px;
  display: grid; place-items: center;
}
.me-av {
  display: block;
  border-radius: 50%;
  background: var(--sah-cream);
  object-fit: contain;
  box-sizing: border-box;
}
.me-av--xs { inline-size: 28px; block-size: 28px; padding: 3px; flex: none; }
.me-av--sm { inline-size: 44px; block-size: 44px; padding: 4px; border: 2px solid var(--c-amber); }
/* Icons wave (agent C): on the phone every player icon is about 2x — the
   room list faces 28 -> 56, your header face 44 -> 80, the scoreboard card
   88 -> 168, the lobby hero 136 -> 256 (both capped by the screen width). */
.phone .me-av--xs { inline-size: 56px; block-size: 56px; padding: 5px; }
.phone .me-av--sm { inline-size: 80px; block-size: 80px; padding: 7px; border-width: 3px; }
.phone .topbar__me { min-inline-size: 80px; block-size: 80px; }
.phone .topbar__spacer { min-inline-size: 80px; }
.me-av--lg {
  inline-size: min(40vw, 168px); block-size: min(40vw, 168px);
  padding: 14px;
  border: 4px solid var(--c-amber);
  margin: var(--s-2) auto var(--s-3);
  animation: pop-in var(--dur-enter) var(--ease-pop) both,
             idle-float 3s var(--ease-smooth) 400ms infinite alternate;
}
.me-intro { text-align: center; }
.me-intro__who {
  font-family: var(--font-display); font-size: var(--p-xl);
  color: var(--c-amber); line-height: 1.2;
}
/* Phone-specific avatar entrance: keeps opacity at 1 throughout so it never
   appears dimmed, unlike the global pop-in which fades from 0. The TV does not
   load this file, so this override is safe. */
.phone .me-av--lg {
  animation: pop-in-phone var(--dur-enter) var(--ease-pop) both,
             idle-float 3s var(--ease-smooth) 400ms infinite alternate;
}

@keyframes pop-in-phone {
  from { opacity: 1; transform: scale(0.84); }
  60%  { opacity: 1; transform: scale(1.06); }
  to   { opacity: 1; transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .me-av--lg { animation: none !important; }
}

/* ══ PHONE CONTROLLER (wave 2) ════════════════════════════════════════════
   Everything below is the phone's own vocabulary, written for 360-390 px
   wide screens held in one hand. Rules of the house:
     - every tap target is at least 44 px (most are 48-64);
     - bright fills carry ink text, violet/ink carry cream (brand spec §1);
     - a state is never colour alone: a glyph or a word always rides along;
     - player text is dir="auto" (set in player.js), so Arabizi, Arabic and
       English each lay out the right way round.                            */

.phone .wrap { max-inline-size: 520px; }
.phone .topbar { margin-block-end: var(--s-3); }
.phone #stage > * + * { margin-block-start: var(--s-4); }
.phone #stage > .flash[hidden] + * { margin-block-start: 0; }

/* ── JOIN ─────────────────────────────────────────────────────────────── */
.joincard { padding: var(--s-5) var(--s-4); }
.joincard__title {
  font-family: var(--font-display); font-weight: 400;
  font-size: var(--p-xl); text-align: center; margin: 0 0 var(--s-4);
  color: var(--c-text);
}
.field__hint { font-size: var(--p-xs); color: var(--c-text-dim); text-align: center; margin-block-start: var(--s-2); }
.phone input { font-size: var(--p-md); min-block-size: 52px; }
.phone #roomCodeInput { min-block-size: 72px; font-size: var(--p-2xl); }
.btn-go { min-block-size: 56px; font-size: var(--p-lg); }
.phone .error:empty { min-block-size: 0; }
.phone .error:not(:empty) { margin-block-end: var(--s-3); }

.character-picker { margin-block: var(--s-4); }
.character-picker__title {
  font-family: var(--font-display);
  font-size: var(--p-lg);
  text-align: center;
  color: var(--c-text);
}
.character-picker__hint {
  margin-block: var(--s-2) var(--s-3);
  color: var(--c-text-2);
  font-size: var(--p-sm);
  text-align: center;
}
.character-picker__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-2);
}
.character-choice {
  min-block-size: 110px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  position: relative;
  padding: var(--s-2);
  border: 1px solid var(--glass-rim);
  border-radius: var(--r-md);
  background: var(--glass-clear);
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  color: var(--c-text);
  cursor: pointer;
  font: inherit;
  transition: transform var(--dur-micro) var(--ease-out);
}
.character-choice:active { transform: scale(0.96); }
.character-choice .me-av { background: transparent; }
.character-choice__name { font-size: var(--p-xs); font-weight: 700; line-height: 1.15; text-align: center; }
.character-choice__taken { font-size: var(--p-xs); font-weight: 700; }
.character-choice.is-selected { border-color: var(--c-amber); box-shadow: 0 0 0 2px var(--c-amber), var(--glass-shadow); }
.character-choice:focus-visible { outline: 3px solid var(--c-aqua); outline-offset: 2px; }
.character-choice:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── BANNER variants ──────────────────────────────────────────────────── */
.phone .banner.is-ok { background: var(--c-aqua-tint); border-color: var(--c-aqua); color: var(--c-aqua); }
.phone .banner.is-ok::before { content: '✓ '; }
.phone .banner.is-tv::before { content: '📺 '; }

/* ── IN-GAME MESSAGE LINE ─────────────────────────────────────────────── */
.flash {
  background: var(--c-rummen-tint); border: 1px solid var(--c-rummen);
  color: var(--c-text); border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4); font-size: var(--p-sm); font-weight: 600;
  text-align: center; animation: banner-drop var(--dur-swap) var(--ease-out) both;
}
.flash::before { content: '⚠ '; color: var(--c-rummen); }

/* ── NOTES (callouts) ─────────────────────────────────────────────────── */
.note {
  background: var(--c-surface); border: 2px solid var(--c-line-loud);
  border-radius: var(--r-md); padding: var(--s-4);
  text-align: center;
  animation: pop-in-phone var(--dur-enter) var(--ease-pop) both;
}
.note__head { font-family: var(--font-display); font-size: var(--p-lg); line-height: 1.2; color: var(--c-text); unicode-bidi: plaintext; }
.note__body { font-size: var(--p-sm); color: var(--c-text-2); margin-block-start: var(--s-2); line-height: 1.45; }
.note__body:empty { display: none; }
.note--big .note__head { font-size: var(--p-xl); }
.note--vip  { border-color: var(--c-amber); background: var(--c-amber-tint); }
.note--vip .note__head { color: var(--c-amber); }
.note--ok   { border-color: var(--c-aqua); background: var(--c-aqua-tint); }
.note--ok .note__head { color: var(--c-aqua); }
.note--you  { border-color: var(--c-amber); }
.note--you .note__head { color: var(--c-amber); }
.note--next { border-style: dashed; }

/* "Look at the TV" — the phone's most repeated instruction. */
.lookup {
  display: flex; align-items: center; justify-content: center; gap: var(--s-2);
  font-weight: 700; font-size: var(--p-md); color: var(--c-text);
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-pill); background: var(--c-surface-2);
  text-align: center; unicode-bidi: plaintext;
}
.lookup__icon { font-size: var(--p-lg); line-height: 1; flex: none; }

/* ── LOBBY ────────────────────────────────────────────────────────────── */
.phone .me-av--lg { inline-size: min(64vw, 256px); block-size: min(64vw, 256px); padding: 20px; border-width: 5px; }
.me-av--md { inline-size: 88px; block-size: 88px; padding: 8px; border: 3px solid var(--c-amber); margin-inline: auto; }
.phone .me-av--md { inline-size: min(46vw, 168px); block-size: min(46vw, 168px); padding: 14px; border-width: 4px; }
.me-intro__in { font-size: var(--p-md); font-weight: 700; color: var(--c-aqua); margin-block-start: var(--s-1); }

.howto {
  border: 1px solid var(--c-line-loud); border-radius: var(--r-md);
  padding: var(--s-4); background: var(--c-surface);
}
.howto__title {
  font-size: var(--p-xs); font-weight: 700; color: var(--c-text-dim);
  text-transform: uppercase; letter-spacing: 0.08em; margin-block-end: var(--s-2);
}
.howto__steps { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s-2); }
.howto__steps li { display: flex; gap: var(--s-3); align-items: flex-start; font-size: var(--p-sm); line-height: 1.4; }
.howto__icon { flex: none; inline-size: 1.6em; text-align: center; font-size: var(--p-md); }

.sectionlabel {
  font-size: var(--p-xs); font-weight: 700; color: var(--c-text-dim);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.phone #stage > .sectionlabel + .roster { margin-block-start: var(--s-2); }
.roster li { min-block-size: 48px; padding-block: var(--s-2); }
.roster__name { flex: 1; min-inline-size: 0; }
.phone .list li .tag { margin-inline-start: 0; }
.phone .list li .tag.tag--you { background: var(--c-aqua-tint); color: var(--c-aqua); }
.phone .list li .tag.tag--vip { background: var(--c-amber); color: var(--c-ink); }

/* ── VIP CONTROLS ─────────────────────────────────────────────────────── */
.ctrlbar {
  border: 2px solid var(--c-amber); border-radius: var(--r-md);
  background: var(--c-surface); padding: var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-3);
}
.ctrlbar__label {
  font-size: var(--p-xs); font-weight: 700; color: var(--c-amber);
  text-transform: uppercase; letter-spacing: 0.08em; text-align: center;
}
.ctrlbar .btn__reason { margin-block-start: calc(-1 * var(--s-1)); font-size: var(--p-xs); }
.ctrlbar .btn__reason:empty { display: none; }
.ctrlbar .btn__reason.btn__reason--need { color: var(--c-amber); font-weight: 700; font-size: var(--p-sm); }
/* During writing / voting the VIP's only lever is the escape hatch: keep it
   quiet and at the bottom, well away from Send. */
.phone #stage > .ctrlbar--quiet {
  border: 1px dashed var(--c-line-loud); background: transparent;
  margin-block-start: var(--s-7); align-items: center;
}
.ctrlbar--quiet .ctrlbar__label { color: var(--c-text-dim); }

.packpick__label { font-size: var(--p-xs); font-weight: 700; color: var(--c-text-dim); margin-block-end: var(--s-2); text-align: center; }
.packpick__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); }
.packpick__opt {
  font: inherit; color: var(--c-text); cursor: pointer;
  min-block-size: 64px; padding: var(--s-2) var(--s-3);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: var(--glass-clear); border: 1px solid var(--glass-rim); border-radius: var(--r-md);
  box-shadow: var(--glass-shadow);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-micro) var(--ease-out), background var(--dur-fast);
}
.packpick__opt:active { transform: scale(0.97); }
.packpick__name { font-weight: 700; font-size: var(--p-sm); line-height: 1.2; text-align: center; }
.packpick__blurb { font-size: var(--p-2xs); color: var(--c-text-dim); text-align: center; line-height: 1.3; }
/* Chosen: filled + a ✓ in the name (player.js). Chill = green, 18+ = violet
   (the brand's 18+ marker; violet is dark-bucket, so cream text). */
.packpick__opt.is-on { background: var(--sah-green); border-color: var(--sah-green); color: var(--sah-ink); }
.packpick__opt.is-on .packpick__blurb { color: var(--sah-ink); }
.packpick__opt--adult { border-color: var(--sah-violet); }
.packpick__opt--adult .packpick__name { color: var(--c-jac-lt); }
.packpick__opt--adult.is-on { background: var(--sah-violet); border-color: var(--sah-violet); color: var(--sah-cream); }
.packpick__opt--adult.is-on .packpick__name,
.packpick__opt--adult.is-on .packpick__blurb { color: var(--sah-cream); }

/* ── ROUND CARD (the get-ready beat) ──────────────────────────────────── */
.roundcard {
  text-align: center; border: 3px solid var(--c-amber); border-radius: var(--r-lg);
  background: var(--c-amber-tint); padding: var(--s-6) var(--s-4);
  animation: pop-in-phone var(--dur-enter) var(--ease-pop) both;
}
.roundcard__eyebrow {
  font-size: var(--p-xs); font-weight: 700; color: var(--c-text-2);
  text-transform: uppercase; letter-spacing: 0.1em;
}
.roundcard__title { font-family: var(--font-display); font-size: var(--p-3xl); line-height: 1.1; color: var(--c-amber); margin-block: var(--s-2); }
.roundcard__line { font-size: var(--p-sm); color: var(--c-text); line-height: 1.45; }
.roundcard__ready { margin-block-start: var(--s-4); font-weight: 700; color: var(--c-text-2); }

/* ── WRITING ──────────────────────────────────────────────────────────── */
.phone .round { margin-block-end: 0; }
.qcard { padding: var(--s-4); border-width: 2px; }
.qcard__head { display: flex; align-items: center; gap: var(--s-2); margin-block-end: var(--s-3); min-block-size: 32px; }
.qcard__slot { font-size: var(--p-xs); font-weight: 700; color: var(--c-text-2); text-transform: uppercase; letter-spacing: 0.06em; }
.qcard__head .timer-num { margin-inline-start: auto; font-size: var(--p-xl); line-height: 1; }
.qcard__badge {
  margin-inline-start: auto; flex: none;
  font-size: var(--p-xs); font-weight: 700; padding: 4px var(--s-3);
  border-radius: var(--r-pill); background: var(--c-surface-2); color: var(--c-text-2);
}
.qcard__badge--sent { background: var(--c-aqua); color: var(--c-ink); font-size: var(--p-sm); }
.qcard__badge--missed { background: var(--c-rummen-tint); color: var(--c-text); border: 1px solid var(--c-rummen); }
.qcard__prompt {
  font-family: var(--font-display); font-size: var(--p-lg); line-height: 1.3;
  color: var(--c-text); margin-block-end: var(--s-3); overflow-wrap: anywhere;
}
.qcard__prompt--sm { font-family: var(--font-ui); font-size: var(--p-sm); font-weight: 600; color: var(--c-text-2); margin-block-end: var(--s-2); }
.qcard__line { font-size: var(--p-sm); color: var(--c-text-2); line-height: 1.4; }
.qcard.is-active { border-color: var(--c-amber); box-shadow: 0 0 0 4px var(--c-amber-tint); }
.qcard.is-sent { border-color: var(--c-aqua); background: var(--c-aqua-tint); box-shadow: none; animation: pop-in-phone var(--dur-enter) var(--ease-pop) both; }
.qcard.is-next { border-style: dashed; border-color: var(--c-line-loud); background: transparent; box-shadow: none; }
.qcard.is-missed { border-style: dashed; border-color: var(--c-rummen); background: transparent; box-shadow: none; }
.qcard.is-missed .qcard__line { color: var(--c-text); font-weight: 700; }
.phone textarea { font-size: var(--p-md); min-block-size: 96px; }
.btn-send { scroll-margin-block-end: var(--s-4); margin-block-start: var(--s-3); min-block-size: 56px; font-size: var(--p-lg); }
.sent { display: flex; flex-direction: column; gap: var(--s-2); }
.sent__text { font-size: var(--p-md); font-weight: 700; color: var(--c-text); overflow-wrap: anywhere; }
.phone .tag {
  display: inline-block; align-self: flex-start;
  font-size: var(--p-xs); font-weight: 700; padding: 2px var(--s-2);
  border-radius: var(--r-pill); background: var(--c-surface-2); color: var(--c-text-2);
}
.phone .tag.tag--safety { color: var(--c-text); border: 1px solid var(--c-line-loud); }
.safety { margin-block-start: var(--s-4); padding-block-start: var(--s-3); border-block-start: 1px dashed var(--c-line-loud); }
.safety__why { font-size: var(--p-xs); color: var(--c-text-2); text-align: center; margin-block-end: var(--s-2); }
.btn-safety {
  background: transparent; color: var(--c-text); border: 2px solid var(--sah-blue);
  font-size: var(--p-sm); min-block-size: 52px; flex-wrap: wrap; line-height: 1.25;
}
.btn-safety { flex-direction: column; gap: 2px; padding-block: var(--s-2); }
.btn-safety__dot { display: none; }             /* two lines: English, then Arabic */
.btn-safety .ar { font-family: var(--font-display); font-weight: 400; font-size: var(--p-md); line-height: 1.2; }
.phone .hint { font-size: var(--p-xs); color: var(--c-text-dim); text-align: center; margin-block-start: var(--s-3); line-height: 1.4; }

/* ── VOTING ───────────────────────────────────────────────────────────── */
.phone .prompt { text-align: center; color: var(--c-text); font-family: var(--font-display); font-weight: 400; margin-block-end: 0; }
.phone .prompt.prompt--sm { font-family: var(--font-ui); font-size: var(--p-sm); font-weight: 600; color: var(--c-text-2); }
.phone .timer-line { margin-block-end: 0; }
.phone .phase { margin-block-end: 0; font-weight: 400; }
.voteoption { min-block-size: 64px; font-size: var(--p-md); font-weight: 600; }
.voteoption__text { flex: 1; min-inline-size: 0; overflow-wrap: anywhere; }
.choices li.is-empty { cursor: default; opacity: 0.5; border-style: dashed; }
.picked {
  border: 2px solid var(--c-aqua); border-radius: var(--r-md);
  padding: var(--s-4); background: var(--c-surface);
}
.picked__label { font-size: var(--p-xs); font-weight: 700; color: var(--c-aqua); text-transform: uppercase; letter-spacing: 0.06em; }
.picked__text { font-size: var(--p-lg); font-weight: 700; margin-block-start: var(--s-1); overflow-wrap: anywhere; }
.tally { text-align: center; }
.tally .dots { margin-block-start: 0; flex-wrap: wrap; }
.tally__n { font-size: var(--p-xs); color: var(--c-text-dim); margin-block-start: var(--s-2); font-variant-numeric: tabular-nums; }

/* ── RESULTS ──────────────────────────────────────────────────────────── */
.results li { align-items: flex-start; }
.result__body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-inline-size: 0; }
.result__text { font-weight: 700; overflow-wrap: anywhere; }
.result__tags { display: flex; flex-wrap: wrap; gap: var(--s-1); margin-block-start: var(--s-1); }
.phone .list li.result.won { border-color: var(--c-amber); border-width: 2px; }
.result.is-mine .who { font-weight: 700; }
.phone .tag.tag--pts { background: var(--c-amber); color: var(--c-ink); }
.phone .tag.tag--win { background: var(--c-aqua); color: var(--c-ink); }
.tag--win::before { content: '🏆 '; }

/* ── STANDING (scoreboard + game over) ────────────────────────────────── */
.standing { text-align: center; }
.standing__rank { font-family: var(--font-display); font-size: var(--p-3xl); line-height: 1.05; color: var(--c-amber); margin-block-start: var(--s-2); }
.standing__of { font-size: var(--p-sm); color: var(--c-text-2); }
.standing__nums { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); margin-block-start: var(--s-4); }
.standing__num {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  background: var(--c-surface); border: 1px solid var(--c-line-loud); border-radius: var(--r-md);
  padding: var(--s-3);
}
.standing__num b { font-family: var(--font-display); font-weight: 400; font-size: var(--p-xl); line-height: 1.1; font-variant-numeric: tabular-nums; }
.standing__num span { font-size: var(--p-xs); color: var(--c-text-dim); }
.standing__num--plus b { color: var(--c-aqua); }
.phone .winner { font-size: var(--p-xl); margin-block: 0; }

/* The stage is rebuilt on every broadcast (someone voted, someone sent).
   Entrance animations belong to a NEW screen only; on a same-screen rebuild
   (#stage.is-calm) nothing re-pops or re-fades, except a confirmation that
   is appearing for the first time (.pop, set once by player.js). */
.phone #stage.is-calm *:not(.pop) { animation: none !important; }
.phone #stage.is-calm .pop { animation: pop-in-phone var(--dur-enter) var(--ease-pop) both; }

@media (prefers-reduced-motion: reduce) {
  .note, .roundcard, .qcard.is-sent, .flash, .phone #stage.is-calm .pop { animation: none !important; }
}
