/* ============================================================
   Water Wolf — styles.css
   Phase 2 Checkpoint B: Game Setup screen skeleton.
   Design targets: iPad Safari landscape primary, iPhone portrait fallback.
   Wet-finger usability → large tap targets (≥48px), high contrast.
   ============================================================ */

:root {
  /* ---- Color palette (dark theme) ----
     Chosen for high contrast in bright poolside conditions. If outdoor
     glare turns out to be a problem on real iPads, we can flip to a
     light theme by changing these vars only. */
  --bg:         #0b1f33;  /* page — deep navy */
  --surface:    #12304d;  /* team card background */
  --surface-2:  #1a3e63;  /* nested block (goalies, field players) */
  --border:     #284e78;  /* subtle divider */

  --fg:         #f5f7fa;  /* primary text */
  --fg-muted:   #a8b6c5;  /* labels, secondary text */
  --accent:     #4fc3f7;  /* headings, accents — light blue */
  --danger:     #ef4444;  /* invalid input, destructive */
  --warn:       #fbbf24;  /* warnings, soft flags */

  --input-bg:     #ffffff;
  --input-fg:     #0b1f33;
  --input-border: #cbd5e1;

  --save-failure-bg:      #5c1d1d;
  --save-failure-border:  #c9302c;
  --save-failure-fg:      #fde8e8;

  --btn-primary-bg:       #2563eb;
  --btn-primary-fg:       #ffffff;
  --btn-primary-disabled-bg: #3b4c66;
  --btn-primary-disabled-fg: #8a9bb2;
  --btn-danger-bg:        #991b1b;

  /* Minimum tap target. Apple HIG says 44pt; we use 48 for wet-finger margin. */
  --tap-min: 48px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  /* Prevent iOS Safari from auto-resizing text on rotation. */
  -webkit-text-size-adjust: 100%;
}

body {
  font-family:
    -apple-system, BlinkMacSystemFont, "SF Pro Text",
    system-ui, sans-serif;
  background: var(--bg);
  color: var(--fg);
  line-height: 1.4;
  /* Respect iOS safe areas so content never hides under the notch / home indicator. */
  padding:
    env(safe-area-inset-top)
    env(safe-area-inset-right)
    env(safe-area-inset-bottom)
    env(safe-area-inset-left);
}

#app {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* ============================================================
   Screen layout (shared between Setup and Scoreboard)
   ============================================================ */

.screen {
  width: 100%;
  max-width: 1400px;
  margin: 0 auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* The `hidden` attribute on a <section> normally just sets display:none;
   being explicit here guards against any later flex/grid rule accidentally
   forcing a hidden screen back on. */
.screen[hidden] {
  display: none !important;
}

/* Scoresheet screen (PDF preview) locks to viewport height — it's
   a print layout whose paper dimensions extend past the viewport,
   and scrolls internally. dvh for iOS Safari's dynamic toolbar,
   vh fallback for older engines. */
.scoresheet-screen {
  box-sizing: border-box;
  min-height: 100vh;
  max-height: 100vh;
  min-height: 100dvh;
  max-height: 100dvh;
  overflow: hidden;
}

/* Scoreboard screen uses PAGE-level scrolling: the Game Progress
   log expands to its natural content height and the whole page
   scrolls when events exceed one viewport. Earlier versions locked
   the scoreboard to 100dvh and scrolled the log internally — the
   fixed height got squeezed on iPad landscape (short viewport +
   tall score band). Page-level scroll just works: log fills what's
   available, then native browser scroll takes over beyond that.

   min-height ensures the screen fills at least one viewport even
   with an empty log — avoids a short stub of content at the top
   of an otherwise empty page. No max-height. */
.scoreboard-screen {
  box-sizing: border-box;
  min-height: 100vh;
  min-height: 100dvh;
}

/* ============================================================
   Setup screen layout
   ============================================================ */

.setup-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  /* Top padding includes env(safe-area-inset-top) so the sticky header
     sits BELOW the iOS status bar / notch in PWA standalone mode (where
     viewport-fit=cover extends the viewport under the system chrome).
     In plain Safari with no inset, env() resolves to 0 and the header
     gets the baseline 8px breathing room. */
  padding: calc(env(safe-area-inset-top, 0px) + 8px) 0 8px;
  box-shadow: 0 4px 8px -2px rgba(0, 0, 0, 0.5);
}

.setup-header-text {
  min-width: 0; /* let the ellipsis on .setup-status actually truncate */
}

.setup-header h1 {
  font-size: 1.6rem;
  color: var(--accent);
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.15;
}

.setup-header-actions {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}

#btn-setup-undo,
#btn-setup-redo {
  flex: 0 0 auto;
  padding: 10px 14px;
  min-height: 44px;
  font-size: 0.95rem;
  min-width: 96px;
}

#btn-setup-undo:disabled,
#btn-setup-redo:disabled,
#btn-redo-last:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.setup-version {
  margin: 2px 0 0;
  font-size: 0.8rem;
  color: var(--fg-muted);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* ---- Game info (top bar) ---- */

.game-info {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 16px;
}

/* ---- Fields / labels / inputs ---- */

.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.field--inline {
  flex-direction: row;
  align-items: center;
  gap: 12px;
}

.field--inline .label {
  min-width: 52px;
}

.field .label {
  font-size: 0.72rem;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}

input[type="text"],
input[type="date"] {
  font: inherit;
  /* 16px min prevents iOS Safari from auto-zooming on focus. */
  font-size: 1rem;
  padding: 10px 12px;
  min-height: var(--tap-min);
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 6px;
  width: 100%;
  /* Stop iOS from putting a shiny inner highlight on text inputs. */
  -webkit-appearance: none;
  appearance: none;
}

input[type="text"]:focus,
input[type="date"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(79, 195, 247, 0.25);
}

/* Field player cap button.
   Styled to match the text inputs so the row reads consistently, but it's
   actually a <button> that opens the grid picker modal. A subtle chevron
   hints that tapping does something. */
.cap-button {
  font: inherit;
  font-size: 1.1rem;
  font-weight: 700;
  padding: 10px 28px 10px 12px;
  min-height: var(--tap-min);
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 6px;
  width: 100%;
  text-align: center;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--input-fg) 50%),
    linear-gradient(-45deg, transparent 50%, var(--input-fg) 50%);
  background-position:
    calc(100% - 14px) 55%,
    calc(100% - 9px) 55%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.cap-button:active {
  transform: scale(0.98);
  border-color: var(--accent);
}

/* Validation-error styling — applied to inputs AND cap buttons by
   renderValidation() in app.js. Warnings are NOT flagged inline (they'd
   light up every empty roster row); only blocking errors get the red border. */
input.invalid,
.cap-button.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.25);
}

/* Summary of current validation errors, shown above the footer. Hidden
   entirely when the game validates cleanly. */
#error-summary {
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid var(--danger);
  border-radius: 8px;
  padding: 12px 16px;
  color: #fecaca;
  font-size: 0.9rem;
}

#error-summary[hidden] {
  display: none;
}

#error-summary .summary-title {
  display: block;
  margin-bottom: 6px;
  color: #fca5a5;
  font-weight: 700;
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

#error-summary ul {
  margin: 0;
  padding-left: 20px;
}

#error-summary li {
  margin: 2px 0;
}

/* ============================================================
   Team columns
   ============================================================ */

.team-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

/* iPhone portrait fallback: stack team columns vertically. */
@media (max-width: 760px) {
  .team-columns {
    grid-template-columns: 1fr;
  }
}

