/* Timer dock (card/strip), timer takeover, Call to courts, Welcome, End celebration. */

/* =====================================================================
   Timer dock: card on Expanded, strip on Medium/Compact
   ===================================================================== */
.timer-dock {
  /* R4-08: --radius-3 at every size, so the Expanded right column (dock + panels) shares one radius. */
  position: relative; overflow: hidden; border-radius: var(--radius-3); padding: var(--card-pad-y) var(--card-pad);
  display: grid; gap: var(--space-2) var(--space-3);
  grid-template-columns: 1fr auto;
  grid-template-areas: "head head" "display controls" "ring ring" "stop stop";
  align-items: center;
  transition: background var(--dur-slow) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.timer-dock__head { grid-area: head; display: flex; align-items: center; gap: var(--space-2); min-height: 28px; }
.timer-dock__label { color: var(--text2); }
.timer-dock__state {
  display: inline-flex; align-items: center; gap: var(--space-2); height: 24px; padding: 0 10px; border-radius: var(--radius-full);
  font-family: var(--font-family-mono); font-size: var(--t-micro); font-weight: 700; letter-spacing: var(--track-caps); text-transform: uppercase; border: 1px solid var(--line-strong); /* R4-06 micro */
}
/* R2-05: the chip only speaks up for Paused / Last 30 s / Time up. */
.timer-dock[data-status="idle"] .timer-dock__state,
.timer-dock[data-status="running"]:not([data-critical="true"]) .timer-dock__state { display: none; }
.timer-dock__display { grid-area: display; text-align: left; min-width: 0; min-height: 48px; padding: 0; container-type: inline-size; } /* R2-22: 48px tall target */
/* The clock is --clock-em wide (fixed .dg/.dc cells, set by paintDigits), so every size class caps
   its font at the display's width (96cqi: a hair of air for glyphs wider than their cell). */
.timer-dock__digits { --clock-cap: calc(96cqi / var(--clock-em)); display: block; font-size: min(var(--t-num-lg), var(--clock-cap)); font-weight: 800; letter-spacing: -0.05em; line-height: 0.95; white-space: nowrap; }
.timer-dock__ring { grid-area: ring; height: 8px; border-radius: 4px; background: linear-gradient(90deg, var(--progress) calc(var(--timer-progress, 1) * 100%), var(--line) 0); overflow: hidden; }
.timer-dock__stop {
  grid-area: stop; min-height: var(--btn-lg); border-radius: var(--radius-full); background: #fff; color: var(--nub-ink); font-size: var(--t-btn-lg); font-weight: 800;
}
.timer-dock__controls { grid-area: controls; display: flex; align-items: center; gap: var(--space-2); }
.timer-dock__btn {
  position: relative; display: inline-flex; align-items: center; justify-content: center; min-width: var(--btn-sm); height: var(--btn-sm); padding: 0 var(--space-4);
  border-radius: var(--radius-full); border: var(--stroke-control) solid var(--line-strong); font-weight: 700; font-size: var(--t-btn-sm); color: var(--text);
  transition: transform var(--dur-fast) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.timer-dock__btn:active { transform: scale(0.93); }
.timer-dock__btn--reset { width: var(--btn-sm); padding: 0; }
.timer-dock__btn--play { width: var(--btn-lg); height: var(--btn-lg); padding: 0; background: var(--control); color: var(--controltext); border-color: transparent; box-shadow: var(--shadow-control); } /* R2-21: Next round is the screen's one lime primary */
/* R3-01 / R3-01b: "ready to start" (timer on and idle, round untouched). Play is the screen's
   one lime primary - the same lime, ink glyph and halo as the takeover's Play disc - while
   Next round steps down to the outline (chrome.css .cmd-btn--next.is-quiet). */
.timer-dock__btn--play.is-primary {
  background: var(--accent-fill); color: var(--on-accent);
  box-shadow: var(--accent-edge), 0 0 0 6px rgba(var(--breathe-rgb), 0.16), 0 10px 28px rgba(var(--breathe-rgb), 0.3);
}
/* One-shot "breathe" when Call to courts hands over (callToCourts.js adds .is-breathe): the disc
   swells once while a ring ripples out. The ring is a pseudo-element so the resting halo holds. */
.timer-dock__btn--play::after {
  content: ''; position: absolute; inset: -2px; border-radius: 50%; pointer-events: none; opacity: 0;
  box-shadow: 0 0 0 3px rgba(var(--breathe-rgb), 0.7);
}
/* Leaving the state: the dock and command bar are rebuilt on every change, so a CSS transition
   cannot run; timerDock.js / main.js add .is-handoff (with a negative delay across re-renders)
   and these keyframes fade the lime out of Play while Next round fills with it - the baton pass. */
@media (prefers-reduced-motion: no-preference) {
  .timer-dock__btn--play.is-breathe { animation: ready-breathe var(--dur-hero) var(--ease-out) 1; }
  .timer-dock__btn--play.is-breathe::after { animation: ready-ring var(--dur-hero) var(--ease-out) 1; }
  .timer-dock__btn--play.is-handoff { animation: play-handoff var(--dur-enter) var(--ease-out) both; }
}
@keyframes ready-breathe { 0%, 100% { transform: scale(1); } 40% { transform: scale(1.06); } }
@keyframes ready-ring { 0% { opacity: 1; transform: scale(1); } 100% { opacity: 0; transform: scale(1.45); } }
@keyframes play-handoff {
  from { background: var(--accent-fill); color: var(--on-accent); box-shadow: var(--accent-edge), 0 0 0 6px rgba(var(--breathe-rgb), 0.16), 0 10px 28px rgba(var(--breathe-rgb), 0.3); }
}
.timer-dock__armed-hint, .timer-overlay__armed-hint { display: none; }
.is-armed .timer-dock__armed-hint, .is-armed .timer-overlay__armed-hint {
  display: block; position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%); white-space: nowrap;
  padding: var(--space-1) var(--space-3); border-radius: var(--radius-1); background: var(--text); color: var(--bg); font-size: var(--t-micro); font-weight: 700; z-index: 3;
}
.is-armed { border-color: var(--live); color: var(--live); }

/* states */
.timer-dock[data-status="running"] { border-color: var(--accent-line); box-shadow: var(--shadow-2), var(--glow-lime); }
.timer-dock[data-status="running"] .timer-dock__state { color: var(--accent); border-color: var(--accent-line); }
.timer-dock[data-status="running"] .timer-dock__state::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: var(--accent-fill); animation: live-dot var(--dur-pulse-slow) ease-in-out infinite; }
.timer-dock[data-status="paused"] .timer-dock__digits { opacity: 0.55; animation: breathe var(--dur-breathe) ease-in-out infinite; }
.timer-dock[data-status="paused"] .timer-dock__ring { background: repeating-linear-gradient(90deg, var(--text3) 0 8px, transparent 8px 14px); }
.timer-dock[data-status="paused"] .timer-dock__state { color: var(--live); border-color: var(--live); }
@keyframes breathe { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.8; } }
.timer-dock[data-critical="true"] {
  background: #000; border-color: var(--critical-ring); color: #fff; box-shadow: 0 0 0 3px color-mix(in srgb, var(--critical-ring) 50%, transparent), 0 0 40px color-mix(in srgb, var(--critical-ring) 40%, transparent);
  -webkit-backdrop-filter: none; backdrop-filter: none; animation: red-pulse var(--dur-pulse) ease-in-out infinite;
}
.timer-dock[data-critical="true"] .timer-dock__digits { color: #fff; }
.timer-dock[data-critical="true"][data-flash="a"] .timer-dock__digits { color: var(--flash-yellow); }
.timer-dock[data-critical="true"] .timer-dock__ring { background: linear-gradient(90deg, var(--critical-ring) calc(var(--timer-progress, 1) * 100%), var(--on-red-line) 0); }
.timer-dock[data-critical="true"] .timer-dock__btn { color: #fff; border-color: var(--on-red-line-strong); }
.timer-dock[data-critical="true"] .timer-dock__btn--play { background: #fff; color: #000; }
.timer-dock[data-critical="true"] .timer-dock__state { color: #fff; border-color: var(--on-red-line-strong); }
.timer-dock[data-status="expired"] { background: var(--time-up); border-color: transparent; color: #fff; box-shadow: 0 0 40px color-mix(in srgb, var(--time-up) 55%, transparent); -webkit-backdrop-filter: none; backdrop-filter: none; }
.timer-dock[data-status="expired"] .timer-dock__digits { animation: blink var(--dur-pulse) steps(2, start) infinite; }
.timer-dock[data-status="expired"] .timer-dock__state { color: #fff; border-color: #fff; background: var(--on-red-soft); }
.timer-dock[data-status="expired"] .timer-dock__ring { background: var(--on-red-line); }
.timer-dock[data-status="expired"] .timer-dock__btn { color: #fff; border-color: var(--on-red-line-strong); }
.timer-dock[data-status="expired"] .timer-dock__btn--play { background: #fff; color: var(--time-up); }
/* R1-17: the low point stays legible (white on red at .6 is still well above 3:1). */
@keyframes blink { 50% { opacity: 0.6; } }

/* Expanded: card */
@media (min-width: 1024px) {
  /* minmax(0, 1fr): the controls row's min-content (274px) outgrew the 300px panel's 260px content
     box and widened the column, and so the digits' container, past the card. */
  .timer-dock { padding: var(--card-pad); gap: var(--space-3); grid-template-columns: minmax(0, 1fr); grid-template-areas: "head" "display" "ring" "stop" "controls"; }
  .timer-dock__display { text-align: center; }
  .timer-dock__digits { font-size: min(clamp(120px, 9vw, 150px), var(--clock-cap)); } /* "12:00" at 150px is 405px: wider than any panel */
  .timer-dock__controls { justify-content: space-between; margin-top: var(--space-1); }
  .timer-dock__btn { height: var(--btn-md); min-width: var(--btn-md); }
  .timer-dock__btn--reset { width: var(--btn-md); }
  .timer-dock__btn--play { width: var(--btn-xl); height: var(--btn-xl); flex-shrink: 0; } /* stays round when the ±30s buttons give way in a 300px panel */
}
/* Expanded on a short viewport (R1-02): tighter card so the panel's Up next stays in view. */
@media (min-width: 1024px) and (max-height: 899px) {
  .timer-dock { padding: var(--space-3) var(--card-pad); gap: var(--space-2); }
  .timer-dock__digits { font-size: min(clamp(96px, 8vw, 116px), var(--clock-cap)); }
  .timer-dock__controls { margin-top: 2px; }
  .timer-dock__stop { min-height: var(--btn-md); font-size: var(--t-btn-md); }
}
/* Medium: strip, digits 64px */
@media (max-width: 1023px) {
  .timer-dock { padding: var(--space-3) var(--space-4); } /* the strip: a tighter, symmetric inset */
}
/* Compact strip: digits 44px, fewer controls */
@media (max-width: 759px) {
  .timer-dock { padding: var(--space-2) var(--space-3); gap: var(--space-1) var(--space-2); }
  .timer-dock__digits { font-size: min(var(--t-num-md), var(--clock-cap)); }
  .timer-dock__btn--play { width: var(--btn-md); height: var(--btn-md); }
  .timer-dock__btn:not(.timer-dock__btn--play):not(.timer-dock__btn--reset) { display: none; }
  .timer-dock__head { min-height: 22px; }
}

/* =====================================================================
   Timer takeover
   ===================================================================== */
.timer-overlay {
  position: fixed; inset: 0; z-index: 50; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(8px, 2vh, 20px); padding: 72px 5vw calc(20px + env(safe-area-inset-bottom, 0px)); color: var(--text);
  background: var(--sky-1), var(--sky-2), var(--sky-3), var(--bg); animation: fade-in var(--dur-base) both;
  overflow: hidden;
}
.timer-overlay::before { /* net mesh */
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0.5;
  background: repeating-linear-gradient(45deg, transparent 0 13px, var(--line) 13px 14px), repeating-linear-gradient(-45deg, transparent 0 13px, var(--line) 13px 14px);
  -webkit-mask: radial-gradient(ellipse at center, transparent 30%, #000 100%); mask: radial-gradient(ellipse at center, transparent 30%, #000 100%);
}
.timer-overlay > * { position: relative; }
.timer-overlay__close {
  position: absolute; top: calc(16px + env(safe-area-inset-top, 0px)); right: 16px; width: 56px; height: 56px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; border: 1px solid var(--line-strong); background: var(--glass-solid); z-index: 3;
}
.timer-overlay__kicker { font-family: var(--font-family-mono); font-size: var(--t-kicker-lg); font-weight: 700; letter-spacing: var(--track-caps-lg); text-transform: uppercase; color: var(--text2); } /* R4-06: the one large mono */
.timer-overlay__face { position: relative; display: flex; flex-direction: column; align-items: center; padding: 0 2vw; max-width: 100%; }
.timer-overlay__digits {
  /* Never wider than the overlay and face side padding leave (86vw) for a --clock-em-wide string. */
  display: block; font-size: min(max(120px, min(31vw, 44vh)), 86vw / var(--clock-em)); font-weight: 800; letter-spacing: 0; line-height: 0.9; white-space: nowrap;
}
.timer-overlay__face::after {
  content: ''; display: block; width: 100%; height: 10px; margin-top: clamp(10px, 2vh, 22px); border-radius: 5px;
  background: linear-gradient(90deg, var(--progress) calc(var(--timer-progress, 1) * 100%), var(--line-strong) 0); /* R2-08 */
}
.timer-overlay__state {
  display: inline-flex; align-items: center; gap: var(--space-2); height: 32px; padding: 0 var(--space-4); border-radius: var(--radius-full);
  font-family: var(--font-family-mono); font-size: var(--t-micro); font-weight: 700; letter-spacing: var(--track-caps); text-transform: uppercase; border: 1px solid var(--line-strong);
}
.timer-overlay__hint { color: var(--text2); }
.timer-overlay__stop-buzzer-btn {
  /* The one control above the ladder: the loudest moment in the app (documented exception). */
  min-height: 88px; padding: 0 56px; border-radius: var(--radius-full); background: #fff; color: var(--nub-ink);
  font-size: var(--t-num-sm); font-weight: 800; letter-spacing: -0.02em; box-shadow: var(--shadow-3); animation: pop-in var(--dur-slow) var(--ease-spring) both;
}
@keyframes pop-in { from { transform: scale(0.85); opacity: 0; } to { transform: none; opacity: 1; } }
.timer-overlay__adjust { display: flex; align-items: center; justify-content: center; gap: var(--space-3); }
.timer-overlay__adjust-btn { min-height: var(--btn-md); min-width: 96px; padding: 0 var(--space-5); border-radius: var(--radius-full); border: var(--stroke-control) solid var(--line-strong); font-size: var(--t-btn-md); font-weight: 800; background: var(--glass-solid); } /* R4-07 md */
/* Reset leads the adjust row: same height and outline as the nudges, square-round with the icon. */
.timer-overlay__adjust-btn--icon { position: relative; display: inline-flex; align-items: center; justify-content: center; min-width: var(--btn-md); padding: 0; border-radius: 50%; }
.timer-overlay__adjust-btn:active { transform: scale(0.94); }
.timer-overlay__controls { display: flex; align-items: center; gap: clamp(16px, 4vw, 40px); margin-top: 4px; }
.timer-overlay__play-btn:active { transform: scale(0.92); }
.timer-overlay__play-btn {
  width: 112px; height: 112px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--accent-fill); color: var(--on-accent); box-shadow: var(--accent-edge), 0 0 0 10px rgba(var(--breathe-rgb), 0.14), 0 16px 44px rgba(var(--breathe-rgb), 0.3); /* R3-13 */
  transition: transform var(--dur-fast) var(--ease-out);
}
.timer-overlay__play-btn svg { width: 44px; height: 44px; }
.timer-overlay[data-status="running"] .timer-overlay__state { color: var(--accent); border-color: var(--accent-line); }
.timer-overlay[data-status="paused"] .timer-overlay__digits { animation: breathe var(--dur-breathe) ease-in-out infinite; }
.timer-overlay[data-status="paused"] .timer-overlay__face::after { background: repeating-linear-gradient(90deg, var(--text3) 0 10px, transparent 10px 18px); }
.timer-overlay[data-status="paused"] .timer-overlay__state { color: var(--live); border-color: var(--live); }

/* critical: pure black, no glass, yellow/white flash, red pulsing perimeter ring */
.timer-overlay[data-critical="true"] { background: #000; color: #fff; --text: #fff; --text2: #fff; --text3: #ddd; --line: var(--on-red-line); --line-strong: var(--on-red-line-strong); --glass-solid: #111; }
.timer-overlay[data-critical="true"]::before { display: none; }
.timer-overlay[data-critical="true"]::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 2; animation: perimeter var(--dur-pulse) ease-in-out infinite;
}
@keyframes perimeter {
  0%, 100% { box-shadow: inset 0 0 0 6px color-mix(in srgb, var(--critical-ring) 35%, transparent); }
  50% { box-shadow: inset 0 0 0 14px var(--critical-ring), inset 0 0 90px color-mix(in srgb, var(--critical-ring) 35%, transparent); }
}
.timer-overlay[data-critical="true"] .timer-overlay__digits { color: #fff; animation: tick-scale var(--dur-pulse) ease-in-out infinite; }
.timer-overlay[data-critical="true"][data-flash="a"] .timer-overlay__digits { color: var(--flash-yellow); }
.timer-overlay[data-critical="true"] .timer-overlay__face::after { background: linear-gradient(90deg, var(--critical-ring) calc(var(--timer-progress, 1) * 100%), var(--on-red-line) 0); }
.timer-overlay[data-critical="true"] .timer-overlay__play-btn { background: #fff; color: #000; box-shadow: 0 0 0 10px var(--on-red-soft); }
@keyframes tick-scale { 0% { transform: scale(1); } 50% { transform: scale(1.03); } 100% { transform: scale(1); } }

/* expired: the loudest thing in the app */
.timer-overlay[data-status="expired"] { background: var(--time-up); color: #fff; --text: #fff; --text2: #fff; --text3: #ffd6d6; --line: var(--on-red-line); --line-strong: var(--on-red-line-strong); --glass-solid: var(--on-red-soft); }
.timer-overlay[data-status="expired"]::before { display: none; }
.timer-overlay[data-status="expired"] .timer-overlay__digits { color: #fff; animation: blink var(--dur-pulse) steps(2, start) infinite; }
.timer-overlay[data-status="expired"] .timer-overlay__state { font-size: var(--t-kicker-lg); letter-spacing: var(--track-caps-lg); height: var(--btn-sm); padding: 0 var(--space-5); background: #fff; color: var(--time-up); border-color: #fff; }
.timer-overlay[data-status="expired"] .timer-overlay__face::after { background: var(--on-red-line); }
.timer-overlay[data-status="expired"] .timer-overlay__play-btn { background: #fff; color: var(--time-up); box-shadow: 0 0 0 10px var(--on-red-soft); }
/* R1-17: expired - Play becomes a small outline "Restart"; Next round is promoted once silenced. */
.timer-overlay__btn-label { font-size: var(--t-micro); font-weight: 800; letter-spacing: 0.02em; }
.timer-overlay[data-status="idle"] .timer-overlay__state { display: none; }
@media (max-width: 759px) {
  .timer-overlay__play-btn:not(.is-restart) { width: 96px; height: 96px; }
} /* R2-16: the Play disc + hint already say "ready" */
.timer-overlay__play-btn.is-restart {
  width: var(--btn-xl); height: var(--btn-xl); flex-direction: column; gap: 2px; background: transparent !important; color: #fff !important;
  border: var(--stroke-control) solid var(--on-red-line-strong); box-shadow: none !important;
}
.timer-overlay__play-btn.is-restart svg { width: 24px; height: 24px; }
/* The dock's Play while expired: an outline restart, not a white disc beside Stop buzzer. */
.timer-dock[data-status="expired"] .timer-dock__btn--play { background: transparent; color: #fff; border: var(--stroke-control) solid var(--on-red-line-strong); box-shadow: none; }

/* R1-18: keep the critical / expired treatment in Windows High Contrast (forced colours). */
@media (forced-colors: active) {
  .timer-dock[data-critical="true"], .timer-overlay[data-critical="true"],
  .timer-dock[data-status="expired"], .timer-overlay[data-status="expired"], .time-up-banner { forced-color-adjust: none; }
}

@media (max-height: 560px) { .timer-overlay { padding-top: 56px; } .timer-overlay__play-btn { width: var(--btn-xl); height: var(--btn-xl); } .timer-overlay__stop-buzzer-btn { min-height: var(--btn-lg); font-size: var(--t-title-sm); } }

/* =====================================================================
   Call to courts
   ===================================================================== */
.call {
  position: fixed; inset: 0; z-index: 45; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4);
  padding: calc(28px + env(safe-area-inset-top, 0px)) 5vw calc(28px + env(safe-area-inset-bottom, 0px));
  background: radial-gradient(70% 55% at 50% -8%, rgba(255, 138, 61, 0.38), transparent 70%), var(--sky-2), var(--sky-3), var(--bg);
  animation: fade-in var(--dur-base) both;
}
.call__head { display: flex; align-items: baseline; gap: var(--space-4); }
.call__round { font-size: clamp(48px, 8vw, 104px); font-weight: 800; font-style: italic; letter-spacing: -0.05em; line-height: 0.95; }
.call__of { font-size: var(--t-kicker-lg); font-weight: 700; text-transform: uppercase; letter-spacing: var(--track-caps-lg); color: var(--text2); }
/* R1-21: courts flow from the top with the Sitting out band right under them; actions stick to the bottom. */
.call__courts { display: flex; flex-direction: column; justify-content: flex-start; gap: var(--space-4); }
/* the number tile sits 16px (+1) in on three sides; nested radius 32 - 16 -> --radius-2 */
.call__court {
  display: grid; grid-template-columns: auto 1fr auto 1fr; align-items: center; gap: var(--space-4) var(--space-5);
  padding: var(--space-4) var(--space-6) var(--space-4) var(--space-4); border-radius: var(--radius-4); background: var(--glass-solid); background-color: var(--surface);
  border: 1px solid var(--line-strong); box-shadow: var(--shadow-2);
}
.call__court-num {
  display: flex; flex-direction: column; align-items: center; justify-content: center; width: 112px; min-height: 96px; border-radius: var(--radius-2);
  background: var(--control); color: var(--controltext); font-family: var(--font-family-sans); font-size: var(--t-num-lg); font-weight: 800; letter-spacing: -0.05em; line-height: 0.95;
}
.call__court-num small { font-family: var(--font-family-mono); font-size: var(--t-micro); font-weight: 700; letter-spacing: var(--track-caps); }
.call__team { font-size: var(--t-call); font-weight: 800; letter-spacing: -0.04em; line-height: 1.02; overflow-wrap: anywhere; }
.call__vs { font-family: var(--font-family-sans); font-size: clamp(20px, 2.4vw, 32px); font-style: italic; font-weight: 700; color: var(--accent); text-transform: lowercase; }
.call__none { font-size: var(--t-title); font-weight: 800; letter-spacing: -0.03em; text-align: center; padding: 60px 0; }
.call__sitting {
  display: flex; align-items: center; gap: var(--space-4); flex-wrap: wrap; padding: var(--space-4) var(--space-5); border-radius: var(--radius-3);
  background: var(--tile-olive); color: var(--tile-olive-ink);
}
.call__sitting-label { color: inherit; opacity: 0.9; }
.call__sitting-names { font-size: var(--t-num-sm); font-weight: 800; letter-spacing: -0.02em; }
.call__actions { display: flex; gap: var(--space-3); align-items: center; justify-content: center; padding-top: var(--space-2); position: sticky; bottom: 0; margin-top: auto; }
/* .call__start is .btn--xl: the one 72 / 22 hero CTA (R4-07) */
@media (prefers-reduced-motion: no-preference) {
  /* R3-07: 60ms per court, 320ms each; "Sitting out" follows the last court (courts x 60ms)
     instead of arriving 850ms late - who sits is the first thing players ask. */
  .call__court { animation: call-in var(--dur-enter) var(--ease-out) both; animation-delay: calc(min(var(--i, 0), 6) * 60ms); }
  .call__sitting { animation: call-in var(--dur-enter) var(--ease-out) both; animation-delay: calc(min(var(--n, 1), 7) * 60ms); }
}
@keyframes call-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
@media (max-width: 759px) {
  .call__actions { flex-wrap: wrap; }
  .call__actions .btn { flex: 1 1 100%; }
  /* R1-08: above the two stacked 72px action buttons (~190px), never over the "Round N" heading. */
  body:has(.call__court) #toast-root, body:has(.call__none) #toast-root { top: auto; bottom: calc(200px + env(safe-area-inset-bottom, 0px)); }
}
@media (max-width: 1023px) {
  .call__court { grid-template-columns: auto 1fr; padding: var(--space-4); }
  .call__court-num { grid-row: span 3; width: 84px; min-height: 84px; font-size: var(--t-num-md); }
  .call__vs { grid-column: 2; }
}

/* =====================================================================
   Welcome
   ===================================================================== */
/* Welcome is a standalone intro (no top bar to align to), so it keeps its own centred measure. */
.welcome { max-width: 900px; margin: 0 auto; position: relative; display: grid; gap: var(--space-5); padding: var(--space-3) 0 var(--space-5); align-content: center; min-height: calc(100dvh - var(--topbar-h) - 60px); }
@media (min-width: 1024px) { .welcome { max-width: 1200px; } }
.welcome__hero { position: relative; z-index: 1; display: flex; flex-direction: column; gap: var(--space-4); max-width: 640px; }
.welcome__mark { display: none; }
.welcome__title { font-size: var(--t-display); font-weight: 800; font-style: italic; letter-spacing: -0.045em; line-height: 0.96; }
.welcome__lead { font-size: var(--t-lead); color: var(--text2); max-width: 34ch; }
.welcome::before { /* ball, half cropped */
  content: ''; position: absolute; z-index: 0; right: -6%; top: -4%; width: min(46vw, 420px); aspect-ratio: 1;
  background: url('../assets/ball.svg') center / contain no-repeat; filter: drop-shadow(0 30px 40px rgba(0, 0, 0, 0.45));
  animation: ball-spin 90s linear infinite; pointer-events: none;
}
.welcome::after { /* court lines */
  content: ''; position: absolute; z-index: 0; inset: 30% -10% -10% 30%; background: var(--line-strong); opacity: 0.3; transform: rotate(-8deg); pointer-events: none;
  -webkit-mask: url('../assets/court-lines.svg') no-repeat center / contain; mask: url('../assets/court-lines.svg') no-repeat center / contain;
}
.welcome__steps { position: relative; z-index: 1; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap-tile); }
.welcome__step {
  position: relative; overflow: hidden; display: flex; flex-direction: column; gap: var(--space-2); padding: var(--card-pad); border-radius: var(--radius-3);
  background: var(--glass-solid); background-color: var(--surface); border: 1px solid var(--line-strong); min-height: 150px; box-shadow: var(--shadow-2);
}
.welcome__step-num { font-family: var(--font-family-sans); font-size: var(--t-num-lg); font-weight: 800; font-style: italic; letter-spacing: -0.06em; line-height: 0.9; color: var(--accent); }
.welcome__step-title { font-size: var(--t-section); font-weight: 800; letter-spacing: -0.03em; }
.welcome__step-text { color: var(--text2); font-size: var(--t-body); line-height: 1.4; }
.welcome__tip { position: relative; z-index: 1; display: flex; gap: var(--space-3); align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-4); border-radius: var(--radius-2); background: var(--glass-solid); border: 1px solid var(--line); }
.welcome__actions { position: relative; z-index: 1; display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; }
/* .welcome__start is .btn--lg (64 / 19; was 68 / 20) */
@media (prefers-reduced-motion: no-preference) {
  .welcome__title, .welcome__lead, .welcome__step, .welcome__actions { animation: fade-rise var(--dur-hero) var(--ease-out) both; }
  .welcome__lead { animation-delay: 0.08s; }
  .welcome__step:nth-child(1) { animation-delay: 0.16s; } .welcome__step:nth-child(2) { animation-delay: 0.24s; } .welcome__step:nth-child(3) { animation-delay: 0.32s; }
  .welcome__actions { animation-delay: 0.4s; }
}
@media (max-width: 759px) {
  .welcome__steps { grid-template-columns: 1fr; }
  .welcome__step { min-height: 0; flex-direction: row; align-items: center; gap: var(--space-4); padding: var(--card-pad); }
  .welcome__step-num { font-size: var(--t-num-md); flex: none; width: 1.1em; text-align: center; } /* R1-22: titles share one x */
  .welcome::before { width: 150px; right: -44px; top: -26px; opacity: 0.4; }
  .welcome__actions .btn { flex: 1; }
}

/* =====================================================================
   End: champion celebration
   ===================================================================== */
.end-hero { position: relative; overflow: hidden; border-radius: var(--radius-4); padding: var(--card-pad-hero); margin-bottom: var(--gap-tile); background: var(--tile-lime); color: var(--on-accent); box-shadow: var(--shadow-3); }
.end-hero::before { /* ball, cropped */
  content: ''; position: absolute; right: -40px; bottom: -60px; width: 300px; height: 300px; background: url('../assets/ball.svg') center / contain no-repeat; opacity: 0.55; transform: rotate(-20deg); pointer-events: none;
}
.end-hero::after { /* court lines */
  content: ''; position: absolute; inset: 0; background: rgba(16, 21, 10, 0.5); opacity: 0.16; pointer-events: none;
  -webkit-mask: url('../assets/court-lines.svg') no-repeat left -12% top -40% / 62% auto; mask: url('../assets/court-lines.svg') no-repeat left -12% top -40% / 62% auto;
}
.end-hero > * { position: relative; z-index: 1; }
.end-hero__kicker { font-family: var(--font-family-mono); font-size: var(--t-micro); font-weight: 700; letter-spacing: var(--track-caps); text-transform: uppercase; opacity: 0.8; }
.end-hero__title { font-size: var(--t-display); font-weight: 800; font-style: italic; letter-spacing: -0.045em; line-height: 0.98; margin-top: var(--space-2); }
.champion__block { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-3); }
.champion__label { color: inherit; opacity: 0.85; display: inline-flex; align-items: center; gap: var(--space-2); }
.champion__label::before { content: ''; width: 14px; height: 14px; background: currentColor; -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 1.5c.7 5.6 4.9 9.8 10.5 10.5-5.6.7-9.8 4.9-10.5 10.5C11.3 16.9 7.1 12.7 1.5 12 7.1 11.3 11.3 7.1 12 1.5z'/></svg>") center / contain no-repeat; mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 1.5c.7 5.6 4.9 9.8 10.5 10.5-5.6.7-9.8 4.9-10.5 10.5C11.3 16.9 7.1 12.7 1.5 12 7.1 11.3 11.3 7.1 12 1.5z'/></svg>") center / contain no-repeat; }
.champion__name { font-size: clamp(44px, 7.4vw, 96px); font-weight: 800; font-style: italic; letter-spacing: -0.05em; line-height: 0.95; overflow-wrap: anywhere; }
.champion__name--multi { font-size: var(--t-display); }
.champion__stats { font-size: var(--t-data); font-weight: 600; opacity: 0.85; margin-top: var(--space-1); } /* R4-06: mono data */
/* R1-10: End layout. Compact/Medium: one column (hero, 2nd/3rd, highlights, table).
   Expanded: hero + podium + highlights on the left, the final table on the right (ux 4.10). */
.end-layout { display: flex; flex-direction: column; }
.end-main { display: flex; flex-direction: column; min-width: 0; }
.end-table { min-width: 0; }
.podium--runners-up { grid-template-columns: 1fr 1fr; align-items: end; }
.podium--runners-up .podium__slot--2 { min-height: 150px; }
.podium--runners-up .podium__slot--3 { min-height: 128px; }
@media (min-width: 1024px) {
  .end-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 var(--gap-tile); align-items: start; }
  .end-table .end-table-title { margin-top: 4px; }
  /* R3-03: the table sizes its own columns to the width it gets (container query below). */
  .end-table { container-type: inline-size; }
}
/* R3-03: on a 1024 iPad the table column is ~420px; give it a little more of the row... */
@media (min-width: 1024px) and (max-width: 1139px) {
  .end-layout { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
  /* the three End actions keep one row in the narrower left column */
  .end-actions { flex-wrap: nowrap; gap: 8px; }
  .end-actions .btn-outline { flex: 1 1 auto; min-width: 0; padding: 0 var(--space-4); }
}
/* ...and tighten the stat columns (76/56/104 + 20px gaps -> 44/52/100 + 12px) so a name keeps
   ~120px. Names wrap onto a second line rather than truncate: the celebration never shows "Fr...". */
@container (max-width: 560px) {
  .end-table .standings-row, .end-table .standings-head { gap: 12px; padding-right: 14px; }
  .end-table .standings-row__stats { grid-template-columns: 44px 52px 100px; column-gap: 12px; }
  .end-table .standings-row__points { min-width: 0; font-size: var(--t-num-sm); }
  .end-table .standings-row__pfpa { min-width: 0; }
  .end-table .standings-row__name { min-width: 8ch; font-size: var(--t-section); line-height: 1.1; white-space: normal; overflow-wrap: break-word; text-overflow: clip; }
}
.content-inner--end .podium__slot--1 { background: var(--glass-solid); background-color: var(--surface); color: var(--text); border-color: var(--accent-line); box-shadow: var(--shadow-2), var(--glow-lime); }
.content-inner--end .podium__slot--1::after { display: none; }
.end-table-title { margin: var(--space-5) var(--space-1) var(--space-3); }
.highlights { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--gap-tile); margin: var(--gap-tile) 0 var(--space-2); } /* R2-25: 2-3 cards */
.highlight { border-radius: var(--radius-3); padding: var(--card-pad-y) var(--card-pad); display: flex; flex-direction: column; gap: var(--space-2); min-width: 0; }
.highlight__value { font-size: var(--t-num-sm); font-weight: 800; letter-spacing: -0.04em; line-height: 1.05; overflow-wrap: anywhere; }
.highlight__sub { color: var(--text2); }
/* R2-04: a plain row under the hero/podium (not a second sticky bottom bar). */
.end-actions { display: flex; gap: var(--space-3); flex-wrap: wrap; align-items: center; margin: var(--gap-tile) 0 var(--space-1); }
.end-actions .btn-outline { min-height: var(--btn-sm); padding: 0 20px; font-size: var(--t-btn-sm); } /* R4-07 sm */
.end-hero__again { margin-top: var(--space-3); font-size: var(--t-hint); font-weight: 600; opacity: 0.8; }

/* R2-04: clipped to the hero, so it never draws over the top bar. */
.end-hero > .confetti { position: absolute; inset: 0; pointer-events: none; overflow: hidden; z-index: 0; }
/* R3-06: the burst lives on the ball side of the hero (sessionEnd.js places bits at 58-98%),
   feathered in so no piece ever crosses the champion's name or the stats line. */
.end-hero > .confetti { -webkit-mask-image: linear-gradient(90deg, transparent 56%, #000 72%); mask-image: linear-gradient(90deg, transparent 56%, #000 72%); }
.champion__stats, .end-hero__again { text-wrap: balance; }
.end-hero__again { max-width: 44ch; }
/* R3-06: the champion moment (ux 4.10 "Micro"): the name settles in from 92% while the points
   count up once (sessionEnd.js). Only on the celebrate render, never on revisits. */
@media (prefers-reduced-motion: no-preference) {
  .end-hero.is-celebrating .champion__name { transform-origin: 0 80%; animation: champion-in var(--dur-slow) var(--ease-out) 160ms both; }
  .end-hero.is-celebrating .champion__label { animation: fade-in var(--dur-enter) var(--ease-out) 80ms both; }
}
@keyframes champion-in { from { opacity: 0; transform: scale(0.92); } to { opacity: 1; transform: none; } }
.champion__pts { font-variant-numeric: tabular-nums; }
.confetti__bit {
  position: absolute; top: -24px; left: var(--x); width: 10px; height: 18px; border-radius: 2px; transform: rotate(var(--r));
  animation: confetti-fall 2.6s var(--d, 0s) cubic-bezier(0.3, 0.6, 0.5, 1) forwards; opacity: 0;
}
/* UX note: the confetti falls inside the lime hero, so no lime/cream bits (they vanish on it). */
.confetti__bit:nth-child(5n+1) { background: var(--nub-ink); }
.confetti__bit:nth-child(5n+2) { background: var(--ember-500); }
.confetti__bit:nth-child(5n+3) { background: var(--sun-400); }
.confetti__bit:nth-child(5n+4) { background: var(--olive-600); }
.confetti__bit:nth-child(5n) { background: var(--sun-500); width: 8px; height: 8px; border-radius: 50%; }
@keyframes confetti-fall {
  0% { opacity: 1; transform: translateY(0) rotate(var(--r)); }
  100% { opacity: 0; transform: translateY(105vh) translateX(40px) rotate(calc(var(--r) + 540deg)); }
}
@media (prefers-reduced-motion: reduce) { .confetti { display: none; } }
@media (max-width: 759px) {
  .highlights { grid-template-columns: repeat(2, 1fr); }
  .highlight:last-child:nth-child(odd) { grid-column: 1 / -1; }
  /* UX note: the three End actions share one row on a phone instead of wrapping "Start over". */
  .end-actions { flex-wrap: nowrap; gap: var(--space-2); }
  .end-actions .btn-outline { flex: 1 1 auto; min-width: 0; padding: 0 var(--space-3); font-size: var(--t-btn-sm); }
}
@media (max-width: 759px) {
  .end-hero::before { width: 190px; height: 190px; right: -50px; bottom: -50px; opacity: 0.35; }
  .podium { grid-template-columns: 1fr; }
  .podium__slot { min-height: 0 !important; flex-direction: row; justify-content: space-between !important; text-align: left; align-items: center; }
  .podium__slot--1 { order: -1; }
}
@media (prefers-reduced-motion: no-preference) {
  .end-hero { animation: fade-rise var(--dur-hero) var(--ease-out) both; }
  .content-inner--end .podium__slot { animation: podium-rise var(--dur-hero) var(--ease-out) both; }
  .content-inner--end .podium__slot--3 { animation-delay: 0.15s; } .content-inner--end .podium__slot--2 { animation-delay: 0.45s; } .content-inner--end .podium__slot--1 { animation-delay: 0.75s; }
}
@keyframes podium-rise { from { opacity: 0; transform: translateY(50px); } to { opacity: 1; transform: none; } }

/* R1-08: on Medium/Expanded the undo toast sits top-right, clear of the "Round N" heading.
   (Compact keeps it above the stacked action buttons - see the max-width:759px block.) */
@media (min-width: 760px) {
  body:has(.call__court) #toast-root, body:has(.call__none) #toast-root {
    bottom: auto; top: calc(20px + env(safe-area-inset-top, 0px)); justify-content: flex-end; padding-right: 5vw;
  }
}

/* R2-23: the critical chip's dot is red, not the running lime dot (one signal in the last 30 s). */
.timer-dock[data-critical="true"] .timer-dock__state::before { background: var(--critical-ring); }
/* R2-24: on red / black surfaces the focus ring is white in both themes (olive on red is ~1.5:1). */
:is(.timer-overlay[data-status="expired"], .timer-overlay[data-critical="true"], .timer-dock[data-status="expired"], .timer-dock[data-critical="true"], .time-up-banner) :focus-visible { outline-color: #fff; }
/* Idle / running (not critical) the head row has nothing to show (the state chip is hidden),
   so drop the row instead of leaving a gap above the digits. */
.timer-dock:is([data-status="idle"], [data-status="running"]:not([data-critical="true"])) .timer-dock__head { display: none; }

/* R2-27: with 1-2 courts on a tall screen, centre the whole call (heading, courts, sitting out,
   actions) as one block instead of leaving a void between the band and the pinned actions. */
@media (min-width: 760px) {
  .call:not(:has(.call__court:nth-child(3))) { justify-content: safe center; --t-call: clamp(56px, 7vh, 96px); }
  .call:not(:has(.call__court:nth-child(3))) > * { width: 100%; max-width: 1100px; margin-left: auto; margin-right: auto; }
  .call:not(:has(.call__court:nth-child(3))) .call__actions { margin-top: 12px; position: static; }
}

/* =====================================================================
   Persona "Do now" (UXR-01 / 09 / 10 / 05 / 16)
   ===================================================================== */
/* UXR-01: time up, buzzer stopped. The dock keeps TIME UP and 0:00 but calms down: a red
   outline on the normal surface instead of the red fill, no blink, and a "Buzzer off" chip. */
.timer-dock.timer-dock--silenced[data-status="expired"] {
  background: var(--glass-solid); background-color: var(--surface); color: var(--text);
  border: 2px solid var(--danger); box-shadow: var(--shadow-2);
}
.timer-dock--silenced[data-status="expired"] .timer-dock__digits { animation: none; color: var(--danger); }
.timer-dock--silenced[data-status="expired"] .timer-dock__state { color: var(--danger); border-color: var(--danger); background: var(--danger-soft); }
.timer-dock--silenced[data-status="expired"] .timer-dock__ring { background: var(--danger-soft); }
.timer-dock--silenced[data-status="expired"] .timer-dock__btn,
.timer-dock--silenced[data-status="expired"] .timer-dock__btn--play { color: var(--text); border-color: var(--line-strong); }
.timer-dock--silenced[data-status="expired"] :focus-visible { outline-color: var(--accent); }
[data-theme="dark"] .timer-dock--silenced[data-status="expired"] :focus-visible { outline-color: var(--accent-fill); }
.timer-dock__silenced { /* R4-06: the same mono micro caps tag as the state chip beside it */
  display: inline-flex; align-items: center; height: 24px; padding: 0 10px; border-radius: var(--radius-full);
  border: 1px solid var(--line-strong); color: var(--text2);
  font-family: var(--font-family-mono); font-size: var(--t-micro); font-weight: 700; letter-spacing: var(--track-caps); text-transform: uppercase;
}

/* UXR-09a: the ready Play gets a verb on phones ("Start clock"); icon-only elsewhere. */
.timer-dock__play-icon { display: flex; }
.timer-dock__play-label { display: none; }
@media (max-width: 759px) {
  .timer-dock__btn--play.is-primary:has(.timer-dock__play-label) { width: auto; padding: 0 var(--space-5) 0 var(--space-4); gap: var(--space-2); }
  .timer-dock__btn--play.is-primary .timer-dock__play-label { display: inline; font-size: var(--t-btn-md); font-weight: 800; letter-spacing: -0.01em; white-space: nowrap; }
  .timer-dock__btn--play.is-primary .timer-dock__play-icon svg { width: 22px; height: 22px; }
  .timer-dock__btn--play.is-primary::after { border-radius: var(--radius-full); }
  /* Phone timer placement §4.8: with the "Start clock" label the controls widened and squeezed
     the digits column, so "12:00" wrapped to "12:0 / 0". Digits never wrap, and while ready
     (full time, nothing to reset) the Reset button steps aside; Reset stays in the full-screen
     timer and returns in the dock as soon as the clock runs. */
  .timer-dock__digits { white-space: nowrap; }
  .timer-dock:has(.timer-dock__btn--play.is-primary) .timer-dock__btn--reset { display: none; }
}

/* UXR-10: on phones "Am I sitting out?" is answered first - the band moves under the heading
   (same node, CSS order) as one line of names. Medium/Expanded keep R3-07's order. */
@media (max-width: 759px) {
  .call__head { order: -2; }
  .call__sitting { order: -1; padding: var(--space-3) var(--space-4); gap: var(--space-1) var(--space-3); animation-delay: 0ms; }
  .call__sitting-names { font-size: var(--t-section); line-height: 1.2; }
}

/* UXR-05: Start over is a danger-text link at the left end, 24px apart from Share / Save. */
.end-actions { justify-content: space-between; }
.end-actions__start-over { flex: none; margin-right: var(--space-5); }
.end-actions__main { display: flex; gap: var(--space-3); align-items: center; margin-left: auto; min-width: 0; }
@media (max-width: 1139px) { .end-actions__main { flex: 1 1 auto; justify-content: flex-end; gap: var(--space-2); } }
@media (max-width: 759px) {
  .end-actions__start-over { margin-right: var(--space-4); }
  .end-actions__main .btn-outline { flex: 1 1 auto; min-width: 0; padding: 0 var(--space-3); font-size: var(--t-btn-sm); }
}

/* UXR-16: why the champion is ahead of an equal-points runner-up. */
.champion__why { margin-top: var(--space-2); font-size: var(--t-body); font-weight: 700; letter-spacing: -0.01em; }
