/*
 * Player device -- a phone, a tablet, whatever is on the table. Handled by
 * strangers mid-pint, so targets are big and nothing important is more than one
 * tap away.
 *
 * The rule the gameplay screen is built on: the player is doing exactly one
 * thing, finding the right answer fast, and everything that isn't the question,
 * the four answers and what a tap is worth right now is in their way. The board,
 * the round and the branding are on the TV the whole room is already looking at;
 * the board is one chip here, and only when asked for. The category earns its
 * line, because it is what the question is about.
 */

html, body { height: 100%; overflow: hidden; -webkit-user-select: none; user-select: none; }
body { display: flex; flex-direction: column; }

.small { font-size: 12px; }

/* ------------------------------------------------------------- team bar --- */
/* One line, three facts: what this player has, who they are, which question this
   is. The branding, the rank chip, the streak chip and the mode badge that used
   to live here are all things nobody looks at while answering. */

.p-bar {
  display: flex; align-items: center; gap: 10px;
  height: 44px; padding: 0 44px 0 16px; /* the connection dot sits in the right gutter */
  border-bottom: 1px solid var(--line);
}
/* A button, so the team can be changed from anywhere, but it has to read as
   part of the bar rather than as a control competing with the answers. */
.p-team {
  flex: 0 1 auto; min-width: 0; text-align: right; display: flex; align-items: center; gap: 8px;
  background: none; border: none; padding: 0; color: var(--muted); font: inherit; cursor: pointer;
}
.p-team-name {
  font-weight: 700; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.p-team-out {
  flex: 0 0 auto; font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--incorrect);
}
/* The running total, on the clock line rather than in the header: filled brand
   purple with white digits, so it can't be misread as the seconds left or as
   what this question is worth (both of which sit beside it in their own
   colours). */
.p-score-badge {
  flex: 0 0 auto;
  font-family: var(--font-display); font-weight: 900; font-size: 20px;
  font-variant-numeric: tabular-nums; color: #fff;
  background: var(--brand); border-radius: var(--r-md);
  padding: 2px 12px; line-height: 1.25;
  box-shadow: 0 0 14px var(--brand-glow);
}
.p-q-progress {
  flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 800; color: var(--muted);
  letter-spacing: 0.06em; font-variant-numeric: tabular-nums;
}
/* The corner is a button (it opens the room sheet) but reads as the label it
   always was; the caret is the only hint, and it drops while a question is up
   so nothing new appears beside the answers. */
.p-room-chip {
  background: none; border: none; padding: 0; font: inherit; cursor: pointer; text-align: left;
  display: flex; align-items: center; gap: 4px;
  font-size: 12px; font-weight: 800; letter-spacing: 0.06em; color: var(--muted);
}
.p-room-chip-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-room-chip-caret { flex: 0 0 auto; font-size: 10px; opacity: 0.8; }
.p-room-chip.is-question .p-room-chip-caret { display: none; }

/* ---------------------------------------------------------- room sheet --- */
.room-sheet-card { display: flex; flex-direction: column; gap: 10px; }
.room-row {
  display: flex; align-items: center; gap: 12px; margin: 0;
  padding: 12px 14px; border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--line);
}
.room-row-here { border-color: var(--line-strong); background: rgba(255, 255, 255, 0.07); }
.room-row-text { flex: 1 1 auto; min-width: 0; }
.room-row-eyebrow {
  font-size: 11px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}
.room-row-name { font-weight: 800; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-row-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.room-row-btn { flex: 0 0 auto; padding: 8px 14px; }
.room-live-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px;
  background: var(--correct, #3ddc84); box-shadow: 0 0 8px var(--correct, #3ddc84);
}
.room-join-code {
  flex: 0 0 84px; width: 84px; padding: 8px 10px; text-align: center; text-transform: uppercase;
  font: inherit; font-weight: 800; letter-spacing: 0.14em;
  background: var(--surface); color: var(--text); border: 1px solid var(--line-strong); border-radius: var(--r-md);
}
.room-row-join { flex-wrap: wrap; }
.room-row-join .room-row-text { flex-basis: 100%; }
.room-row-join .room-join-code { flex: 1 1 0; min-width: 0; width: auto; text-align: left; }
.room-row-join .room-row-btn { padding: 10px 18px; }
.room-sheet-note { margin: 2px 4px 0; }

/* Live's day and week boards inside the sheet: the reason to give a name. */
.room-board {
  padding: 12px 14px; border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--line);
}
.room-board-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.room-board-tabs { display: flex; gap: 4px; }
.room-board-tab {
  font: inherit; font-size: 12px; font-weight: 800; padding: 4px 10px; border-radius: 999px; cursor: pointer;
  color: var(--muted); background: none; border: 1px solid var(--line);
}
.room-board-tab.is-on { color: var(--text); border-color: var(--line-strong); background: rgba(255, 255, 255, 0.08); }
.room-board-rows { list-style: none; margin: 10px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.room-board-row { display: flex; align-items: center; gap: 10px; font-size: 14px; }
.room-board-row .av-c { --av: 28px; }
.room-board-rank { flex: 0 0 22px; font-weight: 800; color: var(--muted); text-align: right; font-variant-numeric: tabular-nums; }
.room-board-name { flex: 1 1 auto; min-width: 0; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-board-pts { flex: 0 0 auto; font-weight: 800; font-variant-numeric: tabular-nums; }
.room-board-row.is-me .room-board-name, .room-board-row.is-me .room-board-pts { color: var(--accent); }
.room-board-flag { flex: 0 0 auto; margin-left: 4px; padding: 3px 8px; border-radius: 999px; border: 1px solid var(--line, rgba(255,255,255,0.18)); background: transparent; color: var(--muted); font: inherit; font-size: 11px; font-weight: 700; }
.room-board-flag:disabled { opacity: 0.6; }
.room-board-empty { margin: 10px 0 0; font-size: 13px; color: var(--muted); }
.room-board-me { margin-top: 8px; font-size: 13px; font-weight: 700; color: var(--muted); }

/* --------------------------------------------------------------- stage --- */

.p-stage { flex: 1; min-height: 0; position: relative; }
.screen { position: absolute; inset: 0; padding: 20px; display: flex; flex-direction: column; overflow-y: auto; }

.p-lobby-title { font-family: var(--font-display); font-size: 34px; font-weight: 900; margin: 6px 0 10px; }

/* ---------------------------------------------------------------- join --- */
/* The first thing a stranger sees on a shared tablet, so it is one question
   with one obvious answer and a thumb-sized target. */

#join-screen { padding: 14px 18px 12px; gap: 12px; }
.join-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex: 0 0 auto; }
.join-brand { display: flex; align-items: center; gap: 10px; }
.join-brand .p-lobby-mark { width: 38px; height: 38px; }
.join-brand .p-lobby-word { font-size: 24px; }
.join-host { font-size: 14px; font-weight: 800; color: var(--brand-bright); font-variant-numeric: tabular-nums; letter-spacing: 0.04em; }
/* Room for the floating face over the corner once the phone has a player. */
body.phone-mode:has(.p-chip-phone:not(.hidden)) .join-host { padding-right: 56px; }
body.phone-mode.chat-on:has(.p-chip-phone:not(.hidden)) .join-host { padding-right: 100px; }
.join-head { flex: 0 0 auto; }

/* The room-code door. While it is up nothing else on the page is true yet, so
   every other screen is off, whatever the last snapshot said. */
body.needs-room .screen:not(#room-screen) { display: none !important; }
body.needs-room #room-screen { display: flex !important; }
/* No team yet, and the "room code needed" pill sits where the name would. */
body.needs-room .p-team { visibility: hidden; }
/* The bar has nothing true to say yet (no team, no question); the landing
   page brings its own header. */
body.needs-room .p-bar, body.needs-room #status { display: none; }
.room-form { display: flex; flex-direction: column; gap: 12px; }

/* ------------------------------------------------------------- landing --- */
/* A poster over the hero art: copy left, join card right, the story below.
   Every colour is a token; gold appears only where it is earned (the live
   question value, the rank-1 number and the scores in the TV illustration). */
.landing {
  display: block; padding: 0; overflow-y: auto; overflow-x: hidden;
  -webkit-user-select: text; user-select: text;
  background: var(--bg); scroll-behavior: smooth;
}
.landing-top {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 16px 20px; border-bottom: 1px solid var(--line);
  position: relative; z-index: 2; background: rgba(11, 7, 20, 0.6); backdrop-filter: blur(6px);
}
.landing-top .brand-name { font-size: 22px; }
.landing-top .brand-mark { width: 40px; height: 40px; }
.landing-nav { display: flex; align-items: center; gap: 8px; flex: none; }
.landing-link {
  color: var(--muted); font-size: 13px; font-weight: 600; text-decoration: none; white-space: nowrap;
  padding: 8px 12px; border-radius: var(--r-pill);
}
.landing-link:hover { color: var(--text); }
.landing-link-host { border: 1px solid var(--line); padding: 8px 14px; }
.landing-link-host:hover { border-color: var(--line-strong); }

.landing-hero { position: relative; display: grid; gap: 22px; padding: 22px 20px 0; }
.landing-copy { position: relative; z-index: 1; }
.landing-eyebrow {
  display: block; font-size: 13px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--brand-bright); margin-bottom: 14px;
}
.landing-h1 {
  margin: 0 0 12px; font-family: var(--font-display); font-weight: 900;
  font-size: clamp(34px, 5.2vw, 60px); line-height: 0.98; letter-spacing: -0.02em;
}
.landing-wordmark { white-space: nowrap; }
.landing-wordmark .brand-name-second { color: var(--brand-bright); }
.landing-lede { margin: 0 0 16px; font-size: clamp(16px, 1.6vw, 20px); line-height: 1.45; color: rgba(255, 255, 255, 0.86); max-width: 34ch; }
.landing-proof { margin: 0; font-weight: 800; font-size: clamp(16px, 1.4vw, 19px); color: var(--gold); letter-spacing: 0.01em; }

/* --- the join card --- */
.landing-join {
  position: relative; z-index: 1;
  background: linear-gradient(160deg, rgba(168, 85, 247, 0.22), rgba(60, 25, 110, 0.38));
  border: 1.5px solid rgba(196, 150, 255, 0.55); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-radius: 22px; padding: 30px 30px 26px;
  box-shadow: 0 0 0 1px rgba(168, 85, 247, 0.18), 0 0 46px rgba(168, 85, 247, 0.28), 0 24px 60px rgba(0, 0, 0, 0.45);
  max-width: 440px; width: 100%; margin-inline: auto;
}
.landing-join-title { margin: 0 0 8px; font-family: var(--font-display); font-weight: 900; font-size: 32px; letter-spacing: -0.01em; color: #fff; }
.landing-join-lede { margin: 0 0 20px; color: rgba(255, 255, 255, 0.78); font-size: 16px; line-height: 1.45; }
.landing-label { font-size: 12px; font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase; color: rgba(255, 255, 255, 0.8); margin-bottom: -2px; }
.landing-join #room-code-input {
  width: 100%; font: 800 30px/1 var(--font-display); letter-spacing: 0.3em; text-transform: uppercase;
  text-align: center; color: #fff; background: rgba(15, 8, 30, 0.55); border: 1px solid rgba(196, 150, 255, 0.45);
  border-radius: 12px; padding: 18px 12px 18px calc(12px + 0.3em); outline: none;
  font-variant-numeric: tabular-nums;
}
.landing-join #room-code-input::placeholder { color: rgba(255, 255, 255, 0.4); }
.landing-join #room-code-input:focus { border-color: var(--brand-bright); box-shadow: 0 0 0 4px rgba(168, 85, 247, 0.28); }
.landing-btn {
  display: block; width: 100%; font: 800 18px/1 var(--font-display); letter-spacing: 0.01em;
  color: #fff; background: linear-gradient(180deg, #9d6bff, var(--brand)); border: 0; border-radius: 12px;
  padding: 19px; cursor: pointer; box-shadow: 0 10px 28px rgba(139, 92, 246, 0.45);
}
.landing-btn:hover, .landing-btn:focus-visible { background: var(--brand-bright); }
.landing-join .join-error { margin: 10px 0 0; }
.landing-or {
  display: flex; align-items: center; gap: 14px; color: rgba(255, 255, 255, 0.7); font-size: 14px;
  margin: 18px 0 14px;
}
.landing-or::before, .landing-or::after { content: ""; flex: 1; height: 1px; background: rgba(196, 150, 255, 0.35); }
.landing-btn-2 {
  display: flex; align-items: center; justify-content: center; gap: 12px; width: 100%;
  font: 700 16px/1 var(--font); color: #fff; background: rgba(15, 8, 30, 0.35);
  border: 1px solid rgba(196, 150, 255, 0.45); border-radius: 12px; padding: 17px; cursor: pointer;
}
.landing-btn-2:hover { border-color: var(--brand-bright); background: rgba(168, 85, 247, 0.16); }
.landing-btn-2 svg { color: #fff; }
.landing-qr-help { margin: 12px 0 0; font-size: 13px; line-height: 1.45; color: rgba(255, 255, 255, 0.72); }
.landing-waiting { margin: 18px 0 0; text-align: center; font-size: 15px; color: rgba(255, 255, 255, 0.72); }
.landing-live-link {
  display: block; margin: 10px 0 0; text-align: center; font-size: 14px; font-weight: 700;
  color: var(--brand-bright); text-decoration: none;
}
.landing-live-link.hidden { display: none; }

/* --- the art --- */
/* Below 1280px the two columns would sit on the podium, so phones and tablets
   get the mobile crop under the card (the code box has to be above the fold on
   a 400x800 screen); wide screens paint the wide export behind the whole hero.
   Neither file is fetched by the other breakpoint. */
.landing-art-mobile { display: none; margin: 0 -20px; aspect-ratio: 800 / 640; background-color: var(--bg); }
@media (max-width: 1279px) {
  .landing-art-mobile {
    display: block;
    background-image: url("/shared/brand/player-hero-mobile-2x.webp");
    background-size: cover; background-position: center;
  }
}

/* --- below the fold --- */
.landing-how { display: grid; gap: 14px; padding: 26px 20px 20px; max-width: 1180px; margin-inline: auto; }
.landing-how > * { min-width: 0; }
.landing-trio { display: grid; gap: 12px; grid-template-columns: 1fr; }
.landing-trio article { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md); padding: 18px 16px 16px; }
.landing-glyph { display: block; width: 28px; height: 28px; color: var(--brand-bright); margin-bottom: 12px; }
.landing-glyph .lc-icon { width: 28px; height: 28px; }
.landing-trio h3 { margin: 0 0 6px; font-size: 16px; font-weight: 800; letter-spacing: -0.01em; }
.landing-trio p { margin: 0; font-size: 14px; line-height: 1.5; color: rgba(255, 255, 255, 0.74); }
.landing-trio p b { color: var(--text); font-weight: 700; }
.landing-fade { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 12px; margin-top: 12px; }
.landing-fade-val { font: 900 22px/1 var(--font-display); color: var(--gold); font-variant-numeric: tabular-nums; }
.landing-fade-bar { height: 8px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.landing-fade-bar i { display: block; height: 100%; width: 62%; background: linear-gradient(90deg, var(--gold), rgba(245, 179, 60, 0.35)); border-radius: var(--r-pill); }

.landing-tv { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 14px; box-shadow: var(--shadow-2); }
.landing-tv-head {
  display: flex; align-items: center; justify-content: space-between; font-size: 11px; font-weight: 800;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--muted); padding: 4px 6px 12px;
}
.landing-tv-mode { color: var(--brand-bright); }
.landing-tv-q { padding: 6px 6px 12px; font-weight: 800; font-size: 15px; }
.landing-tv-rows { display: grid; gap: 8px; }
.landing-tv-row {
  display: grid; grid-template-columns: 26px 1fr auto auto; align-items: center; gap: 10px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-md); padding: 10px 12px;
}
.landing-tv-row.is-top { border-color: rgba(245, 179, 60, 0.45); }
.landing-tv-rank { font-weight: 900; color: var(--muted); font-size: 13px; }
.landing-tv-row.is-top .landing-tv-rank { color: var(--gold); }
.landing-tv-team { font-weight: 800; font-size: 14px; min-width: 0; }
.landing-tv-team small { display: block; color: var(--muted); font-weight: 600; font-size: 11px; margin-top: 2px; }
.landing-tv-score { font-weight: 900; color: var(--gold); font-variant-numeric: tabular-nums; font-size: 14px; }
.landing-stamp {
  font-weight: 900; letter-spacing: 0.16em; text-transform: uppercase; font-size: 10.5px;
  padding: 5px 9px; border-radius: var(--r-sm); border: 1.5px solid currentColor; white-space: nowrap;
}
.landing-stamp.is-good { color: var(--correct); }
.landing-stamp.is-missed { color: var(--incorrect); }
.landing-stamp.is-none { color: var(--muted); }
.landing-tv-cap { margin: 14px 6px 4px; font-size: 13px; color: rgba(255, 255, 255, 0.74); line-height: 1.5; }

.landing-steps { display: grid; gap: 10px; grid-template-columns: 1fr; margin-top: 8px; }
.landing-steps > div { display: flex; gap: 12px; align-items: flex-start; font-size: 14px; line-height: 1.5; color: rgba(255, 255, 255, 0.74); }
.landing-steps b { color: var(--text); }
.landing-n {
  flex: none; width: 26px; height: 26px; border-radius: 50%; background: var(--brand); color: var(--on-brand);
  font-weight: 900; font-size: 13px; display: grid; place-items: center;
}
.landing-foot { text-align: center; color: var(--muted); font-size: 12px; letter-spacing: 0.08em; padding: 18px 0 8px; }
.landing-foot a { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; }
.landing-foot b { color: var(--text); letter-spacing: 0.2em; text-transform: uppercase; font-size: 11px; }

