/* Shared by the player page and the presenter page. Read at arm's length on a laptop and from the back of a room on the big screen. */

/* Fonts are self-hosted so hotel Wi-Fi or a locked-down projector laptop cannot change the look.
   Latin and Latin Extended subsets from Google Fonts, all SIL Open Font License; see public/fonts/.
   Archivo is a variable font, so one file per subset covers weights 400 to 700. */

@font-face {
  font-family: 'Bungee';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/bungee-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Bungee';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/bungee-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Bebas Neue';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/bebas-neue-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Bebas Neue';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/bebas-neue-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/archivo-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('/fonts/archivo-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Close Enough: a retro TV game-show stage. One dark theme by design, so it reads the same on a
   projector and an LED wall: deep studio blue, lit boards, one hot accent (studio gold), white
   for the answer, and green and red only for movement arrows. Three faces: Bungee for the mark,
   Bebas Neue for questions and numbers, Archivo for everything else. */

:root {
  color-scheme: dark;
  --stage: #07103a;          /* deep studio blue */
  --stage-2: #12257f;        /* lit board blue */
  --board: #0c1a5c;
  --bevel: #2a46c4;
  --tile: #1b2c7a;           /* an unlit tile */
  --pale: #e9efff;           /* a lit tile */
  --well: #050b2a;           /* inside an input */
  --gold: #f6c343;
  --gold-deep: #c99416;
  --gold-ink: #1a1500;       /* text on gold */
  --white: #ffffff;
  --dim: #aeb8e8;            /* blue-biased secondary text */
  --rail: #5e6ba8;
  --line: rgba(42, 70, 196, 0.6);
  --up: #5be38a;
  --down: #ff6b6b;
  --radius: 18px;
  --font-mark: 'Bungee', 'Impact', 'Arial Black', sans-serif;
  --font-num: 'Bebas Neue', 'Oswald', 'Impact', 'Arial Narrow', sans-serif;
  --font-body: 'Archivo', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
  --spotlight:
    radial-gradient(ellipse 70% 55% at 50% 10%, rgba(80, 120, 255, 0.55), transparent 65%),
    radial-gradient(ellipse 90% 60% at 50% 100%, rgba(0, 0, 0, 0.6), transparent 60%);
}

*, *::before, *::after { box-sizing: border-box; }

[hidden] { display: none !important; }

html, body { margin: 0; }

body {
  min-height: 100vh;
  background: var(--spotlight), var(--stage);
  background-attachment: fixed;
  color: var(--white);
  font-family: var(--font-body);
  font-size: 20px;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}

.page {
  max-width: 880px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 32px;
  color: var(--dim);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.badge {
  display: inline-block;
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--down);
  color: var(--gold-ink);
  font: 700 14px/1 var(--font-body);
  letter-spacing: 0.04em;
  text-transform: none;
}

h1, h2, h3 { margin: 0 0 16px; line-height: 1.05; font-family: var(--font-num); font-weight: 400; letter-spacing: 0.02em; }
h1 { font-size: 56px; }
h2 { font-size: 40px; }
p { margin: 0 0 16px; }

.muted { color: var(--dim); }
.big { font-size: 28px; }
.center { text-align: center; }

.card {
  background: var(--board);
  border: 3px solid var(--bevel);
  border-radius: var(--radius);
  padding: 36px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}

.stack > * + * { margin-top: 18px; }

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}

.eyebrow {
  color: var(--dim);
  font-family: var(--font-num);
  font-size: 28px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: 8px;
}

.prompt {
  font-family: var(--font-num);
  font-size: 44px;
  line-height: 1.02;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
}

input[type="text"], input[type="password"] {
  width: 100%;
  font: 500 28px/1.2 var(--font-body);
  padding: 14px 18px;
  border: 3px solid var(--bevel);
  border-radius: 12px;
  background: var(--well);
  color: var(--white);
}

input::placeholder { color: var(--rail); opacity: 1; }
input[type="text"]:focus, input[type="password"]:focus { border-color: var(--gold); outline: none; }

input:focus-visible, button:focus-visible {
  outline: 3px solid var(--white);
  outline-offset: 3px;
}

input[type="text"]:focus-visible, input[type="password"]:focus-visible { outline: none; }

/* Buttons: gold with a solid gold-deep bottom edge for the main action, outlined and quiet for the rest. */

button {
  font: 700 22px/1 var(--font-body);
  padding: 18px 30px;
  border-radius: 14px;
  border: 3px solid var(--gold);
  background: var(--gold);
  color: var(--gold-ink);
  box-shadow: 0 6px 0 var(--gold-deep);
  cursor: pointer;
  transition: transform 0.08s ease-out, box-shadow 0.08s ease-out;
}

button:active:not(:disabled) { transform: translateY(4px); box-shadow: 0 2px 0 var(--gold-deep); }

button.secondary {
  background: transparent;
  color: var(--white);
  border-color: var(--bevel);
  box-shadow: none;
}

button.secondary:hover:not(:disabled) { border-color: var(--dim); }
button.secondary:active:not(:disabled) { transform: none; box-shadow: none; background: var(--board); }

button:disabled {
  background: var(--tile);
  border-color: var(--bevel);
  color: var(--rail);
  box-shadow: none;
  cursor: not-allowed;
}

button.link {
  background: none;
  border: none;
  box-shadow: none;
  padding: 0 4px;
  color: var(--white);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}

button.link:active { transform: none; }

.preview {
  min-height: 1.2em;
  font-size: 28px;
  line-height: 1.2;
  font-weight: 600;
  color: var(--white);
  overflow-wrap: anywhere;
}

.preview.typed-out { color: var(--gold); }

.preview-words {
  font-size: 20px;
  line-height: 1.25;
  color: var(--dim);
  overflow-wrap: anywhere;
}

.preview-words:empty { display: none; }

.warning { color: var(--gold); }
.error { color: var(--down); }

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
  list-style: none;
  padding: 0;
  margin: 0;
}

.chips li {
  max-width: 100%;
  padding: 10px 16px;
  border-radius: 10px;
  background: var(--stage-2);
  border: 2px solid var(--bevel);
  font-weight: 600;
  line-height: 1.15;
  overflow-wrap: anywhere;
}

.countdown {
  font-family: var(--font-num);
  font-size: 56px;
  line-height: 1;
  color: var(--gold);
}

.countdown.urgent { color: var(--white); }

.locked {
  font-size: 26px;
  font-weight: 600;
}

.points {
  font-family: var(--font-num);
  font-size: 96px;
  color: var(--gold);
  line-height: 1;
}

.facts {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 8px 24px;
  margin-bottom: 0;
}

.facts dt { color: var(--dim); }
.facts dd { margin: 0; font-weight: 600; }

table.board {
  width: 100%;
  border-collapse: collapse;
}

.board th, .board td {
  text-align: left;
  padding: 10px 12px;
  border-bottom: 2px solid var(--line);
}

.board th { color: var(--dim); font-size: 16px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; }
.board td.num, .board th.num { text-align: right; }
.board td.num { font-family: var(--font-num); font-size: 1.4em; line-height: 1; }
.board tr.me td { background: var(--stage-2); font-weight: 700; }
.board tr.me td.num { color: var(--gold); }

/* How to score, on the welcome screens: one row per band */

.rules h3 { font-size: 30px; letter-spacing: 0.04em; margin: 0 0 8px; color: var(--gold); }
.rules table { width: 100%; border-collapse: collapse; font-size: 18px; }
.rules td { padding: 6px 0; border-bottom: 2px solid var(--line); }
.rules td.pts { text-align: right; font-family: var(--font-num); font-size: 1.5em; line-height: 1; color: var(--gold); }
.rules p { margin: 12px 0 0; font-size: 16px; }

/* Presenter: every screen is a 1920x1080 stage, scaled to fit the window by presenter.js.
   The floor for stage text that carries information is 28px, so it is still about 19px on a 720p
   projector that shows the stage at two thirds; only decoration and disabled labels go smaller. */

body.presenter {
  height: 100vh;
  overflow: hidden;
  background: #030820;
}

.stage {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 1920px;
  height: 1080px;
  transform: translate(-50%, -50%) scale(var(--scale, 1));
  overflow: hidden;
  background: var(--spotlight), var(--stage);
  font-size: 28px;
}

/* Quiet buttons on the stage are outlined in the dim blue, not the bevel, so their edges survive a
   washed-out projector. */
.stage button.secondary { border-color: var(--dim); }
.stage button.secondary:hover:not(:disabled) { border-color: var(--white); }
.stage button.secondary:disabled { border-color: var(--bevel); }

.stage::before { /* the studio floor glow line */
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 6px;
  background: linear-gradient(90deg, transparent, var(--gold), transparent);
  opacity: 0.8;
}

.view { position: absolute; inset: 0; }
.loading { position: absolute; left: 72px; top: 200px; margin: 0; color: var(--dim); font-size: 32px; }
.offline { position: absolute; top: 60px; left: 50%; transform: translateX(-50%); font-size: 28px; padding: 10px 18px; z-index: 2; }

.marquee { position: absolute; top: 44px; left: 72px; display: flex; align-items: center; gap: 22px; }
.mark {
  font-family: var(--font-mark);
  font-size: 46px;
  letter-spacing: 0.02em;
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 0 24px rgba(246, 195, 67, 0.55), 0 3px 0 var(--gold-deep);
}
/* The wide lockup sits in the line box the typed mark used, so the subtitle stays where it was;
   the drop shadow keeps the glow the text-shadow gave the letters. */
.mark-logo { display: block; height: 46px; width: auto; filter: drop-shadow(0 0 16px rgba(246, 195, 67, 0.5)); }
.mark small {
  display: block;
  margin-top: 6px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 28px;
  line-height: 1.1;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--dim);
  text-shadow: none;
  white-space: nowrap;
}

