/* ==========================================================================
   QuizBlitz — shared design system for the host (big screen) and the player
   (phone). No external assets, no fonts, no CDN, no network: fully offline.

   ---------------------------------------------------------------------------
   CONTRACT WITH host.html / play.html
   ---------------------------------------------------------------------------
   Those two pages each carry their own presentation layer and both build on
   the tokens and components below. Everything they reference is defined here
   and is treated as public API:

     answer identity  --a0..--a3, --a0-dark..--a3-dark, --c, --c-dark, --ink-on
     surfaces         --bg --bg-2 --surface --surface-2 --line --line-strong
     ink              --ink --ink-dim --ink-faint
     accents          --accent --accent-2 --gold --silver --bronze --danger --ok
     shape            --r-sm --r-md --r-lg --r-xl
     depth            --shadow-md --shadow-lg
     motion           --ease --dur
     text             --font --mono --font-latin --font-ar --font-he
     direction        --dirx (+1 ltr / -1 rtl)  --ui-dir (ltr / rtl)
     keyframes        popIn riseIn pulseGlow
     stagger          --i   (set per item by JS; used as `calc(var(--i,0) * …)`)

   Nothing in here may be removed without checking both pages first.

   ---------------------------------------------------------------------------
   DIRECTION
   ---------------------------------------------------------------------------
   This file is direction-agnostic: inline-axis properties are logical, so a
   page can set `<html dir="rtl">` and the layout follows. The exceptions are
   marked DIRECTION-NEUTRAL or PINNED where they sit, and §16 at the end of the
   file holds every rule that exists only because of direction. Read
   docs/I18N_DESIGN.md §5.2-§5.5 before adding a physical left/right anywhere.

   THE 2x2 ANSWER GRID NEVER MIRRORS (§16.2). The triangle is answer 0 and it
   is top-left on the projector and on every phone, in every language.

   ---------------------------------------------------------------------------
   THE FOUR ANSWER IDENTITIES
   ---------------------------------------------------------------------------
   --a0 triangle   --a1 diamond   --a2 circle   --a3 square

   The SHAPE is the primary signal; colour is the secondary one. That ordering
   is deliberate and it is also why the palette below is not the usual
   red/blue/yellow/green: those four collapse under red-green colour blindness
   (the previous set measured a CIEDE2000 distance of just 8.3 between the red
   triangle and the green square under simulated deuteranopia — effectively the
   same colour). This set was solved for numerically instead.

   Simulated with Machado 2009 and Viénot 1999, worst pair per condition:

       deuteranopia   min dE00 29.2   (was  8.3)
       protanopia     min dE00 28.4   (was 12.2)
       tritanopia     min dE00 26.5   (was 11.9)
       normal vision  min dE00 39.8

   A dE00 near 2 is "only just distinguishable"; everything here is far above
   that in every condition. The separation is carried by lightness as much as
   by hue (L* 42.7 / 41.0 / 88.0 / 69.9), because lightness is the one axis a
   dichromat keeps intact.

   INK POLARITY is the third, redundant cue and the reason the contrast numbers
   work at all: the two dark fills take white text, the two light fills take
   near-black text. Read it from --ink-on, never hard-code it.

       a0 #c70f46  white ink   5.86:1
       a1 #2f57c6  white ink   6.36:1
       a2 #ffdb29  dark  ink  14.47:1
       a3 #37beac  dark  ink   8.57:1
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* --- The four answer colours. Host and player MUST agree on these. ----- */
  --a0: #c70f46; /* triangle — crimson */
  --a1: #2f57c6; /* diamond  — royal blue */
  --a2: #ffdb29; /* circle   — gold */
  --a3: #37beac; /* square   — jade */

  /*
   * Second stop of an answer tile's gradient. For the WHITE-ink pair this can
   * be genuinely dark. For the DARK-ink pair it deliberately stays close to
   * the base colour, so that near-black ink still clears the 3:1 floor at the
   * foot of the tile, where the gradient is darkest.
   *
   * No page darkens these fills any further: the tile is drawn from --c to
   * --c-dark with only the specular highlight over it, and the contrast
   * figures below are the ones that actually ship. If you deepen a -dark stop
   * for the DARK-ink pair, re-measure the foot of the tile first.
   */
  --a0-dark: #7a0b2c;
  --a1-dark: #1b3273;
  --a2-dark: #f5cc10;
  --a3-dark: #36bbaa;

  /* Deep — for filled graphics that carry no text (bar chart gradients). */
  --a0-deep: #5c0820;
  --a1-deep: #152657;
  --a2-deep: #c99f00;
  --a3-deep: #1f8b7d;

  /* Lite — for a coloured mark ON the dark background: glyphs, rules, text
     gradients. All four clear 3:1 against --bg as a non-text graphic. */
  --a0-lite: #f1497b;
  --a1-lite: #7c96e0;
  --a2-lite: #ffe86b;
  --a3-lite: #5fd2c2;

  /* Ink that is legible on the fill above. Consumed as var(--ink-on). */
  --ink-on: #fff;
  --ink-on-light: #0a0a12;

  /* --- Surfaces --------------------------------------------------------- */
  --bg: #0a0a16;
  --bg-2: #12122c;
  --bg-3: #1a1a3d;
  --surface: rgba(255, 255, 255, 0.055);
  --surface-2: rgba(255, 255, 255, 0.10);
  --surface-3: rgba(255, 255, 255, 0.15);
  --sunk: rgba(0, 0, 0, 0.32);
  --line: rgba(255, 255, 255, 0.14);
  --line-strong: rgba(255, 255, 255, 0.28);

  /* --- Ink -------------------------------------------------------------- */
  --ink: #f4f5ff;      /* 18.1:1 on --bg */
  --ink-dim: #a9adcf;  /*  8.9:1 on --bg */
  --ink-faint: #8d93bf; /* 6.6:1 on --bg, 5.2:1 on --surface-2.
                           The old #6f74a0 measured 4.38:1 and was used for
                           real labels, so it sat just under the body-text
                           bar. Raised rather than re-styling every caption. */

  /* --- Accents ---------------------------------------------------------- */
  --accent: #8b5cf6;
  --accent-deep: #6d28d9; /* white text clears 4.5:1 on this, not on --accent */
  --accent-2: #22d3ee;    /* focus ring — 10.9:1 on --bg */
  --gold: #ffd35c;
  --gold-lite: #ffe487;
  --gold-deep: #c99a1d;
  --silver: #cfd6e6;
  --silver-lite: #ffffff;
  --silver-deep: #8e97ab;
  --bronze: #e8a26a;
  --bronze-lite: #f4c093;
  --bronze-deep: #a86c3c;
  --danger: #ff5470;      /* as INK on dark: 6.3:1 */
  /* Ink for --danger on a --danger-tinted ground: the tint lifts the backdrop
     out from under #ff5470 (4.1:1 on the leaderboard row), this clears it at
     5.3:1. Mirrors the --gold-lite / --ok-lite pattern. */
  --danger-lite: #ff8095;
  --danger-deep: #c8102e; /* as a FILL under white text: 5.9:1 */
  --danger-deeper: #9b0f2b;
  --ok: #21c07a;
  --ok-lite: #35d18e;
  /* Mirrors the --danger ramp: fills to carry white text, not ink colours.
     5.4:1 at the top of the gradient, 14.5:1 at the foot. */
  --ok-deep: #0f7a4a;
  --ok-deeper: #05301f;
  --on-ok: #04180f; /* ink for a filled --ok chip: 7.9:1 */

  /* --- Space ------------------------------------------------------------ */
  --s-1: clamp(0.25rem, 0.55vmin, 0.45rem);
  --s-2: clamp(0.45rem, 1vmin, 0.8rem);
  --s-3: clamp(0.7rem, 1.5vmin, 1.25rem);
  --s-4: clamp(1rem, 2.2vmin, 1.9rem);
  --s-5: clamp(1.35rem, 3vmin, 2.8rem);
  --s-6: clamp(1.8rem, 4.2vmin, 4rem);
  --s-7: clamp(2.4rem, 6vmin, 6rem);
  --pad-screen: clamp(0.9rem, 2.4vmin, 2.6rem);

  /* --- Shape ------------------------------------------------------------ */
  --r-xs: 6px;
  --r-sm: 10px;
  --r-md: 16px;
  --r-lg: 24px;
  --r-xl: 34px;
  --r-pill: 999px;

  /* --- Depth ------------------------------------------------------------ */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.35);
  --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.40);
  --shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.55);
  --shadow-xl: 0 40px 90px rgba(0, 0, 0, 0.62);
  --inset-top: inset 0 1px 0 rgba(255, 255, 255, 0.22);

  /* --- Type ------------------------------------------------------------- */

  /*
   * --font-latin is the base Latin stack. --font is an alias for it, and
   * --font-latin is the tail of --font-ar / --font-he so that a Latin island
   * inside an Arabic sentence ("...شركة Microsoft") resolves through exactly
   * the same faces as the rest of the product.
   *
   * The indirection exists to avoid a var() CYCLE: §16 redefines --font on an
   * Arabic page, so --font-ar must not itself reference --font. A cycle is not
   * a fallback in CSS — it makes the whole declaration invalid at computed
   * value time and the element drops to the UA default face.
   */
  --font-latin: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, "Noto Sans", sans-serif;
  --font: var(--font-latin);
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  /*
   * --- Arabic and Hebrew: SYSTEM FACES ONLY -------------------------------
   *
   * No @font-face, no download, no CDN, nothing baked in. Arabic shaping is a
   * system concern and every real client platform has already solved it; a
   * ~190 KB Regular+Bold WOFF2 pair would also OVERRIDE a better native face
   * on the five platforms that ship one.
   *
   * `font-family` falls back PER CHARACTER, so a name that is present but has
   * no Arabic coverage is a harmless no-op that the list falls through, and a
   * name that is absent costs nothing at all. That is why the list is long.
   *
   * What each platform actually ships:
   *
   *   iOS / iPadOS  SF Arabic (iOS 16+, the better face) and Geeza Pro, which
   *                 has shipped on every release for over a decade.
   *   macOS         SF Arabic (Ventura 13+), Geeza Pro always. Al Bayan and
   *                 friends also ship but are display faces; Al Bayan is last.
   *   Windows       Tahoma has carried full Arabic since Windows 2000 and is
   *                 the entry to bet a deployment on. Sakkal Majalla (8+) and
   *                 Dubai (10 1709+ / Office) are the nicer UI faces. "Segoe
   *                 UI" is first of the Windows group because the Win10/11
   *                 shell resolves Arabic through the Segoe family; VERIFY
   *                 that empirically rather than trust it (I18N_DESIGN §10.4).
   *   Android / CrOS  Noto Naskh Arabic since Android 5, Droid Arabic Naskh
   *                 before it. Android's own fallback chain would find Arabic
   *                 regardless, so these are a preference, not load-bearing.
   *   Linux         Whatever fontconfig has. Debian/Ubuntu `fonts-noto-core`
   *                 and Fedora `google-noto-naskh-arabic-fonts` provide Noto
   *                 Naskh Arabic, and most desktop spins ship it.
   *
   * THE HONEST FAILURE CASE — a minimal container, a kiosk image or a
   * stripped VM with no Arabic font installed. MEASURED on the build box for
   * this stage rather than assumed, because the assumed answer was wrong:
   *
   *   `fc-list :lang=ar` here returns exactly two families — DejaVu Sans and
   *   DejaVu Sans Mono — plus Droid Sans Fallback via fontconfig. Not one name
   *   in the stack above is installed. Chrome 145 nonetheless rendered
   *   `مرحبا بكم في الاختبار لا` CORRECTLY JOINED AND SHAPED, lam-alef
   *   ligature included.
   *
   * I18N_DESIGN §5.5 predicts the opposite — "disconnected letterforms that
   * look like a rendering bug" — and THAT DID NOT REPRODUCE. The reason is
   * that shaping is not the font's job any more: Chrome shapes Arabic in
   * HarfBuzz against whatever glyphs the face provides, and DejaVu Sans
   * carries the Arabic presentation forms it needs. So the realistic bad
   * outcome on a bare Linux box is not breakage, it is a plain, poorly
   * hinted naskh that is legible but ugly at projector size. True tofu
   * (▯▯▯▯▯) needs a box with NO Arabic-capable face at all, which is rarer
   * than the spec assumes.
   *
   * ALSO MEASURED, and it matters more than the above: `document.fonts.check()`
   * returned TRUE for every one of the nineteen candidate families on this
   * box, "SF Arabic" and "Sakkal Majalla" included, none of which exist here.
   * It is not merely unreliable as §5.5 warns — it is useless as a presence
   * test, so nothing downstream should branch on it.
   *
   * The runtime's shaping probe (I18N_DESIGN §5.5, owned by the i18n runtime,
   * not by this file) is what should turn a genuinely fontless box into an
   * advisory naming the package to install. NOTE FOR THAT OWNER: as specified
   * it does not work. It compares the stack's width against a guaranteed-
   * absent family, but the absent family falls back to a DIFFERENT default
   * face, so the two widths differ for reasons that have nothing to do with
   * shaping. Measured here: stack 628px, DejaVu 628px, absent-family 611px,
   * so the probe reports "Arabic is fine" purely because 628 != 611. It would
   * report exactly the same on a box that renders nothing but tofu.
   *
   * The "UI" cuts of Noto are listed ahead of the text cuts on purpose: they
   * carry compressed vertical metrics, and a fixed-height answer tile is
   * exactly where naskh ascenders and descenders overflow.
   */
  --font-ar:
    /* Apple */
    "SF Arabic", "Geeza Pro",
    /* Windows */
    "Segoe UI", "Dubai", "Sakkal Majalla", Tahoma,
    /* Android, ChromeOS, mainstream Linux */
    "Noto Naskh Arabic UI", "Noto Naskh Arabic",
    "Noto Sans Arabic UI", "Noto Sans Arabic", "Droid Arabic Naskh",
    /* Non-Noto Linux packages */
    "Amiri", "Scheherazade New", "KacstOne",
    /* Older Windows and macOS display faces, last because they are display
       faces rather than UI faces */
    "Arabic Typesetting", "Traditional Arabic", "Simplified Arabic", "Al Bayan",
    /* Latin islands, and the final give-up */
    var(--font-latin);

  --font-he:
    "SF Hebrew", "Arial Hebrew", "New Peninim MT",
    "Segoe UI",
    "Noto Sans Hebrew", "Noto Serif Hebrew", "David Libre", "FreeSans",
    var(--font-latin);

  /*
   * Fluid scale. The middle term is `rem + vmin`, not bare vw: the host runs
   * on anything from a 1024px laptop to a 3840x2160 projector, and vmin keeps
   * a 4K screen from turning captions into billboards while the rem floor
   * keeps a 360px phone readable. Every step is capped at both ends.
   */
  --t-3xs: clamp(0.62rem, 0.5rem + 0.32vmin, 0.9rem);
  --t-2xs: clamp(0.7rem, 0.56rem + 0.42vmin, 1.05rem);
  --t-xs: clamp(0.78rem, 0.62rem + 0.55vmin, 1.2rem);
  --t-sm: clamp(0.88rem, 0.7rem + 0.72vmin, 1.4rem);
  --t-md: clamp(1rem, 0.8rem + 0.9vmin, 1.65rem);
  --t-lg: clamp(1.15rem, 0.88rem + 1.3vmin, 2.1rem);
  --t-xl: clamp(1.4rem, 1rem + 2vmin, 3rem);
  --t-2xl: clamp(1.75rem, 1.15rem + 3.2vmin, 4.3rem);
  --t-3xl: clamp(2.1rem, 1.3rem + 4.6vmin, 5.8rem);
  --t-hero: clamp(2.6rem, 1.2rem + 8vmin, 9rem);
  --t-pin: clamp(3.2rem, 0.8rem + 15vmin, 15rem);

  --lh-tight: 1.06;
  --lh-snug: 1.18;
  --lh-body: 1.45;
  --tracking-cap: 0.22em;

  /* --- Motion ----------------------------------------------------------- */
  --dur-1: 110ms;  /* press / micro state */
  --dur-2: 190ms;  /* hover, colour change */
  --dur-3: 300ms;  /* small element enter */
  --dur-4: 460ms;  /* pop, card enter */
  --dur-5: 700ms;  /* bars growing, board moving */
  --dur-6: 1100ms; /* long reveal beats */
  --dur: 380ms;    /* screen transition (public alias) */

  --ease: cubic-bezier(0.22, 1, 0.36, 1);          /* public — do not change */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.55, 0, 1, 0.45);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* overshoots — for pops */
  --ease-snap: cubic-bezier(0.2, 0.9, 0.1, 1);

  /* Every decorative loop multiplies its duration by this. The reduced-motion
     block sets it to 0 so a single token stops the whole ambient layer. */
  --loop: 1;

  --focus: var(--accent-2);
  --focus-w: 3px;
  --focus-gap: 3px;

  color-scheme: dark;
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--t-md);
  line-height: var(--lh-body);
  color: var(--ink);
  background-color: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg {
  max-width: 100%;
}

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

