/* Phone-first, dark, big tap targets, one-handed. */

/* The Barlow Condensed @font-face rules live in css/fonts.css, which every
   page loads — the overlay needs them too. */

/* Body-text contrast was the reason for the repaint: the old --muted (#8a97b2 on
   #1b2439) is ~4.2:1 and unreadable in sunlight. The scale now runs #9aa8c2 for
   body copy (~6.4:1) and #8e9cb8 for labels only. */
:root {
  /* surfaces */
  --bg: #0b1018;          /* page */
  --panel: #0f1726;       /* drawer + sheets */
  --card: #141c2c;        /* cards, secondary buttons */
  --sunken: #0b1018;      /* inputs */
  --bg-2: #1d2740;        /* raised cells: base buttons, steppers, empty dots */
  --line: #26314a;        /* hairlines, card borders */
  --line-2: #2c3852;      /* control borders */

  /* text */
  --chalk: #f2f6fc;       /* primary */
  --body: #9aa8c2;        /* body copy */
  --muted: #8e9cb8;       /* labels, meta */
  --steel: #6ea8f0;       /* accent / selection; text on it is #06090f */

  /* scoring keys */
  --ball: #1f8a4c; --strike: #c93c33; --foul: #4b5563;
  --out: #a86c14;         /* key */
  --out-ui: #e0a92a;      /* dots, badges, occupied bases */
  --run: #2f63cc; --batter: #2b5580; --util: #26314a;
  --accent: #e0a92a;      /* defense editor highlights (was undefined until now) */
  --hit-bg: #123a28;   --hit-line: #1f6b45;   --hit-text: #d8ffe9;
  --undo-bg: #3a2b1a;  --undo-line: #6b4e26;  --undo-text: #f7d99b;
  --clip-bg: #33241f;  --clip-line: #5d422f;  --clip-text: #f7d9c4;
  --take-bg: #1c2c40;  --take-line: #33506e;  /* takeover cards */
  --danger-bg: #3d1f1f; --danger-line: #6b2f2f; --danger-text: #ffd9d9;
  --hr-grad: linear-gradient(180deg, #3a2a52, #1a1426); --hr-line: #4b3a68;

  --disp: system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --num: "Barlow Condensed", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}
/* Signed out mid-game. Amber and red are reserved for things genuinely
   misconfigured, and this is one: nothing will save until it is fixed. Sits
   above everything, including an open sheet, and does not go away by itself. */
.session-lost {
  position: fixed; left: 0; right: 0; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 10px 12px; flex-wrap: wrap;
  padding: calc(env(safe-area-inset-top) + 10px) 14px 12px;
  background: var(--strike); color: #fff; font-size: 14px; line-height: 1.35;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
}
.session-lost[hidden] { display: none; }
.session-lost b { font-size: 15px; flex: 0 0 auto; }
.sl-note { flex: 1 1 220px; }
#sl-login {
  flex: 0 0 auto; margin: 0; padding: 9px 15px; border: 0; border-radius: 10px;
  background: #fff; color: #14181f; font-weight: 800; font-size: 14px;
}

