/*
 * 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 0 auto; font-size: 12px; font-weight: 800; color: var(--muted);
  letter-spacing: 0.06em; font-variant-numeric: tabular-nums;
}

/* --------------------------------------------------------------- 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; }
.join-head { flex: 0 0 auto; }
#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; }

/* ------------------------------------------------------------ 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; }
.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; }
.av-overlay .av-group-btn { font-size: 14px; padding: 8px 18px; }
.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; }
.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 {
  text-align: center;
  font-size: clamp(13px, 1.9vh, 17px); font-weight: 900;
  text-transform: uppercase; letter-spacing: 0.18em; color: var(--gold);
  margin: 14px 0 0;
}
.p-category + .p-question { margin-top: 4px; }
/* 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;
}
/* Plain black, on every size of device: when all four rows are coloured the
   colour is decoration, and the two colours that mean something -- your pick and
   the right answer -- have nothing left to say. */
.answer-btn {
  position: relative; overflow: hidden;
  background: linear-gradient(180deg, #17102c, #100a1e);
  color: var(--text); border: 2px solid var(--line); border-radius: var(--r-lg);
  font-size: clamp(17px, 2.6vh, 28px); font-weight: 700; padding: 0 18px;
  min-height: 62px;
  display: flex; align-items: center; gap: 14px; text-align: left;
  font-family: inherit;
  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);
}
/* 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; inset: 0 auto 0 0; width: 0;
  background: rgba(167, 155, 200, 0.16);
  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: rgba(34, 197, 94, 0.26); }
.answer-btn.selected:not(.correct-final) .answer-share { background: rgba(244, 63, 94, 0.22); }
/* "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(--correct); }
.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; }
#quiz-screen.revealing .fun-fact { padding: 12px 14px; margin-bottom: 10px; }
.answer-btn:active { transform: scale(0.98); }
/* The one row that lights up while the clock runs. */
.answer-btn.selected {
  border-color: var(--brand-bright);
  background: linear-gradient(180deg, rgba(168, 85, 247, 0.28), rgba(124, 58, 237, 0.12));
  box-shadow: 0 0 0 1px var(--brand-bright), 0 0 24px var(--brand-glow);
}
/* 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 { color: var(--incorrect); }
.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); }
}

.answer-btn.correct-final {
  border-color: var(--correct);
  background: linear-gradient(180deg, rgba(34, 197, 94, 0.24), rgba(34, 197, 94, 0.08));
  opacity: 1;
}
.answer-btn:disabled { cursor: default; }

/* Nobody taps "C": the letter is how the host and the TV refer to a row, so it
   stays, quietly, and the answer is the target. */
.answer-letter {
  flex: 0 0 auto; font-weight: 900; font-size: 0.62em; color: var(--muted);
  min-width: 1.2em;
  transition: color var(--t-base) ease;
}
.answer-btn.selected .answer-letter { color: var(--brand-bright); }
.answer-btn.correct-final .answer-letter { color: var(--correct); }
.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-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); }
.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); 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); 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 fact is the same stage the TV gives it, at phone size: it waits for the
   answer to have its beat, then comes up as a dark card of its own. */
.fun-fact {
  font-family: var(--font-display);
  font-size: 18px; line-height: 1.35; font-weight: 700;
  text-align: center; text-wrap: balance;
  color: #fff;
  background: radial-gradient(ellipse at 50% 20%, rgb(70, 22, 110), rgb(18, 8, 34) 80%);
  border: 1px solid rgba(255, 255, 255, 0.12);
  padding: 16px 18px 18px; border-radius: var(--r-md); margin: 0 0 14px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  opacity: 0; transform: translateY(10px);
  transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out);
}
#quiz-screen.is-fact .fun-fact { opacity: 1; transform: 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; }
.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-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; }
.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; }
@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; }
  #quiz-screen.revealing .fun-fact { font-size: 15px; padding: 12px 14px; }
}

/* 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,
body.phone-mode .fun-fact { 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; }
/* And the tidbit comes back for the reveal, where the four buttons have already
   said everything they have to say and the only thing left to do is read. */
