/* Quiz scoring, visual system v2 (Maren), matching the reference image.
   Warm light ground. Dark floating capsule pills. One lime accent. Mobile-first.
   Rule that drives everything: controls CAST shadows, they never receive them. */

:root {
  /* surfaces */
  --bg:            #ECEDF0;
  --surface:       #FBFBFD;   /* cool near-white pills */
  --surface-sunk:  #E4E6EB;
  --feature:       #16181C;   /* the hero black, also the active pill */
  --feature-2:     #212429;
  --feature-raise: #20232A;

  /* text */
  --ink:           #1C1E22;
  --ink-soft:      #54575E;
  --ink-mute:      #63666D;   /* quiet but readable: clears 4.5:1 on every light surface
                                 it sits on, for a dim pub and a mixed-age crowd */
  --ink-ghost:     #8A8D94;   /* the old mute, kept for purely decorative marks only
                                 (dots, chevrons), never for words or figures */
  --on-feature:    #F6F7F4;
  --on-feature-mute:#9AA0A6;

  /* accent */
  --lime:          #BDDA4F;
  --lime-deep:     #97B838;
  --lime-ink:      #1F2A05;
  --lime-glow:     rgba(189,218,79,0.5);
  --lime-veil:     rgba(189,218,79,0.14);

  /* hairlines */
  --line:          rgba(28,30,34,0.08);
  --line-strong:   rgba(28,30,34,0.14);

  /* functional state tints */
  --state-saved:   #3F7D4E;  --state-saved-bg: #E4EFE3;
  --state-queued:  #9A6B1E;  --state-queued-bg:#F4EAD6;
  --state-error:   #B23B2E;  --state-error-bg: #F6E1DC;
  --state-lock:    #6E7178;  --state-lock-bg:  #E7E5DE;

  /* type */
  --font-ui:  "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-num: "Hanken Grotesk", system-ui, sans-serif;

  /* geometry */
  --r-pill: 999px; --r-card: 26px; --r-tile: 18px;
  /* The spacing scale, seven steps on a four pixel base. Every gap in the guest app is
     one of them, and the size of the gap is what says how strongly two things belong.
     --s-8 is the host console's alone: a desktop screen with room to spare. */
  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:24px; --s-6:32px; --s-7:40px;
  --s-8:64px;

  /* the float */
  --lift-1: 0 1px 1px rgba(36,33,26,0.04), 0 2px 4px rgba(36,33,26,0.06), 0 8px 16px rgba(36,33,26,0.08);
  --lift-2: 0 2px 4px rgba(36,33,26,0.05), 0 6px 12px rgba(36,33,26,0.10), 0 16px 30px rgba(36,33,26,0.12);
  --lift-press: 0 1px 2px rgba(36,33,26,0.10), 0 2px 4px rgba(36,33,26,0.08);
  --edge-dark: inset 0 1px 0 rgba(255,255,255,0.07);
  --edge-light: inset 0 1px 0 rgba(255,255,255,0.9);

  /* motion */
  --ease: cubic-bezier(.32,.72,0,1); --t-press:.13s; --t-state:.22s;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background-color: var(--bg);
  background-image: radial-gradient(circle at 1px 1px, rgba(28,30,34,0.04) 1px, transparent 0);
  background-size: 22px 22px;
  color: var(--ink);
  font: 400 16px/1.5 var(--font-ui);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums lining-nums;
}

.sr-only { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; }
.hidden { display: none !important; }
.muted { color: var(--ink-mute); }
.small { font-size: 0.6875rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }

/* ================================================================
   THE GUEST APP SHELL
   ================================================================
   The guest app has to feel like an app in the hand, not a page in a browser, so the
   shell fills the visual viewport exactly and the document itself never scrolls. Scoped
   to html.guest so the host console, which is a working desktop screen and must scroll,
   is untouched.

   Three bands on every stage:
     top     fixed, who this phone is
     middle  the only thing allowed to scroll, and only when its content really exceeds it
     bottom  fixed, where we are in the night

   Spacing anywhere in the guest app comes from one seven-step scale on a four pixel base:
   4, 8, 12, 16, 24, 32, 40. Type comes from one five-step scale: 10 eyebrow, 13 label,
   16 body, 20 title, 48 display. The one deliberate exception is the 28 under the last
   progress row, which Scott set by eye and which is recorded in the design brief. */
html.guest, html.guest > body {
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
}
.app-shell {
  position: fixed; top: 0; left: 0; right: 0;
  height: 100vh;                       /* floor for anything without dvh */
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}
@supports (height: 100dvh) { .app-shell { height: 100dvh; } }
/* app.js sets an inline pixel height from visualViewport where the browser has it, which
   is what makes an iOS keyboard shrink the shell rather than float over the button. */

.app-top, .app-bot, .entry { width: 100%; max-width: 460px; margin-inline: auto; padding-inline: 20px; }
.app-top, .app-bot { flex: 0 0 auto; }
.app-top { padding-top: var(--s-5); }

.app-mid {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.entry { min-height: 100%; display: flex; flex-direction: column; padding-block: 0; }
.screen { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
/* A pane is a band-filling column. pane-centre balances a short screen in the space it
   has instead of stranding it at the top with two thirds of empty ground below. Every
   ladder state centres, the live one included: on a tall phone the slack used to fall in
   one lump between the button's caption and the progress band, about 233px of empty
   ground on a 390 by 844, which read as a page that had run out rather than a screen. The
   gap above the stake card grows instead, and that supersedes the stated 40 from the
   identity row on a tall screen. The floor stays 24, held by the identity row's own
   margin, so a short phone is unchanged.

   safe center is the whole trick. Plain centring in a column that overflows pushes the
   top of the content above the scroll origin, where no gesture can reach it, which on
   this screen would be the stake card saying what the clue is worth. safe falls back to
   flex-start the moment the content is taller than the band, which is exactly the
   keyboard-open case. Guarded by @supports so an older browser keeps today's behaviour
   rather than inheriting the unreachable-overflow bug. */
.pane { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
.pane-centre { justify-content: center; }
@supports (justify-content: safe center) { .pane-centre { justify-content: safe center; } }
.pane-title { display: block; font: 800 20px/1.25 var(--font-ui); letter-spacing: -0.01em; margin: 0 0 var(--s-2); padding-left: 4px; }
.pick-help { margin: var(--s-3) 4px 0; font: 500 13px/1.45 var(--font-ui); color: var(--ink-mute); }
/* Between ladders there is one line and a live dot, and nothing else. The round is named
   by the bottom band and the clues are read aloud, so the card has no other work to do. */
.hold-card { text-align: center; padding-bottom: var(--s-5); }
.hold-card .hero-headline { margin: 0; }
.hold-card .breathe-dot { margin-top: var(--s-5); }

/* ---- top band: who this phone is ---- */
.who { display: flex; align-items: center; gap: var(--s-2); margin-bottom: var(--s-5); }
.who-label { flex: 0 0 auto; font: 700 10px/1.4 var(--font-ui); text-transform: uppercase; letter-spacing: .14em; color: var(--ink-mute); }
.who-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 700 16px/1.4 var(--font-ui); color: var(--ink); }
.who-change { flex: 0 0 auto; margin-left: auto; margin-right: -12px; padding: var(--s-2) var(--s-3); border: 0; background: transparent; color: var(--ink-mute); font: 600 13px/1.4 var(--font-ui); text-decoration: underline; cursor: pointer; }
.who-change:active { color: var(--ink); }

/* ---- bottom band: two scopes, two bars ---- */
.app-bot { padding-top: var(--s-4); padding-bottom: 28px; }
.prog + .prog { margin-top: var(--s-3); }
.prog-label { display: block; font: 700 10px/1.4 var(--font-ui); text-transform: uppercase; letter-spacing: .14em; color: var(--ink-mute); margin-bottom: var(--s-2); }
.prog-pips { display: flex; align-items: center; gap: 6px; height: 18px; }
.pip { flex: 1 1 0; min-width: 0; height: 8px; border-radius: 2px; background: rgba(28,30,34,0.13); }
.pip.is-done { background: rgba(28,30,34,0.32); }
.pip.is-live { height: 18px; border-radius: 3px; background: var(--ink); }

/* ---- the credit, which is chrome and yields ---- */
.app-credit { margin-top: auto; padding-top: var(--s-5); text-align: center; }
.app-credit .app-sig { margin: 0; }
.app-credit .app-ver { margin: 4px auto 0; }
.app-shell[data-stage="ladder"] .app-credit { display: none; }

/* ---- the keyboard, which is the real risk on this app ----
   With the page locked and the shell pinned to the visual viewport, an on-screen keyboard
   would otherwise bury the Lock in button and cost a team its answer. So when the answer
   box takes focus the bottom band stands down, the credit goes, and the middle compresses
   and scrolls the input and the button into the space left above the keyboard. */
.app-shell.kb-open .app-bot,
.app-shell.kb-open .app-credit { display: none; }

/* ---------------- shared pill controls ---------------- */
.btn-primary, .btn-secondary, .btn-danger {
  width: 100%; min-height: 56px; padding: 17px 24px; margin-top: var(--s-4);
  font: 700 1.05rem var(--font-ui); border: 0; border-radius: var(--r-pill); cursor: pointer;
  transition: transform var(--t-press) var(--ease), box-shadow var(--t-state) var(--ease), background var(--t-state);
}
.btn-primary { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark); }
.btn-primary:active { transform: translateY(1px) scale(.985); box-shadow: var(--lift-press), var(--edge-dark); }
.btn-primary:disabled { background: var(--surface-sunk); color: var(--ink-mute); box-shadow: none; transform: none; cursor: not-allowed; }
.btn-secondary { background: var(--surface); color: var(--ink); box-shadow: var(--lift-1), var(--edge-light); }
.btn-secondary:active { transform: translateY(1px) scale(.985); box-shadow: var(--lift-press), var(--edge-light); }
.btn-danger { background: transparent; color: var(--state-error); box-shadow: inset 0 0 0 1.5px var(--state-error); }
.btn-danger:active { transform: translateY(1px) scale(.985); }
.btn-mini { width: auto; margin: 0; min-height: 40px; padding: 9px 18px; font: 600 0.8rem var(--font-ui); border: 0; border-radius: var(--r-pill); background: var(--surface); color: var(--ink); box-shadow: var(--lift-1), var(--edge-light); cursor: pointer; transition: transform var(--t-press) var(--ease), box-shadow var(--t-state); }
.btn-mini:active { transform: translateY(1px) scale(.96); box-shadow: var(--lift-press); }
.btn-mini-danger { color: var(--state-error); box-shadow: inset 0 0 0 1.5px rgba(178,59,46,.4); background: transparent; }

.icon-btn { width:48px; height:48px; padding:0; flex:0 0 48px; border:0; border-radius:var(--r-pill); background:var(--surface); color:var(--ink); box-shadow:var(--lift-1), var(--edge-light); display:grid; place-items:center; cursor:pointer; transition:transform var(--t-press) var(--ease), box-shadow var(--t-state); }
.icon-btn:active { transform: translateY(1px) scale(.96); box-shadow: var(--lift-press), var(--edge-light); }
.icon-btn svg { width: 22px; height: 22px; }

.select-lg {
  width: 100%; min-height: 56px; font: 600 1.0625rem var(--font-ui); color: var(--ink);
  background: var(--surface); border: 0; border-radius: var(--r-pill); box-shadow: var(--lift-1), var(--edge-light);
  padding: 16px 52px 16px 24px; appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 256 256' fill='%238A8D94'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 22px center;
  transition: box-shadow var(--t-state) var(--ease), transform var(--t-press) var(--ease), background var(--t-state);
}
.select-lg:focus-visible { outline: none; box-shadow: var(--lift-2), 0 0 0 2px var(--feature); }
.select-lg:active { transform: translateY(1px) scale(.99); box-shadow: var(--lift-press), var(--edge-light); }
.select-lg.is-set {
  background-color: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark);
  background-repeat: no-repeat; background-position: right 22px center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 256 256' fill='%239AA0A6'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z'/%3E%3C/svg%3E");
}
.select-sm { width: 110px; min-height: 56px; padding: 16px; text-align: center; font: 600 1.0625rem var(--font-ui); color: var(--ink); background: var(--surface); border: 0; border-radius: var(--r-pill); box-shadow: var(--lift-1), var(--edge-light); }
input.select-lg, input.select-sm { -webkit-appearance: none; appearance: none; }
input.select-lg { background-image: none; padding-right: 24px; }