.round-lights { position: absolute; top: 56px; right: 72px; display: flex; gap: 12px; align-items: center; }
.round-lights span { width: 22px; height: 22px; border-radius: 50%; background: var(--tile); box-shadow: inset 0 0 0 2px var(--bevel); }
.round-lights span.done { background: var(--gold); box-shadow: 0 0 14px rgba(246, 195, 67, 0.8); }
.round-lights span.now { background: var(--white); box-shadow: 0 0 18px rgba(255, 255, 255, 0.9); }
.round-lights.many { gap: 8px; }
.round-lights.many span { width: 14px; height: 14px; }
.round-lights b { margin-left: 10px; font-family: var(--font-num); font-size: 30px; font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; color: var(--dim); }

/* A lit board: the bevelled panel the join address and the question sit on. */
.lit {
  position: absolute;
  background: var(--board);
  border: 6px solid var(--bevel);
  border-radius: 22px;
  box-shadow: inset 0 0 0 4px #081345, 0 0 0 10px rgba(42, 70, 196, 0.25), 0 24px 60px rgba(0, 0, 0, 0.5);
}

.stage .meta { color: var(--dim); font-size: 30px; }

.stage .controls { position: absolute; left: 72px; right: 72px; bottom: 44px; display: flex; gap: 16px; align-items: center; }
.stage .controls .spacer { flex: 1; }
.stage .controls button { font-size: 28px; padding: 18px 32px; }

/* Login and no game: one panel in the middle of the stage. */
.stage .panel { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 760px; padding: 48px 56px; }
.stage .panel h1, .stage .panel .headline { font-family: var(--font-num); font-size: 72px; line-height: 1; letter-spacing: 0.02em; text-transform: uppercase; margin: 0 0 12px; }
.stage .panel .meta { margin: 0; }
.stage .panel input { font-size: 32px; }
.stage .panel input.small { font-size: 28px; padding: 10px 14px; }
.stage .panel button { font-size: 28px; }
/* The login panel: each label close to its own field, and space between the groups. */
.stage .login > label { display: block; margin-top: 28px; font-size: 28px; }
.stage .login > h1 + label { margin-top: 18px; }
.stage .login > label + input { margin-top: 6px; }
.stage .login > .row { margin-top: 32px; }
.stage .login .error { font-size: 28px; }

/* Lobby */
/* The address is centred in the room the lit board has under its line, one line or two. */
.join-board { left: 72px; top: 190px; width: 1180px; height: 270px; padding: 34px 48px; display: flex; flex-direction: column; }
.join-board .meta { margin-bottom: 14px; }
.join-url {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  font-family: var(--font-mark);
  font-size: 60px;
  line-height: 1.05;
  letter-spacing: 0.01em;
  color: var(--white);
  text-shadow: 0 0 30px rgba(120, 150, 255, 0.6);
  overflow-wrap: normal;
}
.join-url .nowrap { white-space: nowrap; }
.lobby-teams { position: absolute; left: 72px; top: 500px; width: 1180px; bottom: 150px; overflow: hidden; }
.lobby-teams .meta { margin-bottom: 18px; font-size: 32px; color: var(--white); }
.lobby-teams .chips { gap: 14px 16px; }
.lobby-teams .chips li { font: 600 30px/1.1 var(--font-body); padding: 14px 24px; border-radius: 12px; }
/* On the stage the scoring table is white with a dim heading, so Start round 1 is the one gold thing. */
.view-lobby .rules { position: absolute; right: 72px; top: 200px; width: 520px; }
.view-lobby .rules h3 { font-size: 44px; margin-bottom: 14px; color: var(--dim); }
.view-lobby .rules table { font-size: 28px; }
.view-lobby .rules td { padding: 10px 0; }
.view-lobby .rules td.pts { font-size: 40px; line-height: 1.2; color: var(--white); }
/* The hero lockup in the empty corner under the scoring table, clear of the Restart game button:
   small and half lit, so the join address takes the eye first. */
.lobby-logo { position: absolute; right: 150px; bottom: 150px; height: 200px; width: auto; opacity: 0.5; pointer-events: none; }

/* Start round 1 pulses once when the opening hands back to the lobby. */
.stage .controls button.pulse-once { animation: pulse-once 1.1s ease-out 1; }

@keyframes pulse-once {
  0% { scale: 1; box-shadow: 0 6px 0 var(--gold-deep), 0 0 0 0 rgba(246, 195, 67, 0.85); }
  30% { scale: 1.12; }
  100% { scale: 1; box-shadow: 0 6px 0 var(--gold-deep), 0 0 0 48px rgba(246, 195, 67, 0); }
}

/* The opening sequence: its own layer over the whole stage, outside the screen polling redraws.
   intro.js sets data-phase as the running order goes: black, slam, title, names, hosts. The hero
   logo slams in over CSS rays and beams; when public/intro/sting.mp4 exists it plays over them from
   the slam to the hand-back at 9.5s, and they carry on from the same picture. */

.intro { position: absolute; inset: 0; z-index: 10; overflow: hidden; background: var(--spotlight), var(--stage); }
.intro[data-phase="black"] { background: #000; }
.intro[data-phase="black"] > :not(.intro-skip) { visibility: hidden; }

.intro-burst {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2600px;
  height: 2600px;
  margin: -1300px 0 0 -1300px;
  background: repeating-conic-gradient(rgba(246, 195, 67, 0.2) 0deg 5deg, transparent 5deg 15deg);
  mask-image: radial-gradient(circle, #000 8%, transparent 58%);
  animation: spin 50s linear infinite;
  transition: opacity 0.5s;
}
.intro[data-phase="slam"] .intro-burst { animation: burst-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both, spin 50s linear infinite; }
.intro[data-phase="names"] .intro-burst { opacity: 0.35; }
.intro[data-phase="tim"] .intro-burst { opacity: 0; }

.intro-beams span {
  position: absolute;
  bottom: -80px;
  left: 16%;
  width: 300px;
  height: 1500px;
  margin-left: -150px;
  background: linear-gradient(to top, rgba(205, 220, 255, 0.34), rgba(205, 220, 255, 0) 80%);
  clip-path: polygon(44% 100%, 56% 100%, 100% 0, 0 0);
  transform-origin: 50% 100%;
  filter: blur(8px);
  mix-blend-mode: screen;
  animation: sweep calc(var(--beat) * 8) ease-in-out infinite alternate;
}
.intro-beams span + span { left: 84%; animation-direction: alternate-reverse; }

.intro-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; }
.intro[data-phase="slam"] .intro-flash { animation: flash-out 0.6s ease-out; }

/* The sting video, full stage over the slam and hold; the black phase hides it like everything else. */
.intro-video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; pointer-events: none; }

.intro-mark {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  text-align: center;
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s;
}
/* The hero shrinks as it rises: above the board it stays clear of the first row of tiles, and over
   the hosts it sits above the eyebrow. It steps off for Tim's beat and comes back for the hosts. */