/* --------------------------------------------------------------------------
   3. The ambient background

   Three fixed, pointer-inert layers behind everything. Nothing on a QuizBlitz
   screen is ever completely still, and this is where that starts.

   Cost control: only `transform` and `opacity` are animated, so each layer is
   composited on the GPU and never triggers layout or paint. No filter, no
   box-shadow, no background-position on a full-screen box.
   -------------------------------------------------------------------------- */
body::before,
body::after,
html::before {
  content: "";
  position: fixed;
  /* DIRECTION-NEUTRAL: symmetric full-bleed. Nothing to flip. */
  inset: -30vmax;
  z-index: -2;
  pointer-events: none;
}

/* Layer 1 — the slow colour field. */
body::before {
  background:
    radial-gradient(42vmax 42vmax at 18% 18%, rgba(139, 92, 246, 0.32), transparent 62%),
    radial-gradient(38vmax 38vmax at 84% 12%, rgba(34, 211, 238, 0.20), transparent 62%),
    radial-gradient(46vmax 46vmax at 72% 88%, rgba(199, 15, 70, 0.22), transparent 64%),
    radial-gradient(40vmax 40vmax at 12% 82%, rgba(55, 190, 172, 0.16), transparent 64%),
    linear-gradient(160deg, var(--bg) 0%, var(--bg-2) 55%, var(--bg) 100%);
  animation: drift calc(34s * var(--loop)) var(--ease-inout) infinite alternate;
  will-change: transform;
}

/* Layer 2 — a counter-rotating aurora, so the two never beat in sync. */
html::before {
  z-index: -3;
  background:
    radial-gradient(30vmax 22vmax at 50% 8%, rgba(43, 94, 182, 0.22), transparent 70%),
    radial-gradient(26vmax 20vmax at 20% 65%, rgba(255, 219, 41, 0.07), transparent 70%);
  animation: drift2 calc(52s * var(--loop)) var(--ease-inout) infinite alternate;
  will-change: transform;
  opacity: 0.9;
}

/* Layer 3 — grain. A 140px inline SVG turbulence tile: no network, no image
   file, and it hides the banding a wide dark gradient would otherwise show. */
body::after {
  z-index: -1;
  opacity: 0.15;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
  background-size: 180px 180px;
  animation: grainShift calc(7s * var(--loop)) steps(4, end) infinite;
  will-change: transform;
}

@keyframes drift {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(2.5%, -2%, 0) scale(1.06); }
  100% { transform: translate3d(-2.5%, 2.5%, 0) scale(1.03); }
}

@keyframes drift2 {
  0%   { transform: translate3d(0, 0, 0) scale(1.04) rotate(0deg); }
  100% { transform: translate3d(3%, 2%, 0) scale(1) rotate(6deg); }
}

/* Sub-pixel jitter: enough to keep the grain from looking like a printed
   texture, small enough that nobody consciously sees it move. */
@keyframes grainShift {
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(-1%, 1%, 0); }
  50%  { transform: translate3d(1%, -0.5%, 0); }
  75%  { transform: translate3d(-0.5%, -1%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* --------------------------------------------------------------------------
   4. Screens & transitions
   -------------------------------------------------------------------------- */
.app {
  min-height: 100dvh;
  display: grid;
  grid-template-rows: 1fr;
  /* minmax(0,1fr), not the implicit `auto`: an auto column is max-content
     sized and lets a long question line push the layout wider than the
     viewport instead of wrapping. */
  grid-template-columns: minmax(0, 1fr);
  position: relative;
}

.screen {
  grid-area: 1 / 1;
  display: none;
  flex-direction: column;
  min-width: 0;
  min-height: 100dvh;
  padding: var(--pad-screen);
  opacity: 0;
  /* Enter/leave motion is upward-only: a downward translate on a 100dvh box
     would grow the document and flash a scrollbar mid-transition. */
  transform: translateY(-14px) scale(0.985);
  transition:
    opacity var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

.screen.is-active {
  display: flex;
  opacity: 1;
  transform: none;
}

.screen.is-leaving {
  display: flex;
  opacity: 0;
  transform: translateY(-20px) scale(0.99);
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   5. Type
   -------------------------------------------------------------------------- */
h1, h2, h3 {
  margin: 0;
  line-height: var(--lh-tight);
  letter-spacing: -0.03em;
  font-weight: 850;
  text-wrap: balance;
}

p { margin: 0; }

.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0.45ch;
  font-size: var(--t-sm);
  font-weight: 900;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
}

.brand em {
  font-style: normal;
  background: linear-gradient(96deg, var(--a0-lite), var(--a2) 45%, var(--a1-lite));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.eyebrow {
  margin: 0;
  font-size: var(--t-2xs);
  font-weight: 750;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.muted { color: var(--ink-dim); }
.tabnum { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------------------------------
   6. Focus

   One visible ring, everywhere, on every focusable thing — including elements
   a page may have made focusable after this file was written. :focus-visible
   only, so a mouse click never leaves a ring behind, but a Tab always does.
   -------------------------------------------------------------------------- */
:focus-visible {
  outline: var(--focus-w) solid var(--focus);
  outline-offset: var(--focus-gap);
  border-radius: var(--r-xs);
}

/* On a saturated answer tile the cyan ring would fight the fill, so the ring
   there is the tile's own ink colour, drawn inside the rounded corner. */
.choice:focus-visible,
.ans:focus-visible {
  outline: 4px solid var(--ink-on);
  outline-offset: -6px;
  border-radius: inherit;
}

/* --------------------------------------------------------------------------
   7. Buttons
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--surface-2);
  --btn-fg: var(--ink);
  appearance: none;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xl);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font: inherit;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1.2;
  padding: 0.72em 1.6em;
  font-size: var(--t-md);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition:
    transform var(--dur-1) var(--ease-spring),
    filter var(--dur-2) var(--ease),
    box-shadow var(--dur-2) var(--ease),
    opacity var(--dur-2) var(--ease);
  box-shadow: var(--shadow-md);
  touch-action: manipulation;
}

.btn:hover:not(:disabled) { filter: brightness(1.12); transform: translateY(-2px); }
.btn:active:not(:disabled) { transform: translateY(1px) scale(0.985); filter: brightness(0.94); }

.btn:disabled {
  opacity: 0.38;
  cursor: not-allowed;
  box-shadow: none;
}

/*
 * The primary button is the one thing on the lobby screen that has to be
 * findable from the back of the room, so it gets the only gradient that
 * moves. --accent itself is too light to carry white text (4.23:1), so the
 * gradient runs from --accent-deep (5.7:1) into --a0 (5.9:1).
 */
.btn-primary {
  --btn-bg: linear-gradient(120deg, var(--accent-deep), var(--accent) 45%, var(--a0));
  border-color: transparent;
  color: #fff;
  background-size: 220% 100%;
  box-shadow: 0 14px 40px rgba(139, 92, 246, 0.40), var(--inset-top);
  animation: hueSlide calc(9s * var(--loop)) linear infinite;
}

.btn-primary:disabled { animation: none; }

/* A slow specular wipe. Transform-only, clipped by the button's overflow. */
.btn-primary::after {
  content: "";
  position: absolute;
  /* DELIBERATELY PHYSICAL. A specular wipe is a light source, not a reading
     order: light on this product comes from the upper left in every language
     (see every `linear-gradient(165deg, ...)` fill). Mirroring the wipe alone
     while the 19 gradient angles stayed put would look like a bug, and
     mirroring all of them would relight the whole UI for no benefit. */
  inset: 0 auto 0 -60%;
  width: 45%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.30), transparent);
  transform: translateX(0) skewX(-18deg);
  animation: sheen calc(4.6s * var(--loop)) var(--ease-inout) infinite;
  pointer-events: none;
}

.btn-primary:disabled::after { animation: none; opacity: 0; }

.btn-ghost {
  --btn-bg: transparent;
  border-color: var(--line);
  color: var(--ink-dim);
  box-shadow: none;
}

.btn-ghost:hover:not(:disabled) { color: var(--ink); border-color: var(--line-strong); }

/*
 * ADDITIVE (auth + admin). The quiet sibling of .btn-primary, for the pages
 * where the primary action is a form submit rather than the loudest object in
 * a room: no gradient slide, no sheen, nothing that moves on its own.
 *
 * The fill is answer 1's royal blue, so the one saturated control on a
 * sign-in page is a colour the product already owns. Deliberately NOT the
 * crimson of answer 0: --danger-deep (#c8102e) is within a hair of --a0, and
 * a red submit button sitting under a red error line is a sentence nobody can
 * read. White ink measures 6.36:1 on --a1 and 12.0:1 on --a1-dark, so the
 * label clears 4.5:1 at every point of the ramp; the fill itself clears 3:1
 * against --bg, so the button's edge is findable as a graphic.
 *
 * .btn-primary is untouched and still owns the lobby and the game screens.
 */
.btn-brand {
  --btn-bg: linear-gradient(135deg, var(--a1), var(--a1-dark));
  border-color: transparent;
  color: #fff;
  box-shadow: 0 12px 30px rgba(47, 87, 198, 0.34), var(--inset-top);
}

.btn-brand:hover:not(:disabled) {
  box-shadow: 0 16px 38px rgba(47, 87, 198, 0.46), var(--inset-top);
}

.btn-brand:disabled { box-shadow: none; }

.btn-huge {
  font-size: var(--t-xl);
  padding: 0.62em 2.1em;
}

@keyframes hueSlide {
  0%   { background-position: 0% center; }
  50%  { background-position: 100% center; }
  100% { background-position: 0% center; }
}

@keyframes sheen {
  0%, 62% { transform: translateX(0) skewX(-18deg); }
  100%    { transform: translateX(420%) skewX(-18deg); }
}

/* --------------------------------------------------------------------------
   8. Cards & panels
   -------------------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--shadow-md);
}

.panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-4);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.wrap-narrow {
  width: 100%;
  max-width: 34rem;
  margin: 0 auto;
}

/* --------------------------------------------------------------------------
   9. Answer choices — shape + colour + ink polarity

   Shared by the host's display tiles and the player's keycaps. Both pages
   restyle the surface on top of this; what they must NOT change is which
   shape goes with which colour, or the ink polarity below.
   -------------------------------------------------------------------------- */
.choices {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3);
}

.choice,
.ans {
  --c: var(--a0);
  --c-dark: var(--a0-dark);
  --ink-on: #fff;
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-4);
  min-height: clamp(4.5rem, 15vmin, 11rem);
  border: 0;
  border-radius: var(--r-md);
  background: linear-gradient(165deg, var(--c), var(--c-dark));
  color: var(--ink-on);
  font: inherit;
  font-weight: 800;
  font-size: var(--t-lg);
  line-height: var(--lh-snug);
  /* start, not left: the 2x2 GRID is pinned LTR (§16) but the inside of a
     tile is prose and follows the tile's own direction. */
  text-align: start;
  cursor: pointer;
  overflow: hidden;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.26),
    inset 0 -3px 0 rgba(0, 0, 0, 0.22),
    0 10px 26px rgba(0, 0, 0, 0.42);
  transition:
    transform var(--dur-1) var(--ease-spring),
    filter var(--dur-2) var(--ease),
    opacity var(--dur-3) var(--ease),
    box-shadow var(--dur-2) var(--ease);
  touch-action: manipulation;
}

/*
 * Specular highlight, and the only thing painted over an answer fill. It
 * stops at 26% of the tile height on purpose: the label is vertically
 * centred, so the ink always sits on the raw fill and the measured contrast
 * below is the contrast that actually ships. It spans the whole tile so a
 * page that overrides its `background` still gets a full-bleed element.
 */
.choice::after,
.ans::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.17), transparent 26%);
  pointer-events: none;
}