.signup-hint { margin: var(--s-4) 4px 0; color: var(--ink-mute); font: 500 0.85rem/1.5 var(--font-ui); }
.taken-names { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid var(--line); }
.taken-names-label { display: block; font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); margin-bottom: var(--s-3); }
.taken-names-list { display: flex; flex-wrap: wrap; gap: 6px; }
.taken-chip { font: 600 0.8125rem var(--font-ui); color: var(--ink-soft); background: var(--surface); padding: 6px 13px; border-radius: var(--r-pill); box-shadow: var(--lift-1), var(--edge-light); }

.warn { color: var(--state-queued); background: var(--state-queued-bg); box-shadow: inset 0 0 0 1.5px rgba(154,107,30,0.25); padding: 12px 16px; border-radius: var(--r-tile); margin: var(--s-3) 0 0; font-weight: 500; }

.hero-card { background: var(--feature); color: var(--on-feature); border-radius: var(--r-card); padding: var(--s-5) var(--s-5) 50px; box-shadow: var(--lift-2), var(--edge-dark); position: relative; overflow: hidden; }
.hero-card .eyebrow { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--on-feature-mute); }

/* ---------------- entry ---------------- */
/* .entry's box now comes from the shell block above: the page no longer scrolls, so the
   old top padding and the tall bottom padding that made room for the fixed offline bar
   have both gone. */
.topbar h1 { margin: 0 0 4px; font: 800 1.625rem var(--font-ui); letter-spacing: -0.02em; }
.topbar .sub { margin: 0 0 var(--s-5); color: var(--ink-soft); }

.entry-total { margin: 0 0 var(--s-5); padding: var(--s-5) var(--s-5) var(--s-4); background: var(--feature); color: var(--on-feature); border-radius: var(--r-card); box-shadow: var(--lift-2), var(--edge-dark); position: relative; overflow: hidden; }
.entry-total .eyebrow { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .14em; color: var(--on-feature-mute); }
.entry-total .team { font: 700 1.0625rem var(--font-ui); margin-top: 2px; }
.entry-total .figure { font: 800 3.25rem/1 var(--font-num); font-variant-numeric: tabular-nums; color: var(--lime); margin: var(--s-3) 0 var(--s-1); letter-spacing: -0.02em; }
.entry-total .progress { font: 600 0.8125rem var(--font-ui); color: var(--on-feature-mute); }

.big-label { display: block; font: 700 0.9375rem var(--font-ui); padding-left: 4px; margin: var(--s-5) 0 var(--s-2); }
.help { color: var(--ink-mute); margin: var(--s-2) 4px; }
.rounds { margin-top: var(--s-5); }
.rounds-hold { margin: var(--s-4) 0; padding: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); color: var(--ink-soft); font: 500 0.95rem/1.5 var(--font-ui); text-align: center; }

.row { display: flex; flex-direction: column; gap: var(--s-2); padding: 10px 0; }
.row-label { font: 600 0.8125rem var(--font-ui); color: var(--ink-soft); padding-left: 16px; }

/* the pill shell wraps input + status glyph as one floating capsule */
.in-wrap {
  display: flex; align-items: center; gap: 8px; padding: 8px 12px;
  background: var(--surface); border-radius: var(--r-pill);
  box-shadow: var(--lift-1), var(--edge-light);
  transition: box-shadow var(--t-state) var(--ease), background var(--t-state) var(--ease), transform var(--t-press) var(--ease);
}
.score-input {
  flex: 1; min-width: 0; padding: 12px 4px 12px 12px;
  font: 800 1.625rem/1 var(--font-num); font-variant-numeric: tabular-nums lining-nums;
  text-align: left; color: var(--ink); background: transparent; border: 0; border-radius: 0;
  box-shadow: none; -webkit-appearance: none;
}
.score-input:focus { outline: none; }
.score-input::placeholder { color: var(--ink-mute); font-weight: 700; }

/* focused = active pill goes near-black, number turns white */
.in-wrap:focus-within { background: var(--feature); box-shadow: var(--lift-2), var(--edge-dark); }
.in-wrap:focus-within .score-input { color: var(--on-feature); }
.in-wrap:focus-within .score-input::placeholder { color: var(--on-feature-mute); }

/* saved = stays dark, number turns lime, thin lime ring */
.row:has(.is-saved) .in-wrap { background: var(--feature); box-shadow: var(--lift-2), 0 0 0 1.5px var(--lime-glow), var(--edge-dark); }
.row:has(.is-saved) .score-input { color: var(--lime); }
/* queued = dark + amber ring */
.row:has(.is-queued) .in-wrap { background: var(--feature); box-shadow: var(--lift-2), 0 0 0 1.5px var(--state-queued), var(--edge-dark); }
.row:has(.is-queued) .score-input { color: var(--on-feature); }
/* error = dark + thick red ring + highest lift */
.row:has(.is-error) .in-wrap { background: var(--feature); box-shadow: var(--lift-2), 0 0 0 2px var(--state-error), var(--edge-dark); }
.row:has(.is-error) .score-input { color: #fff; }
/* locked = the one control that does NOT float; it sits down, inert */
.row:has(.is-locked) .in-wrap { background: var(--surface-sunk); box-shadow: none; }
.row:has(.is-locked) .score-input { color: var(--ink-soft); }
/* changed elsewhere = another phone's write won; dark + thick amber caution ring */
.row:has(.is-changed) .in-wrap { background: var(--feature); box-shadow: var(--lift-2), 0 0 0 2px var(--state-queued), var(--edge-dark); }
.row:has(.is-changed) .score-input { color: var(--on-feature); }

/* over the round's max: the save still happens, but the pill goes caution and
   the row says why. This ring outranks the state ring below it in the sheet. */
.row-help { margin: 2px 16px 0; font: 600 0.8125rem var(--font-ui); color: var(--state-queued); }
.row.over-max .in-wrap { box-shadow: var(--lift-2), 0 0 0 2px var(--state-queued), var(--edge-dark); }

/* status glyph as a compact round badge at the pill's right end */
.status { flex: 0 0 auto; width: 40px; height: 40px; padding: 0; display: grid; place-items: center; border: 0; border-radius: var(--r-pill); background: rgba(255,255,255,0.08); color: var(--on-feature-mute); font: 700 0.95rem var(--font-num); cursor: pointer; transition: all var(--t-state) var(--ease); }
.status-txt { display: none; }
.status .status-icon { display: grid; place-items: center; line-height: 0; }
.status svg { width: 19px; height: 19px; display: block; }
.status:active { transform: scale(.92); }
.status.is-empty   { visibility: hidden; }
.status.is-editing { background: rgba(255,255,255,0.08); color: var(--on-feature-mute); }
.status.is-saving  { color: var(--on-feature); }
.status.is-saving svg { animation: spin .8s linear infinite; }
.status.is-saved   { background: var(--lime); color: var(--lime-ink); }
.status.is-queued  { background: var(--state-queued-bg); color: var(--state-queued); }
.status.is-error   { background: var(--state-error); color: #fff; }
.status.is-locked  { background: rgba(28,30,34,0.06); color: var(--state-lock); cursor: default; }
.status.is-changed { background: var(--state-queued-bg); color: var(--state-queued); }

/* Sign toggle: flip a round total below zero (the Wager). Calm by default, filled when the
   value is negative so the marker can see the minus is on. A negative is a state, not an error. */
.sign-toggle { flex: 0 0 auto; width: 40px; height: 40px; padding: 0; display: grid; place-items: center; border: 0; border-radius: var(--r-pill); background: rgba(28,30,34,0.06); color: var(--ink-mute); font: 800 1.25rem/1 var(--font-num); cursor: pointer; transition: all var(--t-state) var(--ease); }
.sign-toggle:active { transform: scale(.92); }
.in-wrap:focus-within .sign-toggle { background: rgba(255,255,255,0.08); color: var(--on-feature-mute); }
.row.is-neg .sign-toggle { background: var(--ink); color: var(--surface); }
.row:has(.is-locked) .sign-toggle { visibility: hidden; }

.signoff { margin-top: var(--s-6); padding-top: var(--s-5); border-top: 1px solid var(--line); }
.done { margin-top: var(--s-5); }
.done-hero { text-align: center; }
.done-tick { color: var(--lime); margin: var(--s-2) 0; line-height: 0; }
.done-tick svg { width: 56px; height: 56px; display: inline-block; }
.done-msg { margin: 0; color: var(--on-feature); font: 600 1.05rem var(--font-ui); }

.offline-bar { position: fixed; left: var(--s-4); right: var(--s-4); bottom: calc(var(--s-4) + env(safe-area-inset-bottom)); margin: 0; padding: 14px 18px; background: var(--state-queued); color: #fff; font: 600 0.9rem var(--font-ui); text-align: center; border-radius: var(--r-pill); box-shadow: var(--lift-2); }

/* ---------------- admin (mobile) ---------------- */
.admin { background-color: var(--bg); }
.login { max-width: 460px; margin: 8vh auto; padding: var(--s-6) var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.login h1 { margin: 0 0 var(--s-4); font: 800 1.625rem var(--font-ui); }

.dash { max-width: 460px; margin: 0 auto; padding: var(--s-6) 20px var(--s-8); }
.dash-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); }
.dash-head h1 { margin: 0; font: 800 1.5rem var(--font-ui); letter-spacing: -0.01em; }
.dash-tag { font: 700 0.7rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--ink-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dash-actions { display: flex; align-items: center; gap: var(--s-3); }
.dash-actions .btn-secondary { width: auto; margin: 0; min-height: 44px; padding: 11px 18px; font-size: 0.95rem; }
.live-dot { width: 9px; height: 9px; border-radius: var(--r-pill); background: var(--ink-ghost); transition: background .2s; }
.live-dot.pulse { background: var(--state-saved); animation: pulse-ring .6s ease-out; }


.board { margin-top: var(--s-6); }
.grid-section { margin-top: var(--s-6); }
.board h2, .grid-section h2 { font: 800 1.05rem var(--font-ui); margin: 0 0 var(--s-3); }
.board-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
/* the freshness stamp: quiet while the poll is healthy, amber the moment it is not */
.upd-stamp { font: 600 0.75rem var(--font-ui); color: var(--ink-mute); white-space: nowrap; }
.upd-stamp.stale { color: var(--state-queued); }
.board h3 { font: 600 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); margin: var(--s-4) 0 var(--s-2); }

.leaderboard { display: flex; flex-direction: column; gap: var(--s-3); }
.lb-row { display: grid; grid-template-columns: 36px 1fr auto; align-items: center; gap: var(--s-3); padding: var(--s-4); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.lb-rank { font: 800 1rem var(--font-num); color: var(--ink-mute); text-align: center; }
.lb-name { font: 700 1.0625rem var(--font-ui); }
.lb-meta { grid-column: 2 / 4; display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.lb-total { font: 800 1.75rem var(--font-num); font-variant-numeric: tabular-nums; text-align: right; grid-row: 1; grid-column: 3; }
.lb-row.leader { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark); padding: var(--s-5) var(--s-4); }
.lb-row.leader .lb-rank, .lb-row.leader .lb-total { color: var(--lime); }
.lb-row.leader .lb-name { color: var(--on-feature); }
.lb-row.leader .meta { background: rgba(255,255,255,.10); color: var(--on-feature-mute); }
#incompleteBlock .lb-row { background: transparent; box-shadow: none; border: 1.5px dashed var(--line-strong); }

.meta { display: inline-flex; align-items: center; gap: 4px; font: 600 0.75rem var(--font-ui); color: var(--ink-soft); background: var(--surface-sunk); padding: 3px 11px; border-radius: var(--r-pill); }
.meta.unsigned { color: var(--state-queued); background: var(--state-queued-bg); }
.meta.selfmark { color: var(--state-queued); background: var(--state-queued-bg); }

.alerts { margin-top: var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); }
.alerts:empty { margin-top: 0; }
.alert { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-pill); font: 500 0.88rem var(--font-ui); box-shadow: var(--lift-1); }
.alert-conflict { background: var(--state-error-bg); color: var(--state-error); }
.alert-unsigned { background: var(--state-queued-bg); color: var(--state-queued); }
.alert-claim    { background: var(--state-queued-bg); color: var(--state-queued); }
.alert strong { font-weight: 700; }
.alert .btn-mini { background: var(--surface); }

/* every-score: per-team expandable cards */
.grid-section { margin-top: var(--s-6); }
.grid-wrap { display: block; }
.score-cards { display: flex; flex-direction: column; gap: var(--s-3); }
.score-card { background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); overflow: hidden; }
.score-card > summary { list-style: none; }
.score-card > summary::-webkit-details-marker { display: none; }
.score-card-head { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-4); cursor: pointer; min-height: 56px; }
.score-card-name { flex: 1; font: 700 1.0625rem var(--font-ui); }
.score-card-flag { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 999px; background: var(--state-error); }
.score-card-total { font: 800 1.375rem var(--font-num); }
.score-card-chev { flex: 0 0 auto; width: 22px; height: 22px; color: var(--ink-ghost); transition: transform var(--t-state) var(--ease); }
.score-card[open] .score-card-chev { transform: rotate(180deg); }
.score-card-body { padding: 0 var(--s-4) var(--s-4); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
.round-cell { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 10px 14px; border-radius: var(--r-pill); background: var(--bg); font: 600 0.8125rem var(--font-ui); color: var(--ink-soft); }
/* the cells are buttons now (tap to set a score), so strip the UA chrome */
button.round-cell { border: 0; margin: 0; width: 100%; text-align: left; cursor: pointer; -webkit-appearance: none; appearance: none; }
.round-cell .rc-val { font: 800 0.95rem var(--font-num); color: var(--ink); }
.round-cell.cell-empty .rc-val { color: var(--ink-ghost); } /* a placeholder dot, not a figure */
.round-cell.cell-conflict { background: var(--state-error-bg); box-shadow: inset 0 0 0 1.5px rgba(178,59,46,.4); color: var(--state-error); }
.round-cell.cell-conflict .rc-val { color: var(--state-error); }

.setup { margin-top: var(--s-6); border-top: 1px solid var(--line); padding-top: var(--s-4); }
.setup h2 { font: 800 1.05rem var(--font-ui); }
.setup-block { margin: var(--s-5) 0; }
.setup-block h3 { margin: 0 0 var(--s-2); font: 700 0.9rem var(--font-ui); }
.setup-block.danger h3 { color: var(--state-error); }
.inline { display: flex; gap: var(--s-2); align-items: center; flex-wrap: wrap; }
.inline .btn-secondary { width: auto; margin: 0; min-height: 56px; padding: 14px 18px; white-space: nowrap; }
.admin-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--s-3); }
.admin-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: 10px 10px 10px 18px; background: var(--surface); border-radius: var(--r-pill); box-shadow: var(--lift-1), var(--edge-light); }
.admin-row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

