/* The Quiz Club — team web client.
   Tokens mirror the iOS design system (violet / amber / green on a dark base). */
:root {
  --primary: #8c5cf5;
  --secondary: #fa9e4a;
  --success: #2ec779;
  --danger:  #ed5a6b;
  /* Countdown colours (plenty / short / last seconds) — separate tokens so
     each template can restyle the timer without touching its status colours
     (Irish e.g. has --success == --secondary == gold). Mirrors the iOS
     PresentationTheme timerOK/timerWarn/timerDanger tokens. */
  --timer-ok: #2ec779;
  --timer-warn: #fa9e4a;
  --timer-danger: #ed5a6b;
  --bg:      #0f0d1e;
  --bg-top:  #211440;
  --surface: #1f1d33;
  --surface-hi: #2e2b49;
  --outline: rgba(255,255,255,.08);
  --on:      #ffffff;
  --muted:   rgba(255,255,255,.62);
  /* Text colour for content sitting ON TOP OF a solid --primary/--success/
     --danger fill (buttons, the selected/correct MC answer-key badge, the
     toast) — a per-theme token instead of a hardcoded white, because white
     text is only readable there for templates whose accent is dark. Every
     template's primary/success/danger is a saturated mid-tone EXCEPT
     Corporate Bright, whose primary/success are themselves near-black (see
     its override below) — so dark text is the correct default here, not
     white. */
  --on-primary:   #0a0a0a;
  --on-secondary: #0a0a0a;
  --on-success:   #0a0a0a;
  --on-danger:    #0a0a0a;
  --radius:  18px;
  --space:   16px;
  color-scheme: dark;
}

/* Presentation templates (host-picked, synced via games/{code}.theme —
   screen.js/team.js set the body class). No class = Classic, untouched.
   Variable overrides re-skin everything; the extra rules below add the
   template-specific effects (neon glow tubes / Irish serif headlines). */