.team-card {
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Team header visually echoes cap color so you can tell which side is which
   even if the labels ever move. */
.team-header h2 {
  margin: 0;
  padding: 10px 14px;
  font-size: 1rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  border-radius: 6px;
  font-weight: 700;
}

.team-card--white .team-header h2 {
  background: #ffffff;
  color: #0b1f33;
  border: 1px solid #cbd5e1;
}

.team-card--dark .team-header h2 {
  background: #0a1929;
  color: #ffffff;
  border: 1px solid #1e3a5f;
}

/* ---- Roster blocks (goalies, field players) ---- */

.roster-block {
  background: var(--surface-2);
  border-radius: 8px;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.roster-block--goalies {
  /* Subtle left accent so the block reads as distinct from field players */
  border-left: 3px solid var(--accent);
}

.roster-block h3 {
  margin: 0 0 2px;
  font-size: 0.72rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

/* ---- Player rows ---- */

/* Field player row: [ cap ] [ last ] [ first ] [ × ]
   v2 schema split — last + first inputs share 1fr 1fr so on a wide
   panel both inputs are usable; on iPhone-portrait the panel is the
   full viewport width so two name inputs still fit. */
.player-row {
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) minmax(0, 1fr) var(--tap-min);
  gap: 8px;
  align-items: center;
}

/* Goalie row swaps the remove button for a label on the left:
   [ label ] [ cap ] [ last ] [ first ] */
.player-row--goalie {
  grid-template-columns: 80px 72px minmax(0, 1fr) minmax(0, 1fr);
}

/* Name inputs in the row — both Last + First take their grid cell.
   Min-width 0 so the cell can shrink below the input's intrinsic
   width if the panel narrows on iPhone-portrait. */
.player-row .name-input {
  min-width: 0;
  width: 100%;
}

.row-label {
  font-size: 0.85rem;
  color: var(--fg-muted);
  text-align: right;
  font-weight: 600;
}

.cap-input {
  text-align: center;
  font-weight: 700;
  font-size: 1.05rem;
  letter-spacing: 0.05em;
}

/* Small placeholder color on dark surfaces — inputs themselves are white
   but this styles the `#` / `Name` hints within them. */
::placeholder {
  color: #94a3b8;
  opacity: 1;
}

/* ============================================================
   Buttons
   ============================================================ */

.btn {
  font: inherit;
  font-size: 1rem;
  font-weight: 700;
  padding: 12px 18px;
  min-height: var(--tap-min);
  border: 2px solid transparent;
  border-radius: 8px;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  /* iOS default tap flash is gray and ugly on colored buttons; remove it. */
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, background 0.15s ease;
}

.btn:active:not(:disabled) {
  transform: scale(0.98);
}

.btn-add {
  background: transparent;
  color: var(--accent);
  border-color: var(--accent);
  width: 100%;
  margin-top: 2px;
  font-weight: 600;
}

.btn-add:hover {
  background: rgba(79, 195, 247, 0.1);
}

.btn-remove {
  background: var(--btn-danger-bg);
  color: #ffffff;
  width: var(--tap-min);
  height: var(--tap-min);
  font-size: 1.3rem;
  line-height: 1;
  padding: 0;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  font-weight: 700;
}

.btn-primary {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
}

.btn-primary:disabled {
  background: var(--btn-primary-disabled-bg);
  color: var(--btn-primary-disabled-fg);
  cursor: not-allowed;
}

.btn-secondary {
  background: transparent;
  color: var(--fg);
  border-color: var(--accent);
}

.btn-secondary:active:not(:disabled) {
  background: rgba(79, 195, 247, 0.1);
}

.btn-danger {
  background: var(--btn-danger-bg);
  color: #ffffff;
  border-color: transparent;
}

.btn-danger:active:not(:disabled) {
  filter: brightness(1.1);
}

/* Wake-lock retry pill — small inline amber warning, lives in the
   scoreboard header next to the other secondary controls. Smaller
   font + lighter padding so it reads as a status indicator rather
   than a primary action, but tappable to re-attempt acquisition. */
.btn-wake-lock-warning {
  background: rgba(255, 193, 7, 0.15);
  color: #ffc107;
  border-color: rgba(255, 193, 7, 0.55);
  font-size: 0.85rem;
  padding: 6px 10px;
}

.btn-wake-lock-warning:active:not(:disabled) {
  background: rgba(255, 193, 7, 0.25);
}

/* ============================================================
   Footer
   ============================================================ */

.setup-footer {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  margin-top: 4px;
}

.setup-footer .btn {
  flex: 1;
  min-width: 220px;
}

/* ============================================================
   Stats Tracking — opt-in v2 stat toggles
   ============================================================ */

.setup-stats-tracking {
  border-top: 1px solid var(--border);
  padding: 14px 0 10px;
  margin-top: 12px;
}

.setup-section-title {
  margin: 0 0 8px;
  font-size: 0.9rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}

.setup-section-subtitle {
  margin-left: 6px;
  color: var(--fg-muted);
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  text-transform: none;
  font-weight: 500;
}

.setup-stats-toggles {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
}

/* Toggle pill — visual weight matches the Swap White/Dark button. The
   right-side state badge ("ON" / "OFF") is the obvious affordance for
   the current state; aria-pressed mirrors it for assistive tech. */
.stats-toggle-pill {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  min-height: 44px;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.stats-toggle-pill .stats-toggle-state {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  padding: 3px 8px;
  border-radius: 6px;
  background: rgba(148, 163, 184, 0.18);
  color: var(--fg-muted);
}

.stats-toggle-pill[aria-pressed="true"] {
  background: rgba(5, 150, 105, 0.18);
  border-color: #059669;
  color: #a7f3d0;
}

.stats-toggle-pill[aria-pressed="true"] .stats-toggle-state {
  background: #059669;
  color: #ffffff;
}

/* ---- Division toggle (Boys / Girls) ----
   Two-button segmented control on Match Setup. Required field;
   neither button is pre-selected on a fresh game (validation
   blocks Start Match until the user picks). Uses the same
   green-on-selected language as .stats-toggle-pill so the visual
   "this is set" cue is consistent. */
.division-toggle {
  display: inline-flex;
  gap: 0;
  border-radius: 8px;
  overflow: hidden;
  border: 1.5px solid var(--border);
}
.division-toggle-btn {
  font: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 10px 18px;
  min-height: 44px;
  background: var(--surface);
  color: var(--fg);
  border: none;
  border-right: 1.5px solid var(--border);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.1s ease;
}
.division-toggle-btn:last-child {
  border-right: none;
}
.division-toggle-btn:active {
  background: rgba(148, 163, 184, 0.1);
}
.division-toggle-btn[aria-pressed="true"] {
  background: rgba(5, 150, 105, 0.18);
  color: #a7f3d0;
}

/* ============================================================
   Scoreboard screen — Phase 3 Checkpoint B
   ============================================================ */

/* Header: three-slot grid — [back] [period] [right spacer].
   The spacer on the right keeps the period indicator centered. */
.scoreboard-header {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 16px;
  /* Top padding includes env(safe-area-inset-top) — same rationale as
     .setup-header above: sticky headers under iOS status bar / notch in
     PWA standalone mode (viewport-fit=cover). */
  padding: calc(env(safe-area-inset-top, 0px) + 8px) 4px 8px;
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  box-shadow: 0 4px 8px -2px rgba(0, 0, 0, 0.5);
}

/* Right-side cluster so we can fit both Undo and the Roster toggle
   without reshaping the whole header grid. */
.scoreboard-header-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* iPhone portrait fallback: the scoreboard header's right cluster
   (Rosters · Undo · Redo · Scoresheet →) plus the Match Setup back
   button overflow a 390-430px viewport, pushing Scoresheet → off
   screen. Drop the 3-column grid to a single column and let the
   right cluster wrap onto its own row(s) so every button stays
   reachable. Tap-min height is preserved — wet-finger usability
   matters on iPhone too. */
@media (max-width: 640px) {
  .scoreboard-header {
    grid-template-columns: 1fr;
    gap: 8px;
  }
  .scoreboard-header-spacer {
    display: none;
  }
  .scoreboard-header-right {
    flex-wrap: wrap;
    justify-content: flex-start;
  }
}

/* Roster / Foul Status panel — rolls down from under the header when
   #btn-roster-toggle is tapped. Uses a max-height transition so the
   animation works without needing to know the panel's final height. */
.roster-panel {
  overflow: hidden;
  max-height: 0;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  margin-top: 4px;
  transition: max-height 0.22s ease, padding 0.22s ease, opacity 0.18s ease;
  opacity: 0;
  padding: 0 12px;
}

.roster-panel--open {
  max-height: 640px; /* generous ceiling; tall rosters just scroll inside */
  opacity: 1;
  padding: 12px;
  overflow: auto; /* scroll internally if content overflows the ceiling */
}

/* Arrow glyph inside the toggle button rotates on open so the control
   reads like a standard disclosure triangle. */
.roster-toggle-glyph {
  display: inline-block;
  margin-right: 6px;
  transition: transform 0.18s ease;
}

#btn-roster-toggle[aria-expanded="true"] .roster-toggle-glyph {
  transform: rotate(180deg);
}

.roster-panel-inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

/* iPhone portrait fallback: stack the two teams. */
@media (max-width: 640px) {
  .roster-panel-inner {
    grid-template-columns: 1fr;
  }
}

.roster-team {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.roster-team-header {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--border);
}

.roster-team-color {
  font-size: 0.7rem;
  color: var(--fg-muted);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
}

.roster-team-school {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--fg);
}

.roster-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.roster-subheader {
  font-size: 0.62rem;
  color: var(--fg-muted);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 800;
  padding: 8px 4px 2px;
}

.roster-row {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  align-items: start;
  gap: 10px;
  padding: 6px 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
}

/* Per-foul detail list in the right column — one line per major
   foul reading "Period · Clock · Code", then a Total line with the
   OUT/amber/green pill. Keeps the roster panel dense but scannable. */
.roster-fouls {
  display: flex;
  flex-direction: column;
  gap: 2px;
  align-items: flex-end;
  font-size: 0.78rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

.roster-foul-line {
  font-weight: 600;
  color: var(--fg);
  letter-spacing: 0.02em;
}

.roster-foul-total {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 2px;
}

.roster-foul-total-label {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-muted);
  font-weight: 700;
}

.roster-row--excluded {
  background: rgba(239, 68, 68, 0.12);
  color: var(--fg-muted);
}

.roster-cap {
  font-weight: 800;
  font-size: 0.95rem;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

.roster-row--excluded .roster-cap {
  text-decoration: line-through;
  color: #fca5a5;
}

.roster-name {
  font-size: 0.9rem;
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.roster-name--empty {
  color: var(--fg-muted);
  font-style: italic;
  opacity: 0.6;
}

/* Foul-count pill — color signals pressure. 0/1 green-ish, 2 amber,
   3 = excluded (OUT). Inline in the roster row; also reused in the
   panel's legend row at the bottom. */
.foul-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  height: 22px;
  padding: 0 8px;
  border-radius: 11px;
  font-size: 0.72rem;
  font-weight: 900;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}

.foul-pill--0 {
  background: rgba(5, 150, 105, 0.18);
  color: #a7f3d0;
  border: 1px solid rgba(5, 150, 105, 0.4);
}

.foul-pill--1 {
  background: rgba(5, 150, 105, 0.22);
  color: #a7f3d0;
  border: 1px solid rgba(5, 150, 105, 0.55);
}

.foul-pill--2 {
  background: rgba(217, 119, 6, 0.22);
  color: #fde68a;
  border: 1px solid rgba(217, 119, 6, 0.55);
}

.foul-pill--excluded {
  background: rgba(220, 38, 38, 0.28);
  color: #fecaca;
  border: 1px solid rgba(220, 38, 38, 0.7);
}

.roster-panel-footer {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px dashed var(--border);
}

.roster-panel-legend {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.roster-legend-note {
  margin-left: 6px;
  font-size: 0.72rem;
  color: var(--fg-muted);
}

.header-spacer {
  min-width: 72px; /* roughly matches the Back button width */
}

#btn-undo-last {
  justify-self: end;
  padding: 10px 14px;
  min-height: 44px;
  font-size: 0.95rem;
  min-width: 96px;
}

#btn-undo-last:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Period indicator — now lives inside the score band's middle column,
   so it stacks vertically: tiny "Period" label, big period number,
   Next Period button below. Narrow screens fall back to a single
   horizontal row since the whole band is stacked already. */
.period-indicator {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 10px;
  min-width: 120px;
  /* Anchor for the absolutely-positioned End Match button (added in
     the @media (min-width: 641px) block below). In narrow / iPhone
     portrait the indicator collapses to a row and End Match flows
     inline; in wide layouts End Match is pinned to the bottom for
     separation from Next Period (accidental-tap prevention). */
  position: relative;
}

.period-indicator .period-label {
  font-size: 0.7rem;
  color: var(--fg-muted);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
}

.period-indicator .period-value {
  font-size: 2.4rem;
  font-weight: 800;
  color: var(--accent);
  text-align: center;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

@media (max-width: 640px) {
  .period-indicator {
    flex-direction: row;
    min-width: 0;
  }
  .period-indicator .period-value {
    font-size: 1.4rem;
  }
}

#btn-next-period,
#btn-end-match {
  padding: 10px 16px;
  min-height: 44px;
  font-size: 0.95rem;
}

#btn-next-period:disabled,
#btn-end-match:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Action buttons under the period indicator stack vertically on
   desktop / iPad landscape so neither button has to share a row
   width with the other. On narrow widths the whole period-indicator
   collapses to a row via the existing media query below, and these
   buttons wrap alongside. */
.period-actions {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: stretch;
  width: 100%;
}

@media (max-width: 640px) {
  .period-actions {
    flex-direction: row;
    width: auto;
  }
}

/* End Match uses a muted red border so it's visually distinguishable
   from Next Period (which is the high-frequency tap) without becoming
   a destructive-style button — it's reversible via Undo. */
#btn-end-match {
  color: var(--danger, #b91c1c);
  border-color: var(--danger, #b91c1c);
}
#btn-end-match:hover:not(:disabled) {
  background: rgba(185, 28, 28, 0.08);
}

/* Wide-layout (iPad landscape, desktop) End Match treatment: pinned
   to the BOTTOM of the period-indicator so it doesn't sit directly
   beneath Next Period — proximity caused accidental taps in
   testing. Bottom edge aligns with the bottom of the score boxes.
   Narrow / iPhone-portrait keeps End Match in normal flow alongside
   Next Period as part of the row layout. */
@media (min-width: 641px) {
  .period-indicator {
    /* Reserve space at the bottom so the centered cluster (label /
       value / Next Period) doesn't collide with the pinned End Match
       button. ~52px = button height + 8px breathing room. */
    padding-bottom: 60px;
  }
  #btn-end-match {
    position: absolute;
    bottom: 8px;
    left: 10px;
    right: 10px;
  }
}

/* When the match is Final, the period label ("PERIOD") is replaced
   with "FINAL" rendered in the accent style. The existing
   .period-value shows the period the match ended in as a
   subscript-size line underneath. */
.period-indicator.is-final .period-label {
  color: var(--danger, #b91c1c);
  font-size: 0.95rem;
  letter-spacing: 0.18em;
}
.period-indicator.is-final .period-value {
  font-size: 1rem;
  color: var(--fg-muted);
  font-weight: 600;
  letter-spacing: 0.08em;
}

/* Score band: two team displays with the Period indicator between
   them so the "what period are we in" reference sits where the eye
   is already pointed when comparing scores. Middle column is `auto`
   so the team panels take the remaining space equally. On narrow
   screens the whole band stacks vertically with the period block
   in the middle of the stack. */
.score-band {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 16px;
  align-items: stretch;
}

@media (max-width: 640px) {
  .score-band {
    grid-template-columns: 1fr;
  }
}

/* ---- Team panel ---- */

.team-panel {
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
  /* Anchors the absolutely-positioned SHOT button (top-outer corner). */
  position: relative;
}

.team-panel-name {
  margin: 0;
  padding: 8px 14px;
  border-radius: 6px;
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  /* Children handle their own font sizing. */
}

.team-panel-color {
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 800;
  opacity: 0.7;
}

.team-panel-school {
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 700;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.team-panel--white .team-panel-name {
  background: #ffffff;
  color: #0b1f33;
  border: 1px solid #cbd5e1;
}

.team-panel--dark .team-panel-name {
  background: #0a1929;
  color: #ffffff;
  border: 1px solid #1e3a5f;
}

/* Bottom row inside each team panel: Saves button on the OUTER edge,
   TOL stack CENTERED in the remaining space between the button and
   the opposite (inner) edge. White is the natural row order
   (saves-left, tol-right); dark uses row-reverse so saves lands on
   its outer (right) edge.
   `align-self: stretch` makes the row span the panel's content area;
   negative horizontal margins extend it past the panel's 16px padding
   so the Saves button lands flush near the rounded corner. TOL is the
   only flex-grow child, so it claims the remainder; .team-meta's
   align-items: center then centers the label + lines horizontally
   within that grown area. */
.team-bottom-row {
  align-self: stretch;
  display: flex;
  align-items: flex-end;
  margin: 6px -12px 0;
  padding: 0 4px;
}

.team-bottom-row .saves-btn {
  flex: 0 0 auto;
}

.team-bottom-row .team-meta {
  flex: 1 1 auto;
}

.team-panel--dark .team-bottom-row {
  flex-direction: row-reverse;
}

/* Extra row for the STEAL button — sits ABOVE team-bottom-row so
   STEAL aligns vertically with SAVES (both on the OUTER edge). One
   item (STEAL); the row's own flex layout pushes it to the outer
   side via justify-content: flex-start (which respects the panel's
   flex-direction, mirroring on dark and flipping with Switch Sides). */
.team-extra-row {
  align-self: stretch;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  margin: 0 -12px;
  padding: 0 4px;
}

.team-extra-row[hidden] {
  display: none;
}

.team-panel--dark .team-extra-row {
  flex-direction: row-reverse;
}

/* ---- View Swap (Switch Sides) ----
   Visual-only rearrangement: white moves to the right slot, dark to
   the left slot. Score-band is a 3-col grid (white | period | dark);
   CSS `order` reshuffles which item lands in which cell without
   touching the grid template or the source order in HTML.

   When swapped, every "outer-edge" affordance on a team-panel needs
   to flip to stay on the OUTER edge of the panel's new position:
     - SHOT button (top-OUTER corner): swap left/right.
     - SAVES button + TOL meta in .team-bottom-row: flip flex-direction
       so SAVES stays on the outer edge.

   The Stats panel's `.roster-panel-inner` is a 2-col grid; same order
   trick puts the dark roster-team on the left and the white one on
   the right so it matches the scoreboard. */
body.view-swapped .team-panel--white      { order: 3; }
body.view-swapped .period-indicator       { order: 2; }
body.view-swapped .team-panel--dark       { order: 1; }
body.view-swapped .roster-team[id="roster-team-white"] { order: 2; }
body.view-swapped .roster-team[id="roster-team-dark"]  { order: 1; }

/* SAVES + SHOT + TOL flip — reversing the team-bottom-row's flex
   direction keeps SAVES on the outer edge (and SHOT on the inner
   edge, with TOL between them) regardless of which side the panel
   currently occupies. STEAL (in team-extra-row) flips by the same
   rule so it stays directly above SHOT. */
body.view-swapped .team-panel--white .team-bottom-row,
body.view-swapped .team-panel--white .team-extra-row { flex-direction: row-reverse; }
body.view-swapped .team-panel--dark  .team-bottom-row,
body.view-swapped .team-panel--dark  .team-extra-row { flex-direction: row; }

/* Switch Sides button styling — same chip shape as Cap Change.
   When pressed (sides currently swapped), tint the button so it
   reads as an active state, not just a one-shot trigger. */
.btn-switch-sides[aria-pressed="true"] {
  background: rgba(56, 189, 248, 0.18);
  border-color: #38bdf8;
  color: #38bdf8;
}

/* TOL label centered above the per-kind lines, each line on its own
   row. Same font-size + weight on label and lines so the stack reads
   as a labeled trio. The label is muted gray; the lines are white. */
.team-meta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: var(--fg-muted);
}

.team-meta .tol-label {
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 800;
  font-size: 1rem;
  color: var(--fg-muted);
}

/* TOL is one tappable button per team. The "TOL" label sits OUTSIDE
   above the button (in the team-meta column); the button itself
   shows both counts on stacked lines (Full + 30 sec). Tap → opens
   the timeout-kind picker → tap a kind → logs immediately. Same
   fast-flow shape as SHOT/STEAL → player picker. Visual treatment
   mirrors SAVES / SHOT / STEAL: bordered pill with internal text. */
.team-meta .tol-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 90px;
  /* Match SHOT/SAVES button height (64px standard, 54px in
     compact-height media block below) so the per-team button row
     reads as a uniform set. */
  min-height: 64px;
  padding: 6px 12px;
  background: rgba(37, 99, 235, 0.14);    /* faint blue tint */
  border: 1.5px solid #2563eb;
  border-radius: 12px;
  color: var(--fg);
  cursor: pointer;
  font-family: inherit;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.04s ease, background 0.1s ease;
}

.team-meta .tol-btn:active:not(:disabled) {
  transform: scale(0.97);
  background: rgba(37, 99, 235, 0.26);
}

.team-meta .tol-btn:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.tol-btn-line {
  font-weight: 800;
  font-size: 0.95rem;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
  white-space: nowrap;
}

/* Timeout-kind picker modal — minimal two-cell chooser opened from
   the per-team TOL button. Re-uses the player-picker-modal layout
   primitives (scrim + centered panel). */
.timeout-picker-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
}

.timeout-picker-modal[hidden] {
  display: none;
}

.timeout-picker-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.timeout-picker-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 360px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.timeout-picker-header h2 {
  margin: 0;
  font-size: 0.95rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  text-align: center;
}

.timeout-picker-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.timeout-picker-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 96px;
  padding: 14px 10px;
  background: rgba(37, 99, 235, 0.14);
  border: 1.5px solid #2563eb;
  border-radius: 12px;
  color: var(--fg);
  cursor: pointer;
  font-family: inherit;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.04s ease, background 0.1s ease;
}

.timeout-picker-cell:active:not(:disabled) {
  transform: scale(0.97);
  background: rgba(37, 99, 235, 0.26);
}

.timeout-picker-cell:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

.timeout-picker-cell-label {
  font-size: 1.1rem;
  font-weight: 800;
  letter-spacing: 0.04em;
}

.timeout-picker-cell-count {
  font-size: 0.85rem;
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* ---- Optional period + clock-time detail (2026-04-29) ----
   Lives below the kind cells inside .timeout-picker-panel. Always
   visible per the picks; timeouts are the slowest part of the match
   and the picker doesn't need fast-flow optimization. The period
   chip row reuses .entry-period-choice exactly so visuals match the
   entry modal. The clock-time input mirrors .entry-clock-input. */
.timeout-picker-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.timeout-picker-detail-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.timeout-picker-detail-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--fg-muted);
}
.timeout-picker-period-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.timeout-picker-clock-input {
  font: inherit;
  font-size: 1.4rem !important;
  font-weight: 800;
  text-align: center;
  padding: 10px;
  min-height: 48px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
  -webkit-appearance: none;
  appearance: none;
}
.timeout-picker-clock-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(79, 195, 247, 0.25);
}
.timeout-picker-clock-input.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.25);
}

.timeout-picker-footer {
  display: flex;
  justify-content: center;
  gap: 10px;
}

/* Selected-state for the timeout kind cells. After the v2.5 polish
   that added Submit, the kind cells are "select" affordances rather
   than commit-on-tap — green-on-emerald aria-pressed treatment so
   the visual matches the rest of the app's "this is set" cue. */
.timeout-picker-cell[aria-pressed="true"] {
  background: rgba(5, 150, 105, 0.22);
  border-color: #059669;
  color: #a7f3d0;
}