.seg { display: inline-flex; gap: 4px; padding: 4px; background: var(--surface-sunk); border-radius: var(--r-pill); box-shadow: inset 0 1px 3px rgba(36,33,26,0.12); }
.seg button { border: 0; padding: 10px 18px; border-radius: var(--r-pill); font: 600 0.875rem var(--font-ui); color: var(--ink-soft); background: transparent; cursor: pointer; transition: all .18s var(--ease); }
.seg button[aria-selected="true"] { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1); }
.seg button:disabled { opacity: .45; cursor: default; }

/* the board toggle (Sign-ups / Leaderboard / future) that sits under Now showing */
.board-seg { display: flex; width: 100%; margin-top: var(--s-6); }
.board-seg button { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 7px; }
.seg-badge { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--lime); color: var(--lime-ink); font: 800 0.75rem var(--font-num); }
.board-seg button[aria-selected="true"] .seg-badge { background: var(--lime); color: var(--lime-ink); }
.board-panel { margin-top: var(--s-5); }
.muted-hint { font: 600 0.72rem var(--font-ui); color: var(--ink-mute); }

/* leaderboard rows are expandable: tap a team to see and fix its round scores */
.lb-card { border-radius: var(--r-card); overflow: hidden; background: var(--surface); box-shadow: var(--lift-1), var(--edge-light); }
.lb-card + .lb-card { margin-top: var(--s-3); }
.lb-card > summary { list-style: none; cursor: pointer; }
.lb-card > summary::-webkit-details-marker { display: none; }
.lb-card .lb-row { display: grid; grid-template-columns: 34px 1fr auto 22px; align-items: center; gap: var(--s-3); background: transparent; box-shadow: none; }
.lb-card .lb-meta { grid-column: 2 / 5; }
.lb-card .score-card-chev { grid-row: 1; grid-column: 4; }
.lb-card[open] .score-card-chev { transform: rotate(180deg); }
.lb-card-body { padding: 0 var(--s-4) var(--s-4); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
.lb-card.leader .lb-card-body .round-cell { background: rgba(255,255,255,0.08); color: var(--on-feature-mute); }
.lb-card.leader .lb-card-body .round-cell .rc-val { color: var(--on-feature); }
.lb-card.leader { background: var(--feature); box-shadow: var(--lift-2), var(--edge-dark); }

/* ---------------- motion ---------------- */
@keyframes breathe { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: .45; transform: scale(.82); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes pulse-ring { 0% { box-shadow: 0 0 0 0 rgba(63,125,78,.5); } 100% { box-shadow: 0 0 0 8px rgba(63,125,78,0); } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
  .btn-primary:active, .btn-secondary:active, .icon-btn:active, .select-lg:active, .status:active, .btn-mini:active, .lad-lock:active, .rs-ctl:active, .lad-pill:active { transform: none !important; }
}

/* ---------------- UI polish pass ---------------- */
html { color-scheme: light; }
body { -webkit-tap-highlight-color: transparent; overflow-x: hidden; }
button, summary, .select-lg, .select-sm, .score-input, .status { touch-action: manipulation; }
button:focus-visible, summary:focus-visible { outline: 2px solid var(--lime-deep); outline-offset: 2px; }
.lb-name, .score-card-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-row > span:first-child { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---------------- console shell screens ---------------- */
.hero-headline { font: 800 1.875rem/1.12 var(--font-ui); letter-spacing: -0.02em; margin: var(--s-2) 0 var(--s-3); color: var(--on-feature); }
.hero-sub { color: var(--on-feature-mute); margin: 0; font-size: 0.95rem; line-height: 1.5; }
.breathe-dot { display: inline-block; width: 10px; height: 10px; border-radius: 999px; background: var(--lime); margin-top: var(--s-4); animation: breathe 3.2s ease-in-out infinite; }

/* Standby's tongue-in-cheek "we're watching your phone" gag: a cheeky line and a blinking
   red monitor light. All in good fun, and it makes phones-down feel policed just enough. */
.standby-cheeky { margin-top: var(--s-4); color: var(--on-feature); font-weight: 500; }
.monitor-strip { display: inline-flex; align-items: center; gap: 9px; margin-top: var(--s-5); padding: 9px 15px; border-radius: var(--r-pill); background: rgba(255,255,255,0.06); box-shadow: inset 0 0 0 1px rgba(255,255,255,0.08); }
.monitor-dot { width: 9px; height: 9px; border-radius: 999px; background: var(--state-error); box-shadow: 0 0 0 0 rgba(178,59,46,0.6); animation: monitor-blink 1.4s ease-in-out infinite; }
.monitor-text { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--on-feature-mute); }
@keyframes monitor-blink { 0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(178,59,46,0.55); } 50% { opacity: .35; box-shadow: 0 0 0 5px rgba(178,59,46,0); } }
.eyebrow-icn { width: 0.85em; height: 0.85em; vertical-align: -2px; }

.gag-card .gag-line { color: var(--on-feature); font: 600 1.0625rem/1.45 var(--font-ui); margin: var(--s-3) 0 var(--s-4); }
.gag-counter { display: flex; align-items: baseline; gap: var(--s-2); padding-top: var(--s-3); border-top: 1px solid var(--line-feature); }
.gag-counter-label { font: 600 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--on-feature-mute); }
.gag-count { font: 800 1.5rem var(--font-num); font-variant-numeric: tabular-nums; color: var(--lime); }
.gag-toggle { margin-top: var(--s-4); background: transparent; border: 0; color: var(--on-feature-mute); font: 600 0.85rem var(--font-ui); text-decoration: underline; cursor: pointer; padding: 0; }
.gag-fine { margin-top: var(--s-3); color: var(--on-feature-mute); font-size: 0.85rem; line-height: 1.5; }
.gag-fine p { margin: 0 0 var(--s-2); }
.gag-fine strong { color: var(--on-feature); }

.catchup-bar { display: block; width: 100%; margin: 0 0 var(--s-4); padding: 14px 18px; border: 0; background: var(--feature); color: var(--on-feature); font: 600 0.9rem var(--font-ui); text-align: center; border-radius: var(--r-pill); box-shadow: var(--lift-2), var(--edge-dark); cursor: pointer; }

/* ---------------- the Clue Ladder (participant) ---------------- */
/* One dark card says where we are (which ladder, which clue, what it is worth), then the
   answer box and the biggest control on any screen in the app: the Lock in button. The tap
   is the hand-in, so it has to be unmissable and impossible to hit by accident: it sits
   under the answer, and stays sunk until there is an answer to lock. */
/* The stake card. One statement top to bottom: where we are, what it is worth, what
   waiting costs. The caption is the point of it, because the cost of waiting is the
   decision the table is actually making, and it gives the line a job instead of leaving
   it a qualifier dangling off the figure. The ladder number is not on this card: the
   progress bar in the bottom band carries it, and having it in both places was the same
   count said twice. */
.stake { background: var(--feature); color: var(--on-feature); border-radius: var(--r-card); padding: 20px; box-shadow: var(--lift-2), var(--edge-dark); }
.stake-eyebrow { display: block; font: 700 10px/1.4 var(--font-ui); text-transform: uppercase; letter-spacing: .14em; color: var(--on-feature-mute); }
.stake-figure { margin-top: var(--s-4); font: 800 48px/1 var(--font-num); letter-spacing: -0.025em; color: var(--lime); font-variant-numeric: tabular-nums; }
.stake-caption { margin: var(--s-2) 0 0; font: 600 13px/1.4 var(--font-ui); color: var(--on-feature); }
/* The action group: one label, one field, one button, one caption, on the scale.
   40 from the stake card, then 8, 12, 12. Nothing else sits between them. */
.lad-action { margin-top: var(--s-7); }
.lad-action .field-label { display: block; margin: 0 0 var(--s-2); padding-left: 4px; font: 700 13px/1.4 var(--font-ui); color: var(--ink); }
.lad-action .lad-lock { margin-top: var(--s-3); }
.lad-action .field-caption { margin: var(--s-3) 4px 0; font: 500 13px/1.4 var(--font-ui); color: var(--ink-mute); }
.lad-action .warn { margin-top: var(--s-3); }
/* Lock in: the biggest control in the app, lime while it can be tapped and sunk until there
   is an answer to lock. It casts a shadow like every other live control here. */
.lad-lock { min-height: 84px; font-size: 1.5rem; }
.lad-lock:not(:disabled) { background: var(--lime); color: var(--lime-ink); box-shadow: var(--lift-2), var(--edge-light); }
.lad-lock:not(:disabled):active { box-shadow: var(--lift-press), var(--edge-light); }
#ladAnswer { font-size: 16px; font-weight: 700; }
/* Locked: the panel takes the whole middle band, because the point is that a glance
   across the table shows who is done. The screen changes shape, not only its wording. It
   sits flat with no float, bound by a lime ring and stamped at the top, and nothing on it
   is a control, because nothing here can be changed. */
.locked {
  background: var(--feature); color: var(--on-feature); border-radius: var(--r-card);
  padding: var(--s-5); box-shadow: 0 0 0 3px var(--lime), var(--edge-dark);
}
.locked-stamp { display: inline-block; padding: var(--s-2) var(--s-3); border-radius: var(--r-pill); background: var(--lime); color: var(--lime-ink); font: 800 10px/1.4 var(--font-ui); text-transform: uppercase; letter-spacing: .14em; }
.locked-answer { margin-top: var(--s-4); font: 800 26px/1.15 var(--font-ui); letter-spacing: -0.02em; color: var(--lime); overflow-wrap: anywhere; }
.locked-meta { margin: var(--s-3) 0 0; font: 600 13px/1.4 var(--font-ui); color: var(--on-feature); }
.locked-wait { margin: var(--s-1) 0 0; font: 500 13px/1.4 var(--font-ui); color: var(--on-feature-mute); }
#ladClosedNote, #ladLive .warn { margin-top: var(--s-4); }