.choice:hover:not(:disabled),
.ans:hover:not(:disabled) { filter: brightness(1.07); }

.choice:active:not(:disabled),
.choice.is-pressed,
.ans:active:not(:disabled),
.ans.is-pressed {
  transform: translateY(3px) scale(0.982);
  filter: brightness(0.9);
  box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.35);
}

/*
 * Identity. --c / --c-dark are the fill; --ink-on is the only thing that may
 * be drawn on top of it. a2 and a3 are light fills and take near-black ink:
 * white on them measures 1.4:1 and 2.6:1, which is unusable at any size.
 */
.choice-0, [data-a="0"] { --c: var(--a0); --c-dark: var(--a0-dark); }
.choice-1, [data-a="1"] { --c: var(--a1); --c-dark: var(--a1-dark); }
.choice-2, [data-a="2"] { --c: var(--a2); --c-dark: var(--a2-dark); --ink-on: var(--ink-on-light); }
.choice-3, [data-a="3"] { --c: var(--a3); --c-dark: var(--a3-dark); --ink-on: var(--ink-on-light); }

/* Belt and braces for the reveal chip in the player layer, which declares its
   own `color` on a lower-specificity selector. */
.chip.choice-0, .chip.choice-1, .chip.choice-2, .chip.choice-3 { color: var(--ink-on); }
.chip.choice-0 .shape, .chip.choice-1 .shape,
.chip.choice-2 .shape, .chip.choice-3 .shape { fill: currentColor; }

.choice .shape,
.ans .shape {
  flex: 0 0 auto;
  width: clamp(1.8rem, 4.6vmin, 3.4rem);
  height: clamp(1.8rem, 4.6vmin, 3.4rem);
  fill: currentColor;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.28));
}

.choice .label,
.ans .label { min-width: 0; overflow-wrap: anywhere; }

/* Reveal states (both views) */
.choice.is-dim,
.ans.is-dim { opacity: 0.3; filter: grayscale(0.65); }

.choice.is-correct,
.ans.is-correct {
  opacity: 1;
  filter: none;
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.35),
    0 0 0 4px #fff,
    0 0 46px rgba(255, 255, 255, 0.5);
}

.choice.is-picked { outline: 4px solid var(--ink-on); outline-offset: -4px; }

/* --------------------------------------------------------------------------
   9b. The answer motif — ADDITIVE (auth.html, admin.html)

   The four answer tiles, shrunk to a mark. The pages a visitor meets OUTSIDE a
   game — sign in, reset a password, admin — have no PIN, no timer and no
   choices, so this is what carries the product's identity there: the same four
   shapes, in the same order, drawn with the same fill and the same ink
   polarity as the tiles they will tap five minutes later.

   Markup:  <span class="motif-tile" data-a="0"><svg class="shape">…</svg></span>

   The defaults sit on the CONTAINER, never on the tile: `.motif-tile` and
   `[data-a="2"]` have equal specificity and §9 is the earlier rule, so a
   default declared on the tile itself would beat the very rule it is meant to
   fall back to and the light pair would end up with white glyphs on gold.

   Nothing in the host or player view uses this; both were written before it
   existed and neither is affected by it.
   -------------------------------------------------------------------------- */
.motif {
  --c: var(--a0);
  --c-dark: var(--a0-dark);
  --ink-on: #fff;
  display: flex;
  gap: var(--s-2);
}

.motif-tile {
  position: relative;
  display: grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--r-sm);
  background: linear-gradient(165deg, var(--c), var(--c-dark));
  color: var(--ink-on);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    inset 0 -2px 0 rgba(0, 0, 0, 0.22),
    var(--shadow-sm);
  animation: motifBob calc(3.6s * var(--loop)) var(--ease-inout) infinite;
}

.motif-tile .shape { width: 50%; height: 50%; fill: currentColor; }

.motif-tile:nth-child(2) { animation-delay: 200ms; }
.motif-tile:nth-child(3) { animation-delay: 400ms; }
.motif-tile:nth-child(4) { animation-delay: 600ms; }

@keyframes motifBob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-0.3rem) rotate(4deg); }
}

/* Its own block rather than a name added to §REDUCED MOTION's list, so that
   list stays exactly as the host and player pages left it. */
@media (prefers-reduced-motion: reduce) {
  .motif-tile { animation: none !important; transform: none !important; }
}

/* --------------------------------------------------------------------------
   9c. .type-desk — ADDITIVE (auth.html, admin.html)

   RESPONSIVE EXTREMES below re-cuts the entire type ramp above 2200px, because
   1vmin on a 2160px-tall projector is 21.6px and a caption at the desk-sized
   coefficients would be invisible from the third row of a hall.

   Sign-in, password reset and admin are never on a projector. They are on a
   desk, at whatever width the window happens to be, and on a 2560px monitor
   the doubled ramp puts the wordmark at 5.2rem — about 670px of tracked capitals
   in a 21rem rail, which overflows the column and runs under the card.

   Re-declaring the desk values on a container overrides the :root rule for
   everything inside it, at every width: identical below 2200px, and the desk
   scale above it. One class rather than a copy of the ramp in each page.
   -------------------------------------------------------------------------- */
.type-desk {
  --t-3xs: clamp(0.62rem, 0.5rem + 0.32vmin, 0.9rem);
  --t-2xs: clamp(0.7rem, 0.56rem + 0.42vmin, 1.05rem);
  --t-xs: clamp(0.78rem, 0.62rem + 0.55vmin, 1.2rem);
  --t-sm: clamp(0.88rem, 0.7rem + 0.72vmin, 1.4rem);
  --t-md: clamp(1rem, 0.8rem + 0.9vmin, 1.65rem);
  --t-lg: clamp(1.15rem, 0.88rem + 1.3vmin, 2.1rem);
  --t-xl: clamp(1.4rem, 1rem + 2vmin, 3rem);
  --t-2xl: clamp(1.75rem, 1.15rem + 3.2vmin, 4.3rem);
  --t-3xl: clamp(2.1rem, 1.3rem + 4.6vmin, 5.8rem);
  --t-hero: clamp(2.6rem, 1.2rem + 8vmin, 9rem);
  --t-pin: clamp(3.2rem, 0.8rem + 15vmin, 15rem);
}

/* --------------------------------------------------------------------------
   10. Connection pill
   -------------------------------------------------------------------------- */
.pill {
  position: fixed;
  /* Logical: the pill follows the reading corner. `.snd` is anchored to
     inset-inline-start, so the two swap corners together and never collide.
     play.html re-anchors this to the top centre; a physical `right: auto`
     there still cancels this, because logical and physical inset properties
     for the same side cascade against each other. */
  inset-inline-end: var(--s-3);
  bottom: var(--s-3);
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 0.6ch;
  padding: 0.5em 1.05em;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: rgba(10, 10, 22, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--ink-dim);
  font-size: var(--t-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity var(--dur-3) var(--ease), transform var(--dur-3) var(--ease);
}

.pill.is-shown { opacity: 1; transform: none; }

.pill .dot {
  width: 0.62em;
  height: 0.62em;
  border-radius: 50%;
  background: var(--gold);
  animation: blip calc(1.1s * var(--loop)) var(--ease-inout) infinite;
}

.pill.is-down .dot { background: var(--danger); }

/* --------------------------------------------------------------------------
   11. Toast
   -------------------------------------------------------------------------- */
.toast {
  position: fixed;
  /* DIRECTION-NEUTRAL — do not "finish the job" and make this logical.
     `left:50%` + `translate(-50%)` is the centring idiom; inset-inline-start
     would flip the anchor while the translate stayed physical and push the
     toast half a width off the screen under RTL. Same for .pill in play.html
     and the two overlays in play.html/host.html. */
  left: 50%;
  top: var(--s-3);
  z-index: 60;
  transform: translate(-50%, -140%);
  max-width: min(90vw, 44rem);
  padding: 0.85em 1.4em;
  border-radius: var(--r-md);
  /* --danger is an INK token: white on it is 3.1:1. A toast is a fill, so it
     uses the deep pair, where white measures 5.9:1. */
  background: linear-gradient(120deg, var(--danger-deep), var(--danger-deeper));
  color: #fff;
  font-weight: 800;
  font-size: var(--t-sm);
  box-shadow: var(--shadow-lg);
  transition: transform var(--dur-4) var(--ease-spring), opacity var(--dur-3) var(--ease);
  opacity: 0;
}

.toast.is-shown { transform: translate(-50%, 0); opacity: 1; }

/* --------------------------------------------------------------------------
   12. Motion system

   A small vocabulary, used everywhere, so the whole app moves in one accent.

     popIn      spring entrance for something that lands  (public)
     riseIn     content arriving from below               (public)
     pulseGlow  a slow attention loop                     (public)
     springUp   a value that changed and wants to be seen
     flashIn    a hard, fast arrival for the reveal
     shimmer    a gradient travelling across text
     blip       the live-connection dot

   Anything that repeats forever multiplies its duration by var(--loop), so
   the reduced-motion block can stop the ambient layer with one token.
   -------------------------------------------------------------------------- */
@keyframes popIn {
  0%   { opacity: 0; transform: scale(0.55) translateY(14px); }
  62%  { opacity: 1; transform: scale(1.09) translateY(0); }
  100% { opacity: 1; transform: scale(1); }
}

@keyframes riseIn {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

@keyframes pulseGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  50%      { box-shadow: 0 0 44px 6px rgba(255, 255, 255, 0.22); }
}

@keyframes springUp {
  0%   { transform: translateY(10px) scale(0.86); opacity: 0; }
  55%  { transform: translateY(0) scale(1.12); opacity: 1; }
  100% { transform: none; opacity: 1; }
}

@keyframes flashIn {
  0%   { opacity: 0; transform: scale(1.16); }
  100% { opacity: 1; transform: none; }
}

/* Travels exactly one tile width, so the loop point is seamless. Pair it with
   `background-size: 160% 100%` on whatever uses it. */
@keyframes shimmer {
  from { background-position: 0% center; }
  to   { background-position: 160% center; }
}

@keyframes blip {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.35; transform: scale(0.7); }
}

/* Utility hooks, for markup that wants the house motion without a component. */
.u-pop { animation: popIn var(--dur-4) var(--ease-spring) both; }
.u-rise { animation: riseIn var(--dur-4) var(--ease) both; }
.u-spring { animation: springUp var(--dur-4) var(--ease-spring) both; }
.u-stagger { animation-delay: calc(var(--i, 0) * 60ms); }

/* ==========================================================================
   HOST VIEW — big screen / projector
   ========================================================================== */

/* --- Common host chrome --------------------------------------------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  flex: 0 0 auto;
  padding-bottom: var(--s-3);
  /* The console's top bar now carries account links (Your quizzes, Admin,
     Sign in). Without wrapping they push the page wider than a 360px phone,
     which is a horizontal scrollbar on every screen, not just this one. */
  flex-wrap: wrap;
}

.topbar-right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--s-3);
  /* Each link may shrink to its text; nothing here may set the page width. */
  min-width: 0;
}

.stage {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
  min-height: 0;
}

.footbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding-top: var(--s-3);
}

/* --- Screen: setup -------------------------------------------------------- */
.setup-head {
  text-align: center;
  margin-bottom: var(--s-5);
}

.setup-head h1 {
  font-size: var(--t-3xl);
  background: linear-gradient(100deg, #fff, var(--a2) 40%, var(--a0-lite) 70%, var(--a1-lite));
  /* 160%, not 260%: a wider window means the four identity colours are all
     visible in the headline at every moment of the sweep, instead of it
     passing through long stretches of a single flat hue. */
  background-size: 160% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  animation: shimmer calc(11s * var(--loop)) linear infinite;
}

.setup-head p {
  margin: var(--s-2) 0 0;
  font-size: var(--t-md);
  color: var(--ink-dim);
}

/* F2 — the Save-results opt-out (§2.2.8). A real <label> wrapping a real
   checkbox: it is keyboard-reachable, the whole strip is a hit target, and
   there is nothing custom to get wrong at 360px or in a forced-colours mode. */
.record-opt {
  display: inline-grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0 var(--s-2);
  margin-top: var(--s-4);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  text-align: start;
  cursor: pointer;
  max-width: 32rem;
}

.record-opt input {
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--accent);
  cursor: pointer;
}