.intro[data-phase="names"] .intro-mark { transform: translateY(calc(-50% - 390px)) scale(0.33); }
.intro[data-phase="tim"] .intro-mark { opacity: 0; transform: translateY(calc(-50% - 260px)) scale(0.5); }
.intro[data-phase="hosts"] .intro-mark { transform: translateY(calc(-50% - 260px)) scale(0.5); }
.intro-logo {
  display: block;
  height: 640px;
  width: auto;
  margin: 0 auto;
  filter: drop-shadow(0 0 50px rgba(246, 195, 67, 0.5));
}
.intro[data-phase="slam"] .intro-logo { animation: slam 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.intro[data-phase="title"] .intro-logo { animation: beat-pulse calc(var(--beat) * 2) ease-out infinite; }
.intro[data-phase="title"] .intro-burst { animation: spin 50s linear infinite, beat-glow calc(var(--beat) * 2) ease-out infinite; }

.intro-board {
  position: absolute;
  left: 120px;
  right: 120px;
  top: 270px;
  bottom: 110px;
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  grid-template-rows: repeat(var(--rows), minmax(0, 260px));
  align-content: center;
  gap: 28px;
  list-style: none;
  margin: 0;
  padding: 0;
  opacity: 0;
  transition: opacity 0.3s;
}
.intro[data-phase="names"] .intro-board { opacity: 1; }

.intro-tile {
  min-width: 0;
  border-radius: 18px;
  background: var(--tile);
  border: 4px solid var(--bevel);
  box-shadow: inset 0 0 0 3px #081345;
}
.intro-tile span {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 12px 22px;
  overflow: hidden;
  font-family: var(--font-num);
  font-size: var(--tile-font, 76px);
  line-height: 0.95;
  letter-spacing: 0.02em;
  text-align: center;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: anywhere;
  color: var(--board);
  visibility: hidden;
}
/* The board centres a short last row: each tile a fixed share of the row, the rows wrapped and centred. */
.intro-board { display: flex; flex-wrap: wrap; justify-content: center; }
.intro-board .intro-tile {
  flex: 0 0 calc((100% - (var(--cols) - 1) * 28px) / var(--cols));
  height: min(260px, calc((100% - (var(--rows) - 1) * 28px) / var(--rows)));
}
.intro-tile.in { animation: tile-lit 0.8s ease-out calc(var(--fly) * 0.7) both; }
.intro-tile.in span { visibility: visible; animation: fly var(--fly) cubic-bezier(0.2, 0.8, 0.3, 1) both; }

.intro-hosts {
  position: absolute;
  left: 100px;
  right: 100px;
  top: 470px;
  height: 460px;
  display: flex;
  flex-direction: column;
  text-align: center;
  visibility: hidden;
}
.intro[data-phase="hosts"] .intro-hosts { visibility: visible; animation: hosts-in 0.6s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.intro-eyebrow { font-family: var(--font-num); font-size: 64px; line-height: 1; letter-spacing: 0.24em; text-transform: uppercase; color: var(--dim); margin-bottom: 18px; }
.intro-host-names {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  font-family: var(--font-num);
  font-size: 200px;
  line-height: 0.95;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-wrap: balance;
  color: var(--white);
  text-shadow: 0 0 50px rgba(255, 255, 255, 0.55);
}

/* Tim's beat, after the names: direction 1 of docs/design/tim-plaque-directions.html as drawn. He
   rises from below the stage at 700px, left of centre, presenting, as the marquee plaque slams in
   beside him on the sting, its bulbs chasing round the rim in threes over its own slow rays. */
.intro-tim-beat { position: absolute; inset: 0; visibility: hidden; pointer-events: none; }
.intro[data-phase="tim"] .intro-tim-beat { visibility: visible; }
.intro-tim-rays {
  position: absolute;
  left: 1290px;
  top: 490px;
  width: 2400px;
  height: 2400px;
  margin: -1200px 0 0 -1200px;
  background: repeating-conic-gradient(rgba(246, 195, 67, 0.14) 0deg 5deg, transparent 5deg 15deg);
  mask-image: radial-gradient(circle, #000 10%, transparent 55%);
}
.intro[data-phase="tim"] .intro-tim-rays { animation: burst-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both, spin 60s linear infinite; }
.intro-plaque { position: absolute; inset: 0; width: 1920px; height: 1080px; overflow: visible; }
.intro-plaque-face { transform-origin: 1290px 490px; }
.intro[data-phase="tim"] .intro-plaque-face { animation: plaque-slam 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.intro[data-phase="tim"] .intro-plaque-bulbs circle { animation: chase 0.75s steps(1) infinite; }
.intro[data-phase="tim"] .intro-plaque-bulbs circle.b1 { animation-delay: -0.25s; }
.intro[data-phase="tim"] .intro-plaque-bulbs circle.b2 { animation-delay: -0.5s; }
.intro-tim { position: absolute; left: 170px; bottom: 0; }
.intro[data-phase="tim"] .intro-tim { animation: tim-rise 0.7s cubic-bezier(0.2, 0.9, 0.3, 1.25) 0.25s both; }
@keyframes plaque-slam {
  0% { opacity: 0; scale: 3.5; rotate: -5deg; }
  55% { opacity: 1; scale: 0.95; rotate: 0deg; }
  75% { scale: 1.03; }
  100% { scale: 1; }
}
@keyframes chase { 0% { opacity: 1; } 33.3% { opacity: 0.28; } }
@keyframes tim-rise { from { transform: translateY(720px); } }

@keyframes burst-in { from { scale: 0.1; opacity: 0; } }
@keyframes spin { to { rotate: 360deg; } }
@keyframes sweep { from { transform: rotate(-32deg); } to { transform: rotate(32deg); } }
@keyframes flash-out { from { opacity: 0.85; } to { opacity: 0; } }
@keyframes slam {
  0% { opacity: 0; scale: 4; rotate: -6deg; }
  55% { opacity: 1; scale: 0.94; rotate: 0deg; }
  75% { scale: 1.05; }
  100% { scale: 1; }
}
@keyframes beat-pulse {
  0% { scale: 1.035; filter: drop-shadow(0 0 90px rgba(246, 195, 67, 0.95)); }
  100% { scale: 1; }
}
@keyframes beat-glow { 0% { filter: brightness(1.9); } 100% { filter: brightness(1); } }
/* The name stays navy as it flies in: its tile is gold from the moment it lands (tile-lit fills
   backwards over its delay), and white on gold was 1.6:1. */
@keyframes fly {
  0% { opacity: 0; scale: 3.2; translate: 0 240px; filter: blur(6px); }
  100% { opacity: 1; scale: 1; translate: 0 0; filter: blur(0); }
}
@keyframes tile-lit {
  0% { background: var(--gold); border-color: var(--gold); box-shadow: 0 0 70px rgba(246, 195, 67, 0.95); }
  100% { background: var(--pale); border-color: var(--pale); box-shadow: 0 0 26px rgba(233, 239, 255, 0.3); }
}
@keyframes hosts-in { from { opacity: 0; scale: 0.6; } }

/* Skip is invisible on the big screen, and comes up under the pointer or keyboard. */
.intro-skip { position: absolute; right: 72px; bottom: 44px; font-size: 28px; padding: 16px 30px; opacity: 0; transition: opacity 0.2s; }
.intro-skip:hover, .intro-skip:focus-visible { opacity: 1; }
/* The close-out's logo hold: Skip gives way to a quiet Done, always readable, with a hint beside it. */
.closeout-done { opacity: 1; }
.closeout-hint { position: absolute; right: 72px; bottom: 120px; font-size: 22px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }

/* With less motion asked for: no slam, flash, rays turning, beams sweeping or beat pulse; the names
   appear on their tiles without flying and Start round 1 does not pulse. The sound is unchanged. */
@media (prefers-reduced-motion: reduce) {
  .intro, .intro * { animation: none !important; transition: none !important; }
  .intro-flash { display: none; }
  .intro-tile.in { background: var(--pale); border-color: var(--pale); }
  .stage .controls button.pulse-once { animation: none; }
}

/* The close-out: the opening's layer again, from the awards' Close the show button (closeout.js).
   It keeps the intro's classes, so the black, the slam, the beat pulse and Tim's beat with the
   plaque are drawn by the rules above; closeout.js sets data-phase through black, slam, title, tim,
   thanks, credits and finale. In the thanks phase the plaque shrinks to the top right, still lit,
   and the card comes in under it beside Tim; without Tim the card takes the middle of the stage. */
.closeout .intro-plaque { transform-origin: 1290px 490px; transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1); }
.closeout[data-phase="thanks"] .intro-plaque { transform: translateY(-290px) scale(0.5); }
.closeout[data-phase="thanks"] .intro-tim-beat { visibility: visible; }
/* The same values as the tim phase's, so the rays and the bulbs carry on turning without a restart. */
.closeout:is([data-phase="tim"], [data-phase="thanks"]) .intro-tim-rays { animation: burst-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both, spin 60s linear infinite; }
.closeout:is([data-phase="tim"], [data-phase="thanks"]) .intro-plaque-bulbs circle { animation: chase 0.75s steps(1) infinite; }
.closeout:is([data-phase="tim"], [data-phase="thanks"]) .intro-plaque-bulbs circle.b1 { animation-delay: -0.25s; }
.closeout:is([data-phase="tim"], [data-phase="thanks"]) .intro-plaque-bulbs circle.b2 { animation-delay: -0.5s; }
.closeout.with-tim[data-phase="thanks"] .intro-burst { opacity: 0; }
.closeout:is([data-phase="thanks"], [data-phase="credits"]) .intro-mark { opacity: 0; transform: translateY(calc(-50% - 260px)) scale(0.5); }
.closeout[data-phase="thanks"] .intro-flash { animation: flash-out 0.6s ease-out; }

.closeout-thanks {
  position: absolute;
  left: 120px;
  right: 120px;
  top: 190px;
  bottom: 130px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  visibility: hidden;
}
.closeout.with-tim .closeout-thanks { left: 760px; right: 70px; top: 390px; bottom: 70px; }
.closeout[data-phase="thanks"] .closeout-thanks { visibility: visible; animation: hosts-in 0.6s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.closeout-headline {
  font-family: var(--font-mark);
  font-size: 88px;
  line-height: 1;
  color: var(--gold);
  text-shadow: 0 2px 0 var(--gold-deep), 0 4px 0 var(--gold-deep), 0 6px 0 var(--gold-deep), 0 8px 0 var(--gold-deep), 0 18px 24px rgba(7, 16, 58, 0.75);
  margin-bottom: 34px;
}
.closeout:not(.with-tim) .closeout-headline { font-size: 120px; }
/* Bebas Neue's glyphs reach past its tight line box; the padding takes them in, so fit() measures true. */
.closeout-name {
  flex: none;
  max-height: 360px;
  padding: 0.2em 0;
  overflow: hidden;
  font-family: var(--font-num);
  font-size: 200px;
  line-height: 0.95;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: anywhere;
  color: var(--white);
  text-shadow: 0 0 50px rgba(255, 255, 255, 0.55);
}
.closeout[data-phase="thanks"] .closeout-name { animation: name-flash 1.2s ease-out 0.3s both; }
.closeout-points { margin-top: -10px; font-family: var(--font-num); font-size: 84px; line-height: 1; letter-spacing: 0.06em; color: var(--gold); }
@keyframes name-flash {
  0% { scale: 1.25; color: var(--gold); text-shadow: 0 0 120px rgba(246, 195, 67, 1), 0 0 40px rgba(255, 255, 255, 0.9); }
  100% { scale: 1; }
}

/* Confetti falls over the card while it is up, each piece on its own path. */
.closeout-confetti { position: absolute; inset: 0; overflow: hidden; pointer-events: none; visibility: hidden; }
.closeout[data-phase="thanks"] .closeout-confetti { visibility: visible; }
.closeout-confetti i {
  position: absolute;
  top: -40px;
  left: var(--x);
  width: var(--w);
  height: calc(var(--w) * 0.45);
  background: var(--colour);
  border-radius: 2px;
}
.closeout[data-phase="thanks"] .closeout-confetti i { animation: confetti-fall var(--fall) linear var(--delay) infinite backwards; }
@keyframes confetti-fall {
  from { transform: translate(0, 0) rotate(0deg); }
  to { transform: translate(var(--drift), 1160px) rotate(var(--spin)); }
}

/* The credits roll up through the middle in the display face, over the turning rays, while the
   bulbs round the stage chase. */
.closeout-bulbs { position: absolute; inset: 0; width: 1920px; height: 1080px; opacity: 0; transition: opacity 0.4s; pointer-events: none; }
.closeout:is([data-phase="credits"], [data-phase="finale"]) .closeout-bulbs { opacity: 1; }
.closeout:is([data-phase="credits"], [data-phase="finale"]) .closeout-bulbs circle { animation: chase 0.75s steps(1) infinite; }
.closeout:is([data-phase="credits"], [data-phase="finale"]) .closeout-bulbs circle.b1 { animation-delay: -0.25s; }
.closeout:is([data-phase="credits"], [data-phase="finale"]) .closeout-bulbs circle.b2 { animation-delay: -0.5s; }
.closeout-credits {
  position: absolute;
  left: 140px;
  right: 140px;
  top: 100%;
  display: flex;
  flex-direction: column;
  gap: 90px;
  text-align: center;
  visibility: hidden;
}
.closeout[data-phase="credits"] .closeout-credits { visibility: visible; animation: credits-roll var(--roll) linear both; }
.closeout-credit .intro-eyebrow { margin-bottom: -10px; }
.closeout-credit-name {
  overflow: hidden;
  padding: 0.2em 0;
  white-space: nowrap;
  font-family: var(--font-num);
  font-size: 160px;
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--white);
  text-shadow: 0 0 50px rgba(255, 255, 255, 0.55);
}
.closeout-credit.team { margin-top: -30px; }
.closeout-credit.team .closeout-credit-name { font-size: 100px; }
.closeout-temporal { display: flex; align-items: center; justify-content: center; gap: 0.15em; }
.closeout-temporal img { height: 1em; width: auto; }
@keyframes credits-roll { from { transform: translateY(0); } to { transform: translateY(calc(-100% - 1080px)); } }

/* The finale: the hero logo slams back in the middle and pulses on the beat until the theme has gone. */
.closeout[data-phase="finale"] .intro-mark { transition: none; }
.closeout[data-phase="finale"] .intro-logo { animation: slam 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both, beat-pulse calc(var(--beat) * 2) ease-out 0.5s infinite; }
.closeout[data-phase="finale"] .intro-burst { animation: spin 50s linear infinite, beat-glow calc(var(--beat) * 2) ease-out infinite; }
.closeout[data-phase="finale"] .intro-flash { animation: flash-out 0.6s ease-out; }

/* With less motion asked for, the rules above the question drop every animation in the layer: no
   slam, no confetti, and the credits stand still in the middle of the stage instead of rolling. */
@media (prefers-reduced-motion: reduce) {
  .closeout-confetti { display: none; }
  .closeout-credits { top: 50%; transform: translateY(-50%); gap: 10px; }
  .closeout-credit-name { font-size: 110px; }
  .closeout-credit.team { margin-top: 0; }
  .closeout-credit.team .closeout-credit-name { font-size: 60px; }
}

/* Question */
.question-board { left: 72px; top: 190px; width: 1240px; height: 400px; padding: 24px 56px; }
.no-clock .question-board { width: 1776px; }
.question {
  height: 100%;
  display: flex;
  align-items: center;
  font-family: var(--font-num);
  font-size: 118px;
  line-height: 0.98;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: anywhere;
}

.clock { position: absolute; right: 120px; top: 190px; width: 420px; height: 420px; }
.clock svg { display: block; width: 100%; height: 100%; }
.clock .ring { fill: var(--board); stroke: var(--bevel); stroke-width: 12; }
.clock .wedge { fill: var(--gold); opacity: 0.92; }
.clock .tick { stroke: var(--white); stroke-width: 4; opacity: 0.7; }
.clock .face { fill: var(--stage); }
.clock .num { position: absolute; inset: 0; display: grid; place-items: center; font-family: var(--font-num); font-size: 190px; line-height: 1; color: var(--white); }
/* The last five seconds: the digits stay solid white and the ring flashes instead. */
.clock.urgent .ring { stroke: var(--white); animation: ring-flash 0.5s steps(2, jump-none) infinite alternate; }
.clock.urgent .wedge { fill: var(--white); opacity: 1; }

@keyframes ring-flash { from { stroke: var(--white); } to { stroke: var(--gold); } }

.teams-in { position: absolute; left: 72px; right: 72px; top: 622px; bottom: 140px; overflow: hidden; }
.teams-in .count { font-family: var(--font-num); font-size: 72px; line-height: 1; letter-spacing: 0.03em; text-transform: uppercase; margin-bottom: 18px; }
.teams-in .count b { color: var(--gold); font-weight: 400; }
.tiles { display: flex; flex-wrap: wrap; gap: 14px 16px; perspective: 800px; }
.tile {
  max-width: 100%;
  font: 600 30px/1.1 var(--font-body);
  padding: 14px 20px;
  border-radius: 10px;
  background: var(--tile);
  border: 2px solid var(--bevel);
  color: var(--dim);
  overflow-wrap: anywhere;
}
.tile .tick { display: none; margin-right: 6px; }
.tile.in { background: var(--pale); color: var(--board); border-color: var(--pale); }
.tile.in .tick { display: inline; }
.tile.flip { animation: flip 0.5s ease-out; }
.tiles.crowded { gap: 10px 12px; }
.tiles.crowded .tile { font-size: 28px; padding: 10px 16px; }
/* Once the clock is urgent, the tables still out pulse a gold outline: who the room is waiting for. */
.tiles.urgent .tile:not(.in) { border-color: var(--gold); color: var(--white); animation: tile-wait 0.8s ease-in-out infinite alternate; }

@keyframes tile-wait {
  from { box-shadow: 0 0 0 0 rgba(246, 195, 67, 0); }
  to { box-shadow: 0 0 0 4px var(--gold), 0 0 22px rgba(246, 195, 67, 0.6); }
}

@keyframes flip {
  0% { transform: rotateX(0); background: var(--tile); color: var(--dim); }
  49% { transform: rotateX(90deg); background: var(--tile); color: var(--dim); }
  51% { transform: rotateX(90deg); }
  100% { transform: rotateX(0); }
}

@media (prefers-reduced-motion: reduce) {
  .clock.urgent .ring { animation: none; }
  .tile.flip { animation: none; }
  .tiles.urgent .tile:not(.in) { animation: none; box-shadow: 0 0 0 4px var(--gold); }
}

.answer-line { font-size: 40px; font-weight: 700; }

/* Reveal, first view: the answer in the largest type, a thin track of unlabelled pins, then a
   board of every team in order of closeness, ten rows in two columns. The answer lands first,
   the pins drop, the scoring zones glow up as the needle lands on the answer, and the rows fill
   in, all inside two seconds. The needle is the hottest thing on the track, brighter than the
   gold closest pin, so the back of the room finds the answer before anything else. */

.answer-card { position: absolute; left: 72px; right: 72px; top: 150px; display: flex; align-items: baseline; gap: 28px; }
.answer-card .label { flex: none; font-family: var(--font-num); font-size: 56px; letter-spacing: 0.05em; text-transform: uppercase; color: var(--dim); }
.answer-card .value { flex: none; font-family: var(--font-num); font-size: 150px; line-height: 1; color: var(--white); text-shadow: 0 0 40px rgba(255, 255, 255, 0.5); }

.track { position: absolute; left: 72px; top: 318px; width: 1776px; height: 160px; overflow: visible; }
.track .rail { fill: var(--board); stroke: var(--bevel); stroke-width: 3; }
.track .tick line { stroke: var(--dim); stroke-width: 3; }
.track .tick text { fill: var(--dim); font: 400 30px var(--font-body); text-anchor: middle; }
.track .pin { fill: var(--white); stroke: var(--stage); stroke-width: 4; opacity: 0.9; }
.track .pin.closest { fill: var(--gold); opacity: 1; filter: drop-shadow(0 0 10px rgba(246, 195, 67, 0.9)); }
.track .off-scale { fill: var(--dim); font: 400 30px var(--font-body); }
.track .off-scale.closest { fill: var(--gold); }
.track .zone { fill: var(--gold); fill-opacity: 0.12; }
.track .needle { filter: drop-shadow(0 0 12px rgba(255, 255, 255, 0.85)) drop-shadow(0 0 3px rgba(255, 255, 255, 0.9)); }
.track .needle line { stroke: var(--white); stroke-width: 8; stroke-linecap: round; }
.track .needle rect { fill: var(--white); }
.track .needle text { fill: var(--stage); font: 400 40px var(--font-num); letter-spacing: 1px; text-anchor: middle; }

.reveal-board {
  position: absolute;
  left: 72px;
  right: 72px;
  top: 500px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-auto-rows: min(76px, calc((436px - (var(--rows) - 1) * 14px) / var(--rows)));
  gap: 14px 40px;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* A row: place, name, guess and points. The guess column is capped and an off-scale guess is put in
   words, so a name takes two lines before it is cut. Points are white; only the closest row is gold. */
.row-tile {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr) minmax(0, max-content) 70px;
  align-items: center;
  gap: 18px;
  min-width: 0;
  padding: 0 22px;
  border-radius: 12px;
  background: var(--board);
  border: 2px solid var(--bevel);
  font-size: 28px;
  font-weight: 600;
}
.row-tile .rank { font-family: var(--font-num); font-size: 40px; line-height: 1; color: var(--dim); }
.row-tile .team { min-width: 0; }
.row-tile .team .name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  line-height: 1.04;
  overflow-wrap: anywhere;
}
.row-tile .guess { max-width: 400px; color: var(--dim); font-weight: 500; font-size: 28px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: right; }
.row-tile .pts { font-family: var(--font-num); font-size: 48px; line-height: 1; color: var(--white); text-align: right; }
.row-tile.zero .pts { color: var(--dim); }
.row-tile.closest { border-color: var(--gold); box-shadow: 0 0 22px rgba(246, 195, 67, 0.45); }
.row-tile.closest .team, .row-tile.closest .pts { color: var(--gold); }
/* Thirteen tables or more: one line each, at the floor. */
.reveal-board.dense { gap: 8px 40px; grid-auto-rows: calc((436px - (var(--rows) - 1) * 8px) / var(--rows)); }
.reveal-board.dense .row-tile { font-size: 28px; }
.reveal-board.dense .row-tile .team .name { -webkit-line-clamp: 1; }
.reveal-board.dense .row-tile .rank { font-size: 30px; }
.reveal-board.dense .row-tile .guess { font-size: 28px; }
.reveal-board.dense .row-tile .pts { font-size: 36px; }

/* The booby prize on the board: a quiet outlined tag after the guess, dimmer than the gold star. */
.row-tile .furthest-tag {
  display: inline-block;
  margin-left: 14px;
  padding: 2px 8px 0;
  border: 2px solid var(--dim);
  border-radius: 6px;
  font: 400 30px/1.1 var(--font-num);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--dim);
  vertical-align: 0.1em;
}
/* A guess dead on the answer: the same tag in gold. */
.row-tile .spot-on-tag {
  display: inline-block;
  margin-left: 14px;
  padding: 2px 8px 0;
  border: 2px solid var(--gold);
  border-radius: 6px;
  font: 400 30px/1.1 var(--font-num);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold);
  vertical-align: 0.1em;
}