/* ---------------- reveal phase (participant): two tabs on one screen ---------------- */
/* full-width segmented tab bar, same visual family as the admin .seg control */
.tabbar { display: flex; gap: 4px; padding: 4px; margin-bottom: var(--s-4); background: var(--surface-sunk); border-radius: var(--r-pill); box-shadow: inset 0 1px 3px rgba(36,33,26,0.12); }
.tab { flex: 1; border: 0; padding: 13px 16px; border-radius: var(--r-pill); font: 700 0.9375rem var(--font-ui); color: var(--ink-soft); background: transparent; cursor: pointer; transition: all .18s var(--ease); }
.tab[aria-selected="true"] { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); }
.tab:active { transform: translateY(1px) scale(.99); }

.reveal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-3); }
.reveal-head .eyebrow { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--lime-deep); }
/* the quiet "Live" label: the dot pulses on each poll so the screen visibly self-updates */
.reveal-live { display: inline-flex; align-items: center; gap: 6px; font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); }
.reveal-live-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--lime-deep); }
.reveal-live-dot.pulse { animation: pulse-ring-lime .8s ease-out; }

.reveal-hold { text-align: center; padding: var(--s-7) var(--s-4); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.reveal-hold-msg { margin: 0 0 var(--s-3); color: var(--ink-soft); font: 600 1.05rem var(--font-ui); }
.reveal-hold .breathe-dot { margin-top: 0; }

.reveal-roundhead { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-3); }
.reveal-rn { flex: 0 0 auto; display: grid; place-items: center; width: 32px; height: 32px; border-radius: 999px; background: var(--feature); color: var(--lime); font: 800 0.95rem var(--font-num); }
.reveal-rname { font: 800 1.25rem var(--font-ui); letter-spacing: -0.01em; min-width: 0; }
.reveal-group { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .09em; color: var(--ink-soft); margin: var(--s-4) 0 var(--s-2); }
.reveal-list { display: block; }

.reveal-item { display: flex; gap: var(--s-3); padding: var(--s-3) var(--s-4); margin-bottom: var(--s-2); background: var(--surface); border-radius: var(--r-tile); box-shadow: var(--lift-1), var(--edge-light); transition: box-shadow var(--t-state) var(--ease); }
.reveal-inum { flex: 0 0 22px; text-align: right; font: 800 0.95rem var(--font-num); color: var(--ink-mute); padding-top: 1px; }
.reveal-content { flex: 1; min-width: 0; }
.reveal-q { font: 500 0.95rem/1.45 var(--font-ui); color: var(--ink); margin-bottom: var(--s-2); white-space: pre-line; }
.reveal-clues { margin: 4px 0 var(--s-2); padding-left: 18px; color: var(--ink-soft); font-size: 0.9rem; line-height: 1.5; }
.reveal-clues li { margin: 3px 0; }
/* answer to come: a calm placeholder, no spoiler, just a promise it will fill in */
.reveal-pending { font: 600 0.8125rem var(--font-ui); color: var(--ink-mute); display: inline-flex; align-items: center; gap: 6px; }
.reveal-pending::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--ink-ghost); }
/* the answer itself: the saved-green the whole app reads as "in and settled",
   and the Numbers-round tolerance note sits right under it, legible on reveal */
.reveal-a { font: 800 1.125rem/1.35 var(--font-ui); color: var(--state-saved); }
.reveal-note { margin-top: 4px; font: 600 0.85rem/1.45 var(--font-ui); color: var(--ink-soft); }
.reveal-item.is-revealed { box-shadow: var(--lift-1), 0 0 0 1.5px var(--lime-glow), var(--edge-light); }
.reveal-item.is-fresh { animation: reveal-pop .9s var(--ease); }
@keyframes reveal-pop { 0% { box-shadow: var(--lift-2), 0 0 0 2.5px var(--lime), var(--edge-light); background: var(--lime-veil); } 100% { box-shadow: var(--lift-1), 0 0 0 1.5px var(--lime-glow), var(--edge-light); background: var(--surface); } }
@keyframes pulse-ring-lime { 0% { box-shadow: 0 0 0 0 var(--lime-glow); } 100% { box-shadow: 0 0 0 7px rgba(189,218,79,0); } }

/* ---------------- admin: control desk + sign-ups ---------------- */
.control-desk { margin-top: var(--s-6); }
.control-desk h2, .signups h2 { font: 800 1.05rem var(--font-ui); margin: 0 0 var(--s-4); }

/* Now showing lives in its own container: a compact vertical segmented toggle (only one
   stage is ever live, so a single sliding thumb marks it) beside a larger live phone
   preview mirroring exactly what the players see. */
.now-showing { padding: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.now-showing h2 { font: 800 1.05rem var(--font-ui); margin: 0 0 var(--s-4); }
.ns-body { display: flex; align-items: center; gap: var(--s-5); }

/* The stage list is a broadcast, and it must never read as a tab.
   A tab changes what the host is looking at. A stage changes what a dozen phones in the
   room are showing, and until now both wore the same costume: a grey sunken trough with
   a dark selected pill, on screen together, a few hundred pixels apart. So the trough
   goes. Stages are rows on the card's own surface with a state dot in front of each, and
   nothing else on this console has a dot inside a control.

   The live row carries its own resting state: a solid dark fill it paints itself. This
   is the fix for the worst fault on the console. The old marking was a near-white label
   over a black thumb that JavaScript positioned from offsetTop, so any moment the Live
   view was hidden (a trip to the Ladder tab to read a clue, which happens forty times a
   night) every offsetTop read zero, the thumb collapsed to the top with no height, and
   the label was left at 1.09 to 1 against the bare ground. Measured, not guessed. Now
   the fill and the text ship as one rule and the state cannot go missing. */
.stage-seg { position: relative; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.stage-seg-opt {
  position: relative; display: flex; align-items: center; gap: var(--s-3);
  border: 0; background: transparent; padding: 11px 14px; border-radius: var(--r-tile);
  font: 600 0.9rem var(--font-ui); color: var(--ink); text-align: left; cursor: pointer;
  transition: background var(--t-state) var(--ease), color var(--t-state) var(--ease), box-shadow var(--t-state) var(--ease);
}
.stage-seg-opt::before { content: ""; flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--line-strong); }
.stage-seg-opt:hover { background: var(--bg); }
.stage-seg-opt:active { transform: scale(.99); }
.stage-seg-opt.is-live { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); }
.stage-seg-opt.is-live::before { background: var(--lime); box-shadow: 0 0 0 3px var(--lime-veil); }

.phone-preview { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: var(--s-2); }
.phone-frame { width: 188px; height: 407px; border-radius: 26px; overflow: hidden; background: var(--bg); box-shadow: var(--lift-2), var(--edge-dark); border: 3px solid var(--ink); }
.phone-frame iframe { width: 375px; height: 812px; border: 0; transform: scale(0.501); transform-origin: top left; pointer-events: none; background: var(--bg); }
.phone-preview-cap { font: 700 0.625rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); }
.signups { margin-top: var(--s-5); }
.signups .admin-row { box-shadow: var(--lift-1), 0 0 0 1.5px var(--lime-glow), var(--edge-light); }
/* mid-scoring, a waiting sign-up is urgent: the block sits above the stage
   controls and wears caution so it cannot be missed */
.signups.is-urgent { background: var(--state-queued-bg); border-radius: var(--r-card); padding: var(--s-4); box-shadow: inset 0 0 0 1.5px rgba(154,107,30,0.25); }
.signups.is-urgent h2 { color: var(--state-queued); }
.signups.is-urgent .admin-row { box-shadow: var(--lift-1), 0 0 0 1.5px var(--state-queued), var(--edge-light); }
.btn-lockin { background: var(--lime); color: var(--lime-ink); box-shadow: var(--edge-light); }

/* Now showing's one-line readout of what the phones are on. Amber while a lock window is
   open or a reveal-y stage is live, so the sensitive moment cannot be missed. */
.ns-readout { margin: calc(-1 * var(--s-2)) 0 var(--s-4); font: 600 0.875rem/1.4 var(--font-ui); color: var(--ink-soft); }
.now-showing.is-amber { background: var(--state-queued-bg); box-shadow: var(--lift-1), 0 0 0 2px var(--state-queued); }
.now-showing.is-amber .ns-readout { color: var(--state-queued); font-weight: 700; }

/* ---------------- the Clue Ladder (host) ---------------- */
/* The host's reading page for the round: a strip of eight pills, the chosen ladder's five
   clues with the live one lit, the answer under a rule, the controls, then a row per table
   with what it typed and a Right / Wrong toggle. The card wears amber while locks are open. */
#ladderView { margin-top: var(--s-5); }
.lad-strip { display: grid; grid-template-columns: repeat(8, minmax(0, 1fr)); gap: 4px; margin-bottom: var(--s-4); }
.lad-pill { min-width: 0; height: 44px; padding: 0; border: 0; border-radius: var(--r-pill); background: var(--surface); color: var(--ink); font: 800 1rem var(--font-num); box-shadow: var(--lift-1), var(--edge-light); cursor: pointer; transition: background var(--t-state), color var(--t-state); }
.lad-pill.is-selected { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); }
.lad-pill.is-live { box-shadow: var(--lift-1), 0 0 0 2px var(--lime), var(--edge-light); }
.lad-pill.is-selected.is-live { box-shadow: var(--lift-1), 0 0 0 2px var(--lime), var(--edge-dark); }
.lad-pill.is-done { color: var(--ink-mute); }
.lad-pill.is-selected.is-done { color: var(--on-feature-mute); }
.lad-admin-card { padding: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.lad-admin-card.is-open { box-shadow: var(--lift-1), 0 0 0 2px var(--state-queued), var(--edge-light); }
.lad-admin-eyebrow { display: block; font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); margin-bottom: var(--s-3); }
.lad-admin-card.is-open .lad-admin-eyebrow { color: var(--state-queued); }
.lad-clues { margin: 0; padding: 0; list-style: none; }
.lad-clue { display: flex; gap: var(--s-3); padding: 12px; margin: 0 -12px; border-radius: var(--r-tile); font: 500 1.05rem/1.45 var(--font-ui); color: var(--ink-mute); }
.lad-clue-n { flex: 0 0 26px; text-align: right; font: 800 1.05rem var(--font-num); }
.lad-clue-text { flex: 1; min-width: 0; }
.lad-clue-pts { flex: 0 0 auto; align-self: center; font: 700 0.72rem var(--font-ui); text-transform: uppercase; letter-spacing: .06em; color: var(--ink-mute); }
.lad-clue.is-read { color: var(--ink-soft); }
.lad-clue.is-now { background: var(--lime-veil); color: var(--ink); font-weight: 600; }
.lad-clue.is-now .lad-clue-n, .lad-clue.is-now .lad-clue-pts { color: var(--lime-deep); }
.lad-clue-empty { font-style: italic; }
.lad-answer { margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line); font: 600 0.9rem var(--font-ui); color: var(--ink-soft); }
.lad-answer strong { font: 800 1.15rem var(--font-ui); color: var(--state-saved); margin-left: 6px; }
/* The cluster is weighted by how often each control is tapped, not by how final it
   sounds. Next clue is the whole rhythm of the round, five times a ladder and forty
   times a night, so it is the filled one and the tallest. Next ladder goes once and
   sits with Off the phones on the last row. Close locks takes a row of its own with an
   amber ring rather than a fill, because closing early refuses a team's answer and it
   must never be shoulder to shoulder with Next clue at the same size. Reading down, the
   rows are the order of the night: start it, run it, close it, move on. */