.record-opt span {
  font-size: var(--t-md);
  color: var(--ink);
}

.record-opt small {
  grid-column: 2;
  font-size: var(--t-sm);
  color: var(--ink-dim);
}

.record-opt input:disabled,
.record-opt:has(input:disabled) {
  cursor: default;
  opacity: 0.55;
}

/* Shown only when recording is OFF — the default state is silent, so the
   projector never acquires a permanent nag. */
.record-off {
  color: var(--gold);
}

/* F2 — the gameover "Saved · 28 players · 15 questions" block. Hidden until
   the `saved` frame arrives, which is always after the podium. */
.saved-block {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  margin-top: var(--s-4);
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink-dim);
  font-size: var(--t-md);
}

.saved-block > span {
  color: var(--ink);
}

.quiz-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  gap: var(--s-3);
  max-width: 84rem;
  width: 100%;
  margin: 0 auto;
  overflow-y: auto;
  padding: 2px;
}

.quiz-card {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  align-items: flex-start;
  text-align: start;
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  animation: riseIn var(--dur-4) var(--ease) both;
  transition:
    transform var(--dur-2) var(--ease-spring),
    border-color var(--dur-2) var(--ease),
    background var(--dur-2) var(--ease);
}

.quiz-card::before {
  content: "";
  position: absolute;
  /* The stripe marks the card's LEADING edge, so it moves with the text. */
  inset-block: 0;
  inset-inline-start: 0;
  inset-inline-end: auto;
  width: 5px;
  background: linear-gradient(180deg, var(--a0), var(--a2), var(--a3), var(--a1));
  opacity: 0.9;
}

.quiz-card:hover,
.quiz-card:focus-visible {
  transform: translateY(-5px);
  border-color: var(--line-strong);
  background: var(--surface-2);
}

.quiz-card:active { transform: translateY(-1px) scale(0.99); }

.quiz-card .qc-title {
  font-size: var(--t-lg);
  font-weight: 850;
  letter-spacing: -0.02em;
  line-height: var(--lh-snug);
  overflow-wrap: anywhere;
}

.quiz-card .qc-meta {
  display: inline-flex;
  align-items: center;
  gap: 0.5ch;
  padding: 0.3em 0.8em;
  border-radius: var(--r-pill);
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-size: var(--t-3xs);
  font-weight: 750;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

.quiz-card .qc-go {
  margin-top: auto;
  font-size: var(--t-2xs);
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-2);
}

.empty-note {
  grid-column: 1 / -1;
  text-align: center;
  padding: var(--s-6);
  color: var(--ink-faint);
  font-size: var(--t-md);
  font-weight: 650;
}

/* --- Screen: lobby -------------------------------------------------------- */
.lobby-grid {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  gap: var(--s-5);
  align-items: center;
  flex: 1 1 auto;
  min-height: 0;
}

@media (max-width: 900px) {
  .lobby-grid { grid-template-columns: 1fr; align-items: start; }
}

.pin-block { text-align: center; }

.pin-label {
  font-size: var(--t-2xs);
  font-weight: 800;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--s-2);
}

/* The single biggest thing in the room. */
.pin {
  font-family: var(--mono);
  font-size: var(--t-pin);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: 0.06em;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(100deg, #fff 0%, var(--a2) 38%, var(--a0-lite) 62%, var(--a1-lite) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 12px 40px rgba(139, 92, 246, 0.45));
  animation: popIn var(--dur-5) var(--ease-spring) both;
  word-break: break-all;
}

.join-url {
  margin-top: var(--s-3);
  font-size: var(--t-lg);
  font-weight: 750;
  color: var(--ink-dim);
}

.join-url b {
  color: var(--ink);
  font-family: var(--mono);
  font-weight: 700;
  overflow-wrap: anywhere;
}

/*
 * The QR sits on the dark lobby panel but is drawn dark-on-light inside its
 * own card: that is what phone cameras decode reliably, and a code that looks
 * good and does not scan is not a feature.
 */
.qr-card {
  margin: var(--s-3) auto 0;
  width: clamp(9rem, 22vmin, 17rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Roomy enough that a page which draws a white quiet-zone ring around the
     image (host.html does, 6px) cannot collide with the caption. */
  gap: var(--s-3);
}

.qr-card[hidden] { display: none; }

.qr-img {
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  display: block;
  border-radius: var(--r-sm);
  background: #fff;
  /* Crisp module edges when the SVG is scaled up on a projector. */
  image-rendering: pixelated;
}

.qr-hint {
  font-size: var(--t-2xs);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.roster {
  display: flex;
  flex-direction: column;
  min-height: 0;
  gap: var(--s-3);
  padding: var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  max-height: 68vh;
}

.roster-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}

.roster-count {
  font-size: var(--t-2xl);
  font-weight: 900;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.roster-count span {
  font-size: 0.42em;
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-inline-start: 0.6ch;
}

.nicks {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: var(--s-2);
  overflow-y: auto;
  min-height: clamp(6rem, 22vmin, 16rem);
  padding: 2px;
}

.nick {
  padding: 0.45em 1em;
  border-radius: var(--r-pill);
  background: linear-gradient(150deg, var(--surface-3), var(--surface));
  border: 1px solid var(--line-strong);
  font-size: var(--t-sm);
  font-weight: 800;
  letter-spacing: -0.01em;
  max-width: 100%;
  overflow-wrap: anywhere;
  animation: popIn var(--dur-4) var(--ease-spring) both;
}

/* Four rotating identity edges, so a filling roster reads as a crowd rather
   than a list. Colour only — the chip is legible without it. */
.nick:nth-child(4n + 1) { box-shadow: inset 0 0 0 1px var(--a0-lite); }
.nick:nth-child(4n + 2) { box-shadow: inset 0 0 0 1px var(--a1-lite); }
.nick:nth-child(4n + 3) { box-shadow: inset 0 0 0 1px var(--a2); }
.nick:nth-child(4n + 4) { box-shadow: inset 0 0 0 1px var(--a3); }

.waiting {
  color: var(--ink-faint);
  font-size: var(--t-sm);
  font-weight: 650;
  padding: 0.4em 0.2em;
}

/* --- Screen: question ----------------------------------------------------- */
.q-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-4);
  flex: 0 0 auto;
  margin-bottom: var(--s-3);
}

.q-text {
  font-size: var(--t-2xl);
  font-weight: 850;
  letter-spacing: -0.025em;
  line-height: var(--lh-tight);
  text-align: center;
  overflow-wrap: anywhere;
}

.q-index {
  font-size: var(--t-2xs);
  font-weight: 800;
  letter-spacing: var(--tracking-cap);
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* Countdown ring. stroke-dashoffset is animated by JS; the only thing that
   transitions here is the sweep and the colour, never geometry. */
.ring {
  position: relative;
  width: clamp(5rem, 13vmin, 10rem);
  height: clamp(5rem, 13vmin, 10rem);
  flex: 0 0 auto;
}

/* DIRECTION-NEUTRAL: the countdown starts at twelve o'clock and sweeps
   clockwise. A clock face does not mirror with the reading order, in any
   locale, so this rotation is left physical on purpose. */
.ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }

.ring .ring-track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.11);
  stroke-width: 10;
}

.ring .ring-bar {
  fill: none;
  stroke: var(--accent-2);
  stroke-width: 10;
  stroke-linecap: round;
  transition: stroke-dashoffset 520ms linear, stroke var(--dur-4) var(--ease);
}

/* Colour is not the only warning: the ring also thumps, and the number is
   already counting down in the middle of it. */
.ring.is-warn .ring-bar { stroke: var(--a2); }
.ring.is-danger .ring-bar { stroke: var(--a0-lite); }

.ring-num {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: var(--t-xl);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.04em;
}

.ring.is-danger .ring-num { color: var(--a0-lite); }

/* Answered counter */
.answered {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15em;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface);
  min-width: clamp(5rem, 12vmin, 9rem);
}

.answered .n {
  font-size: var(--t-2xl);
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.04em;
}

.answered .n em {
  font-style: normal;
  color: var(--ink-faint);
  font-size: 0.5em;
}

.answered .cap {
  font-size: var(--t-3xs);
  font-weight: 800;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* Host choices are display-only and fill the stage. */
.choices.is-display {
  flex: 1 1 auto;
  min-height: 0;
  grid-template-rows: 1fr 1fr;
  max-height: 62vh;
}

.choices.is-display .choice {
  cursor: default;
  min-height: 0;
  justify-content: center;
  text-align: center;
}

.choices.is-display .choice:hover { filter: none; }

/* --- Screen: reveal ------------------------------------------------------- */
.reveal-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: var(--s-5);
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
}

@media (max-width: 900px) {
  .reveal-wrap { grid-template-columns: 1fr; }
}

/* Bar chart. Bars grow from nothing: the height transition IS the reveal. */
.bars {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-2);
  align-items: end;
  flex: 1 1 auto;
  min-height: clamp(11rem, 40vmin, 30rem);
}

.bar-col {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  gap: var(--s-2);
  height: 100%;
}

.bar-n {
  font-size: var(--t-xl);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

.bar {
  --c: var(--a0);
  --c-dark: var(--a0-deep);
  width: 100%;
  min-height: 6px;
  height: 0;
  border-radius: 12px 12px 4px 4px;
  background: linear-gradient(180deg, var(--c), var(--c-dark));
  box-shadow: var(--inset-top);
  transition: height var(--dur-5) var(--ease);
  /* A bar that did not win is quiet, not anonymous: enough colour survives
     for the room to still see which shape it belongs to. */
  opacity: 0.52;
  filter: grayscale(0.35);
}

/* Bars carry no text, so they use the deep pair for real vertical depth. */
.bar-0 { --c: var(--a0); --c-dark: var(--a0-deep); }
.bar-1 { --c: var(--a1); --c-dark: var(--a1-deep); }
.bar-2 { --c: var(--a2); --c-dark: var(--a2-deep); }
.bar-3 { --c: var(--a3); --c-dark: var(--a3-deep); }

.bar-col.is-correct .bar {
  opacity: 1;
  filter: none;
  /* An outline, not a box-shadow: pulseGlow animates box-shadow and would
     otherwise win and erase the ring. */
  outline: 3px solid #fff;
  outline-offset: 0;
  animation: pulseGlow calc(2.2s * var(--loop)) var(--ease-inout) infinite;
}

.bar-foot {
  display: flex;
  align-items: center;
  gap: 0.45ch;
  min-height: 2.2em;
  font-size: var(--t-2xs);
  font-weight: 750;
  color: var(--ink-dim);
  text-align: center;
  /* break-word, not anywhere: `anywhere` also shrinks the column's min-content
     size, so at 360px the labels split mid-word ("Mercur / y") long before
     they had to. This still breaks a genuinely unbreakable word. */
  overflow-wrap: break-word;
}

.bar-foot .shape {
  width: clamp(1rem, 2.2vmin, 1.6rem);
  height: clamp(1rem, 2.2vmin, 1.6rem);
  flex: 0 0 auto;
}

.bar-col.is-correct .bar-foot { color: var(--ink); }

.check {
  display: inline-grid;
  place-items: center;
  width: 1.5em;
  height: 1.5em;
  border-radius: 50%;
  background: var(--ok);
  color: var(--on-ok);
  font-weight: 900;
  flex: 0 0 auto;
  animation: popIn var(--dur-4) var(--ease-spring) both;
}

/* A shape drawn ON the dark panel uses the lite ramp: the tile-fill values
   are tuned for ink contrast, not for standing out against near-black. */
.bar-shape-0 .shape { fill: var(--a0-lite); }
.bar-shape-1 .shape { fill: var(--a1-lite); }
.bar-shape-2 .shape { fill: var(--a2); }
.bar-shape-3 .shape { fill: var(--a3); }

/* --- Leaderboard ---------------------------------------------------------- */
.board {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-height: 0;
  overflow-y: auto;
}

.board-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line);
  background: var(--surface);
  animation: riseIn var(--dur-3) var(--ease) both;
}

.board-row .rk {
  font-size: var(--t-sm);
  font-weight: 900;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
  min-width: 1.8ch;
  /* end, not right: the rank sits against the nickname on either side. */
  text-align: end;
}

.board-row .nk {
  font-size: var(--t-lg);
  font-weight: 800;
  overflow-wrap: anywhere;
}

.board-row .sc {
  font-size: var(--t-lg);
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.board-row.rk-1 { border-color: rgba(255, 211, 92, 0.65); background: rgba(255, 211, 92, 0.1); }
.board-row.rk-1 .rk, .board-row.rk-1 .sc { color: var(--gold); }
.board-row.rk-2 { border-color: rgba(207, 214, 230, 0.45); }
.board-row.rk-2 .rk { color: var(--silver); }
.board-row.rk-3 { border-color: rgba(232, 162, 106, 0.45); }
.board-row.rk-3 .rk { color: var(--bronze); }

/* --- Screen: game over ---------------------------------------------------- */
.podium {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: end;
  gap: var(--s-3);
  max-width: 62rem;
  width: 100%;
  margin: 0 auto var(--s-5);
}

.plinth {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-2);
  animation: riseIn var(--dur-5) var(--ease) both;
}

.plinth .who {
  font-size: var(--t-lg);
  font-weight: 900;
  letter-spacing: -0.02em;
  text-align: center;
  overflow-wrap: anywhere;
  max-width: 100%;
}

.plinth .pts {
  font-size: var(--t-xs);
  font-weight: 800;
  color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
}