/* A guess in the top band but not dead on: the same tag in the deeper gold, so SPOT ON stays the brighter. */
.row-tile .close-enough-tag {
  display: inline-block;
  margin-left: 14px;
  padding: 2px 8px 0;
  border: 2px solid var(--gold-deep);
  border-radius: 6px;
  font: 400 30px/1.1 var(--font-num);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-deep);
  vertical-align: 0.1em;
}

.view-reveal .answer-card .label { animation: fade-in 0.4s ease-out both; }
.view-reveal .answer-card .value { animation: land 0.6s cubic-bezier(0.22, 1, 0.36, 1) both; }
.view-reveal .track .pin { animation: drop 0.35s cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(0.55s + var(--i) * 0.05s); }
.view-reveal .track .off-scale { animation: fade-in 0.35s ease-out 0.9s both; }
.view-reveal .track .zones { animation: fade-in 0.4s ease-out 1.05s both; }
.view-reveal .track .needle { animation: needle-in 0.26s cubic-bezier(0.3, 1.5, 0.6, 1) 1.05s both; }
.view-reveal .row-tile { animation: row-in 0.3s ease-out both; animation-delay: calc(0.9s + var(--i) * 0.06s); }

@keyframes fade-in { from { opacity: 0; } }
@keyframes fade-out { to { opacity: 0; } }
@keyframes land {
  from { opacity: 0; transform: translateY(-60px) scale(1.2); text-shadow: 0 0 90px rgba(255, 255, 255, 1); }
}
@keyframes drop { from { opacity: 0; transform: translateY(-50px); } }
@keyframes needle-in { from { opacity: 0; transform: translateY(-48px); } }
@keyframes row-in { from { opacity: 0; transform: translateY(12px); } }