@media (max-width: 1279px) {
  /* Order: header, join card, art, copy, story. */
  .landing-join { order: 0; }
  .landing-art-mobile { order: 1; }
  .landing-copy { order: 2; }
  .landing-copy { max-width: 640px; margin-inline: auto; text-align: center; }
  .landing-lede { margin-inline: auto; }
}
@media (max-width: 639px) {
  .landing-top .brand-sub { display: none; }
  .landing-link:not(.landing-link-host) { display: none; }
}
@media (max-width: 420px) {
  .landing-top { padding: 12px 14px; gap: 8px; }
  .landing-top .brand-name { font-size: 17px; }
  .landing-link-host { padding: 7px 10px; font-size: 12px; }
  .landing-join { padding: 24px 20px 22px; }
  .landing-join-title { font-size: 27px; }
  .landing-tv-head { letter-spacing: 0.08em; gap: 8px; font-size: 10px; white-space: nowrap; }
  .landing-tv-row { grid-template-columns: 22px 1fr auto; gap: 8px; }
  .landing-tv-score { grid-column: 3; grid-row: 1; }
  .landing-stamp { grid-column: 2 / span 2; justify-self: start; margin-top: 4px; }
}
@media (min-width: 640px) {
  .landing-trio, .landing-steps { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 1280px) {
  .landing-hero {
    grid-template-columns: minmax(0, 31vw) minmax(0, min(420px, 30vw)); justify-content: space-between;
    gap: 48px; align-items: center; padding: 56px 5vw 40px; min-height: min(80vh, 780px);
  }
  /* The wide export is the whole hero's backdrop; its podium sits in the lower
     centre, between the two columns, and --bg is under it until it paints. */
  .landing-hero::before {
    content: ""; position: absolute; inset: 0; left: 50%; width: 100vw; transform: translateX(-50%);
    background: var(--bg) url("/shared/brand/player-hero-2x.webp") center / cover no-repeat;
    pointer-events: none;
  }
  .landing-copy, .landing-join { z-index: 1; }
  /* Only the art's clear thirds get HTML; the podium and tiles stay in view. */
  .landing-copy { justify-self: start; }
  .landing-h1 { font-size: clamp(24px, 2.45vw, 44px); line-height: 1.1; letter-spacing: -0.025em; white-space: nowrap; }
  .landing-lede { font-size: clamp(15px, 1.25vw, 19px); max-width: 30ch; }
  .landing-join { max-width: 420px; }
  .landing-join { position: sticky; top: 24px; margin-inline: 0; justify-self: end; }
}
#join-screen .p-lobby-title { font-size: 30px; margin: 0; line-height: 1.05; }
.join-lede { margin: 4px 0 0; font-size: 14px; font-weight: 700; color: var(--muted); line-height: 1.35; }
/* Each group of controls in its own card, so the eye reads name, then how,
   then Play, and nothing is a paragraph. */
.join-card {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px;
  padding: 12px 14px;
  background: linear-gradient(180deg, rgba(168, 85, 247, 0.06), rgba(168, 85, 247, 0.02));
  border: 1px solid var(--line); border-radius: var(--r-md);
}
.join-card .join-sub-head { margin: 0; }
.join-row-label { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.join-row-hint { font-size: 12px; font-weight: 700; color: var(--muted); }
.join-or {
  display: flex; align-items: center; gap: 10px; font-size: 12px; font-weight: 800;
  color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em;
}
.join-or::before, .join-or::after { content: ""; flex: 1; height: 1px; background: var(--line); }
/* The ready-made names: the phone's own picker, so a taken one greys out the
   way a phone greys out anything it won't let you pick. */
.join-select {
  width: 100%; background: var(--bg);
  color: var(--text); border: 2px solid var(--line-strong); border-radius: var(--r-md);
  font-family: inherit; font-size: 16px; font-weight: 700; padding: 12px 14px;
}
.join-select:focus { outline: none; border-color: var(--brand-bright); box-shadow: 0 0 20px var(--brand-glow); }
.join-select option:disabled { color: #6b7280; }

/* The face, before the name: just the face and "Change". The colour is picked
   on the wheel, and the name is the next card, so neither sits beside it. */
.join-avatar-card {
  flex: 0 0 auto; display: flex; align-items: center; gap: 14px; text-align: left;
  padding: 12px 14px; cursor: pointer; font-family: inherit; color: var(--text);
  background: linear-gradient(180deg, rgba(168, 85, 247, 0.12), rgba(168, 85, 247, 0.03));
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  transition: border-color var(--t-fast) ease, transform var(--t-fast) ease;
}
.join-avatar-card:active { transform: scale(0.99); border-color: var(--brand-bright); }
.join-avatar-face .av-c { --av: 84px; }
.join-avatar-copy { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.join-avatar-copy strong { font-family: var(--font-display); font-size: 19px; font-weight: 900; line-height: 1.1; }
.join-avatar-copy span { font-size: 13px; font-weight: 600; color: var(--muted); }
.join-avatar-change { flex: 0 0 auto; font-size: 14px; font-weight: 900; color: var(--brand-bright); }

/* A device already on a table: what it is on, and the way off it, before any of
   the choosing. The single most common mistake here is joining the wrong
   table's team, and until now the only way out was signing the player out. */
.join-current {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 10px; align-items: flex-start;
  margin: 0 0 16px; padding: 14px 16px;
  background: linear-gradient(180deg, rgba(34, 211, 238, 0.12), rgba(34, 211, 238, 0.03));
  border: 1px solid rgba(34, 211, 238, 0.4); border-radius: var(--r-md);
}
.join-current-line { font-size: 16px; font-weight: 700; }
.join-current-line b { font-weight: 900; }
.join-leave { font-size: 15px; padding: 12px 16px; }

.join-sub-head {
  margin: 0 0 8px; font-size: 12px; font-weight: 900; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.12em;
}

/* The name is taken and this player hasn't got its code: the way forward is a
   button, not the paragraph telling them so. */
.join-guest-offer {
  flex: 0 0 auto; display: flex; flex-direction: column; gap: 8px;
}
.join-guest-btn { font-size: 17px; padding: 14px 16px; }

/* Solo or a table: a two-way switch with the consequence written under each
   side, so a stranger reads what the choice means without a paragraph. */
.join-mode {
  display: flex; gap: 4px; padding: 4px; flex: 0 0 auto;
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--r-md);
}
.join-mode-btn {
  flex: 1; display: flex; flex-direction: column; gap: 2px; align-items: center; text-align: center;
  background: none; color: var(--text); border: none; border-radius: calc(var(--r-md) - 3px);
  font-family: inherit; padding: 10px 4px; min-height: 58px; min-width: 0; justify-content: center;
  transition: background var(--t-fast) ease, color var(--t-fast) ease;
}
.join-mode-btn.is-selected {
  background: var(--brand); color: #fff;
  box-shadow: 0 0 16px var(--brand-glow);
}
.join-mode-btn.is-selected .join-mode-sub { color: rgba(255, 255, 255, 0.85); }
.join-mode-title { font-size: 15px; font-weight: 900; }
.join-regular-pin-row { margin-top: 10px; }
.join-mode-sub { font-size: 11px; font-weight: 600; color: var(--muted); line-height: 1.3; }
.join-sub { font-size: 15px; font-weight: 700; color: var(--muted); margin: 4px 0 10px; }
/* The how screen: two big cards, one tap each. */
#join-step-who, #join-step-how { display: flex; flex-direction: column; gap: 12px; }
.join-how { display: flex; flex-direction: column; gap: 10px; }
.join-how-btn {
  display: flex; flex-direction: column; gap: 4px; align-items: center; text-align: center;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  color: var(--text); border: 2px solid var(--line-strong); border-radius: var(--r-md);
  font-family: inherit; padding: 18px 14px; min-height: 76px; justify-content: center;
  transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease, transform var(--t-fast) ease;
}
.join-how-btn .join-mode-title { font-size: 18px; }
.join-how-btn .join-mode-sub { font-size: 12px; }
.join-how-btn:active { transform: scale(0.98); }
.join-how-btn.is-selected {
  border-color: var(--brand-bright); box-shadow: 0 0 18px var(--brand-glow);
}
/* Teams already playing are the gold thing on this screen: the second person
   at a table is looking for the one their friend just made. */
.join-existing-wrap { border-color: rgba(245, 179, 60, 0.45); }
.join-existing { display: flex; flex-wrap: wrap; gap: 10px; padding-top: 2px; }
.join-team-btn {
  background: linear-gradient(180deg, rgba(245, 179, 60, 0.16), rgba(245, 179, 60, 0.05));
  color: var(--text); border: 2px solid var(--gold); border-radius: var(--r-pill);
  font-family: inherit; font-size: 16px; font-weight: 800; padding: 12px 18px;
  box-shadow: 0 0 14px rgba(245, 179, 60, 0.18);
  transition: border-color var(--t-fast) ease, transform var(--t-fast) ease;
}
.join-team-btn:active { transform: scale(0.97); }

.join-form { display: flex; flex-direction: column; gap: 12px; flex: 0 0 auto; }
.join-input {
  background: var(--bg); color: var(--text); border: 2px solid var(--line-strong);
  border-radius: var(--r-md); font-family: inherit; font-size: 18px; font-weight: 700;
  padding: 12px 14px; width: 100%;
  -webkit-user-select: text; user-select: text;
}
.join-input:focus { outline: none; border-color: var(--brand-bright); box-shadow: 0 0 20px var(--brand-glow); }
.join-input-small { font-size: 16px; padding: 12px 14px; }
/* Play stays on screen while the form scrolls under it, so a thumb never
   has to hunt for it. */
.join-submit-bar {
  position: sticky; bottom: -12px; z-index: 2; margin: 0 -18px -12px; padding: 14px 18px 12px;
  background: var(--bg);
  box-shadow: 0 -14px 14px -6px var(--bg);
}
.join-submit { font-size: 19px; padding: 16px 18px; width: 100%; }
.join-error { color: var(--incorrect); font-size: 15px; font-weight: 700; margin: 0 0 8px; }
.join-change { margin-top: 18px; align-self: flex-start; }
.join-foot {
  flex: 0 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px;
  margin-top: auto; padding-top: 4px;
}
.join-link {
  background: none; border: none; padding: 6px 0; font: inherit; font-size: 14px; font-weight: 800;
  color: var(--brand-bright); cursor: pointer;
}
.join-foot .join-details { margin: 0 0 0 auto; padding: 0; flex: 0 0 auto; }
.join-foot .join-details[open] { flex: 1 0 100%; margin-left: 0; }
.join-foot .join-details summary { list-style: none; font-size: 14px; font-weight: 800; padding: 6px 0; }
.join-foot .join-details summary::-webkit-details-marker { display: none; }

/* The all-time bits: the PIN beside its explanation (so nobody has to guess
   whether it is required), and the record that PIN unlocks. */
.join-pin-row { display: flex; align-items: center; gap: 12px; }
.join-input-pin {
  flex: 0 0 5.2em; width: 5.2em; text-align: center; letter-spacing: 0.3em;
}
.join-pin-note {
  margin: 0; flex: 1; font-size: 13px; font-weight: 600; color: var(--muted);
  line-height: 1.35;
}
.join-pin-note b { color: var(--text); }
.join-team-wrap { display: flex; flex-direction: column; gap: 8px; }
.join-note { margin: 0; font-size: 14px; font-weight: 700; color: var(--accent); }
.join-record { margin: 0; font-size: 14px; font-weight: 800; color: var(--gold); }

/* ------------------------------------------------------- all-time sheet --- */
/* Over the top of whatever is on screen, because a player wants their lifetime
   total between questions as much as at the end of the night. */

.sheet {
  position: fixed; inset: 0; z-index: 40; padding: 18px;
  background: rgba(8, 6, 18, 0.82);
  display: flex; align-items: center; justify-content: center;
}
.sheet-card {
  width: min(560px, 100%); max-height: 100%; overflow-y: auto;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 2px solid var(--line-strong); border-radius: var(--r-lg); padding: 18px;
}
.sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.sheet-title { font-family: var(--font-display); font-size: 26px; font-weight: 900; margin: 0; }
.sheet-card .leaderboard { margin-top: 14px; }

/* --------------------------------------------------------------- chat --- */
/* The bubble sits left of the connection dot on every screen; the header and
   the floating face make room for it while it is showing. */
.p-chat-btn {
  position: fixed; top: 6px; right: 50px; z-index: 61;
  width: 34px; height: 34px; padding: 0; display: grid; place-items: center;
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: 50%; cursor: pointer;
}
.p-chat-btn:active { transform: scale(0.94); }
.p-chat-badge {
  position: absolute; top: -5px; right: -5px; min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: 9px; background: var(--gold-fill); color: var(--on-gold);
  font-size: 11px; font-weight: 800; line-height: 18px; text-align: center;
}
body.chat-on .p-bar { padding-right: 92px; }
body.chat-on .p-chip-phone { right: 94px; }
body.chat-on.phone-mode .p-clock-line { padding-right: 120px; }

#chat-sheet { z-index: 62; background: rgba(5, 2, 12, 0.45); }
.chat-card {
  display: flex; flex-direction: column; gap: 0;
  width: min(560px, 100%); height: 56vh; padding: 12px 0 0;
  border-bottom: 0; border-radius: var(--r-lg) var(--r-lg) 0 0; overflow: hidden;
}
.chat-tabs { display: flex; gap: 6px; padding: 8px 14px; align-items: center; }
.chat-tab {
  flex: 1; padding: 9px 0; border-radius: 999px; text-align: center;
  font: inherit; font-weight: 800; font-size: 14px; cursor: pointer;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--line);
}
.chat-tab.is-on { background: var(--brand); color: var(--on-brand); border-color: transparent; }
.chat-tab.is-closed { opacity: 0.45; }
.chat-x {
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  background: var(--surface-2); color: var(--muted); border: none; font-size: 16px; cursor: pointer;
}
.chat-hint { margin: 0 14px 6px; font-size: 12px; color: var(--muted); text-align: center; min-height: 15px; }
.chat-log {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: 4px 14px; display: flex; flex-direction: column; gap: 8px;
}
.chat-log > :first-child { margin-top: auto; }
.chat-empty { color: var(--muted); font-size: 14px; text-align: center; padding: 20px 0; }
.chat-msg {
  max-width: 82%; padding: 8px 12px; border-radius: 16px; background: var(--surface-2);
  font-size: 15px; line-height: 1.3; overflow-wrap: anywhere;
}
.chat-msg-from { display: block; font-size: 11px; font-weight: 800; color: var(--muted); margin-bottom: 2px; }
.chat-msg.is-room .chat-msg-from { color: var(--gold); }
.chat-msg.is-mine { align-self: flex-end; background: var(--brand-deep); border-bottom-right-radius: 4px; }
.chat-msg.is-mine .chat-msg-from { color: #d8c9ff; }
.chat-form {
  display: flex; gap: 8px; padding: 10px 14px max(14px, env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
}
.chat-form input {
  flex: 1; min-width: 0; border-radius: 999px; background: var(--bg); color: var(--text);
  border: 1px solid var(--line); padding: 11px 14px; font: inherit; font-size: 15px;
}
.chat-form input:disabled { opacity: 0.5; }
.chat-send {
  width: 44px; height: 44px; border-radius: 50%; border: none; cursor: pointer;
  background: var(--brand); color: var(--on-brand); font-size: 18px; display: grid; place-items: center;
}
.chat-send:disabled { opacity: 0.35; }
@media (min-width: 700px) {
  .chat-card { height: min(70vh, 640px); border-bottom: 2px solid var(--line-strong); border-radius: var(--r-lg); }
}

/* ------------------------------------------------------------ profile --- */
/* The face in the corner and the card behind it. */

.p-chip {
  /* Last thing on the bar, beside the connection dot; sized to the bar. */
  flex: 0 0 auto; display: grid; place-items: center;
  width: 32px; height: 32px; padding: 0;
  background: none; border: none; border-radius: 50%; cursor: pointer;
}
.p-chip .av-c { --av: 30px; }
/* Only when the header that carries the chip is gone (big-buttons mode): the
   face floats where the header chip would be, left of the dot and clear of
   the host's tap corner (46px), over every screen including a hold. */
.p-chip-phone { display: none; position: fixed; top: 6px; right: 50px; z-index: 61; }
body.phone-mode .p-chip-phone { display: grid; }
/* Room on the clock line for the floating face. */
body.phone-mode .p-clock-line { padding-right: 76px; }
/* Above the paused veil: a hold is exactly when a player has time to fix
   their name or face. */
#profile-sheet { z-index: 62; }

.profile-card { display: flex; flex-direction: column; gap: 12px; }
/* The one-time "what should we call you?" in Live: name and face only. */
.is-live-ask .sheet-title { font-size: 22px; }
.is-live-ask #profile-guest, .is-live-ask #profile-stats, .is-live-ask #profile-signout { display: none; }
.profile-id { display: flex; align-items: center; gap: 12px; }
.profile-face .av-c { --av: 54px; }
.profile-id-text { min-width: 0; }
.profile-name {
  font-family: var(--font-display); font-size: 22px; font-weight: 900; line-height: 1.1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.profile-sub { font-size: 13px; font-weight: 700; color: var(--muted); margin-top: 2px; }

.profile-guest { display: flex; flex-direction: column; gap: 10px; }
.profile-guest-line { margin: 0; font-size: 14px; font-weight: 600; color: var(--muted); line-height: 1.4; }
.profile-pin-row { display: flex; gap: 10px; }
.profile-pin-row .join-input-pin { flex: 0 0 5.2em; }
.profile-pin-row .btn { flex: 1; }

.profile-look { align-self: flex-start; font-size: 15px; padding: 11px 16px; }
.profile-edit { display: flex; flex-direction: column; gap: 8px; }
.profile-label { margin: 6px 0 0; }
.profile-save { font-size: 17px; padding: 13px 16px; margin-top: 4px; }
.profile-note { margin: 0; font-size: 14px; font-weight: 700; color: var(--correct); }
.profile-note.is-error { color: var(--incorrect); }
.profile-signout { align-self: flex-start; margin-top: 6px; color: var(--muted); }

/* The wheel, full screen and upright: it snaps to whichever face is in the
   middle. The middle one is the big one; the ones above and below are
   smaller and dimmed, so the eye knows which is the choice without a frame
   around it. Above the profile sheet and the paused veil, since both can
   open it. */
.av-overlay {
  position: fixed; inset: 0; z-index: 63; display: flex; flex-direction: column;
  background: var(--bg);
}
.av-overlay-card {
  flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 10px;
  width: min(560px, 100%); margin: 0 auto; padding: 16px 18px calc(14px + env(safe-area-inset-bottom));
}
.av-overlay-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex: 0 0 auto; padding-right: 34px; /* clear of the host tap corner */ }
.av-overlay-sub { margin: 2px 0 0; font-size: 13px; font-weight: 700; color: var(--muted); }
.av-close {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
  background: var(--surface-2); color: var(--text); border: 1px solid var(--line-strong);
  font-size: 24px; line-height: 1; font-family: inherit; display: grid; place-items: center;
}
.av-overlay .av-groups { margin: 0 auto; max-width: 100%; box-sizing: border-box; }
.av-overlay .av-group-btn { font-size: 14px; padding: 8px 12px; white-space: nowrap; flex: 0 1 auto; min-width: 0; }
@media (max-width: 379px) {
  .av-overlay .av-group-btn { font-size: 13px; padding: 8px 9px; }
}
.av-vwheel {
  --wheel-item: 150px; --wheel-face: 96px;
  position: relative; flex: 1; min-height: 0;
  display: flex; flex-direction: column; align-items: center;
  overflow-y: auto; overflow-x: hidden; scroll-snap-type: y mandatory;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
  padding: 0; /* the script pads it to half its own height, once it knows that */
  margin: 0 -18px;
  mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}
.av-vwheel::-webkit-scrollbar { display: none; }
.av-vwheel .av-wheel-item {
  flex: 0 0 var(--wheel-item); width: 100%; display: grid; place-items: center;
  scroll-snap-align: center; background: none; border: none; padding: 0; cursor: pointer;
}
.av-vwheel .av-wheel-item .av-c {
  --av: var(--wheel-face); opacity: 0.3;
  transition: transform 160ms ease, opacity 160ms ease;
}
.av-vwheel .av-wheel-item.is-near .av-c { opacity: 0.55; transform: scale(1.15); }
.av-vwheel .av-wheel-item.is-current .av-c {
  transform: scale(2.2); opacity: 1; position: relative; z-index: 1;
  box-shadow: 0 0 0 3px var(--brand-bright), 0 0 40px var(--brand-glow);
}
@media (max-height: 700px) {
  .av-vwheel { --wheel-item: 120px; --wheel-face: 80px; }
  .av-vwheel .av-wheel-item.is-current .av-c { transform: scale(2); }
}
.av-counter {
  margin: 0; text-align: center; font-size: 13px; font-weight: 800; color: var(--muted);
  font-variant-numeric: tabular-nums; flex: 0 0 auto;
}
.av-colors-title {
  margin: 0; font-size: 12px; font-weight: 900; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.12em; flex: 0 0 auto;
}
.av-swatches-big { gap: 6px; padding: 0; }
.av-swatches-big .av-swatch { width: 30px; height: 30px; }
.av-use { font-size: 19px; padding: 16px 18px; flex: 0 0 auto; margin-top: 2px; }

.av-groups {
  display: flex; gap: 4px; padding: 4px; margin: 0 auto 6px; width: fit-content;
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: 999px;
}
.av-groups:empty { display: none; }
.av-group-btn {
  background: none; color: var(--muted); border: none; border-radius: 999px;
  font-family: inherit; font-size: 13px; font-weight: 800; padding: 6px 14px;
  transition: background var(--t-fast) ease, color var(--t-fast) ease;
}
.av-group-btn.is-selected { background: var(--brand); color: #fff; box-shadow: 0 0 12px var(--brand-glow); }
.av-swatches { display: flex; justify-content: center; gap: 5px; flex-wrap: wrap; padding: 4px 0 0; }
.av-swatch {
  width: 26px; height: 26px; border-radius: 50%; padding: 0; cursor: pointer;
  background: var(--sw); border: 3px solid transparent;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4), inset 0 0 0 1px rgba(255, 255, 255, 0.35);
  transition: transform 120ms ease, border-color 120ms ease;
}
.av-swatch.is-selected { border-color: var(--brand-bright); transform: scale(1.15); }

.profile-stats .p-stats-grid { margin-top: 4px; }

/* ------------------------------------------------------------- paused --- */
/* Over everything, because a device that keeps showing a question nobody is
   scoring is worse than one that admits the night has stopped. Above the
   sheets: a leaderboard opened before the hold must not sit on top of the
   reason the screen went quiet. */

.join-paused {
  margin: 10px 0 0; font-size: 15px; font-weight: 800; color: var(--gold);
}
.paused-veil {
  position: fixed; inset: 0; z-index: 60; padding: 20px;
  background: rgba(8, 6, 18, 0.94);
  display: flex; align-items: center; justify-content: center; text-align: center;
}
.paused-card { max-width: 460px; }
.paused-title {
  font-family: var(--font-display);
  font-size: clamp(34px, 9vw, 54px); font-weight: 900; letter-spacing: 0.01em;
  color: var(--gold);
}
.paused-note {
  margin: 12px 0 0; font-size: clamp(15px, 4vw, 19px); font-weight: 700;
  line-height: 1.4; color: var(--text);
}
.paused-left {
  margin: 14px 0 0; font-size: 15px; font-weight: 700; color: var(--muted);
}
/* The player's own face, so the hold is a chance to fix a name or a look. */
.paused-profile {
  display: inline-flex; align-items: center; gap: 10px; margin: 26px 0 0;
  padding: 8px 16px 8px 8px; cursor: pointer;
  background: rgba(255, 255, 255, 0.06); border: 1px solid var(--line-strong);
  border-radius: 999px; color: var(--text); font-size: 15px; font-weight: 800;
}
.paused-profile .av-c { --av: 36px; }

.join-details { color: var(--muted); font-size: 14px; }
.join-details summary { cursor: pointer; font-weight: 700; list-style: none; }
.join-details summary::-webkit-details-marker { display: none; }
.join-pin-fold { margin: 4px 0 10px; }
.join-pin-fold[open] > summary { margin-bottom: 8px; }
.join-label { display: block; margin: 12px 0 8px; font-size: 13px; }
.join-row { display: flex; gap: 10px; align-items: center; }

.lobby-teammates { margin-top: 8px; color: var(--muted); font-size: 15px; font-weight: 600; }

/* --------------------------------------------------------------- lobby --- */
/* The wait, which for most players is their first look at the product: the mark
   said at a size that means something, then something worth reading rather than
   a screen with one line of grey text on it. */

.p-lobby-hero {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  flex: 0 0 auto; margin: 4px 0 14px; text-align: center;
}
.p-lobby-mark { width: 84px; height: 84px; filter: drop-shadow(0 0 26px var(--brand-glow)); }
.p-lobby-word {
  font-family: var(--font-display); font-size: 40px; font-weight: 900; line-height: 1;
  letter-spacing: -0.01em;
}
/* Same two-tone wordmark as the header and the TV, which is the whole point of
   saying the name this big. */
.p-lobby-word .brand-name-second { color: var(--brand-bright); }
.p-lobby-sub {
  font-size: 12px; font-weight: 800; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.34em;
}
/* A landscape tablet: name on the left, how you're playing on the right, and
   Play across the bottom, so the form is one screen there too. */
@media (min-width: 900px) and (max-height: 900px) {
  #join-screen #join-new-block, #join-screen #join-step-how {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px 16px; align-content: start;
  }
  #join-screen .join-avatar-card, #join-screen .join-current, #join-screen #join-team-block,
  #join-screen #join-existing-wrap {
    grid-column: 1 / -1;
  }
  #join-screen .join-how { display: contents; }
}

.p-welcome {
  flex: 0 0 auto; text-align: center; margin-bottom: 10px;
  background: linear-gradient(180deg, rgba(168, 85, 247, 0.18), rgba(124, 58, 237, 0.05));
  border: 1px solid var(--line-strong); border-radius: var(--r-md); padding: 12px 16px;
}
.p-welcome-line { font-family: var(--font-display); font-size: 22px; font-weight: 900; }
.p-welcome-sub { margin-top: 2px; font-size: 14px; font-weight: 700; color: var(--gold); }
/* The offer to keep tonight's points, taken where the player is standing rather
   than as advice about their next visit. */
.p-welcome-claim { margin-top: 10px; font-size: 16px; padding: 12px 18px; }
.p-welcome-pin {
  margin-top: 10px; display: flex; gap: 8px; align-items: center; justify-content: center;
  flex-wrap: wrap;
}
.p-welcome-pin .join-input-pin { font-size: 18px; padding: 12px 14px; }
.p-welcome-pin-note {
  margin: 8px 0 0; font-size: 13px; font-weight: 700; color: var(--accent); line-height: 1.35;
}
.p-welcome-pin-note.is-error { color: var(--incorrect); }
.p-lobby-status { text-align: center; font-size: 15px; font-weight: 700; }
.lobby-teammates { text-align: center; }

.p-next-up {
  flex: 0 0 auto; display: flex; align-items: center; justify-content: center; gap: 10px;
  margin-top: 12px; padding: 10px 14px; border-radius: var(--r-pill);
  background: rgba(34, 211, 238, 0.1); border: 1px solid rgba(34, 211, 238, 0.35);
}
.p-next-label {
  font-size: 11px; font-weight: 900; color: var(--accent);
  text-transform: uppercase; letter-spacing: 0.16em;
}
.p-next-detail { font-size: 15px; font-weight: 800; }

/* Two tabs, not a menu: what we play, and how I've done. */
.p-tabs { flex: 0 0 auto; display: flex; gap: 8px; margin: 16px 0 12px; }
.p-tab {
  flex: 1; background: var(--surface); color: var(--muted);
  border: 2px solid var(--line); border-radius: var(--r-pill);
  font-family: inherit; font-size: 15px; font-weight: 800; padding: 12px 14px;
  transition: color var(--t-fast) ease, border-color var(--t-fast) ease,
    background var(--t-fast) ease;
}
.p-tab.is-selected {
  color: var(--text); border-color: var(--brand-bright);
  background: linear-gradient(180deg, rgba(168, 85, 247, 0.24), rgba(124, 58, 237, 0.08));
}

/* Its content's height, never less: squeezed to a share of the leftover space
   the card's copy spilled out of the panel and printed itself over the buttons
   below -- on a tablet as well as a phone, which is how it looked on the APK. */
.p-learn { flex: 0 1 auto; min-height: max-content; display: flex; flex-direction: column; }
/* max-content, not 0: on a short screen (a phone on its side) the row must keep
   its card's own height and let the screen scroll, rather than being squeezed
   until the copy spills over the buttons below it. */
.p-learn-row {
  display: flex; align-items: stretch; gap: 8px; flex: 1 1 auto; min-height: max-content;
}
.p-learn-nav {
  flex: 0 0 auto; width: 46px; background: var(--surface); color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--r-md);
  font-family: inherit; font-size: 26px; font-weight: 900; line-height: 1;
}
.p-learn-nav:active { color: var(--text); border-color: var(--brand-bright); }
.p-learn-card {
  flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: center;
  /* Centred rather than stacked at the top: one card's worth of copy in a tall
     space otherwise sits in the corner of an empty panel. */
  justify-content: center; gap: 10px; text-align: center; padding: 18px 16px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line-strong); border-radius: var(--r-lg);
}
.p-learn-card.is-swapping { animation: p-learn-in var(--t-med) ease both; }
.p-learn-art { display: flex; align-items: center; justify-content: center; }
.p-learn-icon { width: 72px; height: 72px; }
img.p-learn-icon { filter: drop-shadow(0 8px 18px rgba(0, 0, 0, 0.6)); }
.p-learn-title { font-family: var(--font-display); font-size: 26px; font-weight: 900; }
.p-learn-blurb { font-size: 15px; font-weight: 600; color: var(--muted); line-height: 1.4; }
.p-learn-meta { font-size: 12px; font-weight: 800; color: var(--accent); letter-spacing: 0.06em; }
.p-learn-dots {
  flex: 0 0 auto; display: flex; justify-content: center; flex-wrap: wrap; gap: 6px; margin-top: 10px;
}
.p-learn-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--line-strong); }
.p-learn-dot.is-on { background: var(--brand-bright); }