body.theme-neon {
  --primary: #00f0ff;
  --secondary: #ffb800;
  --success: #39ff88;
  /* The sign's own tubes: cyan → amber → hot pink (green stays "correct"). */
  --timer-ok: #00f0ff;
  --timer-warn: #ffb800;
  --timer-danger: #ff007f;
  --bg: #0b0e14;
  --bg-top: #0b0e14;
  --surface: #10141c;
  --surface-hi: #16202b;
}
body.theme-neon .bs-badge {
  border: 1.5px solid var(--primary);
  box-shadow: 0 0 8px rgba(0,240,255,.45), inset 0 0 8px rgba(0,240,255,.10);
}
body.theme-neon .bs-badge.amber { border-color: var(--secondary); box-shadow: 0 0 8px rgba(255,184,0,.45), inset 0 0 8px rgba(255,184,0,.10); }
body.theme-neon .bs-badge.answered { border-color: var(--success); box-shadow: 0 0 8px rgba(57,255,136,.45), inset 0 0 8px rgba(57,255,136,.10); }
body.theme-neon .bs-prompt { text-shadow: 0 0 8px rgba(255,255,255,.5), 0 0 26px rgba(0,240,255,.3); }
body.theme-neon .bs-option {
  border: 3px solid rgba(0,240,255,.75);
  background: rgba(0,240,255,.04);
  box-shadow: 0 0 12px rgba(0,240,255,.35), inset 0 0 16px rgba(0,240,255,.08);
}
body.theme-neon .bs-option .key { background: rgba(0,240,255,.08); border: 2px solid var(--primary); color: var(--primary); text-shadow: 0 0 6px rgba(0,240,255,.8); }
body.theme-neon .bs-option.correct {
  border: 4px solid var(--success);
  background: rgba(57,255,136,.07);
  box-shadow: 0 0 18px rgba(57,255,136,.6), inset 0 0 18px rgba(57,255,136,.12);
  /* The tube "strikes" on reveal — the .correct node is inserted fresh with
     the reveal render, so the flicker plays exactly once at that moment. */
  animation: neon-ignite .65s linear;
}
body.theme-neon .bs-option.correct .key { background: var(--success); border-color: var(--success); color: #06130a; }
body.theme-neon .bs-solution { border: 3px solid var(--success); box-shadow: 0 0 18px rgba(57,255,136,.5);
  animation: neon-ignite .65s linear; }
@keyframes neon-ignite {
  0%   { opacity: .05; }
  10%  { opacity: 1; }
  22%  { opacity: .15; }
  34%  { opacity: .9; }
  46%  { opacity: .3; }
  62%  { opacity: 1; }
  75%  { opacity: .6; }
  100% { opacity: 1; }
}
body.theme-neon .bs-rank.gold { box-shadow: 0 0 14px rgba(255,184,0,.35); }

body.theme-irish {
  --primary: #6fcf97;
  --secondary: #d4af37;
  --success: #d4af37;
  /* Green → brass → terracotta; gold alone can't escalate (it's the reveal). */
  --timer-ok: #6fcf97;
  --timer-warn: #d4af37;
  --timer-danger: #d96350;
  --bg: #071009;
  --bg-top: #16352a;
  --surface: #10241b;
  --surface-hi: #17352a;
  --on: #f5efe0;
  --muted: #8fa898;
}
body.theme-irish .bs-title, body.theme-irish .bs-prompt { font-family: Georgia, 'Times New Roman', serif; }
body.theme-irish .bs-option { border: 1px solid rgba(111,207,151,.25); background: rgba(23,105,74,.16); }
body.theme-irish .bs-option .key { background: linear-gradient(180deg,#e8c55a,#c9a227); color: #0a1710; }
body.theme-irish .bs-option.correct { border: 1.5px solid #d4af37; background: rgba(212,175,55,.14); box-shadow: 0 0 16px rgba(212,175,55,.2); }
body.theme-irish .bs-solution { border: 1.5px solid #d4af37; }

/* Corporate — plain white/black/greyscale in two variants. The reveal
   "inverts" instead of using colour: white card on dark, black on bright. */
body.theme-corporate-dark {
  --primary: #e8e8e8;
  --secondary: #9e9e9e;
  --success: #ffffff;
  /* Greyscale escalates by brightness; only the last seconds get colour. */
  --timer-ok: #9e9e9e;
  --timer-warn: #e8e8e8;
  --timer-danger: #ed5a6b;
  --bg: #0a0a0a;
  --bg-top: #101010;
  --surface: #161616;
  --surface-hi: #242424;
}
body.theme-corporate-dark .bs-option { border: 1px solid rgba(255,255,255,.18); }
body.theme-corporate-dark .bs-option.correct { border: 2px solid #fff; background: rgba(255,255,255,.10); }
body.theme-corporate-dark .bs-option.correct .key { background: #fff; color: #111; }
body.theme-corporate-dark .bs-solution { color: #fff; background: rgba(255,255,255,.10); border: 2px solid #fff; }

body.theme-corporate-bright {
  --primary: #1a1a1a;
  --secondary: #6e6e6e;
  --success: #111111;
  --danger: #b00020;
  --timer-ok: #6e6e6e;
  --timer-warn: #111111;
  --timer-danger: #b00020;
  --bg: #f2f2f2;
  --bg-top: #ffffff;
  --surface: #ffffff;
  --surface-hi: #e9e9e9;
  --outline: rgba(0,0,0,.12);
  --on: #111111;
  --muted: rgba(0,0,0,.55);
  /* Inverted from the :root default — this template's primary/success ARE
     near-black, so content on top of them needs light text instead. */
  --on-primary:   #ffffff;
  --on-secondary: #ffffff;
  --on-success:   #ffffff;
  --on-danger:    #ffffff;
}
body.theme-corporate-bright .bs-option { background: rgba(0,0,0,.05); border: 1px solid rgba(0,0,0,.15); }
body.theme-corporate-bright .bs-option .key { background: #1a1a1a; color: #fff; }
body.theme-corporate-bright .bs-option.correct { border: 2px solid #111; background: rgba(0,0,0,.08); }
body.theme-corporate-bright .bs-option.correct .key { background: #111; color: #fff; }
body.theme-corporate-bright .bs-solution { color: #111; background: rgba(0,0,0,.07); border: 2px solid #111; }
body.theme-corporate-bright .bs-badge { background: rgba(0,0,0,.07); }
body.theme-corporate-bright .bs-badge.amber { background: rgba(0,0,0,.05); }
body.theme-corporate-bright .bs-badge.answered { background: rgba(0,0,0,.07); }
body.theme-corporate-bright .bs-rank { background: rgba(0,0,0,.05); }
body.theme-corporate-bright .bs-rule { background: rgba(0,0,0,.05); }
body.theme-corporate-bright .bs-team { background: rgba(0,0,0,.06); }
body.theme-corporate-bright .bs-qr { border: 1px solid rgba(0,0,0,.15); }
body.theme-corporate-bright .bs-footer { background: rgba(0,0,0,.75); color: #fff; }
body.theme-corporate-bright .bs-expl { color: rgba(0,0,0,.8); }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body { margin: 0; height: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
  color: var(--on);
  background: linear-gradient(180deg, var(--bg-top), var(--bg)) fixed;
  min-height: 100dvh;
}

.app {
  max-width: 560px;
  margin: 0 auto;
  padding: max(20px, env(safe-area-inset-top)) 20px calc(24px + env(safe-area-inset-bottom));
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.screen { display: flex; flex-direction: column; gap: var(--space); flex: 1; }

/* Brand */
.brand { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.brand .logo { font-size: 26px; }
/* The actual neon owl instead of the 🦉 emoji, sized to match the old glyph. */
.logo-owl { height: 30px; width: auto; display: block; flex: 0 0 auto; }
.brand h1 { font-size: 18px; margin: 0; font-weight: 800; }

/* Brand hero — the app's actual neon owl plus a glowing wordmark (the same
   cyan neon as the iOS launch/home screen), centred at the top of entry
   screens (team join, creator sign-in) instead of the plain 🦉 emoji. The
   owl PNG carries its own baked glow, so it needs no extra shadow. */
.brand-hero { display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; margin: 6px 0 4px; }
.brand-hero img { width: clamp(104px, 34vw, 158px); height: auto; display: block; }
.brand-hero h1 {
  margin: 0; font-size: clamp(28px, 9vw, 42px); font-weight: 800; letter-spacing: .3px; color: #fff;
  text-shadow: 0 0 8px rgba(0,240,255,.55), 0 0 22px rgba(0,240,255,.30);
}
.brand-hero .tagline { margin: 2px 0 0; font-size: 14px; color: var(--muted); }
.spacer { flex: 1; }

/* Cards */
.card {
  background: var(--surface);
  border: 1px solid var(--outline);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: 0 6px 18px rgba(0,0,0,.25);
}
.center { text-align: center; }
.muted { color: var(--muted); }
.h-lg { font-size: clamp(22px, 6vw, 30px); font-weight: 800; margin: 0; }
/* overflow-wrap here (not on .card generally) so long unbroken strings like
   emails wrap inside their card instead of overflowing it, without affecting
   short neighboring content (e.g. a badge) that shares the same card. */
.h-md { font-size: 20px; font-weight: 700; margin: 0; overflow-wrap: anywhere; }
.big-emoji { font-size: 72px; text-align: center; margin: 8px 0; }

/* Badges */
.badges { display: flex; gap: 8px; flex-wrap: wrap; }
.badge {
  font-size: 12px; font-weight: 700; color: var(--primary);
  background: rgba(140,92,245,.16); padding: 5px 10px; border-radius: 999px;
  /* Whole chips may wrap onto the next line (.badges flex-wrap), but a chip
     never breaks mid-text ("Pub / Regular"). */
  white-space: nowrap;
}
.badge.amber { color: var(--secondary); background: rgba(250,158,74,.16); }

/* Frozen header row (Excel-style "freeze top row"): pinned to the top of
   the screen while the question/reveal card, answer sheet or ranking list
   scrolls underneath it, so remaining time/question count/category stay
   visible without scrolling back up.
   Genuinely `position: fixed`, not `sticky` — sticky was tried first, but
   this row's natural parent (`.screen`) is `display:flex;
   flex-direction:column`, and `position: sticky` on a flex item nested
   inside `.app`'s own flex column is a well-documented real-world Safari/
   WebKit bug: it tests fine in Chromium but silently fails to actually
   stick once a real iPhone scrolls it. `position: fixed` isn't affected by
   ancestor flex/scroll context at all, so it has no such caveat — the
   trade-off is `.ingame-topbar-spacer` below, a same-height flow spacer so
   the fixed bar doesn't render over the content it now sits outside of.
   `--bg-top` is exactly what's behind it at y=0 — the page background is
   `fixed`, so that colour never changes with scroll position. */
.ingame-topbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 20;
  max-width: 560px;
  margin: 0 auto;
  box-sizing: border-box;
  background: var(--bg-top);
  padding: max(10px, env(safe-area-inset-top)) 20px 10px;
  border-bottom: 1px solid var(--outline);
}
.ingame-topbar .brand { margin-bottom: 8px; }
/* Reserves the flow space the fixed bar above occupies, so the card/answer
   list doesn't start out hidden underneath it. Sized generously (brand row
   + up to two wrapped lines of badges + paddings) rather than pixel-exact —
   a sliver of extra whitespace beats clipped content on a slide with more
   badges than usual (wipeout + song + last-question + timer, all at once). */
.ingame-topbar-spacer {
  height: calc(env(safe-area-inset-top) + 120px);
}

/* Forms & buttons */
label { font-size: 13px; color: var(--muted); display: block; margin-bottom: 6px; }
input[type=text], input[type=number], input[type=password], input[type=email], textarea, select {
  width: 100%; font-size: 18px; padding: 15px 16px; color: var(--on);
  background: var(--surface-hi); border: 1px solid var(--outline);
  border-radius: 14px; outline: none;
}
textarea { font-family: inherit; resize: vertical; }
input:focus, textarea:focus, select:focus { border-color: var(--primary); }
input[type=file] { width: 100%; font-size: 13px; color: var(--muted); }
/* Fields flagged by a failed save (create.js applyValidationHighlights).
   .invalid = a blocking error (red); .warn-field = an optional-but-recommended
   gap (amber) that only warns — the save still goes through on a 2nd click. */
.invalid, input.invalid, textarea.invalid, select.invalid {
  border-color: #ed5a6b !important;
  box-shadow: 0 0 0 2px rgba(237,90,107,.35);
}
.warn-field, input.warn-field, textarea.warn-field, select.warn-field, .btn.warn-field {
  border-color: #fa9e4a !important;
  box-shadow: 0 0 0 2px rgba(250,158,74,.38);
}
.code-input { text-transform: uppercase; letter-spacing: 6px; text-align: center; font-weight: 800; }
/* A submitted free-text / estimate answer is dimmed to a faint grey until its
   field is focused again — so a glance at a shared phone can't read what was
   entered. Mid-grey works legibly-faint on both dark and light templates. */
input.ans-dim { color: rgba(150,150,150,.5) !important; }

button { font-family: inherit; cursor: pointer; }
.btn {
  width: 100%; min-height: 52px; font-size: 17px; font-weight: 700;
  /* Not a fixed white — some templates' --primary is itself light (Neon's
     cyan, Corporate Dark's near-white grey), where white text would be
     nearly invisible. --on-primary picks dark or light per template so
     this always reads. */
  color: var(--on-primary); background: var(--primary); border: none; border-radius: 14px;
  padding: 15px; transition: transform .1s ease, filter .1s ease;
}
.btn:active { transform: scale(.98); filter: brightness(.92); }
/* --surface-hi is always a light/dark "raised" step off --bg, same
   direction as the template's own base — the template's normal text
   colour (--on) already reads fine on it, no separate token needed. */
.btn.secondary { background: var(--surface-hi); color: var(--on); }
.btn.amber { background: var(--secondary); color: var(--on-secondary); }
.btn:disabled { opacity: .5; }

/* Options (choice questions) */
.options { display: flex; flex-direction: column; gap: 10px; }
.option {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: 56px; text-align: left; font-size: 17px; font-weight: 600; color: var(--on);
  /* --surface, not a flat white tint — the latter all but vanished against
     Corporate Bright's already-near-white page. One step below the .key
     badge's --surface-hi, so the badge still reads as raised off the row. */
  background: var(--surface); border: 2px solid transparent;
  border-radius: 14px; padding: 12px 14px;
}
.option .key {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 10px;
  display: grid; place-items: center; font-weight: 800;
  background: var(--surface-hi); color: var(--primary);
}
.option.selected { border-color: var(--primary); background: rgba(140,92,245,.14); }
.option.selected .key { background: var(--primary); color: var(--on-primary); }
.option.correct { border-color: var(--success); background: rgba(46,199,121,.16); }
.option.correct .key { background: var(--success); color: var(--on-success); }

/* Result banners */
.result { border-radius: var(--radius); padding: 22px; text-align: center; }
.result.win { background: rgba(46,199,121,.16); border: 1px solid rgba(46,199,121,.4); }
.result.lose { background: rgba(237,90,107,.14); border: 1px solid rgba(237,90,107,.35); }
.result .points { font-size: 40px; font-weight: 800; }
.result .result-emoji { font-size: 44px; }

/* Ranking */
.rank-row {
  display: flex; align-items: center; gap: 12px;
  background: var(--surface); border: 1px solid var(--outline);
  border-radius: 14px; padding: 12px 14px;
}
.rank-row .pos { width: 26px; font-weight: 800; color: var(--muted); }
.rank-row.me { border-color: var(--primary); }
.rank-row .score { margin-left: auto; font-weight: 800; font-variant-numeric: tabular-nums; }

/* Lobby roster — the "who's already here" chips shown while waiting for the
   host to start. Own team highlighted. */
.lobby-teams { display: flex; flex-wrap: wrap; gap: 8px; }
.lobby-team {
  font-size: 14px; font-weight: 600; color: var(--on);
  background: var(--surface-hi); border: 1px solid var(--outline);
  padding: 8px 12px; border-radius: 999px;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lobby-team.me { border-color: var(--primary); color: var(--primary); }

/* Score chip */
.scorechip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--surface); border: 1px solid var(--outline);
  padding: 8px 14px; border-radius: 999px; font-weight: 700;
}

/* Toast */
.toast {
  position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%);
  background: var(--danger); color: var(--on-danger); padding: 12px 18px; border-radius: 12px;
  font-weight: 600; box-shadow: 0 8px 24px rgba(0,0,0,.4); z-index: 10;
}

.status-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.status-dot.off { background: var(--danger); }
.pulse { animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .45 } }
@media (prefers-reduced-motion: reduce) { .pulse { animation: none } .btn:active { transform: none } }

/* Host-specific */
.code {
  font-size: 52px; font-weight: 800; letter-spacing: 10px;
  color: var(--secondary); margin: 6px 0;
}
input[type=checkbox] { width: 20px; height: 20px; accent-color: var(--primary); }

/* ---- Quiz creator: a desktop tool -------------------------------------
   Unlike the team/host clients (which live in a phone's hand), building a
   quiz is a laptop job. create.html tags its <main> with `.creator`, and
   ONLY that page breaks out of the 560px phone column to use the whole
   window — questions flow into as many columns as fit instead of a single
   tall stack. Everything still collapses back to one column below the
   breakpoint, so a phone keeps a usable (if cramped) editor. No other page
   is affected. */
.creator .field { margin-bottom: 12px; }
/* q-grid / list-grid are single-column grids on phones (same spacing as
   the old stacked cards) and become multi-column on a wide screen. */
.creator .q-grid, .creator .list-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
.creator .q-grid { gap: 10px; }

/* "Add question" tile — replaces the old button-under-the-grid. It's the last
   cell of the q-grid, so the "+" sits exactly where the next question appears.
   Phone (single column): a slim, HINTED bar — not a full card — so it doesn't
   blow up the page height. Desktop rule below stretches it to fill the empty
   cell beside the last question. Keeps the .add-question class → same handler. */
.creator .q-grid .add-tile {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 11px 14px; cursor: pointer;
  font: inherit; color: var(--primary); font-weight: 600; font-size: 13px;
  background: rgba(140, 92, 245, .06);
  border: 1.5px dashed rgba(140, 92, 245, .5); border-radius: 12px;
  transition: background .15s ease, border-color .15s ease, transform .12s ease;
}
.creator .q-grid .add-tile:hover { background: rgba(140, 92, 245, .13); border-color: var(--primary); }
.creator .q-grid .add-tile:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.creator .q-grid .add-tile .add-tile-plus {
  display: grid; place-items: center; width: 26px; height: 26px; border-radius: 50%;
  font-size: 19px; line-height: 1; font-weight: 400;
  background: rgba(140, 92, 245, .16); border: 1px solid rgba(140, 92, 245, .45);
}

/* View toggle (Standard ⇄ Bulk) at the very top of the editor. */
.creator .view-toggle { display: inline-flex; gap: 4px; background: var(--surface-hi); border: 1px solid var(--outline); border-radius: 12px; padding: 4px; margin-bottom: 14px; }
.creator .vt-btn { border: none; background: transparent; color: var(--muted); font-weight: 700; font-size: 14px; padding: 9px 18px; border-radius: 9px; cursor: pointer; }
.creator .vt-btn.active { background: var(--primary); color: #fff; }

/* The rounded card per round IS the visual grouping of its questions — give
   it a touch more presence than a plain card, and keep its own fields from
   stretching the full width. */
.creator .round-card { border-color: rgba(140,92,245,.30); }
.creator .round-head { display: flex; gap: 10px; align-items: center; }
.creator .round-title { max-width: 440px; }
.creator .round-type { max-width: 340px; }

/* Compact question cards so up to five fit across without shouting. */
.creator .q-grid .card { padding: 12px; }
.creator .q-grid .card label { font-size: 12px; margin-bottom: 4px; }
.creator .q-grid .card input[type=text], .creator .q-grid .card input[type=number],
.creator .q-grid .card textarea, .creator .q-grid .card select { font-size: 14px; padding: 9px 10px; border-radius: 10px; }
/* Inline optional-field checkboxes (Image / Audio side by side; Explanation). */
.creator .opt-toggles { display: flex; gap: 18px; flex-wrap: wrap; margin-top: 10px; }
.creator .opt-check { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; font-size: 13px; margin: 0; color: var(--on); }
/* The round's two toggles stacked directly under each other (not side by side),
   grouped under the category. */
.creator .round-opts { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-top: 10px; }
.creator .opt-field { margin-top: 8px; }
/* Bulk grid: the trailing empty ENTRY row is dimmed (a placeholder) until you
   click into it — then it takes the normal row colour and a fresh dimmed row
   appears below, so there's always one clearly-optional blank at the bottom. */
.creator #bulk-table tr.bulk-blank { opacity: .38; transition: opacity .15s ease; }
/* Per-row: cells that don't apply to the row's Type are greyed out and inert
   (A–D + ✓ only for choice; Accepted only for text; Number only for estimate). */
.creator #bulk-table .bulk-off { opacity: .28; pointer-events: none; }

@media (min-width: 880px) {
  /* Fluid: no fixed cap — the creator grows with the browser window; the
     question grid gains columns (up to five) the wider it gets. Side padding
     scales gently with the viewport so it never hugs the edges. */
  .app.creator { max-width: none; padding-left: clamp(24px, 3.5vw, 72px); padding-right: clamp(24px, 3.5vw, 72px); }

  /* Quiz meta stays a compact block (title full, difficulty beside a roomy
     description) — the single-line fields must NOT stretch across the screen;
     only the question grid uses the full width. */
  .app.creator .meta-grid { display: grid; grid-template-columns: 1fr 1.4fr; column-gap: 20px; max-width: 720px; }
  .app.creator .meta-grid .meta-wide { grid-column: 1 / -1; }
  .app.creator .meta-grid .field { margin-bottom: 14px; }

  /* Fixed column counts (not auto-fill) stepping 3 → 4 → 5 with width, so a
     five-question round lands on ONE row and is never split 3+2. */
  .app.creator .q-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; align-items: start; }
  .app.creator .list-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }

  /* On desktop the tile becomes a full cell that STRETCHES to the height of the
     last question card (align-self overrides the grid's align-items:start), so
     it fills the empty area beside the last question with a centred "+". */
  .app.creator .q-grid .add-tile {
    flex-direction: column; align-self: stretch; min-height: 150px;
    gap: 10px; padding: 16px; border-width: 2px; font-size: 13.5px;
  }
  .app.creator .q-grid .add-tile:hover { transform: translateY(-1px); }
  .app.creator .q-grid .add-tile .add-tile-plus { width: 44px; height: 44px; font-size: 26px; }

  /* Action buttons no longer stretch the full window width. */
  .app.creator .editor-actions { justify-content: flex-end; }
  .app.creator .editor-actions .btn { width: auto; min-width: 150px; padding-left: 26px; padding-right: 26px; }
  .app.creator .editor-tools .btn { width: auto; padding-left: 22px; padding-right: 22px; }
}
@media (min-width: 1180px) { .app.creator .q-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1480px) { .app.creator .q-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }

/* Segmented control (two-way toggle, e.g. reveal-mode preference) */
.segmented { display: flex; background: var(--surface-hi); border-radius: 14px; padding: 4px; gap: 4px; }
.segmented button {
  flex: 1; border: none; background: transparent; color: var(--muted);
  font-size: 14px; font-weight: 700; padding: 12px 10px; border-radius: 10px;
  transition: background .15s ease, color .15s ease;
}
.segmented button.active { background: var(--primary); color: #fff; }

/* Landscape phones (rotated): the portrait single-column layout wastes the
   wide screen and forces vertical scrolling on question/reveal screens.
   Compact the chrome, widen the column and lay multiple-choice options in a
   two-column grid so the same content fits without scrolling — nothing is
   hidden, only re-arranged. */
@media (orientation: landscape) and (max-height: 520px) {
  .app { max-width: 900px; padding-top: 10px; padding-bottom: 12px; }
  .screen { gap: 10px; }
  /* The logo row is pure chrome — in landscape every vertical pixel goes to
     the actual content instead. */
  .brand { display: none; }
  .scorechip { padding: 5px 12px; font-size: 14px; }
  .card { padding: 14px 16px; }
  .h-lg { font-size: 22px; }
  .h-md { font-size: 17px; }
  .big-emoji { font-size: 44px; margin: 4px 0; }
  .options { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
  .option { min-height: 46px; font-size: 15px; padding: 8px 12px; }
  .option .key { width: 28px; height: 28px; border-radius: 8px; }
  /* Result banner becomes one compact row: emoji · verdict · points. */
  .result { display: flex; align-items: center; justify-content: center; gap: 14px; padding: 10px 16px; }
  .result .result-emoji { font-size: 26px; }
  .result .points { font-size: 24px; }
  /* The "Waiting for the host…" line keeps its message but not its margins. */
  .screen p.pulse { margin: 2px 0; }
}