.lad-controls { margin-top: var(--s-4); display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-2); }
.lad-controls .rs-ctl-start { grid-column: 1 / -1; background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark); }
.lad-controls .rs-ctl.rs-ctl-clue { grid-column: 1 / -1; min-height: 64px; font-size: 1.05rem; background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark); }
.lad-controls .rs-ctl.rs-ctl-close { grid-column: 1 / -1; background: var(--surface); color: var(--ink); box-shadow: var(--lift-1), inset 0 0 0 2px var(--state-queued); }
.lad-controls .rs-ctl.rs-ctl-open { grid-column: 1 / -1; background: var(--state-queued-bg); color: var(--state-queued); }
.lad-tables { margin-top: var(--s-4); display: flex; flex-direction: column; gap: var(--s-2); }
.lad-table { display: grid; grid-template-columns: 1fr auto; gap: 2px var(--s-3); align-items: center; padding: 12px 12px 12px 16px; background: var(--surface); border-radius: var(--r-tile); box-shadow: var(--lift-1), var(--edge-light); }
.lad-table-name { font: 700 0.8rem var(--font-ui); color: var(--ink-soft); }
.lad-table-ans { font: 800 1.15rem var(--font-ui); color: var(--ink); overflow-wrap: anywhere; }
.lad-table-ans.is-none { font: 600 0.9rem var(--font-ui); color: var(--ink-mute); }
.lad-table-meta { font: 600 0.75rem var(--font-ui); color: var(--ink-mute); }
.lad-mark { grid-row: 1 / 4; grid-column: 2; display: inline-flex; gap: 4px; padding: 3px; background: var(--surface-sunk); border-radius: var(--r-pill); }
.lad-mark button { border: 0; min-height: 38px; padding: 6px 14px; border-radius: var(--r-pill); background: transparent; color: var(--ink-soft); font: 700 0.8rem var(--font-ui); cursor: pointer; }
.lad-mark button:disabled { opacity: .45; cursor: not-allowed; }
.lad-mark button.is-right[aria-pressed="true"] { background: var(--state-saved); color: #fff; }
.lad-mark button.is-wrong[aria-pressed="true"] { background: var(--state-error); color: #fff; }
.lad-table.is-right { box-shadow: var(--lift-1), 0 0 0 1.5px var(--state-saved), var(--edge-light); }
.lad-table.is-wrong { box-shadow: var(--lift-1), 0 0 0 1.5px rgba(178,59,46,.4), var(--edge-light); }
.lad-totals { margin-top: var(--s-5); padding: var(--s-4) var(--s-5) var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.lad-totals h3 { margin: 0 0 var(--s-2); font: 800 1rem var(--font-ui); }
/* A team still waiting to be marked is drawn as a word where the figure would be, plus
   an amber rail down its left edge. A figure is only ever printed when it is a real one,
   a zero included: marked wrong, or never locked in. The left padding is on every row so
   the name column never jumps as teams get marked one at a time. */
.lad-total-row { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s-3); padding: 7px 0 7px var(--s-2); border-top: 1px solid var(--line); font: 600 0.95rem var(--font-ui); }
.lad-total-row b { font: 800 1.25rem var(--font-num); font-variant-numeric: tabular-nums; }
.lad-total-row.is-pending { box-shadow: inset 2px 0 0 var(--state-queued); }
.lad-total-val { display: inline-flex; align-items: baseline; gap: var(--s-2); }
.lad-total-wait { font: 700 0.8rem var(--font-ui); color: var(--ink-mute); }
.lad-totals .rs-ctl { margin-top: var(--s-4); }
.lad-totals .rs-ctl-score.is-waiting { box-shadow: var(--lift-1), inset 0 0 0 2px var(--state-queued); }
.lad-post-note { margin: var(--s-2) 0 0; font: 600 0.8rem/1.45 var(--font-ui); color: var(--ink-mute); }
.lad-post-note.is-warn { color: var(--state-queued); }
/* On a laptop the host reads this at arm's length while talking to a room, so the answers
   and the marks step up a size and the controls get taller. */
@media (min-width: 768px) {
  #ladderView { max-width: 720px; margin-left: auto; margin-right: auto; }
  .lad-clue { font-size: 1.15rem; }
  .lad-table { padding: 14px 14px 14px 20px; }
  .lad-table-name { font-size: 0.9rem; }
  .lad-table-ans { font-size: 1.5rem; }
  .lad-table-ans.is-none { font-size: 1rem; }
  .lad-table-meta { font-size: 0.85rem; }
  .lad-mark button { min-height: 44px; padding: 8px 18px; font-size: 0.9rem; }
  .lad-controls .rs-ctl { min-height: 56px; font-size: 1rem; }
}

/* ---------------- admin on a larger screen (iPad / desktop) ---------------- */
@media (min-width: 768px) {
  .dash { max-width: 940px; }
  #liveView { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-5); align-items: start; }
  #liveView > * { margin-top: 0; }
  .control-desk, .board-seg, #alerts, #signupsPanel, #boardPanel, #markingPanel, .setup { grid-column: 1 / -1; }
  .stage-pill { padding: 13px 22px; font-size: 0.95rem; }
  #runsheetView { max-width: 720px; margin: 0 auto; }
}

/* run sheet (questions + answers) */
.dash-actions .seg { padding: 3px; }
.dash-actions .seg button { padding: 8px 14px; font-size: 0.85rem; }
#runsheetView { margin-top: var(--s-5); }
/* Run sheet as the host's reading page: a segmented round selector along the top, then the
   chosen round's questions with answers inline. A tapped question is marked to hold your
   place. Nothing here pushes to any phone. */
.rs-rounds { position: relative; display: flex; gap: 4px; padding: 4px; margin-bottom: var(--s-5); background: var(--bg); border-radius: var(--r-tile); box-shadow: inset 0 1px 2px rgba(28,30,34,0.08); overflow-x: auto; }
.rs-rounds-thumb { position: absolute; top: 4px; bottom: 4px; left: 4px; width: 0; background: var(--feature); border-radius: calc(var(--r-tile) - 4px); box-shadow: var(--lift-1), var(--edge-dark); transition: left var(--t-state) var(--ease), width var(--t-state) var(--ease); }
.rs-round-opt { position: relative; z-index: 1; flex: 0 0 auto; display: flex; align-items: baseline; gap: 7px; border: 0; background: transparent; padding: 10px 16px; border-radius: calc(var(--r-tile) - 4px); font-family: var(--font-ui); color: var(--ink); cursor: pointer; white-space: nowrap; transition: color var(--t-state) var(--ease); }
.rs-round-opt .rs-ro-n { font: 800 0.95rem var(--font-num); }
.rs-round-opt .rs-ro-name { font: 600 0.9rem var(--font-ui); }
.rs-round-opt.is-live { color: var(--on-feature); }

.rs-round-panel { background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); padding: var(--s-5); }
.rs-note { margin: 0 0 var(--s-4); padding: var(--s-4); background: var(--surface-sunk); border-radius: var(--r-tile); font: 600 0.95rem/1.5 var(--font-ui); color: var(--ink); }
.rs-group { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .09em; color: var(--ink-soft); margin: var(--s-5) 0 var(--s-2); }
.rs-item { display: flex; gap: var(--s-4); padding: 14px 12px; margin: 0 -12px; border-top: 1px solid var(--line); border-radius: var(--r-tile); cursor: pointer; transition: background var(--t-state) var(--ease); }
.rs-item:first-of-type { border-top: 0; }
.rs-item:hover { background: var(--bg); }
.rs-item.is-current { background: var(--lime-veil); }
.rs-inum { flex: 0 0 26px; text-align: right; font: 800 1.05rem var(--font-num); color: var(--ink-mute); }
.rs-item.is-current .rs-inum { color: var(--lime-deep); }
.rs-content { flex: 1; min-width: 0; }
.rs-q { font: 500 1.05rem/1.45 var(--font-ui); color: var(--ink); white-space: pre-line; }
.rs-a { font: 800 1.05rem var(--font-ui); color: var(--state-saved); }
.rs-clues { margin: 6px 0 0; padding-left: 20px; color: var(--ink-soft); font-size: 0.95rem; }
.rs-clues li { margin: 2px 0; }
.rs-itemnote { font-size: 0.85rem; color: var(--ink-mute); margin-top: 4px; }

/* Host-only clue block: the ammo the host can dole out to a stuck table. Amber, tagged, and
   clearly set apart so it never reads as part of the question. Never shown on any phone. */
.rs-hostclue { margin-top: var(--s-3); padding: 10px var(--s-4) 10px 12px; background: var(--state-queued-bg); border-radius: var(--r-tile); box-shadow: inset 0 0 0 1px rgba(154,107,30,0.18); }
.rs-hostclue-tag { display: inline-block; font: 800 0.62rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--state-queued); margin-bottom: 4px; }
.rs-hostclue-list { margin: 0; padding-left: 18px; color: var(--ink); font: 500 0.9rem/1.45 var(--font-ui); }
.rs-hostclue-list li { margin: 3px 0; }
.rs-hostclue-list li + li { color: var(--ink-soft); }

/* Answers console: questions/answers on the left, reveal + scoring controls on the right.
   Tapping an answer row reveals it live to every phone; the row shows its reveal state. */
.rs-layout { display: grid; grid-template-columns: 1fr; gap: var(--s-4); align-items: start; }
@media (min-width: 768px) { .rs-layout { grid-template-columns: 1fr 232px; } }
.rs-round-panel.is-live { box-shadow: var(--lift-1), 0 0 0 1.5px var(--lime-glow), var(--edge-light); }
.rs-revealable { position: relative; }
.rs-revealable .rs-a { opacity: .5; transition: opacity var(--t-state) var(--ease); }
.rs-item.is-revealed .rs-a { opacity: 1; }
.rs-reveal-dot { flex: 0 0 auto; align-self: center; width: 12px; height: 12px; border-radius: 999px; background: transparent; box-shadow: inset 0 0 0 1.5px var(--line-strong); transition: all var(--t-state) var(--ease); }
.rs-item.is-revealed .rs-reveal-dot { background: var(--lime); box-shadow: inset 0 0 0 1.5px var(--lime-deep); }
.rs-item.is-revealed { background: var(--lime-veil); }

.rs-controls { display: flex; flex-direction: column; gap: var(--s-2); position: sticky; top: var(--s-3); }
.rs-ctl { width: 100%; min-height: 48px; border: 0; border-radius: var(--r-tile); padding: 12px 16px; font: 700 0.9rem var(--font-ui); color: var(--ink); background: var(--surface); box-shadow: var(--lift-1), var(--edge-light); cursor: pointer; transition: transform var(--t-press) var(--ease), box-shadow var(--t-state), background var(--t-state), color var(--t-state); text-align: left; }
.rs-ctl:active { transform: translateY(1px) scale(.99); box-shadow: var(--lift-press); }
.rs-ctl:disabled { opacity: .5; cursor: not-allowed; }
.rs-ctl.is-on { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); }
.rs-ctl-score.is-on { background: var(--lime); color: var(--lime-ink); box-shadow: var(--lift-1), var(--edge-light); }

.rs-tracker-wrap { margin-top: var(--s-2); }
.rs-tracker { width: 100%; display: flex; align-items: center; gap: 8px; border: 0; border-radius: var(--r-tile); padding: 12px 14px; cursor: pointer; background: var(--state-saved-bg); color: var(--state-saved); box-shadow: var(--edge-light); text-align: left; transition: box-shadow var(--t-state); }
.rs-tracker.is-missing { background: var(--state-error-bg); color: var(--state-error); }
.rs-tracker-count { font: 800 1.25rem var(--font-num); font-variant-numeric: tabular-nums; }
.rs-tracker-of { font-size: 0.8rem; opacity: .7; }
.rs-tracker-label { flex: 1; font: 600 0.8rem var(--font-ui); }
.rs-tracker .score-card-chev { width: 18px; height: 18px; color: currentColor; }
.rs-tracker[aria-expanded="true"] .score-card-chev { transform: rotate(180deg); }
.rs-tracker-missing { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s-2); }
.rs-miss-chip { font: 600 0.75rem var(--font-ui); color: var(--state-error); background: var(--state-error-bg); padding: 4px 11px; border-radius: var(--r-pill); }
.rs-tracker-none { font-size: 0.8rem; margin: var(--s-2) 0 0; }

/* Printouts: a blank answer sheet per round, previewed small and printable one per team.
   The .ps-* sheet is authored at A4 width (794px @ 96dpi) so it previews scaled and prints
   true to size. */
#printoutsView { margin-top: var(--s-5); }
.printout-card { display: flex; align-items: center; gap: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); padding: var(--s-4); margin-bottom: var(--s-4); }
.printout-preview { flex: 0 0 auto; width: 180px; height: 255px; overflow: hidden; border-radius: 8px; background: #fff; box-shadow: var(--lift-1), var(--edge-light); }
.printout-scale { width: 794px; transform: scale(0.2267); transform-origin: top left; }
.printout-meta { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }
.printout-round { font: 700 0.7rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); }
.printout-name { font: 800 1.15rem var(--font-ui); color: var(--ink); }
.printout-desc { font-size: 0.85rem; color: var(--ink-soft); margin-bottom: var(--s-2); }
.printout-meta .btn-secondary { width: auto; margin: 0; }

/* Whole packs: the two controls that print the night's paper in the order it is played.
   They sit above the single sheets because the pack is the thing a table is handed and a
   single sheet is the reprint when one goes walkabout. */