@keyframes p-learn-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* Your record: a few big numbers a player can read at a glance, then the two
   categories they'll actually talk about. */
.p-stats { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.p-stats-rank {
  text-align: center; font-size: 14px; font-weight: 800; color: var(--gold); margin-bottom: 12px;
}
.p-stats-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.p-stat {
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 12px 8px; text-align: center;
}
.p-stat-value {
  font-family: var(--font-display); font-size: 24px; font-weight: 900;
  font-variant-numeric: tabular-nums; color: var(--brand-bright);
}
.p-stat-label {
  margin-top: 2px; font-size: 11px; font-weight: 800; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.08em; line-height: 1.25;
}
.p-stats-head {
  margin: 18px 0 8px; font-size: 12px; font-weight: 900; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.14em;
}
.p-cat-row {
  display: flex; align-items: center; gap: 12px; padding: 12px 14px; margin-bottom: 8px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-md);
}
.p-cat-icon { width: 34px; height: 34px; flex: 0 0 auto; }
.p-cat-text { flex: 1; min-width: 0; }
.p-cat-name { font-size: 16px; font-weight: 800; }
.p-cat-meta { font-size: 12px; font-weight: 700; color: var(--muted); }
.p-cat-pct {
  font-family: var(--font-display); font-size: 22px; font-weight: 900;
  font-variant-numeric: tabular-nums;
}
.p-stats-note { font-size: 14px; font-weight: 600; color: var(--muted); line-height: 1.45; }

.p-lobby-actions {
  flex: 0 0 auto; display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px;
  /* The row the carousel must not be allowed to reach: a background of its own
     so that if anything above ever does overflow, the buttons stay legible. */
  position: relative; padding-top: 4px; background: var(--bg);
}
.p-lobby-actions .join-change { margin-top: 0; }
.p-ended-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 18px; }
.p-ended-actions .join-change { margin-top: 0; }

/* A phone on its side, or a tablet with the keyboard up: the brand is the first
   thing that can afford to give up room, not the thing being read. */
@media (max-height: 620px) {
  .p-lobby-hero { flex-direction: row; justify-content: center; gap: 10px; margin: 0 0 8px; }
  .p-lobby-mark { width: 40px; height: 40px; }
  .p-lobby-word { font-size: 26px; }
  .p-lobby-sub { display: none; }
  .p-welcome-line { font-size: 18px; }
  .p-tabs { margin: 10px 0 8px; }
  .p-learn-icon { width: 48px; height: 48px; }
  .p-learn-card { padding: 14px; }
  .p-lobby-actions { margin-top: 12px; }
  /* Natural height and let the screen scroll: stretching the carousel to fill a
     short screen leaves it shorter than its own copy. */
  .p-learn { flex: 0 0 auto; }
  .p-learn-row { min-height: 190px; }
}

/* A tablet held the way tablets are actually held: who you are down the left,
   what we play down the right, and nothing to scroll for. */
/* 900px of width and 900px of height covers what tablets actually are held at
   -- 1280x800 and 1280x720 sat just outside the old 760px ceiling, so on the
   commonest Android tablet of all the single column ran past the bottom of the
   screen and put the carousel over the buttons underneath it. */
@media (min-width: 900px) and (max-height: 900px) {
  #lobby {
    display: grid; align-content: start; column-gap: 20px;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  }
  #lobby > .p-lobby-hero { grid-area: 1 / 1; flex-direction: column; }
  #lobby > .p-lobby-hero .p-lobby-mark { width: 72px; height: 72px; }
  #lobby > .p-lobby-hero .p-lobby-word { font-size: 36px; }
  #lobby > .p-lobby-hero .p-lobby-sub { display: block; }
  #lobby-welcome { grid-area: 2 / 1; }
  #team-status { grid-area: 3 / 1; }
  #lobby-teammates { grid-area: 4 / 1; }
  #lobby-next-up { grid-area: 5 / 1; }
  #lobby > .p-lobby-actions { grid-area: 6 / 1; align-self: end; margin-top: 20px; }
  #lobby > .p-tabs { grid-area: 1 / 2; align-self: start; margin: 0 0 12px; }
  /* Three actions on one line, so the last one isn't below the fold on the very
     screen a player is looking for it on. */
  #lobby > .p-lobby-actions .btn { font-size: 14px; padding: 11px 16px; }
  #lobby-learn, #lobby-stats { grid-area: 2 / 2 / 7 / 3; }
  #lobby-learn { flex: 1 1 auto; }
  .p-learn-row { min-height: 0; }
}

/* The shortest tablet of the lot (1024x600): the two columns fit, but the brand
   stacked above them pushed the last action button off the bottom. The lockup
   lies down and gives the room back. */
@media (min-width: 900px) and (max-height: 660px) {
  #lobby > .p-lobby-hero { flex-direction: row; justify-content: center; gap: 10px; }
  #lobby > .p-lobby-hero .p-lobby-mark { width: 44px; height: 44px; }
  #lobby > .p-lobby-hero .p-lobby-word { font-size: 28px; }
  #lobby > .p-lobby-hero .p-lobby-sub { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .p-learn-card.is-swapping { animation: none; }
}

/* ------------------------------------------------------------ question --- */

/* The clock: two numbers on one line, a hairline under them, and the pin. Where
   the category badge and the round badge used to be. */
.p-clock { flex: 0 0 auto; margin-bottom: 12px; }
.p-clock-line {
  display: flex; align-items: center; justify-content: flex-end; gap: 12px;
  margin-bottom: 6px; min-height: 28px;
}
/* The score sits at the far left of the line; the seconds and the worth stay
   together on the right, where they were. */