/* Read by a screen reader, invisible to everyone else. Not display:none and not
   hidden — either would drop it out of the accessibility tree, which is exactly
   what stops a live region from ever announcing anything. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
/* Instant taps: no double-tap zoom on rapid scoring, no accidental text selection. */
button, select, input[type="range"], input[type="color"], summary, .pos-grid button {
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
:focus-visible { outline: 2px solid var(--steel); outline-offset: 2px; }
html, body { margin: 0; min-height: 100%; background: var(--bg); color: var(--chalk); font-family: var(--disp); }
/* No accidental pull-to-refresh mid-inning. */
html { overscroll-behavior-y: none; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body { padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
  overscroll-behavior-y: none; }
.view { max-width: 560px; margin: 0 auto; padding: 16px; }

h1 { font-size: 26px; margin: 4px 0 18px; letter-spacing: 0.02em; }
h1 span { color: var(--steel); }
h2 { font-size: 15px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin: 20px 0 10px; }

.card { background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 18px; }
label { display: block; font-size: 13px; color: var(--muted); margin-bottom: 12px; }
input { width: 100%; margin-top: 6px; padding: 14px; font-size: 18px; background: var(--sunken); border: 1px solid var(--line); border-radius: 12px; color: var(--chalk); }
input:focus { outline: 2px solid var(--steel); }
/* The invite field is dead weight on a scoreboard that does not use one, so it
   sits quieter than the two fields everybody fills in. */
label.opt { color: var(--steel); }
label.opt span { color: var(--muted); text-transform: none; letter-spacing: 0; }
label.opt input { padding: 10px; font-size: 15px; }

button { font-family: var(--disp); font-weight: 700; border: none; border-radius: 14px; cursor: pointer; }
.primary { width: 100%; padding: 16px; font-size: 18px; background: var(--run); color: #fff; margin-top: 6px; }
.primary.big { font-size: 20px; padding: 18px; }
.ghost { background: transparent; color: var(--chalk); border: 1px solid var(--line); padding: 12px; width: 100%; margin-top: 10px; }
.ghost.small { width: auto; padding: 8px 12px; font-size: 13px; margin: 0; }
.msg { color: var(--steel); min-height: 20px; margin: 12px 2px 0; font-size: 14px; }

.tag { color: var(--muted); font-size: 13px; } .tag b { color: var(--chalk); }

/* ---- The live screen -----------------------------------------------------
   Everything pressed during an at-bat is in the bottom two thirds and never
   moves. Nothing between the header and the bottom row scrolls; the pad takes
   whatever height is left, so a taller phone gets bigger keys, not dead space. */
.gm-head { display: flex; align-items: center; gap: 12px; padding: 6px 16px 12px; }
.gm-head .ghost.small { padding: 9px 12px; font-size: 14px; font-weight: 600; border-radius: 12px; color: #c8d4e8; }
/* The score owns this row. It was flex:1 against an air chip allowed 42% of
   it, so a team called "Blue Steel" rather than "BLSTL" got squeezed to a
   letter and an ellipsis. The score takes what it needs first and the chip
   truncates instead. */
.gm-score { flex: 1 1 auto; min-width: 0; display: flex; align-items: baseline; gap: 9px; }
.gm-score b { font-family: var(--num); font-size: 40px; font-weight: 600; line-height: 1; }
/* Two 40px numbers, a back button, an on-air chip and two dots leave about
   three characters for each name. A team called "Blue Steel" is worth more
   than four points of score digit, so the digits give way when the names are
   long — set from renderGame, which knows how long they are. */
.gm-head.longnames .gm-score b { font-size: 31px; }
.gm-head.longnames .gm-abbr { max-width: 13ch; font-size: 11px; letter-spacing: 0; }
.gm-score b.pop { animation: sc-pop 0.7s cubic-bezier(.2, .8, .2, 1); }
.gm-score #g-home-runs { margin-left: auto; }
.gm-abbr { flex: 0 1 auto; min-width: 3ch; font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  color: var(--muted); max-width: 12ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The dot marks who is batting — the same convention the overlay uses. */
.gm-abbr.bat { color: var(--chalk); }
.gm-abbr.bat::after { content: ' ●'; }

.gm-sit { display: flex; align-items: center; gap: 12px; margin: 0 16px; padding: 12px 14px;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px;
  color: var(--chalk); text-align: left; }
.gm-sit:active { filter: brightness(1.15); }
.gm-sit:disabled { pointer-events: none; }
.gm-sit:disabled .gm-edit { visibility: hidden; }
.gm-mid { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; }
.gm-inning { font-family: var(--num); font-size: 26px; font-weight: 700; color: var(--steel); letter-spacing: 0.03em; }
.gm-div { width: 1px; height: 30px; background: var(--line); }
.gm-count { display: flex; flex-direction: column; gap: 3px; }
.cd-row { display: flex; align-items: center; gap: 5px; }
.cd-row i { width: 8px; font-size: 10px; font-weight: 800; font-style: normal; color: var(--muted); }
.cd { width: 10px; height: 10px; border-radius: 999px; background: #1d2740; }
.cd.b { background: #34b56a; } .cd.s { background: #e0524a; } .cd.o { background: var(--out-ui); }

/* Same shape as the sheet's diamond, so opening the sheet is never a surprise. */
.gm-mini { position: relative; flex: 0 0 auto; width: 44px; height: 44px; margin-left: auto; }
.mb { position: absolute; width: 14px; height: 14px; border-radius: 2px;
  transform: translate(-50%, -50%) rotate(45deg); background: #1d2740; border: 1px solid var(--line-2); }
.mb.on { background: var(--out-ui); border-color: var(--out-ui); }
.mb.b1 { left: calc(50% + 15px); top: 50%; }
.mb.b2 { left: 50%; top: calc(50% - 15px); }
.mb.b3 { left: calc(50% - 15px); top: 50%; }
.mb.mh { left: 50%; top: calc(50% + 15px); width: 11px; height: 11px; background: var(--line); border-color: var(--line); }

/* A button: it opens the lineup sheet. Reads as a line, not a control, so the
   pad keeps its shape — the LINEUP › tag is what says it can be tapped. */
.gm-batter { display: flex; align-items: center; gap: 10px; padding: 8px 18px 6px; min-height: 40px; min-width: 0; width: 100%;
  background: none; border: 0; border-radius: 0; color: var(--chalk); text-align: left; font-weight: 400; cursor: pointer; }
.gm-batter:disabled { cursor: default; }
.gm-batter:active:not(:disabled) { filter: brightness(1.25); }
.gm-edit { margin-left: auto; flex: 0 0 auto; font-size: 11px; font-weight: 800; letter-spacing: 0.06em; color: var(--steel); }
.gm-edit[hidden] { display: none; }
.gm-batter[hidden] { display: none; }
.gm-hitter { font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gm-vs { font-size: 12px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.gm-batter .tag[hidden] { display: none; }

.gm-bottom { display: flex; gap: 6px; padding: 0 12px env(safe-area-inset-bottom); }
/* Icon over label, like a tab bar: five doors fit a phone and each says what it is. */
.gm-bottom > button { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 8px 2px; font-size: 11.5px; font-weight: 700; border-radius: 12px; white-space: nowrap; }
.gm-bottom > button > i { font-style: normal; font-size: 20px; line-height: 1.1; }
.gm-bottom .undo { font-weight: 800; }
.gm-b { background: var(--card); border: 1px solid var(--line); color: var(--chalk); }
.gm-b:active { filter: brightness(1.2); }
.gm-b[hidden] { display: none; }
/* The two things reached for mid-play, one tap each. Replay keeps the clip
   colours it had in the drawer, so it is the same button in a new place. */
.gm-b.replay { background: var(--clip-bg); border-color: var(--clip-line); color: var(--clip-text); }
.gm-b.replay.busy { background: var(--steel); border-color: var(--steel); color: #06090f; }
.gm-b.onair { background: var(--take-bg); border-color: var(--take-line); }

/* What is on air, and the ✕ that takes it down. Red because it is live. */
.air-chip { flex: 0 1 auto; min-width: 0; max-width: 34%; display: flex; align-items: center; gap: 6px;
  padding: 3px 3px 3px 10px; border-radius: 999px; background: var(--danger-bg);
  border: 1px solid var(--danger-line); color: var(--danger-text); font-size: 12px; font-weight: 700; }
.air-chip[hidden] { display: none; }
.air-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 999px; background: #ff5a4f; }
.air-lab { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.air-x { flex: 0 0 auto; width: 34px; height: 34px; padding: 0; border-radius: 999px;
  background: rgba(255, 255, 255, 0.1); color: var(--danger-text); font-size: 13px; }
.air-x:active { filter: brightness(1.4); }

/* "Phone" is short OR narrow — a landscape phone is 844 wide and 390 tall. */
@media (max-width: 699px), (max-height: 500px) {
  /* --app-h is set from visualViewport in control.js. 100dvh is the fallback,
     and was the whole story until a number pad closing on iOS left dvh at the
     shrunken value: the shell stayed short and the bottom bar sat in the middle
     of the screen until something else forced a relayout. */
  body.in-game { height: var(--app-h, 100dvh); overflow: hidden; }
  body.in-game #game-view { max-width: none; margin: 0; padding: 0; height: 100%;
    display: flex; flex-direction: column; min-height: 0; }
  body.in-game .setup-guide { margin: 0 16px 10px; }
  body.in-game .game-cols { flex: 1; min-height: 0; display: flex; }
  body.in-game .col-live { flex: 1; min-height: 0; display: flex; flex-direction: column;
    overflow-y: auto; overscroll-behavior: contain; padding: 10px 16px 12px; }
  /* Baseball: nothing scrolls at all. */
  body.in-game.bb .col-live { overflow: hidden; }
  /* ...except while the setup checklist is open, which is 290px of content the
     pad would otherwise absorb — on a 375x600 phone that crushed BALL to 32px
     and clipped the at-bat bar. Setup is not scoring: give the pad a floor and
     let the column scroll until the checklist is collapsed or done. */
  body.in-game.bb.guide-open .col-live { overflow-y: auto; }
  body.in-game.bb.guide-open .col-live > .sport-only[data-sport="baseball"] { flex: 0 0 auto; min-height: 380px; }
  body.in-game.bb .col-live > .sport-only[data-sport="baseball"] { flex: 1; min-height: 0; display: flex; }
  body.in-game.bb .pad { flex: 1; min-height: 0; grid-template-rows: 1.35fr 1fr 0.8fr; }
  /* The other sports: the same fixed shell. Their pads hold game flow only
     (corrections are in the Situation sheet), so the big keys take what is left. */
  body.in-game:not(.bb) .col-live > .sp-pad:not([hidden]) { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  body.in-game:not(.bb) .sp-keys { flex: 1; min-height: 132px; grid-auto-rows: 1fr; }
  body.in-game:not(.bb) .sp-keys .key { padding: 0 6px; font-size: 19px; }
  body.in-game.bb .key.ball, body.in-game.bb .key.strike { font-size: 27px; letter-spacing: 0.05em; }
  body.in-game.bb .key { padding: 0; font-size: 20px; }
  body.in-game.bb .key.batter { font-size: 17px; }
}

/* Landscape phone is ~390pt tall — a four-row pad would be four slots of
   nothing. Three columns, two rows, and the drawer arrives from the side. */
@media (max-height: 500px) and (orientation: landscape) {
  body.in-game.bb .pad { grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr; }
  body.in-game.bb .key.batter { font-size: 15px; }
  body.in-game.bb .key.ball, body.in-game.bb .key.strike { font-size: 20px; }
  .gm-batter { padding-top: 4px; padding-bottom: 0; }
}

/* Tablet / desktop: live controls left, panels right. Phones stay one column. */
@media (min-width: 700px) and (min-height: 501px) {
  #game-view { max-width: 1128px; }
  /* Not a flex child here, so the bar needs to be told to fill the row. */
  .gm-head, .gm-batter { padding-left: 0; padding-right: 0; }
  .gm-sit { width: 100%; margin: 0; }
  /* Undo stays reachable without scrolling here too. */
  .gm-bottom { position: sticky; bottom: 0; z-index: 15; margin-top: 16px;
    padding: 12px 0 calc(12px + env(safe-area-inset-bottom)); background: var(--bg);
    box-shadow: 0 -10px 14px -8px rgba(0, 0, 0, 0.6); }
  .gm-bottom > button { flex: 0 1 220px; }
  .game-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
  /* Sheets centre and round on all sides — they're dialogs here, not phone sheets. */
  .sheet { align-items: center; padding: 20px; }
  .sheet-card { border-radius: 20px; padding-bottom: 20px; border-bottom: 1px solid var(--line-2); }
  .sheet-card .grab { display: none; }
  .sheet-card.scroll { max-height: 82dvh; }
}

/* Roomier on a real monitor: the panel column stops feeling like a phone. */
@media (min-width: 1280px) and (min-height: 501px) {
  #game-view { max-width: 1320px; }
  .game-cols { grid-template-columns: 1fr 1.1fr; gap: 24px; }
  .view { max-width: 620px; }
}

/* Mouse and trackpad get hover feedback; touch devices must never keep a stuck
   hover state after a tap, so this is gated rather than applied globally. */
@media (hover: hover) and (pointer: fine) {
  .key:hover, .base-btn:hover, .fxbtn:hover, .step:hover, .game-row:hover,
  .primary:hover, .ghost:hover, .panel > summary:hover { filter: brightness(1.18); }
  .fxbtn:disabled:hover, .obsbtn:disabled:hover { filter: none; }
}

/* Lobby: pick a game, make one, or read up. */
.lobby-head { display: flex; align-items: center; gap: 12px; padding: 8px 2px 14px; }
.lobby-title { font-size: 22px; font-weight: 700; letter-spacing: -0.01em; margin: 0; }
.lobby-who { margin-left: auto; font-size: 12px; font-weight: 500; color: var(--muted); }
.lobby-head .ghost.small { font-size: 13px; font-weight: 600; padding: 9px 12px; border-radius: 12px; }
#lobby-view .primary.big { padding: 19px; font-size: 18px; font-weight: 800; border-radius: 16px; margin: 0 0 18px; }

.games-list { display: flex; flex-direction: column; gap: 9px; }
.past-games { margin-top: 6px; }
.past-games > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 12px 4px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.past-games > summary::-webkit-details-marker { display: none; }
.past-games > summary::after { content: '▸'; margin-left: auto; transition: transform 0.15s; }
.past-games[open] > summary::after { transform: rotate(90deg); }
.past-n { font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--card); border: 1px solid var(--line); color: #c8d4e8; letter-spacing: 0; }
.game-row.final { opacity: 0.8; }
.sel .opt { font-style: normal; opacity: 0.75; }
#ng-startsat { margin-top: 6px; padding: 12px; font-size: 16px; background: var(--sunken); border: 1px solid var(--line); border-radius: 12px; color: var(--chalk); }
.game-row { width: 100%; display: flex; align-items: center; gap: 12px; text-align: left;
  background: var(--card); border: 1px solid var(--line); border-radius: 16px; padding: 14px 15px; color: var(--chalk); }
.game-row:active { filter: brightness(1.2); }
.g-sport { flex: 0 0 auto; font-size: 22px; line-height: 1; }
.g-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
/* Long team names wrap to a second line instead of vanishing under the score. */
.g-name { font-size: 15px; font-weight: 700; line-height: 1.25;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; overflow-wrap: anywhere; }
.g-live { flex: 0 0 auto; font-size: 10px; font-weight: 800; letter-spacing: 0.1em;
  padding: 2px 7px; border-radius: 5px; background: var(--strike); color: #fff; }
.g-state { display: flex; align-items: center; gap: 7px; min-width: 0; font-size: 12px; font-weight: 500; color: var(--muted); }
.g-state > span:last-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.g-score { flex: 0 0 auto; font-family: var(--num); font-size: 30px; font-weight: 600; line-height: 1; }
.g-chev { flex: 0 0 auto; font-size: 13px; color: var(--muted); }
.danger-row { display: flex; gap: 12px; margin-top: 14px; }
.danger-row .fxbtn { flex: 1; }

/* Collapsible config panels */
.panel { scroll-margin-top: 72px; border: 1px solid var(--line); border-radius: 12px; margin-top: 10px; background: var(--card); overflow: hidden; }
.panel > summary { list-style: none; cursor: pointer; padding: 15px 16px; font-weight: 700; font-size: 14px; color: var(--chalk); display: flex; align-items: center; justify-content: space-between; }
.panel > summary::-webkit-details-marker { display: none; }
.panel > summary::after { content: '▸'; color: var(--muted); transition: transform 0.2s; }
.panel[open] > summary::after { transform: rotate(90deg); }
.panel-body { padding: 2px 16px 16px; }
/* Keyboard hint is desktop-only noise on a phone. */
.kbd-hint { display: none; text-align: center; opacity: 0.7; margin-top: 16px; }
@media (hover: hover) and (pointer: fine) { .kbd-hint { display: block; } }

/* Toast */
.toast { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 50;
  background: var(--steel); color: #06090f; padding: 11px 20px; border-radius: 999px; font-weight: 700; font-size: 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45); animation: toast-in 0.2s ease; }
.toast[hidden] { display: none; }
/* In a game the toast sits above the bottom bar, not on Undo — and it can hold
   a button now (Dropped 3rd?), which must never land under a thumb meant for Undo. */
body.in-game .toast { bottom: calc(90px + env(safe-area-inset-bottom)); }
.toast-act { margin-left: 12px; padding: 7px 12px; border-radius: 999px; background: #06090f;
  color: var(--steel); font-size: 13px; font-weight: 800; }

/* ---- Ball in play ------------------------------------------------------- */
.play-card .sit-head { margin-bottom: 12px; }
/* IN PLAY, step 1: the result, grouped the way a scorer thinks of it. */
.pr-grp { margin: 10px 2px 6px; font-size: 11px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.pr-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 8px; }
#pr-hits { grid-template-columns: repeat(4, 1fr); }
.pr-b { padding: 14px 6px; border-radius: 12px; background: var(--card); border: 1px solid var(--line);
  color: var(--chalk); font-size: 15px; font-weight: 700; }
.pr-b.hit { background: var(--hit-bg); border-color: var(--hit-line); color: var(--hit-text); font-size: 17px; font-weight: 800; }
.pr-b.out { background: var(--undo-bg); border-color: var(--undo-line); color: var(--undo-text); }
.pr-b.blocked { opacity: 0.4; }
.pr-b:active { filter: brightness(1.2); }
.play-will { margin: 10px 2px 12px; font-size: 13px; line-height: 1.45; color: var(--body); text-wrap: pretty; }
/* A ballfield, because the tap is "who fielded it", and people find SS by where it stands. */
.play-field { position: relative; width: 100%; aspect-ratio: 1 / 0.9; max-height: 46dvh; border-radius: 18px; overflow: hidden;
  background: radial-gradient(120% 90% at 50% 100%, #10281b 0%, #0b1c13 70%); border: 1px solid #1b3a28; }
.pf-dirt { position: absolute; left: 50%; top: 66%; width: 42%; aspect-ratio: 1; transform: translate(-50%, -50%) rotate(45deg);
  border: 2px solid rgba(224, 169, 42, 0.28); background: rgba(168, 108, 20, 0.08); }
.pf-arc { position: absolute; left: 50%; top: 66%; width: 150%; aspect-ratio: 1; transform: translate(-50%, -50%);
  border-radius: 50%; border: 1px dashed rgba(242, 246, 252, 0.08); }
.fielder { position: absolute; transform: translate(-50%, -50%); min-width: 76px; min-height: 48px; padding: 6px 8px;
  border-radius: 12px; background: rgba(20, 28, 44, 0.95); border: 1px solid var(--line-2); color: var(--chalk);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; }
.fielder b { font-family: var(--num); font-size: 20px; font-weight: 700; line-height: 1; color: var(--steel); }
.fielder span { font-size: 11px; font-weight: 600; max-width: 86px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fielder:active { background: var(--steel); }
.fielder:active b, .fielder:active span { color: #06090f; }
.sheet-actions .primary.play-out { background: var(--out); }

.rs-play { margin: 0 0 4px; font-family: var(--num); font-size: 26px; font-weight: 700; letter-spacing: 0.02em; }
.rs-grid { display: grid; grid-template-columns: minmax(64px, 1.3fr) repeat(5, minmax(0, 1fr)); gap: 5px; align-items: center; margin-top: 12px; }
.rs-hd { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); text-align: center; }
.rs-who { min-width: 0; font-size: 11px; line-height: 1.2; color: var(--muted); }
.rs-who b { display: block; font-size: 13px; color: var(--chalk); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rs-opt { height: 46px; padding: 0; border-radius: 10px; background: var(--card); border: 1px solid var(--line-2);
  color: var(--body); font-family: var(--num); font-size: 16px; font-weight: 700; }
/* Underlined: "where he already is", so holding a runner is easy to find. */
.rs-opt.stay { box-shadow: inset 0 -3px 0 var(--line-2); }
.rs-opt.on { background: var(--steel); border-color: var(--steel); color: #06090f; }
.rs-opt.on.o { background: var(--out); border-color: var(--out); color: #fff; }
.rs-opt.on.h { background: var(--run); border-color: var(--run); color: #fff; }
.rs-opt.clash { box-shadow: inset 0 0 0 2px var(--strike); }
.rs-sum { margin: 12px 2px 0; font-size: 13px; line-height: 1.45; color: var(--body); }
.rs-sum.bad { color: #ff9b94; }
#rs-record:disabled { opacity: 0.45; }
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.muted { color: var(--muted); }

@keyframes sc-pop { 0% { transform: scale(1); } 30% { transform: scale(1.3); color: var(--steel); } 100% { transform: scale(1); } }
/* The other sports still write their three spans into the same bar. */
.sc-inning { font-family: var(--num); font-size: 26px; font-weight: 700; color: var(--steel); letter-spacing: 0.03em; }
.sc-count { font-family: var(--num); font-size: 20px; }
.sc-outs { color: var(--muted); font-size: 13px; margin-left: auto; }

/* Button pad */
.pad { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.key { padding: 26px 10px; font-size: 22px; letter-spacing: 0.04em; color: #fff; border-radius: 18px; }
/* No transition on the way in — a key has to look pressed before the finger
   lifts — and a short one on the way out. */
.key:active { transform: translateY(2px); filter: brightness(1.12); }
.key { transition: transform 90ms ease, filter 90ms ease; }

.key.ball { background: var(--ball); } .key.strike { background: var(--strike); }
.key.inplay { background: var(--steel); color: #06090f; }
.key.util { background: var(--util); font-size: 16px; padding: 18px 10px; }

/* Undo + bases + util + walk sheet */
.undo { background: var(--undo-bg); color: var(--undo-text); border: 1px solid var(--undo-line); padding: 8px 16px; font-size: 15px; }
.undo:active { filter: brightness(1.15); }

.key.foul { background: var(--foul); } .key.batter { background: var(--batter); }
/* The pad diamond: a key-sized cell holding three bases. Each base is a thumb
   target; the cell itself does nothing. */
.key.pad-dia { position: relative; background: var(--card); border: 1px solid var(--line); padding: 0; min-height: 84px; }
.pd { position: absolute; width: 30%; height: 44%; min-width: 44px; min-height: 40px; transform: translate(-50%, -50%);
  display: grid; place-items: center; background: none; border: none; padding: 0; }
.pd i { display: block; width: 26px; height: 26px; border-radius: 5px; transform: rotate(45deg);
  background: var(--sunken); border: 1px solid var(--line-2); transition: background 0.12s ease; }
.pd.on i { background: var(--out-ui); border-color: var(--out-ui); }
.pd:active i { filter: brightness(1.25); }
.pd.b1 { left: 72%; top: 52%; } .pd.b2 { left: 50%; top: 27%; } .pd.b3 { left: 28%; top: 52%; }
.pd-home { position: absolute; left: 50%; top: 80%; width: 14px; height: 14px; transform: translate(-50%, -50%) rotate(45deg);
  background: var(--line); border-radius: 3px; }

.bases-label { display: block; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 8px; }
.bases-row { display: flex; gap: 8px; flex-wrap: wrap; }
.base-btn { flex: 1 1 auto; min-width: 56px; padding: 16px 8px; font-size: 16px; background: var(--bg-2); border: 1px solid var(--line); color: var(--chalk);
  transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease; }
/* The scoring keys already confirm a press; the bases and utility rows didn't. */
.base-btn:active { transform: translateY(1px); filter: brightness(1.3); }
.base-btn.wide { flex: 2 1 auto; }
.base-btn.on { background: var(--out-ui); border-color: var(--out-ui); color: #06090f; }
.base-btn.hit { background: var(--hit-bg); border-color: var(--hit-line); color: var(--hit-text); font-weight: 800; }
.base-btn.hit:active { filter: brightness(1.25); }
.base-btn:active { filter: brightness(1.1); }

.util-row { display: flex; gap: 12px; margin-top: 12px; }
.util-row .key { flex: 1; }

/* Bottom sheets */
/* Above the drawer (25), below the signed-out banner (40) and the toast (50).
   openSheet() closes the drawer, so the two should never overlap — but the way
   into Game Setup on a phone is a button inside the drawer, and at 20 a slip in
   that pairing did not read as a layering bug, it read as a dead button. */
.sheet { position: fixed; inset: 0; background: rgba(6, 9, 15, 0.68); display: flex; align-items: flex-end; z-index: 30; }
.sheet[hidden] { display: none; }
.sheet-card { width: 100%; max-width: 560px; margin: 0 auto; background: var(--panel); border: 1px solid var(--line-2); border-bottom: none;
  border-radius: 24px 24px 0 0; padding: 10px 18px calc(18px + env(safe-area-inset-bottom));
  box-shadow: 0 -24px 50px -20px #000; }
.sheet-card h3 { margin: 0 0 6px; font-size: 20px; font-weight: 700; }

/* Confirming a play is never a dialog — it is a sheet with the number big
   enough to read at a glance and one button that does the thing. */
.confirm-copy { margin: 0; font-size: 14px; line-height: 1.55; color: var(--body); text-wrap: pretty; }
.confirm-go { width: 100%; padding: 20px; font-size: 18px; font-weight: 800; letter-spacing: 0.04em;
  color: #fff; background: var(--hr-grad); border: 1px solid var(--hr-line); border-radius: 16px; }
.confirm-go:active { filter: brightness(1.15); transform: translateY(2px); }
.confirm-card .ghost { border-radius: 14px; padding: 14px; font-size: 14px; }
.step { width: 48px; height: 48px; font-size: 24px; background: var(--card); border: 1px solid var(--line-2); color: var(--chalk); border-radius: 13px; }
.sheet-actions { display: flex; gap: 12px; margin-top: 8px; }
.sheet-actions .ghost, .sheet-actions .primary { margin-top: 0; }
.sheet-actions .primary, .sit-card .primary { background: var(--run); }

/* Sheets and the drawer enter the same way — 260ms, spring-ish. */
.sheet-card { animation: sheet-in 0.26s cubic-bezier(0.2, 0.8, 0.2, 1); }
@keyframes sheet-in { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .sheet-card { animation: fade-in 0.18s linear; }
  .key:active, .base-btn:active, .fxbtn:active, .gm-b:active { transform: none; }
  .gm-score b.pop { animation: none; }
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* Moments / FX pad */
.fx-pad { margin-top: 16px; }
.fxbtn { padding: 15px 6px; font-size: 14px; font-weight: 700; background: var(--bg-2); border: 1px solid var(--line); color: var(--chalk); border-radius: 12px; }
.fxbtn:active { filter: brightness(1.15); transform: translateY(1px); }
.fx-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; }
/* An authored display: beats the UA [hidden] rule, so .sport-only could not
   hide this one — Batting order + Defense showed on football and soccer. */
.fx-grid[hidden] { display: none; }
.rally-toggle { background: #2a2033; }
.rally-toggle.on { background: var(--out-ui); border-color: var(--out-ui); color: #06090f; }
.fxbtn.charge { width: 100%; margin-top: 8px; background: #1f3a2e; border-color: #2f5d47; }

/* Audio pad */
.audio-row { display: flex; gap: 8px; align-items: stretch; margin-bottom: 4px; }
.sel { flex: 1; display: flex; flex-direction: column; gap: 6px; font-size: 12px; color: var(--muted); }
.sel select { padding: 12px; font-size: 16px; background: var(--sunken); border: 1px solid var(--line); border-radius: 12px; color: var(--chalk); }
.fxbtn.mute { align-self: flex-end; min-width: 84px; }
.fxbtn.mute.on { background: var(--strike); border-color: var(--strike); color: #fff; }
.slider { display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--muted); margin-top: 12px; }
.slider input[type="range"] { flex: 1; height: 30px; accent-color: var(--steel); }
.slider b { font-family: var(--num); font-size: 18px; color: var(--chalk); min-width: 3.5ch; text-align: right; }
.sublabel { display: block; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin: 14px 0 8px; }
.pos-row { display: flex; align-items: flex-start; gap: 14px; }
.pos-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; flex: 0 0 auto; width: 176px; }
.pos-grid button { aspect-ratio: 1; background: var(--bg-2); border: 1px solid var(--line); color: #c8d4e8; border-radius: 10px; font-size: 18px; cursor: pointer; }
.pos-grid button:active { filter: brightness(1.2); }
.pos-grid button.on { background: var(--steel); color: #06090f; border-color: var(--steel); }
.pos-side { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 9px; }
.pos-note { margin: 0; font-size: 12px; line-height: 1.45; color: var(--body); text-wrap: pretty; }
/* 16:9, same shape as the frame the bug lands on. */
.pos-preview { position: relative; height: 78px; background: var(--sunken); border: 1px solid var(--line-2); border-radius: 10px; overflow: hidden; }
.pos-bug { position: absolute; width: 56px; height: 22px; border-radius: 4px; background: var(--steel);
  transform: translate(-50%, -50%); transition: top 0.16s ease, left 0.16s ease, transform 0.16s ease; }
/* The chosen design, roughly: a layout's shape, or an animated bug's own picture. */
.pos-bug[data-layout="bar"], .pos-bug[data-layout="lowerthird"] { width: 70px; height: 14px; }
.pos-bug[data-layout="minimal"] { width: 60px; height: 11px; border-radius: 6px; }
.pos-bug[data-layout="bug"], .pos-bug[data-layout="scorebox"] { width: 40px; height: 30px; }
.pos-bug.thumb { width: 62px; height: 26px; border-radius: 2px; background: center / contain no-repeat;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .5)); }

/* Football control */
.fb-dist { align-self: center; font-family: var(--num); font-size: 20px; min-width: 2.5ch; text-align: center; }
.fb-score { margin-top: 8px; }
/* A button beside a labelled select lines up with the select, not the label. */
.audio-row > .fxbtn { align-self: flex-end; padding: 13px 16px; margin: 0; }
.audio-row > .sel { margin-bottom: 0; }
.audio-row { margin-bottom: 12px; }
.replay-row { margin-top: 10px; }
.replay-auto { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 700; color: var(--chalk); }
.replay-auto .switch .track { width: 46px; height: 28px; }
.replay-auto .switch .knob { width: 22px; height: 22px; }
.replay-auto .switch input:checked + .track .knob { transform: translateX(18px); }
.replay-hint { margin-top: 6px; }
.replay-hint[data-tone="ok"] { color: var(--ball); }
.replay-hint[data-tone="warn"] { color: var(--out-ui); }
.replay-hint[data-tone="bad"] { color: var(--strike); }

#card-text { margin-top: 8px; padding: 14px; font-size: 16px; border-radius: 12px; }
.fxbtn.cardclear { width: 100%; margin-top: 8px; background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger-text); }
/* Full-screen cards read differently from the corner cards — they hide the bug. */
.fxbtn.takeover { width: 100%; margin-bottom: 8px; background: var(--take-bg); border-color: var(--take-line); }
.fx-grid.two { grid-template-columns: 1fr 1fr; }

/* On Air sheet — every tile the same height, so a two-word label and a
   one-letter K sit on one baseline. The lit tile is what is on air now. */
.onair-card .sublabel { margin: 16px 0 8px; }
.onair-card .sit-head + .sport-only .sublabel { margin-top: 0; }
.onair-card .sublabel em { font-style: normal; text-transform: none; letter-spacing: 0; color: var(--steel); margin-left: 6px; }
.onair-card .fxbtn { min-height: 54px; }
.onair-card .fxbtn.takeover, .onair-card .fxbtn.charge { width: auto; margin: 0; }
.onair-card .fxbtn.sugg { border-color: var(--steel); }
.onair-card [data-card].on { background: var(--steel); border-color: var(--steel); color: #06090f; }
.onair-card .rally-toggle { grid-column: 1 / -1; }
.onair-card .air-text { margin-top: 10px; }
.onair-card .air-text { display: flex; flex-direction: column; gap: 6px; font-size: 12px; color: var(--muted); }
.onair-card .air-text em { font-style: normal; opacity: 0.8; }
.onair-card .air-why { margin: 8px 0 0; font-size: 12px; color: var(--muted); display: flex; align-items: center; gap: 6px; }
.onair-card .air-why em { font-style: normal; color: var(--steel); }
.sugg-dot { width: 12px; height: 12px; border-radius: 4px; border: 2px solid var(--steel); }
.onair-card #card-text { margin-top: 0; }

/* Situation sheet — bases, count, inning, and the corrections for all three.
   It replaces the Bases row, the pitch-count stepper and the whole Manual
   adjust panel; the live pad keeps none of them. */
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.grab { display: block; width: 44px; height: 5px; border-radius: 999px; background: #33405e; margin: 0 auto 12px; }
.sit-card { background: var(--panel); border-color: var(--line-2); box-shadow: 0 -24px 50px -20px #000; border-radius: 24px 24px 0 0; padding: 10px 18px calc(18px + env(safe-area-inset-bottom)); }
.sit-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 16px; }
.sit-head h3 { margin: 0; font-size: 20px; font-weight: 700; }
.sit-sub { font-size: 13px; color: var(--muted); }

.sit-bases { display: flex; align-items: center; gap: 16px; background: var(--card);
  border: 1px solid var(--line); border-radius: 18px; padding: 16px; }
.sit-side { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 9px; }
.sit-note { margin: 0; font-size: 12px; line-height: 1.45; color: var(--body); text-wrap: pretty; }
.sit-side .base-btn, .sit-wide { background: var(--bg-2); border: 1px solid var(--line-2); color: #c8d4e8;
  border-radius: 12px; padding: 13px 10px; font-size: 14px; font-weight: 700; }
.sit-wide { display: block; width: 100%; margin-top: 9px; }
.end-row { margin: 14px 0 6px; }
.end-row .end-game { width: 100%; padding: 13px 8px; font-size: 14px; }
.end-row .sit-end, .sit-card .sit-end { background: var(--danger-bg); border: 1px solid var(--danger-line); color: var(--danger-text); }
.end-row .sit-end.over { background: var(--bg-2); border-color: var(--line-2); color: #c8d4e8; }
.sit-card .sit-end { margin-top: 16px; background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger-text); }
.sit-card .sit-end.over { background: var(--bg-2); border-color: var(--line-2); color: #c8d4e8; }
.sit-pair { display: flex; gap: 9px; margin-top: 9px; }
.sit-pair .base-btn { flex: 1; padding: 13px 8px; font-size: 14px; background: var(--bg-2); border: 1px solid var(--line-2); color: #c8d4e8; }
/* The route out of the play sheet to the runner plays. It reads as a note with
   a tap on it, not as another way to record an out. */
.play-runner-note { display: block; width: 100%; text-align: left; padding: 11px 13px; margin-bottom: 11px;
  font-size: 14px; font-weight: 700; background: var(--bg-2); border: 1px dashed var(--line-2); color: #c8d4e8; }
.play-runner-note span { display: block; margin-top: 2px; font-size: 12px; font-weight: 600; color: var(--muted); }
/* The two Clear lineup buttons sit in a pair, so they take the row's spacing
   rather than End game's standalone gap, and grey out with nothing to clear. */
.sit-card .sit-pair .sit-end { margin-top: 0; background: var(--bg-2); border-color: var(--danger-line); color: var(--danger-text); }
.sit-card .sit-end:disabled { opacity: 0.4; pointer-events: none; }

/* The diamond. Bases are 38px of ink inside a 44px target — nothing on this
   sheet is smaller than a thumb. */
.diamond { position: relative; flex: 0 0 auto; width: 132px; height: 132px; }
.diamond::before { content: ''; position: absolute; left: 50%; top: 50%; width: 88px; height: 88px;
  transform: translate(-50%, -50%) rotate(45deg); border: 1px solid var(--line-2); border-radius: 8px; }
.dbase { position: absolute; width: 44px; height: 44px; transform: translate(-50%, -50%);
  display: grid; place-items: center; background: none; border: none; padding: 0; }
.dbase i { display: block; width: 38px; height: 38px; border-radius: 6px; transform: rotate(45deg);
  background: var(--sunken); border: 1px solid var(--line-2);
  transition: background 0.12s ease, border-color 0.12s ease; }
.dbase.on i { background: var(--out-ui); border-color: var(--out-ui); }
.dbase:active i { filter: brightness(1.25); }
.dbase.b1 { left: calc(50% + 44px); top: 50%; }
.dbase.b2 { left: 50%; top: calc(50% - 44px); }
.dbase.b3 { left: calc(50% - 44px); top: 50%; }
.dhome { position: absolute; left: 50%; top: calc(50% + 44px); width: 26px; height: 26px;
  transform: translate(-50%, -50%) rotate(45deg); background: #26314a; border-radius: 5px; }

.sit-steps { margin-top: 14px; }
.sit-more { margin-top: 14px; }
.sit-more > summary { list-style: none; cursor: pointer; padding: 14px; text-align: center;
  font-size: 13px; font-weight: 700; color: #c8d4e8; border: 1px solid var(--line-2); border-radius: 14px; }
.sit-more > summary::-webkit-details-marker { display: none; }
.sit-more > summary::after { content: ' ▸'; color: var(--muted); }
.sit-more[open] > summary::after { content: ' ▾'; }
.sit-more-body { padding-top: 4px; }
.sit-card .sheet-actions { margin-top: 14px; background: var(--panel); }
.sit-card .primary { padding: 17px; font-size: 16px; font-weight: 800; border-radius: 14px; }

/* Steppers — 46px, the smallest control in the design */
.adj-row { display: flex; align-items: center; gap: 12px; margin-top: 9px; }
.adj-row .adj-lab { flex: 1; color: #c8d4e8; font-size: 14px; }
.adj-row .step { width: 46px; height: 46px; font-size: 22px; border-radius: 13px; }
.adj-row > b { font-family: var(--num); font-size: 26px; min-width: 2ch; text-align: center; }
.adj-row .base-btn { flex: 0 0 auto; min-width: 72px; padding: 13px 14px; font-size: 13px; }

/* Setup sheet sub-sections: teams stay in view, the rest folds away */
.su-panel { margin-top: 10px; background: var(--bg-2); }
.su-panel > summary { padding: 13px 14px; font-size: 13px; }
.su-panel .panel-body { padding: 2px 14px 14px; }

/* Permission tiers: a feature you haven't enabled is a choice, not a fault, so
   it reads muted. Amber is reserved for "you enabled this and it's misbehaving". */
.panel > summary { gap: 8px; }
.panel-need { margin-left: auto; margin-right: 8px; font-size: 11px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.06em; }
.hint[data-tone="off"] { color: var(--muted); }

/* ---- The drawer ----------------------------------------------------------
   A bottom sheet on a phone, the panel column from 700px. Presentation only:
   both states wrap the same panel bodies. */

/* The tier the pad is actually running at, said once at the top of the tab, so
   a disabled control reads as not-unlocked instead of broken. */
.obs-tier { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding: 13px 14px;
  background: var(--card); border: 1px solid var(--line); border-radius: 14px; }
.ot-lab { flex: 1; font-size: 13px; color: var(--body); }
.ot-lab b { color: var(--chalk); }
.obs-tier .ghost.small { margin: 0; font-size: 12px; }

/* Landscape phone: no room for a bottom sheet over a 390pt-tall screen, so the
   drawer comes in from the side instead and keeps the pad visible. */
@media (max-height: 500px) and (orientation: landscape) {
}
@media (max-height: 500px) and (orientation: landscape) and (prefers-reduced-motion: reduce) {
}

/* The switch on the replay row, and everything the OBS toggle hides */
.switch { display: inline-flex; margin: 0; cursor: pointer; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch .track { width: 52px; height: 31px; border-radius: 999px; background: var(--bg-2);
  border: 1px solid var(--line); position: relative; transition: background 0.18s ease, border-color 0.18s ease; }
.switch .knob { position: absolute; top: 2px; left: 2px; width: 25px; height: 25px; border-radius: 50%;
  background: var(--muted); transition: transform 0.18s ease, background 0.18s ease; }
.switch input:checked + .track { background: var(--ball); border-color: var(--ball); }
.switch input:checked + .track .knob { transform: translateX(21px); background: #fff; }
.switch input:focus-visible + .track { outline: 2px solid var(--steel); outline-offset: 2px; }

body.no-obs .obs-only { display: none; }

/* OBS stream / record / buffer */
.obs-row { display: flex; gap: 8px; }
.fxbtn.obsbtn { flex: 1; background: var(--bg-2); }
.fxbtn.obsbtn.on { background: var(--ball); border-color: var(--ball); color: #fff; }
.fxbtn.obsbtn.live { background: var(--strike); border-color: var(--strike); color: #fff; }
.fxbtn.obsbtn.armed { background: var(--out-ui); border-color: #fff; color: #06090f; font-size: 12px; }
.fxbtn.obsbtn:disabled { opacity: 0.45; }
#obs-hint[data-tone="ok"] { color: var(--ball); }
#obs-hint[data-tone="warn"] { color: var(--out-ui); }

/* Camera (OBS scene) switcher */
.scene-list { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.fxbtn.scene { padding: 16px 10px; text-align: left; background: var(--bg-2); }
.fxbtn.scene.on { background: var(--ball); border-color: var(--ball); color: #fff; }
.fxbtn.scene:disabled { opacity: 0.5; }
#scene-hint[data-tone="ok"], #cam-hint[data-tone="ok"] { color: var(--ball); }
#scene-hint[data-tone="warn"], #cam-hint[data-tone="warn"] { color: var(--out-ui); }

/* Lobby help / setup instructions */
.help { margin-top: 22px; }
.help-h { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: 0.12em; margin: 0 0 9px 2px; }

/* Support footer (lobby) */
.support { margin: 26px 0 8px; text-align: center; }
.support-cap { margin: 0 0 10px; font-size: 13px; color: var(--muted); }
.support-link { display: inline-block; line-height: 0; border-radius: 12px; }
.support-link img { height: 50px; width: auto; border-radius: 12px; }
.support-link:active { filter: brightness(1.1); }
.help-body { color: var(--chalk); font-size: 14px; line-height: 1.55; }
.help-body p { margin: 8px 0; }
.help-body ol, .help-body ul { margin: 8px 0; padding-left: 22px; }
.help-body li { margin: 7px 0; }
.help-body b { color: var(--chalk); }
.help-body li, .help-body p { color: var(--body); }
.help-table { width: 100%; border-collapse: collapse; margin: 10px 0; font-size: 13px; }
.help-table th, .help-table td { border: 1px solid var(--line); padding: 8px 10px; text-align: left; vertical-align: top; color: var(--body); }
.help-table th { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; }
.help-table .t-sub { color: var(--muted); font-size: 11px; }
.t-need { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); border: 1px solid var(--line); border-radius: 5px; padding: 1px 5px; }
.help-tip { margin-top: 12px !important; padding: 10px 12px; border-left: 3px solid var(--steel);
  background: var(--card); border-radius: 0 8px 8px 0; font-size: 13px; }

/* Sponsors */
.sp-row { display: grid; grid-template-columns: 1fr 1fr auto; gap: 6px; align-items: center; margin-bottom: 6px; }
.sp-row input { margin-top: 0; padding: 10px; font-size: 16px; }
.fxbtn.sp-del { width: auto; margin: 0; padding: 10px 12px; }
.sp-toggle { display: flex; align-items: center; gap: 8px; margin: 12px 0 4px; font-size: 14px; color: var(--chalk); }
.sp-toggle input { width: 20px; height: 20px; accent-color: var(--steel); }
.sp-timing { display: flex; gap: 10px; }
.sp-timing .fld { flex: 1; }

/* Unsent scoring, queued while the signal is out */
.pending { font-size: 12px; font-weight: 800; color: #06090f; background: var(--out-ui);
  border-radius: 999px; padding: 3px 9px; white-space: nowrap; }
.pending[hidden] { display: none; }

/* Connection status dot */
/* The shadow fold's badge. Quiet when the rebuild agrees with the row, loud
   only when it does not — it is a check on the model, not a scoring control. */
.fold-badge { flex: 0 0 auto; align-self: center; margin-right: 7px; padding: 3px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 700; line-height: 1.5; background: var(--bg-2); border: 1px solid var(--line-2); color: var(--muted); }
.fold-badge[data-state="ok"]      { background: var(--hit-bg); border-color: var(--hit-line); color: var(--hit-text); }
.fold-badge[data-state="diff"]    { background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger-text); }
.fold-badge[data-state="partial"] { background: var(--undo-bg); border-color: var(--undo-line); color: var(--undo-text); }
.fold-badge[data-state="busy"]    { opacity: 0.6; }
.conn-dot { flex: 0 0 auto; align-self: center; width: 9px; height: 9px; border-radius: 999px; font-size: 0; }
.conn-dot[data-state="live"] { background: #34b56a; box-shadow: 0 0 0 4px rgba(52, 181, 106, 0.16); }
.conn-dot[data-state="connecting"] { background: var(--out-ui); }
.conn-dot[data-state="down"] { background: var(--strike); animation: conn-blink 1s steps(2, start) infinite; }
@keyframes conn-blink { 50% { opacity: 0.25; } }

/* Guided setup checklist */
.setup-guide { background: var(--card); border: 1px solid var(--steel); border-radius: 12px; margin-bottom: 12px; overflow: hidden; }
.setup-guide[hidden] { display: none; }
.setup-guide.complete { border-color: var(--ball); }
.sg-head { width: 100%; display: flex; align-items: center; gap: 10px; background: transparent; border: none; color: var(--chalk); padding: 13px 14px; font-size: 15px; cursor: pointer; }
.sg-progress { margin-left: auto; font-family: var(--num); color: var(--steel); font-weight: 700; }
.sg-chev { color: var(--muted); transition: transform 0.2s; }
.setup-guide.collapsed .sg-chev { transform: rotate(-90deg); }
.setup-guide.collapsed .sg-body { display: none; }
.sg-body { padding: 0 14px 12px; }
.sg-sub { color: var(--muted); font-size: 13px; margin: 0 0 8px; }
.sg-step { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-top: 1px solid var(--line); }
.sg-step[hidden] { display: none; }
.sg-dot { width: 26px; height: 26px; border-radius: 999px; background: var(--bg-2); border: 1px solid var(--line); display: grid; place-items: center; font-size: 13px; font-weight: 800; color: var(--muted); flex: 0 0 auto; }
.sg-step.done .sg-dot { background: var(--ball); border-color: var(--ball); color: #f2f6fc; }
.sg-lab { flex: 1; font-size: 14px; }
.sg-step.done .sg-lab { color: var(--muted); text-decoration: line-through; }
.sg-go { background: var(--steel); color: #06090f; border: none; border-radius: 10px; padding: 9px 15px; font-weight: 700; font-size: 13px; }
.sg-step.done .sg-go { background: var(--bg-2); color: var(--muted); border: 1px solid var(--line); }

/* Lineup sheet — one team at a time; # · name · position on every row. */
.lu-tabs { display: flex; gap: 4px; padding: 3px; margin-bottom: 12px; background: var(--sunken);
  border: 1px solid var(--line); border-radius: 12px; }
.lu-tabs button { flex: 1; min-width: 0; padding: 10px 6px; border-radius: 9px; background: none; color: var(--body);
  font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lu-tabs button[aria-pressed="true"] { background: var(--card); color: var(--chalk); box-shadow: inset 0 0 0 1px var(--line-2); }
.lu-side[hidden] { display: none; }
.lu-cols { display: flex; gap: 6px; padding: 0 0 2px; font-size: 10px; font-weight: 700; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted); }
.lu-cols .c-ord { flex: 0 0 calc(34px + 3.4ch + 6px); }
.lu-cols .c-num { flex: 0 0 calc(3ch + 20px); text-align: center; }
.lu-cols .c-name { flex: 1 1 0; }
.lu-cols .c-pos { flex: 0 0 64px; text-align: center; }
.fieldcheck { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin: 0 2px 8px; font-size: 12px; color: var(--body); }
.fieldcheck b { padding: 2px 7px; border-radius: 999px; border: 1px solid rgba(224, 169, 42, 0.5);
  color: var(--out-ui); font-family: var(--num); font-size: 13px; }
.fieldcheck.ok { color: var(--ball); font-weight: 700; }
.lu-side .lineup-row { gap: 6px; }
.lineup-row .b-pos { flex: 0 0 64px; width: 64px; min-width: 0; margin: 0; padding: 10px 4px 10px 8px;
  font-family: var(--num); font-size: 17px; font-weight: 700; color: var(--steel);
  background: var(--sunken); border: 1px solid var(--line); border-radius: 10px; }
.lineup-row .b-pos.none { color: var(--muted); }
.lineup-row .b-pos:disabled { opacity: 0.35; }
/* The player a dropdown just moved off their spot — they need a new one. */
.lineup-row.benched { animation: benched 1.8s ease; }
@keyframes benched { 0%, 60% { background: rgba(224, 169, 42, 0.2); box-shadow: 0 0 0 2px var(--out-ui); border-radius: 10px; } }
@media (prefers-reduced-motion: reduce) { .lineup-row.benched { animation: none; box-shadow: 0 0 0 2px var(--out-ui); border-radius: 10px; } }

/* Saved-team load/save row */
.team-load { display: flex; gap: 6px; align-items: stretch; margin-bottom: 10px; }
.team-load select { flex: 1 1 0; min-width: 0; padding: 10px; font-size: 16px; background: var(--sunken); border: 1px solid var(--line); border-radius: 10px; color: var(--chalk); }
/* width/margin reset: .fxbtn.cardclear is width:100% with a top margin for its
   full-row uses, which here stretched 🗑 across the row and crushed the picker. */
.team-load .fxbtn { flex: 0 0 auto; width: auto; margin-top: 0; padding: 10px 12px; }

/* Nested sub-panels (lineup teams, custom theme) — compact, accordion-exempt */
.panel .panel { margin-top: 8px; background: var(--bg-2); }
.panel .panel > summary { padding: 12px 14px; font-size: 13px; }
.lineup-list { margin-top: 4px; }
.lineup-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.lineup-row input { width: auto; margin-top: 0; padding: 10px; font-size: 16px; border-radius: 10px; }
/* Explicit width + min-width:0 on both: a flex item's min-width:auto lets iOS
   Safari grow an input to its default ~20-char size, which made # wider than name. */
.lineup-row .b-num { flex: 0 0 calc(3ch + 20px); width: calc(3ch + 20px); min-width: 0; text-align: center; font-family: var(--num); padding-left: 4px; padding-right: 4px; }
.lineup-row .b-name { flex: 1 1 0; width: 0; min-width: 0; }
.lineup-row .ord { flex: 0 0 1.6ch; text-align: center; font-family: var(--num); font-size: 13px; color: var(--muted); }
.cur-dot { flex: 0 0 auto; width: 34px; height: 34px; font-size: 16px; background: var(--bg); border: 1px solid var(--line); color: var(--muted); border-radius: 999px; }
.lineup-row.at-bat .cur-dot { background: var(--out-ui); border-color: var(--out-ui); color: #06090f; }
.lineup-row.at-bat .b-name { border-color: var(--out-ui); }
.lineup-row.at-bat .ord { color: var(--chalk); }
/* Batting-order drag: the order number is the grip */
.lineup-list .ord { flex-basis: 3.4ch; padding: 10px 0; border-radius: 8px; cursor: grab; touch-action: none; user-select: none; }
.lineup-list .ord::before { content: '⋮⋮'; margin-right: 2px; letter-spacing: -2px; opacity: .6; }
.lineup-row.dragging { opacity: .35; }
.lineup-row.hot { border-radius: 10px; box-shadow: 0 0 0 2px var(--accent); background: rgba(232,178,58,.14); }
.lb-ghost { position: fixed; z-index: 9999; transform: translate(-50%, -50%); pointer-events: none; opacity: .92;
  background: var(--steel); color: #06090f; font-size: 13px; font-weight: 700; padding: 7px 12px; border-radius: 999px; white-space: nowrap; }

/* Clock row */
.clock-row { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.clock-row[hidden] { display: none; }
.clock-disp { font-family: var(--num); font-size: 26px; font-weight: 700; min-width: 4ch; }
.clock-disp.low { color: var(--strike); }
.clock-row .ghost.small { flex: 1; }

/* Practice */
.practice-row { display: flex; gap: 12px; margin-top: 16px; }
.practice-row .fxbtn { flex: 1; }
.fxbtn.demo.on { background: var(--ball); border-color: var(--ball); color: #fff; }

/* Setup sheet */
.sheet-card.scroll { max-height: 88vh; max-height: 88dvh; overflow-y: auto;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }
/* Save/Close ride along at the bottom of a scrolling sheet. A phone in landscape
   has ~390pt of height — no dialog fits, so the actions must never be something
   you have to go looking for. */
/* Pinned into the card's bottom padding too, so rows never peek out beneath it. */
.sheet-card.scroll .sheet-actions { position: sticky; bottom: calc(-18px - env(safe-area-inset-bottom)); z-index: 1;
  margin-top: 14px; padding: 12px 0 calc(18px + env(safe-area-inset-bottom)); margin-bottom: calc(-18px - env(safe-area-inset-bottom)); background: var(--panel);
  box-shadow: 0 -10px 14px -8px rgba(0, 0, 0, 0.55); }
.setup-cols { display: flex; gap: 12px; }
.setup-col { flex: 1; display: flex; flex-direction: column; gap: 8px; margin: 8px 0; }
.col-h { display: block; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-top: 8px; }
.setup-col input { padding: 12px; font-size: 16px; background: var(--sunken); border: 1px solid var(--line); border-radius: 10px; color: var(--chalk); }
.colorlab { display: flex; align-items: center; justify-content: space-between; font-size: 13px; color: var(--muted); }
.colorlab input[type="color"] { width: 48px; height: 34px; background: none; border: 1px solid var(--line); border-radius: 8px; }
.fld { display: block; font-size: 13px; color: var(--muted); margin: 12px 0; }
.fld input { width: 100%; margin-top: 6px; padding: 12px; font-size: 16px; background: var(--sunken); border: 1px solid var(--line); border-radius: 10px; color: var(--chalk); }

.urlbar { display: flex; gap: 8px; margin-top: 16px; }
.urlbar input { font-family: var(--mono); font-size: 16px; }
.hint { color: var(--body); font-size: 12px; margin-top: 10px; line-height: 1.5; }

/* Other sports' pads: rows never wrap, values sit in a box, labels breathe. */
.sp-pad .bases-label { margin: 12px 0 6px; }
.sp-pad .bases-label:first-child { margin-top: 0; }
.sp-pad .bases-label em { font-style: normal; text-transform: none; letter-spacing: 0; opacity: 0.8; }
.sp-row { display: flex; gap: 8px; }
.sp-row + .sp-row, .sp-keys + .sp-row { margin-top: 8px; }
.sp-row > * { flex: 1 1 0; min-width: 0; }
.sp-row .base-btn { padding: 13px 4px; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sp-row .base-btn small { font-size: 11px; opacity: 0.75; font-weight: 600; }
.sp-val { flex: 0 0 60px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: var(--sunken); border: 1px solid var(--line); border-radius: 12px;
  font-family: var(--num); font-size: 20px; line-height: 1; }
.sp-val small { font-family: inherit; font-size: 10px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); margin-top: 3px; }
.sit-steps > .sublabel:first-child { margin-top: 0; }
.adj-row > .base-btn#vb-target { min-width: 96px; }
#fb-firstdown { flex-grow: 1.6; }
#fb-dist-dn, #fb-dist-up { flex-grow: 0.8; }

/* Strike three: swinging / looking / dropped */
.k3-opts { display: grid; gap: 10px; }
.k3-opts .base-btn { padding: 16px; font-size: 16px; }
.k3-opts .blocked { opacity: 0.4; }
.k-back { display: inline-block; transform: scaleX(-1); }

/* Runners: one row per runner */
.rn-list { display: grid; gap: 12px; }
.rn-row { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.rn-who { grid-column: 1 / -1; font-size: 15px; }
.rn-b { padding: 14px 8px; font-size: 15px; }
.rn-b.blocked { opacity: 0.4; }

/* Field screen: full screen, positions by jersey number */
.field-view { position: fixed; inset: 0; z-index: 60; background: var(--bg); display: flex; flex-direction: column;
  gap: 10px; padding: calc(10px + env(safe-area-inset-top)) 14px calc(14px + env(safe-area-inset-bottom)); overflow-y: auto; }
.field-view[hidden] { display: none; }
body.field-open { overflow: hidden; }
.fv-top { display: flex; align-items: center; gap: 12px; }
.fv-top h2 { margin: 0; font-size: 24px; color: var(--chalk); text-transform: none; letter-spacing: 0; }
.fv-back { min-height: 52px; padding: 0 18px; font-size: 19px; background: var(--card); color: var(--chalk); border: 1px solid var(--line-2); }
.fv-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; padding: 4px; border-radius: 14px; background: var(--card); }
.fv-tabs button { min-height: 48px; font-size: 16px; background: none; color: var(--body); }
.fv-tabs button[aria-pressed="true"] { background: var(--steel); color: #06090f; }
.fv-note { margin: 0; font-size: 17px; color: var(--chalk); min-height: 1.3em; }
.fv-field { position: relative; flex: 1; min-height: 360px; max-height: 560px; border-radius: 18px; background: #0f2a1c; border: 1px solid #1e4a31; }
.fv-dirt { position: absolute; left: 50%; top: 68%; width: 34%; aspect-ratio: 1; transform: translate(-50%, -50%) rotate(45deg);
  border: 2px solid #3d6b4f; background: #6b4a2b33; }
.fv-tile { position: absolute; transform: translate(-50%, 0); width: 25%; min-width: 78px; height: 72px; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px; background: #141c2ce6; color: #fff; border: 2px solid var(--line-2); border-radius: 14px; }
.fv-tile small { font-size: 13px; letter-spacing: 0.08em; color: #c8d4e8; }
.fv-tile b { font-family: var(--num); font-size: 34px; line-height: 0.95; }
.fv-tile.empty { border-style: dashed; border-color: var(--out-ui); }
.fv-tile.empty b { color: var(--out-ui); }
.fv-numbers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.fv-numbers[hidden] { display: none; }
.fv-num { min-height: 96px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  background: var(--card); color: var(--chalk); border: 2px solid var(--line-2); border-radius: 14px; }
.fv-num b { font-family: var(--num); font-size: 40px; line-height: 1; }
.fv-num span { font-size: 13px; color: var(--body); font-weight: 600; }
.fv-num small { font-size: 13px; color: var(--muted); }
.fv-num.bench small { color: var(--out-ui); }
.fv-num.on { background: var(--steel); border-color: #cfe3ff; color: #06090f; }
.fv-num.on span, .fv-num.on small { color: #06090f; }

/* The big three (Situation, On Air, Lineup) are full screens, not sheets:
   nothing half-covered behind them, no flick to dismiss, one ‹ Back that is
   always in the same place at the top. */
.sheet.full { background: var(--bg); align-items: stretch; padding: 0; }
.sheet.full > .sheet-card { max-width: 720px; height: 100%; max-height: none; border: none; border-radius: 0; box-shadow: none;
  background: var(--bg); overflow-y: auto; overscroll-behavior: contain;
  padding: 0 16px calc(24px + env(safe-area-inset-bottom)); animation: fade-in 0.15s linear; }
.full-top { position: sticky; top: 0; z-index: 2; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin: 0 -16px 14px; padding: calc(10px + env(safe-area-inset-top)) 16px 10px; background: var(--bg);
  border-bottom: 1px solid var(--line); }
.full-top h3 { margin: 0; font-size: 22px; font-weight: 700; }
.full-top .sit-sub { flex-basis: 100%; margin-top: -4px; }
@media (min-width: 700px) { .sheet.full { padding: 0; align-items: stretch; } .full-top .sit-sub { flex-basis: auto; margin-top: 0; } }

/* The Setup screen itself: the same full-screen shell as the Field screen,
   with panes that push in place of a drawer and a modal sheet. */
.setup-view { position: fixed; inset: 0; z-index: 60; background: var(--bg); display: flex; flex-direction: column;
  padding: 0 16px calc(24px + env(safe-area-inset-bottom)); overflow-y: auto; overscroll-behavior: contain; }
.setup-view[hidden] { display: none; }
body.setup-open { overflow: hidden; }
.setup-view .full-top { margin: 0 -16px 14px; }
.sv-pane[hidden] { display: none; }
.sv-pane > .set-sec:last-child { margin-bottom: 6px; }
.set-row input[type="color"] { flex: 0 0 auto; width: 54px; height: 34px; padding: 0; border-radius: 9px; border: 1px solid var(--line-2); background: var(--sunken); }
.set-row select.set-input { appearance: none; -webkit-appearance: none; background-image: none; }
@media (min-width: 700px) { .setup-view { padding-inline: calc(50% - 344px); } .setup-view .full-top { margin-inline: 0; } }

/* ---- Settings rows -------------------------------------------------------
   Five row types, and nothing else. The drawer grew three ways to group a
   setting (details accordions, caps headers with no box, bare rows on the
   background), three ways to label one, and two toggle styles eight rows
   apart — which is what reads as sloppy, rather than any single control
   being ugly. A screen built only from these matches every other screen,
   including ones nobody has designed yet.

   They live inside the shell the Field, Lineup and On Air screens already
   use (.sheet.full + .full-top), so a settings screen is not a new pattern —
   it is the pattern this app already settled on.

   The five: .set-head (section), then rows inside one .set-card —
   .set-row (a value, taps through), .set-row.toggle, .set-row.field,
   .set-row.danger. Nothing nests. */
.set-sec { display: flex; flex-direction: column; gap: 8px; margin-bottom: 18px; }
.set-head { font-size: 12px; font-weight: 800; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.set-card { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }

/* One row. A link or a button when it goes somewhere, a div when it doesn't —
   never a div with a click handler, which Tab skips. */
.set-row { display: flex; align-items: center; gap: 10px; width: 100%; box-sizing: border-box;
  min-height: 52px; padding: 11px 13px; text-align: left; font-size: 16px; color: var(--chalk);
  /* buttons here carry the app's bold button weight, divs do not — a row must
     read the same whether or not it happens to tap through to something */
  font-family: inherit; font-weight: 500;
  background: none; border: none; border-radius: 0; text-decoration: none; }
.set-row + .set-row { border-top: 1px solid var(--line); }
/* block, not inline: the sub-line under a label is a block child, and a
   block inside an inline parent breaks the row into columns. */
.set-lab { flex: 1 1 auto; min-width: 0; display: block; }
.set-sub { display: block; margin-top: 2px; font-size: 13px; color: var(--muted); }
/* The current value, right-aligned: a row should answer its question without
   being opened. */
.set-val { flex: 0 1 auto; font-size: 15px; font-weight: 700; color: var(--body); text-align: right;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.set-go { flex: 0 0 auto; font-size: 17px; line-height: 1; color: var(--muted); }
.set-dot { flex: 0 0 auto; width: 16px; height: 16px; border-radius: 5px; border: 1px solid var(--line-2); }
.set-tag { flex: 0 0 auto; padding: 3px 8px; font-size: 11px; font-weight: 700; border-radius: 999px;
  background: var(--bg-2); border: 1px solid var(--line-2); color: var(--muted); }
button.set-row, a.set-row { cursor: pointer; }
button.set-row:active, a.set-row:active { background: var(--bg-2); }
@media (hover: hover) { button.set-row:hover, a.set-row:hover { background: var(--bg-2); } }
.set-row[aria-disabled="true"], .set-row:disabled { opacity: 0.45; pointer-events: none; }
.set-row[hidden] { display: none; }   /* Custom colours only shows on the Custom theme */

/* Toggle row: one switch, everywhere. A real checkbox underneath, so it is
   focusable, announced and togglable from the keyboard. */
.set-switch { position: relative; flex: 0 0 auto; width: 46px; height: 28px; }
.set-switch input { position: absolute; inset: 0; margin: 0; width: 100%; height: 100%; opacity: 0; }
.set-switch i { position: absolute; inset: 0; border-radius: 999px; background: var(--bg-2);
  border: 1px solid var(--line-2); transition: background 0.14s linear; }
.set-switch i::after { content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px;
  border-radius: 999px; background: var(--body); transition: transform 0.14s ease, background 0.14s linear; }
.set-switch input:checked + i { background: var(--ball); border-color: var(--ball); }
.set-switch input:checked + i::after { transform: translateX(18px); background: var(--chalk); }
.set-switch input:focus-visible + i { outline: 2px solid var(--steel); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .set-switch i, .set-switch i::after { transition: none; } }

/* Field row: the label keeps a fixed column so stacked fields line up. */
.set-row.field { padding: 9px 13px; }
.set-row.field .set-lab { flex: 0 0 104px; font-size: 15px; color: var(--body); }
.set-input { flex: 1 1 auto; min-width: 0; min-height: 44px; padding: 9px 11px; font: inherit; font-size: 16px;
  color: var(--chalk); background: var(--sunken); border: 1px solid var(--line-2); border-radius: 10px; }
.set-input:focus-visible { outline: 2px solid var(--steel); outline-offset: 1px; }

/* Destructive row: the only red in a settings screen, so it means something. */
.set-row.danger .set-lab { color: var(--danger-text); }
.set-row.danger .set-go { color: var(--danger-line); }
.set-row.danger:active { background: var(--danger-bg); }
@media (hover: hover) { .set-row.danger:hover { background: var(--danger-bg); } }

/* One line under a card, for the thing a row cannot say in four words. */
/* A team reads as a crest, a name and what is in it. */
.team-crest { flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 12px; background: var(--bg-2);
  font-family: var(--num); font-size: 19px; font-weight: 700; letter-spacing: 0.02em; color: #f2f6fc;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45); }
.team-row { gap: 12px; }
.team-row .set-lab b { display: block; font-size: 16px; font-weight: 700; }
.team-crest-card { display: flex; align-items: center; gap: 13px; padding: 13px; }
.team-crest-card .team-crest { width: 54px; height: 54px; border-radius: 14px; font-size: 23px; }
.team-crest-card .set-lab b { display: block; font-size: 17px; font-weight: 700; }

/* A range inside a row takes the space a value would. */
.set-row input[type="range"] { flex: 1 1 auto; min-width: 0; max-width: 190px; }
.set-row .fxbtn, .set-row .ghost { flex: 0 0 auto; margin: 0; }
.set-note { margin: 2px 2px 0; font-size: 13px; line-height: 1.5; color: var(--muted); }
.set-note a { color: var(--body); }

/* Batter strip: jersey number first, then name and who follows; pitcher on the right. */
.gm-num { flex: 0 0 auto; font-family: var(--num); font-size: 40px; font-weight: 700; line-height: 1; color: var(--chalk); }
.gm-num:empty { display: none; }
.gm-who { display: flex; flex-direction: column; min-width: 0; flex: 1; text-align: left; }
.gm-batter .gm-hitter { font-size: 17px; }
.gm-batter .gm-vs { font-size: 14px; color: var(--body); }
.gm-p { flex: 0 0 auto; display: flex; flex-direction: column; align-items: flex-end; }
.gm-p small { font-size: 11px; font-weight: 800; letter-spacing: 0.08em; color: var(--muted); }
.gm-p b { font-family: var(--num); font-size: 24px; font-weight: 700; color: var(--chalk); line-height: 1.05; }

/* Last play recorded, in words */
.last-play { margin: 2px 16px 0; padding: 10px 14px; border-radius: 12px; background: #16233a; border: 1px solid #2b4a78;
  color: var(--chalk); font-size: 17px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.last-play[hidden] { display: none; }
.last-play.undone { background: var(--card); border-color: var(--line-2); color: var(--body); }
@media (min-width: 700px) { .last-play { margin: 0; } }

/* Lineup: positions are read-only chips (tap = Field screen); save status in the header */
button.lineup-row .b-pos, .lineup-row .b-pos { text-align: center; }
.lineup-row .b-pos.none { color: var(--muted); }
button.fieldcheck { width: 100%; background: none; border: none; padding: 6px 2px; text-align: left; font-weight: 600; min-height: 40px; }
.lu-status[data-state="saved"] { color: var(--ball); font-weight: 700; }
.lu-status[data-state="failed"] { color: var(--out-ui); font-weight: 700; }

/* Announcement ticker (On Air). Presets fill the box; Show puts it up, and
   while it is up the same button reads Update. */
.tk-box { display: flex; flex-direction: column; gap: 8px; }
#tk-text { width: 100%; box-sizing: border-box; resize: none; padding: 12px 14px; font: inherit; font-size: 16px; line-height: 1.35;
  color: var(--chalk); background: var(--bg-2); border: 1px solid var(--line); border-radius: 12px; }
.tk-presets { display: flex; flex-wrap: wrap; gap: 6px; }
.tk-pre { padding: 8px 12px; border-radius: 999px; font-size: 13px; font-weight: 700;
  background: var(--bg-2); border: 1px solid var(--line); color: var(--chalk); }
.tk-pre:active { filter: brightness(1.2); }
.tk-row { display: flex; gap: 8px; align-items: stretch; }
.tk-tone { display: flex; border: 1px solid var(--line); border-radius: 12px; overflow: hidden; flex: 0 0 auto; }
.tk-tone button { padding: 0 12px; font-size: 13px; font-weight: 700; background: var(--bg-2); color: var(--muted); border: 0; }
.tk-tone button[aria-pressed="true"] { background: var(--steel); color: #06090f; }
.tk-tone #tk-tone-alert[aria-pressed="true"] { background: #e8a531; color: #1a1204; }
.onair-card .tk-row .fxbtn { flex: 1; min-height: 48px; margin: 0; width: auto; }
.onair-card .tk-row .fxbtn[hidden] { display: none; }
.tk-go.live { background: var(--steel); border-color: var(--steel); color: #06090f; }
#tk-state { color: var(--muted); }
#tk-state.on { color: #ff7a6e; }
.tk-chip { max-width: none; }

/* Game paused (On Air). */
.pz-box { display: flex; flex-direction: column; gap: 8px; }
.pz-reasons { display: flex; flex-wrap: wrap; gap: 6px; }
.pz-r { padding: 9px 12px; border-radius: 999px; font-size: 13px; font-weight: 700;
  background: var(--bg-2); border: 1px solid var(--line); color: var(--chalk); }
.pz-r[aria-pressed="true"] { background: #e8a531; border-color: #e8a531; color: #1a1204; }
.pz-timer { display: flex; align-items: center; gap: 6px; }
.pz-timer[hidden] { display: none; }
.pz-tl { font-size: 13px; color: var(--muted); margin-right: auto; }
.pz-timer .step { min-width: 46px; height: 44px; padding: 0 8px; font-size: 14px; font-weight: 700; border-radius: 10px;
  background: var(--bg-2); border: 1px solid var(--line); color: var(--chalk); }
.pz-mins { display: flex; align-items: center; gap: 4px; padding: 0 10px; height: 44px; border-radius: 10px;
  background: var(--bg-2); border: 1px solid var(--line); font-size: 13px; color: var(--muted); }
.pz-mins input { width: 2.4em; background: none; border: 0; padding: 0; color: var(--chalk);
  font: inherit; font-size: 20px; font-weight: 800; text-align: right; }
.onair-card .tk-row .pz-restart { background: #3a2d0a; border-color: #6b5214; color: #f5d98a; }

.pz-note { margin: 0; font-size: 12px; color: var(--muted); }
#pz-state.on { color: #ff7a6e; }

/* New Game: both teams, with a swap between them */
.ng-teams { display: grid; gap: 8px; margin-top: 12px; }
.ng-team { display: grid; gap: 6px; }
.ng-team .sel { flex: none; }
.ng-team select, .ng-team input { padding: 12px; font-size: 16px; background: var(--sunken); border: 1px solid var(--line);
  border-radius: 12px; color: var(--chalk); }
.ng-team input[hidden] { display: none; }
.ng-swap { justify-self: center; width: 44px; height: 32px; border-radius: 10px; background: var(--card);
  border: 1px solid var(--line-2); color: var(--chalk); font-size: 16px; }

/* Lineup quick entry: the jersey keypad and the paste box */
.lq-bar { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 10px 0; }
.lq-btn { padding: 11px 8px; border-radius: 12px; background: var(--card); border: 1px solid var(--line-2); color: var(--chalk);
  font-size: 14px; font-weight: 700; }
.lq-keys, .lq-paste { display: grid; gap: 10px; margin-bottom: 12px; }
.lq-keys[hidden], .lq-paste[hidden] { display: none; }
.lq-typed { display: flex; align-items: baseline; gap: 12px; padding: 8px 14px; background: var(--card);
  border: 1px solid var(--line); border-radius: 14px; }
.lq-typed b { font: 600 40px/1 var(--num); min-width: 2ch; font-variant-numeric: tabular-nums; color: var(--chalk); }
.lq-typed span { color: var(--muted); font-size: 13px; }
.lq-pad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.lq-pad button { height: 56px; border-radius: 14px; background: var(--bg-2); border: 1px solid var(--line-2); color: var(--chalk);
  font: 600 28px/1 var(--num); }
.lq-pad button:active { filter: brightness(1.25); }
.lq-pad .lq-next { background: var(--steel); border-color: var(--steel); color: #06090f; font-size: 20px; }
.lq-done { border-radius: 12px; padding: 12px; }
.lq-paste textarea { width: 100%; box-sizing: border-box; padding: 12px; border-radius: 12px; background: var(--sunken);
  border: 1px solid var(--line); color: var(--chalk); font: 15px/1.5 var(--mono); resize: vertical; }
/* An opponent's empty spots are information, not a to-do. */
.fieldcheck.optional { background: var(--card); border-color: var(--line); color: var(--muted); }