/* Inline missing-time warning. Yellow accent, between the detail
   section and the footer. Hidden by default; shown when a kind is
   picked but the clock-time input is empty. Doesn't block Submit. */
.timeout-picker-warning {
  background: rgba(251, 191, 36, 0.1);
  border: 1px solid var(--warn);
  color: #fde68a;
  border-radius: 8px;
  padding: 8px 12px;
  font-size: 0.82rem;
  line-height: 1.35;
}
.timeout-picker-warning[hidden] {
  display: none !important;
}

/* Saves button — single tap target sized for wet fingers. Big count
   number + small SAVES label stacked vertically. Visible only when
   game.optionalStats.saves is on (button.hidden=false). */
.saves-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 90px;
  min-height: 64px;
  padding: 6px 12px;
  background: rgba(234, 88, 12, 0.14);   /* faint orange tint */
  border: 1.5px solid #ea580c;
  border-radius: 12px;
  color: var(--fg);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.04s ease, background 0.1s ease;
}

.saves-btn[hidden] {
  display: none;
}

.saves-btn:active {
  transform: scale(0.97);
  background: rgba(234, 88, 12, 0.26);
}

.saves-btn-label {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: #fb923c;
}

.saves-btn-count {
  font-size: 1.6rem;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}

/* Shot button — same shape as Saves, lives in .team-bottom-row at
   the OPPOSITE end from SAVES (per user direction: bottom-INNER
   corner of each panel, with TOL meta in the middle). The dark
   panel's flex-direction: row-reverse mirrors the layout so SAVES
   stays outer and SHOT stays inner on both sides. Green to tie
   visually to the GOALS action button (shot → goal pipeline).
   Visible only when game.optionalStats.shotAttempts is on. */
.shot-btn {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 90px;
  min-height: 64px;
  padding: 6px 12px;
  background: rgba(5, 150, 105, 0.14);   /* faint emerald — matches GOALS family */
  border: 1.5px solid #059669;
  border-radius: 12px;
  color: var(--fg);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.04s ease, background 0.1s ease;
}

.shot-btn[hidden] {
  display: none;
}

/* Steal button — same shape as SHOT, lives in .team-extra-row
   directly above SHOT on the inner edge of each team-panel. Two-tap
   fast flow (button + player), no team picker, no Review. Yellow
   to distinguish from the orange SHOT and cyan SAVES. Visible only
   when game.optionalStats.steals is on. */
.steal-btn {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-width: 90px;
  min-height: 64px;
  padding: 6px 12px;
  background: rgba(234, 179, 8, 0.14);    /* faint yellow tint */
  border: 1.5px solid #eab308;
  border-radius: 12px;
  color: var(--fg);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.04s ease, background 0.1s ease;
}

.steal-btn[hidden] {
  display: none;
}

.steal-btn:active {
  transform: scale(0.97);
  background: rgba(234, 179, 8, 0.26);
}

.steal-btn-label {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: #facc15;
}

.steal-btn-count {
  font-size: 1.6rem;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}

.shot-btn:active {
  transform: scale(0.97);
  background: rgba(5, 150, 105, 0.26);
}

.shot-btn-label {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: #34d399;
}

.shot-btn-count {
  font-size: 1.6rem;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}

/* Giant score number. Tabular numerals prevent the digits jumping
   around when going from 9 to 10. */
.team-score {
  font-size: 5.5rem;
  font-weight: 900;
  line-height: 1;
  text-align: center;
  color: var(--accent);
  padding: 8px 0 14px;
  font-variant-numeric: tabular-nums;
}

/* Short-viewport compaction — iPad landscape (820px or less tall,
   more with Safari's URL bar), smaller laptops in reduced windows,
   and any device where vertical real estate is tight. The default
   scoreboard layout uses a generous 5.5rem score digit + generous
   panel padding, which is right for portrait. In shorter viewports
   that sizing eats into the event-log-panel's flex:1 share and
   squeezes the Game Progress log to the point that only 1–2 rows
   render. We trade big-number drama for usable log space. */
@media (max-height: 820px) {
  .team-panel {
    padding: 10px 14px;
    gap: 6px;
  }
  .team-panel-name {
    padding: 6px 10px;
  }
  .team-panel-school {
    font-size: 0.85rem;
  }
  .team-score {
    font-size: 3.5rem;
    padding: 2px 0 6px;
  }
  /* Compact mode: shrink the TOL label + count lines uniformly so
     the stack matches the SAVES/SHOT button heights. */
  .team-meta .tol-label {
    font-size: 0.85rem;
  }
  .team-meta .tol-btn { min-height: 54px; min-width: 80px; padding: 3px 10px; }
  .tol-btn-line { font-size: 0.85rem; }
  .saves-btn { min-height: 54px; min-width: 80px; padding: 4px 10px; }
  .saves-btn-count { font-size: 1.3rem; }
  .saves-btn-label { font-size: 0.65rem; }
  .shot-btn { min-height: 54px; min-width: 80px; padding: 4px 10px; }
  .shot-btn-count { font-size: 1.3rem; }
  .shot-btn-label { font-size: 0.65rem; }
  .steal-btn { min-height: 54px; min-width: 80px; padding: 4px 10px; }
  .steal-btn-count { font-size: 1.3rem; }
  .steal-btn-label { font-size: 0.65rem; }
  .period-indicator {
    gap: 6px;
    padding: 6px 8px;
    min-width: 100px;
  }
  /* Compact-height layouts (iPad landscape ≤820px tall) still want
     End Match pinned to the bottom in wide viewports — keep room
     for the absolutely-positioned button. Slightly smaller than the
     desktop reservation since the buttons themselves are compacted
     to min-height: 40px below. */
  @media (min-width: 641px) {
    .period-indicator {
      padding-bottom: 50px;
    }
  }
  .period-indicator .period-label {
    font-size: 0.65rem;
  }
  .period-indicator .period-value {
    font-size: 1.8rem;
  }
  #btn-next-period,
  #btn-end-match {
    padding: 8px 12px;
    min-height: 40px;
    font-size: 0.85rem;
  }
  .btn-action {
    padding: 12px 10px;
    min-height: 52px;
    font-size: 1rem;
  }
  /* With less vertical room, the screen's own padding + gap between
     sections matters too. Trim both so the log keeps more space. */
  .scoreboard-screen {
    padding: 10px 16px;
    gap: 10px;
  }
}

/* ---- Action buttons (GOAL / FOULS / TIMEOUT) ----
   Consolidated into a single horizontal row below the score band.
   Each tap opens the unified entry modal; FOULS reveals a subtype
   row (Exclusion / Penalty / Brutality / Misconduct / Yellow / Red)
   before the rest of the fields. */

/* Flex (not grid) so a `hidden` button drops out of the layout cleanly
   — grid items with display:none vacate their column track but a fixed
   `repeat(N, 1fr)` template would still render the leftover slot for
   any hidden child. With flex + `flex: 1 1 0` each visible button
   takes an equal share regardless of count (3 baseline, 4 when STEAL
   opt-in is on, future 5 etc.). */
.action-buttons-row {
  display: flex;
  gap: 10px;
}

.action-buttons-row > .btn-action {
  flex: 1 1 0;
  min-width: 0;
}

.btn-action {
  font: inherit;
  font-size: 1.15rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  padding: 18px 14px;
  min-height: 64px;
  border: 2px solid transparent;
  border-radius: 10px;
  cursor: pointer;
  color: #fff;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, filter 0.1s ease;
}

.btn-action:active:not(:disabled) {
  transform: scale(0.98);
  filter: brightness(1.1);
}

.btn-action:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

/* Action-specific color. Kept as solid blocks (not outlines) so cap-tap
   recognition works in bright sunlight. */
.btn-action--goal      { background: #059669; }  /* emerald — the celebration */
.btn-action--fouls     { background: #dc2626; }  /* red — any foul (subtype picked inside) */
.btn-action--timeout   { background: #2563eb; }  /* blue — neutral */

/* ---- Event log ---- */

.event-log-panel {
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* On the scoreboard screen this panel grows to fill remaining
     viewport space (flex-grow: 1) AND expands past it if the log
     has many events (page-level scrolling kicks in). No
     max-height / internal overflow — the browser scrolls the
     whole page instead. */
  flex: 1 1 auto;
}

/* Keep a visible panel even when the log is empty — the
   Game Progress header, column labels, and footer buttons
   need somewhere to live. */
.scoreboard-screen .event-log-panel {
  min-height: 200px;
}

.event-log-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}

.event-log-title {
  margin: 0;
  font-size: 0.78rem;
  color: var(--accent);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 700;
}

/* Footer below the event log — hosts two low-frequency actions:
   "+ Custom Event" (escape hatch) and "⟲ Cap Change" (mid-match
   cap-number swaps). Both are logged as events. Two buttons flex
   side-by-side with a small gap; on narrow screens they wrap. */
.event-log-footer {
  display: flex;
  justify-content: center;
  gap: 10px;
  flex-wrap: wrap;
  padding-top: 6px;
  border-top: 1px dashed var(--border);
  margin-top: 4px;
}

.btn-add-custom {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 18px;
  min-height: 44px;
  font: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--fg-muted);
  background: transparent;
  border: 2px dashed var(--border);
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.1s ease, border-color 0.1s ease, background 0.1s ease;
}

.btn-add-custom:hover,
.btn-add-custom:focus-visible {
  color: var(--fg);
  border-color: var(--accent);
  background: rgba(79, 195, 247, 0.06);
  outline: none;
}

.btn-add-custom:active {
  transform: scale(0.98);
}

.btn-add-custom-plus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  font-size: 1.4rem;
  font-weight: 900;
  line-height: 1;
  color: var(--accent);
}

/* End-of-period divider between event groups in the running log.
   Solid black band so it visually snaps apart from the surrounding
   event rows at a glance. */
.event-log-divider {
  list-style: none;
  margin: 6px 0;
  padding: 10px 6px;
  text-align: center;
  color: #ffffff;
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: #000000;
  border-top: 1px solid #000000;
  border-bottom: 1px solid #000000;
  border-radius: 4px;
}

/* Column header row. Uses the SAME grid template as .event-log-item
   below so "Time" sits directly over the clock column, "Cap" over the
   cap column, etc. Muted colour + tiny font so the headers read as
   labels, not entries. */
.event-log-columns {
  display: grid;
  /* Score column uses a fixed 48px (not auto) so the header grid
     and each row grid share identical track widths — the running
     score values in the rows below sit pixel-aligned under the
     centered Score/W-D header. An auto track would size each
     grid independently (the header's content is wider than a
     typical "1-0" value), visibly misaligning the columns. */
  grid-template-columns: 52px 36px 28px 40px 1fr 48px;
  gap: 10px;
  padding: 4px 6px 6px;
  border-bottom: 1px solid var(--border);
  color: var(--fg-muted);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.event-log-columns span {
  text-align: center;
}

.event-log-columns span:first-child {
  text-align: right; /* Time is right-aligned in the rows — match it here */
}

.event-log-columns span:nth-child(5) {
  text-align: left;  /* Event label column is left-aligned in the rows */
}

.event-log-columns span:last-child {
  text-align: center; /* Score column is centered — the running
                         score values in the rows below center too,
                         so the header sits directly above them. */
}

/* Score header stacks "Score" (small) centered over "W–D" (main) so
   the column has an explicit label without the header row growing
   wider. */
.event-log-columns .col-header-score {
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
  gap: 1px;
}

.col-header-score-small {
  font-size: 0.56rem;
  font-weight: 600;
  opacity: 0.7;
  letter-spacing: 0.1em;
}

.event-log {
  list-style: none;
  margin: 0;
  padding: 0;
  font-variant-numeric: tabular-nums;
}

.event-log-item {
  display: grid;
  /* [clockTime] [period] [team badge] [cap] [type label] [score-after] */
  /* Score column fixed at 48px (matches .event-log-columns) so rows
     and header share identical track widths — see the comment there. */
  grid-template-columns: 52px 36px 28px 40px 1fr 48px;
  align-items: center;
  gap: 10px;
  padding: 8px 6px;
  border-bottom: 1px solid var(--border);
  font-size: 0.92rem;
}

.event-log-item:last-child {
  border-bottom: none;
}

/* Rows are tappable (open the edit modal) — hint at it visually. */
.event-log-item[data-event-id] {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  border-radius: 4px;
}

.event-log-item[data-event-id]:active {
  background: rgba(79, 195, 247, 0.08);
}

/* Highlight: this foul tipped the player over the exclusion threshold.
   Red tint + red left-edge accent + a second row for the "Nth
   penalty – rolled" comment. */
.event-log-item--excluded {
  background: rgba(239, 68, 68, 0.18);
  box-shadow: inset 4px 0 0 var(--danger);
}

.event-log-item--excluded[data-event-id]:active {
  background: rgba(239, 68, 68, 0.26);
}

/* "Needs info" — yellow tint + amber left-edge band on rows where a
   required field is missing (player / clock time / team / goal type).
   Whole row is already tappable to open the edit modal. The amber
   color (--warn) reads as "soft flag" — noticeable but not an error.
   Skipped on rows that are also excluded-trigger (red wins) since
   those should already be addressed first. */
.event-log-item--needs-info:not(.event-log-item--excluded) {
  background: rgba(251, 191, 36, 0.10);
  box-shadow: inset 4px 0 0 var(--warn);
}

.event-log-item--needs-info:not(.event-log-item--excluded)[data-event-id]:active {
  background: rgba(251, 191, 36, 0.20);
}

/* Exclusion comment, rendered inline inside the event-type cell so it
   sits immediately after the event label ("BRUTALITY – Third penalty
   – rolled"). Italic + red so it reads as a note. */
.event-log-item .event-comment-inline {
  color: var(--danger);
  font-style: italic;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: none;
}

.event-log-item .event-clock {
  color: var(--fg);
  font-weight: 700;
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.event-log-item .event-clock--empty {
  color: var(--fg-muted);
  opacity: 0.4;
}

.event-log-item .event-cap {
  color: var(--fg);
  font-weight: 800;
  font-size: 0.9rem;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.event-log-item .event-cap--empty {
  color: var(--fg-muted);
  opacity: 0.4;
}

/* Game Progress cap column when the event is attributed to Coach or
   Bench — smaller text, accent color, no # prefix. */
.event-log-item .event-cap--staff {
  color: var(--accent);
  font-size: 0.65rem;
  font-weight: 900;
  letter-spacing: 0.1em;
}

.event-log-item .event-period {
  color: var(--fg-muted);
  font-weight: 700;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-align: center;
}

.event-log-item .event-team {
  font-weight: 800;
  text-align: center;
  padding: 2px 0;
  border-radius: 4px;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
}

.event-log-item--white .event-team {
  background: #ffffff;
  color: #0b1f33;
}

.event-log-item--dark .event-team {
  background: #0a1929;
  color: #ffffff;
  border: 1px solid #1e3a5f;
}

/* Custom events without a team picked — no cap-colored badge, just
   the dimmed em-dash to match the other empty cells in the row. */
.event-log-item--unscored .event-team,
.event-log-item .event-team--empty {
  background: transparent;
  color: var(--fg-muted);
  opacity: 0.4;
  font-weight: 700;
}

.event-log-item .event-type {
  font-weight: 700;
  font-size: 0.88rem;
  letter-spacing: 0.04em;
}

.event-log-item .event-score {
  color: var(--accent);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  text-align: center; /* Sits directly under the centered Score/W-D header */
}

.event-log-item .event-score--empty {
  color: var(--fg-muted);
  opacity: 0.4;
  font-weight: 700;
  text-align: center;
}

.event-log-empty {
  color: var(--fg-muted);
  font-style: italic;
  padding: 16px 6px;
  text-align: center;
  font-size: 0.9rem;
}

/* ============================================================
   Cap number picker modal
   ============================================================ */

/* When the modal is open, prevent the background page from scrolling.
   iOS Safari ignores `overflow: hidden` for touch-drag, so we also pin
   the body with `position: fixed` and `width: 100%`. The inline `top`
   style — set in refreshBodyScrollLock — holds the page's current scroll
   offset so it doesn't visually jump on open/close. */
body.modal-open {
  position: fixed;
  left: 0;
  right: 0;
  width: 100%;
  overflow: hidden;
}

.cap-picker-modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

/* Native [hidden] attribute already hides the element, but a !important
   override guards against any child rule (flex, etc.) forcing it visible. */
.cap-picker-modal[hidden] {
  display: none !important;
}

.cap-picker-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.cap-picker-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.cap-picker-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}

.cap-picker-header h2 {
  margin: 0;
  font-size: 0.95rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

.cap-picker-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  padding: 14px;
  overflow-y: auto;
}

.cap-picker-cell {
  font: inherit;
  font-size: 1.3rem;
  font-weight: 700;
  min-height: 56px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, background 0.15s ease;
}

.cap-picker-cell:active {
  transform: scale(0.95);
  background: #e2e8f0;
}

/* The clear / none cell is muted so users can tell it apart from numbers. */
.cap-picker-cell--clear {
  background: transparent;
  color: var(--fg-muted);
  border-style: dashed;
  border-color: var(--fg-muted);
}

.cap-picker-cell--clear:active {
  background: rgba(168, 182, 197, 0.15);
}

/* Caps already in use on the active team. The <button disabled> blocks the
   tap; these styles make it read as unavailable rather than broken. */
.cap-picker-cell--in-use {
  background: #e2e8f0;
  color: #94a3b8;
  border-color: #cbd5e1;
  cursor: not-allowed;
  text-decoration: line-through;
  text-decoration-thickness: 2px;
}

.cap-picker-cell--in-use:active {
  /* Disabled cells shouldn't flash on tap. */
  transform: none;
}

.cap-picker-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
}

.cap-picker-footer .btn {
  min-width: 120px;
}

/* Narrower screens (iPhone portrait): reduce grid columns so cells stay big. */
@media (max-width: 480px) {
  .cap-picker-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* ============================================================
   Entry modal — one card for new events (team + player + time)
   with a Review stage for confirmation.
   ============================================================ */

.entry-modal {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.entry-modal[hidden] {
  display: none !important;
}

.entry-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.entry-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Stage = fill or review. Flex-column so header stays pinned at
   top, footer pinned at bottom, and body absorbs the remainder.
   min-height: 0 is the key — without it the body's overflow-y: auto
   can't resolve (flex items default to min-content, so body would
   expand to natural height and the panel would clip). This became
   visible on iPad landscape where the fill-stage's foul-type +
   period + team + player grid + time fields together exceed the
   available height and internal scrolling wasn't working. */
.entry-stage {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
  overflow: hidden;
}

.entry-stage[hidden] {
  display: none !important;
}

.entry-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  text-align: center;
  flex: 0 0 auto;
}

.entry-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

.entry-body {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;  /* iOS momentum-scroll */
}

.entry-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.entry-field[hidden] {
  display: none !important;
}

.entry-label {
  font-size: 0.72rem;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}

/* Foul type — shown for OTHER FOUL events. Five subtype choices laid
   out as equal-width grid cells so no button is wider than the rest
   just because its label is longer ("Red Card" vs "Penalty"). On
   narrow screens the grid auto-wraps via minmax. */
.entry-foul-type-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px;
}