/* Crown above the winner's plinth (inline SVG, never an emoji font). */
.plinth .crown {
  width: clamp(1.6rem, 4.6vmin, 3.4rem);
  height: clamp(1.6rem, 4.6vmin, 3.4rem);
  fill: var(--gold);
  filter: drop-shadow(0 3px 10px rgba(255, 211, 92, 0.5));
}

.plinth .block {
  width: 100%;
  border-radius: var(--r-md) var(--r-md) 0 0;
  border: 1px solid var(--line-strong);
  border-bottom: 0;
  display: grid;
  place-items: center;
  font-size: var(--t-3xl);
  font-weight: 900;
  color: rgba(0, 0, 0, 0.55);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.28);
}

.plinth-1 { order: 2; }
.plinth-2 { order: 1; }
.plinth-3 { order: 3; }

.plinth-1 .block {
  height: clamp(7rem, 24vmin, 17rem);
  background: linear-gradient(180deg, var(--gold-lite), var(--gold) 45%, var(--gold-deep));
  box-shadow: 0 0 60px rgba(255, 211, 92, 0.35);
}
.plinth-2 .block {
  height: clamp(5rem, 17vmin, 12rem);
  background: linear-gradient(180deg, var(--silver-lite), var(--silver) 45%, var(--silver-deep));
}
.plinth-3 .block {
  height: clamp(4rem, 13vmin, 9.5rem);
  background: linear-gradient(180deg, var(--bronze-lite), var(--bronze) 45%, var(--bronze-deep));
}

.plinth-1 .who { font-size: var(--t-xl); }

.final-list {
  max-width: 62rem;
  width: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  overflow-y: auto;
  min-height: 0;
}

.gameover-title {
  text-align: center;
  font-size: var(--t-3xl);
  margin-bottom: var(--s-4);
  background: linear-gradient(100deg, var(--a2), #fff 50%, var(--a1-lite));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ==========================================================================
   PLAYER VIEW helpers (the phone page adds its own layer on top)
   ========================================================================== */
.field {
  width: 100%;
  padding: 0.85em 1.1em;
  border-radius: var(--r-md);
  border: 1px solid var(--line-strong);
  background: rgba(255, 255, 255, 0.07);
  color: var(--ink);
  font: inherit;
  font-size: clamp(1rem, 4.5vw, 1.4rem);
  font-weight: 700;
  transition: border-color var(--dur-2) var(--ease), background var(--dur-2) var(--ease);
}

.field::placeholder { color: var(--ink-faint); }
.field:focus { border-color: var(--accent-2); background: rgba(255, 255, 255, 0.1); }
.field:focus-visible { outline: var(--focus-w) solid var(--focus); outline-offset: 2px; }

.big-stat {
  font-size: clamp(2.4rem, 14vw, 5rem);
  font-weight: 900;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

/* ==========================================================================
   RESPONSIVE EXTREMES
   ========================================================================== */

/*
 * A 3840x2160 projector. vmin is 21.6px there, so every fluid step is already
 * pinned to its cap; what is left is to stop the layout from becoming a thin
 * ribbon of content in the middle of a huge screen, and to let the display
 * type actually use the room.
 */
@media (min-width: 2200px) {
  /*
   * The WHOLE ramp is re-cut here, not just the display sizes. On a 2160px-tall
   * screen 1vmin is 21.6px, so the desk-sized coefficients above leave a
   * caption at ~17px — invisible from the third row of a hall. The steps below
   * roughly double the small end while keeping the same rhythm between steps.
   */
  :root {
    --t-3xs: clamp(0.9rem, 0.4rem + 0.55vmin, 1.5rem);
    --t-2xs: clamp(1rem, 0.45rem + 0.72vmin, 1.8rem);
    --t-xs: clamp(1.1rem, 0.5rem + 0.85vmin, 2.1rem);
    --t-sm: clamp(1.25rem, 0.55rem + 1.05vmin, 2.5rem);
    --t-md: clamp(1.4rem, 0.6rem + 1.3vmin, 3rem);
    --t-lg: clamp(1.7rem, 0.7rem + 1.8vmin, 3.9rem);
    --t-xl: clamp(2.2rem, 0.9rem + 2.6vmin, 5.2rem);
    --t-2xl: clamp(2.6rem, 1.15rem + 3.4vmin, 6.4rem);
    --t-3xl: clamp(3.2rem, 1.3rem + 4.6vmin, 8rem);
    --t-hero: clamp(2.6rem, 1.2rem + 8vmin, 12rem);
    --t-pin: clamp(3.2rem, 0.8rem + 15vmin, 20rem);
  }

  .quiz-grid { max-width: 120rem; grid-template-columns: repeat(auto-fill, minmax(26rem, 1fr)); }
  .podium, .final-list { max-width: 92rem; }
  .choices.is-display { max-height: 58vh; }
  .screen { padding: clamp(2.6rem, 3vmin, 5rem); }
}

/*
 * A 360px phone. The shared components are already fluid; these are the two
 * places where a shared rule is simply the wrong shape on a small screen.
 */
@media (max-width: 420px) {
  .choices { gap: 0.5rem; }
  .board-row { gap: 0.5rem; padding: 0.45rem 0.6rem; }
  .toast { max-width: calc(100vw - 1.2rem); font-size: 0.9rem; }
  .pill { inset-inline-end: 0.6rem; bottom: 0.6rem; }
}

/* Short and wide — a laptop in a lecture theatre, or a phone in landscape.
   Height, not width, is the scarce axis. */
@media (max-height: 560px) and (orientation: landscape) {
  .screen { padding-block: 0.6rem; }
  .choices.is-display { max-height: none; }
  .roster { max-height: 78vh; }
  .qr-card { width: clamp(6rem, 16vmin, 11rem); }
}

/* ==========================================================================
   REDUCED MOTION

   Everything decorative stops. What remains is the state itself: a screen
   still swaps, a bar still shows its final height, the countdown ring still
   reads the remaining time — because those carry information, not flourish.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root {
    /* One token collapses every ambient loop that opted into it. */
    --loop: 0;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  /* The ambient background layers: stop them outright rather than run them
     at 0.001ms, which would leave a jump at the end of the first cycle. */
  html::before,
  body::before,
  body::after,
  .btn-primary,
  .btn-primary::after,
  .setup-head h1,
  .pin,
  .pill .dot,
  .bar-col.is-correct .bar,
  .nick,
  .quiz-card,
  .board-row,
  .plinth,
  .check,
  .u-pop,
  .u-rise,
  .u-spring {
    animation: none !important;
  }

  /* …and make sure nothing is stranded mid-entrance by that. */
  .nick,
  .quiz-card,
  .board-row,
  .plinth,
  .check,
  .pin,
  .u-pop,
  .u-rise,
  .u-spring {
    opacity: 1;
    transform: none;
  }

  .btn-primary::after { opacity: 0; }
  .setup-head h1, .pin { background-position: 0 center; }
  .screen { transform: none; }
  .screen.is-leaving { transform: none; }
  .btn:hover:not(:disabled) { transform: none; }
  .quiz-card:hover, .quiz-card:focus-visible { transform: none; }
  .choice:active:not(:disabled), .choice.is-pressed,
  .ans:active:not(:disabled), .ans.is-pressed { transform: none; }

  /* The correct bar keeps a static ring instead of a pulsing glow. */
  .bar-col.is-correct .bar { outline: 3px solid #fff; box-shadow: none; }
}

/* ==========================================================================
   ===== audio: owned by the sound stream; do not interleave =====

   F3 §2.3.5 — the host's sound control. One appended block, tokens only, no
   new custom properties.

   Placement: the bottom of the READING-START edge (inset-inline-start, so
   bottom-left in English and bottom-right in Arabic). .pill is anchored to
   inset-inline-end and .toast is top-centre, so the two corner controls swap
   together and this corner is free on all six host screens in either
   direction — a switch that is somewhere different on each screen is a switch
   nobody finds while a room of thirty is waiting.

   The stack is a column: Enable-sound chip, the four-way menu, then the button
   itself at the bottom, so the button stays put and everything else grows
   upwards out of it.
   ========================================================================== */
.snd {
  position: fixed;
  inset-inline-start: var(--s-3);
  bottom: var(--s-3);
  z-index: 55;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-2);
}

.snd[hidden] { display: none; }

/* Both the speaker glyphs and the option glyphs. The cone inherits this fill;
   the waves carry their own stroke and are left alone. */
.snd-ico {
  width: 1.25em;
  height: 1.25em;
  flex: none;
  fill: currentColor;
}

/* 44px minimum hit area, at every one of the type scale's extremes. */
.snd-btn,
.snd-opt,
.snd-enable {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.7ch;
  min-height: 44px;
  min-width: 44px;
  padding: 0.5em 1.05em;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: rgba(10, 10, 22, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--ink);
  font-family: inherit;
  font-size: var(--t-2xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  cursor: pointer;
  transition: color var(--dur-2) var(--ease), border-color var(--dur-2) var(--ease),
    background-color var(--dur-2) var(--ease);
}

.snd-btn:hover,
.snd-enable:hover { border-color: var(--accent); }

/* Muted is a state worth reading from the back of the room, so it dims the
   whole control rather than only swapping the glyph. */
.snd.is-off .snd-btn { color: var(--ink-faint); }

.snd-name { text-transform: uppercase; }

/* The shortcut, as a key cap. Decorative — the button's aria-label says it. */
.snd-keyhint {
  margin-inline-start: 0.3ch;
  padding: 0.1em 0.5em;
  border-radius: var(--r-xs);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-faint);
  font-family: var(--mono);
  font-size: 0.85em;
  letter-spacing: 0;
}

/*
 * The idle pulse. It runs ONLY while the bed is actually playing, which makes
 * the control an indicator as well as a switch: if the room is silent and this
 * is pulsing, the laptop is muted at the OS level, not the app. It multiplies
 * var(--loop), so reduced motion stops it with everything else.
 */
.snd.is-playing .snd-btn {
  animation: sndPulse calc(2.6s * var(--loop)) var(--ease-inout) infinite;
}

@keyframes sndPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0); }
  50%      { box-shadow: 0 0 0 6px rgba(139, 92, 246, 0.16); }
}

/* --- The four presets --------------------------------------------------- */
.snd-menu {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  padding: var(--s-2);
  border-radius: var(--r-lg);
  border: 1px solid var(--line-strong);
  background: rgba(10, 10, 22, 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--shadow-lg);
  animation: popIn var(--dur-3) var(--ease-spring) both;
}

.snd-menu[hidden] { display: none; }

.snd-opt {
  width: 100%;
  justify-content: flex-start;
  border-color: transparent;
  border-radius: var(--r-md);
  background: transparent;
  color: var(--ink-dim);
  letter-spacing: normal;
}

.snd-opt:hover { background: var(--surface); color: var(--ink); }

.snd-opt.is-on {
  background: var(--surface-2);
  border-color: var(--accent);
  color: var(--ink);
}

.snd-opt-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: start;
  line-height: var(--lh-snug);
}

.snd-opt-text b { font-weight: 800; }

.snd-opt-text i {
  font-style: normal;
  font-weight: 600;
  font-size: 0.85em;
  color: var(--ink-faint);
}

/* --- Enable-sound chip -------------------------------------------------- */
/* Only ever on screen when audio was asked for and the browser has not handed
   over a running context yet, so it is allowed to be loud about itself. */
.snd-enable {
  border-color: var(--accent);
  background: linear-gradient(120deg, var(--accent-deep), var(--bg-3));
  color: #fff;
  animation: popIn var(--dur-4) var(--ease-spring) both;
}

.snd-enable[hidden] { display: none; }

/* On a phone-sized viewport the word is the first thing to go: the glyph and
   the 44px target stay. */
@media (max-width: 30rem) {
  .snd-name,
  .snd-keyhint { display: none; }
  .snd-btn { padding: 0.5em 0.75em; }
}

/* --- Phone: the two join-screen switches and the in-question mute ---------
   §2.3.5. The markup carries `.btn .btn-ghost .btn-sm`, and `.btn-sm` lives in
   `play.html`'s own inline <style> — which this file may not edit (§2.3.8) and
   which the browser reads AFTER this one. So every rule below that has to beat
   it is written one level deeper (`.snd-group .snd-toggle`, `.q-meta
   .snd-mini`): equal specificity would lose on document order, and `.btn-sm`'s
   `min-height: 2.25rem` is 36 px, four short of the 44 px §2.3.5 requires.
   No `!important`, no new custom property, existing tokens only. */
.snd-group {
  margin-top: var(--s-2);
}

.snd-group .snd-toggle {
  /* The 44 px target comes from min-height rather than padding, so the label
     can shrink on a 320 px screen and the hit area cannot. */
  display: inline-flex;
  align-items: center;
  gap: 0.5ch;
  min-height: 44px;
  padding: 0.35em 0.9em;
  font-size: var(--t-sm);
  border-radius: var(--r-pill);
}

.snd-lbl { font-weight: 800; letter-spacing: 0.02em; }

/* The current value, not a second label: quieter than the name it follows. */
.snd-state {
  font-weight: 700;
  font-size: 0.85em;
  color: var(--ink-faint);
}

/* Pressed is the only state that earns colour, and `aria-pressed` is the
   source of truth for both the switch and this rule, so the two cannot
   disagree — there is no separate class to forget to toggle. */
.snd-group .snd-toggle[aria-pressed="true"] {
  border-color: var(--ok);
  color: var(--ink);
}

.snd-group .snd-toggle[aria-pressed="true"] .snd-state { color: var(--ok-deep); }