body.phone-mode #quiz-screen.revealing .fun-fact { display: block; }

/* ------------------------------------------------- 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: var(--correct); }

/* ------------------------------------------------------------ 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 */

/* One moment, the phone's own: what the tap was worth, over the top of the
   answers, then back to the reveal. Rings and numbers, no video. It covers the
   screen but takes no taps: the board chip and the way out of big buttons are
   under it, and four seconds of a control doing nothing reads as a broken one. */
.earned {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; background: radial-gradient(circle at 50% 45%, rgba(76, 29, 149, 0.96), rgba(11, 7, 20, 0.985) 70%);
  animation: earned-in 220ms var(--ease-out);
}
.earned.hidden { display: none; }
@keyframes earned-in { from { opacity: 0; } to { opacity: 1; } }
.earned-label { margin: 0; font-size: clamp(15px, 4.5vmin, 22px); font-weight: 800; color: var(--muted); letter-spacing: 0.14em; text-transform: uppercase; }
.earned-points {
  margin: 0; font-family: var(--font-display); font-weight: 900;
  font-size: clamp(72px, 32vmin, 160px); line-height: 1; color: var(--gold);
  font-variant-numeric: tabular-nums; text-shadow: 0 0 34px rgba(245, 179, 60, 0.35);
  animation: earned-pop 380ms var(--ease-out);
}
.earned.is-zero .earned-points { color: var(--muted); text-shadow: none; }
@keyframes earned-pop {
  from { transform: scale(0.6); opacity: 0; }
  60% { transform: scale(1.06); }
  to { transform: none; opacity: 1; }
}
/* The same rings the TV uses on a moment, at phone scale. */
.earned-rings { position: absolute; width: 1px; height: 1px; }
.earned-rings i {
  position: absolute; left: 50%; top: 50%; width: 60vmin; height: 60vmin;
  margin: -30vmin 0 0 -30vmin; border-radius: 50%;
  border: 3px solid rgba(168, 85, 247, 0.6);
  animation: earned-ring 1.8s ease-out infinite;
}
.earned-rings i:nth-child(2) { animation-delay: 0.6s; }
.earned-rings i:nth-child(3) { animation-delay: 1.2s; }
@keyframes earned-ring {
  from { transform: scale(0.35); opacity: 0.8; }
  to { transform: scale(1.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .earned-rings i, .reading-dots i { animation: none; }
  .earned-points { animation: none; }
}

/* ------------------------------------------------ the question count-in --- */
/* Two seconds before a question lands the reveal goes dark and the phone counts
   it in: a ring pulses in with a "2", again with a "1", then a white flash --
   the frame the buzz fires on -- and the question drops in on top. Everything
   runs on the phone's own clock from the moment it is armed, so the flash and
   the vibration land together whatever the network is doing. 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 {
  position: fixed; inset: 0; z-index: 40; pointer-events: none;
  display: grid; place-items: center; overflow: hidden;
  background: rgba(11, 7, 22, 0.97);
  animation: drop-veil 300ms var(--ease-out) both;
}
.question-drop.hidden { display: none; }
.question-drop > * { grid-area: 1 / 1; }
.drop-ring {
  width: 80vmin; height: 80vmin; border-radius: 50%;
  border: 4px solid var(--brand-bright); opacity: 0;
  box-shadow: 0 0 40px var(--brand-glow), inset 0 0 40px var(--brand-glow);
  animation: drop-pulse 1s cubic-bezier(0.2, 0.8, 0.2, 1) both;
}
.drop-ring:nth-child(2) { border-width: 6px; animation-delay: 1s; }
.drop-num {
  font-size: 44vmin; font-weight: 900; line-height: 1; color: #fff; opacity: 0;
  text-shadow: 0 0 60px var(--brand-glow);
  animation: drop-num 1s ease-out both;
}
.drop-one { animation-delay: 1s; }
.drop-burst {
  width: 20vmin; height: 20vmin; border-radius: 50%; border: 6px solid #fff; opacity: 0;
  animation: drop-burst 450ms cubic-bezier(0.1, 0.9, 0.2, 1) 2s both;
}
.drop-flash {
  position: absolute; inset: 0; background: #fff; opacity: 0;
  animation: drop-flash 350ms ease-out 2s both;
}
/* Before the final question of a game the count-in carries a flashing
   "Last question!" banner above the numbers. */
.drop-last {
  display: none; align-self: start; margin-top: 14vh;
  padding: 10px 22px; border-radius: 999px;
  background: rgba(59, 7, 100, 0.85); border: 2px solid var(--gold, #f5b33c);
  font-weight: 900; font-size: clamp(20px, 6vmin, 34px); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--gold, #f5b33c);
  text-shadow: 0 0 18px rgba(245, 179, 60, 0.9);
}
.question-drop.is-last .drop-last {
  display: block;
  animation: drop-last-flash 0.5s steps(2, jump-none) infinite;
}
@keyframes drop-last-flash { from { opacity: 1; } to { opacity: 0.35; } }
/* The veil lets go on its own once the flash is spent, 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 2.3s both; }
@keyframes drop-veil { from { opacity: 0; } to { opacity: 1; } }
@keyframes drop-veil-out { to { opacity: 0; visibility: hidden; } }
@keyframes drop-pulse {
  0% { transform: scale(1.15); opacity: 0; }
  15% { opacity: 1; }
  100% { transform: scale(0.55); opacity: 0; }
}
@keyframes drop-num {
  0% { transform: scale(1.4); opacity: 0; }
  15% { opacity: 0.95; transform: scale(1); }
  80% { opacity: 0.9; }
  100% { opacity: 0; transform: scale(0.9); }
}
@keyframes drop-burst {
  0% { transform: scale(0.4); opacity: 0; border-width: 12px; }
  8% { opacity: 1; }
  100% { transform: scale(7); opacity: 0; border-width: 1px; }
}
@keyframes drop-flash { 0% { opacity: 0; } 10% { opacity: 0.85; } 100% { opacity: 0; } }

/* 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. */
.kickoff {
  position: fixed; inset: 0; z-index: 38; pointer-events: none;
  display: grid; place-items: center; overflow: hidden;
  background: var(--bg);
  animation: drop-veil 300ms var(--ease-out) both;
}
.kickoff.hidden { display: none; }
.kickoff > * { grid-area: 1 / 1; }
.kickoff-rings { position: relative; width: 70vmin; height: 70vmin; opacity: 0; transition: opacity 400ms; }
.kickoff.is-go .kickoff-rings { opacity: 1; }
.kickoff-ring {
  position: absolute; inset: 0; border-radius: 50%; border: 3px solid var(--brand-bright);
  animation: kickoff-swell 1.5s 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 { 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: var(--muted);
}
.kickoff.is-go .kickoff-label { color: var(--gold); font-size: 30px; }
.kickoff-num {
  font-size: 46vmin; font-weight: 900; line-height: 1; color: #fff;
  text-shadow: 0 0 60px var(--brand-glow);
}
.kickoff.is-go .kickoff-num { color: var(--gold); text-shadow: 0 0 70px rgba(245, 179, 60, 0.7); }
.kickoff-num.is-tick { animation: kickoff-tick 600ms cubic-bezier(0.15, 1.2, 0.3, 1) both; }
@keyframes kickoff-tick {
  0% { transform: scale(1.25); opacity: 0.4; }
  100% { transform: scale(1); opacity: 1; }
}
.kickoff-title { font-size: 16px; font-weight: 800; color: var(--muted); letter-spacing: 0.04em; }
@media (prefers-reduced-motion: reduce) {
  .kickoff, .kickoff-ring, .kickoff-num.is-tick { animation: none; }
}

/* ------------------------------------------------------- first-time tip --- */
.first-tip { z-index: 45; }
.first-tip-card { width: min(420px, 100%); display: grid; gap: 16px; }
.first-tip-list { margin: 0; padding: 0 0 0 22px; display: grid; gap: 10px; font-size: 17px; line-height: 1.35; }
.first-tip-list b { color: var(--gold); }
.first-tip-ok { width: 100%; min-height: 52px; font-size: 18px; }

/* ------------------------------------------------------- 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; }
}
.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; }