.entry-foul-type-choice {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 10px 14px;
  min-height: 44px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  transition: transform 0.05s ease;
  white-space: nowrap;
}

.entry-foul-type-choice:active {
  transform: scale(0.97);
}

.entry-foul-type-choice--selected {
  background: rgba(220, 38, 38, 0.18); /* soft red — matches FOULS btn */
  border-color: var(--danger);
  color: #fecaca;
}

/* Goal-type subtype row — same structural rules as the foul-type
   row, but selected state tints green to match the GOAL action
   button so the link between the button and its submenu is obvious. */
.entry-goal-type-row,
.edit-goal-type-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
}

.entry-goal-type-choice,
.edit-goal-type-choice {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 10px 14px;
  min-height: 44px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  transition: transform 0.05s ease;
  white-space: nowrap;
}

.entry-goal-type-choice:active,
.edit-goal-type-choice:active {
  transform: scale(0.97);
}

.entry-goal-type-choice--selected,
.edit-goal-type-choice--selected {
  background: rgba(5, 150, 105, 0.22); /* soft emerald — matches GOAL btn */
  border-color: #059669;
  color: #a7f3d0;
}

/* Timeout-kind row — same structural rules as foul-type / goal-type.
   Selected state tints amber to match the TIMEOUT action button on the
   scoreboard so the link between the button and its submenu is obvious. */
.entry-timeout-kind-row,
.edit-timeout-kind-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
}

.entry-timeout-kind-btn,
.edit-timeout-kind-btn {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 10px 14px;
  min-height: 44px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  transition: transform 0.05s ease;
  white-space: nowrap;
}

.entry-timeout-kind-btn:active,
.edit-timeout-kind-btn:active {
  transform: scale(0.97);
}

.entry-timeout-kind-btn--selected,
.edit-timeout-kind-btn--selected {
  background: rgba(245, 158, 11, 0.22); /* soft amber — matches TIMEOUT btn */
  border-color: #f59e0b;
  color: #fde68a;
}

/* Period selector — one small button per reached period. Current
   game period is pre-selected; tapping another logs retroactively. */
.entry-period-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.entry-period-choice {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 8px 14px;
  min-height: 40px;
  min-width: 52px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  transition: transform 0.05s ease;
}

.entry-period-choice:active {
  transform: scale(0.97);
}

.entry-period-choice--selected {
  background: rgba(79, 195, 247, 0.15);
  border-color: var(--accent);
  color: var(--accent);
}

/* Team choices: same styling rules as the edit modal's team toggles.
   minmax(0, 1fr) — not plain 1fr — so columns can actually shrink below
   their content's intrinsic min-width. Without minmax(0, ...), the
   grid track defaults to `minmax(auto, 1fr)`, which honors the
   intrinsic min-content of the children. The .choice-school span has
   white-space: nowrap, so a long school name like "Davenport High
   School" forces the column wider than half the modal — the dark
   button (column 2) then spills off the right edge on iPhone-portrait
   viewports. Reproduced live during the iPhone-portrait smoke test
   (Run 2). minmax(0, 1fr) lets the column shrink, which lets the
   existing text-overflow: ellipsis on .choice-school finally kick in. */
.entry-team-choices {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px;
}

.entry-team-choice {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 88px;
  padding: 12px;
  border-radius: 10px;
  border: 2px solid var(--border);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  opacity: 0.6;
  transition: transform 0.05s ease, opacity 0.15s ease;
}

.entry-team-choice:active:not(:disabled) {
  transform: scale(0.98);
}

.entry-team-choice:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.entry-team-choice--selected {
  opacity: 1;
  box-shadow: inset 0 0 0 3px var(--accent);
}

.entry-team-choice--white {
  background: #ffffff;
  color: #0b1f33;
  border-color: #cbd5e1;
}

.entry-team-choice--dark {
  background: #0a1929;
  color: #ffffff;
  border-color: #1e3a5f;
}

.entry-team-choice .choice-badge {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.75;
}

.entry-team-choice .choice-school {
  font-size: 1rem;
  font-weight: 800;
  text-align: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-team-choice .choice-subtitle {
  font-size: 0.78rem;
  opacity: 0.7;
  font-weight: 600;
  min-height: 1em;
}

/* Inline player grid on the entry card. Field players come first
   (most common picks at the top), starting goalie next, backup last
   if named — same order as the roster helper. */
.entry-player-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

@media (max-width: 480px) {
  .entry-player-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.entry-player-cell {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 78px;
  padding: 10px 8px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  text-align: center;
  transition: transform 0.05s ease, box-shadow 0.1s ease;
}

.entry-player-cell:active {
  transform: scale(0.97);
  background: #e2e8f0;
}

/* Currently-selected player stands out with the accent ring. */
.entry-player-cell--selected {
  box-shadow: inset 0 0 0 3px var(--accent);
  border-color: var(--accent);
}

/* ============================================================
   Assist picker — inline grid of player cells used by both the
   entry-modal and edit-modal Assist field. Visually mirrors the
   scorer (.entry-player-cell) grid but uses cyan accents so the
   two picks stay distinct on the same card. The "No assist"
   sentinel cell sits first; the goal scorer's cell is disabled.
   ============================================================ */

.entry-assist-grid,
.edit-assist-grid,
.entry-ejection-drawn-grid,
.edit-ejection-drawn-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px;
}

.entry-assist-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 10px 6px;
  min-height: 64px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  font: inherit;
  color: var(--fg);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, box-shadow 0.1s ease;
}

.entry-assist-cell:active {
  transform: scale(0.97);
}

/* Currently-selected assister stands out with a cyan ring (distinct
   from the scorer's emerald). Visually communicates "this player
   gets the assist credit". */
.entry-assist-cell--selected {
  box-shadow: inset 0 0 0 3px #06b6d4;
  border-color: #06b6d4;
  background: rgba(6, 182, 212, 0.12);
}

/* No-assist sentinel — slightly muted so it reads as "default /
   skip" without being aggressively de-emphasized. */
.entry-assist-cell--none {
  background: rgba(148, 163, 184, 0.10);
  border-style: dashed;
}

/* The goal scorer's cell is disabled in the assist grid (a player
   can't assist their own goal). Reduced opacity + the emerald
   border make it clear which player is the scorer without it
   competing for selection. */
.entry-assist-cell--scorer {
  opacity: 0.55;
  cursor: not-allowed;
  border-color: #059669;
}

.entry-assist-cell .pp-cap {
  font-size: 1.4rem;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.entry-assist-cell .pp-name {
  font-size: 0.78rem;
  font-weight: 600;
  opacity: 0.8;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-assist-cell .pp-staff-label {
  font-size: 0.85rem;
  letter-spacing: 0.08em;
}

.entry-player-cell .pp-cap {
  font-size: 1.5rem;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.entry-player-cell .pp-name {
  font-size: 0.78rem;
  font-weight: 600;
  opacity: 0.8;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.entry-player-cell .pp-role {
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #4b6478;
}

/* Excluded player — reached the major-foul threshold. Cell is
   disabled; visually muted with a red tint and an "Excluded" label. */
.entry-player-cell--excluded {
  opacity: 0.55;
  background: #fee2e2;
  border-color: #fca5a5;
  cursor: not-allowed;
}

.entry-player-cell--excluded .pp-cap {
  color: #991b1b;
}

.entry-player-cell--excluded .pp-name {
  color: #7f1d1d;
  opacity: 0.75;
}

.entry-player-cell .pp-excluded {
  font-size: 0.6rem;
  font-weight: 900;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--danger);
}

/* Coach / Bench cells — muted palette, no cap number. Appended to
   the grid for misconduct / yellow / red card events. */
.entry-player-cell--staff {
  background: #1f3a5a;
  color: #dbeafe;
  border-color: #365e8d;
}

.entry-player-cell--staff:active {
  background: #2a4672;
}

.entry-player-cell--staff.entry-player-cell--selected {
  box-shadow: inset 0 0 0 3px var(--accent);
  border-color: var(--accent);
}

.entry-player-cell--staff .pp-staff-label {
  font-size: 1rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 900;
}

.entry-player-empty {
  grid-column: 1 / -1;
  padding: 20px 8px;
  text-align: center;
  color: var(--fg-muted);
  font-style: italic;
  font-size: 0.9rem;
}

.entry-clock-input {
  font: inherit;
  font-size: 1.8rem !important;
  font-weight: 800;
  text-align: center;
  padding: 12px;
  min-height: 58px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
  -webkit-appearance: none;
  appearance: none;
}

.entry-clock-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(79, 195, 247, 0.25);
}

.entry-clock-input.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.25);
}

/* Custom-event description input (entry + edit modals) */
.entry-custom-input,
.edit-custom-input {
  font: inherit;
  font-size: 1.05rem;
  padding: 14px;
  min-height: 56px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 8px;
  -webkit-appearance: none;
  appearance: none;
}

.entry-custom-input:focus,
.edit-custom-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(79, 195, 247, 0.25);
}

.entry-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  flex-wrap: wrap;
  flex: 0 0 auto;   /* Pinned at bottom while .entry-body scrolls */
}

.entry-footer .btn {
  min-width: 100px;
}

/* Review stage */

.entry-review-intro {
  margin: 0;
  font-size: 0.88rem;
  color: var(--fg-muted);
}

.entry-review-columns {
  padding: 4px 6px;
  border-top: 1px solid var(--border);
}

.entry-review-preview {
  list-style: none;
  margin: 0;
  padding: 0;
  background: var(--surface-2);
  border-radius: 6px;
  font-variant-numeric: tabular-nums;
}

.entry-review-preview .event-log-item {
  padding: 10px 6px;
  cursor: default;
}

.entry-review-preview .event-log-item:active {
  background: transparent;
}

.entry-review-warnings {
  background: rgba(251, 191, 36, 0.1);
  border: 1px solid var(--warn);
  color: #fde68a;
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 0.88rem;
}

.entry-review-warnings[hidden] {
  display: none !important;
}

.entry-review-warnings strong {
  display: block;
  color: var(--warn);
  margin-bottom: 4px;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.entry-review-warnings ul {
  margin: 0;
  padding-left: 20px;
}

.entry-review-warnings li {
  margin: 2px 0;
}

/* The whole banner is tappable — same shortcut as the ← Edit footer
   button. Cursor + active feedback advertise the affordance, and
   the inline "Tap to edit" hint at the bottom names the action. */
.entry-review-warnings[role="button"] {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 0.1s ease;
}
.entry-review-warnings[role="button"]:active {
  background: rgba(251, 191, 36, 0.18);
}
.entry-review-warnings-hint {
  display: block;
  margin-top: 6px;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--warn);
  text-align: right;
}

/* ============================================================
   Player picker modal
   Roster-scoped grid: each cell is a cap number + name for one
   player on the selected team. Sorted by cap via the same rules
   as the setup form.
   ============================================================ */

.player-picker-modal {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.player-picker-modal[hidden] {
  display: none !important;
}

.player-picker-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.player-picker-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 640px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.player-picker-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  text-align: center;
}

.player-picker-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
}

.player-picker-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  padding: 14px;
  overflow-y: auto;
}

@media (max-width: 520px) {
  .player-picker-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.player-picker-cell {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 88px;
  padding: 10px 8px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, filter 0.1s ease;
  text-align: center;
}

.player-picker-cell:active {
  transform: scale(0.97);
  background: #e2e8f0;
}

.player-picker-cell .pp-cap {
  font-size: 1.6rem;
  font-weight: 900;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.player-picker-cell .pp-name {
  font-size: 0.82rem;
  font-weight: 600;
  opacity: 0.8;
  /* Truncate long names so the cell height stays predictable */
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.player-picker-cell .pp-role {
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #4b6478;
}

.player-picker-empty {
  grid-column: 1 / -1;
  padding: 24px 8px;
  text-align: center;
  color: var(--fg-muted);
  font-style: italic;
}

.player-picker-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
}

.player-picker-footer .btn {
  min-width: 120px;
}

/* ============================================================
   Saved Rosters — "Load saved roster" button + picker modal  (V2 #8a)
   ============================================================ */

.team-card-actions {
  display: flex;
  justify-content: flex-start;
}

.btn-load-roster {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  padding: 8px 14px;
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--accent);
  border: 1px solid var(--border);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.btn-load-roster:hover,
.btn-load-roster:focus-visible {
  filter: brightness(1.1);
}

.btn-load-roster:active {
  transform: scale(0.98);
}

.roster-picker-modal {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.roster-picker-modal[hidden] {
  display: none !important;
}

.roster-picker-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.roster-picker-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.roster-picker-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  text-align: center;
}

.roster-picker-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
}

.roster-picker-sub {
  margin: 6px 0 0;
  font-size: 0.78rem;
  color: var(--fg-muted);
}

.roster-picker-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  overflow-y: auto;
}

