/* ══ Padel Console — deck layout styles ══
   Broadcast rack-unit aesthetic: machined dark steel, hairline seams,
   tally-red for anything on air, condensed industrial type. A fixed
   three-column deck sized for a laptop browser:
     score    — readout · teams (folded) · point keys · undo · highlights
     graphics — program monitor · one row per graphic, each carrying its
                own controls
     stats    — live numbers → beside the scorebug / story strip
   New match (a dialog) sets up each match, Setup (a drawer) holds the
   event-wide settings, and Help (?) explains the deck — the deck itself
   carries no instructions.

   Type: nothing anyone reads is under 14px. The only smaller type is
   the capital section tags (13px) and one-word capital chips — AIR,
   BAR, AUTO — at 12px; capitals at those sizes stand taller than 14px
   lower case. Mono is for numbers and keys only. */

:root {
  /* Steel */
  --steel-0: #0b0c0e;   /* page */
  --steel-1: #121417;   /* panel */
  --steel-2: #191c20;   /* inset (inputs, rows) */
  --steel-3: #22262b;   /* hover */
  --seam: #24282e;
  --seam-strong: #343a42;

  /* Ink */
  --ink: #e8eaed;
  --ink-2: #9aa2ac;
  --ink-3: #808a96;     /* quiet text — still 5:1 on a panel */
  --ink-4: #3d434c;     /* rules, dots, idle marks — never text */

  /* Signals */
  --tally: #ff3d33;              /* ON AIR — the only loud colour */
  --tally-text: #ff6a5f;
  --tally-bg: #2a1210;
  --tally-glow: rgba(255, 61, 51, 0.35);
  --ok: #3fd189;  --ok-bg: #0d2418;
  --warn: #f6b73c; --warn-bg: #251d0a;
  --focus: #5aa2ff; --focus-bg: #12233c;

  /* Type */
  --font-ui: 'Barlow Semi Condensed', system-ui, sans-serif;
  --font-disp: 'Barlow Condensed', var(--font-ui);
  --font-mono: 'IBM Plex Mono', Consolas, monospace;
  --fs-chip: 12px;   /* one-word capital chips */
  --fs-tag: 13px;    /* capital section tags */
  --fs-text: 14px;   /* everything read */
  --fs-ctl: 15px;    /* inputs, selects, row buttons */

  /* Graphics rows: preview height grows with the screen */
  --thumb-h: clamp(62px, 9.4vh, 116px);

  --r: 4px;
  --r-lg: 7px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

/* ── Shell: the deck never scrolls; zones absorb overflow ── */
html, body { height: 100%; }
body {
  font-family: var(--font-ui);
  font-size: var(--fs-text);
  background:
    radial-gradient(140% 90% at 50% -10%, #16181c 0%, var(--steel-0) 55%),
    var(--steel-0);
  color: var(--ink);
  overflow: hidden;
}
#deck { height: 100%; display: flex; flex-direction: column; padding: 10px 12px 12px; gap: 10px; max-width: 1720px; margin: 0 auto; }

/* ── Top bar ── */
.topbar {
  display: flex; align-items: center; gap: 16px;
  background: var(--steel-1); border: 1px solid var(--seam); border-radius: var(--r-lg);
  padding: 8px 12px; flex-shrink: 0;
}
.brandmark {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-disp); font-size: 18px; font-weight: 700;
  letter-spacing: 2.5px; white-space: nowrap;
}
.brandmark em { font-style: normal; color: var(--ink-3); font-weight: 500; }

/* The situation, loudest thing on the bar: match point in tally red,
   set/break/deciding points amber, tiebreaks amber, a quiet "Set 2 in
   play" when nothing hangs on the next point. */
.status {
  flex: 1; min-width: 0; text-align: center;
  font-family: var(--font-disp); font-size: 21px; font-weight: 700; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color 0.2s;
}
.status.quiet { color: var(--ink-3); font-weight: 600; letter-spacing: 2px; }
.status.tiebreak, .status.alert { color: var(--warn); }
.status.match-over { color: var(--ok); }
.status.alert.match-point { color: var(--tally-text); text-shadow: 0 0 14px var(--tally-glow); }

.topbar-right { display: flex; align-items: center; gap: 8px; }
.topbar-gap { width: 1px; height: 22px; background: var(--seam-strong); margin: 0 6px; }

/* Link lights: this console's connection, and whether an encoder is
   showing the latest graphics. Quiet when fine, loud when not. */
.link-pill {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  font-family: var(--font-ui); font-size: var(--fs-text); font-weight: 600; color: var(--ink-2);
  background: var(--steel-2); border: 1px solid var(--seam); border-radius: 999px;
  padding: 4px 12px 4px 10px; cursor: default;
}
.link-pill i { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-4); flex-shrink: 0; }
.link-pill.ok i { background: var(--ok); box-shadow: 0 0 6px rgba(63, 209, 137, 0.6); }
.link-pill.warn { color: var(--warn); border-color: rgba(246, 183, 60, 0.45); background: var(--warn-bg); }
.link-pill.warn i { background: var(--warn); }
.link-pill.bad { color: var(--tally-text); border-color: var(--tally); background: var(--tally-bg); }
.link-pill.bad i { background: var(--tally); animation: pill-blink 1s steps(2, start) infinite; }
@keyframes pill-blink { to { visibility: hidden; } }
.clock {
  font-family: var(--font-mono); font-size: 15px; font-weight: 500; color: var(--ink-2);
  background: var(--steel-2); border: 1px solid var(--seam);
  padding: 4px 12px; border-radius: var(--r); font-variant-numeric: tabular-nums;
}
.btn {
  font-family: var(--font-ui); font-size: var(--fs-text); font-weight: 600; letter-spacing: 0.3px;
  padding: 6px 14px; border-radius: var(--r); cursor: pointer; transition: all 0.15s; white-space: nowrap;
  background: var(--steel-2); border: 1px solid var(--seam-strong); color: var(--ink-2);
}
.btn:hover { color: var(--ink); border-color: var(--ink-3); }
.btn.danger:hover { color: var(--tally-text); border-color: var(--tally); }
/* the one thing to press next: New match on a fresh console, Start in the dialog */
.btn.primary { background: var(--focus); border-color: var(--focus); color: #04101f; }
.btn.primary:hover { color: #04101f; border-color: #8cbcff; background: #7ab4ff; }
.fs-btn { font-size: 16px; padding: 4px 10px; line-height: 1.2; }
.fs-btn.active { color: var(--ink); border-color: var(--ink-3); }

/* ── Deck grid ──
   The side columns take a share of the window, so a laptop screen
   hands its width to the graphics column rather than the score column */
.deck-grid {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: clamp(340px, 26vw, 440px) minmax(0, 1fr) clamp(280px, 21vw, 330px);
  gap: 10px;
}
.zone {
  min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  display: flex; flex-direction: column; gap: 10px; padding-right: 2px;
  scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent;
}
.zone::-webkit-scrollbar, .stats-list::-webkit-scrollbar, .highlight-list::-webkit-scrollbar,
.sponsor-list::-webkit-scrollbar, .drawer-body::-webkit-scrollbar, .modal-body::-webkit-scrollbar { width: 8px; }
.zone::-webkit-scrollbar-track, .stats-list::-webkit-scrollbar-track, .highlight-list::-webkit-scrollbar-track,
.sponsor-list::-webkit-scrollbar-track, .drawer-body::-webkit-scrollbar-track, .modal-body::-webkit-scrollbar-track { background: transparent; }
.zone::-webkit-scrollbar-thumb, .stats-list::-webkit-scrollbar-thumb, .highlight-list::-webkit-scrollbar-thumb,
.sponsor-list::-webkit-scrollbar-thumb, .drawer-body::-webkit-scrollbar-thumb, .modal-body::-webkit-scrollbar-thumb {
  background: var(--seam-strong); border-radius: 4px;
}
@media (max-width: 1100px) {
  body { overflow: auto; }
  .deck-grid { grid-template-columns: 1fr; }
  #deck { height: auto; }
  /* stacked: nothing is height-constrained, so the monitor is a fixed box */
  .zone-air .monitor-panel { flex: 0 0 auto; min-height: 0; max-height: none; }
  .point-buttons { max-height: none; }
}

/* ── Panels ── */
.panel {
  background: linear-gradient(180deg, rgba(255,255,255,0.015), rgba(0,0,0,0)) , var(--steel-1);
  border: 1px solid var(--seam); border-radius: var(--r-lg);
  padding: 10px 12px 12px; flex-shrink: 0;
}
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 10px; min-height: 26px; }
.panel-tag {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-ui); font-size: var(--fs-tag); font-weight: 700;
  color: var(--ink-2); text-transform: uppercase; letter-spacing: 1.6px; white-space: nowrap;
}
.panel-tag::before { content: ""; width: 6px; height: 6px; border-radius: 1px; background: var(--ink-3); }
.link-btn {
  background: none; border: none; cursor: pointer; white-space: nowrap;
  font-family: var(--font-ui); font-size: var(--fs-text); font-weight: 600;
  color: var(--ink-3); transition: color 0.15s;
}
.link-btn:hover { color: var(--ink); }
/* destructive link actions (reset stats, clear all) read as such at rest */
.link-btn.danger { color: #c9675f; }
.link-btn.danger:hover { color: var(--tally-text); }

/* ── Broadcast-styled scoreboard (theme-driven via --o-* vars) ── */
.bug-mimic {
  border-top: 4px solid var(--o-c1, #ffcc08);
  border-bottom: 4px solid var(--o-c1, #ffcc08);
  border-radius: var(--o-radius, 0); overflow: hidden;
}
.bug-mimic .score-row { position: relative; display: flex; align-items: center; gap: 10px; background: var(--o-surface, #000); padding: 6px 8px 6px 0; min-height: 46px; }
/* a county too long for one line wraps to two — both rows then take
   the two-line height so the readout stays a pair (fitNameInput) */
.bug-mimic.tall .score-row { min-height: 54px; }
.bug-mimic .score-row::before {
  content: ""; position: absolute; inset: 0;
  background: var(--o-row-gloss); pointer-events: none; z-index: 1;
}
.bug-mimic .score-row > * { position: relative; z-index: 2; }
.team-color-bar { width: 4px; align-self: stretch; border-radius: 2px; background: var(--focus); }
.team-name-wrap { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; }
/* Serve indicator: always yellow, whatever accent the overlay theme
   uses — the console reads the same in every look */
.serve-dot {
  width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; cursor: pointer;
  background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.3); transition: all 0.2s;
}
.serve-dot.active { background: #ffcc08; border-color: #ffcc08; box-shadow: 0 0 9px rgba(255, 204, 8, 0.85); }
/* The console's own condensed face, not the theme's: a wide display
   font (Montserrat caps) would push "Durham & Cleveland" below
   legibility. fitNameInput() steps the size down from 23px; a name that
   still doesn't fit at 15px wraps to two lines instead of shrinking on. */
.team-name {
  flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; cursor: pointer;
  font-family: var(--font-disp); text-transform: uppercase; letter-spacing: 0.3px;
  font-size: 23px; font-weight: 700; color: var(--o-surface-text, #fff); padding-top: 2px;
  line-height: 1.1; border-bottom: 1px dashed transparent; transition: border-color 0.2s;
}
/* breaks between words only: a word too long for the line overflows,
   and fitNameInput reads that as "smaller" */
.team-name.two-line { white-space: normal; line-height: 1.02; overflow-wrap: normal; }
.team-name:hover { border-bottom-color: rgba(255, 255, 255, 0.3); }
.set-scores { display: flex; gap: 5px; }
.score-cell, .point-cell { display: flex; flex-direction: column; align-items: center; gap: 1px; }
.score-arrow, .point-arrow {
  background: none; border: none; font-size: 13px; line-height: 1; cursor: pointer;
  padding: 2px 6px; transition: color 0.15s, opacity 0.12s; color: rgba(255, 255, 255, 0.55);
}
.point-arrow { padding: 2px 8px; }
.score-arrow:hover, .point-arrow:hover { color: var(--o-c1, #ffcc08); }
.game-score {
  text-align: center; transition: filter 0.15s;
  background: var(--o-cell, #fff); color: var(--o-cell-text, #000);
  font-family: var(--o-font, inherit); font-size: 25px; font-weight: 700;
  min-width: 52px; padding: 4px 8px 2px;
}
.game-score.ad { color: var(--o-alt, #b43030); }
.set-score {
  text-align: center; border: none; outline: none;
  appearance: textfield; -moz-appearance: textfield;
  background: var(--o-c1, #ffcc08); color: var(--o-c1-text, #000);
  font-family: var(--o-font, inherit); font-size: 20px; font-weight: 700;
  width: 34px; padding: 5px 0 3px;
}
.set-score::-webkit-outer-spin-button, .set-score::-webkit-inner-spin-button { -webkit-appearance: none; }
.set-score.current { box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.85); }
.set-score.lost { opacity: 0.55; }
.set-score.future { opacity: 0.3; }

/* ── Fix score: the scoreboard is a readout until you unlock it ──
   Locked (default): no steppers, the numbers don't respond to clicks,
   set cells can't be typed into, set navigation is hidden. A stray click
   during play can't change what's on air. Unlocked: everything shows at
   full opacity — no hover-hunting — and the panel takes an amber edge. */
.fix-switch {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer; user-select: none;
  font-family: var(--font-ui); font-size: var(--fs-text); font-weight: 600;
  color: var(--ink-2); border: 1px solid var(--seam-strong); border-radius: var(--r); padding: 2px 10px;
  transition: all 0.15s;
}
.fix-switch input { display: none; }
.fix-switch::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: var(--ink-4); transition: all 0.15s; }
.fix-switch:hover { color: var(--ink); border-color: var(--ink-3); }
body.fixing .fix-switch { color: var(--warn); border-color: var(--warn); background: var(--warn-bg); }
body.fixing .fix-switch::before { background: var(--warn); box-shadow: 0 0 6px var(--warn); }
body.fixing .score-panel { border-color: var(--warn); box-shadow: 0 0 0 1px var(--warn-bg); }
body:not(.fixing) .score-arrow, body:not(.fixing) .point-arrow { display: none; }
body:not(.fixing) .game-score { cursor: default; }
body:not(.fixing) .set-score { pointer-events: none; }
body:not(.fixing) .set-score.future:not(:hover) { opacity: 0.3; }
body.fixing .game-score { cursor: pointer; }
body.fixing .game-score:hover { filter: brightness(0.9); }
body.fixing .set-score.future:hover, body.fixing .set-score.future:focus { opacity: 0.75; }
.fix-hint {
  display: none; margin-top: 8px; padding: 6px 10px; border-radius: var(--r);
  background: var(--warn-bg); border: 1px solid rgba(246, 183, 60, 0.35);
  color: var(--warn); font-size: var(--fs-text); line-height: 1.4;
}
body.fixing .fix-hint { display: block; }

/* Set label always shows, with the format beside it; the prev/next keys
   are corrections, so they only exist while fixing */
.set-nav { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 9px; min-height: 24px; }
.set-nav button {
  background: transparent; border: 1px solid var(--seam-strong); color: var(--ink-2);
  padding: 3px 10px; border-radius: var(--r); font-size: var(--fs-text); font-family: var(--font-ui);
  cursor: pointer; transition: all 0.15s; white-space: nowrap;
}
body:not(.fixing) .set-nav button { display: none; }
/* while fixing, the set keys need the room the format note takes */
body.fixing .set-note { display: none; }
.set-nav button:hover:not(:disabled) { border-color: var(--ink-3); color: var(--ink); background: var(--steel-2); }
.set-nav button:disabled { opacity: 0.25; cursor: default; }
.set-label { font-family: var(--font-disp); font-size: 17px; font-weight: 700; color: var(--ink); letter-spacing: 1px; text-transform: uppercase; white-space: nowrap; }
.set-note { font-size: var(--fs-text); color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.set-note:not(:empty)::before { content: "·"; margin-right: 10px; color: var(--ink-3); }

/* ── Disclosures: Teams & players, Highlights — folded panels whose
   head row stays live (the graphics switch, the count, clear all) ── */
.disclosure { padding: 0; }
.disc-head { display: flex; align-items: center; gap: 10px; padding: 6px 12px 6px 6px; min-height: 44px; }
.disc-head > :last-child { margin-left: auto; }
.disc-btn {
  display: flex; align-items: center; gap: 8px; background: none; border: none; cursor: pointer;
  color: var(--ink); font-family: var(--font-ui); font-size: var(--fs-ctl); font-weight: 600;
  padding: 4px 6px; border-radius: var(--r); transition: all 0.15s; white-space: nowrap;
}
.disc-btn:hover { background: var(--steel-2); }
.disc-btn .chev { display: inline-block; font-size: 11px; color: var(--ink-3); transition: transform 0.15s; }
.disclosure.open .disc-btn .chev { transform: rotate(90deg); }
.disc-btn .count { font-family: var(--font-mono); font-size: var(--fs-text); color: var(--ink-3); font-weight: 500; }
.disc-body { display: none; padding: 10px 12px 12px; border-top: 1px solid var(--seam); }
.disclosure.open .disc-body { display: block; }

/* A switch with its words: the words are the label, so a click on
   either flips it */
.switch-label {
  display: inline-flex; align-items: center; gap: 10px; cursor: pointer; user-select: none;
  font-size: var(--fs-text); color: var(--ink-2); white-space: nowrap;
}
.switch-label:hover { color: var(--ink); }

.player-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.player-grid input, .team-row input[type="text"] {
  min-width: 0; padding: 6px 9px; background: var(--steel-2);
  border: 1px solid var(--seam); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-ctl); font-family: var(--font-ui); outline: none;
}
.player-grid input:focus, .team-row input[type="text"]:focus { border-color: var(--focus); }
/* One block per team: colour · name · short name, then the players */
.team-block + .team-block { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--seam); }
.team-row { display: flex; align-items: center; gap: 7px; margin-bottom: 6px; }
.team-row .team-name-edit { flex: 1 1 52%; font-weight: 600; }
.team-row .short-edit { flex: 1 1 48%; }
/* Players off the graphics → the names stay stored; dim to say so */
#teamsPanel:has(#showPlayersToggle:not(:checked)) .player-grid { opacity: 0.45; }

/* ── Point keys: the most-used controls, straight under the readout,
   taking the height the column has spare ── */
.point-buttons {
  flex: 1 0 auto; min-height: 110px; max-height: clamp(200px, 34vh, 340px);
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
}
.point-btn {
  position: relative; border: none; border-radius: var(--r-lg); padding: 14px 10px 13px;
  font-family: var(--font-disp); font-size: 34px; font-weight: 700; letter-spacing: 4px;
  cursor: pointer; transition: transform 0.08s, filter 0.15s; color: #fff; min-width: 0;
}
.point-btn:hover { filter: brightness(1.12); }
.point-btn:active { transform: scale(0.975); }
/* the team's name over POINT: up to two lines, so a long county is
   never cut to "Northumberland & T…" on the key that scores for it */
.point-btn .team-label {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
  font-family: var(--font-ui); font-size: 17px; font-weight: 600; line-height: 1.15;
  letter-spacing: 0.3px; margin: 0 auto 4px; opacity: 0.92; text-transform: none;
  max-width: 100%; overflow-wrap: anywhere;
}
.point-btn.flash { animation: btnFlash 0.35s ease; }
@keyframes btnFlash { 0% { filter: brightness(1.7); } 100% { filter: brightness(1); } }

/* Key caps: the only small mono on the deck */
.hotkey-badge {
  position: absolute; top: 8px; right: 9px; font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  background: rgba(0, 0, 0, 0.35); border: 1px solid rgba(255, 255, 255, 0.25);
  padding: 1px 7px; border-radius: 3px; letter-spacing: 0; line-height: 1.35;
}
.actions .hotkey-badge, .tally-cap .hotkey-badge {
  position: static; background: var(--steel-0); border-color: var(--seam-strong); color: var(--ink-2);
}

/* ── Undo / save row ── */
.actions { display: flex; gap: 10px; flex-shrink: 0; }
.actions button {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 9px;
  background: var(--steel-1); border: 1px solid var(--seam-strong); color: var(--ink);
  padding: 11px 10px; border-radius: var(--r-lg); font-size: var(--fs-ctl); font-weight: 600;
  font-family: var(--font-ui); cursor: pointer; transition: all 0.15s;
}
.actions button:hover:not(:disabled) { border-color: var(--ink-3); }
.actions button:disabled { opacity: 0.35; cursor: default; }
/* Undo is the panic key — heavier presence, amber signal on reach */
.actions #undoBtn { flex: 1.5; font-weight: 700; letter-spacing: 0.3px; background: var(--steel-2); }
.actions #undoBtn:hover:not(:disabled) { border-color: var(--warn); color: var(--warn); }
.actions button.flash-confirm { animation: confirmFlash 0.5s ease; }
@keyframes confirmFlash { 0% { border-color: var(--ok); color: var(--ok); } 100% { } }

/* ── Highlights (folded; opens into the column's spare height) ── */
.moments-panel { margin-top: auto; }
.moments-panel.open { flex: 1 1 150px; min-height: 150px; display: flex; flex-direction: column; }
.moments-panel.open .disc-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.highlight-btn-row { margin-bottom: 8px; }
.highlight-btn-row input {
  width: 100%; padding: 7px 10px; background: var(--steel-2);
  border: 1px solid var(--seam); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-ctl); font-family: var(--font-ui); outline: none;
}
.highlight-btn-row input:focus { border-color: var(--focus); }
.highlight-list { flex: 1; min-height: 0; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent; }
.highlight-item {
  display: flex; justify-content: space-between; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: var(--r); font-size: var(--fs-text);
}
.highlight-item:nth-child(odd) { background: var(--steel-2); }
.highlight-item .hl-label { color: var(--focus); font-weight: 600; cursor: pointer; }
.highlight-item .hl-score { font-family: var(--font-mono); font-size: var(--fs-text); color: var(--ink); }
.highlight-item .hl-time { color: var(--ink-3); font-family: var(--font-mono); font-size: var(--fs-text); margin-left: 8px; }
.highlight-item .hl-body { min-width: 0; }
.highlight-item .hl-main { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* who won the point, with the team's colour, and what hung on it */
.highlight-item .hl-win { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-text); font-weight: 600; color: var(--ink); }
.highlight-item .hl-win .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.highlight-item .hl-win em {
  font-style: normal; font-size: var(--fs-chip); font-weight: 700; letter-spacing: 0.8px; text-transform: uppercase;
  color: var(--warn); border: 1px solid rgba(246, 183, 60, 0.4); border-radius: 3px; padding: 0 5px;
}
.highlight-item .hl-sub { margin-top: 2px; color: var(--ink-2); }
.highlight-item .hl-sub .hl-teams { margin-right: 8px; }
.highlight-item .hl-sub .hl-score { color: var(--ink-2); }
.hl-delete {
  background: none; border: none; color: var(--ink-3); cursor: pointer;
  font-size: 18px; line-height: 1; transition: color 0.15s; padding: 0 4px;
}
.hl-delete:hover { color: var(--tally-text); }
.stats-empty { font-size: var(--fs-text); color: var(--ink-3); padding: 8px 2px; line-height: 1.4; }

/* ── Program monitor ──
   Takes the height the graphics rows leave, up to a cap: the rows are
   what the operator works, the monitor is the check on the composite.
   It has first claim on spare height (a flex-grow of 1000 against the
   rows' 1), and whatever is left past its cap goes to the rows' panel.
   (Not a fractional grow on the rows: grow factors summing under 1 take
   only that fraction of the space.) fitMonitor() sizes it to the
   largest 16:9 that fits. */
.zone-air .monitor-panel {
  flex: 1000 1 0; min-height: 170px; max-height: calc(30vh + 52px); overflow: hidden;
  display: flex; flex-direction: column;
}
.zone-air .graphics-panel { flex: 1 0 auto; }
.monitor-panel { padding-bottom: 10px; }
.monitor-panel .panel-head { margin-bottom: 8px; }
/* One line says what viewers can see right now — the names of every
   graphic on air, or that there are none */
.onair-line {
  flex: 1; min-width: 0; text-align: right;
  font-size: var(--fs-text); font-weight: 600; color: var(--ink-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; transition: color 0.2s;
}
.onair-line.on { color: var(--tally-text); }
.onair-beacon {
  font-size: var(--fs-chip); font-weight: 700; letter-spacing: 2px;
  color: var(--ink-3); border: 1px solid var(--seam-strong); border-radius: 3px;
  padding: 2px 8px 1px; transition: all 0.2s; flex-shrink: 0;
}
.onair-beacon.on {
  color: #fff; background: var(--tally); border-color: var(--tally);
  box-shadow: 0 0 14px var(--tally-glow);
  animation: beaconPulse 1.6s ease-in-out infinite;
}
@keyframes beaconPulse { 50% { box-shadow: 0 0 4px var(--tally-glow); } }
.monitor {
  position: relative; overflow: hidden; flex: 1; min-height: 0;
  width: 100%; margin: 0 auto; cursor: pointer;
  border-radius: var(--r); border: 1px solid var(--seam-strong); background: #000;
}
.monitor.sized { flex: none; } /* explicit width/height from fitMonitor() */
.monitor iframe {
  position: absolute; left: 0; top: 0; width: 1920px; height: 1080px;
  border: 0; transform-origin: 0 0; pointer-events: none; background: transparent;
}
/* Idle watermark: black without it reads as broken, not as "nothing cut" */
.monitor::after {
  content: "No graphics on air"; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-text); font-weight: 600; letter-spacing: 1px;
  color: var(--ink-3); opacity: 0; transition: opacity 0.3s; pointer-events: none;
}
.monitor.idle::after { opacity: 1; }

/* ── Graphics: one row per graphic ──
   A row = the cut (preview, name, key — one button) and, beside it, the
   controls that only matter to that graphic. Clicking a control never
   cuts: the two are siblings, not nested. */
.gfx-list { display: flex; flex-direction: column; gap: 8px; }
.cp-frame {
  display: flex; align-items: stretch; min-width: 0;
  border: 1px solid var(--seam); border-radius: var(--r-lg); overflow: hidden;
  background: var(--steel-2); position: relative;
  transition: border-color 0.15s, box-shadow 0.2s;
}
.cp-frame:hover { border-color: var(--seam-strong); }
.cp-frame.live { border-color: var(--tally); box-shadow: 0 0 0 1px var(--tally), 0 0 16px var(--tally-glow); }
.cut {
  flex: 0 0 auto; display: flex; align-items: stretch; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.cut:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.cp-view {
  display: block; overflow: hidden; position: relative; background: #0d0e10;
  width: calc(var(--thumb-h) * 2.3); height: var(--thumb-h); align-self: center;
}
.cp-view iframe {
  border: 0; display: block; pointer-events: none;
  /* width/height/scale set per row by fitTiles(): each overlay page
     gets a FIXED viewport sized to its graphic, so the preview shows the
     true layout at any window size */
  transform-origin: 0 0;
}
/* Off air = dimmed preview, so the live ones read from across the
   room. Hover restores it so a graphic can be checked before it is cut. */
.cp-frame:not(.live) .cp-view { filter: brightness(0.55); transition: filter 0.15s; }
.cp-frame:not(.live) .cut:hover .cp-view { filter: brightness(0.9); }
/* A look's art pack can retire the matchup graphic (County Cup: the
   lower third IS the matchup and the board covers "coming up") — its
   mode and URL button go — and its boards artwork can carry its own
   title, so there is none to type. */
body.retire-versus .cp-versus, body.retire-versus .ctx-versus, body.retire-versus .ol-versus, body.boards-untitled .title-only { display: none; }
.tally-cap {
  width: 124px; display: flex; flex-direction: column; justify-content: center; gap: 7px;
  padding: 8px 12px; border-left: 1px solid var(--seam); background: var(--steel-1);
}
.tally-name {
  font-size: var(--fs-text); font-weight: 700; line-height: 1.15;
  letter-spacing: 1px; text-transform: uppercase; color: var(--ink);
  overflow: hidden; overflow-wrap: anywhere; max-height: 2.3em;
}
.cp-frame.live .tally-name { color: var(--tally-text); }
.tally-keys { display: flex; align-items: center; gap: 6px; min-height: 22px; }
.air-chip {
  display: none; font-size: var(--fs-chip); font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase;
  color: #fff; background: var(--tally); border-radius: 3px; padding: 1px 6px;
}
.cp-frame.live .air-chip { display: inline-block; }

/* Per-row controls */
.tile-ctl {
  flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 7px;
  padding: 8px 12px; border-left: 1px solid var(--seam);
}
.ctl-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.tile-ctl .ctl-row { min-height: 32px; }
.ctl-label { font-size: var(--fs-text); font-weight: 600; color: var(--ink-2); white-space: nowrap; }
.ctl-row .ctl-label { flex: 1; }
.ctl-value { font-size: var(--fs-text); color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.ctl-value.wrap { white-space: normal; line-height: 1.35; }
body:has(#badgeEnabledToggle:not(:checked)) #bugBarNote { color: var(--ink-3); }
.tile-ctl input[type="text"], .tile-ctl select {
  flex: 1; min-width: 0; height: 32px; padding: 3px 9px; background: var(--steel-1);
  border: 1px solid var(--seam-strong); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-text); font-family: var(--font-ui); outline: none;
}
.tile-ctl select { cursor: pointer; }
.tile-ctl input[type="text"].narrow { flex: 0 1 40%; }
.tile-ctl input[type="text"]:focus, .tile-ctl select:focus { border-color: var(--focus); }
/* Mode-scoped fields: a text box shows only while the mode that reads
   it is selected (board → Event or Coming up) */
.ctx-board-match { display: none; }
body.board-match .ctx-board-match { display: flex; }
body.board-match .ctx-board-event { display: none; }

/* The lower-third row: three overlay previews stacked in one view, the
   selected mode's shown; the mode's own field under the switch.
   body.slot-<mode> is set by renderSlot(). */
.cp-slot .cp-view iframe { display: none; }
body.slot-story #cpStory, body.slot-match #cpL3, body.slot-text #cpL3, body.slot-versus #cpVersus { display: block; }
.cp-slot .slot-story, .cp-slot .slot-match, .cp-slot .slot-text, .cp-slot .slot-versus { display: none; }
body.slot-story .cp-slot .slot-story, body.slot-match .cp-slot .slot-match,
body.slot-text .cp-slot .slot-text, body.slot-versus .cp-slot .slot-versus { display: flex; }
/* selected mode differs from what is live: a chip on the preview says
   what is live (never a row — the row's height must not move) */
.slot-chip {
  position: absolute; top: 4px; right: 4px; z-index: 2;
  font-size: var(--fs-chip); font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  color: #fff; background: var(--tally); border-radius: 3px; padding: 1px 6px; white-space: nowrap;
}
.slot-chip:empty { display: none; }

/* Uploaded graphics' rows */
.customs-tiles { display: contents; }
.cp-custom .cp-view img { width: 100%; height: 100%; object-fit: contain; display: block; }
.cp-custom .tile-ctl { flex-direction: row; align-items: center; justify-content: space-between; }
.cp-custom .ctl-value { color: var(--ink-2); }

/* ── Segmented controls ── */
.seg { display: flex; gap: 4px; flex-wrap: wrap; }
.seg button {
  padding: 5px 12px; font-size: var(--fs-text); font-family: var(--font-ui); font-weight: 600;
  cursor: pointer; white-space: nowrap;
  background: var(--steel-1); border: 1px solid var(--seam-strong);
  border-radius: var(--r); color: var(--ink-2); transition: all 0.15s;
}
.seg button:hover { color: var(--ink); border-color: var(--ink-3); }
.seg button.active { background: var(--focus-bg); border-color: var(--focus); color: #cfe2ff; }

/* ── Toggles ── */
.toggle { position: relative; display: inline-block; width: 40px; height: 22px; cursor: pointer; flex-shrink: 0; }
.toggle input { display: none; }
.toggle .slider {
  position: absolute; inset: 0; background: var(--steel-3); border-radius: 11px;
  border: 1px solid var(--seam-strong);
  transition: all 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.toggle .slider::before {
  content: ""; position: absolute; width: 14px; height: 14px; border-radius: 50%;
  background: var(--ink-3); top: 3px; left: 3px;
  transition: all 0.22s cubic-bezier(0.22, 1, 0.36, 1);
}
.toggle input:checked + .slider { background: var(--focus-bg); border-color: var(--focus); }
.toggle input:checked + .slider::before { background: var(--focus); transform: translateX(18px); }

/* ── Stats zone ── */
.zone-stats { display: flex; }
.zone-stats .stats-section { flex: 1; min-height: 140px; display: flex; flex-direction: column; }
/* Destination tabs: a stat goes beside the scorebug or out as the
   story strip — the tab names the graphic, not the mechanism */
.dest-seg { display: grid; grid-template-columns: 1fr 1fr; gap: 4px; margin-bottom: 10px; }
.dest-seg button { padding: 7px 8px; }
.stats-list {
  flex: 1; min-height: 50px; overflow-y: auto; display: flex; flex-direction: column; gap: 3px;
  scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent;
}
.stat-row, .stats-auto-row {
  display: grid; grid-template-columns: 1fr auto auto auto; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: var(--r); background: var(--steel-2);
  border: 1px solid transparent;
}
.stats-auto-row {
  grid-template-columns: 1fr auto auto; margin-bottom: 6px; cursor: pointer;
  background: transparent; border: 1px dashed var(--seam-strong);
}
.stats-auto-row:hover { border-color: var(--ink-3); }
.stats-auto-row.active { border-style: solid; border-color: var(--focus); background: var(--focus-bg); }
.stats-auto-row.live { border-style: solid; border-color: var(--tally); background: var(--tally-bg); }
.stats-auto-row .stat-label em {
  font-style: normal; font-size: var(--fs-chip); font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase;
  color: var(--ink-3); margin-left: 6px;
}
.stats-auto-row.live .stat-value { color: var(--tally-text); }
/* Custom text: the operator's own words on the bar, one row up from
   the stats so it is one click away mid-match */
.custom-text-row { grid-template-columns: 1fr auto auto; margin-bottom: 10px; padding: 5px 8px 5px 5px; }
.custom-text-row input {
  min-width: 0; height: 32px; padding: 3px 9px; background: var(--steel-1);
  border: 1px solid var(--seam-strong); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-text); font-family: var(--font-ui); outline: none;
}
.custom-text-row input:focus { border-color: var(--focus); }
.custom-text-row.live { background: var(--tally-bg); border-color: var(--tally); }
.custom-text-row .row-state:empty { display: none; }
/* Row text wraps rather than truncates: the rows ARE the on-air text,
   and a clipped "Holds Durham & Cleveland 4/10…" hides what is live */
.stat-label { min-width: 0; font-size: var(--fs-text); color: var(--ink-2); line-height: 1.3; overflow-wrap: anywhere; }
.stat-value { font-family: var(--font-mono); font-size: var(--fs-text); color: var(--ink); font-weight: 600; white-space: nowrap; }

/* Tabbed rows: the scorebug tab shows the stat and its value, the
   story tab the head-to-head pairs. Whole row is the control; on air =
   tally red. */
.stat-row.badge-row { grid-template-columns: 1fr auto auto auto; cursor: pointer; }
/* Group headings break the sheet into Points · Serve · Big points · Match */
.stat-group {
  font-size: var(--fs-tag); font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase;
  color: var(--ink-3); padding: 12px 2px 3px;
}
.stat-group:first-child { padding-top: 2px; }
.stat-row.live .stat-label { color: var(--ink); }
/* the live row also shows the exact words on air */
.stat-air {
  grid-column: 1 / -1; font-size: var(--fs-text); line-height: 1.35;
  color: var(--tally-text); overflow-wrap: anywhere;
}
.stat-air::before { content: attr(data-where); color: var(--ink-3); }
/* story rows: the two sides' numbers with their team colours */
.stat-pair { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono); font-size: var(--fs-text); font-weight: 600; color: var(--ink); white-space: nowrap; }
.stat-pair .dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; margin-left: 8px; flex-shrink: 0; }
.stat-pair .dot:first-child { margin-left: 0; }
.stat-value .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-left: 6px; vertical-align: 1px; }
.stat-label .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 7px; vertical-align: 1px; }
.dot.a { background: var(--team-a, #6366f1); }
.dot.b { background: var(--team-b, #ef4444); }
.row-state:empty { display: none; }
/* rows that show as text on the bar rather than beside the bug say so */
.dest-tag {
  font-style: normal; font-size: var(--fs-chip); font-weight: 700; letter-spacing: 1px; text-transform: uppercase;
  color: var(--ink-3); border: 1px solid var(--seam-strong); border-radius: 3px; padding: 0 5px; margin-left: 7px;
  vertical-align: 1px; white-space: nowrap;
}
.stat-row.story-row { grid-template-columns: 1fr auto auto auto; cursor: pointer; }
.stat-row.badge-row:hover, .stat-row.story-row:hover { border-color: var(--seam-strong); }
.row-state {
  font-size: var(--fs-chip); font-weight: 700;
  letter-spacing: 1.2px; color: var(--tally-text); white-space: nowrap;
}
.stat-row.badge-row.live, .stat-row.story-row.live {
  background: var(--tally-bg); border-color: var(--tally);
}
.stat-pin {
  background: var(--steel-0); border: 1px solid var(--seam-strong); color: var(--ink-2);
  font-size: 13px; font-family: var(--font-mono);
  padding: 2px 8px; border-radius: 3px; cursor: pointer; transition: all 0.15s; white-space: nowrap;
}
.stat-pin:hover { border-color: var(--focus); color: var(--ink); }
.stat-row.active .stat-pin { background: var(--focus); color: #fff; border-color: var(--focus); }
/* "8s" timed buttons: faint at rest where there is a pointer (a column
   of identical buttons is noise), half-visible on touch (the courtside
   iPad has no hover), armed = tally red while counting down */
.stat-pin.timed-btn { min-width: 34px; text-align: center; }
.stat-row .stat-pin.timed-btn { opacity: 0.45; transition: opacity 0.12s, border-color 0.15s, color 0.15s; }
@media (hover: none) { .stat-row .stat-pin.timed-btn { opacity: 0.6; } }
.stat-row:hover .stat-pin.timed-btn, .stat-row:focus-within .stat-pin.timed-btn { opacity: 1; }
.stat-row .stat-pin.timed-btn.armed { opacity: 1; background: var(--tally); border-color: var(--tally); color: #fff; }

/* ── Drawers (Setup, Matches) ── */
.drawer-backdrop {
  position: fixed; inset: 0; background: rgba(5, 6, 8, 0.6);
  opacity: 0; pointer-events: none; transition: opacity 0.22s; z-index: 50;
}
.drawer-backdrop.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 480px; max-width: 92vw;
  background: var(--steel-1); border-left: 1px solid var(--seam-strong);
  box-shadow: -18px 0 40px rgba(0, 0, 0, 0.5);
  transform: translateX(102%); transition: transform 0.24s cubic-bezier(0.2, 0.85, 0.25, 1);
  z-index: 60; display: flex; flex-direction: column;
}
.drawer.open { transform: none; }
.drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 18px; border-bottom: 1px solid var(--seam); flex-shrink: 0;
}
.drawer-body { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 18px 20px; scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent; }
.drawer-sec { padding: 16px 0 8px; border-bottom: 1px solid var(--seam); }
.drawer-sec:last-child { border-bottom: none; }
.sec-tag {
  font-size: var(--fs-tag); font-weight: 700;
  color: var(--ink-2); text-transform: uppercase; letter-spacing: 1.6px; margin-bottom: 10px;
}
.summary-note { color: var(--ink-3); font-weight: 500; letter-spacing: 0.3px; text-transform: none; font-size: var(--fs-text); margin-left: 4px; }

.select-row { display: flex; gap: 8px; margin-bottom: 8px; }
.select-row select, .nm-row select {
  flex: 1; min-width: 0; background: var(--steel-2); border: 1px solid var(--seam-strong);
  color: var(--ink); padding: 7px 9px; border-radius: var(--r);
  font-size: var(--fs-ctl); font-family: var(--font-ui); outline: none; cursor: pointer;
}
.select-row select:focus, .nm-row select:focus { border-color: var(--focus); }

.setting-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 8px 0; }
/* scorebug shape switch: only meaningful under the County Cup look */
.bug-style-row { display: none; }
body.theme-cc .bug-style-row { display: flex; }
.setting-row + .setting-row { border-top: 1px solid var(--seam); }
.setting-label { font-size: var(--fs-text); color: var(--ink-2); }

.sponsor-add-row { display: flex; gap: 8px; margin: 12px 0 8px; }
.sponsor-add-row input {
  flex: 1; min-width: 0; padding: 7px 10px; background: var(--steel-2);
  border: 1px solid var(--seam); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-ctl); outline: none; font-family: var(--font-ui);
}
.sponsor-add-row input:focus { border-color: var(--focus); }
.sponsor-add-row button {
  background: var(--steel-2); border: 1px solid var(--seam-strong); color: var(--ink-2);
  padding: 7px 16px; border-radius: var(--r); font-size: var(--fs-text); font-weight: 600;
  font-family: var(--font-ui); cursor: pointer; transition: all 0.15s;
}
.sponsor-add-row button:hover { border-color: var(--focus); color: var(--ink); }
.sponsor-list { display: flex; flex-direction: column; gap: 4px; max-height: 260px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent; }
.sponsor-row {
  display: grid; grid-template-columns: auto 1fr auto auto auto; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: var(--r); background: var(--steel-2);
}
.sponsor-row.off { opacity: 0.45; }
.sponsor-row .sponsor-name {
  min-width: 0; background: transparent; border: none; outline: none;
  color: var(--ink); font-size: var(--fs-text); font-family: var(--font-ui);
  border-bottom: 1px dashed transparent; transition: border-color 0.2s;
}
.sponsor-row .sponsor-name:hover, .sponsor-row .sponsor-name:focus { border-bottom-color: var(--seam-strong); }
.sponsor-row select {
  max-width: 130px; background: var(--steel-0); border: 1px solid var(--seam-strong);
  color: var(--ink-2); font-size: var(--fs-text); padding: 3px 5px;
  border-radius: 3px; outline: none; cursor: pointer; font-family: var(--font-ui);
}
.mini-btn {
  background: var(--steel-0); border: 1px solid var(--seam-strong); color: var(--ink-2);
  font-family: var(--font-ui); font-size: var(--fs-text); font-weight: 600;
  padding: 3px 10px; border-radius: var(--r); cursor: pointer; transition: all 0.15s; white-space: nowrap;
}
.mini-btn:hover { border-color: var(--focus); color: var(--ink); }
.sponsor-hint { font-size: var(--fs-text); color: var(--ink-3); margin-top: 10px; line-height: 1.5; }
.sponsor-hint strong { color: var(--ink-2); }
.sponsor-hint code { font-family: var(--font-mono); font-size: 13px; color: var(--ink-2); }

/* ── Matches drawer: the archive, downloads, restore ── */
.matches-drawer { width: 580px; }
.match-list { display: flex; flex-direction: column; gap: 6px; }
.match-row {
  display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; align-items: center;
  padding: 10px 12px; border-radius: var(--r); background: var(--steel-2); border: 1px solid var(--seam);
}
.match-row.on-console { border-color: var(--focus); }
.match-row .m-teams { font-size: var(--fs-ctl); font-weight: 600; color: var(--ink); }
.match-row .m-teams .won { color: var(--ok); }
.match-row .m-teams .won::after { content: " ✓"; }
.match-row .m-score { font-family: var(--font-mono); font-size: var(--fs-text); color: var(--ink-2); font-variant-numeric: tabular-nums; }
.match-row .m-score em { font-family: var(--font-ui); font-style: normal; color: var(--warn); margin-left: 6px; }
.match-row .m-meta { grid-column: 1 / -1; font-size: var(--fs-text); color: var(--ink-3); }
.match-row .m-actions { grid-column: 1 / -1; display: flex; gap: 6px; flex-wrap: wrap; margin-top: 3px; }
.match-row .m-actions button {
  padding: 5px 11px; font-size: var(--fs-text); font-family: var(--font-ui); cursor: pointer;
  background: var(--steel-1); border: 1px solid var(--seam-strong); border-radius: var(--r); color: var(--ink-2);
}
.match-row .m-actions button:hover { border-color: var(--focus); color: var(--ink); }
.match-row .m-actions button.restore { border-color: var(--focus); color: var(--ink); }
.match-row .m-actions .hl-delete { margin-left: auto; border: none; background: none; font-size: 18px; }
.drawer-sec .wide-btn {
  width: 100%; padding: 9px; font-size: var(--fs-text); font-family: var(--font-ui); cursor: pointer;
  background: var(--steel-2); border: 1px solid var(--seam-strong); border-radius: var(--r); color: var(--ink-2);
}
.drawer-sec .wide-btn:hover { border-color: var(--focus); color: var(--ink); }

/* ── Toast: what just happened (a match kept, a restore) ── */
.toast {
  position: fixed; left: 50%; bottom: 18px; transform: translate(-50%, 20px); z-index: 450;
  max-width: min(92vw, 640px); display: flex; align-items: center; gap: 12px;
  background: var(--steel-3); border: 1px solid var(--seam-strong); color: var(--ink);
  padding: 11px 15px; border-radius: var(--r-lg); font-size: var(--fs-ctl); line-height: 1.4;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
  opacity: 0; pointer-events: none; transition: opacity 0.2s, transform 0.2s;
}
.toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast b { font-weight: 700; }
.toast .link-btn { color: var(--focus); font-size: var(--fs-ctl); }

/* ── Auth banner: saves are being rejected (key missing/wrong) ── */
.auth-banner {
  display: none; position: fixed; left: 50%; transform: translateX(-50%); top: 10px;
  z-index: 400; max-width: min(92vw, 580px);
  background: #6e1616; border: 1px solid #c24040; color: #ffd9d9;
  padding: 9px 16px; border-radius: var(--r); font-size: var(--fs-text); line-height: 1.4;
  cursor: pointer; box-shadow: 0 6px 22px rgba(0, 0, 0, 0.45);
}
.auth-banner.show { display: block; }
.auth-banner:hover { background: #7e1a1a; }

/* ── Access key input (setup drawer) ── */
.player-pair { display: flex; gap: 8px; margin-top: 8px; }
.player-pair input {
  flex: 1; min-width: 0; padding: 7px 10px; background: var(--steel-2);
  border: 1px solid var(--seam); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-ctl); font-family: var(--font-ui); outline: none;
}
.player-pair input:focus { border-color: var(--focus); }

.overlay-link-row { display: flex; gap: 6px; flex-wrap: wrap; }
.overlay-link-row button {
  flex: 1; min-width: 84px; padding: 7px 8px; font-size: var(--fs-text); cursor: pointer; text-align: center;
  background: var(--steel-2); border: 1px solid var(--seam-strong); font-family: var(--font-ui);
  border-radius: var(--r); color: var(--ink-2); transition: all 0.15s;
}
.overlay-link-row button:hover { border-color: var(--focus); color: var(--ink); }

/* Team colour swatches, inline beside the name inputs */
.team-swatch {
  width: 22px; height: 22px; padding: 0; flex-shrink: 0;
  border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 50%;
  background: none; cursor: pointer;
}
.team-swatch::-webkit-color-swatch-wrapper { padding: 0; }
.team-swatch::-webkit-color-swatch { border: none; border-radius: 50%; }

.hotkey-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; }
.hotkey-row + .hotkey-row { border-top: 1px solid var(--seam); }
.hotkey-label { font-size: var(--fs-text); color: var(--ink-2); }
.hotkey-capture {
  min-width: 56px; background: var(--steel-2); border: 1px solid var(--seam-strong);
  color: var(--ink); font-family: var(--font-mono); font-size: 13px; font-weight: 600;
  padding: 4px 10px; border-radius: var(--r); cursor: pointer; transition: all 0.15s;
}
.hotkey-capture:hover { border-color: var(--focus); }
.hotkey-capture.listening { border-color: var(--warn); color: var(--warn); animation: listenPulse 1s ease-in-out infinite; }
@keyframes listenPulse { 50% { opacity: 0.6; } }

/* ── Help sheet: ? toggles, Esc closes — how the deck works and the
   live bindings, for whoever is covering the console ── */
.hk-sheet {
  position: fixed; inset: 0; z-index: 70; display: none; align-items: center; justify-content: center;
  background: rgba(5, 6, 8, 0.7); padding: 20px;
}
.hk-sheet.open { display: flex; }
.hk-card {
  width: min(94vw, 600px); max-height: calc(100vh - 40px); overflow-y: auto;
  background: var(--steel-1); border: 1px solid var(--seam-strong); border-radius: 10px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6); padding: 16px 22px 18px;
  scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent;
}
.hk-how { display: grid; grid-template-columns: max-content 1fr; gap: 9px 16px; margin: 4px 0 6px; }
.hk-how dt { font-size: var(--fs-text); font-weight: 700; color: var(--ink); }
.hk-how dd { font-size: var(--fs-text); color: var(--ink-2); line-height: 1.45; }
.hk-how b { color: var(--ink); font-weight: 600; }
.hk-grid { display: grid; grid-template-columns: 1fr auto; align-items: center; }
.hk-grid > div { padding: 7px 0; border-top: 1px solid var(--seam); font-size: var(--fs-text); color: var(--ink-2); }
.hk-grid .hk-group {
  grid-column: 1 / -1; padding: 16px 0 5px; border-top: none;
  font-size: var(--fs-tag); font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase; color: var(--ink-2);
}
.hk-grid .hk-group + div, .hk-grid .hk-group + div + div { border-top: none; }
.hk-grid .hk-key {
  justify-self: end; font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--ink);
  background: var(--steel-2); border: 1px solid var(--seam-strong); border-radius: 3px;
  padding: 2px 9px; min-width: 40px; text-align: center;
}
.hk-foot { margin-top: 14px; font-size: var(--fs-text); color: var(--ink-3); line-height: 1.5; }

/* ── New match: teams → format → check the graphics → start ── */
.modal {
  position: fixed; inset: 0; z-index: 80; display: flex; align-items: center; justify-content: center;
  background: rgba(5, 6, 8, 0.72); padding: 20px;
}
.modal[hidden] { display: none; }
.modal-card {
  width: min(94vw, 780px); max-height: calc(100vh - 40px); display: flex; flex-direction: column;
  background: var(--steel-1); border: 1px solid var(--seam-strong); border-radius: 10px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6);
}
.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 22px; border-bottom: 1px solid var(--seam); flex-shrink: 0;
}
.modal-head h2 { font-family: var(--font-disp); font-size: 24px; font-weight: 700; letter-spacing: 1.2px; text-transform: uppercase; }
.modal-body {
  flex: 1; min-height: 0; overflow-y: auto; padding: 4px 22px 14px;
  scrollbar-width: thin; scrollbar-color: var(--seam-strong) transparent;
}
.modal-foot {
  display: flex; align-items: center; gap: 10px; padding: 14px 22px;
  border-top: 1px solid var(--seam); flex-shrink: 0;
}
.modal-foot .btn { font-size: var(--fs-ctl); padding: 8px 18px; }
.nm-keep { flex: 1; min-width: 0; font-size: var(--fs-text); color: var(--ink-3); line-height: 1.4; }
.nm-sec { padding: 16px 0 8px; }
.nm-sec + .nm-sec { border-top: 1px solid var(--seam); }
/* one team = colour · name · short name, then its two players under the names */
.nm-team {
  display: grid; grid-template-columns: 26px minmax(0, 1.3fr) minmax(0, 1fr); gap: 6px 8px;
  align-items: center; margin-bottom: 12px;
}
.nm-team .nm-player { grid-row: 2; }
.nm-team .nm-player:nth-child(4) { grid-column: 2; }
.nm-team .nm-player:nth-child(5) { grid-column: 3; }
.nm-team input[type="text"] {
  min-width: 0; height: 36px; padding: 4px 10px; background: var(--steel-2);
  border: 1px solid var(--seam-strong); border-radius: var(--r);
  color: var(--ink); font-size: var(--fs-ctl); font-family: var(--font-ui); outline: none;
}
.nm-team input[type="text"]:focus { border-color: var(--focus); }
.nm-team .nm-name { font-size: 16px; font-weight: 700; }
.nm-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 2px 0 12px; }
.nm-row select { flex: 0 1 260px; }
.nm-label { font-size: var(--fs-text); font-weight: 600; color: var(--ink-2); }
.nm-spacer { flex: 1; }
.nm-format select { flex: 1 1 0; }
.nm-previews { display: grid; gap: 8px; margin: 2px 0 12px; }
.nm-prev {
  position: relative; overflow: hidden; border-radius: var(--r); border: 1px solid var(--seam-strong);
  background: radial-gradient(120% 140% at 30% 20%, #25303d 0%, #10151c 60%, #0a0d12 100%);
}
#nmBugBox { height: 100px; }
#nmL3Box { height: 132px; }
.nm-prev iframe { position: absolute; left: 0; top: 0; border: 0; transform-origin: 0 0; pointer-events: none; background: transparent; }

/* ── QR codes: two links to scan, side by side ── */
.qr-card { width: min(94vw, 720px); }
.qr-body { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; padding: 18px 22px 22px; }
@media (max-width: 640px) { .qr-body { grid-template-columns: 1fr; } }
.qr-fig { display: flex; flex-direction: column; gap: 12px; }
.qr-code { background: #fff; border-radius: 8px; padding: 6px; }
.qr-code svg { display: block; width: 100%; height: auto; }
.qr-fig figcaption { display: flex; flex-direction: column; gap: 5px; font-size: var(--fs-text); color: var(--ink-2); line-height: 1.45; }
.qr-fig figcaption b { font-size: var(--fs-ctl); color: var(--ink); }
.qr-fig figcaption .link-btn { align-self: flex-start; color: var(--focus); padding: 0; margin-top: 2px; }

/* ── Who's serving (Scoring: Servers, Full stats) ──
   Over the point keys: the serving team's two players, the server lit
   in the serve dot's yellow. Amber while it asks — a team's first serve
   of a set — with the order's guess outlined. */
.serve-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; padding: 7px 10px;
  border-left: 4px solid var(--team-a, var(--focus));
}
.serve-row.team-b { border-left-color: var(--team-b, var(--tally)); }
.serve-row[hidden] { display: none; }
.serve-q {
  flex: 1 1 auto; min-width: 0; font-size: var(--fs-tag); font-weight: 700; letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--ink-2); transition: color 0.2s;
}
.serve-row.ask { border-color: var(--warn); background: var(--warn-bg); }
.serve-row.ask .serve-q { color: var(--warn); letter-spacing: 0.6px; text-transform: none; font-size: var(--fs-ctl); }
.serve-players { display: flex; gap: 6px; flex: 0 1 auto; min-width: 0; }
.serve-players button {
  display: inline-flex; align-items: center; gap: 7px; min-width: 0; max-width: 170px; padding: 6px 12px;
  font-family: var(--font-disp); font-size: 17px; font-weight: 700; letter-spacing: 0.4px; text-transform: uppercase;
  background: var(--steel-2); border: 1px solid var(--seam-strong); border-radius: var(--r);
  color: var(--ink-2); cursor: pointer; transition: all 0.15s; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.serve-players button::before { content: ""; width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--ink-4); }
.serve-players button:hover { border-color: var(--ink-3); color: var(--ink); }
.serve-players button.on { color: var(--ink); border-color: #ffcc08; }
.serve-players button.on::before { background: #ffcc08; box-shadow: 0 0 7px rgba(255, 204, 8, 0.8); }
.serve-players button.guess { color: var(--ink); border: 1px dashed var(--warn); }
.serve-players button.guess::before { background: var(--warn); }

/* ── The court (Scoring: Full stats) ──
   Over the actions row: the court as the camera sees it (court.js), and
   under it only the server's ace and double fault, Forced after an
   error, and ⋯ for the rest. The point keys give way to the court's own
   end strips. */
.court-panel { display: flex; flex-direction: column; gap: 8px; padding: 8px; }
.court-panel[hidden] { display: none; }
#deskCourt {
  height: clamp(270px, calc(100vh - 520px), 440px);
  --cm-font: var(--font-disp); --cm-name-size: 15px; --cm-key-w: 46px; --cm-key-h: 36px; --ce-h: 28px; --cm-kbd-font: var(--font-mono);
}
.court-shots { display: flex; gap: 6px; }
.court-shots button {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px; flex: 1 1 auto; min-width: 0; min-height: 34px; padding: 4px 10px;
  font-family: var(--font-ui); font-size: var(--fs-text); font-weight: 600; white-space: nowrap;
  background: var(--steel-2); border: 1px solid var(--seam-strong); border-radius: var(--r); color: var(--ink); cursor: pointer; transition: all 0.15s;
}
.court-shots button:hover:not(:disabled) { border-color: var(--ink-3); }
.court-shots button:disabled { opacity: 0.35; cursor: default; }
.court-shots button[hidden] { display: none; }
.court-shots .dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--ink-3); }
.court-shots .ce-key { margin-left: 2px; }
.court-shots .more { flex: 0 0 auto; font-size: 20px; line-height: 1; padding: 0 12px; position: relative; }
.court-shots .more.note::after { content: ""; position: absolute; top: 5px; right: 5px; width: 7px; height: 7px; border-radius: 50%; background: var(--warn); }
#courtFixBtn[aria-expanded="true"] { border-color: var(--focus); }
#forcedBtn.active { background: var(--focus-bg); border-color: var(--focus); color: #cfe2ff; }
.court-fix { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 4px 14px; }
.court-fix[hidden], .court-fix [hidden] { display: none; }
/* the court's end strips are the plain point keys now */
body.court-on .point-buttons { display: none; }
/* the Setup drawer's and New match's level switches, and what each means */
.scoring-seg { display: flex; }
.scoring-seg button { flex: 1; }
.scoring-note { margin-top: 8px; font-size: var(--fs-text); color: var(--ink-3); line-height: 1.45; }
.nm-scoring-row { flex-wrap: nowrap; align-items: flex-start; }
.nm-scoring-row .seg { flex-shrink: 0; }
.nm-note { flex: 1; min-width: 0; font-size: var(--fs-text); color: var(--ink-3); line-height: 1.4; }
.nm-note.warn { color: var(--warn); }
/* ── Named by the players (display.js): no team names to type — each
   side is its pair's surnames ── */
.name-mode-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 2px 0 10px; }
body.names-players .team-name-edit { display: none; }
body.names-players .team-row .short-edit { flex: 1; }
.nm-names-row .sec-tag { margin-bottom: 0; }
#newMatchModal.nm-players .nm-name { display: none; }
.hk-card .hk-guide { margin-left: auto; margin-right: 14px; text-decoration: none; }
.setting-label small { display: block; margin-top: 2px; font-size: var(--fs-text); color: var(--ink-3); line-height: 1.4; }

/* ── Brand kit (Setup → Look) ── */
.brand-kit { border-top: 1px solid var(--seam); margin-top: 4px; }
.brand-body { padding-bottom: 4px; }
.brand-body[hidden] { display: none; }
.brand-colours { display: flex; align-items: center; gap: 16px; padding: 4px 0 10px; }
.brand-colour { display: inline-flex; align-items: center; gap: 8px; font-size: var(--fs-text); color: var(--ink-2); cursor: pointer; }
.brand-colour .team-swatch { width: 26px; height: 26px; }
.brand-colours .mini-btn { margin-left: auto; }
.brand-colours .mini-btn:disabled { opacity: 0.4; cursor: default; }
.brand-note {
  font-size: var(--fs-text); color: var(--warn); line-height: 1.45;
  padding: 7px 10px; margin: 0 0 10px; border-radius: var(--r);
  background: rgba(255, 179, 71, 0.08); border: 1px solid rgba(255, 179, 71, 0.25);
}
.brand-note[hidden] { display: none; }
.brand-kit .select-row .mini-btn { padding: 0 14px; }