.p-score-badge { margin-right: auto; }
.p-timer-count {
  font-family: var(--font-display); font-size: 20px; font-weight: 900;
  font-variant-numeric: tabular-nums; color: var(--muted);
}
.p-timer-count.urgent { color: var(--incorrect); }
/* What a tap banks right now: the only reason to hurry, so it is the biggest
   thing on the line and it never moves. */
.p-worth-now {
  font-family: var(--font-display); font-size: 22px; font-weight: 900;
  font-variant-numeric: tabular-nums; color: var(--gold);
}

/* The pin rides on the bar, centred on it, at the percentage the fill had
   reached when the tap landed (set by player.js). On the bar rather than under
   it because below is where the first answer starts, and the label was landing
   behind it. */
.p-clock-bar { position: relative; }
.p-pick-pin {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  display: flex; align-items: center;
  pointer-events: none; z-index: 2;
}
/* A tap in the first or last moments of the clock puts the pin near an edge,
   where a centred label hangs off the screen and loses a digit, so it tucks
   inside the bar instead. */
.p-pick-pin.at-end { transform: translate(-100%, -50%); }
.p-pick-pin.at-start { transform: translate(0, -50%); }
.p-pick-pin-label {
  font-family: var(--font-display); font-size: 13px; font-weight: 900;
  font-variant-numeric: tabular-nums; color: #fff; white-space: nowrap;
  background: var(--brand); border: 1px solid var(--brand-bright);
  border-radius: var(--r-pill); padding: 1px 8px;
  box-shadow: 0 0 0 2px var(--bg);
}
/* Tapped later than last time, for less: the number says so without a sentence
   about it. */
.p-pick-pin.is-down .p-pick-pin-label {
  background: var(--incorrect); border-color: var(--incorrect);
}