.roster-card {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 12px 14px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 10px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, filter 0.1s ease;
  text-align: left;
  width: 100%;
}

.roster-card:active {
  transform: scale(0.99);
  background: #e2e8f0;
}

.roster-card-title {
  font-size: 1rem;
  font-weight: 800;
  line-height: 1.2;
}

.roster-card-badge {
  display: inline-block;
  margin-left: 2px;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  vertical-align: middle;
  background: #d8e2ec;
  color: #3a5468;
}

.roster-card-badge--match {
  background: var(--accent);
  color: #ffffff;
}

.roster-card-meta {
  font-size: 0.78rem;
  font-weight: 600;
  opacity: 0.75;
}

.roster-picker-empty {
  margin: 0;
  padding: 22px 10px;
  text-align: center;
  color: var(--fg-muted);
  font-style: italic;
  line-height: 1.45;
}

.roster-picker-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
}

.roster-picker-footer .btn-secondary {
  min-width: 120px;
}

.btn-link {
  background: none;
  border: none;
  color: var(--accent);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
  padding: 6px 4px;
}

/* ---- Saved Rosters manage screen ---- */

.saved-rosters-header {
  display: flex;
  align-items: center;
  gap: 14px;
}

.saved-rosters-header h1 {
  margin: 0;
  font-size: 1.25rem;
}

.saved-rosters-intro {
  margin: 0;
  color: var(--fg-muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

.saved-rosters-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.saved-roster-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
}

.saved-roster-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  flex: 1 1 220px;
}

.saved-roster-title {
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.2;
}

.saved-roster-meta {
  font-size: 0.82rem;
  color: var(--fg-muted);
}

.saved-roster-actions {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}

.saved-roster-actions .btn {
  min-width: 84px;
}

.saved-roster-delete {
  background: #7f1d1d;
  color: #fff;
  border: 1px solid #991b1b;
  border-radius: 8px;
  padding: 8px 12px;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.saved-roster-delete:hover,
.saved-roster-delete:focus-visible {
  filter: brightness(1.12);
}

.saved-rosters-empty {
  margin: 0;
  padding: 22px 10px;
  text-align: center;
  color: var(--fg-muted);
  font-style: italic;
  line-height: 1.45;
}

/* ---- Past Games ---- */

/* "View past games…" button row on the Setup screen, sitting between
   the Game Info block and the team columns. Global affordance — not
   per-team, so it gets its own row outside the team-columns block. */
.setup-past-games {
  display: flex;
  justify-content: flex-end;
}

.past-games-header {
  display: flex;
  align-items: center;
  gap: 14px;
}

.past-games-header h1 {
  margin: 0;
  font-size: 1.25rem;
}

.past-games-intro {
  margin: 0;
  color: var(--fg-muted);
  font-size: 0.9rem;
  line-height: 1.45;
}

.past-games-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.past-game-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 12px 14px;
}

.past-game-info {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  flex: 1 1 220px;
}

.past-game-title {
  font-size: 1.05rem;
  font-weight: 800;
  line-height: 1.2;
}

.past-game-meta {
  font-size: 0.82rem;
  color: var(--fg-muted);
}

.past-game-actions {
  display: flex;
  gap: 8px;
  flex: 0 0 auto;
}

.past-game-actions .btn {
  min-width: 84px;
}

.past-game-delete {
  background: #7f1d1d;
  color: #fff;
  border: 1px solid #991b1b;
  border-radius: 8px;
  padding: 8px 12px;
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.past-game-delete:hover,
.past-game-delete:focus-visible {
  filter: brightness(1.12);
}

.past-games-empty {
  margin: 0;
  padding: 22px 10px;
  text-align: center;
  color: var(--fg-muted);
  font-style: italic;
  line-height: 1.45;
}

/* ---- Saved-roster editor modal ---- */

.roster-edit-modal {
  position: fixed;
  inset: 0;
  z-index: 130;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.roster-edit-modal[hidden] {
  display: none !important;
}

.roster-edit-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.roster-edit-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 560px;
  max-height: 92vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.roster-edit-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  text-align: center;
}

.roster-edit-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
}

.roster-edit-body {
  padding: 14px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.roster-edit-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.roster-edit-footer .btn {
  min-width: 120px;
}

/* ============================================================
   Event edit modal
   Opened by tapping a Game Progress row. Edits team / player /
   clock time, or deletes the event outright.
   ============================================================ */

.event-edit-modal {
  position: fixed;
  inset: 0;
  z-index: 125;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.event-edit-modal[hidden] {
  display: none !important;
}

.event-edit-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.event-edit-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.event-edit-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  text-align: center;
  flex: 0 0 auto;
}

.event-edit-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

.event-edit-meta {
  margin: 4px 0 0;
  color: var(--fg-muted);
  font-size: 0.85rem;
}

.event-edit-body {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.edit-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.edit-field[hidden] {
  display: none !important;
}

.edit-label {
  font-size: 0.72rem;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}

/* Type grid in the edit modal — equal-width buttons, wraps responsively
   via auto-fit. Selected type gets the accent ring, matching the
   foul-subtype row in the entry modal. */
.edit-type-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
}

.edit-type-choice {
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  padding: 10px 10px;
  min-height: 42px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: transform 0.05s ease;
  white-space: nowrap;
}

.edit-type-choice:active {
  transform: scale(0.97);
}

.edit-type-choice--selected {
  background: rgba(79, 195, 247, 0.15);
  border-color: var(--accent);
  color: var(--accent);
}

/* Period row in the edit modal — small buttons, same visual as the
   entry modal's period row. */
.edit-period-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.edit-period-choice {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 8px 14px;
  min-height: 40px;
  min-width: 52px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  transition: transform 0.05s ease;
}

.edit-period-choice:active {
  transform: scale(0.97);
}

.edit-period-choice--selected {
  background: rgba(79, 195, 247, 0.15);
  border-color: var(--accent);
  color: var(--accent);
}

.edit-team-choices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.edit-team-choice {
  font: inherit;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 64px;
  padding: 10px 12px;
  border-radius: 10px;
  border: 2px solid var(--border);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease, filter 0.1s ease;
  opacity: 0.55;
}

.edit-team-choice:active {
  transform: scale(0.98);
}

.edit-team-choice--selected {
  opacity: 1;
  /* Extra inset border using box-shadow so we don't fight the per-color
     outer border. */
  box-shadow: inset 0 0 0 3px var(--accent);
}

.edit-team-choice--white {
  background: #ffffff;
  color: #0b1f33;
  border-color: #cbd5e1;
}

.edit-team-choice--dark {
  background: #0a1929;
  color: #ffffff;
  border-color: #1e3a5f;
}

.edit-team-choice .choice-badge {
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  opacity: 0.75;
}

.edit-team-choice .choice-school {
  font-size: 0.95rem;
  font-weight: 700;
  text-align: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.edit-player-row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.edit-player-current {
  flex: 1;
  min-width: 140px;
  padding: 10px 14px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 8px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.edit-player-current.is-empty {
  color: var(--fg-muted);
  font-style: italic;
  font-weight: 500;
}

.edit-player-row .btn {
  flex: 0 0 auto;
}

.edit-clock-input {
  font: inherit;
  font-size: 1.6rem !important;
  font-weight: 800;
  text-align: center;
  padding: 12px;
  min-height: 56px;
  background: var(--input-bg);
  color: var(--input-fg);
  border: 2px solid var(--input-border);
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
  -webkit-appearance: none;
  appearance: none;
}

.edit-clock-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(79, 195, 247, 0.25);
}

.edit-clock-input.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.25);
}

.event-edit-footer {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}

.event-edit-footer-spacer {
  flex: 1;
}

.event-edit-footer .btn {
  min-width: 96px;
}

/* ============================================================
   Scoresheet export screen
   ============================================================

   Reproduces the USA Water Polo Official Sanctioned Event Scoresheet
   (S&R Sport form) as closely as possible in HTML. The target is a
   single-page letter-LANDSCAPE print output that a league will accept
   as a direct replacement for the paper form.

   Structure mirrors the paper sheet:
     1. Title bar
     2. Team strip (White Team / Coach / Dark Team / Coach)
     3. Two-team roster tables side by side (caps 2–18 and 20 per
        paper, each row has PF cells + STATS + Activity-by-Period)
     4. Goalkeeper sub-tables under each roster
     5. Bottom strip: 4-column Game Progress log (left) | Timeouts +
        Game Results (middle) | Game Info + Referees + Legend (right)

   Deferred stats (Assists, Steals, Ej Drawn, Attempts, Goalkeeper
   Saves) and not-yet-captured info fields (Coach, Site, Time, Secy,
   Referees) render as empty cells per the user's direction:
   "if the data is not provided, leave the box blank."

   Two audiences for the same markup:
     - On-screen preview inside the dark app shell (scorekeeper
       eyeballs the sheet before sharing)
     - Print / PDF output via Safari's Share → Print → Save to Files
       (the @media print block at the end swaps colors + sizing for
       paper fidelity) */

.scoresheet-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 8px 4px;
}

.scoresheet-nav-title {
  margin: 0;
  font-size: 0.88rem;
  color: var(--accent);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-weight: 700;
}

.scoresheet-nav-actions {
  display: flex;
  gap: 8px;
}

/* ---- Print-flow hint card ----
   Permanent, always-visible reminder above the scoresheet preview.
   Tells the parent scorekeeper exactly which two manual settings
   to apply in Safari's print dialog (Orientation = Landscape,
   Scale = 91%) — both unfixable WebKit quirks documented in
   DECISIONS 2026-04-23.

   Visual goal: noticeable but not alarming. Uses --warn (amber)
   for the left edge to draw the eye without reading as an error.
   Lives outside the .scoresheet container so the printed PDF is
   untouched; hidden during print via the @media print block. */
.scoresheet-print-hint {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 8px 12px;
  border-left: 3px solid var(--warn);
  background: var(--surface);
  border-radius: 4px;
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--fg);
  flex: 0 0 auto;
}
.scoresheet-print-hint-label {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.78rem;
  color: var(--warn);
}
.scoresheet-print-hint-body strong {
  font-weight: 700;
  color: var(--fg);
}

/* ---- Share-flow hint card ----
   Sibling to .scoresheet-print-hint, shown ONLY when the match is
   Final. Tells the parent scorekeeper how to hand the PDF off to the
   other team's coach via Safari's print preview → share icon. Uses
   --accent (cyan) for the left edge to distinguish it from the amber
   print-quirk reminder; both can be visible simultaneously after
   End Match. Lives outside the .scoresheet container so the printed
   PDF is untouched; hidden during print via the @media print block. */
.scoresheet-share-hint {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 8px 12px;
  border-left: 3px solid var(--accent);
  background: var(--surface);
  border-radius: 4px;
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--fg);
  flex: 0 0 auto;
}
.scoresheet-share-hint-label {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.78rem;
  color: var(--accent);
}
.scoresheet-share-hint-body strong {
  font-weight: 700;
  color: var(--fg);
}

/* iPhone portrait fallback for the Scoresheet screen.
   Two narrow-viewport problems handled here:

   1. The .scoresheet-nav row (← Match · SCORESHEET title ·
      Save CSV ↓ · Print / Share ↗) squeezes its buttons on a
      390-430px viewport, forcing "CSV" / "Share" / "↗" onto
      separate lines and producing very tall buttons. Letting the
      flex row wrap, hiding the title, and stacking the actions
      below the back button keeps the buttons at their natural
      width.

   2. The .scoresheet article is laid out for landscape paper
      (~1000px wide). At 390px it collapses every column and the
      cell labels overlap. Force a min-width and let the screen
      container scroll horizontally so the scorekeeper can pan
      across the preview instead of seeing a squished mess. The
      print output is untouched — this @media block doesn't fire
      when Safari renders to 11in landscape paper. */
@media (max-width: 640px) {
  .scoresheet-nav {
    flex-wrap: wrap;
    justify-content: flex-start;
    gap: 8px;
  }
  /* Hide the redundant title on narrow phones — the back button +
     action buttons make it obvious which screen you're on, and the
     title was eating a flex slot that forced button-text wrap. */
  .scoresheet-nav-title {
    display: none;
  }
  .scoresheet-nav-actions {
    flex-wrap: wrap;
  }
}

/* Scoresheet article horizontal-scroll — separate, wider breakpoint.
   The article is laid out for landscape paper (~1000px wide). At
   anything narrower, the team rosters and especially the 4 Game
   Progress sub-tables (which split a `repeat(4, 1fr)` grid) collapse
   and headers cram together (e.g. "Identity" / "Score" / "Time" /
   "W D" / "Remarks" / "W-D" overlap visually).
   History:
   - 2026-04-29: was previously gated to max-width: 640px (iPhone-
     portrait only). User reported the same crammed-headers symptom on
     iPhone-landscape (844px). Bumped to 900px so iPhone-landscape and
     iPad-portrait (768-834px) also got the horizontal-pan treatment.
   - 2026-05-13: bumped again from 900 → 1000 after the same crammed-
     headers symptom showed up on iPhone 16 Pro Max landscape (932px
     CSS viewport — JUST above the 900 threshold). 1000px matches the
     scoresheet's natural target width, so anything narrower than that
     can't fit the 4-column Game Progress grid comfortably anyway.
   iPad-landscape (≥1024px) still renders the scoresheet at its
   natural width without scroll.
   The print output is untouched — this @media block doesn't fire
   when Safari renders to 11in landscape paper. */
@media (max-width: 1000px) {
  /* One scroll container instead of nested ones: the screen scrolls
     in both axes, the scoresheet itself takes its natural size. */
  .scoresheet-screen {
    overflow: auto;
  }
  .scoresheet {
    min-width: 1000px;
    overflow: visible;
    flex: 0 0 auto;
  }
}

/* The scoresheet itself — white paper surface inside the dark shell,
   with the paper aspect ratio baked in so the on-screen preview
   reads like what the print will look like. */
.scoresheet {
  background: #ffffff;
  color: #000000;
  padding: 12px 14px;
  border-radius: 6px;
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 9.5px;
  line-height: 1.2;
  display: flex;
  flex-direction: column;
  gap: 6px;
  overflow: auto;
  flex: 1 1 auto;
  min-height: 0;
}

/* ---- Header strip ---- */
.sheet-title-bar {
  text-align: center;
  font-weight: 800;
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 2px 0;
  border-bottom: 1px solid #000000;
}

.sheet-team-strip {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1.6fr 1fr;
  gap: 12px;
  padding: 4px 2px;
  font-size: 10px;
}

.sheet-team-field {
  display: flex;
  align-items: baseline;
  gap: 6px;
  border-bottom: 1px solid #000000;
  padding-bottom: 1px;
}

.sheet-team-label {
  font-weight: 700;
  white-space: nowrap;
}

.sheet-team-value {
  font-weight: 600;
  min-height: 14px;
  flex: 1;
}

/* ---- Rosters (two teams side by side) ---- */