/* --- Phone: the in-game sound and vibrate pair ---------------------------- */
/* Two 20 px glyphs in 44 px targets. One rule serves both places they appear —
   beside the clock in `.q-meta`, and under the verdict on the reveal — because
   the wrapper is the same `.snd-pair` in both and `.snd-pair .snd-mini` has the
   same specificity as the `.q-meta .snd-mini` it replaces, which is what it
   takes to beat `play.html`'s later inline `.btn-sm`. Tapping either never
   sends a frame and never touches the answer path.

   Vibrate lives here as well as on the join screen because the join screen is
   gone the moment a player is in: a phone that resumed after a screen lock
   never renders it, and its owner had no way to stop the buzzing. */
.snd-pair {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  flex: none;
}

/* On the reveal it is a row of its own rather than a corner of a header. */
.snd-pair-row {
  justify-content: center;
  align-self: center;
  margin-top: var(--s-2);
}

.snd-pair .snd-mini {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  min-height: 44px;
  padding: 0;
  border-radius: var(--r-pill);
  flex: none;
}

.snd-pair .snd-mini .snd-ico { width: 20px; height: 20px; }

.snd-pair .snd-mini[aria-pressed="true"] { border-color: var(--ok); color: var(--ink); }

/* Sound is wanted but the browser has not handed over a running context — on a
   phone that RESUMED into a live question this button is the only trusted
   gesture left, so it has to look like the thing to press. The pulse
   multiplies var(--loop), so reduced motion stops it with everything else and
   the colour carries the state on its own. */
.snd-pair .snd-mini.is-blocked {
  border-color: var(--accent);
  color: var(--accent);
  animation: sndPulse calc(2.6s * var(--loop)) var(--ease-inout) infinite;
}

/* ===== end audio ===== */

/* ==========================================================================
   16. BIDI, DIRECTION AND ARABIC TYPOGRAPHY
   ==========================================================================

   Appended last on purpose: everything in here has to win against the rules
   above it without a single `!important`.

   Read docs/I18N_DESIGN.md §5.2-§5.5 before changing anything below. The three
   decisions this block implements, in the order they matter:

     1. UI direction and CONTENT direction are independent. `<html dir>` is set
        once by the i18n bootstrap from the chosen interface language; every
        string the server did not author gets its own `dir`/`lang` from
        `qb.markText()`, derived per string. An English host writing an Arabic
        quiz is the normal case, not an edge case, and nothing here couples the
        two.

     2. THE ANSWER GRID NEVER MIRRORS. See §16.2.

     3. Technical strings — the PIN, invite codes, timers, scores — are forced
        LTR and isolated in every language, because they are read aloud and
        typed into a keypad.

   PUBLIC TOKENS ADDED BY THIS BLOCK
     --font-ar --font-he --font-latin   font stacks (§1)
     --dirx                             +1 in LTR, -1 in RTL. Multiply any
                                        horizontal translate by it; `transform`
                                        never follows `dir` on its own.
     --ui-dir                           `ltr` / `rtl`, the CURRENT UI direction,
                                        readable from inside a container that
                                        has pinned its own `direction`.
   Both are custom properties, so they inherit through a pinned `direction`
   and a nested `dir=` island resets them correctly for its own subtree.
   -------------------------------------------------------------------------- */

/* --- 16.1 Direction tokens ------------------------------------------------ */
/* `[dir="rtl"]` last: on `<html dir="rtl">` both selectors match at equal
   specificity and document order decides. */
:root,
[dir="ltr"] { --dirx: 1; --ui-dir: ltr; }
[dir="rtl"] { --dirx: -1; --ui-dir: rtl; }

/* --------------------------------------------------------------------------
   16.2 THE ANSWER GRID DOES NOT FLIP

   Answer 0 is the triangle and it is TOP-LEFT on the projector and on every
   phone in the room, in every language, forever.

   Three reasons, in order of weight:

     1. A phone and a projector must agree. The host draws four count bars and
        four answer lines in index order; the player draws four keycaps. If the
        grid honoured `dir`, an Arabic-UI phone would show the triangle top
        RIGHT while the projector showed it top LEFT, and a room with mixed
        phone languages would have students physically tapping different
        positions for the same answer. That is a correctness bug wearing a
        localisation costume — the one failure mode in this whole workstream
        that loses a game rather than looking wrong.
     2. The shapes are a legend, not prose. Bidi reordering applies to text
        runs. A control surface — a keypad, a lift panel, a game controller —
        is not reordered by language.
     3. Keyboard access. `1 2 3 4` map to positions.

   `.bars` and `.podium` are pinned for reason 1 as well: bar n must sit under
   tile n, and a podium is a chart, not a sentence. `.motif` is the same four
   identities shrunk to a mark on the signed-out pages, and it is pinned so a
   visitor meets the shapes in the order they will tap them.

   THE INSIDE OF A TILE STILL FLIPS, because that part IS prose:
   `qb.markText()` puts `dir="rtl"` on the tile itself from its own label, and
   an element's own `dir` attribute always beats a direction inherited from
   this pin — so a `dir="rtl"` tile puts its shape icon at the right edge and
   flows the Arabic away from it, with no DOM reordering and no second rule.

   The `:not([dir])` clause is the case markText cannot answer: a label with no
   strong character at all ("1969", "H2O"). The spec's answer for a string with
   no opinion is "inherit the UI direction" — but inside a pinned container the
   inherited direction is the pin, not the UI. --ui-dir carries the real answer
   through, because custom properties are not affected by `direction`.
   -------------------------------------------------------------------------- */
.choices,
.bars,
.motif,
.podium { direction: ltr; }

.choices > *:not([dir]),
.bars > *:not([dir]),
.podium > *:not([dir]) { direction: var(--ui-dir, ltr); }

/* --------------------------------------------------------------------------
   16.3 Technical strings — forced LTR and isolated, in EVERY language

   THE PIN IS WESTERN DIGITS. Not Arabic-Indic, not ever, and this is the most
   consequential numeral decision in the product:

     - The PIN is READ ALOUD across a room and TYPED INTO A PHONE. Whatever the
       projector renders has to be enterable on the keypad the student is
       holding, and `inputmode="numeric"` on an Arabic-locale phone still
       shows a keypad the student can read either way — but the QR payload and
       the /join?pin= URL are ASCII by construction, so a projector showing
       ٤٥٩١٢٣ and a URL carrying 459123 are two different PINs to a human.
     - There is no single right answer for `ar` anyway: the Maghreb writes
       Western digits, the Levant and Gulf write Arabic-Indic.
     - Scores and timers have to be visually comparable down a leaderboard.

   CSS cannot transliterate; it can only stop the layout from undoing the
   choice. The rendering side is here, the digit-folding of an Arabic-Indic
   keystroke on input is `qb.asciiDigits()` in the runtime.

   `unicode-bidi: isolate` is what `<bdi>` does. Using the CSS property means
   the existing innerHTML templates never grow a wrapper element, and the
   isolation holds even where a future implementer forgets markText.

   Everything listed here is ASCII BY CONSTRUCTION. A string that mixes a
   translated word with a number (.q-index "Question 3 of 10", .plinth .pts
   "1842 pts") is NOT technical and belongs in §16.4 instead — forcing it LTR
   would lay its Arabic out backwards.
   -------------------------------------------------------------------------- */
.pin,
#pin-cells,
.pin-ok .pin-val,
.tabnum,
.mono,
code,
kbd,
.join-url b,
.snd-keyhint,
.ring-num,
.count-num,
.bar-n,
.big-stat,
.lead-cd,
.q-clock b,
.answered .n,
.copyrow .field,
td.num {
  direction: ltr;
  unicode-bidi: isolate;
}

/* --------------------------------------------------------------------------
   16.4 User content and mixed strings — isolated, direction left alone

   Two different reasons, one mechanism:

     - A nickname, a question or a choice carries its own direction from
       markText. Isolating it stops an Arabic nickname from reordering the
       English leaderboard row around it, and vice versa.
     - It is also the containment half of the bidi-control defence. `src/text.rs`
       rejects the twelve reordering characters at the door for nicknames,
       titles, questions and choices — but a stale resume token, an imported
       quiz written before that landed, or any future call site that forgets to
       validate can still put one on screen. Isolation means the damage stops
       at the element instead of reversing the row.
   -------------------------------------------------------------------------- */
/*
 * EVERY SELECTOR CARRIES `:not([dir="auto"])`, AND THAT IS LOAD-BEARING.
 *
 * `dir="auto"` is implemented BY THE UA STYLESHEET, and it does not use the
 * same value everywhere. Per the HTML rendering spec, `<pre dir=auto>` and
 * `<textarea dir=auto>` get `unicode-bidi: plaintext`; every other
 * `[dir=auto]` element gets `unicode-bidi: isolate` and has its `direction`
 * resolved from content by the auto-directionality algorithm. (Measured on
 * Chrome 145, not assumed — an older `plaintext`-for-everything reading of
 * that spec is out of date.)
 *
 * Either way these are UA declarations, and a bare `.q-text { unicode-bidi:
 * isolate }` is an AUTHOR declaration, so it wins. For the textarea that is a
 * silent regression: `plaintext` becomes `isolate`, and the editor's question
 * field stops flipping to RTL as Arabic is typed into it — the exact behaviour
 * of Journey 1 in I18N_DESIGN §1. `static/editor.html:874` is
 * `<textarea class="q-text" dir="auto">`, so `.q-text` hit it directly.
 *
 * Nothing is given up by excluding `[dir=auto]`: `plaintext` behaves as
 * `isolate` and additionally takes its direction from the first strong
 * character, and the non-textarea cases are already `isolate` from the UA
 * sheet. This rule now only ever ADDS isolation where there was none.
 *
 * Found by computed-style differential, not by reading. The whole signature
 * was one line — `unicode-bidi: plaintext -> isolate` on editor.html's
 * textarea. Nothing moved by a pixel, so no screenshot could have shown it.
 */
.nick:not([dir="auto"]),
.nk:not([dir="auto"]),
.qc-title:not([dir="auto"]),
.qc-meta:not([dir="auto"]),
.q-text:not([dir="auto"]),
.q-index:not([dir="auto"]),
.plinth .who:not([dir="auto"]),
.plinth .pts:not([dir="auto"]),
.verdict .pts:not([dir="auto"]),
.board-row .nk:not([dir="auto"]),
.board-row .sc:not([dir="auto"]),
.board-row .rk:not([dir="auto"]),
.answerline .txt:not([dir="auto"]),
.choice .label:not([dir="auto"]),
.ans .label:not([dir="auto"]),
.bar-foot:not([dir="auto"]),
.roster-count:not([dir="auto"]),
.waiting:not([dir="auto"]) { unicode-bidi: isolate; }

/* --------------------------------------------------------------------------
   16.5 Transforms and asymmetric icons

   `transform` NEVER follows `dir`, so every horizontal one needs an explicit
   sign and every horizontally-asymmetric icon needs mirroring.

   Only genuinely horizontal arrows mirror. ic-up, ic-down, ic-check, ic-cross,
   ic-crown, ic-flame, ic-lock, ic-tick, ic-x, ic-info, ic-del, ic-dup, ic-hold,
   sh-0..sh-3 and sh-crown must NOT — and neither must sh-arrow where it is used
   for a rank move, because there it points up or down. The one place sh-arrow
   IS horizontal is the mode reel's transfer arrow, which host.html rotates 90°.

   These four rules reach into selectors defined in host.html and auth.html.
   That is deliberate: they are DIRECTION rules, they belong with the rest of
   direction handling, and each is written one level deeper than the rule it
   has to beat, since the page's own <style> is read after this file. Move them
   into their owning page if that page ever grows a direction section.
   -------------------------------------------------------------------------- */

/* auth.html — the arrow on the "Play a game" card. Mirrored, and its hover
   nudge re-signed so it still travels FORWARD rather than backwards. */
[dir="rtl"] .arw { transform: scaleX(-1); }
[dir="rtl"] .joincta:hover .arw {
  transform: translateX(calc(4px * var(--dirx))) scaleX(-1);
}

/* host.html — the mode reel's "A took from B" arrow, rotated to horizontal. */
[dir="rtl"] .reel-item .rl-arrow { transform: rotate(-90deg); }

/* host.html — a leaderboard row leaving the board slides out of the reading
   edge, not into it. */
[dir="rtl"] #board .board-row.is-exit { transform: translateX(-28px); }

/* admin.html — the toggle switch. The track would flip with `dir` while the
   knob's `translateX` stayed physical, which is worse than not flipping at
   all: the knob would sit at the ON end while the track read OFF. Pin the
   whole control, exactly as a real physical switch is not mirrored.
   (`.sw` is built by admin.js, not written in admin.html's markup, which is
   why grepping the HTML for it finds nothing. The rules are at admin.html:414
   and the knob's physical offsets are `left: 3px` + `translate(1.15rem,-50%)`
   at :428 and :442.) */
.sw { direction: ltr; }

/* The obvious worry about that pin is that it also pins the switch's LABEL,
   and an Arabic label laid out under an LTR paragraph direction resolves its
   neutrals and trailing punctuation on the wrong side. VERIFIED, and it does
   not apply: `.sw` is built in exactly one place (admin.js:862 `toggle()`)
   with three children — the checkbox, `span.track`, and `span.sr-only` — and
   the sr-only span is visually hidden. There is no visible label inside a
   `.sw` to mis-order, so pinning the whole control costs nothing at all.
   (admin.html:447 styles `.sw .txt`; nothing ever builds a `.txt` inside a
   `.sw`, so that rule is already dead. Left alone — not this file's to fix.)
   A `.sw .txt { direction: var(--ui-dir) }` rule was written here and then
   removed once that was checked: it would have been dead code carrying a
   confident comment, which is worse than no rule. */