/* Reveal, second view, and the final scores: a podium for the top three, the rest in one column. */

.podium {
  position: absolute;
  left: 72px;
  top: 190px;
  width: 980px;
  height: 720px;
  border-bottom: 6px solid var(--bevel); /* the floor the steps stand on */
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) minmax(0, 1fr);
  align-items: end;
  gap: 22px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.step {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 10px;
  min-width: 0;
  padding: 28px 18px 24px;
  background: var(--board);
  border: 6px solid var(--bevel);
  border-bottom: 0;
  border-radius: 18px 18px 0 0;
  text-align: center;
}
.step .place { font-family: var(--font-mark); font-size: 48px; line-height: 1.1; color: var(--gold); }
/* The name takes what the step has left and presenter.js shrinks it to fit (fitPodium). */
.step .team { min-height: 0; font-size: 34px; font-weight: 700; line-height: 1.12; text-wrap: balance; overflow-wrap: anywhere; overflow: hidden; }
.step .team.closest { color: var(--gold); }
.step-score { flex: none; display: flex; align-items: baseline; justify-content: center; gap: 14px; }
.step .pts { font-family: var(--font-num); font-size: 96px; line-height: 1; }
.step .move { font-size: 30px; line-height: 1.1; white-space: nowrap; }
.step-1 { order: 2; }
.step-2 { order: 1; }
.step-3 { order: 3; }
.step.rank-1 { height: 560px; border-color: var(--gold); box-shadow: 0 0 40px rgba(246, 195, 67, 0.35); }
.step.rank-2 { height: 440px; }
.step.rank-3 { height: 360px; }
.view-complete .step.rank-1 .place { font-size: 40px; }
/* The winner's name in gold, and a gold flash over the top step as the final scores come up. */
.view-complete .step.rank-1 .team { color: var(--gold); }
.view-complete .step.rank-1 { position: relative; overflow: hidden; animation: winner-glow 1.6s ease-out 0.2s both; }
.view-complete .step.rank-1::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 40%, rgba(255, 236, 170, 0.9), rgba(246, 195, 67, 0.55) 45%, rgba(246, 195, 67, 0) 80%);
  opacity: 0;
  pointer-events: none;
  animation: winner-flash 1.2s ease-out 0.2s;
}

@keyframes winner-flash { 0% { opacity: 1; } 100% { opacity: 0; } }
@keyframes winner-glow { 0% { box-shadow: 0 0 120px rgba(246, 195, 67, 0.95); } 100% { box-shadow: 0 0 40px rgba(246, 195, 67, 0.35); } }

/* The winner moment (presenter.js, winnerMoment): the top step opens dark, a white question mark
   where its name and points go under the Winner label, and pulses gold while Tim says the lead under the drum roll. When
   `sealed` comes off, the glow and the flash above play as the fanfare does. A first place in the
   rest, from a tie of four or more, waits unnamed too. */