.timer-bar-track {
  height: 8px; background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-pill); overflow: hidden;
}
.timer-bar-fill {
  height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--brand), var(--brand-bright));
  transition: width 0.12s linear;
}
.timer-bar-fill.urgent { background: linear-gradient(90deg, #b91c5c, var(--incorrect)); }

/* While the clock runs, the question and its four answers own the whole
   screen — no scrolling, no dead space under the last option. */
#quiz-screen { display: flex; flex-direction: column; }
/* The gap over the question is deliberate: the score badge and the worth are
   numbers, the question is prose, and they were close enough to read as one
   block. */
.p-question { font-size: clamp(20px, 3.4vh, 34px); line-height: 1.22; font-weight: 800; margin: 14px 0 12px; }
/* What the question is about, in the same gold small-caps the TV uses for it. A
   question naming a year or a surname is a riddle until you know the subject,
   and the player who is looking down needs that as much as the room does. */
.p-category {
  justify-self: center; align-self: center; margin: 12px auto 0;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 14px; border-radius: 999px;
  background: rgba(59, 7, 100, 0.55); border: 1px solid rgba(168, 85, 247, 0.55);
  box-shadow: 0 0 18px rgba(168, 85, 247, 0.25);
  font-family: var(--font-display);
  font-size: clamp(11px, 1.6vh, 14px); font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.16em; color: #fcd68a;
}
.p-category:empty { display: none; }
.p-category::before { content: "★"; color: var(--gold); font-size: 0.9em; }
.p-category + .p-question { margin-top: 10px; }
/* At reveal the fact is the headline and the question is already a two-line
   summary; a label over it is noise. */
#quiz-screen.revealing .p-category { display: none; }

/* One answer per row, each the same height, together filling everything left
   over. A single column means the thumb travels straight down to change an
   answer instead of diagonally across a grid, and it matches the TV row for
   row so "the third one" means the same thing on both. */
.answers-grid {
  display: grid;
  grid-template-columns: 1fr;
  grid-auto-rows: 1fr;
  gap: clamp(8px, 1.4vh, 16px);
  flex: 1 1 auto;
  min-height: 0;
}
/* Every row carries its own colour for the whole question and through the
   reveal, the same as the TV's cards: A violet, B cyan, C pink, D gold. Picked,
   right and wrong are layers on top of that identity, never a recolour. */
.answer-btn[data-choice="A"], .p-fact-answer[data-choice="A"] { --c: var(--choice-a); --c-rgb: 139, 92, 246; --on-c: #150a2b; }
.answer-btn[data-choice="B"], .p-fact-answer[data-choice="B"] { --c: var(--choice-b); --c-rgb: 34, 211, 238; --on-c: #04252b; }
.answer-btn[data-choice="C"], .p-fact-answer[data-choice="C"] { --c: var(--choice-c); --c-rgb: 244, 114, 182; --on-c: #2b0a1a; }
.answer-btn[data-choice="D"], .p-fact-answer[data-choice="D"] { --c: var(--choice-d); --c-rgb: 245, 179, 60; --on-c: #2b1a04; }
.answer-btn {
  --c: var(--brand); --c-rgb: 124, 58, 237; --on-c: #fff;
  position: relative; overflow: hidden;
  background: linear-gradient(158deg, rgba(var(--c-rgb), 0.16), #100a1e 60%);
  color: var(--text); border: 2px solid rgba(var(--c-rgb), 0.4); border-radius: var(--r-lg);
  font-size: clamp(17px, 2.6vh, 28px); font-weight: 700; padding: 0 16px;
  min-height: 62px;
  display: flex; align-items: center; gap: 14px; text-align: left;
  font-family: inherit;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
  transition: opacity var(--t-slow) var(--ease-out), border-color var(--t-fast) ease,
    background var(--t-base) ease, transform var(--t-fast) var(--ease-out),
    box-shadow var(--t-base) ease;
}
/* How much of the room went with this answer, behind the row it belongs to. A
   number in the corner made the player do arithmetic to find the popular wrong
   one; a bar is read without reading. Width is set at reveal only. */
.answer-share {
  position: absolute; left: 0; bottom: 0; height: 4px; width: 0;
  background: linear-gradient(90deg, rgba(var(--c-rgb), 0.7), rgba(var(--c-rgb), 0.3));
  transition: width 520ms var(--ease-out);
  pointer-events: none;
}
#quiz-screen:not(.revealing) .answer-share { width: 0 !important; }
.answer-btn.correct-final .answer-share { background: linear-gradient(90deg, var(--c), rgba(var(--c-rgb), 0.6)); }
.answer-btn.selected:not(.correct-final) .answer-share { background: rgba(244, 63, 94, 0.55); }
/* "Which one did I tap?" -- the question this screen never answered. */
.answer-tick {
  flex: 0 0 auto; display: none;
  font-size: clamp(18px, 2.4vh, 24px); font-weight: 900; color: var(--brand-bright);
}
.answer-btn.selected .answer-tick { display: block; }
.answer-btn.selected.correct-final .answer-tick { color: var(--c); }
.answer-btn.selected.eliminated-pick .answer-tick,
#quiz-screen.revealing .answer-btn.selected:not(.correct-final) .answer-tick {
  color: var(--incorrect);
}
/* While the clock runs the tick is a badge on the card you touched: "Locked in"
   or "Changed to D", and the points once the server has said. At reveal the
   card goes back to the plain tick; the badge would be a second score. */
.answer-badge { display: none; }
#quiz-screen:not(.revealing) .answer-btn.selected .answer-tick { display: none; }
#quiz-screen:not(.revealing) .answer-btn.selected .answer-badge:not(:empty) {
  display: inline-block; flex: 0 0 auto;
  background: var(--brand-bright); color: #fff;
  font: 900 clamp(13px, 1.8vh, 15px)/1 var(--font-display);
  letter-spacing: 0.02em; padding: 9px 14px; border-radius: 999px;
  box-shadow: 0 4px 16px var(--brand-glow);
}
.answer-badge.is-flash { animation: answer-badge-flash 420ms var(--ease-out) both; }
@keyframes answer-badge-flash {
  0% { transform: scale(0.6); opacity: 0; }
  55% { transform: scale(1.1); opacity: 1; }
  100% { transform: scale(1); }
}
/* A pick the hint ruled out: "CHANGE IT" is the whole message, and the
   locked-in badge beside it squeezed the answer off a phone. */
#quiz-screen:not(.revealing) .answer-btn.selected.eliminated-pick .answer-badge:not(:empty) { display: none; }
/* The card you left, for two seconds: dim, and honest about what it was. */
.answer-btn.was-pick { opacity: 0.55; }
.answer-btn.was-pick::after {
  content: "was your pick"; flex: 0 0 auto;
  color: var(--muted); font: 700 clamp(12px, 1.6vh, 14px)/1 var(--font-display);
  border: 1px solid rgba(255, 255, 255, 0.25); padding: 8px 12px; border-radius: 999px;
}
body.phone-mode .answer-badge,
body.phone-mode .answer-btn.was-pick::after { position: absolute; bottom: 12px; left: 14px; }
/* At reveal the answers give a little space back to the tidbit, but they stay
   full size and all four stay on screen: which one was right, which one you
   tapped and how the room split is the whole point of this beat. */
#quiz-screen.revealing .answers-grid { flex: 0 1 auto; grid-auto-rows: minmax(52px, auto); gap: clamp(6px, 1vh, 12px); }
#quiz-screen.revealing .answer-btn { min-height: 52px; font-size: clamp(15px, 2.1vh, 22px); }
/* The clock stops but the line stays: the pin on it is where this player tapped
   and what it was worth, which is the one thing they'd otherwise have to take on
   trust. The question shrinks -- it's on the TV in letters a foot tall. */
#quiz-screen.revealing .p-clock-line { min-height: 0; }
#quiz-screen.revealing .p-timer-count,
#quiz-screen.revealing .p-worth-now { display: none; }
#quiz-screen.revealing .p-question {
  font-size: clamp(15px, 1.9vh, 20px); line-height: 1.3; color: var(--muted);
  margin: 0 0 10px;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
#quiz-screen.revealing .reveal-panel { margin-top: 12px; }
.answer-btn:active { transform: scale(0.98); }
/* The one row that lights up while the clock runs: its own colour, brighter. */
.answer-btn.selected {
  border-color: var(--c);
  background: linear-gradient(158deg, rgba(var(--c-rgb), 0.38), rgba(var(--c-rgb), 0.1) 70%);
  box-shadow: 0 0 0 1px rgba(var(--c-rgb), 0.6), 0 0 26px rgba(var(--c-rgb), 0.45);
}
/* Your wrong answer at reveal: red, and still obviously the one you tapped. */
#quiz-screen.revealing .answer-btn.selected:not(.correct-final) {
  opacity: 1; filter: none;
  border-color: var(--incorrect);
  background: linear-gradient(180deg, rgba(244, 63, 94, 0.2), rgba(244, 63, 94, 0.06));
  box-shadow: none;
}
#quiz-screen.revealing .answer-btn.selected:not(.correct-final) .answer-label {
  color: var(--text); text-decoration: none;
}
/* Progressive elimination (5s/8s) and the wrong answers at reveal. A dead
   answer has to be unmistakable at a glance mid-question: dimming alone read as
   "slightly greyer", so it also loses its colour, is struck through and carries
   an OUT stamp where the thumb was about to land. Not so dim it can't be read,
   though -- at reveal the wrong answers are still the ones the room is arguing
   about. */
.answer-btn.eliminated {
  opacity: 0.78;
  background: repeating-linear-gradient(
    -45deg,
    rgba(255, 255, 255, 0.03) 0 8px,
    rgba(0, 0, 0, 0.18) 8px 16px
  ), var(--bg);
  border-color: rgba(148, 163, 184, 0.3);
  filter: grayscale(1);
}
.answer-btn.eliminated .answer-label { text-decoration: line-through; color: var(--muted); }
.answer-btn.eliminated::after {
  content: "OUT";
  font-size: 11px; font-weight: 900; letter-spacing: 0.16em; color: var(--muted);
  border: 2px solid rgba(148, 163, 184, 0.45); border-radius: var(--r-pill);
  padding: 3px 8px;
}
/* The hint took away the answer this player had already tapped, which is the
   one elimination they have to act on. Their own button comes back out of the
   greyed-out pile in red -- not "wrong", but "change this". */
.answer-btn.eliminated.eliminated-pick {
  opacity: 1;
  filter: none;
  border-color: var(--incorrect);
  background: linear-gradient(180deg, rgba(244, 63, 94, 0.28), rgba(244, 63, 94, 0.1));
  box-shadow: 0 0 0 1px var(--incorrect), 0 0 22px rgba(244, 63, 94, 0.35);
  animation: pick-out-flash 1.6s var(--ease-out) 2;
}
.answer-btn.eliminated-pick .answer-label { color: var(--text); }
.answer-btn.eliminated-pick .answer-letter { background: var(--incorrect); color: #fff; box-shadow: none; }
.answer-btn.eliminated-pick::after {
  content: "CHANGE IT";
  color: var(--incorrect);
  border-color: var(--incorrect);
}
@keyframes pick-out-flash {
  0%, 100% { box-shadow: 0 0 0 1px var(--incorrect), 0 0 22px rgba(244, 63, 94, 0.35); }
  50% { box-shadow: 0 0 0 2px var(--incorrect), 0 0 34px rgba(244, 63, 94, 0.6); }
}

/* The right answer keeps its own colour and gets brighter: full border, a glow
   in that colour, the check in the corner. Nothing turns green. */
.answer-btn.correct-final {
  border-color: var(--c);
  background: linear-gradient(158deg, rgba(var(--c-rgb), 0.32), rgba(22, 16, 42, 0.98) 65%);
  box-shadow: 0 0 0 2px rgba(var(--c-rgb), 0.3), 0 0 28px rgba(var(--c-rgb), 0.5);
  opacity: 1; filter: none;
}
.answer-btn.correct-final .answer-label { color: #fff; text-decoration: none; }
.answer-btn::before {
  content: ""; position: absolute; top: 50%; right: 10px; margin-top: -12px;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--c) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12.5l4.2 4.2L19 7' fill='none' stroke='%23101010' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 62% no-repeat;
  box-shadow: 0 0 14px rgba(var(--c-rgb), 0.7);
  opacity: 0; transform: scale(0.6);
  transition: opacity var(--t-base) var(--ease-out), transform var(--t-base) var(--ease-out);
}
.answer-btn.correct-final::before { opacity: 1; transform: none; }
/* The check takes the corner the share number had; the stage that follows says
   how many got it. */
body:not(.phone-mode) #quiz-screen.revealing .answer-btn.correct-final .answer-pct { display: none; }
.answer-btn:disabled { cursor: default; }

/* The letter is how the host and the TV refer to a row, so it is the row's
   colour badge -- the same disc the TV draws -- and the answer is the target. */
.answer-letter {
  flex: 0 0 auto; font-weight: 900; font-size: 0.68em;
  width: 1.75em; height: 1.75em; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(var(--c-rgb), 0.22); color: var(--c);
  box-shadow: inset 0 0 0 2px rgba(var(--c-rgb), 0.55);
  transition: color var(--t-base) ease, background var(--t-base) ease, box-shadow var(--t-base) ease;
}
.answer-btn.selected .answer-letter,
.answer-btn.correct-final .answer-letter {
  background: var(--c); color: var(--on-c);
  box-shadow: 0 0 0 3px rgba(var(--c-rgb), 0.3), 0 0 16px rgba(var(--c-rgb), 0.6);
}
.answer-btn.eliminated:not(.eliminated-pick) .answer-letter {
  background: var(--surface-3); color: var(--muted);
  box-shadow: inset 0 0 0 2px rgba(148, 163, 184, 0.3);
}
.answer-label { flex: 1; position: relative; }

/* Clues are half of what a Buzztime player is working with, so each one gets a
   numbered card and the newest is the loud one — not a line of small print. */
.clue-banner { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; flex: 0 0 auto; }
.clue-card {
  display: flex; align-items: center; gap: 10px;
  background: linear-gradient(90deg, rgba(34, 211, 238, 0.16), rgba(34, 211, 238, 0.02));
  border: 1px solid rgba(34, 211, 238, 0.35); border-left: 6px solid var(--accent);
  border-radius: var(--r-sm); padding: 10px 12px;
  font-size: 17px; font-weight: 700; color: var(--text);
}
/* The clue that just landed is the most important thing on the screen after the
   four buttons -- it is the way in to the answer -- so it is sized like it,
   rather than like a caption under the question. */
.clue-card.clue-newest {
  font-size: clamp(21px, 3.4vh, 32px); line-height: 1.25;
  background: linear-gradient(90deg, rgba(34, 211, 238, 0.28), rgba(34, 211, 238, 0.05));
  box-shadow: 0 0 24px rgba(34, 211, 238, 0.22);
}
/* The clue that has already been read is context, not news: it keeps its words
   (a player who looks down late still needs them) and gives up the size, the
   glow and half its padding to the clue that just landed and to the four
   buttons underneath. */
.clue-card.clue-prev {
  font-size: clamp(15px, 2.2vh, 21px);
  font-weight: 600;
  padding: 6px 12px;
  color: var(--muted);
  background: rgba(34, 211, 238, 0.06);
  border-color: rgba(34, 211, 238, 0.18);
  border-left-width: 4px;
}
.clue-card.clue-prev .clue-tag {
  background: rgba(34, 211, 238, 0.3); color: var(--text);
  padding: 2px 6px; font-size: 10px;
}
.clue-tag {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  background: var(--accent); color: #04252b; border-radius: var(--r-pill);
  padding: 3px 8px; font-size: 11px; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.08em;
}
.clue-text { flex: 1; }

/* --------------------------------------------------------- how it works --- */
/* The same rules card the TV shows, so a player looking down at the tablet
   isn't the one person in the room who missed them. */

.p-briefing { gap: 10px; align-items: center; text-align: center; margin: auto; }
#p-briefing-crest { width: 84px; height: 84px; }
#p-briefing-crest .game-crest-icon { font-size: 50px; }
/* The pack's own artwork is a wordmark, so the square crest becomes a banner. */
#p-briefing-crest.is-logo { width: auto; max-width: 82%; }
.p-briefing .game-title { font-size: 28px; }
.p-briefing .rules-list { text-align: left; }
.p-briefing .rules-list li { font-size: 14px; }
.p-briefing-heading {
  font-family: var(--font-display); font-size: 14px; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--brand-bright);
  margin-top: 4px;
}

/* The room is waiting on everyone: one gold button that won't be missed, then
   a gold line saying you've tapped it and nobody's waiting on you. */
.p-ready {
  width: 100%; display: flex; flex-direction: column; align-items: center; gap: 10px;
  margin-top: 8px; position: sticky; bottom: 0; padding: 10px 0 max(6px, env(safe-area-inset-bottom));
  background: var(--bg); box-shadow: 0 -18px 18px var(--bg);
}
.p-ready-count {
  margin: 0; font-size: 13px; font-weight: 800; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.12em;
}
.p-ready-btn {
  width: 100%; max-width: 360px; min-height: 60px; font-size: 20px; font-weight: 900;
  font-family: var(--font-display); letter-spacing: 0.02em;
  background: linear-gradient(180deg, #ffd071, var(--gold)); color: #2a1a02;
  border: 2px solid #ffe2a3; border-radius: var(--r-pill);
  box-shadow: 0 0 0 0 rgba(245, 179, 60, 0.7);
  animation: p-ready-pulse 1.6s ease-out infinite;
}
.p-ready-btn:active { transform: scale(0.98); }
@keyframes p-ready-pulse {
  0% { box-shadow: 0 0 0 0 rgba(245, 179, 60, 0.75); transform: scale(1); }
  60% { box-shadow: 0 0 0 18px rgba(245, 179, 60, 0); transform: scale(1.03); }
  100% { box-shadow: 0 0 0 0 rgba(245, 179, 60, 0); transform: scale(1); }
}
.p-ready-done {
  margin: 0; font-size: 16px; font-weight: 900; color: var(--gold);
}
.p-ready-done::before { content: "\2713\00a0"; }
.p-sit-out {
  background: none; border: 0; padding: 6px 10px; color: var(--muted);
  font-size: 13px; font-weight: 700; text-decoration: underline; cursor: pointer;
}
.p-sitting-out { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.p-sitting-out p { margin: 0; font-size: 14px; font-weight: 700; color: var(--gold); }
.p-sit-back { min-height: 48px; font-size: 16px; font-weight: 900; border-radius: var(--r-pill); }

/* ------------------------------------------------------- between games --- */
/* A player who looks down mid-break should see the same clock the TV has, and
   be told in one line that nothing has been lost. */

.p-break { gap: 8px; align-items: center; text-align: center; margin: auto; }
.p-break-kicker {
  font-family: var(--font-display); font-size: 14px; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.18em; color: var(--brand-bright);
}
.p-break-clock {
  font-family: var(--font-display); font-weight: 900; font-size: 64px; line-height: 1;
  font-variant-numeric: tabular-nums; color: var(--gold);
}
.p-break-label {
  font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.16em;
  color: var(--muted);
}
.p-break-next { font-size: 20px; font-weight: 900; margin-top: 6px; }
.p-break-note { font-size: 14px; color: var(--muted); margin: 4px 0 0; max-width: 34ch; }
.p-break-standing { font-size: 15px; font-weight: 800; color: var(--accent); }
.p-break-today { margin-top: 4px; font-size: 14px; font-weight: 800; color: var(--muted); }
/* The venue's record on the game: the score to beat before it, the standing
   (or freshly broken) record after it. */
.p-record { margin: 4px 0 0; font-size: 14px; font-weight: 800; color: var(--muted); }
.p-record-label {
  text-transform: uppercase; letter-spacing: 0.14em; font-size: 11px; color: var(--brand-bright);
}
.p-record-score { color: var(--text); font-variant-numeric: tabular-nums; }
.p-record.is-new .p-record-label, .p-record.is-new .p-record-score { color: var(--gold); }
.p-break-fill, .p-break-you, .p-break-count { display: grid; gap: 12px; width: min(560px, 100%); justify-items: center; }
.p-break-count { gap: 8px; }
.p-break-in { animation: p-break-in 320ms cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes p-break-in {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
.p-break-fact-card {
  width: 100%; padding: 14px 16px; border-radius: var(--r-lg); text-align: left;
  border: 1px solid var(--brand-bright);
  background: linear-gradient(160deg, rgba(124, 58, 237, 0.28), var(--surface) 70%);
}
.p-break-fact-tag {
  font-size: 11px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--brand-bright); margin-bottom: 6px;
}
.p-break-fact { margin: 0; font-size: clamp(17px, 4.6vmin, 22px); font-weight: 700; line-height: 1.35; text-wrap: pretty; }
.p-break-board-wrap { width: 100%; display: grid; gap: 6px; }
.p-break-board-title {
  font-size: 12px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}
.p-break-board { display: grid; gap: 6px; max-height: 38vh; overflow-y: auto; overscroll-behavior: contain; }

/* The ballot for the next game. Anything Goes, then the categories, then the
   franchises; the game that just played is pinned on top, already selected. */
.p-break-vote { display: grid; gap: 10px; width: min(720px, 100%); text-align: left; }
.p-vote-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.p-vote-title { font-family: var(--font-display); font-weight: 900; font-size: 22px; line-height: 1.05; }
.p-vote-clock {
  font-family: var(--font-display); font-weight: 900; font-size: 22px; color: var(--gold);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.p-vote-clock.is-urgent { color: var(--danger, #ef4444); }
.p-vote-hint { margin: 0; font-size: 13px; color: var(--muted); }
/* The two small ways in and out of the ballot: "Change game" under the break
   card, "Back to the break" at the top of the ballot. Links, not buttons — the
   break is the screen, the ballot is the detour. */
.p-break-change, .p-vote-back {
  background: none; border: 0; padding: 6px 2px; margin: 0; font: inherit; font-size: 14px;
  font-weight: 900; color: var(--brand-bright); cursor: pointer; justify-self: start;
}
.p-break-change { margin-top: 6px; justify-self: center; }
.p-break-change:active, .p-vote-back:active { opacity: 0.7; }
.p-vote-search {
  width: 100%; box-sizing: border-box; min-height: 42px; padding: 0 14px; border-radius: var(--r-pill);
  border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--text); font: inherit; font-size: 15px;
}
.p-vote-shelf-wrap { position: relative; }
.p-vote-shelf {
  display: grid; gap: 8px; max-height: 46vh; overflow-y: auto; overscroll-behavior: contain;
  padding-right: 2px; padding-bottom: 44px;
}
/* The list runs on below the fold: fade the last cards out and say so, until
   the player has scrolled to the end. */
.p-vote-shelf-wrap::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 72px; pointer-events: none;
  background: linear-gradient(180deg, transparent, var(--bg, #0b0714) 85%); transition: opacity 0.2s;
}
.p-vote-more {
  position: absolute; z-index: 2; left: 50%; bottom: 10px; transform: translateX(-50%); pointer-events: none;
  padding: 8px 16px; border-radius: var(--r-pill); color: #1a1030;
  background: var(--gold-fill); box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45); font-size: 12px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  white-space: nowrap; animation: p-vote-bob 1.6s ease-in-out infinite; transition: opacity 0.2s;
}
@keyframes p-vote-bob { 0%, 100% { transform: translate(-50%, 0); } 50% { transform: translate(-50%, 4px); } }
.p-vote-shelf-wrap.is-end::after, .p-vote-shelf-wrap.is-end .p-vote-more { opacity: 0; }
@media (min-width: 700px) { .p-vote-shelf { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.p-vote-group {
  grid-column: 1 / -1; font-size: 11px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--muted); margin-top: 6px;
}
.p-vote-card {
  display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  min-height: 60px; padding: 8px 12px; border-radius: 16px; text-align: left; font: inherit; color: var(--text);
  border: 2px solid var(--line); background: var(--surface-2); cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.p-vote-card.is-selected { border-color: var(--gold); background: rgba(245, 179, 60, 0.14); }
.p-vote-card.is-voted { border-color: var(--brand-bright); }
.p-vote-card.is-voted.is-selected { border-color: var(--gold); }
.p-vote-card.is-last { border-style: dashed; }
.p-vote-card.is-last.is-selected { border-style: solid; }
.p-vote-art {
  width: 44px; height: 44px; border-radius: 10px; overflow: hidden; display: grid; place-items: center;
  background: var(--surface);
}
.p-vote-art img { width: 100%; height: 100%; object-fit: cover; }
.p-vote-art .lc-icon { width: 26px; height: 26px; }
.p-vote-card-text { display: grid; gap: 2px; min-width: 0; }
.p-vote-card-name { font-weight: 900; font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-vote-card-sub { font-size: 12px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-vote-card.is-last .p-vote-card-sub { color: var(--gold); font-weight: 800; }
.p-vote-mark { font-size: 18px; color: var(--gold); min-width: 1em; text-align: right; }
.p-vote-bar {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 12px;
  position: sticky; bottom: 0; padding-top: 6px;
  background: linear-gradient(180deg, transparent, var(--surface) 40%);
}
.p-vote-status { font-size: 14px; font-weight: 700; color: var(--muted); }
.p-vote-status.is-voted { color: var(--gold); }
.p-vote-btn {
  min-height: 52px; padding: 0 28px; border-radius: var(--r-pill); font-weight: 900; font-size: 17px;
  text-transform: uppercase; letter-spacing: 0.08em; background: var(--gold-fill); color: #1a1030; border: 0;
}
.p-vote-btn:disabled { opacity: 0.45; }
.p-vote-btn.is-sent { background: var(--surface-2); color: var(--gold); border: 2px solid var(--gold); }

.p-break-vote-result { display: grid; gap: 8px; width: min(560px, 100%); justify-items: center; }
.p-vote-result-art {
  width: 110px; height: 110px; border-radius: var(--r-lg); overflow: hidden; display: grid; place-items: center;
  background: var(--surface-2);
}
.p-vote-result-art img { width: 100%; height: 100%; object-fit: cover; }
.p-vote-result-art .lc-icon { width: 56px; height: 56px; }
.p-vote-result-title { font-family: var(--font-display); font-weight: 900; font-size: 30px; line-height: 1; }
.p-vote-result-who { display: flex; align-items: center; gap: 8px; color: var(--gold); font-weight: 800; font-size: 16px; }
.p-vote-result-who .av-group { --av: 30px; }
.p-vote-result-reason { margin: 0; font-size: 15px; font-weight: 700; line-height: 1.35; text-wrap: pretty; }
.p-vote-result-rows { width: 100%; display: grid; gap: 4px; text-align: left; }
.p-vote-result-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; font-size: 13px; color: var(--muted);
  border-bottom: 1px solid var(--line); padding: 3px 0;
}
.p-vote-result-row b { color: var(--text); }

/* --------------------------------------------------------- wager panel --- */
/* The stake picker sits above the answer grid, since the stake is chosen
   first and the grid is what the thumb lands on last. */

.wager-panel {
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line-strong); border-radius: var(--r-md);
  padding: 14px 16px; margin-bottom: 14px;
}
.wager-label { font-size: 15px; font-weight: 800; margin: 0 0 12px; }
.wager-values { display: flex; flex-wrap: wrap; gap: 10px; }
.wager-btn {
  background: var(--bg); color: var(--text); border: 2px solid var(--line);
  border-radius: var(--r-md); font-family: var(--font-display);
  font-size: 20px; font-weight: 900; min-width: 58px; padding: 12px 14px;
  transition: border-color var(--t-fast) ease, background var(--t-fast) ease, transform var(--t-fast) ease;
}
.wager-btn:active { transform: scale(0.96); }
.wager-btn.selected {
  border-color: var(--brand-bright); color: var(--brand-bright);
  background: rgba(168, 85, 247, 0.18); box-shadow: 0 0 20px var(--brand-glow);
}
.wager-btn.spent { opacity: 0.28; text-decoration: line-through; }
.wager-status { font-size: 13px; color: var(--muted); margin: 12px 0 0; font-weight: 600; }
.wager-status-set { color: var(--brand-bright); }
.wager-status-warn { color: var(--incorrect); }

/* Wager mode's halftime list question — no answer grid, just the prompt and,
   at reveal, the full list the host is scoring against. */
.list-panel {
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid var(--line); border-left: 5px solid var(--accent);
  border-radius: var(--r-sm); padding: 14px 16px; margin-bottom: 14px;
}
.list-instructions { margin: 0; font-size: 16px; font-weight: 700; }
.list-tiles {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 12px 0 0;
}
.list-tile {
  min-height: 58px; padding: 10px 12px; text-align: left;
  font-size: 16px; font-weight: 700; color: var(--text);
  background: var(--surface); border: 2px solid var(--line);
  border-radius: var(--r-sm);
}
.list-tile.is-picked {
  border-color: var(--brand-bright); background: rgba(168, 85, 247, 0.18);
  box-shadow: inset 0 0 0 1px var(--brand-bright);
}
/* At reveal a tile says one of three things: you got it, you guessed it wrong,
   or it belonged and you left it. */
.list-tile.tile-hit { border-color: var(--correct); background: rgba(34, 197, 94, 0.2); }
.list-tile.tile-miss {
  border-color: var(--incorrect); background: rgba(244, 63, 94, 0.18);
  text-decoration: line-through; color: var(--muted);
}
.list-tile.tile-unclaimed {
  border-color: var(--correct); border-style: dashed; color: var(--correct);
}
.list-status { margin: 10px 0 0; font-size: 14px; color: var(--muted); }
.list-status-set { color: var(--text); font-weight: 700; }

.hint { margin: 10px 0 0; text-align: center; color: var(--muted); font-size: 14px; flex: 0 0 auto; }

/* The only line of prose the gameplay screen has left, and it appears when
   something has gone wrong with a tap: it didn't reach the game, the game
   refused it, or a hint just killed it. Everything a tap does when it works is
   said by the pin on the clock line instead. */
.answer-worth {
  margin: 8px 0 0; text-align: center; flex: 0 0 auto;
  font-size: 15px; font-weight: 800; color: var(--gold);
  letter-spacing: 0.01em;
}
.answer-worth .answer-worth-note {
  display: block; margin-top: 2px;
  font-size: 13px; font-weight: 600; color: var(--muted); letter-spacing: 0;
}
.answer-worth.answer-worth-down { color: var(--incorrect); }

/* ------------------------------------------------------------ reactions --- */
/* Eight taps that go nowhere near the score: they land on the TV, so the row
   stays a thin strip under the answers rather than competing with them. */
.reactions {
  display: flex; justify-content: center; gap: 6px; flex-wrap: nowrap;
  margin: 10px 0 0; flex: 0 0 auto;
}
.reaction-btn {
  position: relative;
  flex: 0 1 auto; min-width: 0;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line); border-radius: 50%;
  width: 38px; height: 38px; padding: 0;
  font: inherit; font-size: 19px; line-height: 1; cursor: pointer;
  transition: transform var(--t-fast) var(--ease-out), background var(--t-fast) ease;
}
.reaction-btn:active { transform: scale(0.9); background: rgba(255, 255, 255, 0.1); }
/* The reaction's effect is across the room, so the tap needs its own receipt
   here: the emoji floats off the button it came from. */
.reaction-btn.is-sent::after {
  content: attr(data-emoji);
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 19px;
  animation: reaction-fly 700ms var(--ease-out) forwards;
}
.reaction-btn.is-sent { animation: reaction-pop 320ms var(--ease-out); }
@keyframes reaction-pop {
  0% { transform: scale(1); }
  40% { transform: scale(1.28); background: rgba(168, 85, 247, 0.22); }
  100% { transform: scale(1); }
}
@keyframes reaction-fly {
  0% { opacity: 0.9; transform: translateY(0) scale(1); }
  100% { opacity: 0; transform: translateY(-38px) scale(1.5); }
}

/* Connected is the normal state and doesn't need a word: it shrinks to a green
   dot in the corner, and only the states worth doing something about
   (connecting, reconnecting) spell themselves out as a pill. */
.status-pill.status-connected {
  top: 17px; right: 16px; /* centred on the 44px bar */
  width: 10px; height: 10px; min-width: 0; padding: 0;
  border-radius: 50%; overflow: hidden;
  text-indent: -999px; white-space: nowrap;
  background: var(--correct); color: transparent;
  box-shadow: 0 0 10px rgba(34, 197, 94, 0.5);
}

/* Reads as a verdict, not an error: the tablet is fine, the team is out. */
.out-msg {
  margin: 10px 0 0; text-align: center; flex: 0 0 auto;
  color: var(--incorrect); font-size: 15px; font-weight: 800;
}

/* -------------------------------------------------------------- reveal --- */

/* What's left of the reveal on a device: the tidbit, and the wait for the next
   question. The verdict is the rows themselves -- green where the answer was, red
   under the tick if that wasn't it -- and the points are their own beat. */
.reveal-panel { margin-top: 14px; flex: 0 0 auto; display: flex; flex-direction: column; }
.fun-fact-tag {
  display: block; margin-bottom: 6px;
  font-family: var(--font-display); font-size: 11px; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.22em; color: var(--gold);
  text-align: center;
}
/* The reveal's second beat, the stage the TV gives it at phone size. Once the
   rows have said right or wrong it takes their place: the answer in its own
   colour and the thing worth knowing about it, nothing else. The clock line
   (with this player's pin) stays above, the countdown and the foot below. */
.p-fact-stage {
  flex: 1 1 auto; min-height: 0;
  display: grid; place-items: center;
  padding: 14px 6px 10px;
  border-radius: var(--r-lg);
  background: radial-gradient(ellipse at 50% 30%, rgb(70, 22, 110), rgb(14, 7, 28) 78%);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.4);
  animation: p-fact-stage-in 500ms var(--ease-out) both;
}
.p-fact-stage.hidden { display: none; }
@keyframes p-fact-stage-in { from { opacity: 0; } to { opacity: 1; } }
.p-fact-card {
  display: grid; justify-items: center; gap: 12px;
  width: 100%; max-width: 440px; text-align: center; padding: 0 10px;
  animation: p-fact-in 500ms 120ms var(--ease-out) both;
}
@keyframes p-fact-in { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
.p-fact-answer-tag {
  font-family: var(--font-display); font-size: 11px; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.24em; color: var(--muted);
}
.p-fact-answer {
  --c: var(--brand); --c-rgb: 124, 58, 237; --on-c: #fff;
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 12px 14px; border-radius: var(--r-lg);
  background: linear-gradient(158deg, rgba(var(--c-rgb), 0.34), rgba(22, 16, 42, 0.98) 65%);
  border: 2px solid var(--c);
  box-shadow: 0 0 0 2px rgba(var(--c-rgb), 0.3), 0 0 30px rgba(var(--c-rgb), 0.5);
  text-align: left;
}
.p-fact-answer .answer-letter {
  font-size: 15px; width: 30px; height: 30px;
  background: var(--c); color: var(--on-c);
  box-shadow: 0 0 0 3px rgba(var(--c-rgb), 0.3), 0 0 16px rgba(var(--c-rgb), 0.6);
}
.p-fact-answer-text { flex: 1; font-size: clamp(18px, 2.8vh, 26px); font-weight: 800; line-height: 1.2; color: #fff; }
.p-fact-check {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  background: var(--c) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M5 12.5l4.2 4.2L19 7' fill='none' stroke='%23101010' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") center / 62% no-repeat;
  box-shadow: 0 0 14px rgba(var(--c-rgb), 0.7);
}
.p-fact-count { font-size: 13px; font-weight: 700; color: var(--muted); }
.p-fact-count:empty { display: none; }
.p-fact-fact { display: grid; gap: 8px; margin-top: 6px; }
.p-fact-fact.hidden { display: none; }
/* Live's dispute line: small, at the foot of the card, one tap to the reasons. */
.p-fact-report { margin-top: 10px; display: grid; gap: 8px; justify-items: center; }
.p-fact-report.hidden { display: none; }
.p-fact-report-link {
  background: none; border: none; padding: 4px 0; color: var(--muted); font: inherit;
  font-size: 12px; font-weight: 700; cursor: pointer;
}
.p-fact-report-reasons { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; }
.p-fact-report-reasons.hidden { display: none; }
.p-fact-report-chip {
  border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 999px; background: rgba(255, 255, 255, 0.08);
  color: var(--text, #fff); font: inherit; font-size: 12px; font-weight: 800; padding: 6px 12px; cursor: pointer;
}
.p-fact-report-chip:active { transform: scale(0.96); }
.p-fact-report-done { margin: 0; font-size: 12px; font-weight: 700; color: var(--muted); }
.p-fact-report-done.hidden { display: none; }
.p-fact-text {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(17px, 2.6vh, 23px); line-height: 1.32; font-weight: 700;
  text-wrap: balance; color: #fff;
  text-shadow: 0 4px 24px rgba(0, 0, 0, 0.6);
}
/* The stage takes the question's place; the rows' verdict has been read. */
#quiz-screen.is-fact .p-question,
#quiz-screen.is-fact .clue-banner,
#quiz-screen.is-fact .answers-grid,
#quiz-screen.is-fact .reactions,
#quiz-screen.is-fact .out-msg,
#quiz-screen.is-fact .answer-worth { display: none; }

/* The board: never on the answering screen (the single biggest reason answering
   used to feel crowded), up on its own for a few seconds after the points beat,
   and behind the trophy chip the rest of the time. It sits on the bottom edge,
   where a thumb can pull it down. */
.sheet-bottom { align-items: flex-end; padding: 0; }
.standings-card {
  display: flex; flex-direction: column; gap: 12px;
  width: min(560px, 100%); max-height: 68vh;
  border-bottom: 0; border-radius: var(--r-lg) var(--r-lg) 0 0;
  padding-bottom: max(18px, env(safe-area-inset-bottom));
  touch-action: pan-y; overflow: hidden; will-change: transform;
}
.sheet-grip {
  width: 44px; height: 5px; border-radius: 3px; margin: -6px auto 0;
  background: rgba(255, 255, 255, 0.28);
}
.standings-card .standing-chase { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
.standings-card .standing-note { flex: 0 0 auto; }
/* The TV's commentary crawl, one line high, pinned to the bottom edge for the
   whole reveal: above the board sheet and the Next-question stage, under the
   chat sheet and the lead-change stage. The full width so the crawl has as
   long a run as the phone allows. */
.p-ticker {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  min-width: 0; overflow: hidden; pointer-events: none;
  padding: 7px 0 max(7px, env(safe-area-inset-bottom));
  border-top: 2px solid var(--brand);
  background: rgba(22, 16, 42, 0.94);
}
body.has-ticker .moment-toast { bottom: calc(max(28px, env(safe-area-inset-bottom)) + 40px); }
body.has-ticker .standings-card { padding-bottom: calc(max(18px, env(safe-area-inset-bottom)) + 40px); }
/* The strip is fixed, so the screen leaves it a lane: the foot row (rank chip,
   reactions, Big buttons) stays fully in view above it. */
body.has-ticker #quiz-screen .p-foot { margin-bottom: calc(max(7px, env(safe-area-inset-bottom)) + 40px); }
.p-ticker.hidden { display: none; }
.p-ticker-move {
  display: inline-block; white-space: nowrap; padding-left: 100%;
  font-family: var(--font-display); font-size: 15px; font-weight: 900;
  letter-spacing: 0.03em; text-transform: uppercase; color: #fcd68a;
  animation: p-ticker 22s linear infinite -3s;
}
.p-ticker-line { padding: 0 14px; }
.p-ticker-sep { color: var(--brand-bright); }
@keyframes p-ticker {
  from { transform: translateX(0); }
  to { transform: translateX(-100%); }
}
@media (prefers-reduced-motion: reduce) {
  .p-ticker-move { animation: none; padding-left: 12px; white-space: normal; }
}
.standings-card .sheet-title { font-size: 20px; }
@media (min-width: 700px) {
  .sheet-bottom { align-items: center; padding: 18px; }
  .standings-card { border-bottom: 2px solid var(--line-strong); border-radius: var(--r-lg); max-height: 80%; }
}
/* The chip catches the board: a quick swell as the sheet shrinks into it. */
.p-foot-chip.is-caught { animation: chip-catch 520ms cubic-bezier(0.2, 0.9, 0.3, 1.4); }
@keyframes chip-catch {
  0% { transform: scale(1); }
  40% { transform: scale(1.22); background: rgba(168, 85, 247, 0.3); color: var(--text); border-color: var(--brand-bright); }
  100% { transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .p-foot-chip.is-caught { animation: none; }
}

.standing-chase { display: grid; gap: 6px; }
.standing-row-face { --av: 30px; }
.standing-row {
  display: grid; grid-template-columns: 24px auto minmax(0, 1fr) auto 32px;
  align-items: center; gap: 10px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 8px 12px;
}
.standing-row.is-you { border-color: var(--brand-bright); background: var(--surface-2); }
.standing-row-rank { font-weight: 900; color: var(--muted); text-align: center; }
.standing-row.rank-1 .standing-row-rank { color: var(--gold); }
.standing-row.rank-2 .standing-row-rank { color: var(--silver); }
.standing-row.rank-3 .standing-row-rank { color: var(--bronze); }
.standing-row-name { font-size: 15px; font-weight: 800; line-height: 1.2; overflow-wrap: anywhere; }
.standing-row-joined { display: block; font-size: 11px; font-weight: 600; color: var(--muted); letter-spacing: 0.02em; }
.standing-row-score {
  font-size: 15px; font-weight: 900; font-variant-numeric: tabular-nums;
}
.standing-row .lb-move { font-size: 12px; text-align: right; }
.standing-note {
  font-size: 12px; font-weight: 700; color: var(--muted); text-align: center;
}

/* ------------------------------------------------------ the bottom line --- */
/* Two icons and a word, and nothing that moves: the board, the reactions and the
   way into big buttons. Both sheets and the emoji row live behind these, so the
   answering screen has four buttons on it and nothing else. */

.p-foot {
  flex: 0 0 auto; display: flex; align-items: center; gap: 10px;
  margin-top: 10px;
}
.p-foot-chip, .p-foot-icon, .p-foot-text {
  background: rgba(255, 255, 255, 0.04); color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--r-pill);
  font: inherit; font-size: 13px; font-weight: 800; cursor: pointer;
  transition: background var(--t-fast) ease, color var(--t-fast) ease;
}
.p-foot-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px;
  font-variant-numeric: tabular-nums;
}
.p-foot-chip-icon { font-size: 14px; line-height: 1; }
.p-foot-icon {
  width: 36px; height: 36px; padding: 0; font-size: 18px; line-height: 1;
  border-radius: 50%; margin-left: auto;
}
.p-foot-icon.is-open { background: rgba(168, 85, 247, 0.22); color: var(--text); border-color: var(--brand-bright); }
.p-foot-text { padding: 7px 14px; }
.p-foot-chip:active, .p-foot-icon:active, .p-foot-text:active { transform: scale(0.96); }

/* The gap to the next question, counted down rather than stated once: the same
   clock and the same number the TV is showing. */
.p-next-countdown { margin-top: 14px; gap: 12px; }
/* The host has stopped the gap's clock on this answer. */
.p-hold-line {
  margin: 10px 0 0; text-align: center;
  font-family: var(--font-display); font-size: 13px; font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.12em; color: var(--gold);
}
.p-hold-line.hidden { display: none; }
.p-next-countdown .countdown-label { font-size: 14px; }

/* --------------------------------------------------------------- final --- */

.final-place { font-size: 20px; font-weight: 800; color: var(--gold); margin: 0 0 16px; }
.final-awards { display: grid; gap: 8px; margin: 0 0 16px; }
.your-night {
  display: grid; gap: 12px; margin: 0 0 16px; padding: 14px;
  border-radius: var(--r-lg); border: 1px solid var(--brand-bright);
  background: linear-gradient(160deg, rgba(124, 58, 237, 0.28), var(--surface) 70%);
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.35);
}
.your-night-head { display: flex; align-items: center; gap: 12px; }
.your-night-av { --av: 44px; }
.your-night-title { display: grid; gap: 2px; min-width: 0; flex: 1 1 auto; }
.your-night-eyebrow { font-size: 11px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
.your-night-name { font-family: var(--font-display); font-size: 18px; font-weight: 900; overflow-wrap: anywhere; }
.your-night-score { font-family: var(--font-display); font-size: 28px; font-weight: 900; color: var(--gold); font-variant-numeric: tabular-nums; }
.your-night-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.your-night-stat {
  display: grid; gap: 1px; padding: 10px 8px; text-align: center;
  border-radius: var(--r-md, 12px); background: rgba(255, 255, 255, 0.05); border: 1px solid var(--line);
}
.your-night-stat-value { font-family: var(--font-display); font-size: 20px; font-weight: 900; font-variant-numeric: tabular-nums; }
.your-night-stat-label { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text); }
.your-night-stat-sub { font-size: 11px; color: var(--muted); }
.your-night-line { margin: 0; font-size: 13px; font-weight: 700; color: var(--muted); text-align: center; }
.your-night-pin {
  display: flex; align-items: center; gap: 12px; margin-top: 12px; padding: 10px 12px;
  border-radius: 12px; background: rgba(255, 255, 255, 0.06); font-size: 13px; line-height: 1.35;
}
.your-night-pin .btn { flex: 0 0 auto; margin: 0; }
@media (max-width: 360px) { .your-night-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.final-award {
  display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  border-radius: var(--r-md, 12px); border: 1px solid var(--line);
  background: var(--surface); text-align: left;
}
.final-award.is-you {
  border-color: var(--gold); background: rgba(245, 179, 60, 0.12);
  box-shadow: 0 0 0 1px rgba(245, 179, 60, 0.35);
}
.final-award-icon { font-size: 26px; line-height: 1; flex: 0 0 auto; }
.final-award-text { display: grid; gap: 2px; min-width: 0; }
.final-award-text b { font-family: var(--font-display); font-size: 15px; text-transform: uppercase; letter-spacing: 0.06em; }
.final-award-text span { font-size: 13px; color: var(--muted); }
.final-award.is-you .final-award-text span { color: var(--text); }
.leaderboard-player .lb-row { padding: 12px 16px; gap: 12px; }
.leaderboard-player .lb-rank { font-size: 22px; }
.leaderboard-player .lb-name { font-size: 17px; }
.leaderboard-player .lb-meta { font-size: 12px; }
.leaderboard-player .lb-score { font-size: 22px; }
.leaderboard-player .lb-delta { font-size: 14px; padding: 3px 10px; min-width: 3.6em; }

/* A style of play with its own logo wears it instead of the glyph on the
   carousel. */
.chip-logo { max-height: 44px; width: auto; }
.p-learn-logo { max-height: 64px; max-width: 90%; width: auto; }

/* ---------------------------------------------------------- phone mode --- */
/*
 * A phone held in one hand has about a third of a tablet's screen, and the
 * question, the category and the fun fact are all already on the TV. Phone mode
 * gives the whole screen to the four buttons: everything else goes, including
 * the top bar, and what a player still needs — their score, the clock, the way
 * out — fits on one line.
 *
 * Offered, never imposed, and only where the screen is actually small: on a
 * tablet there is nothing to reclaim, so the controls aren't there at all.
 */
/* The hidden host gesture's target. No size on screen, no hint that it is
   there, and above the status pill so the taps land on it rather than on the
   bar behind it. */
.p-admin-corner {
  position: fixed; top: 0; right: 0; width: 46px; height: 56px;
  /* Above the connection pill, which sits in the same corner: the taps have
     to reach this and not stop at a label. */
  z-index: 110; background: transparent;
}


/* Narrow, or short: a phone on its side is 844x390, which has even less room
   above the buttons than the same phone upright. */
@media (max-width: 640px), (max-height: 480px) {
  .p-bar { padding: 0 40px 0 12px; }
  .p-clock-line { min-height: 26px; }
  .p-worth-now { font-size: 20px; }
  .p-timer-count { font-size: 17px; }
  .p-score-badge { font-size: 18px; padding: 2px 10px; }
  .standing-row { padding: 6px 10px; }
  /* At reveal the question has done its job -- it's on the TV -- so it stands
     down to a line and the four rows stay whole and readable, wrong ones
     included: which one it was, which one you tapped, and how the room split. */
  #quiz-screen.revealing .p-question { display: none; }
  #quiz-screen.revealing .answers-grid { gap: 8px; grid-auto-rows: minmax(46px, auto); }
  #quiz-screen.revealing .answer-btn { min-height: 46px; font-size: 16px; padding: 0 12px; }
  #quiz-screen.revealing .reveal-panel { margin-top: 10px; }
}

/* Everything the TV is already showing. The clue banner stays: in Buzztime the
   clues are the question, and a phone player would otherwise be guessing. So
   does the clock line -- it's two numbers and a hairline, and it's the only
   thing telling the player what a tap is worth and what theirs got. */
body.phone-mode .p-bar,
body.phone-mode .p-question { display: none; }
/* Except in a clue night: a clue is written about the question ("this trio of
   brothers..."), so hiding the question leaves the clue a riddle with no
   subject. It comes back as one tight line, not the full-size prose the TV is
   already carrying. */
body.phone-mode #quiz-screen.has-clues .p-question {
  display: block;
  font-size: 15px; line-height: 1.3; font-weight: 700;
  margin: 0 0 8px; color: var(--muted);
}
/* At the reveal the phone has the right answer, the shares and this player's
   result to fit; the clues did their job while the clock was running. */
/* A phone has four buttons to fit under the clue, so it keeps the floor size
   rather than scaling with the screen. */
body.phone-mode .clue-card.clue-newest { font-size: 21px; }
body.phone-mode .clue-card.clue-prev { font-size: 15px; }
body.phone-mode #quiz-screen.revealing .clue-banner,
body.phone-mode #quiz-screen.revealing.has-clues .p-question { display: none; }

/* With nothing above them, the buttons take the screen: a thumb should be able
   to hit any of the four without the phone changing hands. */
body.phone-mode #quiz-screen { padding: 10px; }
body.phone-mode .answers-grid { gap: 10px; }
body.phone-mode .answer-btn { min-height: 0; font-size: clamp(18px, 4.6vh, 30px); }
/* The reveal still shrinks the grid to make room for the result, but with no
   fun fact and no question there is far more of it to give back. */
body.phone-mode #quiz-screen.revealing .answers-grid { grid-auto-rows: minmax(48px, auto); }

/* ------------------------------------------------------- the reading beat */

/* The question goes up on its own and nobody's clock is running. The four
   buttons keep their space so nothing moves under a thumb already on its way,
   and they fade up together the moment the server says they're live. */
.answers-grid { transition: opacity 380ms var(--ease-out); }
#quiz-screen.is-reading .answers-grid { opacity: 0; pointer-events: none; }
#quiz-screen.is-reading .timer-bar-fill { background: rgba(167, 155, 200, 0.35); box-shadow: none; }
.reading-msg {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  margin: 10px 0 0; font-size: 14px; font-weight: 700; color: var(--muted);
}
.reading-dots { display: inline-flex; gap: 5px; }
.reading-dots i {
  width: 7px; height: 7px; border-radius: 50%; background: var(--brand-bright);
  animation: reading-pulse 1.1s ease-in-out infinite;
}
.reading-dots i:nth-child(2) { animation-delay: 0.15s; }
.reading-dots i:nth-child(3) { animation-delay: 0.3s; }
@keyframes reading-pulse {
  0%, 100% { opacity: 0.25; transform: scale(0.8); }
  50% { opacity: 1; transform: scale(1); }
}
/* Phone mode hides the question, but the reading beat IS the question, so it
   comes back for as long as the buttons are held. */
body.phone-mode #quiz-screen.is-reading .p-question {
  display: block; font-size: clamp(20px, 3.4vh, 30px); margin: 8px 0 0;
}
body.phone-mode #quiz-screen.is-reading .reading-msg { order: 99; }

/* ------------------------------------------------- what the room went with */

/* Shares, and only once the answer is out: live percentages are just a poll of
   which table guessed first, and they'd hand the room the answer. */
.answer-pct {
  display: none; font-family: var(--font-display); font-weight: 900;
  font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums;
}
#quiz-screen.revealing .answer-pct { display: block; }
.answer-btn.correct-final .answer-pct { color: #fff; }

/* ------------------------------------------------------------ big buttons */

/* The answer is the target: it's what the player is reading and what the thumb
   is aiming at. The letter is a small mark in the corner for the people calling
   "C!" across the table, and the button itself stays black so the only colour
   on the screen means something — your pick, and the right answer. */
body.phone-mode .answer-btn {
  position: relative; justify-content: center; text-align: center;
  padding: 10px 38px; font-weight: 800; letter-spacing: -0.01em;
  background: linear-gradient(180deg, #17102c, #100a1e);
}
body.phone-mode .answers-grid[data-len="m"] .answer-btn { font-size: clamp(16px, 3.6vh, 25px); }
body.phone-mode .answers-grid[data-len="l"] .answer-btn { font-size: clamp(15px, 3vh, 21px); }
body.phone-mode .answer-label { flex: 0 1 auto; }
body.phone-mode .answer-btn[data-choice] .answer-letter {
  position: absolute; top: 8px; right: 12px;
  min-width: 0; font-size: 12px;
}
body.phone-mode .answer-tick { position: absolute; top: 6px; left: 12px; }
body.phone-mode .answer-pct { position: absolute; bottom: 7px; right: 12px; }
/* The OUT stamp is a badge beside the answer on a wide button; centred under a
   big one it fights the answer for the middle of the screen. */
body.phone-mode .answer-btn.eliminated::after { position: absolute; bottom: 7px; left: 12px; }
/* Nothing was ever eliminated in a clue night, so three answers stamped OUT at
   its reveal is three untruths, and three things to read past on the way to the
   one that's lit green. The player's own wrong answer keeps its mark. */
#quiz-screen.has-clues.revealing .answer-btn.eliminated:not(.eliminated-pick)::after {
  content: none;
}
/* Big buttons give the screen to the four answers, so the reaction row gets the
   thinnest version of itself that a thumb can still hit. */
body.phone-mode .reactions { gap: 4px; margin-top: 8px; }
body.phone-mode .reaction-btn { width: 34px; height: 34px; font-size: 17px; }

/* --------------------------------------------------------- points takeover */

/* The score receipt: what the last question just paid, and nothing else -- no
   total, no question number, no board (that is the next screen). The finished
   question dims and blurs, and one of three supplied plates rises over it
   (web_shared/brand/receipt-*.webp, used as delivered: ring, glow, rays and
   sparks are all in the pixels); only the label and the number are live text,
   placed in the plate's own pixel grid so they sit in its ring on any phone.
   Tiers (data-tier): "max" for the question's full price -- gold ring, rays,
   sparks, one glint; "partial" for anything less -- violet ring, gold number
   over the plate's gold underline; "zero" -- violet ring, lavender number,
   MISSED CALL or NO CALL, no gold. It covers the screen but takes no taps. */
.earned {
  position: absolute; inset: 0; z-index: 5; pointer-events: none; overflow: hidden;
  container-type: size;
  background: rgba(5, 2, 16, 0.55);
  -webkit-backdrop-filter: blur(4px) brightness(0.3); backdrop-filter: blur(4px) brightness(0.3);
  animation: earned-scrim 140ms ease-out both;
  transition: opacity 200ms ease;
}
.earned.hidden { display: none; }
.earned.is-out { opacity: 0; }
@keyframes earned-scrim { from { opacity: 0; } to { opacity: 1; } }

/* Each plate's pixel size, and how far it may outgrow the screen: the frame
   covers the screen unless that would push the ring off the sides, in which
   case it stops at --cap screen widths and the blurred question shows above
   and below. --u is one plate pixel. --band-top/--band-h is the strip of
   plate pixels holding the ring, its glow and sparks: on a landscape screen
   (a tablet held sideways) a portrait plate can't cover the screen and keep
   its ring on it, so the frame is sized to fit that strip in the height and
   slid so the strip is centred, the blurred question showing either side. */
.earned[data-tier="max"] { --pw: 1024; --ph: 1536; --cap: 1.19; --band-top: 150; --band-h: 900; }
.earned[data-tier="partial"],
.earned[data-tier="zero"] { --pw: 941; --ph: 1671; --cap: 1.7; --band-top: 440; --band-h: 610; }
.earned-frame {
  position: absolute; left: 50%; top: 50%; translate: -50% -50%;
  width: min(max(100cqw, calc(100cqh * var(--pw) / var(--ph))), calc(100cqw * var(--cap)));
  aspect-ratio: var(--pw) / var(--ph);
  container-type: inline-size;
}
@container (min-aspect-ratio: 1/1) {
  .earned-frame {
    width: min(100cqw, calc(100cqh * var(--pw) / var(--band-h) * 0.94));
    translate: -50% calc(-100% * (var(--band-top) + var(--band-h) / 2) / var(--ph));
  }
}
.earned-plate {
  position: absolute; inset: 0; width: 100%; height: 100%; display: none;
}
.earned[data-tier="max"] .for-max,
.earned[data-tier="partial"] .for-partial,
.earned[data-tier="zero"] .for-zero { display: block; }

.earned-label, .earned-points, .earned-glint {
  --u: calc(100cqw / var(--pw));
  position: absolute; left: 0; right: 0; margin: 0; text-align: center;
  font-family: var(--font-display); font-synthesis: none;
}
.earned-label {
  top: calc(var(--label-y) * var(--u)); font-size: calc(var(--label-size) * var(--u));
  font-weight: 800; line-height: 1; letter-spacing: 0.145em; text-transform: uppercase; color: #fff;
  text-shadow: 0 0 calc(24 * var(--u)) rgba(195, 135, 255, 0.45);
  animation: earned-label-in 140ms ease-out 240ms both;
}
@keyframes earned-label-in { from { transform: translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
/* The number is drawn twice: the element itself carries the solid fill and
   the bevel shadows, its ::after the gradient clipped to the glyphs on top.
   Painting the shadows on a transparent-text gradient muddies the glyphs
   (Samsung Internet in particular), so the two stay separate. */
.earned-points {
  top: calc(var(--points-y) * var(--u)); font-size: calc(var(--points-size) * var(--u) * var(--fit, 1));
  font-weight: 900; line-height: 0.94; letter-spacing: -0.06em; font-variant-numeric: tabular-nums; color: #f5b331;
  text-shadow: 0 calc(2 * var(--u)) 0 #fff3be, 0 calc(5 * var(--u)) 0 #d78610, 0 calc(9 * var(--u)) 0 #a65206,
    0 calc(12 * var(--u)) 0 #6e3203,
    0 calc(22 * var(--u)) calc(34 * var(--u)) rgba(40, 8, 0, 0.8), 0 0 calc(40 * var(--u)) rgba(255, 183, 41, 0.55);
  animation: earned-points-in 280ms cubic-bezier(0.16, 0.88, 0.24, 1) 340ms both;
}
.earned-points::after {
  content: attr(data-text); position: absolute; inset: 0; text-shadow: none;
  color: transparent; -webkit-background-clip: text; background-clip: text;
  background-image: linear-gradient(180deg, #fff8d6 0%, #ffe17b 26%, #f5b331 55%, #c7710d 82%, #8a4a06 100%);
}
@keyframes earned-points-in {
  from { transform: scale(0.82); opacity: 0; }
  70% { transform: scale(1.04); opacity: 1; }
  to { transform: none; opacity: 1; }
}

/* Full price: the plate blooms in, then the words (1.2 s in all). */
.earned[data-tier="max"] {
  --label-y: 430; --label-size: 50; --points-y: 492; --points-size: 200; --ring-w: 640;
}
.earned[data-tier="max"] .earned-plate { animation: earned-ring-in 320ms cubic-bezier(0.16, 0.88, 0.24, 1) 100ms both; }
@keyframes earned-ring-in {
  0% { opacity: 0; transform: scale(0.84); }
  70% { opacity: 1; transform: scale(1.03); }
  100% { opacity: 1; transform: none; }
}
.earned-glint {
  display: none; left: 28%; right: 28%; top: calc(592 * var(--u));
  height: calc(6 * var(--u)); border-radius: 999px; opacity: 0; z-index: 2;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 235, 0.1), #fff9d5, rgba(255, 255, 235, 0.1), transparent);
  box-shadow: 0 0 16px #f6b822;
  animation: earned-glint 1.2s both;
}
.earned[data-tier="max"] .earned-glint { display: block; }
@keyframes earned-glint {
  0%, 38% { opacity: 0; transform: translateX(-22%); }
  44% { opacity: 1; }
  49%, 100% { opacity: 0; transform: translateX(22%); }
}

/* Less than full price: softer and quicker (0.85 s); the number rests on the
   plate's gold underline. */
.earned[data-tier="partial"] {
  --label-y: 575; --label-size: 46; --points-y: 632; --points-size: 185; --ring-w: 470;
}
.earned[data-tier="partial"] .earned-plate { animation: earned-soft-in 320ms cubic-bezier(0.16, 0.88, 0.24, 1) 100ms both; }
@keyframes earned-soft-in { from { opacity: 0; transform: scale(0.92); } to { opacity: 1; transform: none; } }
.earned[data-tier="partial"] .earned-label { animation-delay: 200ms; }
.earned[data-tier="partial"] .earned-points {
  color: #efa22c;
  animation: earned-points-soft 260ms cubic-bezier(0.16, 0.88, 0.24, 1) 280ms both;
}
.earned[data-tier="partial"] .earned-points::after {
  background-image: linear-gradient(180deg, #ffefae 0%, #fcd36b 28%, #efa22c 62%, #a85b0a 100%);
}
@keyframes earned-points-soft { from { transform: scale(0.9); opacity: 0; } to { transform: none; opacity: 1; } }

/* Nothing this time: a neutral reset (0.6 s), lavender on violet, no gold. */
.earned[data-tier="zero"] {
  --label-y: 575; --label-size: 46; --points-y: 625; --points-size: 210; --ring-w: 470;
}
.earned[data-tier="zero"] .earned-plate { animation: earned-zero-in 200ms ease-out 100ms both; }
@keyframes earned-zero-in { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }
.earned[data-tier="zero"] .earned-label { animation-delay: 180ms; text-shadow: 0 0 calc(24 * var(--u)) rgba(195, 135, 255, 0.32); }
.earned[data-tier="zero"] .earned-points {
  letter-spacing: -0.05em; color: #e6d8ff;
  text-shadow: 0 calc(2 * var(--u)) 0 #fff, 0 calc(8 * var(--u)) calc(20 * var(--u)) rgba(69, 26, 130, 0.55), 0 0 calc(32 * var(--u)) rgba(173, 102, 255, 0.52);
  animation: earned-label-in 240ms ease-out 180ms both;
}
.earned[data-tier="zero"] .earned-points::after {
  background-image: linear-gradient(180deg, #fff 0%, #e6d8ff 43%, #a970ed 100%);
}

@media (prefers-reduced-motion: reduce) {
  .earned, .earned-plate, .earned-label, .earned-points { animation: none; }
  .earned-glint { display: none !important; }
  .reading-dots i { animation: none; }
}

/* ------------------------------------------------ the question count-in --- */
/* The seconds before a question lands: the TV's "Next question" card at phone
   size, on the same beat. What it's about, the headline slamming in, which
   number it is, and a line across the top draining to the moment it drops --
   the frame the buzz fires on. Everything runs on the phone's own clock from
   the moment it is armed. The veil takes no taps; there is nothing to tap
   during the gap anyway. Above the points takeover and below the paused veil,
   which cancels it. */
.question-drop {
  --drop-seconds: 2s;
  position: fixed; inset: 0; z-index: 40; pointer-events: none;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  background: #0b0914 radial-gradient(ellipse 90% 55% at 50% 50%, rgba(91, 33, 182, 0.55), transparent 70%);
  animation: drop-veil 200ms var(--ease-out) both;
}
.question-drop.hidden { display: none; }
/* The TV's stage set is 16:9; a phone is the other way up. Cropped to the
   phone's height it is a dark wall with no arch, so instead the whole set --
   arch, towers, lit floor, crowd -- runs as a band across the middle of the
   screen, a shade wider than the phone so the arch fills it, feathered into
   the plum above and below. */
.drop-stage {
  position: absolute; left: -10vw; width: 120vw; top: 50%; transform: translateY(-50%);
  aspect-ratio: 1920 / 1081;
  background: url("/shared/brand/stage.webp") center / cover no-repeat;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 14%, #000 86%, transparent);
}
.drop-sweep {
  position: absolute; top: 0; bottom: 0; left: 0; width: 18vw;
  background: linear-gradient(90deg, transparent, rgba(168, 85, 247, 0.3), transparent);
  animation: drop-sweep 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes drop-sweep {
  0% { transform: translateX(-120%) skewX(-25deg); opacity: 0; }
  20%, 80% { opacity: 0.8; }
  100% { transform: translateX(650%) skewX(-25deg); opacity: 0; }
}
.drop-drain {
  position: absolute; top: 0; left: 0; right: 0; height: 6px;
  background: rgba(59, 7, 100, 0.6);
}
.drop-drain > span {
  display: block; height: 100%; width: 100%;
  background: linear-gradient(90deg, var(--gold), var(--brand-bright), var(--accent, #22d3ee));
  box-shadow: 0 0 16px rgba(245, 179, 60, 0.9);
  animation: drop-drain var(--drop-seconds) linear forwards;
}
@keyframes drop-drain { from { width: 100%; } to { width: 0%; } }
/* The words hang in the arch; the counter sits on the lit floor below it as
   it does on the TV (the band's floor is about a third of its width down
   from the screen's middle). */
.drop-text {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(14px, 3vh, 30px);
  text-align: center; padding: 0 20px;
}
.drop-category {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 18px; border-radius: 999px;
  background: rgba(59, 7, 100, 0.7); border: 2px solid rgba(168, 85, 247, 0.6);
  box-shadow: 0 0 30px rgba(168, 85, 247, 0.5);
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(13px, 2.2vh, 20px); letter-spacing: 0.12em; text-transform: uppercase;
  color: #fcd68a;
  animation: drop-pop 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.15s both;
}
.drop-category:empty { display: none; }
.drop-category::before {
  content: "\2605"; color: var(--gold); font-size: 0.9em;
  animation: drop-bounce 1s ease-in-out infinite;
}
@keyframes drop-pop {
  0% { transform: scale(0.8); opacity: 0; }
  40% { transform: scale(1.05); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes drop-bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-18%); }
}
.drop-headline {
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(40px, 13vw, 88px); line-height: 0.95;
  letter-spacing: -0.03em; text-transform: uppercase;
  /* Solid fills with text-shadow, not gradient-clipped text: Samsung Internet
     and some Chromium builds draw a clipped gradient plus a filter as a muddy
     brown block. */
  color: #f6f3ff;
  text-shadow: 0 10px 30px rgba(0, 0, 0, 0.9);
  animation: drop-slam 1.6s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.drop-headline em {
  font-style: normal; display: block;
  color: #fcd34d;
  text-shadow: 0 0 30px rgba(245, 179, 60, 0.8), 0 10px 30px rgba(0, 0, 0, 0.7);
}
@keyframes drop-slam {
  0% { transform: scale(0.6) translateY(20px); opacity: 0; }
  25% { transform: scale(1.08) translateY(-4px); opacity: 1; }
  35% { transform: scale(0.98) translateY(0); }
  50% { transform: scale(1.02); }
  75% { transform: scale(0.99); }
  100% { transform: scale(1); }
}
/* The final question of a game: the headline flashes gold so the table knows
   this is the one that settles it. */
.question-drop.is-last .drop-headline {
  animation: drop-slam 1.6s cubic-bezier(0.16, 1, 0.3, 1) both,
    drop-last-flash 0.5s steps(2, jump-none) 0.6s infinite;
}
@keyframes drop-last-flash { from { opacity: 1; } to { opacity: 0.45; } }
.drop-counter {
  position: absolute; top: calc(50% + 34vw); padding: 8px 18px; border-radius: 12px;
  background: rgba(22, 16, 42, 0.9); border: 2px solid rgba(168, 85, 247, 0.5);
  box-shadow: 0 0 30px rgba(124, 58, 237, 0.5);
  font-family: var(--font-display); font-weight: 900;
  font-size: clamp(15px, 2.4vh, 22px); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--gold); text-shadow: 0 0 20px rgba(245, 179, 60, 0.9);
  animation: drop-pop 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0.4s both;
}
.drop-counter:empty { display: none; }
/* The veil lets go on its own once the line has run out, question or no
   question yet -- a late packet still gets the question in with the drop below. */
.question-drop.is-spent { animation: drop-veil-out 250ms ease-out calc(var(--drop-seconds) + 0.3s) both; }
@keyframes drop-veil { from { opacity: 0; } to { opacity: 1; } }
@keyframes drop-veil-out { to { opacity: 0; visibility: hidden; } }

/* The question that follows the count-in drops in from the top; a question
   that arrives with no count-in (reading beat off, a resumed night) just
   appears as before. */
#quiz-screen.is-dropping .p-category,
#quiz-screen.is-dropping .p-question {
  animation: question-drop-in 500ms cubic-bezier(0.15, 1.2, 0.3, 1) both;
}
#quiz-screen.is-dropping .p-question { animation-delay: 60ms; }
@keyframes question-drop-in {
  0% { opacity: 0; transform: translateY(-60px) scale(1.08); }
  60% { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .question-drop *, #quiz-screen.is-dropping .p-category, #quiz-screen.is-dropping .p-question {
    animation-duration: 1ms !important;
  }
}

/* The TV's countdown on the phone for the last ten seconds before a game: the
   number the TV shows, big enough to read from the table, gold and buzzing for
   the final three. Under the count-in and paused veils, over everything else. */
/* --heat runs 0 at ten seconds to 1 at one: the number warms from white to
   gold, its glow and the rings' pace build with it, and the line across the
   top drains -- so the count is going somewhere from the first second, not
   only once it says "Here we go!". */
.kickoff {
  --heat: 0;
  position: fixed; inset: 0; z-index: 38; pointer-events: none;
  display: grid; place-items: center; overflow: hidden;
  background: #0b0914 radial-gradient(ellipse 90% 55% at 50% 50%, rgba(91, 33, 182, 0.55), transparent 70%);
  animation: drop-veil 300ms var(--ease-out) both;
}
.kickoff.hidden { display: none; }
.kickoff > * { grid-area: 1 / 1; }
.kickoff .drop-stage, .kickoff .drop-sweep, .kickoff .drop-drain { grid-area: auto; }
.kickoff .drop-drain > span { animation: none; width: 100%; transition: width 120ms linear; }
.kickoff-rings {
  position: relative; width: 70vmin; height: 70vmin;
  opacity: calc(0.35 + var(--heat) * 0.65); transition: opacity 400ms;
}
.kickoff-ring {
  position: absolute; inset: 0; border-radius: 50%; border: 3px solid var(--brand-bright);
  animation: kickoff-swell calc(2.4s - var(--heat) * 1.2s) ease-out infinite;
}
.kickoff-ring:nth-child(2) { animation-delay: 0.5s; border-color: rgba(245, 179, 60, 0.7); }
.kickoff-ring:nth-child(3) { animation-delay: 1s; border-color: rgba(34, 211, 238, 0.6); }
@keyframes kickoff-swell {
  0% { transform: scale(0.4); opacity: 0.9; }
  100% { transform: scale(1.6); opacity: 0; }
}
.kickoff-body { position: relative; z-index: 1; display: grid; justify-items: center; gap: 6px; text-align: center; padding: 0 24px; }
.kickoff-label {
  font-family: var(--font-display); font-size: 22px; font-weight: 800;
  letter-spacing: 0.12em; text-transform: uppercase; color: #d9c8ff;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.8);
  animation: kickoff-breathe 1.6s ease-in-out infinite;
}
@keyframes kickoff-breathe { 0%, 100% { opacity: 0.75; } 50% { opacity: 1; } }
.kickoff.is-go .kickoff-label { color: var(--gold); font-size: 30px; animation: none; }
.kickoff-num {
  font-family: var(--font-display); font-size: 46vmin; font-weight: 900; line-height: 1;
  color: color-mix(in srgb, #fff, #fcd34d calc(var(--heat) * 100%));
  text-shadow:
    0 0 calc(30px + var(--heat) * 50px) rgba(245, 179, 60, calc(0.2 + var(--heat) * 0.6)),
    0 0 60px var(--brand-glow), 0 10px 30px rgba(0, 0, 0, 0.8);
}
.kickoff.is-go .kickoff-num { color: var(--gold); text-shadow: 0 0 90px rgba(245, 179, 60, 0.85), 0 10px 30px rgba(0, 0, 0, 0.8); }
.kickoff-num.is-tick { animation: kickoff-tick 700ms cubic-bezier(0.15, 1.2, 0.3, 1) both; }
@keyframes kickoff-tick {
  0% { transform: scale(1.6) translateY(-6vh); opacity: 0; filter: brightness(2); }
  45% { transform: scale(0.96) translateY(0); opacity: 1; filter: brightness(1.3); }
  100% { transform: scale(1); opacity: 1; filter: brightness(1); }
}
.kickoff-title {
  font-size: 16px; font-weight: 800; color: #fcd68a; letter-spacing: 0.04em;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.8);
}
@media (prefers-reduced-motion: reduce) {
  .kickoff, .kickoff-ring, .kickoff-num.is-tick, .kickoff-label, .kickoff .drop-sweep { animation: none; }
}

/* ------------------------------------------------------- first-time tip --- */
/* An inline card on the lobby or briefing, never a modal: the game underneath
   is always reachable, and the card fades on its own before the first question. */
.first-tip { width: 100%; margin: 12px auto; transition: opacity 400ms ease; }
.first-tip.is-leaving { opacity: 0; pointer-events: none; }
.first-tip-card {
  width: min(420px, 100%); margin: 0 auto; display: grid; gap: 10px; text-align: left;
  padding: 14px 16px; border-radius: 16px;
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border: 1px solid rgba(180, 140, 255, 0.35);
}
.first-tip-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.first-tip-title { font-family: var(--font-display); font-size: 18px; font-weight: 900; margin: 0; }
.first-tip-list { margin: 0; padding: 0 0 0 20px; display: grid; gap: 6px; font-size: 15px; line-height: 1.35; }
.first-tip-list b { color: var(--gold); }
.first-tip-ok {
  flex: none; background: none; border: 1px solid rgba(180, 140, 255, 0.45); border-radius: 999px;
  color: var(--brand-bright); font: inherit; font-size: 13px; font-weight: 900; padding: 6px 12px; cursor: pointer;
}

/* ------------------------------------------------------- the moment toast --- */
/* A line to this player over the reveal: rises from the bottom edge, clear of
   the answers and the top bar, and drops out before the points beat. It is over the screen, not in
   it, so nothing below moves. */
.moment-toast {
  position: fixed; left: 50%; bottom: max(28px, env(safe-area-inset-bottom));
  z-index: 35; pointer-events: none;
  display: inline-flex; align-items: center; gap: 10px;
  max-width: calc(100% - 28px); padding: 10px 18px 10px 14px;
  border-radius: var(--r-pill);
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.96), rgba(76, 29, 149, 0.96));
  border: 1px solid var(--brand-bright);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45), 0 0 0 4px rgba(168, 85, 247, 0.18);
  color: #fff; font-weight: 900; font-size: clamp(15px, 4.2vmin, 19px);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: moment-in 360ms cubic-bezier(0.2, 0.9, 0.3, 1.3) both;
}
.moment-toast.hidden { display: none; }
.moment-toast.is-out { animation: moment-out 240ms ease-in both; }
.moment-icon { font-size: 1.3em; line-height: 1; }
@keyframes moment-in {
  from { transform: translate(-50%, 140%) scale(0.9); opacity: 0; }
  to { transform: translate(-50%, 0) scale(1); opacity: 1; }
}
@keyframes moment-out {
  from { transform: translate(-50%, 0); opacity: 1; }
  to { transform: translate(-50%, 140%); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .moment-toast, .moment-toast.is-out { animation-duration: 1ms; }
}

/* ------------------------------------------------------- lead change stage --- */
/* The whole phone for 1.5s: the game-show stage edge to edge, and one
   centred column over it -- banner, the new leader's face in the gold ring,
   their name. The plate is sized and shifted so its dark aperture sits dead
   centre, under the ring. Above every sheet and pill; nothing to tap. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.lead-stage {
  position: fixed; inset: 0; z-index: 120; pointer-events: none;
  background: #0b0914;
  animation: lead-stage-in 150ms ease-out both, lead-stage-out 300ms ease-in 2.2s forwards;
}
.lead-stage.hidden { display: none; }
.lead-frame {
  position: absolute; inset: 0;
  background: #1a0630 url("/shared/brand/lead-change-stage.webp") 50% -6.5vh / auto 106vh no-repeat;
  overflow: hidden;
}
/* Placed where the plate puts them, as on the TV: the banner in the outlined
   box across the top (7% to 24.6% of the plate), the face on the aperture at
   the plate's 53.3%, the name on the podium's face at 73%. */
.lead-banner {
  position: absolute; left: 6%; right: 6%; top: 0.9vh; height: 18.7vh;
  display: flex; align-items: center; justify-content: center; text-align: center;
  font-family: var(--font-display, inherit); font-weight: 900; text-transform: uppercase;
  font-size: clamp(30px, 12vw, 64px); line-height: 1; letter-spacing: 0.01em;
  overflow-wrap: anywhere;
  color: #fff; -webkit-text-stroke: 0.06em #5b21b6; paint-order: stroke fill;
  text-shadow: 0 0 22px rgba(139, 92, 246, 0.9), 0 4px 0 #3b0d7a;
  animation: lead-banner-in 200ms cubic-bezier(0.2, 0.9, 0.3, 1.2) 150ms both;
}
/* The plate's ring, measured in the art: centred at 53.5% of the plate,
   clear inside 25.4% of its height. Plate is 106vh tall, shifted up 6.5vh,
   so the face is 26.9vh at 50.2vh. No ring or halo drawn live. */
.lead-face {
  --lf: min(26.9vh, 92vw);
  position: absolute; left: calc(50% - var(--lf) / 2); top: calc(50.2vh - var(--lf) / 2);
  width: var(--lf); aspect-ratio: 1;
  border-radius: 50%; overflow: hidden; background: #1a0630;
  display: flex; align-items: center; justify-content: center;
  container-type: size;
  animation: lead-face-in 300ms cubic-bezier(0.2, 0.9, 0.3, 1.15) 250ms both;
}
.lead-face .tv-lead-face {
  --av: 100%;
  display: block; width: 100%; height: 100%; border: 0; box-shadow: none;
  background: var(--av-bg, #1a0630);
}
.lead-face .tv-lead-face.av-default { background: #1a0630; }
.lead-face .tv-lead-face img { object-fit: cover; }
.lead-face .tv-lead-pair { --av: 62cqw; display: flex; width: auto; }
.lead-face .tv-lead-pair .av-c { border-color: #1a0630; }
.lead-face .tv-lead-pair .av-c + .av-c { margin-left: -14cqw; }
.lead-name {
  position: absolute; left: 6%; right: 6%; top: 71vh;
  display: block; text-align: center; font-weight: 900; font-size: clamp(18px, 7vw, 34px); line-height: 1.1;
  color: #fff; text-shadow: 0 0 18px #1a0630, 0 2px 10px rgba(0, 0, 0, 0.9);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: lead-banner-in 200ms ease-out 350ms both;
}
@keyframes lead-stage-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes lead-stage-out {
  from { opacity: 1; transform: scale(1); }
  to { opacity: 0; transform: scale(1.04); }
}
@keyframes lead-banner-in {
  from { opacity: 0; transform: translateY(-6%) scale(0.94); }
  to { opacity: 1; transform: none; }
}
@keyframes lead-face-in {
  from { opacity: 0; transform: scale(0.82); }
  to { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .lead-stage, .lead-banner, .lead-face, .lead-name { animation: none; }
}

/* AWARDS: the TV's three plates, each cropped to the middle of a landscape
   plate so its ring sits on the phone; the face live in the ring, the title
   set live over the top (the plate's own lettering is wider than a phone),
   name and score on the floor. */
.award-stage {
  --award-s: 3s;
  position: fixed; inset: 0; z-index: 120; pointer-events: none;
  background: #0b0914;
  animation: lead-stage-in 150ms ease-out both,
    lead-stage-out 300ms ease-in calc(var(--award-s) - 300ms) forwards;
}
.award-stage.hidden { display: none; }
.award-frame {
  position: absolute; inset: 0; overflow: hidden;
  background: #1a0630 center / auto 110vh no-repeat;
}
.award-frame::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 24vh;
  background: linear-gradient(#1a0630 30%, rgba(26, 6, 48, 0));
}
.kind-perfect_game .award-frame { background-image: url("/shared/brand/perfect-game-stage.webp"); background-position: 50% -11vh; background-size: auto 120vh; }
.kind-all_correct .award-frame { background-image: url("/shared/brand/all-correct-stage.webp"); background-position: 50% -16vh; }
.kind-personal_best .award-frame { background-image: url("/shared/brand/personal-best-stage.webp"); background-position: 50% -13vh; }
.award-headline {
  position: absolute; left: 6%; right: 6%; top: 2vh; height: 16vh;
  display: flex; align-items: center; justify-content: center; text-align: center;
  font-family: var(--font-display, inherit); font-weight: 900; text-transform: uppercase;
  font-size: clamp(28px, 11vw, 60px); line-height: 1; letter-spacing: 0.01em;
  color: #fff; -webkit-text-stroke: 0.06em #5b21b6; paint-order: stroke fill;
  text-shadow: 0 0 22px rgba(245, 179, 60, 0.8), 0 4px 0 #3b0d7a;
  animation: lead-banner-in 200ms cubic-bezier(0.2, 0.9, 0.3, 1.2) 150ms both;
}
.kind-perfect_game .award-headline { color: #ffe08a; }
/* The plate's own PERFECT GAME lettering lands under the live title on a phone. */
.kind-perfect_game .award-frame::before { height: 28vh; background: linear-gradient(#1a0630 55%, rgba(26, 6, 48, 0)); }
/* Each ring measured in its plate (centre / clear inside height), then
   through that plate's size and shift above: perfect game 52.3% / 34.9% of
   120vh - 11vh; all correct 64.5% / 36% of 110vh - 16vh; personal best
   62.4% / 40% of 110vh - 13vh. No ring or halo drawn live. */
.award-face {
  --lf: min(41.9vh, 92vw);
  position: absolute; left: calc(50% - var(--lf) / 2); top: calc(51.8vh - var(--lf) / 2);
  width: var(--lf); aspect-ratio: 1;
  border-radius: 50%; overflow: hidden; background: #1a0630;
  display: flex; align-items: center; justify-content: center;
  container-type: size;
  animation: lead-face-in 300ms cubic-bezier(0.2, 0.9, 0.3, 1.15) 250ms both;
}
.kind-all_correct .award-face { --lf: min(39.6vh, 92vw); top: calc(55vh - var(--lf) / 2); }
.kind-personal_best .award-face { --lf: min(44vh, 92vw); top: calc(55.6vh - var(--lf) / 2); }
.award-face .tv-lead-face {
  --av: 100%;
  display: block; width: 100%; height: 100%; border: 0; box-shadow: none;
  background: var(--av-bg, #1a0630);
}
.award-face .tv-lead-face.av-default { background: #1a0630; }
.award-face .tv-lead-face img { object-fit: cover; }
.award-face .tv-lead-pair { --av: 62cqw; display: flex; width: auto; }
.award-face .tv-lead-pair .av-c { border-color: #1a0630; }
.award-face .tv-lead-pair .av-c + .av-c { margin-left: -14cqw; }
.award-name, .award-detail {
  position: absolute; left: 6%; right: 6%;
  display: block; text-align: center; font-weight: 900; line-height: 1.1;
  color: #fff; text-shadow: 0 0 18px #1a0630, 0 2px 10px rgba(0, 0, 0, 0.9);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  animation: lead-banner-in 200ms ease-out 350ms both;
}
.award-name { top: 76vh; font-size: clamp(18px, 7vw, 34px); }
.award-detail { top: 83vh; font-size: clamp(16px, 5.5vw, 26px); color: var(--gold, #f5b33c); }
@media (prefers-reduced-motion: reduce) {
  .award-stage, .award-headline, .award-face, .award-name, .award-detail { animation: none; }
}
.p-break-board .standing-row { grid-template-columns: 24px auto minmax(0, 1fr) auto; }
.p-break-you .your-night { width: 100%; margin: 0; text-align: left; }
.p-break-board .standing-row-name { text-align: left; }
.standing-chase.no-moves .standing-row { grid-template-columns: 24px auto minmax(0, 1fr) auto; }
.standing-chase.no-moves .lb-move { display: none; }

/* Big buttons put the letter in the top-right corner, where the check lands at
   reveal; the check is in the row's colour, so it carries the identity alone. */
body.phone-mode .answer-btn.correct-final .answer-letter { display: none; }
body.phone-mode .answer-btn::before { top: 8px; right: 12px; margin-top: 0; }

/* A short phone (360x640 and its kind) with a long question: the question
   text gives up size before the rows give up the screen, and the rows sit at
   the height of a thumb rather than a palm, so all four stay above the foot. */
@media (max-height: 700px) {
  body:not(.phone-mode) #quiz-screen { padding: 12px 14px 10px; }
  body:not(.phone-mode) .p-category { margin-top: 6px; padding: 4px 12px; font-size: 11px; }
  body:not(.phone-mode) .p-category + .p-question { margin-top: 6px; }
  body:not(.phone-mode) .p-question { font-size: clamp(15px, 2.9vh, 20px); line-height: 1.2; margin: 8px 0 6px; }
  body:not(.phone-mode) .answers-grid { gap: 6px; }
  body:not(.phone-mode) .answer-btn { min-height: 46px; font-size: clamp(14px, 2.4vh, 17px); padding: 0 12px; gap: 10px; }
  body:not(.phone-mode) #quiz-screen.revealing .answer-btn { min-height: 40px; }
}

/* the Main Stage, watching between questions. */
.live-watch-card { margin: 14px 0 10px; }
.live-watch-sub { margin: 0; color: var(--muted); font-size: 14px; text-align: center; }

/* Live's front door: a slim code bar above the question, the host link under
   it. Both go the moment the phone has a name. */
.live-door-top {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  padding: 6px 12px; border-bottom: 1px solid var(--line);
  background: rgba(255, 255, 255, 0.03);
}
.live-door-text { flex: 1 1 auto; min-width: 0; font-size: 12px; color: var(--muted); line-height: 1.25; }
.live-door-code {
  flex: 0 0 68px; width: 68px; padding: 6px 8px; border-radius: var(--r-sm, 8px);
  border: 1px solid var(--line); background: rgba(0, 0, 0, 0.3); color: var(--text);
  font: inherit; font-size: 14px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; text-align: center;
}
.live-door-code::placeholder { color: var(--muted); opacity: 0.6; letter-spacing: 0.14em; }
.live-door-go {
  flex: 0 0 auto; padding: 6px 10px; border-radius: var(--r-sm, 8px); border: 1px solid var(--line);
  background: none; color: var(--text); font: inherit; font-weight: 800; cursor: pointer;
}
.live-door-foot {
  flex: 0 0 auto; display: block; padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line); text-align: center;
  font-size: 13px; font-weight: 700; color: var(--muted); text-decoration: none;
}
.live-door-foot.hidden, .live-door-top.hidden { display: none; }

/* The corner chip in Live: a live dot in front of the session line. */
.p-room-chip.is-live::before {
  content: ""; flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
  background: var(--brand-bright); box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.35);
  animation: live-dot 2s ease-out infinite;
}
@keyframes live-dot {
  0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.35); }
  70% { box-shadow: 0 0 0 5px rgba(255, 255, 255, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
}