.pack-card { background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); padding: var(--s-4); margin-bottom: var(--s-4); }
.pack-title { font: 800 1.15rem var(--font-ui); color: var(--ink); margin: 0 0 var(--s-1); }
.pack-desc { font-size: 0.85rem; color: var(--ink-soft); margin: 0 0 var(--s-3); }
.pack-btns { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }
.pack-btns .btn-secondary { width: auto; margin: 0; }
.pack-note { font-size: 0.85rem; color: var(--ink-soft); margin: 0; }

/* The answer sheet itself, print-native: near-black ink, grey hairlines, generous writing
   height, no shadows or colour, so a team's biro is always the darkest thing on the row. */
.ps-sheet { width: 794px; box-sizing: border-box; padding: 36px 64px; background: #fff; color: #16181c; font-family: "Hanken Grotesk", system-ui, sans-serif; }
.ps-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 28px; border-bottom: 2px solid #16181c; padding-bottom: 10px; }
.ps-team { flex: 1; min-width: 0; }
.ps-team-label { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #6b7280; margin-bottom: 8px; }
.ps-team-line { display: block; height: 34px; border-bottom: 1.5px solid #16181c; }
/* A pack printed for a named team carries the name where the biro would have gone: on
   the rule, not floating above it, at the size a person writes rather than a heading. */
.ps-team-line.is-named { display: flex; align-items: flex-end; }
.ps-team-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-bottom: 4px; font-size: 18px; font-weight: 700; line-height: 1.3; color: #16181c; }
.ps-title { text-align: right; }
.ps-round { display: block; font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: #6b7280; }
.ps-name { display: block; font-size: 26px; font-weight: 800; letter-spacing: -0.01em; }
.ps-eyebrow { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .12em; color: #9ca3af; margin-top: 12px; }
.ps-blurb { font-size: 14px; color: #374151; margin: 8px 0 0; }
.ps-lines { list-style: none; margin: 10px 0 0; padding: 0; }
.ps-line { display: flex; align-items: flex-end; gap: 16px; margin-bottom: 7px; }
.ps-num { flex: 0 0 26px; text-align: right; font-weight: 800; font-size: 16px; color: #6b7280; }
.ps-write { flex: 1; height: 26px; border-bottom: 1.5px solid #9aa1ab; }
.ps-stake { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; }
.ps-stake em { font-style: normal; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: #6b7280; }
.ps-stake b { display: inline-grid; place-items: center; width: 24px; height: 24px; border: 1.5px solid #9aa1ab; border-radius: 999px; font-size: 13px; font-weight: 800; color: #16181c; }
/* Stake & Joker labels sit once as thin column heads above the numbered rows,
   right-aligned so they sit directly above their bubbles and tick boxes. */
.ps-colheads { display: flex; justify-content: flex-end; align-items: flex-end; gap: 16px; margin-bottom: 2px; padding-right: 0; }
.ps-colhead { display: none; }
.ps-colhead-stake { display: inline-flex !important; align-items: center; gap: 8px; }
.ps-colhead-joker { display: inline-flex !important; align-items: center; }
.ps-colhead em { font-style: normal; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: #6b7280; }
/* Joker tick boxes sit on every row, no individual label: the word "Joker"
   sits once above them as a column head. */
.ps-joker { flex: 0 0 auto; display: inline-flex; align-items: center; }
.ps-box { width: 20px; height: 20px; border: 1.5px solid #9aa1ab; border-radius: 4px; }

/* Round-total box at the foot of every answer sheet. */
.ps-total { display: flex; align-items: center; justify-content: flex-end; gap: 16px; margin-top: 14px; padding-top: 10px; border-top: 2px solid #16181c; }
.ps-total-label { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .1em; color: #16181c; }
.ps-total-box { width: 96px; height: 44px; border: 2px solid #16181c; border-radius: 6px; }
/* Sectioned answer sheet (the Music round's two halves, numbered 1-10 then 1-10). */
.ps-section + .ps-section { margin-top: 10px; }
.ps-section-title { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: #16181c; margin: 10px 0 3px; padding-bottom: 5px; border-bottom: 1.5px solid #d1d5db; }
/* Welcome / intro table handout. */
.ps-welcome .pw-intro { font-size: 16px; line-height: 1.5; color: #16181c; margin: 16px 0 0; }
.ps-welcome h3 { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .08em; color: #16181c; margin: 0 0 8px; }
.pw-join { display: flex; gap: 28px; align-items: flex-start; margin-top: 20px; }
.pw-join-text { flex: 1; min-width: 0; }
.pw-join-text ol, .pw-rules ul { margin: 0; padding-left: 20px; }
.pw-join-text ol li, .pw-rules ul li { font-size: 14px; line-height: 1.5; color: #374151; margin-bottom: 5px; }
.pw-note { font-size: 13px; line-height: 1.5; color: #6b7280; margin: 10px 0 0; }
.pw-qr { flex: 0 0 150px; text-align: center; }
.pw-qr-code { width: 150px; height: 150px; }
.pw-qr-code svg { width: 100%; height: 100%; display: block; }
.pw-qr-cap { display: block; margin-top: 8px; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: #6b7280; }
.pw-qr-url { display: block; margin-top: 3px; font-size: 11px; font-weight: 600; color: #9aa1ab; word-break: break-all; }
.pw-rules { margin-top: 20px; }
.pw-close { font-size: 15px; line-height: 1.5; color: #16181c; margin: 20px 0 0; font-weight: 600; }

/* ---------------- team map: place tokens on the courtyard, pair by proximity ---------------- */
#mapView { margin-top: var(--s-5); }
.map-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3) var(--s-4); margin-bottom: var(--s-4); }
.map-bar .rs-hint { margin: 0; flex: 1 1 240px; }
.map-actions { flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-3); }
.map-actions .btn-secondary { width: auto; margin: 0; }
/* Building-side picker: tap an edge to mark where the building is, the anchor for orientation. */
.building-side { display: inline-flex; align-items: center; gap: 4px; padding: 4px; background: var(--surface-sunk); border-radius: var(--r-pill); box-shadow: inset 0 1px 3px rgba(36,33,26,0.12); }
.building-side-label { font: 700 0.68rem var(--font-ui); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-mute); padding: 0 8px 0 6px; }
.building-side button { border: 0; padding: 8px 13px; border-radius: var(--r-pill); font: 600 0.82rem var(--font-ui); color: var(--ink-soft); background: transparent; cursor: pointer; transition: all .18s var(--ease); }
.building-side button[aria-pressed="true"] { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1); }
/* The canvas scrolls inside its frame; the inner .team-map is a fixed portrait courtyard so
   token coordinates are stable, and the browser's own pinch-zoom handles zooming. */
.map-scroll { overflow: auto; border-radius: var(--r-card); background: var(--surface); box-shadow: var(--lift-1), var(--edge-light); -webkit-overflow-scrolling: touch; max-height: 78vh; max-width: 780px; margin: 0 auto; }

/* The building edge: a solid bar with a repeated label down the chosen side. */
.map-building { position: absolute; background: var(--feature); color: var(--on-feature); display: grid; place-items: center; z-index: 1; }
.map-building span { font: 800 0.75rem var(--font-ui); text-transform: uppercase; letter-spacing: .3em; color: var(--on-feature-mute); }
.map-building-top    { top: 0; left: 0; right: 0; height: 34px; }
.map-building-bottom { bottom: 0; left: 0; right: 0; height: 34px; }
.map-building-left   { top: 0; bottom: 0; left: 0; width: 34px; }
.map-building-right  { top: 0; bottom: 0; right: 0; width: 34px; }
.map-building-left span, .map-building-right span { writing-mode: vertical-rl; letter-spacing: .3em; }
/* No touch-action:none here, so the browser's own pinch-zoom and pan on the courtyard keep
   working; only the tokens below suppress default touch so a drag never scrolls the canvas. */
.team-map { position: relative; background-color: var(--bg); background-image: radial-gradient(circle at 1px 1px, rgba(28,30,34,0.06) 1px, transparent 0); background-size: 40px 40px; }
.map-token { position: absolute; z-index: 2; transform: translate(-50%, -50%); display: grid; place-items: center; min-width: 74px; min-height: 74px; max-width: 150px; padding: 10px 14px; border-radius: 999px; background: var(--surface); color: var(--ink); box-shadow: var(--lift-2), var(--edge-light); cursor: grab; user-select: none; touch-action: none; text-align: center; }
.map-token-label { font: 700 0.8rem/1.15 var(--font-ui); overflow-wrap: anywhere; }
.map-token.is-dragging { cursor: grabbing; box-shadow: var(--lift-2), 0 0 0 2px var(--feature), var(--edge-light); z-index: 10; }
/* The host square: distinct shape and the amber-ish feature fill, the anchor everything else
   orients around. */
.map-host { border-radius: var(--r-tile); background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark); min-width: 84px; min-height: 84px; }
.map-host .map-token-label { color: var(--lime); letter-spacing: .08em; }

.marking-list { display: flex; flex-direction: column; gap: var(--s-2); }
.marking-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-4); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.marking-pair { font: 700 1.0625rem var(--font-ui); }
.marking-tag { font: 600 0.72rem var(--font-ui); text-transform: uppercase; letter-spacing: .08em; color: var(--ink-mute); background: var(--surface-sunk); padding: 4px 11px; border-radius: var(--r-pill); white-space: nowrap; }
.marking-trio .marking-tag { color: var(--state-queued); background: var(--state-queued-bg); }

/* A quiet signature, for those who notice it. Not a link, not a promo. */
.app-sig { display: block; text-align: center; margin: 22px 0 14px; font-size: 11px; font-weight: 600; letter-spacing: .1em; color: var(--ink-soft); opacity: .5; }

/* What build this is. Just about there and no more: it reads "version" until
   hovered or tapped, then swaps to the numbers. Colour is the only thing the
   channel changes. The beta tone is a literal because this palette is
   deliberately monochrome and has no warning token to borrow. */
.app-ver { display: block; margin: 0 auto 18px; padding: 0; background: none;
  border: 0; cursor: pointer; font-family: var(--font-ui);
  font-size: 9px; line-height: 1.6; letter-spacing: .04em; text-align: center;
  color: var(--ink-ghost); opacity: .45; transition: opacity 120ms ease; }
.app-ver[data-channel="beta"] { color: #C2502A; }
.app-ver:hover, .app-ver:focus-visible, .app-ver[data-open="true"] { opacity: 1; }
.app-ver .sv-full { display: none; }
.app-ver:hover .sv-word, .app-ver:focus-visible .sv-word,
.app-ver[data-open="true"] .sv-word { display: none; }
.app-ver:hover .sv-full, .app-ver:focus-visible .sv-full,
.app-ver[data-open="true"] .sv-full { display: inline; }

.print-stage { display: none; }
@media print {
  @page { size: A4 portrait; margin: 6mm 14mm 8mm; }
  body.printing #login, body.printing #dash { display: none !important; }
  body.printing .print-stage { display: block; }
  /* Extra breathing room on the right, taken from the writing line, so the printer's
     hardware edge never clips the ends of the lines. Left stays at the @page margin. */
  .print-stage .ps-sheet { width: 100%; padding: 0 6mm 0 0; }
  .print-stage .ps-sheet .ps-eyebrow { display: none; }
  /* A print job can now be a whole pack, or a pack per team, so every sheet on the stage
     starts its own page and none of them is ever split down the middle. Both the modern
     property and the legacy one, because the printer in the room is driven by whatever
     browser Scott happens to have open. The last sheet in the job breaks after nothing:
     a page break on the final element is what feeds out a blank sheet at the end. */
  .print-stage > * { break-after: page; page-break-after: always; break-inside: avoid; page-break-inside: avoid; }
  .print-stage > *:last-child { break-after: auto; page-break-after: auto; }
}

/* story thread (the Ruby dog-walk listening test), rendered at the end of the run sheet */
.rs-story { box-shadow: var(--lift-1), 0 0 0 1.5px var(--lime-glow), var(--edge-light); }
.rs-n-star { background: var(--lime); color: var(--lime-ink); }
.rs-canon { margin: 0 0 var(--s-3); padding-left: 20px; color: var(--ink-soft); font-size: 0.9rem; }
.rs-canon li { margin: 3px 0; }
.rs-beat { margin: var(--s-2) 0; padding: var(--s-3) var(--s-4); border-radius: var(--r-tile); background: var(--lime-veil); border-left: 3px solid var(--lime-deep); }
.rs-beat-trap { background: var(--state-error-bg); border-left-color: var(--state-error); }
.rs-beat-head { font: 700 0.7rem var(--font-ui); text-transform: uppercase; letter-spacing: .06em; color: var(--lime-deep); margin-bottom: 4px; }
.rs-beat-trap .rs-beat-head { color: var(--state-error); }
.rs-beat-plants { font: 600 0.8rem var(--font-ui); color: var(--ink-soft); margin-bottom: 6px; }
.rs-beat-text p { margin: 0 0 8px; font-size: 0.95rem; line-height: 1.55; color: var(--ink); }
.rs-beat-text p:last-child { margin-bottom: 0; }
.rs-group-end { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1.5px solid var(--line); color: var(--lime-deep); }
.rs-subgroup { font: 700 0.8rem var(--font-ui); color: var(--ink-soft); margin: var(--s-3) 0 var(--s-2); }

/* ---------------- graphics pass: state icons + signal wave ---------------- */
.hero-icn { display: inline-grid; place-items: center; width: 52px; height: 52px; border-radius: 16px; background: var(--lime-veil); color: var(--lime); margin-bottom: var(--s-4); }
.hero-icn svg { width: 28px; height: 28px; }
.hero-icn-onlight { color: var(--lime-deep); }
.hero-card > * { position: relative; z-index: 1; }
/* The decorative lime "signal wave" under hero cards has been removed: Scott found the
   squiggle noisy, and the cards read cleaner without it. The bottom padding on .hero-card
   is kept as breathing room rather than space for a graphic. */

/* centre the single-card "moment" screens so the empty space sits balanced. They are
   already band-filling flex columns from the shell block; this only says where the
   content sits inside the band. #v-answers, #v-scoring and #v-leaderboard are left out
   on purpose: they are full working screens that can outgrow the band and scroll. */
#v-welcome, #v-signup, #v-gag, #v-pending, #v-standby, #v-resting { justify-content: center; }

/* Published leaderboard on the phones: ranked teams, each expanding to its round scores. */
.pub-board { display: flex; flex-direction: column; gap: var(--s-3); margin-top: var(--s-4); }
.pub-empty { text-align: center; padding: var(--s-7) var(--s-4); color: var(--ink-soft); }
.pub-empty .breathe-dot { margin: 0 0 var(--s-3); }
.pub-row { background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); overflow: hidden; }
.pub-row > summary { list-style: none; cursor: pointer; }
.pub-row > summary::-webkit-details-marker { display: none; }
.pub-sum { display: grid; grid-template-columns: 34px 1fr auto 22px; align-items: center; gap: var(--s-3); padding: var(--s-4); min-height: 60px; }
.pub-rank { font: 800 1rem var(--font-num); color: var(--ink-mute); text-align: center; }
.pub-name { font: 700 1.0625rem var(--font-ui); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pub-total { font: 800 1.75rem var(--font-num); font-variant-numeric: tabular-nums; }
.pub-chev { width: 20px; height: 20px; color: var(--ink-ghost); transition: transform var(--t-state) var(--ease); }
.pub-row[open] .pub-chev { transform: rotate(180deg); }
.pub-body { padding: 0 var(--s-4) var(--s-4); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2); }
.pub-cell { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 10px 14px; border-radius: var(--r-pill); background: var(--bg); font: 600 0.8125rem var(--font-ui); color: var(--ink-soft); }
.pub-cell-r { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pub-cell-v { font: 800 0.95rem var(--font-num); color: var(--ink); flex: 0 0 auto; }
.pub-row.leader { background: var(--feature); box-shadow: var(--lift-2), var(--edge-dark); }
.pub-row.leader .pub-name { color: var(--on-feature); }
.pub-row.leader .pub-rank, .pub-row.leader .pub-total { color: var(--lime); }
.pub-row.leader .pub-cell { background: rgba(255,255,255,0.08); color: var(--on-feature-mute); }
.pub-row.leader .pub-cell-v { color: var(--on-feature); }

/* live points award (Taskmaster-style host scoring) */
.award { margin-top: var(--s-5); }
.award-head { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-3); flex-wrap: wrap; }
.award-head h2 { font: 800 1.05rem var(--font-ui); margin: 0; }
.award-head .select-lg { width: auto; min-width: 150px; max-width: 240px; }
.award-teams { display: flex; flex-direction: column; gap: var(--s-2); }
.award-row { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 6px var(--s-3); padding: 14px 16px; background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.award-name { font: 700 1.0625rem var(--font-ui); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.award-pts { display: inline-block; font: 800 1.625rem var(--font-num); font-variant-numeric: tabular-nums; text-align: right; min-width: 2ch; }
.award-pts.flash { animation: ptsflash .5s ease; }
.award-btns { grid-column: 1 / -1; display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: 2px; }
.award-btns button { flex: 1 1 0; min-width: 54px; min-height: 50px; border: 0; border-radius: var(--r-pill); font: 800 1.1rem var(--font-num); background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); cursor: pointer; transition: transform var(--t-press) var(--ease), box-shadow var(--t-state); }
.award-btns button:active { transform: translateY(1px) scale(.95); box-shadow: var(--lift-press); }
.award-btns button.minus { flex: 0 0 64px; background: var(--surface); color: var(--ink-soft); box-shadow: var(--lift-1), var(--edge-light); }
@keyframes ptsflash { 0% { color: var(--lime-deep); transform: scale(1.3); } 100% { transform: scale(1); } }

/* Host-pushed full-screen round display (Flags / Puzzles reel), shown over everything. */
.display-overlay { position: fixed; inset: 0; z-index: 9000; background: #12110f; }
.display-overlay.hidden { display: none; }
.display-overlay iframe { width: 100%; height: 100%; border: 0; display: block; }

/* Round-display toggles in the admin "Now showing" panel. */
.ns-controls { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--s-4); }
.display-toggles { display: flex; gap: var(--s-3); }
.disp-toggle { flex: 1; min-width: 0; border: 0; padding: 10px 12px; border-radius: var(--r-tile); font: 700 0.9rem var(--font-ui); color: var(--ink-soft); background: var(--bg); box-shadow: inset 0 1px 2px rgba(28,30,34,0.08); cursor: pointer; transition: background var(--t-state) var(--ease), color var(--t-state) var(--ease), box-shadow var(--t-state); }
.disp-toggle:active { transform: scale(.99); }
.disp-toggle.is-armed { color: var(--ink); background: var(--surface); box-shadow: var(--lift-1), var(--edge-light); }
.disp-toggle.is-live { color: var(--on-feature); background: var(--feature); box-shadow: var(--lift-1), var(--edge-dark); }

/* ---------------- quiz night records (admin) ---------------- */
/* Saving a night and sharing it are two separate acts, so the card shows them as two
   separate bands: what the record is, then whether its link is live. */
.rec-capture { margin-top: var(--s-5); padding: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.rec-capture h2 { margin: 0 0 var(--s-2); font: 800 1.05rem var(--font-ui); }
.rec-capture .rs-hint { margin: 0 0 var(--s-3); }
.rec-capture .btn-secondary { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-2), var(--edge-dark); }
.rec-summary { margin: 0 0 var(--s-4); padding: 12px 16px; border-radius: var(--r-tile); background: var(--bg); font: 600 0.875rem var(--font-ui); color: var(--ink-soft); }
.rec-capture-fields { display: flex; gap: var(--s-3); flex-wrap: wrap; }
.rec-capture-fields .select-lg { flex: 1 1 200px; width: auto; }
.rec-capture-fields .select-sm { width: 168px; text-align: left; }

.rec-list-block { margin-top: var(--s-6); }
.rec-list { display: flex; flex-direction: column; gap: var(--s-4); margin-top: var(--s-4); }
.rec-card { padding: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.rec-head { margin-bottom: var(--s-4); }
.rec-title { margin: 0; font: 800 1.125rem var(--font-ui); letter-spacing: -0.01em; }
.rec-meta { margin: 4px 0 0; font: 600 0.8125rem var(--font-ui); color: var(--ink-mute); }
.rec-won { margin: var(--s-2) 0 0; font: 500 0.9375rem var(--font-ui); color: var(--ink-soft); }
.rec-won strong { color: var(--ink); font-weight: 800; }

.rec-share { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-tile); background: var(--bg); }
.rec-share.is-live { background: var(--lime-veil); box-shadow: inset 0 0 0 1.5px var(--lime-glow); }
.rec-share-state { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-mute); }
.rec-share.is-live .rec-share-state { color: var(--lime-ink); }
.rec-link { flex: 1 1 100%; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 600 0.8125rem var(--font-num); color: var(--ink-soft); }
.rec-share-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-left: auto; }
.rec-open { display: inline-flex; align-items: center; text-decoration: none; }

.rec-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--s-3); }
.rec-body { margin-top: var(--s-4); }
.rec-standings { display: flex; flex-direction: column; gap: 6px; }
.rec-standing { display: grid; grid-template-columns: 30px 1fr auto; align-items: center; gap: var(--s-3); padding: 10px 14px; border-radius: var(--r-tile); background: var(--bg); }
.rec-standing-rank { font: 800 0.875rem var(--font-num); color: var(--ink-mute); text-align: center; }
.rec-standing-name { font: 700 0.9375rem var(--font-ui); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rec-standing-total { font: 800 1.125rem var(--font-num); font-variant-numeric: tabular-nums; }
.rec-standing.leader { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); }
.rec-standing.leader .rec-standing-rank, .rec-standing.leader .rec-standing-total { color: var(--lime); }
.rec-stamp { margin: var(--s-3) 0 0; font: 600 0.75rem var(--font-ui); color: var(--ink-mute); }

/* ---------------- the shared board (/board/<slug>) ---------------- */
/* The same ranked rows the room watched on the night, so a link opened weeks later reads
   as the board people remember rather than a report about it. */
.board-page { padding-bottom: var(--s-8); }
.board-state { min-height: 60dvh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: var(--s-3); }
.board-state h1 { margin: 0; font: 800 1.5rem var(--font-ui); }
.board-state p { margin: 0; max-width: 30ch; }
.board-hero { background: var(--feature); color: var(--on-feature); border-radius: var(--r-card); padding: var(--s-5); box-shadow: var(--lift-2), var(--edge-dark); }
.board-hero .eyebrow { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--on-feature-mute); }
.board-hero-title { margin-top: 6px; font: 800 1.75rem/1.15 var(--font-ui); letter-spacing: -0.02em; }
.board-hero-when { margin: var(--s-2) 0 0; font: 600 0.8125rem var(--font-ui); color: var(--on-feature-mute); }
.board-winner { margin-top: var(--s-5); padding-top: var(--s-4); border-top: 1px solid rgba(255,255,255,0.12); display: flex; flex-direction: column; gap: 2px; }
.board-winner-label { font: 700 0.6875rem var(--font-ui); text-transform: uppercase; letter-spacing: .12em; color: var(--on-feature-mute); }
.board-winner-name { font: 800 1.375rem/1.2 var(--font-ui); color: var(--on-feature); }
.board-winner-score { font: 800 2.75rem/1 var(--font-num); font-variant-numeric: tabular-nums; color: var(--lime); letter-spacing: -0.02em; margin-top: var(--s-2); }
.board-page .warn { margin-top: var(--s-4); }
.board-frozen { margin: var(--s-5) 0 0; text-align: center; font: 500 0.8125rem var(--font-ui); color: var(--ink-mute); }

/* A long round name must shrink inside its cell, never push the grid past the card edge:
   the name ellipsises and the figure beside it always stays readable. */
.pub-cell, .round-cell { min-width: 0; }

/* The view toggle does not fit a phone. Let the strip scroll inside the header, the way the
   run sheet's round selector does, rather than let it push the whole console sideways: an
   admin page that scrolls horizontally on the night is a page the host has to fight.
   The strip may shrink but must never grow: given room to grow it stretches into a mostly
   empty pill that runs into the cog, which is worse than the problem it solves. */
.dash-head { flex-wrap: wrap; row-gap: var(--s-3); }
.dash-tag { min-width: 0; flex: 0 1 auto; }
.dash-actions { min-width: 0; flex: 1 1 auto; justify-content: flex-end; }
.dash-actions .seg { min-width: 0; flex: 0 1 auto; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.dash-actions .seg::-webkit-scrollbar { display: none; }
.dash-actions .seg button { flex: 0 0 auto; white-space: nowrap; }
/* The cog is a peer of the strip, not part of it, so it keeps its own space at every width. */
.dash-actions .icon-btn { flex: 0 0 auto; }
.dash-actions .icon-btn.is-open { background: var(--feature); color: var(--on-feature); box-shadow: var(--lift-1), var(--edge-dark); }

/* Panel headings sit beside their hint until the pair is too wide for the screen. */
.board-head { flex-wrap: wrap; }

/* On a phone the share buttons wrap under the link, so pinning them right leaves a ragged
   stub. Let them flow from the left instead. */
@media (max-width: 520px) {
  .rec-share-actions { margin-left: 0; }
}

/* ---------------- Setup: the console behind the cog ---------------- */
/* Everything that is not the night itself. It takes the whole console over rather than
   expanding under it, and every block is a closed disclosure carrying a one-line readout of
   what is inside, so the host opens the one thing they came for and sees nothing else. */
#setupView { margin-top: var(--s-5); }
.setup-head { margin-bottom: var(--s-4); }
.setup-head h2 { margin: 0 0 4px; font: 800 1.5rem var(--font-ui); letter-spacing: -0.01em; }
.setup-head .rs-hint { margin: 0; }

#setupView .setup-block { margin: 0 0 var(--s-3); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); overflow: hidden; }
.setup-summary { list-style: none; cursor: pointer; display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); padding: var(--s-4) var(--s-5); min-height: 60px; flex-wrap: wrap; }
.setup-summary::-webkit-details-marker { display: none; }
.setup-summary-title { font: 800 1.0625rem var(--font-ui); }
.setup-summary-note { font: 600 0.8125rem var(--font-ui); color: var(--ink-mute); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.setup-block[open] .setup-summary { border-bottom: 1px solid var(--line); }
.setup-body { padding: var(--s-4) var(--s-5) var(--s-5); }
.setup-body > .rs-hint:first-child { margin-top: 0; }
.setup-body h3 { margin: 0 0 var(--s-2); font: 700 0.9rem var(--font-ui); }
.setup-subhead { margin-top: var(--s-6); }
.setup-block-danger .setup-summary-title { color: var(--state-error); }
/* The capture panel is a plain block inside Setup now, not a floating card of its own. */
#setupView .rec-capture { padding: 0; background: none; box-shadow: none; border-radius: 0; margin-top: 0; }
#setupView .rec-list-block { margin-top: var(--s-5); }

/* ---------------- start a new night ---------------- */
.nn-step { margin: 0 0 var(--s-5); }
.nn-step-title { display: flex; align-items: center; gap: var(--s-2); margin: 0 0 var(--s-2); font: 700 0.9375rem var(--font-ui); }
.nn-step-n { display: inline-grid; place-items: center; width: 22px; height: 22px; border-radius: 999px; background: var(--feature); color: var(--on-feature); font: 800 0.75rem var(--font-num); flex: 0 0 auto; }
.nn-step .rs-hint { margin-top: 0; }

/* A choice reads as a choice: the whole row is the target, and the chosen one is filled in. */
.nn-check { display: flex; align-items: flex-start; gap: var(--s-3); padding: 14px 16px; border-radius: var(--r-tile); background: var(--bg); cursor: pointer; margin-bottom: var(--s-2); transition: background var(--t-state) var(--ease), box-shadow var(--t-state); }
.nn-check.is-on { background: var(--lime-veil); box-shadow: inset 0 0 0 1.5px var(--lime-glow); }
.nn-check input { margin: 3px 0 0; flex: 0 0 auto; width: 18px; height: 18px; accent-color: var(--feature); }
.nn-check > span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nn-check strong { font: 700 0.9375rem var(--font-ui); }
.nn-check-sub { font: 500 0.8125rem var(--font-ui); color: var(--ink-soft); }
.nn-clear { margin: 0; padding: 12px 16px; border-radius: var(--r-tile); background: var(--bg); font: 500 0.875rem var(--font-ui); color: var(--ink-soft); }
.nn-warn { margin: var(--s-2) 0 0; padding: 12px 16px; border-radius: var(--r-tile); font: 600 0.875rem var(--font-ui); color: var(--state-error); background: var(--state-error-bg); box-shadow: inset 0 0 0 1.5px rgba(178,59,46,.25); }

.nn-rounds { display: flex; flex-direction: column; gap: 6px; }
.nn-round { display: flex; align-items: center; gap: var(--s-3); padding: 10px 16px; border-radius: var(--r-tile); background: var(--bg); transition: background var(--t-state) var(--ease), box-shadow var(--t-state); }
.nn-round.is-on { background: var(--surface); box-shadow: var(--lift-1), var(--edge-light); }
.nn-round-pick { display: grid; grid-template-columns: 18px 1fr; align-items: center; gap: 2px var(--s-3); flex: 1 1 auto; min-width: 0; cursor: pointer; }
.nn-round-pick input { grid-row: 1 / 3; width: 18px; height: 18px; accent-color: var(--feature); }
.nn-round-name { font: 700 0.9375rem var(--font-ui); min-width: 0; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.nn-round-where { font: 500 0.75rem var(--font-ui); color: var(--ink-mute); }
.nn-tag { font: 700 0.625rem var(--font-ui); text-transform: uppercase; letter-spacing: .08em; color: var(--state-queued); background: var(--state-queued-bg); padding: 3px 8px; border-radius: var(--r-pill); }
.nn-round-max { flex: 0 0 auto; }
.nn-max { width: 76px; min-height: 44px; padding: 10px; font-size: 0.9375rem; }
.nn-max:disabled { opacity: .4; }
.nn-add { margin-top: var(--s-3); }
.nn-add .select-lg { flex: 1 1 180px; width: auto; }
.nn-summary { margin: var(--s-4) 0 0; font: 600 0.875rem var(--font-ui); color: var(--ink-soft); }
#nnCreate { margin-top: var(--s-3); }

/* ---------------- the host's score sheet ---------------- */
/* Every team against every round, typed straight in. Scrolls sideways inside its own box on
   a phone rather than pushing the console wide, and the team column stays put so you never
   lose track of whose row you are on. */
.score-grid-wrap { margin-top: var(--s-4); overflow-x: auto; -webkit-overflow-scrolling: touch; background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-1), var(--edge-light); }
.score-grid { border-collapse: separate; border-spacing: 0; width: 100%; }
.score-grid th, .score-grid td { padding: 8px 10px; text-align: center; }
.score-grid thead th { position: sticky; top: 0; z-index: 2; background: var(--surface); font: 700 0.75rem var(--font-ui); color: var(--ink-mute); border-bottom: 1px solid var(--line); }
.score-grid .sg-round span { display: block; max-width: 11ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 0 auto; }
.score-grid .sg-round em { font: 600 0.6875rem var(--font-num); color: var(--ink-ghost); font-style: normal; }
.score-grid th.sg-name { position: sticky; left: 0; z-index: 1; background: var(--surface); text-align: left; font: 700 0.875rem var(--font-ui); max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; box-shadow: 1px 0 0 var(--line); }
.score-grid thead th.sg-name { z-index: 3; }
.score-grid th.sg-name em { display: block; font: 600 0.6875rem var(--font-ui); color: var(--state-queued); font-style: normal; }
.score-grid tbody tr + tr th, .score-grid tbody tr + tr td { border-top: 1px solid var(--line); }
.sg-total { font: 800 1rem var(--font-num); font-variant-numeric: tabular-nums; }
.sg-input { width: 56px; min-height: 42px; padding: 8px 4px; text-align: center; border: 0; border-radius: var(--r-tile); background: var(--bg); color: var(--ink); font: 700 0.9375rem var(--font-num); -webkit-appearance: none; appearance: none; }
.sg-input:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--feature); background: var(--surface); }
.sg-input.is-saved { background: var(--state-saved-bg); color: var(--state-saved); }
.sg-input.is-bad { background: var(--state-error-bg); color: var(--state-error); box-shadow: inset 0 0 0 1.5px var(--state-error); }
.sg-cell.is-over .sg-input { box-shadow: inset 0 0 0 1.5px var(--state-queued); }

/* Adding a whole list of names at once, tucked away under the one-at-a-time box. */
.team-bulk { margin-top: var(--s-4); }
.team-bulk > summary { cursor: pointer; font: 700 0.875rem var(--font-ui); padding: 10px 0; list-style: none; }
.team-bulk > summary::-webkit-details-marker { display: none; }
/* The open marker is a plain hyphen, not an en dash. It pairs with the plus as a
   disclosure sign, and the house dash sweep should never have to decide whether a
   punctuation mark in a content string is prose. */
.team-bulk > summary::before { content: "+ "; color: var(--ink-mute); }
.team-bulk[open] > summary::before { content: "- "; }
.bulk-box { width: 100%; padding: 14px 16px; border: 0; border-radius: var(--r-tile); background: var(--bg); color: var(--ink); font: 500 0.9375rem/1.6 var(--font-ui); resize: vertical; box-shadow: inset 0 1px 3px rgba(36,33,26,0.10); }
.bulk-box:focus-visible { outline: none; box-shadow: inset 0 1px 3px rgba(36,33,26,0.10), 0 0 0 2px var(--feature); }

/* The board toggle grew a fourth tab (Scores). Same treatment as the view strip in the
   header: scroll the buttons inside the pill rather than let them widen the page. */
.board-seg { display: flex; max-width: 100%; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.board-seg::-webkit-scrollbar { display: none; }
.board-seg button { flex: 0 0 auto; white-space: nowrap; }
/* The score sheet scrolls sideways inside its own box, never by moving the page. */
.score-grid-wrap { max-width: 100%; }
.score-grid { min-width: max-content; width: auto; }

/* A picture beside a revealed answer (the flag, in Round 2). Sits on white because a flag
   with white in it would otherwise dissolve into the card, and capped short so a round of
   twenty stays scrollable rather than becoming a mile of images. */
.reveal-img { display: block; max-width: 100%; max-height: 96px; width: auto; margin: 0 0 var(--s-3); padding: 8px; background: #fff; border-radius: var(--r-tile); box-shadow: 0 0 0 1px var(--line), var(--lift-1); }

/* ---------------- the confirm, host console only ----------------
   One dialog for anything that cannot be undone. A native <dialog>, so Escape, the focus
   trap and the top layer are the browser's job rather than ours. The consequence sits on
   the action button with the real number in it, because the label is what gets read at
   the moment of the tap, and the way out holds the focus when the dialog opens. The card
   floats on the ground the same way every other control does: it casts, never receives. */
.confirm { padding: 0; border: 0; background: none; width: min(540px, calc(100vw - var(--s-6))); }
.confirm::backdrop { background: rgba(28,30,34,0.44); }
.confirm-card { padding: var(--s-5); background: var(--surface); border-radius: var(--r-card); box-shadow: var(--lift-2), var(--edge-light); }
.confirm-title { margin: 0 0 var(--s-2); font: 800 1.25rem var(--font-ui); letter-spacing: -0.01em; }
.confirm-body { margin: 0 0 var(--s-5); font: 500 0.9375rem/1.5 var(--font-ui); color: var(--ink-soft); }
/* Stacked rather than side by side, and both full width, because the action's label
   carries a count and a team name and so has no fixed length. A row would wrap at some
   names and not others, and a control label on two lines is the fault this console has
   already been through once. Stacked, the layout is the same every time. */
.confirm-actions { display: flex; flex-direction: column; gap: var(--s-2); }
.confirm-actions button { margin: 0; min-height: 52px; padding: 14px 20px; font-size: 0.9375rem; }
.confirm-actions .btn-danger { box-shadow: inset 0 0 0 1.5px var(--state-error), var(--lift-1); }

/* ---- short screens ----
   One breakpoint doing one job: find the vertical room a small phone does not have. The
   smallest handset likely in the room is 375 by 667, and once the browser's own chrome
   has taken its cut that is about 553 of usable height. At the full rhythm the ladder
   screen runs about 60 over that, which would put the Lock in button below the fold on
   the one screen where it must never be. So the frame tightens and the content does not:
   the bands give back their padding and the button comes down to 64, which still leaves
   it far and away the biggest control in the app. */
@media (max-height: 620px) {
  .app-top { padding-top: var(--s-4); }
  .who { margin-bottom: var(--s-4); }
  .app-bot { padding-top: var(--s-2); padding-bottom: var(--s-4); }
  .lad-action { margin-top: var(--s-5); }
  .lad-lock { min-height: 64px; }
}