.sheet-rosters {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.sheet-roster {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 8.5px;
}

.sheet-roster th,
.sheet-roster td {
  border: 1px solid #000000;
  padding: 1px 2px;
  text-align: center;
  vertical-align: middle;
  height: 14px;
}

.sheet-roster th {
  background: #e6e6e6;
  font-weight: 700;
  font-size: 8px;
  line-height: 1.1;
  padding: 2px 2px;
}

.sheet-roster .sheet-col-player { width: 20%; }
.sheet-roster .sheet-col-no     { width: 5%;  }
.sheet-roster .sheet-col-pf     { width: 12%; }
.sheet-roster .sheet-col-total  { width: 5%;  }

/* Player name cell — left-aligned with a tiny indent. */
.sheet-roster tbody td:first-child {
  text-align: left;
  padding-left: 3px;
  font-weight: 500;
}

.sheet-roster .sheet-roster-sub th {
  font-size: 7.5px;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.sheet-roster .sheet-period-total td {
  background: #f0f0f0;
  font-weight: 700;
}

/* Zebra-stripe the roster so the eye can trace a single player's
   row across the full width of the stats + activity-by-period grid.
   Applied to tds (not trs) so per-row tints like .sheet-row--excluded
   can still paint the row red for a fouled-out player — the
   higher-specificity excluded rule below wins on those rows. */
.sheet-roster tbody tr:nth-child(even) td {
  background: #f2f2f2;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.sheet-roster tbody tr.sheet-row--excluded td {
  background: #f3d5d5;
}

.sheet-roster .sheet-pt-label {
  text-align: right;
  padding-right: 4px;
}

/* Personal Fouls cell — 3 sub-boxes matching the paper form. Each
   box holds one major-foul entry (E2, P3, B4); empty boxes stay
   blank. Interior dividers are drawn by each box's left border
   (except the first). */
.sheet-roster td:nth-child(3),
.sheet-goalie td:nth-child(3) {
  padding: 0;
}

.sheet-pf-boxes {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  height: 100%;
  min-height: 14px;
}

.sheet-pf-box {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 7.5px;
  font-weight: 700;
  padding: 1px;
}

.sheet-pf-box + .sheet-pf-box {
  border-left: 1px solid #000000;
}

/* Hashed-out cells (goalie Ej Drawn + Attempts — both the header and
   the body cells) — diagonal stripes indicate "not applicable" per
   the paper form's convention. Selectors cover the goalie thead th
   (needs to beat `.sheet-goalie th { background: #e6e6e6 }`) and
   any generic hashed cell in the roster/progress tables. */
.sheet-cell--hashed,
.sheet-goalie th.sheet-cell--hashed,
.sheet-goalie td.sheet-cell--hashed,
.sheet-roster th.sheet-cell--hashed,
.sheet-roster td.sheet-cell--hashed {
  background:
    repeating-linear-gradient(
      45deg,
      rgba(255, 255, 255, 0.92) 0,
      rgba(255, 255, 255, 0.92) 3px,
      #000000 3px,
      #000000 4px
    );
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

/* Goalie tables — one row per team, slotted under the rosters. Use a
   shared structural set of columns so they line up visually with the
   main roster above. */
.sheet-goalies {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 2px;
}

.sheet-goalie {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 8.5px;
}

.sheet-goalie th,
.sheet-goalie td {
  border: 1px solid #000000;
  padding: 1px 2px;
  text-align: center;
  vertical-align: middle;
  height: 14px;
}

.sheet-goalie th {
  background: #e6e6e6;
  font-weight: 700;
  font-size: 8px;
  padding: 2px 2px;
}

.sheet-goalie .sheet-col-player { width: 20%; }
.sheet-goalie .sheet-col-pf     { width: 12%; }
.sheet-goalie .sheet-col-total  { width: 5%;  }

.sheet-goalie tbody td:first-child {
  text-align: left;
  padding-left: 3px;
  font-weight: 500;
}

/* ---- Bottom strip: Game Progress + Timeouts/Results + Info/Legend ---- */

/* Bottom strip proportions tuned to letter-landscape usable width
   (~979 CSS px with 0.35" margins). Game Progress gets the lion's
   share of the row (4 readable columns), with Timeouts/Results in a
   narrow middle stack and Info/Legend on the right. minmax(0, …)
   lets each column shrink below its content minimum if the viewport
   is narrower, so on-screen preview scrolls gracefully while print
   always lays out at the paper proportions. */
.sheet-bottom {
  display: grid;
  grid-template-columns:
    minmax(0, 3.2fr)  /* Game Progress */
    minmax(0, 1fr)    /* Timeouts + Game Results */
    minmax(0, 1.3fr); /* Info + Referees + Legend */
  gap: 6px;
  margin-top: 4px;
  align-items: start;
}

.sheet-section-title {
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 4px;
  background: #e6e6e6;
  /* No top / side borders — the parent box's outline handles its
     own perimeter. A bottom divider separates the title from the
     content below and is added via the box-specific rules further
     down (e.g. .sheet-info-box .sheet-section-title). */
  border-bottom: 1px solid #000000;
}

/* The Game Progress header is NOT wrapped by an outlined box (the
   four column tables below each have their own outlines). Give it
   its own 2px outline so it reads as a distinct label block,
   matching the visual treatment of the Timeouts / Game Results /
   Custom Notes / Game Information titles. */
.sheet-progress-wrap > .sheet-section-title {
  outline: 2px solid #000000;
  outline-offset: -1px;
  border-bottom: none;
  margin-bottom: 2px;
}

/* Game Progress — 4 narrow columns side by side. Each column is its
   own small table with a thick outer border (applied below via the
   outer-cell selectors). Events flow left-to-right, top-to-bottom so
   a long log fills all 4 columns rather than spilling off the page. */
.sheet-progress-columns {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
}

.sheet-progress-col {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 7.5px;
}

.sheet-progress-col th,
.sheet-progress-col td {
  border: 1px solid #000000;
  padding: 2px 3px;
  text-align: center;
  vertical-align: middle;
  /* Fixed row height keeps columns 1–4 aligned even when a wrapped
     remark (e.g. "Fouled Out (…)") would otherwise push rows taller.
     Font is larger than the other tiny tables so the scoresheet
     reads easily without the cells getting taller. */
  height: 22px;
  font-size: 10px;
}

.sheet-progress-col thead th {
  height: 14px;
  font-size: 9px;
}

.sheet-progress-col th {
  background: #e6e6e6;
  font-weight: 700;
  font-size: 7px;
}

/* Paper column widths — Time + twin W|D identity + Remarks + Score.
   Remarks is narrower than before since the cells now hold legend
   codes (P, E, YC, G/N, CN1) rather than full event labels. Width
   redistributed to Time/W/D/Score so each stays readable. The
   "Fouled Out (…)" suffix still fits via wrap-on-word-boundary. */
.sheet-progress-col .sheet-pc-col-time     { width: 20%; }
.sheet-progress-col .sheet-pc-col-identity { width: 20%; }
.sheet-progress-col .sheet-pc-col-w,
.sheet-progress-col .sheet-pc-col-d        { width: 10%; }
.sheet-progress-col .sheet-pc-col-remarks  { width: 36%; }
.sheet-progress-col .sheet-pc-col-score    { width: 24%; }

/* Thick 2px outer border around every independent scoresheet block
   (rosters, goalie sub-tables, Timeouts, Game Results, Custom Notes,
   Game Information, Referee Signatures, Legend) — mirrors the treatment
   applied to the 4 Game Progress column tables so each "box" reads
   as a distinct panel on the paper form. For tables we use `outline`
   on the table element so we don't need to micro-manage rowspan-edge
   cells; for div containers we just bump border-width. */
.sheet-roster,
.sheet-goalie,
.sheet-mini {
  outline: 2px solid #000000;
  outline-offset: -1px;
}

/* Div-based blocks use outline on top of the existing 1px border so
   the thick perimeter is visible and lines up with the table-based
   blocks above (which also use outline: 2px). outline-offset: -1px
   lets the outline overlap the border for a crisp edge. */
.sheet-info-box,
.sheet-legend-box,
.sheet-custom-notes,
.sheet-cap-change-note {
  outline: 2px solid #000000;
  outline-offset: -1px;
}

/* End-of-period divider row inside each Game Progress column —
   solid black bar with white uppercase text, mirrors the on-screen
   Game Progress end-of-period bar so the print and app look
   consistent. */
.sheet-progress-col .sheet-pc-divider td {
  background: #000000;
  color: #ffffff;
  font-weight: 800;
  letter-spacing: 0.08em;
  font-size: 8.5px;
  text-transform: uppercase;
  text-align: center;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

/* Thick 2px outer border on each of the 4 Game Progress column
   tables — marks each column as a distinct block. With
   border-collapse: collapse the perimeter is drawn by styling the
   outermost cells' top/bottom/left/right borders. Care: the left
   edge must target ONLY the first row's first cell and tbody cells,
   not the sub-header row's first cell (which would put a thick
   border on the "W" header cell since Time has rowspan=2 and "W" is
   the first child of row 2). */
.sheet-progress-col thead tr:first-child th {
  border-top: 2px solid #000000;
}
.sheet-progress-col tbody tr:last-child td {
  border-bottom: 2px solid #000000;
}
.sheet-progress-col thead tr:first-child th:first-child,
.sheet-progress-col tbody td:first-child {
  border-left: 2px solid #000000;
}
.sheet-progress-col thead th:last-child,
.sheet-progress-col tbody td:last-child {
  border-right: 2px solid #000000;
}

/* "Score" sub-header sits above "W-D" with no bottom border so the
   two-line header reads as a single stacked label. */
.sheet-progress-col th.sheet-pc-score-top {
  border-bottom: none;
  padding-bottom: 0;
}

/* Remarks cell — left-aligned, allow wrapping. Inherits the column's
   larger font-size so the notation is legible on print without
   making the row taller. */
.sheet-progress-col tbody td:nth-child(4) {
  text-align: left;
  padding-left: 3px;
  white-space: normal;
  word-break: break-word;
  line-height: 1.05;
}

/* Middle stack: Timeouts + Game Results, each small. */
.sheet-middle-stack {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 140px;
}

.sheet-mini {
  border-collapse: collapse;
  table-layout: fixed;
  width: 100%;
  font-size: 8.5px;
}

.sheet-mini th,
.sheet-mini td {
  border: 1px solid #000000;
  padding: 2px 3px;
  text-align: center;
  vertical-align: middle;
  height: 14px;
}

.sheet-mini thead tr:first-child th {
  background: #d8d8d8;
  font-size: 9px;
  font-weight: 800;
  padding: 3px 2px;
}

.sheet-mini thead tr:nth-child(2) th {
  background: #eeeeee;
  font-size: 8px;
}

.sheet-mini tbody th {
  background: #f4f4f4;
  font-weight: 700;
  width: 30%;
}

/* Right stack: Game Info + Referees + Legend + Game # */
.sheet-right-stack {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 170px;
  font-size: 8.5px;
}

.sheet-info-box {
  border: 1px solid #000000;
}

.sheet-info-box .sheet-section-title {
  border-bottom: 1px solid #000000;
}

.sheet-info-row {
  display: grid;
  grid-template-columns: 70px 1fr;
  border-top: 1px solid #000000;
  min-height: 14px;
}

.sheet-info-row:first-of-type {
  border-top: none;
}

.sheet-info-label {
  font-weight: 700;
  padding: 1px 4px;
  background: #f4f4f4;
  border-right: 1px solid #000000;
  font-size: 8px;
}

.sheet-info-row span:last-child {
  padding: 1px 4px;
}

/* Referee Signatures box — each row needs room for an actual
   handwritten signature, not just a one-line caption. Label stays
   small-height on the left; the signature half aligns to the bottom
   so any pre-typed content (none in v1) reads from the signing line. */
.sheet-referees .sheet-info-row {
  min-height: 42px;
}

.sheet-referees .sheet-info-label {
  align-self: stretch;
  display: flex;
  align-items: center;
}

.sheet-referees .sheet-info-row span:last-child {
  display: flex;
  align-items: flex-end;
  padding-bottom: 2px;
}

/* Custom Notes footer — appears only when the match has at least one
   custom event. Sits in the right stack above the Game Info block so
   it lines up visually with the Game Progress column where CN{n}
   labels appear. */
.sheet-custom-notes {
  border: 1px solid #000000;
}

.sheet-custom-notes .sheet-section-title {
  border-bottom: 1px solid #000000;
}

.sheet-custom-notes-list {
  list-style: none;
  margin: 0;
  padding: 3px 6px;
  font-size: 7.5px;
  line-height: 1.35;
}

.sheet-custom-note {
  padding: 1px 0;
  word-break: break-word;
}

.sheet-custom-note-label {
  font-weight: 800;
}

/* Cap Change Note — same outlined-block treatment as Custom Notes,
   but the body is a single paragraph rather than a numbered list
   since the message is advisory (not a list of items to look up). */
.sheet-cap-change-note {
  border: 1px solid #000000;
  margin-top: 6px;
}

.sheet-cap-change-note .sheet-section-title {
  border-bottom: 1px solid #000000;
}

.sheet-cap-change-note-body {
  padding: 4px 6px;
  font-size: 7.5px;
  line-height: 1.4;
  word-break: break-word;
}

.sheet-cap-change-note-body p {
  margin: 0 0 3px 0;
}

.sheet-cap-change-note-body p:last-child {
  margin-bottom: 0;
}

.sheet-cap-change-note-body code {
  font-family: inherit;
  font-weight: 700;
  font-size: 0.95em;
}

/* Definition list for the CC / CS / GS codes. Tight margins so
   the whole note stays compact in the right-column stack. */
.sheet-cap-change-key {
  list-style: none;
  margin: 0 0 3px 0;
  padding: 0;
}

.sheet-cap-change-key li {
  padding: 1px 0;
}

.sheet-legend-box {
  border: 1px solid #000000;
  padding: 4px;
  font-size: 7.5px;
}

.sheet-legend-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.sheet-legend-head {
  font-weight: 800;
  font-size: 8px;
  margin-bottom: 1px;
}

.sheet-legend-item {
  line-height: 1.3;
}

/* Identity row under the goals/fouls legend — 1-char codes (C / B)
   used in the Game Progress identity column, spelled out inline. */
.sheet-legend-identity {
  margin-top: 4px;
  padding-top: 3px;
  border-top: 1px dashed #888888;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
}

.sheet-legend-note {
  color: #555555;
  font-style: italic;
}

/* Tiny swatch before "Row tint = player fouled out" in the legend. */
.sheet-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  background: #f3d5d5;
  border: 1px solid #000000;
  vertical-align: middle;
  margin-right: 4px;
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.sheet-game-num {
  display: grid;
  grid-template-columns: 70px 1fr;
  border-top: 1px solid #000000;
  margin-top: 4px;
  min-height: 14px;
}

.sheet-game-num .sheet-info-label {
  background: transparent;
  border-right: 1px solid #000000;
  padding: 2px 4px;
}

/* Excluded-player tint mirrors the on-screen Game Progress
   behavior — lets a reader spot a "rolled" player at a glance. */
.sheet-row--excluded {
  background: #f3d5d5;
}

/* ---- Save-failure banner ----
   Surfaced by storage.js via the onWriteFailure callback. Appears
   above the entire app shell so it stays visible through screen
   switches; hidden during print via the @media print block below.

   The :not([hidden]) selector is load-bearing: setting display: flex
   unconditionally on the element would override the browser's
   built-in [hidden] { display: none } rule (CSS property beats HTML
   attribute), and the banner would ALWAYS be visible regardless of
   the hidden attribute. */
.save-failure-banner:not([hidden]) {
  background: var(--save-failure-bg);
  border-bottom: 2px solid var(--save-failure-border);
  color: var(--save-failure-fg);
  padding: 10px 14px;
  font-size: 0.9rem;
  line-height: 1.35;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.save-failure-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.save-failure-banner strong {
  font-size: 1rem;
}
.save-failure-detail {
  opacity: 0.9;
}
.save-failure-dismiss {
  background: transparent;
  color: var(--save-failure-fg);
  border: 1px solid var(--save-failure-border);
  border-radius: 6px;
  width: 32px;
  min-width: 32px;
  height: 32px;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  opacity: 0.9;
}
.save-failure-dismiss:active {
  opacity: 0.6;
}

/* ---- Once-a-season "tidy up your saved rosters" nudge banner ----
   Same above-the-app placement as the save-failure banner, but an
   informational (not alarming) treatment. The :not([hidden]) guard
   is load-bearing for the same reason — see the save-failure note. */
.roster-season-banner:not([hidden]) {
  background: var(--surface-2);
  border-bottom: 2px solid var(--accent);
  color: var(--fg);
  padding: 10px 14px;
  font-size: 0.9rem;
  line-height: 1.35;
  display: flex;
  align-items: center;
  gap: 12px;
}
.roster-season-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.roster-season-banner strong {
  font-size: 1rem;
  color: var(--accent);
}
.roster-season-detail {
  opacity: 0.9;
}
.roster-season-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
.roster-season-actions .btn-secondary {
  min-width: 88px;
}
.roster-season-dismiss {
  background: transparent;
  color: var(--fg);
  border: 1px solid var(--border);
  border-radius: 6px;
  width: 32px;
  min-width: 32px;
  height: 32px;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  opacity: 0.85;
}
.roster-season-dismiss:active {
  opacity: 0.55;
}

/* ---- Print stylesheet ---- */
@media print {
  body {
    background: #ffffff;
    color: #000000;
  }

  /* Hide every screen except the scoresheet, and strip the app-shell
     padding / viewport lock so the printed page sizes naturally. */
  .screen:not(#screen-scoresheet) {
    display: none !important;
  }

  .screen {
    max-width: none;
    max-height: none;
    min-height: 0;
    overflow: visible;
    padding: 0;
    margin: 0;
    display: block;
  }

  .scoresheet-screen {
    overflow: visible;
  }

  .scoresheet-nav,
  .scoresheet-print-hint,
  .scoresheet-share-hint,
  .match-locked-banner,
  .viewing-saved-banner,
  .sheet-ref-sign-btn,
  .save-failure-banner,
  .roster-season-banner {
    display: none !important;
  }

  /* On paper, the signature slots collapse the button column and
     stretch the signature line to fill the freed space. */
  .sheet-ref-slot {
    grid-template-columns: 48px 1fr;
    padding: 2px 4px;
    min-height: 28px;
    border-bottom: 1px solid #000000;
  }

  .sheet-ref-slot:last-child {
    border-bottom: none;
  }

  .sheet-ref-signature {
    min-height: 24px;
    border-bottom: none; /* The slot's own bottom border is the signing line */
  }

  /* Print hint pseudo-element (when signed slot is empty) shouldn't
     show on the paper output. */
  .sheet-ref-signature--empty::after {
    display: none;
  }

  .scoresheet {
    background: #ffffff;
    color: #000000;
    padding: 0;
    border-radius: 0;
    box-shadow: none;
    overflow: visible;
    flex: none;
    /* Clamp to the printable area so Safari doesn't silently shrink-to-fit.
       10.5in buffers slightly under the 10.6in landscape usable width
       (11in page − 2 × 0.2in side margin). */
    width: 10.5in;
    max-width: 10.5in;
    box-sizing: border-box;
    /* Explicit vertical padding inside the scoresheet box. This keeps
       table borders (GP last-row 2px border; roster/goalie 2px outline)
       from rendering exactly at the page-margin edge, which Safari's
       print engine visually clips. Content sits ~10px clear of the
       @page margin on both top and bottom regardless of where natural
       block boundaries land. */
    padding: 4px 0 12px 0;
  }

  /* Preserve the background shading on headers / period totals /
     excluded rows when printing. */
  .sheet-roster th,
  .sheet-goalie th,
  .sheet-mini th,
  .sheet-progress-col th,
  .sheet-mini tbody th,
  .sheet-info-label,
  .sheet-section-title,
  .sheet-roster .sheet-period-total td,
  .sheet-row--excluded {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* ---- Print-only vertical compression ----
     The on-screen scoresheet is ~10in tall when 10.3in wide (square-ish,
     mirrors the paper form's density). Landscape letter usable area is
     10.3in × 7.8in — content overflows vertically by ~1.5in. The rules
     below shrink row heights, gaps, and padding without touching font
     sizes, so printed text stays at its designed readable size. */

  /* Game Progress — biggest single contributor. Row 22 → 13px × 18 rows.
     Font 10px → 9.5px is a small concession that also helps "E – Fouled
     Out" fit without wrapping to 3 lines (which had been inflating that
     row's height regardless of the height cap). */
  /* Body rows compressed tight — this is where the big vertical savings
     come from. 12px cell with 9.5px font × 1.05 line-height = 10px of
     content exactly fits inside the 12 − 2px borders = 10px inner area.
     Header rows are NOT compressed here (they need room for "Identity /
     W D", "Score / W-D" two-row labels). */
  .sheet-progress-col tbody td,
  .sheet-progress-col tbody th {
    height: 12px;
    padding: 0 3px;
    line-height: 1.05;
    font-size: 9.5px;
  }
  /* Game Progress header rows — readable font, full row height. */
  .sheet-progress-col thead th {
    height: 13px;
    padding: 1px 3px;
    font-size: 8px;
    line-height: 1.1;
  }
  /* "Identity" (8 chars) overflows its 20%-wide colspan cell at 8px.
     Drop that one header to 7px with tight letter-spacing so the
     label fits cleanly centered over W / D. */
  .sheet-progress-col thead th.sheet-pc-col-identity {
    font-size: 7px;
    letter-spacing: -0.02em;
  }
  .sheet-progress-col .sheet-pc-divider td {
    height: 12px;
  }
  /* Last body row needs 2px extra height so the thick 2px outer
     border lives inside the cell instead of clipping below it. */
  .sheet-progress-col tbody tr:last-child td {
    height: 15px;
  }

  /* Roster + goalie BODY rows compressed to 12px — comfortable floor
     for 8.5px font × 1.1 line-height. The remaining ~9% fit gap vs.
     Safari's 100% print scale is closed by the manual "Scale: 91%"
     tap in the print dialog (see print flow docs). Tried compressing
     further but it only made text cramped without fixing the clip. */
  .sheet-roster tbody td,
  .sheet-roster tbody th,
  .sheet-goalie tbody td,
  .sheet-goalie tbody th {
    height: 12px;
  }

  /* Roster sub-header row — two-line labels "Ejections / Drawn" and
     (in narrow cells) "Attempts" need more than 14px × 1.1 line-height
     = 15.4px; bump to 18px so neither clips. */
  .sheet-roster .sheet-roster-sub th {
    height: 18px;
    padding: 1px 2px;
  }

  /* Roster sub-column widths now live in the table's <colgroup> —
     the only reliable way to override widths on non-first-row cells
     under table-layout: fixed. */

  /* Goalie column widths now live in each goalie table's <colgroup>
     (same reason as rosters — table-layout: fixed only reads widths
     from the first row or <col> elements). */

  /* Roster + goalie footer (Period Total row) matches body at 12px. */
  .sheet-roster tfoot td {
    height: 12px;
  }

  /* Game # row — the very bottom of the right stack. Tight min-height
     + margin so the row doesn't push the right stack past the
     content-safe area (see @page margin further down). */
  .sheet-game-num {
    min-height: 11px;
    margin-top: 2px;
  }
  .sheet-game-num .sheet-info-label {
    padding: 0 4px;
  }

  /* Mini-table (Timeouts, Game Results) — body rows tight, header row
     keeps its natural height so "White" / "Dark" doesn't get pinched. */
  .sheet-mini tbody td,
  .sheet-mini tbody th {
    height: 12px;
    padding: 1px 3px;
  }

  /* Info rows (Game Information, and referee row labels). */
  .sheet-info-row {
    min-height: 10px;
  }

  /* Referee Signature rows — 32px (~0.33in) is still usable for a
     signature and gives a more comfortable writing line than the
     aggressive 28px we tried. */
  .sheet-referees .sheet-info-row {
    min-height: 32px;
  }

  /* Right-column and middle-column vertical gaps tighter. */
  .sheet-right-stack {
    gap: 2px;
  }
  .sheet-middle-stack {
    gap: 3px;
  }

  /* Section-title strips appear in ~6 blocks — shave a px of padding. */
  .sheet-section-title {
    padding: 1px 4px;
  }

  /* Cap Change Note body — advisory text, safe to compress hard. */
  .sheet-cap-change-note-body {
    padding: 0 5px;
    line-height: 1.0;
    font-size: 6.5px;
  }
  .sheet-cap-change-note {
    margin-top: 2px;
  }
  .sheet-cap-change-key li {
    padding: 0;
  }
  .sheet-cap-change-key {
    margin-bottom: 2px;
  }

  /* Legend box — tighter padding + line-height. */
  .sheet-legend-box {
    padding: 1px 4px;
  }
  .sheet-legend-item {
    line-height: 1.15;
  }
  .sheet-legend-identity {
    margin-top: 2px;
    padding-top: 2px;
  }

  /* Scoresheet-wide block gap and sub-gap tightening — small wins
     add up. */
  .scoresheet {
    gap: 1px;
  }
  .sheet-rosters {
    gap: 4px;
  }
  .sheet-bottom {
    margin-top: 2px;
  }
  .sheet-goalies {
    gap: 4px;
  }

  @page {
    /* Explicit dimensions (not the "letter landscape" keyword) —
       iOS Safari reliably honors W×H but often ignores "landscape".
       (Separate problem: Safari on iPad ignores this entirely on the
       share-sheet Save-to-Files path; user manually taps Landscape in
       the print dialog. This declaration stays correct for other
       browsers and print targets.)
       Asymmetric margin: 0.3in top preserves 3-hole punch clearance
       on the landscape long edge (0.3 is near the minimum for most
       standard 3-hole punches). Bottom 0.35in gives real clearance
       below the content so Safari's print preview doesn't visually
       clip the last row. Sides 0.2in keep horizontal content to
       10.6in usable. */
    size: 11in 8.5in;
    margin: 0.3in 0.2in 0.35in 0.2in;
  }
}

/* ============================================================
   In-Game Cap Change modal — mirrors .entry-modal structure for
   visual consistency (scrim, panel, rounded corners, scroll
   inside the panel). Three mode buttons at the top; per-mode
   fields reveal below. Preview strip near the footer shows the
   resulting narrative and gates the Confirm button.
   ============================================================ */

.cap-change-modal {
  position: fixed;
  inset: 0;
  z-index: 110;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.cap-change-modal[hidden] {
  display: none !important;
}

.cap-change-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.cap-change-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 620px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.cap-change-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
  text-align: center;
  flex: 0 0 auto;   /* Pinned at top while body scrolls */
}

.cap-change-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

.cap-change-body {
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1 1 auto;
  min-height: 0;      /* Required to let overflow-y resolve */
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;  /* iOS momentum-scroll */
}

.cap-change-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.cap-change-field[hidden] {
  display: none !important;
}

.cap-change-label {
  font-size: 0.72rem;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-weight: 700;
}

/* Mode picker — same visual language as the foul-type row. */
.cap-change-mode-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
}

.cap-change-mode-btn {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 10px 14px;
  min-height: 44px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  transition: transform 0.05s ease;
  white-space: nowrap;
}

.cap-change-mode-btn:active {
  transform: scale(0.97);
}

.cap-change-mode-btn--selected {
  background: rgba(56, 189, 248, 0.15); /* soft accent tint */
  border-color: var(--accent);
  color: var(--accent);
}

/* Team toggle — mirror of .entry-team-choices */
.cap-change-team-choices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.cap-change-team-choice {
  font: inherit;
  padding: 10px 12px;
  min-height: 48px;
  background: transparent;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
  color: var(--fg);
}

.cap-change-team-choice .choice-badge {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--fg-muted);
}

.cap-change-team-choice .choice-school {
  font-size: 0.92rem;
  font-weight: 700;
}

.cap-change-team-choice--selected {
  background: rgba(56, 189, 248, 0.12);
  border-color: var(--accent);
}

.cap-change-team-choice--white.cap-change-team-choice--selected {
  background: rgba(255, 255, 255, 0.08);
  border-color: #e5e7eb;
}

.cap-change-team-choice--dark.cap-change-team-choice--selected {
  background: rgba(31, 41, 55, 0.8);
  border-color: #9ca3af;
}

/* Player and cap pickers inside the modal. Reuses the .pp-*
   inner-cell styling from the entry player grid so the visual
   language stays consistent. */
.cap-change-player-grid,
.cap-change-goalie-row {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 8px;
}

.cap-change-cap-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 6px;
}

.cap-change-player-cell {
  font: inherit;
  background: transparent;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  min-height: 64px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.05s ease;
}

.cap-change-player-cell:active {
  transform: scale(0.97);
}

.cap-change-player-cell:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}

.cap-change-player-cell--selected {
  background: rgba(56, 189, 248, 0.18);
  border-color: var(--accent);
}

.cap-change-cap-cell {
  font: inherit;
  font-size: 0.95rem;
  font-weight: 700;
  background: transparent;
  border: 1.5px solid var(--border);
  border-radius: 6px;
  padding: 8px 6px;
  min-height: 44px;
  cursor: pointer;
  color: var(--fg);
  -webkit-tap-highlight-color: transparent;
  font-variant-numeric: tabular-nums;
}

.cap-change-cap-cell:active {
  transform: scale(0.95);
}

.cap-change-cap-cell--in-use {
  opacity: 0.3;
  cursor: not-allowed;
  text-decoration: line-through;
}

.cap-change-cap-cell--selected {
  background: rgba(56, 189, 248, 0.2);
  border-color: var(--accent);
  color: var(--accent);
}

/* Period row — matches .entry-period-choice exactly so the Cap
   Change modal's period selector feels the same as the entry and
   edit modals. Buttons size to content (with a 52px min-width for
   visual stability) and flex-wrap on narrow widths, rather than
   grid-stretching to full container width. */
.cap-change-period-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.cap-change-period-btn {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  padding: 8px 14px;
  min-height: 40px;
  min-width: 52px;
  background: transparent;
  color: var(--fg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  transition: transform 0.05s ease;
}

.cap-change-period-btn:active {
  transform: scale(0.97);
}

.cap-change-period-btn--selected {
  background: rgba(79, 195, 247, 0.15);
  border-color: var(--accent);
  color: var(--accent);
}

.cap-change-clock-input {
  font: inherit;
  font-size: 1rem;
  padding: 10px 12px;
  min-height: 44px;
  background: var(--bg);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  color: var(--fg);
  width: 100%;
  box-sizing: border-box;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
}

.cap-change-clock-input.invalid {
  border-color: var(--danger);
}

.cap-change-empty {
  font-size: 0.85rem;
  color: var(--fg-muted);
  font-style: italic;
  padding: 8px 4px;
}

.cap-change-preview {
  padding: 10px 12px;
  border-radius: 8px;
  font-size: 0.88rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1.5px solid var(--border);
  min-height: 42px;
  display: flex;
  align-items: center;
}

.cap-change-preview--ok {
  background: rgba(34, 197, 94, 0.12);
  border-color: #22c55e;
  color: #bbf7d0;
}

.cap-change-preview--error {
  background: rgba(220, 38, 38, 0.1);
  border-color: var(--danger);
  color: #fca5a5;
  font-style: italic;
}

.cap-change-footer {
  padding: 12px 18px;
  border-top: 1px solid var(--border);
  display: flex;
  gap: 10px;
  justify-content: flex-end;
  flex: 0 0 auto;   /* Pinned at bottom while body scrolls */
}

/* Inner pp-* helpers — reuse tokens from the entry player grid so
   the cells feel like part of the same design system. */
.cap-change-player-cell .pp-cap {
  font-size: 1rem;
  font-weight: 800;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.cap-change-player-cell .pp-role {
  font-size: 0.65rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-muted);
  font-weight: 700;
}

.cap-change-player-cell .pp-name {
  font-size: 0.85rem;
  color: var(--fg);
}

.cap-change-player-cell .pp-name--empty {
  color: var(--fg-muted);
  font-style: italic;
}

/* Cap-change rows in the Game Progress log — subtly distinct so
   the reader can scan past them, since they're metadata about the
   match rather than scoring/foul activity. */
.event-log-item--cap-change {
  opacity: 0.88;
}

.event-type--cap-change {
  font-style: italic;
  letter-spacing: 0.02em;
}

/* ============================================================
   Referee signature blocks on the scoresheet.

   Each slot stacks a label, a signature line (which fills with
   an <img> of the captured signature when present), and a
   Sign / Re-sign button. Buttons hide on print so the paper
   output only shows label + signature. When empty, the signature
   line renders a thin underline as a visual placeholder.
   ============================================================ */

.sheet-ref-slot {
  display: grid;
  grid-template-columns: 60px 1fr auto;
  align-items: center;
  gap: 6px;
  padding: 4px 6px;
  min-height: 44px;
  border-bottom: 1px solid var(--border);
}

.sheet-ref-slot:last-child {
  border-bottom: none;
}

.sheet-ref-slot .sheet-info-label {
  font-size: 0.7rem;
}

/* Signature line — empty by default (thin underline placeholder),
   grows an <img> when signed. The img stretches to the slot width
   so variable-width signatures fit predictably. */
.sheet-ref-signature {
  position: relative;
  min-height: 70px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}

.sheet-ref-signature img {
  display: block;
  max-width: 100%;
  max-height: 70px;
  object-fit: contain;
  /* User feedback 2026-04-29: signatures were nearly impossible to
     see on screen at the prior 36px max-height — strokes downsampled
     into invisibility. Doubling to 70px + bumping canvas line width
     to 6px restores legibility. The PNG carries a white background
     (filled in resizeSignatureCanvas) so the stroke contrast holds
     up regardless of the dark surface behind the slot. */
}

.sheet-ref-signature--empty::after {
  /* Tiny italic hint when the slot is awaiting a signature. Sized
     small enough that the longer pre-End-Match instruction
     ("Tap End Match to enable signing") fits on a single line in
     the narrow right-stack column without wrapping. */
  content: attr(data-hint);
  position: absolute;
  bottom: 4px;
  font-style: italic;
  font-size: 0.6rem;
  color: var(--fg-muted);
  pointer-events: none;
  white-space: nowrap;
}

.sheet-ref-sign-btn {
  font-size: 0.8rem;
  padding: 4px 10px;
  min-height: 32px;
  white-space: nowrap;
}

/* ============================================================
   Match-locked banner on the scoresheet screen.

   Appears above the print-hint card when both referee signatures
   are captured AND the match is Final. Hidden on print. Uses the
   accent color for high contrast since a locked match is a state
   the scorekeeper needs to notice immediately.
   ============================================================ */

.match-locked-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  margin: 0 0 12px 0;
  background: var(--accent);
  color: var(--bg);
  border-radius: 8px;
  font-size: 0.95rem;
  line-height: 1.35;
}

.match-locked-banner[hidden] {
  display: none !important;
}

.match-locked-banner-icon {
  font-size: 1.3rem;
  flex: 0 0 auto;
}

.match-locked-banner-body {
  flex: 1 1 auto;
}

/* Viewing-saved-game banner. Different palette from match-locked
   (cyan-accent outline on a subtle surface tint, not solid accent
   fill) so the two banners read as distinct states — one means
   "the live game is locked," the other means "this is a snapshot." */
.viewing-saved-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  margin: 0 0 12px 0;
  background: var(--surface-2);
  color: var(--fg);
  border: 2px solid var(--accent);
  border-radius: 8px;
  font-size: 0.95rem;
  line-height: 1.35;
}

.viewing-saved-banner[hidden] {
  display: none !important;
}

.viewing-saved-banner-icon {
  font-size: 1.3rem;
  flex: 0 0 auto;
}

.viewing-saved-banner-body {
  flex: 1 1 auto;
}

/* When locked, disabled buttons inherit a clear "can't press me" look.
   Scoped via the body class (see app.js matchLocked handling) so the
   disabled state trickles across all screens, not just the scoresheet. */
body.match-locked .sheet-ref-sign-btn[data-action="sign"] {
  display: none;
}

/* ============================================================
   Full-screen signature modal.

   Covers the entire viewport so the drawing surface is as large
   as possible. Canvas fills the panel body; Accept / Clear sit
   in a sticky footer. Drawing is pointer-based so finger and
   stylus input on iPad both work (pointer events unify mouse +
   touch + pen).
   ============================================================ */

.signature-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: stretch;
  justify-content: stretch;
}

.signature-modal[hidden] {
  display: none !important;
}

.signature-modal-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
}