/* --------------------------------------------------------------------------
   16.6 Arabic typography

   `:lang()` matches on the INHERITED language, so `:lang(ar)` matches the
   element carrying lang="ar" AND every descendant of it. That is what makes an
   Arabic question inside an English page pick up Arabic metrics. Doubling the
   pseudo-class raises specificity to (0,2,0) so it beats the two-class rules
   in §9, §11 and §13 without an `!important`.

   FONT SELECTION IS DONE WITH TOKENS, NOT `font-family`, wherever it can be.
   A blunt `:lang(ar) { font-family: var(--font-ar) }` at (0,2,0) would also
   win against `.pin { font-family: var(--mono) }` at (0,1,0) and silently
   steal the monospace face from the PIN, the invite code and the JSON pane on
   every Arabic page. So:
     - the page-wide swap redefines --font, which only `body` consumes, and
       leaves every explicit --mono stack in the tree completely alone;
     - content ISLANDS use `[lang="ar"]`, an attribute selector that matches
       ONLY the element markText actually marked and not its descendants, so it
       can never reach a .pin that has no lang of its own.
   -------------------------------------------------------------------------- */

/* Page-wide: the interface language is Arabic. */
html:lang(ar) { --font: var(--font-ar); }
html:lang(he) { --font: var(--font-he); }

/* Content islands: one Arabic question inside an otherwise English page. The
   token swap above cannot reach these — they have no `font-family` of their
   own, they inherit body's computed value — so this is the one real
   `font-family` in the block, scoped as narrowly as it can be. */
[lang="ar"] { font-family: var(--font-ar); }
[lang="he"] { font-family: var(--font-he); }

/*
 * THE CRITICAL RULE.
 *
 * Tracking inserts space BETWEEN letterforms, and Arabic is cursive: 0.2em
 * turns مرحبا into five disconnected shapes that look like a broken font, and
 * the negative trackings on .q-text, h1-h3 and .nick are worse still because
 * they collide the joins.
 *
 * THE HONEST COUNT, re-measured with comments stripped rather than taken from
 * the spec: 28 letter-spacing declarations in this file and 110 across
 * static/. I18N_DESIGN §0 says 58; that number was measured on 2026-08-23,
 * before games.html and import.html existed. host.html alone now has 22 and
 * play.html 14. This one rule kills all of them for Arabic text.
 *
 * It is safe to be this blunt because the only elements that legitimately want
 * tracking hold ASCII by construction, and those are excluded by name. The
 * exclusion list is deliberately SHORT: .eyebrow, .pin-label, .q-index,
 * .qr-hint, .qc-meta, .qc-go, .snd-name and .answered .cap are all translated
 * UI labels, and Arabic has no capitals for their `text-transform: uppercase`
 * to reach either, so they SHOULD lose their tracking.
 *
 * WHY FIVE `:lang(ar)` AND NOT TWO. `:not()` takes the specificity of its most
 * specific argument, so the obvious `:lang(ar):lang(ar):not(...)` is (0,3,0) —
 * and (0,3,0) IS NOT ENOUGH. Every page's own <style> is parsed AFTER this
 * file, so it wins every tie. Three real declarations were measured leaking
 * through at (0,3,0):
 *
 *   host.html    .reel-item.is-huge .rl-who          (0,3,0)  -0.02em
 *   host.html    .reveal-mode .reel-item.is-huge .rl-who
 *                                                    (0,4,0)  (inherits it)
 *   import.html  td[data-lbl]:not(:empty)::before    (0,3,2)   0.12em
 *
 * `.rl-who` is the one that matters: host.js builds it from a PLAYER NICKNAME
 * (host.js:2234, :2797, :2806), so it holds arbitrary user text and negative
 * tracking on an Arabic nickname collides the joins on the projector, at
 * --t-2xl, in front of the room. Five repetitions give (0,5,0), which clears
 * the highest measured competitor (0,4,0) with one step of headroom.
 *
 * `#si-invite` in auth.html keeps its 0.04em and that is CORRECT: an ID is
 * (1,0,0) and no number of classes beats it, and the invite code is ASCII by
 * construction — exactly the kind of tracking that should survive.
 */
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar):not(.pin, .brand, .mono, code, kbd),
:lang(he):lang(he):lang(he):lang(he):lang(he):not(.pin, .brand, .mono, code, kbd) {
  letter-spacing: normal;
  word-spacing: normal;
}

/*
 * ...and the same kill for GENERATED content, which the rule above cannot
 * reach. A declaration whose subject is `::before` applies to the pseudo-
 * element box itself, so it is not overridden by any rule on the originating
 * element no matter how specific — it has to be beaten on its own subject.
 *
 * There are exactly two pseudo-element letter-spacing rules in the whole tree,
 * both in import.html, and only one of them can ever hold Arabic:
 *
 *   td[data-lbl]:not(:empty)::before  content: attr(data-lbl)  0.12em  ← this
 *   .qrow.is-edited .c-n::after       content: "edited"        0.04em
 *
 * `attr(data-lbl)` renders the responsive table's column headings, which the
 * i18n runtime translates, so on an Arabic import screen that pseudo-element
 * holds Arabic at 0.12em tracking. The second is a hard-coded ASCII literal in
 * the stylesheet and can never be Arabic; it loses its tracking on an Arabic
 * page too, which is harmless and not worth a carve-out. (That literal is also
 * an untranslated string — an i18n-catalogue problem, not a CSS one. Flagged
 * for whoever owns import.html rather than papered over here.)
 */
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar)::before,
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar)::after,
:lang(he):lang(he):lang(he):lang(he):lang(he)::before,
:lang(he):lang(he):lang(he):lang(he):lang(he)::after {
  letter-spacing: normal;
  word-spacing: normal;
}

/*
 * Arabic naskh sits on a smaller optical body than the Latin faces this scale
 * was tuned against, and carries taller ascenders and deeper descenders. ~6%
 * up on every size, and materially looser leading.
 *
 * Redefining the TOKENS rather than sweeping font-size means an Arabic subtree
 * inside an English page gets Arabic metrics automatically, which is exactly
 * right, and it is ~16 declarations instead of a file-wide edit.
 *
 * --t-pin is NOT bumped. The PIN is Western digits in --mono (§16.3); it is
 * the one display size on the page that is never Arabic, and growing it 6%
 * risks the 15rem cap overflowing a projector.
 */
:lang(ar):lang(ar) {
  --t-3xs: clamp(0.66rem, 0.53rem + 0.34vmin, 0.96rem);
  --t-2xs: clamp(0.74rem, 0.59rem + 0.45vmin, 1.11rem);
  --t-xs:  clamp(0.83rem, 0.66rem + 0.58vmin, 1.27rem);
  --t-sm:  clamp(0.93rem, 0.74rem + 0.76vmin, 1.48rem);
  --t-md:  clamp(1.06rem, 0.85rem + 0.95vmin, 1.75rem);
  --t-lg:  clamp(1.22rem, 0.93rem + 1.38vmin, 2.23rem);
  --t-xl:  clamp(1.48rem, 1.06rem + 2.12vmin, 3.18rem);
  --t-2xl: clamp(1.85rem, 1.22rem + 3.39vmin, 4.56rem);
  --t-3xl: clamp(2.23rem, 1.38rem + 4.88vmin, 6.15rem);
  --t-hero: clamp(2.76rem, 1.27rem + 8.48vmin, 9.5rem);

  --lh-tight: 1.30;
  --lh-snug: 1.45;
  --lh-body: 1.80;

  /* Tashkeel above and the deep naskh descenders below both clip against a
     tight line box; an underline drawn at the alphabetic baseline cuts
     straight through them. */
  text-underline-position: under;
}

/* Hebrew needs the leading but not the size bump: it has no cursive joining to
   break, no tashkeel, and its optical body is close to Latin. */
:lang(he):lang(he) {
  --lh-tight: 1.20;
  --lh-snug: 1.32;
  --lh-body: 1.65;
}

/*
 * .type-desk re-declares the WHOLE ramp on a container (auth, admin), and a
 * value declared on a nearer ancestor beats one declared on a further one no
 * matter how specific the further rule is. Without this, an Arabic sign-in
 * page would silently fall back to Latin metrics. Same values as the base
 * Arabic ramp, because .type-desk IS the base desk ramp; --t-pin is left to
 * .type-desk's own declaration.
 */
.type-desk:lang(ar):lang(ar) {
  --t-3xs: clamp(0.66rem, 0.53rem + 0.34vmin, 0.96rem);
  --t-2xs: clamp(0.74rem, 0.59rem + 0.45vmin, 1.11rem);
  --t-xs:  clamp(0.83rem, 0.66rem + 0.58vmin, 1.27rem);
  --t-sm:  clamp(0.93rem, 0.74rem + 0.76vmin, 1.48rem);
  --t-md:  clamp(1.06rem, 0.85rem + 0.95vmin, 1.75rem);
  --t-lg:  clamp(1.22rem, 0.93rem + 1.38vmin, 2.23rem);
  --t-xl:  clamp(1.48rem, 1.06rem + 2.12vmin, 3.18rem);
  --t-2xl: clamp(1.85rem, 1.22rem + 3.39vmin, 4.56rem);
  --t-3xl: clamp(2.23rem, 1.38rem + 4.88vmin, 6.15rem);
  --t-hero: clamp(2.76rem, 1.27rem + 8.48vmin, 9.5rem);
}

/*
 * ...and the same trap in the other direction on a projector. RESPONSIVE
 * EXTREMES re-cuts the ramp on `:root` above 2200px, which is (0,1,0) and
 * loses to the (0,2,0) Arabic block above — so an Arabic host on a 4K
 * projector would have got DESK-sized captions in a lecture hall. The
 * projector ramp, times the same 1.06.
 */
@media (min-width: 2200px) {
  :lang(ar):lang(ar) {
    --t-3xs: clamp(0.95rem, 0.42rem + 0.58vmin, 1.59rem);
    --t-2xs: clamp(1.06rem, 0.48rem + 0.76vmin, 1.91rem);
    --t-xs:  clamp(1.17rem, 0.53rem + 0.9vmin, 2.23rem);
    --t-sm:  clamp(1.33rem, 0.58rem + 1.11vmin, 2.65rem);
    --t-md:  clamp(1.48rem, 0.64rem + 1.38vmin, 3.18rem);
    --t-lg:  clamp(1.8rem, 0.74rem + 1.91vmin, 4.13rem);
    --t-xl:  clamp(2.33rem, 0.95rem + 2.76vmin, 5.51rem);
    --t-2xl: clamp(2.76rem, 1.22rem + 3.6vmin, 6.78rem);
    --t-3xl: clamp(3.39rem, 1.38rem + 4.88vmin, 8.48rem);
    --t-hero: clamp(2.76rem, 1.27rem + 8.48vmin, 12.72rem);
  }
}

/*
 * Two classes assume Latin density and squeeze the line box to prove it.
 * .q-text carries -0.025em and --lh-tight; a tile label carries --lh-snug.
 * Arabic in either clips its own tashkeel against the line above.
 *
 * WHY FIVE `:lang(ar)` HERE TOO, and not the two this rule shipped with.
 * The 2x2 answer grid on the phone is `<div class="choices choices-fill">`
 * (play.html), and play.html's own <style> carries
 *
 *     .choices-fill .choice .label { line-height: 1.14; -webkit-line-clamp: 4;
 *                                    overflow: hidden }        (0,3,0)
 *
 * A doubled `:lang()` is also (0,3,0) -- `:lang()` counts as a class -- and
 * that page block is parsed AFTER app.css, so it won the tie and every Arabic
 * choice label rendered at 1.14 leading: tashkeel collided with the line above
 * and naskh descenders were cut by the clamp's `overflow: hidden`. It lost in
 * BOTH directions, on an Arabic UI (`<html lang=ar>` -> the descendant form)
 * and on an Arabic answer inside an English page (markText puts lang="ar" on
 * the span itself -> the compound form). Five repetitions match the
 * letter-spacing kill above and clear the (0,4,0) `.choices-fill.len-l` size
 * steps with a step of headroom.
 */
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar) .label,
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar).label,
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar) .q-text,
:lang(ar):lang(ar):lang(ar):lang(ar):lang(ar).q-text { line-height: var(--lh-snug); }

/*
 * ...and the consequence of winning that tie, which has to be paid or the fix
 * trades a collision for a clip. The tile is a fixed-height box: at 1.14
 * leading a 4-line clamp occupies 4.56em, at 1.45 it occupies 5.80em -- 27%
 * more than the box has. Arabic carries ~25% more meaning per character
 * (which is why the runtime's density factor exists, I18N_DESIGN §5.4 Part E),
 * so one fewer line holds the same sentence: 3 lines at 1.45 is 4.35em, back
 * inside the box the Latin ramp was measured against. The three steps move
 * together, 4/5/6 -> 3/4/5, so the len-l and len-xl stepdowns keep their shape.
 */
.choices-fill .choice .label:lang(ar):lang(ar),
:lang(ar):lang(ar) .choices-fill .choice .label { -webkit-line-clamp: 3; }
.choices-fill.len-l .choice .label:lang(ar):lang(ar),
:lang(ar):lang(ar) .choices-fill.len-l .choice .label { -webkit-line-clamp: 4; }
.choices-fill.len-xl .choice .label:lang(ar):lang(ar),
:lang(ar):lang(ar) .choices-fill.len-xl .choice .label { -webkit-line-clamp: 5; }

/*
 * Answer tiles are a fixed-height box and Arabic is ~25% shorter in characters
 * for the same content, so the runtime's length heuristic lands the same
 * sentence in a LARGER size class (I18N_DESIGN §5.4 Part E handles that side
 * with a per-script density factor). This is the CSS half of the same problem:
 * let a long Arabic label wrap to the space it needs rather than push the tile.
 */