.view-complete .step.sealed { animation: none; border-color: var(--bevel); box-shadow: none; background: #081345; }
.view-complete .step.sealed::after { animation: none; }
.view-complete .step.sealed .place { color: var(--dim); }
.view-complete .step.sealed .team, .view-complete .step.sealed .step-score { visibility: hidden; }
.view-complete .step.sealed::before {
  content: "?";
  position: absolute;
  inset: auto 0 24px;
  height: 170px;
  display: grid;
  place-items: center;
  font: 400 170px/1 var(--font-num);
  color: var(--white);
}
.view-complete .step.sealed.rolling { border-color: var(--gold); animation: step-roll 0.5s ease-in-out infinite alternate; }
.view-complete .step.sealed.rolling::before { color: var(--gold); }
.view-complete .standings .rest li.sealed .team, .view-complete .standings .rest li.sealed .pts { visibility: hidden; }

@keyframes step-roll {
  from { box-shadow: 0 0 20px rgba(246, 195, 67, 0.25); }
  to { box-shadow: 0 0 70px rgba(246, 195, 67, 0.7); }
}

.standings .rest {
  position: absolute;
  left: 1110px;
  right: 72px;
  top: 190px;
  display: grid;
  grid-auto-rows: min(84px, calc(720px / var(--n)));
  list-style: none;
  margin: 0;
  padding: 0;
}
.standings .rest li {
  display: grid;
  grid-template-columns: 80px minmax(0, 1fr) 110px 90px;
  align-items: center;
  padding: 0 10px;
  border-bottom: 2px solid var(--line);
  font-size: 30px;
  line-height: 1.08;
}
.view-complete .standings .rest li { grid-template-columns: 80px minmax(0, 1fr) 110px; }
.standings .rest .place { font-family: var(--font-num); font-size: 40px; color: var(--dim); }
.standings .rest .team { display: flex; align-items: center; gap: 16px; min-width: 0; }
/* A long name takes two lines before it is cut. */
.standings .rest .team .name { min-width: 0; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.standings .rest .team.closest { color: var(--gold); }
.standings .rest .pts { text-align: right; font-family: var(--font-num); font-size: 40px; }
.standings .rest .move { text-align: right; }

.move { font-weight: 700; }
.move.up { color: var(--up); }
.move.down { color: var(--down); }
.move.flat { color: var(--dim); }

/* A gold tag after the name of a team on a streak of two rounds or more, on the podium and in the rest. */
.streak-tag {
  flex: none;
  align-self: center;
  padding: 3px 10px 0;
  border-radius: 8px;
  background: var(--gold);
  color: var(--gold-ink);
  font: 400 28px/1.1 var(--font-num);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
.step .streak-tag { font-size: 30px; }
/* Why a tie on points went the way it did: a quiet line under the winner's name on the final screen. */
.step .tiebreak-why { flex: none; font: 400 28px/1.1 var(--font-num); letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }

/* The standings make room above the buttons for a strip of callouts, one line at a time. */
.view-standings .podium { height: 650px; }
.view-standings .standings .rest { grid-auto-rows: min(84px, calc(650px / var(--n))); }
.callouts {
  position: absolute;
  left: 72px;
  right: 72px;
  top: 862px;
  height: 76px;
  display: flex;
  align-items: center;
  gap: 28px;
  padding: 0 28px;
  background: var(--board);
  border: 4px solid var(--bevel);
  border-radius: 16px;
}
.callout-slot { position: relative; flex: 1; min-width: 0; align-self: stretch; overflow: hidden; }
.callout {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  font: 700 34px/1.1 var(--font-body);
  color: var(--white);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.callout.in { animation: callout-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both; }
.callout.out { animation: callout-out 0.35s ease-in both; }
.callout-dots { flex: none; display: flex; gap: 10px; }
.callout-dots span { width: 12px; height: 12px; border-radius: 50%; background: var(--tile); box-shadow: inset 0 0 0 2px var(--bevel); }
.callout-dots span.now { background: var(--gold); box-shadow: 0 0 10px rgba(246, 195, 67, 0.8); }

@keyframes callout-in { from { opacity: 0; transform: translateY(100%); } }
@keyframes callout-out { to { opacity: 0; transform: translateY(-100%); } }

/* A moment's headline card: the round's big moments (exactly right, a long streak, a far miss) on
   the reveal's answer view, in the empty space top right beside the answer, clear of the track and
   the board. A gold eyebrow, the team large and the fact under it; the announcer says the sentence.
   presenter.js sets `left` to keep it clear of a long answer, and `.low` puts it over the right of
   the track when the answer leaves no room. It slides in from the right and out again, or only
   fades when less motion is asked for. The animated announcer will stand in this card next. */
.moment-card {
  position: absolute;
  left: 1000px;
  right: 72px;
  top: 104px;
  height: 210px;
  z-index: 5;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
  padding: 6px 36px;
  overflow: hidden;
  background: linear-gradient(90deg, rgba(246, 195, 67, 0.16), rgba(246, 195, 67, 0) 60%), var(--board);
  border: 6px solid var(--gold);
  border-radius: 22px;
  box-shadow: inset 0 0 0 4px #081345, 0 0 0 10px rgba(246, 195, 67, 0.18), 0 0 60px rgba(246, 195, 67, 0.35), 0 24px 60px rgba(0, 0, 0, 0.6);
  cursor: pointer;
  animation: moment-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.moment-card.low { top: 300px; left: auto; width: 760px; }
.moment-card.leaving { animation: moment-out 0.4s cubic-bezier(0.55, 0, 0.75, 0.2) both; }
.moment-card-far { border-color: var(--bevel); box-shadow: inset 0 0 0 4px #081345, 0 0 0 10px rgba(42, 70, 196, 0.3), 0 24px 60px rgba(0, 0, 0, 0.6); background: var(--board); }
.moment-eyebrow { flex: none; font: 400 30px/1 var(--font-num); letter-spacing: 0.24em; text-transform: uppercase; color: var(--gold); }
.moment-card-far .moment-eyebrow { color: var(--dim); }
.moment-team {
  /* At most two lines; fitText shrinks a long name until it fits them. The padding, taken back by the
     margin, holds the tall glyphs of the display face, so they do not read to fitText as overflow. */
  flex: none;
  max-height: 128px;
  margin: -8px 0;
  padding: 8px 0;
  overflow: hidden;
  font: 400 72px/1.04 var(--font-num);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--white);
  text-shadow: 0 0 24px rgba(255, 255, 255, 0.3);
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.moment-fact { flex: none; font: 400 36px/1 var(--font-num); letter-spacing: 0.05em; text-transform: uppercase; color: var(--pale); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The question's quip is a sentence in Tim's bubble, not a team name: the same face, smaller, in up to
   four or five lines (fitText shrinks it to 28px, the least anywhere on the stage). */
.moment-card-quip .moment-team { max-height: 150px; font-size: 56px; line-height: 1.05; text-wrap: pretty; }

@keyframes moment-in { from { opacity: 0; transform: translateX(120px); } }
@keyframes moment-out { to { opacity: 0; transform: translateX(120px); } }

/* A takeover: a new leader fills the standings view for three seconds with the mark, the line in
   the display face and a gold flash as it lands, then the strip carries on. Never shown when less
   motion is asked for. */
.takeover {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 0 140px 60px;
  overflow: hidden;
  background:
    radial-gradient(ellipse 60% 50% at 50% 55%, rgba(246, 195, 67, 0.22), transparent 70%),
    var(--spotlight), var(--stage);
  text-align: center;
  cursor: pointer;
  animation: takeover-in 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.takeover::before { /* the gold flash as it lands */
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 55%, rgba(255, 236, 170, 0.95), rgba(246, 195, 67, 0.75) 45%, rgba(246, 195, 67, 0) 85%);
  opacity: 0;
  pointer-events: none;
  animation: takeover-flash 0.9s ease-out;
}
.takeover.leaving { animation: takeover-out 0.4s ease-in both; }
.takeover-mark { width: 150px; height: 150px; margin-bottom: 36px; filter: drop-shadow(0 0 30px rgba(246, 195, 67, 0.7)); }
.takeover-eyebrow { font: 400 64px/1 var(--font-num); letter-spacing: 0.24em; text-transform: uppercase; color: var(--gold); margin-bottom: 18px; }
.takeover-eyebrow:empty { display: none; }
.takeover-line {
  /* A fixed box two lines tall, so fitText can tell when a long line overflows it. */
  width: 100%;
  height: 420px;
  display: grid;
  place-items: center;
  font: 400 190px/1 var(--font-num);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--white);
  text-shadow: 0 0 50px rgba(255, 255, 255, 0.45), 0 6px 0 rgba(0, 0, 0, 0.35);
  text-wrap: balance;
  overflow-wrap: anywhere;
}

/* The winner's card: the points under the name, and a name box a little shorter so both clear Tim. */
.takeover-winner .takeover-line { height: 380px; }
.takeover-note { margin-top: 18px; font: 400 72px/1 var(--font-num); letter-spacing: 0.08em; text-transform: uppercase; color: var(--gold); }

@keyframes takeover-in { from { opacity: 0; transform: scale(1.08); } }
@keyframes takeover-out { to { opacity: 0; transform: scale(0.96); } }
@keyframes takeover-flash { 0% { opacity: 1; } 100% { opacity: 0; } }

/* Tim Poral on the stage (public/tim.js and public/tim.css draw and pose him). Each spot is a
   `stage-tim-*` class presenter.js puts on the figure. While his voice is off the stage carries
   `tim-off`: he is hidden and the cards he speaks from lose their tails and take their room back. */
.stage.tim-off .stage-tim { display: none; }
.stage .tim.stage-tim.leaving { animation: tim-leave 0.3s ease-in both; }
@keyframes tim-leave { to { opacity: 0; transform: translateY(40px); } }

/* Reveal: 380px at the top right, clear of the track and 28px down, so he stays on the stage when he leans in to
   talk at the top of his bob. The round lights and the "Round N" label step left of him (`tim-up`, set by
   presenter.js while he is up) so they read in full. */
.stage .tim.stage-tim-reveal { position: absolute; right: 72px; top: 28px; z-index: 6; }
.view-reveal .round-lights { transition: right 0.3s ease-out; }
.view-reveal.tim-up .round-lights { right: 420px; }
.stage.tim-off .view-reveal.tim-up .round-lights { right: 72px; }
/* The headline card is his bubble, ending short of him with its tail at his microphone. */
.moment-card.with-tim { right: 420px; overflow: visible; }
.moment-card.with-tim::before, .moment-card.with-tim::after { content: ""; position: absolute; clip-path: polygon(0 0, 100% 50%, 0 100%); }
.moment-card.with-tim::before { right: -52px; top: 44px; width: 46px; height: 64px; background: var(--gold); }
.moment-card.with-tim::after { right: -36px; top: 55px; width: 30px; height: 42px; background: var(--board); }
.moment-card-far.with-tim::before { background: var(--bevel); }
/* A long answer drops the card below him, over the right of the track and in front of the foot of his figure, its tail pointing up at him. */
.moment-card.low.with-tim { top: 330px; height: 170px; right: 72px; z-index: 7; }
.moment-card.low.with-tim::before, .moment-card.low.with-tim::after { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.moment-card.low.with-tim::before { right: 190px; top: -46px; width: 60px; height: 40px; }
.moment-card.low.with-tim::after { right: 199px; top: -12px; width: 42px; height: 22px; }
.stage.tim-off .moment-card.with-tim { right: 72px; }
.stage.tim-off .moment-card.with-tim::before, .stage.tim-off .moment-card.with-tim::after { display: none; }

/* Standings: 220px at the left end of the callout strip, which is his bubble. With him there the
   podium stands 100px higher, so his head clears the second step's score. */
.stage:not(.tim-off) .view-standings:has(.callouts.with-tim) .podium { height: 550px; }
.stage:not(.tim-off) .view-standings:has(.callouts.with-tim) .step.rank-1 { height: 540px; }
.callouts.with-tim { left: 276px; }
.stage .tim.stage-tim-strip { position: absolute; left: -208px; bottom: -24px; }
.callouts.with-tim::before, .callouts.with-tim::after { content: ""; position: absolute; clip-path: polygon(100% 0, 0 50%, 100% 100%); }
.callouts.with-tim::before { left: -32px; top: 14px; width: 28px; height: 40px; background: var(--bevel); }
.callouts.with-tim::after { left: -22px; top: 20px; width: 22px; height: 28px; background: var(--board); }
.stage.tim-off .callouts.with-tim { left: 72px; }
.stage.tim-off .callouts.with-tim::before, .stage.tim-off .callouts.with-tim::after { display: none; }
/* A new leader's takeover: he pops up at the bottom left of the card, 380px. */
.stage .tim.stage-tim-takeover { position: absolute; left: 72px; bottom: 0; }
/* The line sits above his head, so it never runs behind him. */
.takeover.with-tim { padding-bottom: 300px; }

/* Final scores, during the winner moment: 380px standing on the third step (`--step` is its
   height, set by presenter.js), beside the dark top step. */
.stage .tim.stage-tim-final { position: absolute; left: 751px; top: calc(530px - var(--step, 0px)); z-index: 4; }

/* Awards: 260px at the bottom centre, between the buttons, his feet on the floor line. */
.stage .tim.stage-tim-awards { position: absolute; left: calc(50% - 104px); bottom: 6px; }

/* Lobby: 240px beside Show controls, standing on the floor line below the buttons. */
.lobby-tim { position: relative; flex: none; align-self: stretch; width: 192px; }
.stage .tim.stage-tim-lobby { position: absolute; left: 0; bottom: -38px; }

/* Explain the rules: a quiet button after Show controls, hidden with Tim, who does the explaining.
   Pressed, Tim takes the whole stage (public/rules.js): his own layer, built like the opening's, with
   slow gold rays behind, Tim at 700px at the left and one big card to his right for each line, sliding
   in as it starts and out as it ends. The button stays above the layer so a second press stops him. */
.stage .controls button.explain-rules { color: var(--dim); }
.stage .controls button.explain-rules.explaining { position: relative; z-index: 11; color: var(--white); }
.stage.tim-off .explain-rules { display: none; }

.rules-layer { position: absolute; inset: 0; z-index: 10; overflow: hidden; background: var(--spotlight), var(--stage); animation: fade-in 0.3s ease-out both; }
.rules-rays {
  position: absolute;
  left: 1330px;
  top: 540px;
  width: 2600px;
  height: 2600px;
  margin: -1300px 0 0 -1300px;
  background: repeating-conic-gradient(rgba(246, 195, 67, 0.14) 0deg 5deg, transparent 5deg 15deg);
  mask-image: radial-gradient(circle, #000 8%, transparent 56%);
  animation: spin 60s linear infinite;
}
.rules-tim { position: absolute; left: 100px; bottom: 0; animation: tim-rise 0.7s cubic-bezier(0.2, 0.9, 0.3, 1.25) both; }
.rules-skip { position: absolute; right: 72px; bottom: 44px; font-size: 28px; padding: 16px 30px; opacity: 0; transition: opacity 0.2s; }
.rules-skip:hover, .rules-skip:focus-visible { opacity: 1; }

/* The cards share one box right of Tim; only the line being said is showing. Everything inside is in
   em of the card's font size, which the script shrinks only if a scoring table has too many rows. */
.rules-card {
  position: absolute;
  left: 800px;
  right: 100px;
  top: 150px;
  bottom: 170px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 36px 64px;
  overflow: hidden;
  font-size: 120px;
  background: var(--board);
  border: 10px solid var(--gold);
  border-radius: 44px;
  box-shadow: 0 0 0 6px var(--gold-deep), 0 0 90px rgba(246, 195, 67, 0.3), 0 30px 70px rgba(0, 0, 0, 0.55);
  visibility: hidden;
  opacity: 0;
}
.rules-card.in { visibility: visible; animation: rules-card-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1) both; }
.rules-card.out { visibility: visible; animation: rules-card-out 0.4s ease-in both; }
.rules-card-text { display: flex; flex-direction: column; gap: 0.12em; font-family: var(--font-num); font-size: 1em; line-height: 0.98; letter-spacing: 0.02em; text-transform: uppercase; text-wrap: balance; color: var(--white); text-shadow: 0 0 40px rgba(255, 255, 255, 0.4); }
.rules-card-text .gold { color: var(--gold); text-shadow: 0 0 40px rgba(246, 195, 67, 0.5); }
.rules-card-4 { font-size: 150px; }
/* The scoring table at stage size: labels at 0.43em of 120px is 52px and the points large, each row a
   gold wash with a gold edge as Tim reaches it. */
.rules-card .rules h3 { margin: 0 0 0.12em; font-size: 0.55em; line-height: 1; color: var(--gold); }
.rules-card .rules table { width: 100%; font-size: 0.43em; }
.rules-card .rules td { padding: 0.14em 0.4em; border-bottom-width: 3px; }
.rules-card .rules td.pts { padding-right: 0.4em; font-size: 1.7em; line-height: 1; color: var(--white); }
.rules-card .rules tr { background: transparent; transition: background 0.25s ease-out, box-shadow 0.25s ease-out; }
.rules-card .rules tr.lit-row { background: rgba(246, 195, 67, 0.32); box-shadow: inset 10px 0 0 var(--gold); }
.rules-card .rules tr.lit-row td.pts { color: var(--gold); }
@keyframes rules-card-in { from { opacity: 0; transform: translateX(160px); } to { opacity: 1; transform: none; } }
@keyframes rules-card-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateX(-160px); } }
/* With less motion asked for: the cards appear and go without sliding, the rows light without easing,
   the rays hold still and Tim does not rise; his mouth still moves. */
@media (prefers-reduced-motion: reduce) {
  .rules-layer, .rules-layer * { animation: none !important; transition: none !important; }
  .rules-card.in { opacity: 1; }
  .rules-card.out { visibility: hidden; }
}

/* Show controls: a quiet button beside Roll intro on the lobby, and a small panel on the stage above
   the button bar with one switch per feature, each a little track that lights gold when on. Closed
   by default, it sits over the stage without moving anything under it. */
.stage .controls button.show-controls-button { color: var(--dim); }
.show-controls {
  position: absolute; left: 72px; bottom: 140px; z-index: 8; width: 640px;
  padding: 26px 30px 30px; display: flex; flex-direction: column; gap: 14px;
  background: var(--board); border: 4px solid var(--bevel); border-radius: 20px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
}
.show-controls-head { display: flex; align-items: center; justify-content: space-between; }
.show-controls-head h3 { margin: 0; font-size: 36px; }
.show-controls-head button { font-size: 28px; padding: 10px 20px; }
.show-controls-note { margin: 0; color: var(--gold); font-size: 28px; line-height: 1.3; }
.show-controls-list { display: grid; gap: 10px; }

/* Sound check: a quiet button that plays every sound in turn, with a line under it naming each one. */
.sound-check { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.sound-check-button { color: var(--dim); font-size: 28px; padding: 12px 22px; }
.sound-check-status { margin: 0; min-height: 1.3em; font-size: 28px; line-height: 1.3; color: var(--dim); }
.sound-check-status.playing { color: var(--white); }
.stage .login .sound-slot { margin-top: 28px; }
.sound-slot:empty { display: none; }
button.feature-switch { display: flex; align-items: center; gap: 16px; width: 100%; text-align: left; font-size: 28px; padding: 12px 18px; }
.switch-track { position: relative; flex: none; width: 52px; height: 30px; border-radius: 15px; background: var(--tile); box-shadow: inset 0 0 0 2px var(--bevel); transition: background 0.15s ease-out; }
.switch-knob { position: absolute; top: 4px; left: 4px; width: 22px; height: 22px; border-radius: 50%; background: var(--dim); transition: transform 0.15s ease-out, background 0.15s ease-out; }
/* On reads pale and white, not gold, so the switches never compete with the gold main button. */
.feature-switch[aria-checked="true"] .switch-track { background: var(--pale); box-shadow: 0 0 12px rgba(233, 239, 255, 0.45); }
.feature-switch[aria-checked="true"] .switch-knob { transform: translateX(22px); background: var(--board); }
.feature-switch:disabled .switch-track { opacity: 0.5; }

/* Which build the page is talking to, small and dim on the login panel and beside Restart game in
   the lobby; gold when a newer build has gone live under an open page. */
.build-stamp { margin: 0; color: var(--dim); font-size: 28px; letter-spacing: 0.04em; white-space: nowrap; }
.build-stamp:empty { display: none; }
.build-stamp.stale { color: var(--gold); font-weight: 700; }

/* Awards, the second view of the final screen: up to three tiles across the stage, sealed until
   Next award opens them one at a time with a flip. */
.awards {
  position: absolute;
  left: 72px;
  right: 72px;
  top: 160px;
  height: 770px;
  display: grid;
  grid-template-columns: repeat(var(--n), minmax(0, 560px));
  justify-content: center;
  gap: 40px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.award {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  min-width: 0;
  padding: 36px 36px 32px;
  background: var(--board);
  border: 6px solid var(--bevel);
  border-radius: 22px;
  box-shadow: inset 0 0 0 4px #081345, 0 24px 60px rgba(0, 0, 0, 0.5);
  text-align: center;
}
/* The entrance plays once; presenter.js marks the tile `entered` after it, so a roll or a flip
   coming off never restarts it (which made a tile vanish for a moment after its flip). */
.award:not(.entered) { animation: award-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(var(--i) * 0.35s); }
.award-sharpest:not(.sealed), .award-streak:not(.sealed) { border-color: var(--gold); box-shadow: inset 0 0 0 4px #081345, 0 0 40px rgba(246, 195, 67, 0.3); }
/* Each part has a fixed height, so the names and the numbers line up across the tiles whatever wraps. */
.award-mark { flex: none; width: 132px; height: 132px; filter: drop-shadow(0 0 22px rgba(246, 195, 67, 0.55)); transition: opacity 0.3s ease-out, filter 0.3s ease-out; }
.award.sealed .award-mark { opacity: 0.28; filter: grayscale(0.7); }
.award-title { height: 118px; display: grid; place-items: center; font: 400 58px/1.02 var(--font-num); letter-spacing: 0.04em; text-transform: uppercase; color: var(--gold); text-wrap: balance; }
.award-furthest .award-title { color: var(--white); }
.award-teams { width: 100%; height: 150px; display: grid; place-items: center; font-size: 46px; font-weight: 700; line-height: 1.15; text-wrap: balance; overflow: hidden; }
.award-name { display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
.award-sealed { font: 400 150px/1 var(--font-num); color: var(--white); }
.award-value { margin-top: auto; min-height: 154px; display: flex; flex-direction: column; justify-content: flex-end; align-items: center; }
.award-value b { font: 400 130px/0.9 var(--font-num); color: var(--white); }
.award-value span { font: 400 34px/1 var(--font-num); letter-spacing: 0.08em; text-transform: uppercase; color: var(--dim); }
.award-note { height: 72px; font-size: 28px; line-height: 1.2; color: var(--dim); text-wrap: balance; }
/* Sealed, a tile is its mark, its name in white and a white question mark in the middle of what is
   left, with no empty slots under it; the tile whose drum roll is playing owns the gold. */
.award.sealed .award-title { color: var(--white); }
.award.sealed .award-teams { flex: 1; height: auto; }
.award.sealed .award-value, .award.sealed .award-note { display: none; }
/* An award nobody earned opens to "Nobody": the mark stays dim, the border stays plain and there is no number. */
.award-empty .award-mark { opacity: 0.28; filter: grayscale(0.7); }
.award.award-empty:not(.sealed) { border-color: var(--bevel); box-shadow: inset 0 0 0 4px #081345, 0 24px 60px rgba(0, 0, 0, 0.5); }
.award-empty:not(.sealed) .award-title { color: var(--white); }
.award-empty:not(.sealed) .award-teams { flex: 1; height: auto; color: var(--dim); }
.award-empty .award-value, .award-empty .award-note { display: none; }
.award.rolling .award-title, .award.rolling .award-sealed, .award.flip-out .award-title, .award.flip-out .award-sealed { color: var(--gold); }
.award.flip-out { border-color: var(--gold); }
/* The tile whose drum roll is playing glows gold, pulsing. The flip is two half turns: the sealed
   face turns away to edge-on and holds, the face changes, and the new face turns in from the other edge. */
.award.rolling { border-color: var(--gold); animation: award-roll 0.5s ease-in-out infinite alternate; }
.award.flip-out { animation: award-flip-out 0.35s ease-in forwards; }
.award.flip-in { animation: award-flip-in 0.35s ease-out both; }

@keyframes award-in { from { opacity: 0; transform: translateY(40px) scale(0.96); } }
@keyframes award-roll {
  from { box-shadow: inset 0 0 0 4px #081345, 0 0 20px rgba(246, 195, 67, 0.25); }
  to { box-shadow: inset 0 0 0 4px #081345, 0 0 70px rgba(246, 195, 67, 0.7); }
}
@keyframes award-flip-out {
  from { transform: perspective(1600px) rotateY(0deg); }
  to { transform: perspective(1600px) rotateY(90deg); }
}
@keyframes award-flip-in {
  from { transform: perspective(1600px) rotateY(-90deg); }
  to { transform: perspective(1600px) rotateY(0deg); }
}

.closest-note { margin: 4px 0 0; color: var(--gold); font-weight: 700; }
.furthest-note { margin: 4px 0 0; color: var(--dim); font-weight: 600; }

/* Player: the team laptop. Same palette as the stage but calmer, one card in the middle; on the
   guess screen the input is the one gold-bordered thing, and the countdown is a number, not a dial. */

body.player .page {
  max-width: 728px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 24px 24px 16px;
}
body.player .topbar { margin-bottom: 0; }
body.player .topbar .mark-logo { height: 24px; filter: drop-shadow(0 0 8px rgba(246, 195, 67, 0.45)); }
.topbar-end { display: flex; align-items: center; gap: 12px; min-width: 0; text-align: right; overflow-wrap: anywhere; }
body.player main { flex: 1; display: grid; align-content: start; padding: 24px 0 0; }
body.player .card { width: 100%; }
body.player .card h1 { text-transform: uppercase; }
body.player .card .team-name { font-size: 64px; overflow-wrap: anywhere; }
body.player .card button { font-size: 20px; padding: 14px 24px; border-radius: 12px; }
body.player .card button.link { font-size: inherit; padding: 0 4px; }
body.player label { display: block; color: var(--dim); font-size: 16px; }
body.player form.stack > * + * { margin-top: 12px; }

.card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.guess-card .countdown { flex: none; margin-left: auto; }

input.guess-input {
  border-color: var(--gold);
  padding: 16px 22px;
  font: 400 56px/1 var(--font-num);
  letter-spacing: 0.04em;
}
input.guess-input:focus { box-shadow: 0 0 0 4px rgba(246, 195, 67, 0.25); }

.foot { margin-bottom: 0; color: var(--dim); font-size: 16px; }
.points span { font-size: 40px; color: var(--dim); }
.points.zero { color: var(--dim); }

@media (prefers-reduced-motion: reduce) {
  .view-reveal .answer-card .label, .view-reveal .answer-card .value,
  .view-reveal .track .pin, .view-reveal .track .off-scale, .view-reveal .track .zones, .view-reveal .track .needle,
  .view-reveal .row-tile, .callout.in, .callout.out, .award:not(.entered), .award.rolling, .award.flip-out, .award.flip-in { animation: none; }
  .award-mark { transition: none; }
  .switch-track, .switch-knob { transition: none; }
  /* The headline card only fades in and out; the winner's step does not flash. */
  .moment-card { animation: fade-in 0.3s ease-out both; }
  .moment-card.leaving { animation: fade-out 0.3s ease-in both; }
  .view-complete .step.rank-1, .view-complete .step.rank-1::after, .view-complete .step.sealed.rolling { animation: none; }
  /* The winner's card just appears and goes; only it takes the stage under reduced motion. */
  .takeover, .takeover::before, .takeover.leaving { animation: none; }
  /* Tim comes and goes without moving; tim.css stills the figure itself. */
  .stage .tim.stage-tim.leaving { animation: none; }
}

@media (max-width: 600px) {
  body { font-size: 18px; }
  .page { padding: 20px 16px 48px; }
  h1 { font-size: 32px; }
  .prompt { font-size: 26px; }
  .card { padding: 20px; }
  input[type="text"] { font-size: 26px; }
}

/* Questions editor: a working page for the presenter laptop, not the stage. The same board and gold,
   at desk size: one card per question, Save the one gold button, problems in red beside the field. */

body.editor .page { max-width: 1180px; padding: 24px 32px 64px; }
body.editor .topbar { margin-bottom: 24px; }
body.editor .topbar .mark-logo { height: 24px; filter: drop-shadow(0 0 8px rgba(246, 195, 67, 0.45)); }
body.editor .topbar a { color: var(--dim); }
body.editor h1 { font-size: 48px; margin-bottom: 4px; }
body.editor .login { max-width: 560px; }
body.editor .login label { display: block; font-size: 16px; }
body.editor button { font-size: 18px; padding: 12px 22px; border-radius: 12px; }
body.editor button.small { font-size: 15px; padding: 8px 14px; border-radius: 10px; }
body.editor button.danger:hover:not(:disabled) { border-color: var(--down); color: var(--down); }

.editor-head {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  padding: 12px 0 16px;
  background: var(--stage);
  border-bottom: 2px solid var(--line);
}
.editor-head .status { margin: 0; color: var(--dim); font-size: 16px; }
.editor-head .unsaved { display: block; color: var(--gold); font-weight: 700; }
.editor-head .toolbar { flex: none; }
.editor-body .help { margin: 16px 0 0; font-size: 16px; }
.editor-body .message { margin: 16px 0 0; padding: 12px 16px; border-radius: 12px; font-size: 17px; font-weight: 600; background: var(--board); border: 2px solid var(--bevel); }
.editor-body .message.warning { border-color: var(--gold); color: var(--gold); }
.editor-body .message.error { border-color: var(--down); color: var(--down); }
.editor-body .message.ok { border-color: var(--up); color: var(--up); }

.q-list { list-style: none; margin: 20px 0; padding: 0; display: grid; gap: 16px; }
.q-list .empty { padding: 24px 0; }
.card.q { padding: 18px 22px 20px; border-width: 2px; box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35); }
.q-head { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.q-head .q-num { font-family: var(--font-num); font-size: 26px; font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gold); }
.q-head .spacer { flex: 1; }
.q-grid { display: grid; grid-template-columns: 2fr 1.2fr 1fr 1fr; gap: 12px 16px; }
.q-grid .field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.q-grid .field.wide { grid-column: 1 / -1; }
.q-grid .field > span { color: var(--dim); font-size: 14px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.q-grid .field.f-answer { grid-column: 1; }
body.editor .q-grid input[type="text"], body.editor .q-grid select {
  width: 100%;
  font: 500 18px/1.3 var(--font-body);
  padding: 10px 12px;
  border: 2px solid var(--bevel);
  border-radius: 10px;
  background: var(--well);
  color: var(--white);
}
body.editor .q-grid .field.f-prompt input { font-size: 20px; font-weight: 600; }
body.editor .q-grid .field.f-answer input { font: 400 26px/1.1 var(--font-num); letter-spacing: 0.04em; padding: 8px 12px; }
body.editor .q-grid select { appearance: auto; }
body.editor .q-grid input:focus, body.editor .q-grid select:focus { border-color: var(--gold); outline: none; }
body.editor .q-grid .invalid, body.editor .card.q.invalid { border-color: var(--down); box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.3); }
.q-grid .field .count { align-self: flex-end; color: var(--dim); font-size: 13px; }

/* The Show section, above the questions: the hosts Tim addresses and the standings cadence, with one Save. */
body.editor h2 { margin: 0 0 12px; font-family: var(--font-num); font-size: 26px; font-weight: 400; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gold); }
.card.show-section { margin: 20px 0 8px; padding: 18px 22px 20px; border-width: 2px; }
.show-section .field { display: flex; flex-direction: column; gap: 4px; }
.show-section .field > span { color: var(--dim); font-size: 14px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.show-section .show-row { display: flex; gap: 12px; align-items: stretch; margin-top: 16px; }
.show-section .standings-field { margin-top: 18px; }
body.editor .show-section input[type="text"],
body.editor .show-section input[type="number"] {
  min-width: 0;
  max-width: 560px;
  font: 600 20px/1.3 var(--font-body);
  padding: 10px 12px;
  border: 2px solid var(--bevel);
  border-radius: 10px;
  background: var(--well);
  color: var(--white);
}
body.editor .show-section input[type="number"] { width: 120px; }
body.editor .show-section input[type="text"]:focus,
body.editor .show-section input[type="number"]:focus { border-color: var(--gold); outline: none; }
body.editor .show-section input.invalid { border-color: var(--down); box-shadow: 0 0 0 3px rgba(255, 107, 107, 0.3); }
.show-section .show-preview { margin: 10px 0 0; font-size: 17px; color: var(--pale); }
.show-section .show-note { margin: 8px 0 0; font-size: 16px; font-weight: 600; }
.show-section .show-note.ok { color: var(--up); }
.show-section .show-note.error { color: var(--down); }
.q-grid .field .count.over { color: var(--down); font-weight: 700; }

@media (max-width: 760px) {
  body.editor .page { padding: 16px 16px 48px; }
  .editor-head { flex-direction: column; align-items: stretch; }
  .q-grid { grid-template-columns: 1fr 1fr; }
  .q-grid .field.f-answer { grid-column: auto; }
}

/* The lobby: how many questions the stored set holds, beside the round lights. */
.round-lights .set-count { margin-left: 18px; color: var(--dim); font-size: 24px; letter-spacing: 0.02em; white-space: nowrap; }
.stage .login .editor-link { margin: 24px 0 0; font-size: 26px; }
.stage .login .editor-link a { color: var(--dim); }

/* The lobby's Log out, quiet beside the build stamp. */
.stage .controls button.log-out { padding: 0 4px; font-size: 28px; font-weight: 400; color: var(--dim); }
.stage .controls button.log-out:hover { color: var(--white); }