.signature-modal-panel {
  /* Fill the .signature-modal parent (position: fixed; inset: 0) rather
     than 100vh/100vw. iPad Safari's 100vh includes the space behind
     the dynamic URL bar, which was pushing the Accept button off the
     visible viewport and making it look like no submit existed. */
  position: absolute;
  inset: 0;
  background: var(--surface);
  display: flex;
  flex-direction: column;
}

.signature-modal-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
}

.signature-modal-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
}

.signature-modal-close {
  background: transparent;
  border: none;
  color: var(--fg);
  font-size: 1.8rem;
  line-height: 1;
  padding: 4px 10px;
  cursor: pointer;
  border-radius: 6px;
}

.signature-modal-close:hover,
.signature-modal-close:focus-visible {
  background: rgba(255, 255, 255, 0.08);
  outline: none;
}

.signature-canvas-wrap {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  padding: 12px;
  min-height: 0;
}

.signature-canvas {
  flex: 1 1 auto;
  width: 100%;
  background: #ffffff;
  border: 2px solid var(--border);
  border-radius: 10px;
  /* Prevent touch-scroll / page-zoom gestures from interfering
     with signature drawing on iPad Safari. */
  touch-action: none;
  cursor: crosshair;
  min-height: 0;
}

.signature-hint {
  flex: 0 0 auto;
  margin: 8px 0 0 0;
  text-align: center;
  font-size: 0.85rem;
  color: var(--fg-muted);
}