:lang(ar):lang(ar) .choice .label,
:lang(ar):lang(ar) .ans .label { overflow-wrap: anywhere; hyphens: none; }

/* ==========================================================================
   16.7 The language control, and the no-Arabic-font advisory
   ==========================================================================

   THE CONTROL. Every page carries the same markup, a <details> so the
   disclosure needs no JavaScript:

       <details class="langctl">
         <summary class="langctl-btn" data-t-title="lang.label" ...>globe</summary>
         <div class="langctl-menu" role="group" data-t-aria-label="lang.choose">
           <a class="langctl-opt" data-qb-lang="en" href="?lang=en" lang="en">English</a>
           <a class="langctl-opt" data-qb-lang="ar" href="?lang=ar" lang="ar">العربية</a>
         </div>
       </details>

   Each language names itself IN ITS OWN LANGUAGE AND SCRIPT, never translated
   and never a flag: a reader who cannot read the interface in front of them
   can still recognise their own language in a list, and a flag names a country
   rather than a language.

   The `href` is the no-JavaScript fallback and on its own it is lossy — a bare
   "?lang=ar" replaces the whole query string and drops the fragment, so
   /editor?id=7, /join?pin=065432, /games?id=3 and /reset#<token> would each
   change language and lose the thing that made the link worth opening.
   `data-qb-lang` is the hook that fixes it and it IS wired: one delegated
   listener in /i18n.js (bindLangControl) rewrites only the `lang` parameter of
   the current URL and location.replace()s it, so the rest of the query, the
   fragment, and an existing ?lang= all survive. Do not paste a copy of that
   listener into a page; it belongs in the runtime, once.

   This block is the ONE copy of that explanation. It used to be a 20-line HTML
   comment repeated ten times across eight pages, which is how it came to say
   the listener did not exist for months after it did.

   THE ADVISORY. `qb.fontAdvisory(container)` renders one dismissible line when
   the shaping probe (`qb.arabicOk()`) says this device has no Arabic-capable
   face — a kiosk image, a minimal container, a stripped projector VM. Telling
   the operator to install `fonts-noto-core` is worth more than any fallback
   this product could ship, and without these rules the box would render as
   unstyled inline text with no surface behind it. It is built by
   createElement, never innerHTML (§6.2), and it is the caller that decides
   where it goes — /join and / call it, because those are the two screens a
   room actually reads from. */

.qb-font-note {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin: var(--s-3) 0 0;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font-size: var(--t-2xs);
  line-height: var(--lh-body);
  text-align: start;
}
.qb-font-note > span { flex: 1 1 12rem; min-width: 0; }
.qb-font-note > .btn { flex: 0 0 auto; }

/* ===== end bidi/RTL ===== */

/* ===== media (MEDIA_DESIGN §2.5) — in-game question art ==================
   Append-only block. Three client streams land in this file, so it is one
   delimited region and nothing above it is edited.

   Everything here is scoped to `.q-art`, which exists only inside the two
   question screens and only when an `art` frame arrived. A classic quiz
   renders no element with this class, so none of these rules can match and
   every unrelated screen is byte-identically unaffected — which is the whole
   point of the scoping.

   The box is RESERVED from the asset's own aspect ratio before the bytes
   arrive (host.js/play.js set --qb-ar), so a picture arriving late never
   reflows the choices under a running timer. That is a fairness property, not
   a cosmetic one: a layout shift at the moment a player is reaching for an
   answer costs them the answer.                                             */

/* `[hidden]` FIRST, and it is not optional: an author rule of the same
   specificity beats the UA stylesheet's `[hidden] { display: none }`, so
   `.q-art { display: block }` alone would render an empty plate on EVERY
   classic question — projector and phone — for a quiz with no pictures at all.
   `.qr-card[hidden]`, `.snd[hidden]`, `.snd-menu[hidden]` and
   `.snd-enable[hidden]` above exist for exactly this reason. */
.q-art[hidden] { display: none; }

.q-art {
  display: block;
  margin: 0 0 var(--s-3);
  /* Logical properties throughout, so RTL needs no second rule set. */
  padding-inline: 0;
  text-align: center;
  /* Never let a picture push the choices off a projector. */
  max-block-size: 34vh;
}

.q-art img {
  display: block;
  margin-inline: auto;
  max-inline-size: 100%;
  max-block-size: 34vh;
  inline-size: auto;
  block-size: auto;
  border-radius: var(--r-md);
  /* The reserved box: the intrinsic ratio the server sent, so the space is
     claimed on the frame BEFORE the image decodes. */
  aspect-ratio: var(--qb-ar, auto);
  object-fit: contain;
  /* A picture is content on a surface that is already dark or already light;
     a neutral plate keeps a transparent PNG legible on both. */
  background: var(--surface-2, rgba(127, 127, 127, 0.12));
}

/* The phone gets less room: the choices are the interactive part and must stay
   reachable with a thumb without scrolling. */
#s-question .q-art,
#s-question .q-art img {
  max-block-size: 22vh;
}

/* An image that failed to load must not leave a grey plate sitting where a
   picture should be — the question still works without it. */
.q-art.is-failed { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .q-art img { transition: opacity 140ms ease-out; }
}
.q-art img[data-loading="1"] { opacity: 0; }

/* ===== end media ===== */

/*
 * Projector legibility (external review, §UI). The hall ramp above fires only
 * at >=2200px, so a 1600- or 1920-wide projector renders the DESK scale and the
 * reveal answer (.answerline .txt = --t-xl) computes to ~38px — under a 15 m
 * reading target of ~65px. The host view IS the big-screen context
 * (body[data-audio-role="host"] in host.html), so it gets the hall ramp from
 * 1200px up. Scoped to that shell on purpose: the authoring pages (editor,
 * library, admin) on a normal 1920 desktop monitor keep the desk scale, so this
 * is not the app-wide restyle a normal monitor would show. Final size at a
 * given throw is a real-room call; this removes the breakpoint cliff.
 */
@media (min-width: 1200px) {
  body[data-audio-role="host"] {
    --t-3xs: clamp(0.9rem, 0.4rem + 0.55vmin, 1.5rem);
    --t-2xs: clamp(1rem, 0.45rem + 0.72vmin, 1.8rem);
    --t-xs: clamp(1.1rem, 0.5rem + 0.85vmin, 2.1rem);
    --t-sm: clamp(1.25rem, 0.55rem + 1.05vmin, 2.5rem);
    --t-md: clamp(1.4rem, 0.6rem + 1.3vmin, 3rem);
    --t-lg: clamp(1.7rem, 0.7rem + 1.8vmin, 3.9rem);
    --t-xl: clamp(2.2rem, 0.9rem + 2.6vmin, 5.2rem);
    --t-2xl: clamp(2.6rem, 1.15rem + 3.4vmin, 6.4rem);
    --t-3xl: clamp(3.2rem, 1.3rem + 4.6vmin, 8rem);
    --t-hero: clamp(2.6rem, 1.2rem + 8vmin, 12rem);
    --t-pin: clamp(3.2rem, 0.8rem + 15vmin, 20rem);
  }
}

/* ==========================================================================
   BLITZ identity (electric) — external-design pick, additive over the base.
   Answer fills (--a0..--a3) and --ink-on are deliberately UNCHANGED, so every
   measured tile/label contrast still ships. The electric feel is environment,
   not garish tiles: a charged background, a volt-yellow countdown ring, a
   colour glow on the tiles, and a rounded, friendly type stack (no external
   font — Apple gets SF Rounded, others fall back through the system stack;
   a bundled display face is a follow-up to finish the look cross-platform).
   ========================================================================== */
:root {
  --volt: #ffe14d;            /* electric yellow — the charge accent */
  --spark: var(--accent-2);   /* cyan, already the focus colour */
  --font-latin: ui-rounded, "SF Pro Rounded", "Segoe UI Rounded", Nunito,
    system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

/* Punchier electric colour field + a faint diagonal speed-streak. */
body::before {
  background:
    radial-gradient(42vmax 42vmax at 18% 18%, rgba(139, 92, 246, 0.40), transparent 62%),
    radial-gradient(38vmax 38vmax at 84% 12%, rgba(34, 211, 238, 0.28), transparent 62%),
    radial-gradient(46vmax 46vmax at 72% 88%, rgba(199, 15, 70, 0.24), transparent 64%),
    radial-gradient(40vmax 40vmax at 12% 82%, rgba(55, 190, 172, 0.18), transparent 64%),
    repeating-linear-gradient(115deg, transparent 0 30px, rgba(255, 255, 255, 0.018) 30px 32px),
    linear-gradient(160deg, #0b0a22 0%, #12102e 55%, #0b0a22 100%);
}

/* Charged tiles: same fill, add a colour glow and keep the arcade lip. */
.choice,
.ans {
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.26),
    inset 0 -3px 0 rgba(0, 0, 0, 0.22),
    0 10px 26px rgba(0, 0, 0, 0.42),
    0 0 22px -6px var(--c);
}

/* The countdown is a CHARGE ring: volt, and it glows. Warn/danger still shift. */
.ring .ring-bar { stroke: var(--volt); }
.ring svg { filter: drop-shadow(0 0 6px rgba(255, 225, 77, 0.55)); }
.ring.is-warn .ring-bar { stroke: #ffb020; }
.ring.is-danger .ring-bar { stroke: var(--a0-lite); }

/* The PIN reads like a charged sign. */
.pin { text-shadow: 0 0 18px rgba(255, 225, 77, 0.32), 0 0 42px rgba(34, 211, 238, 0.20); }

/* The correct answer crackles at reveal. */
.choice.is-correct,
.ans.is-correct {
  box-shadow:
    inset 0 2px 0 rgba(255, 255, 255, 0.26),
    0 0 0 4px var(--volt),
    0 0 34px -4px var(--volt);
}


/* ==========================================================================
   BLITZ display face — Baloo 2 (rounded), embedded as base64 so it ships in
   the binary with NO external fetch (offline invariant preserved). Latin only;
   Arabic/Hebrew keep their own faces via per-character fallback in --font-ar/he.
   ========================================================================== */
@font-face{ font-family:"Blitz Display"; font-weight:700; font-style:normal; font-display:swap;
  src:url(data:font/woff2;base64,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) format("woff2"); }
@font-face{ font-family:"Blitz Display"; font-weight:800; font-style:normal; font-display:swap;
  src:url(data:font/woff2;base64,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) format("woff2"); }
:root{
  --font-latin:"Blitz Display", ui-rounded, "SF Pro Rounded", Nunito, system-ui,
    -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
/* Stronger electric so Blitz actually reads: brighter streaks + tile glow. */
body::before{
  background:
    radial-gradient(42vmax 42vmax at 18% 18%, rgba(139,92,246,0.44), transparent 62%),
    radial-gradient(38vmax 38vmax at 84% 12%, rgba(34,211,238,0.32), transparent 62%),
    radial-gradient(46vmax 46vmax at 72% 88%, rgba(199,15,70,0.26), transparent 64%),
    radial-gradient(40vmax 40vmax at 12% 82%, rgba(55,190,172,0.20), transparent 64%),
    repeating-linear-gradient(115deg, transparent 0 26px, rgba(120,180,255,0.05) 26px 28px),
    linear-gradient(160deg, #0b0a24 0%, #14113a 55%, #0b0a24 100%);
}
.choice, .ans{
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,0.26),
    inset 0 -3px 0 rgba(0,0,0,0.22),
    0 10px 26px rgba(0,0,0,0.42),
    0 0 30px -4px var(--c);
}

/* --------------------------------------------------------------------------
   Blitz: the podium (projector and phone share these blocks).

   First place is VOLT, not gold — the charge colour the whole identity hangs
   off — with a beam of it rising off the block over the winner's face and
   name. Silver runs cool with a cyan cast; bronze warm. Fills and inks are
   unchanged in role, so every contrast pair stays what it was.
   -------------------------------------------------------------------------- */
.plinth .block { position: relative; }
.plinth-1 .block {
  background: linear-gradient(180deg, #fff6b8, var(--volt, #ffe14d) 38%, #e6be00);
  border-color: rgba(255, 246, 184, 0.75);
  box-shadow:
    0 0 70px -6px rgba(255, 225, 77, 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.55);
}
.plinth-1 .block::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 100%;
  width: 170%;
  height: clamp(11rem, 42vmin, 26rem);
  transform: translateX(-50%);
  pointer-events: none;
  z-index: -1;
  background: radial-gradient(ellipse 52% 100% at 50% 100%,
    rgba(255, 225, 77, 0.32), rgba(255, 225, 77, 0.10) 45%, rgba(255, 225, 77, 0) 72%);
  animation: beamPulse calc(2.8s * var(--loop)) var(--ease-inout) infinite;
}
@keyframes beamPulse {
  0%, 100% { opacity: 0.85; }
  50%      { opacity: 1; transform: translateX(-50%) scaleX(1.06); }
}
.plinth-2 .block {
  background: linear-gradient(180deg, #f2f6ff, #c6d0ea 45%, #8d99bf);
  box-shadow: 0 0 40px -10px rgba(34, 211, 238, 0.35);
}
.plinth-3 .block {
  background: linear-gradient(180deg, #ffcf9e, #e8a064 45%, #b26a33);
}
.plinth-1 .who { color: var(--volt, #ffe14d); text-shadow: 0 0 18px rgba(255, 225, 77, 0.45); }
.plinth .crown { fill: var(--volt, #ffe14d); filter: drop-shadow(0 0 10px rgba(255, 225, 77, 0.65)); }