.signature-modal-footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding: 12px 16px;
  border-top: 1px solid var(--border);
}

/* ============================================================
   Match-locked disabled state for entry / edit / cap-change /
   undo / redo buttons across all screens. The body.match-locked
   class is toggled centrally (see renderScoreboard in app.js) so
   visually disabled state and pointer-events:none match.
   ============================================================ */
body.match-locked .btn-action,
body.match-locked .btn-add-custom,
body.match-locked .btn-cap-change,
body.match-locked #btn-end-match,
body.match-locked #btn-undo-last,
body.match-locked #btn-redo-last,
body.match-locked #btn-next-period,
body.match-locked #btn-switch-sides,
body.match-locked .saves-btn,
body.match-locked .shot-btn,
body.match-locked .steal-btn,
body.match-locked .tol-btn,
body.match-locked .event-log-item {
  opacity: 0.45;
  pointer-events: none;
}

body.match-locked .event-log-item {
  cursor: default;
}

/* ============================================================
   Stats panel — tabbed view (Players / Fouls / Goals / Timeouts)
   ============================================================ */

/* Tabs row across the top of the panel — only one category renders
   at a time so the panel reads as a single focused list. The active
   tab gets an underline-style accent + bold weight. */
.stats-tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  padding: 0 0 0 4px;
  margin: 0 0 8px;
  /* On narrow viewports the 9 tabs overflow horizontally — let the
     tab row itself scroll left-right instead of pushing the whole
     page wide. -webkit-overflow-scrolling for iOS momentum.
     scrollbar hidden via the WebKit pseudo so the row reads as a
     clean strip. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  white-space: nowrap;
}

.stats-tabs::-webkit-scrollbar {
  display: none;
}

.stats-tab {
  background: transparent;
  border: none;
  border-bottom: 3px solid transparent;
  color: var(--fg-muted);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 10px 14px;
  margin-bottom: -1px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  min-height: 44px;
  transition: color 0.1s ease;
  /* Don't let individual tabs shrink under the horizontal-scroll
     constraint — they should keep their natural width and let the
     row scroll. */
  flex: 0 0 auto;
}

.stats-tab:hover,
.stats-tab:focus-visible {
  color: var(--fg);
  outline: none;
}

.stats-tab--active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* Two-line stacked tab label (e.g. "Ejections" over "Drawn") so the
   tab row stays compact while keeping each word readable. Used on
   the Ejections Drawn tab; line-height tightened so the two lines
   fit within the same min-height as a single-line tab. */
.stats-tab-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  line-height: 1.05;
  gap: 1px;
}

.stats-tabpanel[hidden] {
  display: none !important;
}

.stats-tabpanel {
  margin-top: 6px;
}

.stats-section-title {
  margin: 0 0 6px;
  font-size: 0.75rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 700;
}

.stats-empty {
  color: var(--fg-muted);
  font-style: italic;
  font-size: 0.85rem;
  padding: 4px 2px;
}

/* ---- Players chip grid ---- */

.stats-players-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px;
}

.stats-player-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  min-height: 40px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  font: inherit;
  color: var(--fg);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  text-align: left;
  transition: transform 0.04s ease, background 0.1s ease;
}

.stats-player-chip:active {
  transform: scale(0.97);
  background: rgba(56, 189, 248, 0.08);
}

.stats-player-chip-cap {
  font-size: 1rem;
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
  flex: 0 0 auto;
}

.stats-player-chip-name {
  font-size: 0.85rem;
  font-weight: 600;
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.stats-player-chip-name--empty {
  font-style: italic;
  color: var(--fg-muted);
}

.stats-player-chip--goalie {
  border-color: rgba(56, 189, 248, 0.5);
}

.stats-player-chip--excluded {
  background: rgba(220, 38, 38, 0.18);
  border-color: var(--danger);
  color: #fecaca;
}

.stats-player-chip-out {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--danger);
  color: #ffffff;
  flex: 0 0 auto;
}

/* ---- Goals list ---- */

.stats-goals-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.stats-goals-row {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.stats-goals-row:active {
  background: rgba(56, 189, 248, 0.08);
}

.stats-goals-cap {
  font-weight: 800;
  font-size: 0.95rem;
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}

.stats-goals-name {
  font-weight: 600;
  font-size: 0.85rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.stats-goals-name--empty {
  color: var(--fg-muted);
  font-style: italic;
}

.stats-goals-count {
  font-size: 1.1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  color: var(--fg);
}

.stats-goals-row--excluded {
  background: rgba(220, 38, 38, 0.12);
  border-color: rgba(220, 38, 38, 0.5);
}

.stats-goals-out {
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--danger);
  color: #ffffff;
}

/* ---- Timeouts box ---- */

.stats-timeouts {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.stats-timeouts-called {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.85rem;
}

.stats-timeouts-called li {
  font-variant-numeric: tabular-nums;
}

.stats-timeouts-remaining {
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--fg-muted);
  border-top: 1px solid var(--border);
  padding-top: 4px;
}

/* ============================================================
   Player Detail modal
   ============================================================ */

.player-detail-modal {
  position: fixed;
  inset: 0;
  z-index: 130;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.player-detail-modal[hidden] {
  display: none !important;
}

.player-detail-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.65);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

.player-detail-card {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.6);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.player-detail-header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}

.player-detail-header h2 {
  margin: 0;
  font-size: 1rem;
  color: var(--accent);
  letter-spacing: 0.06em;
  font-weight: 700;
  text-transform: uppercase;
}

.player-detail-close {
  background: transparent;
  border: none;
  color: var(--fg);
  font-size: 1.6rem;
  line-height: 1;
  padding: 4px 10px;
  cursor: pointer;
  border-radius: 6px;
}

.player-detail-close:hover,
.player-detail-close:focus-visible {
  background: rgba(255, 255, 255, 0.08);
  outline: none;
}

.player-detail-banner {
  flex: 0 0 auto;
  padding: 8px 18px;
  background: var(--danger);
  color: #ffffff;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-align: center;
  font-size: 0.85rem;
}

.player-detail-banner[hidden] {
  display: none !important;
}

.player-detail-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.player-detail-role {
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-muted);
}

.player-detail-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.player-detail-section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  border-bottom: 1px solid var(--border);
  padding-bottom: 4px;
}

.player-detail-section-label {
  /* Match the count number's font-size + weight so the label and
     total read as a balanced pair across the row instead of the
     tiny-label-next-to-giant-number imbalance the smoke-test
     surfaced. Drop the uppercase + letter-spacing transformation
     since the larger size doesn't need them to feel like a heading. */
  font-size: 1.6rem;
  letter-spacing: 0;
  text-transform: none;
  color: var(--accent);
  font-weight: 700;
  line-height: 1;
}

.player-detail-section-count {
  font-size: 1.6rem;
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.player-detail-section-empty {
  font-style: italic;
  color: var(--fg-muted);
  font-size: 0.85rem;
  padding: 2px 4px;
}

.player-detail-section-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.85rem;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

.player-detail-cards {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  padding: 8px 0;
}

.player-detail-card-count {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.player-detail-card-count-label {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-muted);
}

.player-detail-card-count-num {
  font-size: 1rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.player-detail-footer {
  flex: 0 0 auto;
  padding: 10px 18px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
}

/* =================================================================
   Admin entry button + Admin modal + PIN modals — Feature #15.
   Deliberately understated: the entry is a single small button at
   the bottom of Setup; the PIN copy and controls live inside the
   Admin modal so the home page isn't cluttered. All modals reuse
   the standard scrim + panel pattern from the rest of the app.
   ================================================================= */

.setup-admin-trigger {
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: center;
}

/* Admin modal — wraps the PIN row + caveat behind the Admin button. */

.admin-modal[hidden] { display: none; }

.admin-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.admin-modal-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
}

.admin-modal-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  max-width: 420px;
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.admin-modal-header {
  padding: 16px 18px 8px;
  border-bottom: 1px solid var(--border);
}

.admin-modal-header h2 {
  margin: 0;
  font-size: 1.1rem;
}

.admin-modal-body {
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.admin-section-heading {
  margin: 0;
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--fg-muted);
}

.admin-modal-footer {
  padding: 12px 18px 16px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  border-top: 1px solid var(--border);
}

.setup-admin-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.setup-admin-row .admin-pin-status {
  font-size: 0.9rem;
  color: var(--fg-muted);
}

.setup-admin-caveat {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--fg-muted);
}

/* PIN modals — shared shape between Set and Verify. */

.admin-pin-modal[hidden] { display: none; }

.admin-pin-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.admin-pin-scrim {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
}

.admin-pin-panel {
  position: relative;
  background: var(--surface);
  border: 2px solid var(--border);
  border-radius: 14px;
  max-width: 380px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0;
  overflow: hidden;
}

.admin-pin-header {
  padding: 16px 18px 8px;
}

.admin-pin-header h2 {
  margin: 0 0 4px;
  font-size: 1.1rem;
}

.admin-pin-sub {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--fg-muted);
}

.admin-pin-body {
  padding: 8px 18px 4px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.admin-pin-body input[type="password"] {
  font-size: 1.4rem;
  letter-spacing: 0.4em;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.admin-pin-error {
  margin: 0;
  font-size: 0.85rem;
  color: #c0392b;
  font-weight: 600;
}

.admin-pin-footer {
  padding: 12px 18px 16px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  border-top: 1px solid var(--border);
  margin-top: 8px;
}

