:root {
  --bg: #03060d;
  --bg2: #0b1220;
  --card: #0b101f;
  --card-2: #0f1828;
  --line: #1b2741;
  --line-2: #2a385c;
  --text: #eaf0ff;
  --muted: #a9b3c7;
  --accent: #3ba9ff;
  --accent-2: #89d0ff;
  --good: #30d158;
  --bad: #ff5f57;
  --gold: #ffd166;
  /* Clip-range accent. Distinct from --gold (which is owned by goal markers
     / highlighted scorer) and from --accent-2 (the scrub-bar blue) so the
     band and clip buttons don't fight other meaningful UI cues. */
  --clip: #b18cff;
  --team-blue: #89d0ff;
  --team-red:  #ff8aa3;
  --radius: 16px;

  /* ---- Brand / page-chrome theming surface ----
     These are the stable "props" API league deployments are expected to
     override to retheme the page. Names are preserved across versions;
     values can be anything a CSS gradient / color accepts. Consumed by
     shell.css (header, brand h1) and the body background below. */
  --brand-grad-from:  #fff;
  --brand-grad-to:    #cfe1ff;
  --header-bg-top:    rgba(10,16,30,.95);
  --header-bg-bot:    rgba(10,16,30,.80);
  --page-bg-radial-hi: #14223c;
  --page-bg-conic-lo:  #0c1830;
  --page-bg-conic-hi:  #0b1220;
}

/* ---- Light-mode overrides ----
   Mirrors poncepuck.net's flag system so embedded deployments don't have
   to teach us their conventions:
     <html data-theme="light">    → always light
     <html data-theme="dark">     → always dark (the :root defaults above)
     <html data-theme="default">  → follow OS via prefers-color-scheme
   The :root block above is the unconditional dark palette; the rules below
   only override variables when the active theme resolves to light. JS in
   js/theme.js observes data-theme changes at runtime and re-paints the
   rink canvas to match. */
:root[data-theme="light"] {
  --bg:                #f5f8ff;
  --bg2:               #eaf0fa;
  --card:              #ffffff;
  --card-2:            #f5f8ff;
  --line:              rgba(27,36,68,.18);
  --line-2:            rgba(27,36,68,.12);
  --text:              #0b1530;
  --muted:             #475063;
  --accent:            #2a8edb;
  --accent-2:          #1a6fb5;
  --good:              #2da14d;
  --bad:               #d83a3a;
  --gold:              #b8860b;
  --clip:              #7a5cd9;
  --team-blue:         #1f4f82;
  --team-red:          #7a2e3f;
  --brand-grad-from:   #0b1530;
  --brand-grad-to:     #2a8edb;
  --header-bg-top:     rgba(255,255,255,.95);
  --header-bg-bot:     rgba(245,248,255,.85);
  --page-bg-radial-hi: #d8e6f8;
  --page-bg-conic-lo:  #e8eef9;
  --page-bg-conic-hi:  #f0f5fc;
}
@media (prefers-color-scheme: light) {
  :root[data-theme="default"] {
    --bg:                #f5f8ff;
    --bg2:               #eaf0fa;
    --card:              #ffffff;
    --card-2:            #f5f8ff;
    --line:              rgba(27,36,68,.18);
    --line-2:            rgba(27,36,68,.12);
    --text:              #0b1530;
    --muted:             #475063;
    --accent:            #2a8edb;
    --accent-2:          #1a6fb5;
    --good:              #2da14d;
    --bad:               #d83a3a;
    --gold:              #b8860b;
    --clip:              #7a5cd9;
    --team-blue:         #1f4f82;
    --team-red:          #7a2e3f;
    --brand-grad-from:   #0b1530;
    --brand-grad-to:     #2a8edb;
    --header-bg-top:     rgba(255,255,255,.95);
    --header-bg-bot:     rgba(245,248,255,.85);
    --page-bg-radial-hi: #d8e6f8;
    --page-bg-conic-lo:  #e8eef9;
    --page-bg-conic-hi:  #f0f5fc;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; scroll-padding-top: 72px; }
body {
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  color: var(--text);
  background:
    radial-gradient(1200px 800px at 10% 10%, var(--page-bg-radial-hi), transparent 60%) fixed,
    conic-gradient(from 230deg at 70% 20%, var(--page-bg-conic-lo), var(--page-bg-conic-hi) 25%, var(--page-bg-conic-hi) 75%, var(--page-bg-conic-lo)) fixed,
    var(--bg);
  min-height: 100vh;
}
a { color: inherit; text-decoration: none; }
a:hover { color: var(--accent-2); }

.wrap { max-width: 1600px; margin: 0 auto; padding: 8px; }
main.wrap { padding-top: 16px; display: flex; flex-direction: column; gap: 16px; }

/* Header, brand, nav, and optional mod/live links have moved to shell.css
   so the app fragment can mount inside a league-provided page chrome
   without carrying the generic top bar. */

/* App toolbar row: holds the replay picker, local-file input, and the
   currently-loaded status pill. Lives inside <main> rather than the shell
   header so the app fragment is self-contained when embedded in a league
   page that strips the generic header. Flex-wraps on narrow viewports. */
.app-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}
.app-toolbar[hidden] { display: none; }

/* Generic flex-spacer. Used in toolbars and (formerly) in the shell header
   to push trailing items to the right edge. Lives in app.css so toolbars
   inside the app fragment can rely on it without pulling in shell.css. */
.navspacer { flex: 1; }

.btn, .btn-primary {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: 12px; font-weight: 600;
  border: 1px solid rgba(255,227,143,.28);
  background: rgba(5,10,22,.9); color: var(--text);
  transition: transform .12s ease, border-color .15s ease, box-shadow .15s ease, background .12s ease;
  cursor: pointer; font-size: 14px;
}
.btn:hover:not(:disabled) { transform: translateY(-1px); border-color: rgba(255,227,143,.75); background: rgba(14,20,36,.95); }
.btn-primary {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: #0b1220; border-color: transparent;
  box-shadow: 0 10px 28px rgba(59,169,255,.35);
}
.btn-primary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 14px 34px rgba(59,169,255,.45); color: #0b1220; }
.btn:disabled { opacity: .4; cursor: not-allowed; }

.muted { color: var(--muted); font-size: 12px; }

/* ---------- file input label ---------- */
.file-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 12px; border-radius: 10px; font-weight: 600;
  background: rgba(59,169,255,.12); color: var(--accent-2);
  border: 1px solid rgba(59,169,255,.3); cursor: pointer;
  font-size: 13px; user-select: none;
  transition: background .12s ease, border-color .12s ease;
}
.file-btn:hover { background: rgba(59,169,255,.2); border-color: rgba(59,169,255,.5); }
.file-btn[hidden] { display: none; }

/* ---------- replay selector dropdown ---------- */
.replay-select {
  background: #0f1428; color: var(--text);
  border: 1px solid var(--line-2); border-radius: 10px;
  padding: 8px 10px; font: inherit; font-size: 13px;
  min-width: 360px; max-width: 560px;
}
.replay-select:focus { outline: none; border-color: var(--accent-2); }

/* ---------- cards ---------- */
.card {
  background: color-mix(in oklab, var(--card) 92%, #0e1830);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 20px; box-shadow: 0 22px 50px rgba(0,0,0,.35), inset 0 1px 0 rgba(255,255,255,.04);
}
.card h3 {
  margin: 0 0 14px; font-size: 22px;
  display: flex; align-items: baseline; gap: 10px;
}
.card h3 .sub { color: var(--muted); font-size: 13px; font-weight: 400; }

/* ---------- stage (rink) ---------- */
#stage { position: relative; border-radius: 12px; overflow: hidden; border: 1px solid var(--line); background: #0b1220; }
#rink { display: block; width: 100%; height: auto; background: #eef3f9; }
#stage.dark #rink { background: #0e1a2f; }

/* Annotation canvas sits on top of the rink at the same pixel size. Default
   to pointer-events:none so it doesn't steal hover/click from the players;
   the draw-mode toggle adds .drawing to enable capture. */
#annot {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  pointer-events: none;
  touch-action: none;
}
#stage.drawing #annot { pointer-events: auto; cursor: crosshair; }
#stage.drawing #rink  { cursor: crosshair; }

/* During clip export the renderer composites chat, ref, and annotation
   overlays onto the rink canvas (so captureStream grabs them). Hide the
   live DOM/canvas copies while recording so the viewer doesn't see them
   doubled up on top of the canvas-drawn versions. */
#stage.exporting #annot,
#stage.exporting #chatOverlay,
#stage.exporting #refOverlay { display: none; }

/* Floating icon button. Nests inside a stage-toolbar; sized to match the
   toolbar's other pill-shaped controls so they align on one row. */
.stage-icon-btn {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted);
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer; user-select: none;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.stage-icon-btn:hover { color: var(--text); background: rgba(255,255,255,.05); }

/* Floating toolbar pinned to a top corner of the rink stage. The
   -left variant holds the draw/markup tools; the -right variant holds
   the heatmap tools and the save-screenshot icon. */
.stage-toolbar {
  position: absolute;
  top: 10px;
  display: flex; align-items: center; gap: 8px;
  background: rgba(5,10,22,.8);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  padding: 4px 8px;
  z-index: 4;
  backdrop-filter: blur(4px);
}
.stage-toolbar-left  { left: 10px; }
.stage-toolbar-right { right: 10px; }

/* Fullscreen button: single floating icon pinned to the bottom-right of
   the rink stage. Shares .stage-icon-btn sizing and hover behavior; adds
   the same pill background the toolbars use so it reads as a control
   rather than a stray icon. */
.stage-fullscreen-btn {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 4;
  background: rgba(5,10,22,.8);
  border: 1px solid var(--line-2);
  backdrop-filter: blur(4px);
}

/* Rotate-to-landscape fullscreen (phone). Sits just left of the regular
   fullscreen button and is hidden by default — only phone-width or
   coarse-pointer viewers need it. On click it requests fullscreen and
   tries Screen Orientation Lock to landscape (Android Chrome/Edge);
   iOS silently declines the lock and the user rotates the phone
   physically, which iOS auto-reflows within fullscreen. */
.stage-rotate-fullscreen-btn {
  position: absolute;
  right: 44px;
  bottom: 10px;
  z-index: 4;
  background: rgba(5,10,22,.8);
  border: 1px solid var(--line-2);
  backdrop-filter: blur(4px);
  display: none;
}
@media (hover: none) and (pointer: coarse) {
  .stage-rotate-fullscreen-btn { display: flex; }
}
@media (max-width: 820px) {
  .stage-rotate-fullscreen-btn { display: flex; right: 40px; bottom: 6px; }
}

/* Fullscreen presentation: the whole viewer card (stage + playbar +
   view controls) goes fullscreen so the user keeps transport / toggles
   / clip controls. The card is a flex column: stage flex-grows, and
   #controls + #viewControls take their natural height below it. The
   rink + annot canvases are CSS-sized by JS in transport.js to match
   the stage's flex-allocated box while preserving the 1000:620 aspect.
   HUD/overlay elements remain pinned to the stage's corners. */
#viewerCard:fullscreen {
  background: var(--card);
  border-radius: 0;
  border: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
#viewerCard:fullscreen #stage {
  flex: 1 1 auto;
  min-height: 0;
  /* stage bg shows through the canvas's transparent non-rink pixels,
     so DOM overlays (HUD, chat, ref, pp) and canvas-painted ref PNGs
     all share the same background color. */
  background: var(--card);
  border-radius: 0;
  border: none;
  position: relative;
}
/* Canvas fills the stage entirely; the renderer aspect-fits the rink
   inside via baseScale = min(scaleX, scaleY). This keeps overlay
   anchors (right/bottom of stage) aligned with the corresponding edges
   of the canvas bitmap so the ref text bubble stays above the ref PNG
   and the chat/HUD sit at the true corners of the drawing surface. */
#viewerCard:fullscreen #rink,
#viewerCard:fullscreen #annot {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  max-width: none;
  max-height: none;
}
#viewerCard:fullscreen #rink {
  background: transparent;  /* let stage bg show through non-rink area */
}
#viewerCard:fullscreen #controls,
#viewerCard:fullscreen #viewControls {
  margin: 0;
  padding: 8px 16px;
  background: var(--bg-2, #0b1220);
  border-top: 1px solid var(--line);
}
.stage-toolbar .btn { padding: 4px 10px; font-size: 12px; min-width: 0; }

#drawToggle,
#heatmapToggle {
  display: flex; align-items: center; justify-content: center;
  padding: 4px 10px;
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  cursor: pointer;
  border-radius: 6px;
  border: 1px solid var(--line-2);
  user-select: none;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
#drawToggle:hover,
#heatmapToggle:hover { color: var(--text); background: rgba(255,255,255,.05); }
#drawToggle:has(input:checked),
#heatmapToggle:has(input:checked) {
  color: var(--gold);
  background: rgba(255,209,102,.14);
  border-color: rgba(255,209,102,.5);
}

.draw-tools { display: flex; align-items: center; gap: 8px; }
/* Vertical divider between tools and the toggle on the right. */
.draw-tools::after,
.stage-toolbar .mode-picker::after {
  content: ""; width: 1px; height: 20px;
  background: var(--line-2); margin: 0 2px;
}

.swatches { display: flex; gap: 4px; }
.swatch {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid transparent; cursor: pointer; padding: 0;
  transition: transform .12s ease, border-color .12s ease, filter .12s ease;
}
.swatch:hover { transform: scale(1.1); }
.swatch.active { border-color: var(--text); box-shadow: 0 0 0 2px rgba(0,0,0,0.4); }

.tool-picker { display: flex; gap: 2px; }
.tool-picker .tool {
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  background: transparent; color: var(--muted);
  border: 1px solid transparent; border-radius: 6px;
  cursor: pointer; padding: 0;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.tool-picker .tool:hover { color: var(--text); background: rgba(255,255,255,.05); }
.tool-picker .tool.active {
  color: var(--accent-2);
  background: rgba(59,169,255,.14);
  border-color: rgba(59,169,255,.35);
}

/* ---------- heatmap mode picker ---------- */
.mode-picker { display: inline-flex; gap: 2px; align-items: center; }
.mode-picker .mode {
  display: flex; align-items: center; justify-content: center;
  height: 26px; padding: 0 10px;
  background: transparent; color: var(--muted);
  border: 1px solid transparent; border-radius: 6px;
  font: 600 11px Inter, -apple-system, Segoe UI, sans-serif;
  letter-spacing: .04em;
  cursor: pointer;
  transition: color .12s ease, background .12s ease, border-color .12s ease;
}
.mode-picker .mode:hover { color: var(--text); background: rgba(255,255,255,.05); }
.mode-picker .mode.active {
  color: var(--gold);
  background: rgba(255,209,102,.14);
  border-color: rgba(255,209,102,.45);
}

/* Dim state for stage-toolbar controls.
 *
 * We avoid `opacity` here: the parent `.stage-toolbar` uses
 * `backdrop-filter: blur(4px)`, which in several browsers causes child
 * `opacity` to composite inconsistently against the blurred backdrop -
 * sometimes looking no dimmer than the normal state. Using explicit
 * low-alpha rgba on color/border/background gives the same visual effect
 * but renders reliably because no new stacking context is involved.
 *
 * Two distinct dim triggers:
 *   .inactive   - the whole tool cluster is off (heatmap disabled, or
 *                 draw mode off). All children dim uniformly.
 *   .is-off / :disabled on a .btn - that single button is unavailable
 *                 (Undo/Clear with no strokes yet). */
.mode-picker.inactive,
.draw-tools.inactive {
  pointer-events: none;
}
.mode-picker.inactive .mode,
.mode-picker.inactive .mode.active,
.mode-picker.inactive .mode:hover,
.draw-tools.inactive .tool,
.draw-tools.inactive .tool.active,
.draw-tools.inactive .tool:hover,
.draw-tools.inactive .btn,
.draw-tools.inactive .btn:hover {
  color: rgba(169, 179, 199, .32) !important;
  background: transparent !important;
  border-color: rgba(255, 255, 255, .05) !important;
  box-shadow: none !important;
}
/* Swatches have inline background colors set from JS, so dim them via
   desaturation instead of background overrides. */
.draw-tools.inactive .swatch,
.draw-tools.inactive .swatch:hover,
.draw-tools.inactive .swatch.active {
  filter: grayscale(1) brightness(.45);
  border-color: transparent !important;
  box-shadow: none !important;
  transform: none !important;
}

.stage-toolbar .btn:disabled,
.stage-toolbar .btn.is-off {
  color: rgba(169, 179, 199, .32) !important;
  border-color: rgba(255, 255, 255, .05) !important;
  background: transparent !important;
  box-shadow: none !important;
  cursor: not-allowed !important;
  pointer-events: none;
}
.stage-toolbar .btn:disabled:hover,
.stage-toolbar .btn.is-off:hover {
  transform: none !important;
  color: rgba(169, 179, 199, .32) !important;
  background: transparent !important;
  border-color: rgba(255, 255, 255, .05) !important;
}

/* ---------- chat overlay on the rink ---------- */
#chatOverlay {
  position: absolute;
  bottom: 10px; left: 10px; right: 10px;
  display: flex; flex-direction: column;
  justify-content: flex-end;
  gap: 4px;
  pointer-events: none;
  z-index: 3;
  max-height: 140px;
  overflow: hidden;
}

/* ---------- ref signal overlay (right side, above canvas ref images) ----- */
/* Canvas bitmap is 1000x600; drawRefSignals() paints PNGs in the bottom 32%
   of that bitmap. This overlay sits just above them at the same fractional
   offset so the messages float directly on top of the linesman images. */
#refOverlay {
  position: absolute;
  bottom: 34%; right: 10px;
  display: flex; flex-direction: column;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 4px;
  pointer-events: none;
  z-index: 3;
  max-height: 140px;
  overflow: hidden;
}
#refOverlay .chat-bubble { text-align: right; }
.chat-bubble {
  background: rgba(3,6,13,0.82);
  color: var(--text);
  padding: 5px 10px;
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.3;
  border: 1px solid var(--line-2);
  max-width: 520px;
  width: fit-content;
  word-wrap: break-word;
  transition: opacity .4s ease;
  backdrop-filter: blur(4px);
}
.chat-bubble.fading { opacity: 0.2; }
.chat-bubble.clickable { pointer-events: auto; cursor: pointer; }
.chat-bubble.clickable:hover { background: rgba(15,22,42,0.92); border-color: rgba(120,140,180,.5); }
.chat-name { font-weight: 600; }
.chat-name.clickable-name { cursor: pointer; }
.chat-name.clickable-name:hover { text-decoration: underline; }
.chat-bubble.highlighted {
  border-color: var(--gold);
  box-shadow: 0 0 8px rgba(255,209,102,0.45);
  background: rgba(40,28,6,0.88);
}

/* ---------- momentum chart card ---------- */
#chartWrap {
  position: relative;
  width: 100%;
  border-radius: 8px;
  background: rgba(10, 18, 34, 0.55);
  border: 1px solid var(--line);
  overflow: hidden;
}
#chartCanvas, #chartPlayhead {
  display: block;
  width: 100%;
}
#chartPlayhead {
  position: absolute;
  inset: 0;
  cursor: pointer;
}

/* ---------- chat transcript card ---------- */
#chatCard #chatList {
  max-height: 360px;
  overflow-y: auto;
  font-size: 13px;
  padding: 4px 0;
}
.chat-entry {
  display: flex;
  gap: 10px;
  padding: 4px 8px;
  cursor: pointer;
  border-radius: 4px;
  align-items: baseline;
}
.chat-entry:hover { background: rgba(59,169,255,.07); }
.chat-entry.highlighted {
  background: rgba(255,209,102,.12);
  box-shadow: inset 2px 0 0 var(--gold);
}
.chat-entry.highlighted .msg { color: var(--gold); }
.chat-entry.highlighted:hover { background: rgba(255,209,102,.18); }
.chat-entry .ts {
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  flex-shrink: 0;
  min-width: 46px;
  text-align: right;
}
.chat-entry .msg {
  color: var(--text);
  word-wrap: break-word;
  flex: 1;
}

#hud {
  position: absolute; top: 10px; left: 50%; transform: translateX(-50%);
  pointer-events: none;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
}

#possessionPill[hidden] { display: none; }
#possessionPill {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(5,10,22,.85);
  border: 1px solid var(--line-2);
  border-radius: 8px;
  padding: 3px 10px;
  font-size: 11px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  backdrop-filter: blur(4px);
  color: var(--muted);
  letter-spacing: .06em;
  pointer-events: auto;
}
#possessionPill .possession-label {
  font-size: 9px; letter-spacing: 1px; opacity: .7;
}
#possession { color: var(--text); font-weight: 700; letter-spacing: .02em; text-transform: none; }
#possession[data-team="2"] { color: var(--team-blue); }
#possession[data-team="3"] { color: var(--team-red);  }

/* Cinematic banner shown while the viewer is replaying the seconds leading
   to a goal in the dead window between BlueScore/RedScore and the next
   faceoff. Sits below the scoreboard so it doesn't fight the clock. */
#cinematicBanner {
  position: absolute;
  top: 68px; left: 50%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 10px;
  padding: 6px 16px;
  background: rgba(5, 10, 22, .92);
  border: 1px solid var(--line-2);
  border-radius: 10px;
  font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 800; letter-spacing: .12em;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
  pointer-events: none;
  z-index: 5;
  animation: cinematic-in .25s ease-out;
}
#cinematicBanner[hidden] { display: none; }
#cinematicBanner .cinematic-tag {
  font-size: 10px; color: var(--muted); letter-spacing: .16em;
}
#cinematicBanner[data-team="blue"] {
  border-color: rgba(137,208,255,.55);
  box-shadow: 0 0 18px rgba(137,208,255,.35);
  color: var(--team-blue);
}
#cinematicBanner[data-team="red"] {
  border-color: rgba(255,138,163,.55);
  box-shadow: 0 0 18px rgba(255,138,163,.35);
  color: var(--team-red);
}
@keyframes cinematic-in {
  from { opacity: 0; transform: translate(-50%, -6px); }
  to   { opacity: 1; transform: translate(-50%, 0); }
}

/* Power-play indicator — same slot as the cinematic banner but they never
   coexist (cinematic fires during the post-goal lull, PP only during
   active play). Smaller type than the banner so it reads as status
   rather than a marquee. */
#ppOverlay {
  position: absolute;
  top: 68px; left: 50%; transform: translateX(-50%);
  padding: 4px 10px;
  background: rgba(3, 6, 13, .82);
  border: 1px solid var(--line-2);
  border-radius: 6px;
  font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
  backdrop-filter: blur(4px);
  pointer-events: none;
  z-index: 5;
  white-space: nowrap;
}
#ppOverlay[hidden] { display: none; }
#ppOverlay[data-team="blue"] {
  border-color: rgba(137,208,255,.55);
  color: var(--team-blue);
}
#ppOverlay[data-team="red"] {
  border-color: rgba(255,138,163,.55);
  color: var(--team-red);
}

#scoreboard {
  display: flex; gap: 14px; align-items: center;
  background: rgba(5,10,22,.85); color: var(--text);
  padding: 8px 16px; border-radius: 12px;
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--line-2);
  backdrop-filter: blur(4px);
}
#scoreboard .team { display: flex; align-items: center; gap: 6px; font-weight: 800; font-size: 20px; }
#scoreboard .team .label { font-size: 10px; letter-spacing: 1px; opacity: .85; font-weight: 700; }
#scoreboard .team.blue .label { color: var(--team-blue); }
#scoreboard .team.red  .label { color: var(--team-red);  }
#scoreboard .mid { text-align: center; font-size: 11px; line-height: 1.15; color: var(--muted); }
#scoreboard .mid #clock { font-size: 14px; font-weight: 700; color: var(--text); }

/* ---------- playback controls ---------- */
/* Two-row layout:
 *   #controls      — playback essentials: play, scrub, time/status, speed
 *   #viewControls  — render toggles on the left, clip export on the right
 * Splitting keeps the scrub row uncluttered and makes the clip controls
 * easier to spot alongside the gold range band on the scrub bar above. */
#controls {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: 24px;
}
#viewControls {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}
#viewControls .vc-group { display: inline-flex; align-items: center; gap: 14px; flex-wrap: wrap; }
#viewControls .vc-spacer { flex: 1; min-width: 12px; }

#controls #playBtn { min-width: 80px; justify-content: center; }
#controls label,
#viewControls label { font-size: 12px; color: var(--muted); letter-spacing: .6px; text-transform: uppercase; }
#controls select,
#viewControls select {
  background: #0f1428; color: var(--text);
  border: 1px solid var(--line-2); border-radius: 10px;
  padding: 6px 10px; font: inherit; font-size: 13px;
}
#controls select:focus,
#viewControls select:focus { outline: none; border-color: var(--accent-2); }
#viewControls input[type="checkbox"] { vertical-align: middle; margin-right: 4px; accent-color: var(--accent-2); }
#viewControls .toggle { text-transform: none; letter-spacing: 0; color: var(--text); font-size: 13px; }

/* Clip export group: right-aligned on row 2, visually distinct. */
#viewControls .clip-controls {
  display: inline-flex; align-items: center; gap: 8px;
}
#viewControls .clip-controls[hidden] { display: none; }
#viewControls .clip-controls label { display: inline-flex; align-items: center; gap: 6px; }
#viewControls .clip-btn {
  padding: 6px 12px; font-size: 12px; min-width: 0;
}
#viewControls .clip-btn.active {
  color: var(--clip);
  border-color: rgba(177, 140, 255, .75);
  background: rgba(177, 140, 255, .14);
  box-shadow: 0 0 12px rgba(177, 140, 255, .3);
}
#viewControls .clip-btn-ghost {
  border-color: transparent;
  color: var(--muted);
  background: transparent;
}
#viewControls .clip-btn-ghost:hover:not(:disabled) {
  color: var(--text);
  background: rgba(255, 255, 255, .04);
  border-color: var(--line-2);
}
#viewControls .clip-label {
  font-size: 12px; color: var(--muted);
  letter-spacing: .6px; text-transform: uppercase;
  padding-right: 4px;
}
#viewControls .clip-range-label {
  font-variant-numeric: tabular-nums;
  font-size: 11px; font-weight: 600;
  color: var(--clip);
  letter-spacing: .02em;
  min-width: 160px;
  text-align: center;
  padding: 3px 10px;
  background: rgba(177, 140, 255, .1);
  border: 1px solid rgba(177, 140, 255, .32);
  border-radius: 6px;
}
#viewControls .clip-range-label.placeholder {
  color: var(--muted);
  background: transparent;
  border-style: dashed;
  border-color: var(--line-2);
  text-transform: none; letter-spacing: 0;
  font-weight: 500;
}

/* Full-page modal while a clip is recording. Blocks input so the user
   doesn't scrub / seek mid-record; the recorder drives playback itself. */
#clipProgress {
  position: fixed; inset: 0;
  background: rgba(3, 6, 13, .72);
  backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000;
}
#clipProgress[hidden] { display: none; }
.clip-progress-box {
  background: var(--card);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  padding: 20px 26px;
  min-width: 300px;
  text-align: center;
  box-shadow: 0 22px 50px rgba(0,0,0,.55);
}
.clip-progress-title {
  font-size: 13px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 10px;
}
.clip-progress-track {
  position: relative; height: 6px;
  background: var(--line); border-radius: 999px;
  overflow: hidden;
}
.clip-progress-bar {
  position: absolute; left: 0; top: 0; height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  transition: width .08s linear;
}
.clip-progress-pct {
  margin-top: 8px;
  font-size: 12px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* "Are you still there?" idle modal. Mirrors #clipProgress so it stacks
   above the rink and any HUD overlays without inheriting their styles. */
#idleModal {
  position: fixed; inset: 0;
  background: rgba(3, 6, 13, .72);
  backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000;
}
#idleModal[hidden] { display: none; }
.idle-modal-box {
  background: var(--card);
  border: 1px solid var(--line-2);
  border-radius: 12px;
  padding: 22px 28px;
  min-width: 320px; max-width: 420px;
  text-align: center;
  box-shadow: 0 22px 50px rgba(0,0,0,.55);
}
.idle-modal-title {
  font-size: 14px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 10px;
}
.idle-modal-body {
  font-size: 13px; color: var(--text);
  margin-bottom: 16px;
}
.idle-modal-btn {
  appearance: none; -webkit-appearance: none;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  color: #0b1220; border: 0; border-radius: 8px;
  padding: 10px 22px;
  font-size: 13px; font-weight: 700; letter-spacing: .04em;
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(0,0,0,.35);
}
.idle-modal-btn:focus-visible { outline: 2px solid var(--accent-2); outline-offset: 2px; }

/* ---------- custom scrub bar (YouTube-style) ---------- */
#scrub {
  position: relative; flex: 1; min-width: 240px;
  height: 22px; cursor: pointer;
  display: flex; align-items: center;
  touch-action: none; user-select: none;
  outline: none;
}
#scrub[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }
#scrub .track {
  position: relative;
  width: 100%; height: 4px;
  background: var(--line);
  border-radius: 999px;
  transition: height .12s ease;
}
#scrub:hover:not([aria-disabled="true"]) .track,
#scrub.dragging .track { height: 6px; }
#scrub .buffered,
#scrub .played {
  position: absolute; left: 0; top: 0; height: 100%;
  border-radius: 999px;
  pointer-events: none;
  width: 0%;
}
#scrub .buffered { background: var(--line-2); }
#scrub .played  { background: linear-gradient(90deg, var(--accent), var(--accent-2)); }
#scrub .loadbar {
  position: absolute; left: 0; top: 0; height: 100%;
  width: 100%;
  border-radius: 999px;
  pointer-events: none;
  overflow: hidden;
  opacity: 0;
  transition: opacity .2s ease;
}
#scrub.loading .loadbar { opacity: 1; }
#scrub .loadbar::before {
  content: "";
  position: absolute; top: 0; left: 0;
  width: 28%; height: 100%;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(137,208,255,0.75) 50%,
    transparent 100%);
  animation: scrub-loadbar 1.4s linear infinite;
}
@keyframes scrub-loadbar {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(460%); }
}
/* Clip range band: shows the [playhead − clipLength, playhead] span that
   will be captured on Export. Extends well above and below the thin scrub
   track so the range is obvious at a glance — the 4 px track alone wasn't
   enough real estate to read. Bold gold edges mark the exact start and end
   ticks; the fill is a low-alpha wash so goal/faceoff markers inside the
   band still read through. Sits under the thumb so the playhead is always
   visible even when it lines up with the band's right edge. */
#scrub .clip-range {
  position: absolute;
  top: -9px; height: calc(100% + 18px);
  background: rgba(177, 140, 255, .18);
  border-left:  3px solid rgba(177, 140, 255, .95);
  border-right: 3px solid rgba(177, 140, 255, .95);
  box-shadow: 0 0 12px rgba(177, 140, 255, .35),
              inset 0 0 0 1px rgba(177, 140, 255, .4);
  border-radius: 4px;
  pointer-events: none;
  width: 0;
}
/* Pending state: only one endpoint is set and the other follows the
   playhead. Dashed edges signal "not final yet" without losing the band. */
#scrub .clip-range.pending {
  background: rgba(177, 140, 255, .08);
  border-left-style:  dashed;
  border-right-style: dashed;
  box-shadow: inset 0 0 0 1px rgba(177, 140, 255, .25);
}
#scrub[aria-disabled="true"] .clip-range { display: none; }
#scrub .clip-range[hidden] { display: none; }

#scrub .markers {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0;
  pointer-events: none;
}
.scrub-marker {
  position: absolute;
  top: -4px; height: calc(100% + 8px);
  width: 3px; margin-left: -1.5px;
  border-radius: 2px;
  pointer-events: auto;   /* so tooltips work */
  cursor: pointer;
}
.scrub-marker[data-team="blue"] {
  background: var(--team-blue);
  box-shadow: 0 0 6px rgba(137,208,255,0.7);
}
.scrub-marker[data-team="red"] {
  background: var(--team-red);
  box-shadow: 0 0 6px rgba(255,138,163,0.7);
}
.scrub-marker.scorer-highlight {
  background: var(--gold);
  box-shadow: 0 0 10px rgba(255,209,102,0.95);
  width: 4px; margin-left: -2px;
  height: calc(100% + 12px); top: -6px;
  z-index: 2;
}
.scrub-marker.assist-highlight {
  background: rgba(255,209,102,0.55);
  box-shadow: 0 0 6px rgba(255,209,102,0.45);
  z-index: 1;
}
/* Faceoff markers are drawn under goal markers — thinner, muted, no glow,
   so the scrub bar isn't overwhelmed by them. They mark where a faceoff
   started (transition INTO GAME_PHASE.FACEOFF). */
.scrub-marker.faceoff-marker {
  top: 0; height: 100%;
  width: 2px; margin-left: -1px;
  background: rgba(169, 179, 199, .38);
  box-shadow: none;
  border-radius: 1px;
}
.scrub-marker.faceoff-marker:hover { height: calc(100% + 8px); top: -4px; background: rgba(169, 179, 199, .7); }
.scrub-marker:hover { height: calc(100% + 14px); top: -7px; }

/* Power-play bands: translucent team-color fills spanning the PP interval.
   Sit behind goal/faceoff point markers so those still read on top. */
.scrub-pp-band {
  position: absolute;
  top: 0; height: 100%;
  pointer-events: auto;
  cursor: pointer;
  border-radius: 2px;
  opacity: 0.45;
}
.scrub-pp-band[data-team="blue"] { background: var(--team-blue); }
.scrub-pp-band[data-team="red"]  { background: var(--team-red); }
.scrub-pp-band:hover { opacity: 0.75; }

#scrub .thumb {
  position: absolute; top: 50%;
  width: 12px; height: 12px;
  margin-left: -6px; margin-top: -6px;
  background: var(--accent-2);
  border-radius: 50%;
  pointer-events: none;
  left: 0%;
  transform: scale(0);
  transition: transform .15s ease, box-shadow .15s ease;
  box-shadow: 0 0 0 0 rgba(137, 208, 255, 0.0);
}
#scrub:hover:not([aria-disabled="true"]) .thumb,
#scrub.dragging .thumb,
#scrub:focus-visible .thumb {
  transform: scale(1);
  box-shadow: 0 0 0 5px rgba(137, 208, 255, 0.25);
}

/* ---------- time display & status pill ---------- */
.time-display {
  font-variant-numeric: tabular-nums;
  font-size: 12px; font-weight: 600;
  color: var(--muted);
  min-width: 90px; text-align: right;
}
#statusPill {
  min-width: 70px; text-align: center;
  background: rgba(255,255,255,.04);
}
#statusPill[data-kind="buffering"],
#statusPill[data-kind="loading"] {
  background: rgba(59,169,255,.14); color: var(--accent-2);
  border-color: rgba(59,169,255,.3);
}
#statusPill[data-kind="streaming"] {
  background: rgba(48,209,88,.12); color: var(--good);
  border-color: rgba(48,209,88,.3);
}
#statusPill[data-kind="playing"] { color: var(--text); }
#statusPill[data-kind="paused"]  { color: var(--muted); }
#statusPill[data-kind="end"]     { color: var(--gold); border-color: rgba(255,209,102,.35); }
#statusPill[data-kind="error"]   {
  background: rgba(255,95,87,.14); color: #ffbcb9;
  border-color: rgba(255,95,87,.4);
}

/* ---------- meta row ---------- */
#meta {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 8px 24px; font-size: 13px;
}
#meta b { color: var(--muted); font-weight: 700; margin-right: 6px;
          text-transform: uppercase; font-size: 11px; letter-spacing: .06em; }

/* ---------- match summary (top of matchCard) ---------- */
#matchSummary {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 24px;
  padding: 4px 0 18px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
#matchScore {
  display: flex; align-items: center; gap: 14px;
  font-weight: 800;
}
.mscore-team { display: flex; align-items: center; gap: 10px; }
.mscore-team.red { flex-direction: row-reverse; }
.mscore-label {
  font-size: 12px; letter-spacing: .12em;
  color: var(--muted);
}
.mscore-team.blue .mscore-label { color: var(--team-blue); }
.mscore-team.red  .mscore-label { color: var(--team-red); }
.mscore-val { font-size: 42px; line-height: 1; }
.mscore-team.blue .mscore-val { color: var(--team-blue); }
.mscore-team.red  .mscore-val { color: var(--team-red); }
.mscore-sep { color: var(--muted); font-size: 24px; font-weight: 400; }

#matchTotals {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 6px 24px;
  margin: 0; flex: 1; min-width: 280px;
  font-size: 13px;
}
#matchTotals > div { display: flex; flex-direction: column; gap: 2px; }
#matchTotals dt {
  color: var(--muted); font-size: 11px;
  text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
}
#matchTotals dd { margin: 0; color: var(--text); }

/* ---------- match highlights (shot shelf + ice tilt + goalie wall) ---------- */
.match-highlights {
  flex: 1 1 100%;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  align-items: start;
}
.highlight {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  min-width: 0;
}
.highlight-header {
  display: flex; align-items: baseline; gap: 8px;
  align-self: stretch; justify-content: space-between;
}
.highlight-header h4 {
  margin: 0; font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted);
}
.highlight-header .sub {
  color: var(--muted); font-size: 11px;
}
.ice-tilt-svg {
  width: 100%; max-width: 240px; height: auto;
  display: block;
}
.tilt-plank {
  transition: transform 600ms cubic-bezier(.22,1,.36,1);
  transform-box: view-box;
  transform-origin: 180px 90px;
}
.plank-body {
  fill: #1c2640;
  stroke: var(--line-2); stroke-width: 1;
}
.plank-end {
  stroke: rgba(0,0,0,.35); stroke-width: 1;
}
.plank-end.blue { fill: var(--team-blue); }
.plank-end.red  { fill: var(--team-red); }
.plank-label {
  font: 700 11px/1 Inter, system-ui, sans-serif;
  fill: #0a1020; letter-spacing: .08em;
}
.tilt-puck {
  fill: #101622; stroke: var(--text); stroke-width: 1.5;
  transition: cx 600ms cubic-bezier(.22,1,.36,1);
  filter: drop-shadow(0 2px 2px rgba(0,0,0,.5));
}
.fulcrum { fill: var(--line-2); stroke: var(--line); stroke-width: 1; }
.floor   { stroke: var(--line); stroke-width: 1; }

.ice-tilt-legend {
  display: flex; gap: 10px; flex-wrap: wrap;
  justify-content: center;
  font-size: 11px;
}
.ice-tilt-legend .zone {
  display: inline-flex; align-items: baseline; gap: 5px;
  color: var(--muted);
  padding: 1px 7px;
  border-radius: 999px;
  border: 1px solid transparent;
  transition: background 200ms, border-color 200ms, color 200ms;
}
.ice-tilt-legend .zone em {
  font-style: normal; font-weight: 700; font-size: 12px;
  color: var(--text);
}
.ice-tilt-legend .zone.blue em  { color: var(--team-blue); }
.ice-tilt-legend .zone.red  em  { color: var(--team-red); }
.ice-tilt-legend .zone[data-heavy="true"] {
  background: rgba(255,255,255,.04);
  border-color: var(--line-2);
}
.ice-tilt-legend .zone.blue[data-heavy="true"] {
  background: rgba(137,208,255,.10);
  border-color: rgba(137,208,255,.35);
}
.ice-tilt-legend .zone.red[data-heavy="true"] {
  background: rgba(255,138,163,.10);
  border-color: rgba(255,138,163,.35);
}
.ice-tilt-verdict {
  margin: 0; color: var(--text); font-size: 12px; text-align: center;
}

/* ---------- shot shelf ---------- */
.shot-shelf-svg {
  width: 100%; max-width: 260px; height: auto;
  display: block;
}
.shelf-baseline { stroke: var(--line-2); stroke-width: 1; }
.shelf-chip {
  font: 700 10px/1 Inter, system-ui, sans-serif;
  letter-spacing: .08em;
}
.shelf-chip.blue { fill: var(--team-blue); }
.shelf-chip.red  { fill: var(--team-red); }
.shelf-goal { filter: drop-shadow(0 1px 1px rgba(0,0,0,.5)); }
.shot-shelf-legend {
  display: flex; flex-direction: column; gap: 2px;
  font-size: 11px; color: var(--muted);
  align-self: stretch; align-items: center;
}
.shot-shelf-legend .zone em {
  font-style: normal; font-weight: 700; color: var(--text);
}
.shot-shelf-legend .zone.blue em { color: var(--team-blue); }
.shot-shelf-legend .zone.red  em { color: var(--team-red); }

/* ---------- goalie wall ---------- */
.goalie-wall-svg {
  width: 100%; max-width: 240px; height: auto;
  display: block;
}
.wall-body {
  stroke: rgba(0,0,0,.35); stroke-width: 1;
  transition: height 500ms cubic-bezier(.22,1,.36,1),
              y      500ms cubic-bezier(.22,1,.36,1);
}
.wall-body.blue { fill: rgba(137,208,255,.72); }
.wall-body.red  { fill: rgba(255,138,163,.72); }
.wall-brick { stroke: rgba(0,0,0,.25); stroke-width: 1; }
.wall-floor { stroke: var(--line-2); stroke-width: 1; }
.wall-pct {
  font: 800 12px/1 Inter, system-ui, sans-serif;
  letter-spacing: .02em;
}
.wall-pct.blue { fill: var(--team-blue); }
.wall-pct.red  { fill: var(--team-red); }
.wall-absent {
  font: 600 11px/1 Inter, system-ui, sans-serif;
  fill: var(--muted);
}
.goalie-wall-legend {
  display: flex; gap: 14px; justify-content: space-around;
  align-self: stretch;
  font-size: 11px; color: var(--muted);
}
.goalie-wall-legend .zone {
  display: flex; flex-direction: column; align-items: center; gap: 1px;
  min-width: 0;
}
.goalie-wall-legend .zone em {
  font-style: normal; font-weight: 700; color: var(--text);
  font-size: 12px;
  max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.goalie-wall-legend .zone.blue em { color: var(--team-blue); }
.goalie-wall-legend .zone.red  em { color: var(--team-red); }

/* ---------- stats table (shares match-table aesthetic) ---------- */
.match-table { width: 100%; border-collapse: collapse; }
.match-table th, .match-table td {
  text-align: left; padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.match-table th {
  font-size: 11px; letter-spacing: .6px; text-transform: uppercase;
  color: var(--muted); font-weight: 700;
}
.match-table td { background-color: var(--heat, transparent); }
.match-table tr:hover td {
  background: linear-gradient(rgba(59,169,255,.05), rgba(59,169,255,.05)), var(--heat, transparent);
}
.match-table td.num, .match-table th.num {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.match-table td.name { font-weight: 650; }
.match-table td.name .flag {
  display: inline-block; margin-right: 6px;
  width: 18px; height: 13px;
  object-fit: cover;
  vertical-align: -1px;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0,0,0,.35);
}
.match-table td.zone { white-space: nowrap; width: 1%; }
.match-table td.steamid { color: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; }
.match-table td.steamid .steam-link { color: inherit; border-bottom: 1px dotted rgba(169,179,199,.4); }
.match-table td.steamid .steam-link:hover { color: var(--accent-2); border-bottom-color: var(--accent-2); }

/* Roster-churn glyphs next to the username. Each conveys a single event
 * via its tooltip; color-codes by category so a scan of the team rows
 * surfaces unusual players fast. */
.churn-badge {
  display: inline-block; margin-left: 6px;
  font-size: 11px; line-height: 1;
  padding: 1px 5px; border-radius: 999px;
  background: rgba(255,255,255,.05);
  color: var(--muted);
  border: 1px solid transparent;
  cursor: help;
  vertical-align: 1px;
}
.churn-badge.teams { color: var(--team-blue); border-color: rgba(137,208,255,.35); }
.churn-badge.pos   { color: var(--gold);      border-color: rgba(255,209,102,.35); }
.churn-badge.late  { color: var(--good);      border-color: rgba(48,209,88,.35); }
.churn-badge.early { color: var(--bad);       border-color: rgba(255,95,87,.35); }

/* Team color bar at start of each stats row.
 * PlayerTeam enum: 2 = Blue, 3 = Red. */
.match-table td.team-bar { width: 3px; padding: 0; }
.match-table td.team-bar.team-2 { background: var(--team-blue); }
.match-table td.team-bar.team-3 { background: var(--team-red); }

/* Team-change divider */
.match-table tr.team-break td { border-top: 2px solid var(--line-2); }

/* Goalie tag */
.match-table tr.goalie td.name::after { content: " (G)"; color: var(--muted); font-size: 11px; font-weight: 400; }

/* Leading-stat highlight: first row of each team (highest-points) gets a gold touch */
.match-table tr.top td.pts { color: var(--gold); font-weight: 800; }

/* Cross-panel selection - click a stats row to highlight the player on the rink. */
.match-table tbody tr { cursor: pointer; }
.match-table tbody tr.selected td {
  background: linear-gradient(rgba(255,209,102,0.08), rgba(255,209,102,0.08)), var(--heat, transparent);
}
.match-table tbody tr.selected td.name { color: var(--gold); font-weight: 700; }

/* Position chip */
.pos-chip {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: .04em;
  border: 1px solid var(--line-2); background: rgba(255,255,255,.02);
  color: var(--muted); min-width: 28px; text-align: center;
}

/* ---------- status pill ---------- */
.status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 10px; border-radius: 999px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--line-2); background: rgba(255,255,255,.03);
  color: var(--muted);
}

/* ---------- responsive ---------- */

/* Touch-specific affordances. `hover: none` + `pointer: coarse` targets
   devices whose primary input is a finger / pen, so every rule here is
   a no-op on mouse/trackpad and can't regress desktop. The main job is
   giving the scrub bar a visible playhead indicator (otherwise the
   playhead is hidden until the user starts dragging — unusable on
   touch) and enlarging pill-sized controls to a finger-friendly size. */
@media (hover: none) and (pointer: coarse) {
  /* Scrub: fatter track + always-visible thumb. Desktop keeps the
     hover-reveal behavior because this block doesn't apply there. */
  #scrub { height: 32px; }
  #scrub .track { height: 6px; }
  #scrub.dragging .track { height: 8px; }
  #scrub .thumb {
    width: 16px; height: 16px;
    margin-left: -8px; margin-top: -8px;
    transform: scale(1);
  }
  #scrub.dragging .thumb {
    transform: scale(1.2);
    box-shadow: 0 0 0 6px rgba(137, 208, 255, 0.28);
  }
  /* Goal/faceoff markers grow slightly and pick up an invisible
     tap-area pad via ::after so fingers can land on the 3-4 px ribbon. */
  .scrub-marker { width: 5px; margin-left: -2.5px; }
  .scrub-marker::after {
    content: "";
    position: absolute;
    left: -7px; right: -7px; top: -6px; bottom: -6px;
  }
  .scrub-marker.faceoff-marker { width: 3px; margin-left: -1.5px; }
  .scrub-marker.scorer-highlight { width: 6px; margin-left: -3px; }

  /* Stage toolbar controls: 26 px was the hover-happy mouse size.
     Bump to ~36 px on touch for comfortable taps without changing the
     toolbar's visual footprint much. */
  .stage-icon-btn,
  .tool-picker .tool { width: 34px; height: 34px; }
  .swatch { width: 26px; height: 26px; }
  .mode-picker .mode { height: 34px; padding: 0 12px; font-size: 12px; }
  #drawToggle, #heatmapToggle { padding: 8px 12px; font-size: 12px; }
  .stage-toolbar { padding: 5px 8px; gap: 6px; }
  .stage-toolbar .btn { padding: 7px 12px; font-size: 12px; }

  /* Row-height on the play control + clip buttons. */
  #controls .btn,
  #viewControls .clip-btn { padding: 10px 14px; min-height: 38px; }

  /* Sticky-hover guard. On touch, :hover state lingers after a tap
     until the user taps elsewhere — the button looks stuck in its
     hover state. Flatten the hover transform so there's no visible
     residue; color changes still apply so active state is still
     obvious. */
  .btn:hover:not(:disabled),
  .btn-primary:hover:not(:disabled) { transform: none; }
}

/* Narrow viewport: phones landscape, small tablets, narrow desktop
   windows. Tightens header + card chrome, stacks the controls rows,
   shrinks the scoreboard/overlays so they don't crowd small rinks.
   Desktop at full width never enters this block. */
@media (max-width: 820px) {
  html { scroll-padding-top: 120px; }
  .wrap { padding: 6px; }
  main.wrap { padding-top: 10px; gap: 12px; }
  .card { padding: 14px; border-radius: 12px; }
  .card h3 { font-size: 18px; }
  .card h3 .sub { font-size: 12px; }

  /* Replay select can flex to fill its row when wrapped. */
  .replay-select { flex: 1 1 240px; min-width: 0; max-width: 100%; }

  /* Match summary: compress gaps so score + totals still fit one row
     when there's room, but stack cleanly when they don't. */
  #matchSummary { gap: 14px; padding-bottom: 14px; margin-bottom: 14px; }
  .mscore-val { font-size: 34px; }
  #matchTotals {
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 4px 16px;
    min-width: 220px;
  }
  /* Highlights stack into a single column on narrow screens so each
     visualization gets its own full-width row instead of being squeezed. */
  .match-highlights { grid-template-columns: 1fr; gap: 16px; }

  /* Meta grid: 2 cols instead of auto-fit 220px. (Replaces the old
     800px-only override, extended with other tweaks in this block.) */
  #meta { grid-template-columns: 1fr 1fr; }

  /* Scoreboard overlay: smaller type + gap, still readable. */
  #scoreboard { gap: 10px; padding: 6px 12px; }
  #scoreboard .team { font-size: 17px; gap: 4px; }
  #scoreboard .team .label { font-size: 9px; }
  #scoreboard .mid #clock { font-size: 13px; }
  #scoreboard .mid #period { font-size: 10px; }
  #possessionPill { font-size: 10px; padding: 2px 8px; }

  /* Cinematic / PP banners move up to match the smaller scoreboard. */
  #cinematicBanner { top: 58px; font-size: 11px; padding: 4px 12px; letter-spacing: .08em; }
  #ppOverlay       { top: 58px; font-size: 11px; padding: 3px 8px; }

  /* Stage toolbars: thinner padding so they don't crowd a ~360-wide rink.
     At narrow widths the left (markup) and right (heatmap) toolbars would
     collide when both were expanded — horizontal row of tools + swatches
     + Undo/Clear can easily be wider than half a phone rink. Switching
     to column-reverse puts the toggle chip on top with the expanded tool
     group dropping DOWN beneath it, and hiding inactive groups reclaims
     the space entirely when a side isn't in use. Max-width caps each
     toolbar so the two sides can never meet in the middle. */
  .stage-toolbar {
    top: 6px; padding: 3px 6px; gap: 4px;
    flex-direction: column-reverse;
    max-width: calc(50% - 12px);
  }
  .stage-toolbar-left  { left:  6px; align-items: flex-start; }
  .stage-toolbar-right { right: 6px; align-items: flex-end;   }
  .stage-fullscreen-btn { right: 6px; bottom: 6px; }

  /* Vertical divider between toggle and tools becomes a horizontal sliver
     in column mode — drop it. */
  .draw-tools::after,
  .stage-toolbar .mode-picker::after { display: none; }

  /* Inactive tool group collapses entirely instead of dimming in place.
     On desktop we keep the dim-in-place behavior (tools stay visible as
     a hint) because real estate is cheap there; on phones it's critical
     that the two corners don't grow into each other. */
  .stage-toolbar .draw-tools.inactive,
  .stage-toolbar .mode-picker.inactive { display: none; }

  /* Active tool group wraps its items so a long swatch row folds into
     two shorter rows instead of pushing the toolbar past its max-width. */
  .stage-toolbar .draw-tools,
  .stage-toolbar .mode-picker { flex-wrap: wrap; gap: 4px; }
  .stage-toolbar-right .mode-picker { justify-content: flex-end; }
  .stage-toolbar .draw-tools .btn { padding: 5px 10px; font-size: 11px; }

  /* Chat overlay on the rink uses less vertical space at small heights. */
  #chatOverlay, #refOverlay { max-height: 96px; }
  .chat-bubble { font-size: 11px; padding: 3px 8px; max-width: 100%; }

  /* Controls row: scrub gets its own row so it isn't squeezed to a
     100 px strip between the play button and the time readout. */
  #controls { gap: 8px; margin-top: 16px; }
  #controls #playBtn { min-width: 68px; padding: 8px 14px; }
  #scrub { flex: 1 1 100%; order: 3; }
  .time-display { font-size: 11px; min-width: 72px; }
  #controls label { font-size: 11px; }
  #controls select, #viewControls select { padding: 6px 8px; font-size: 12px; }

  #viewControls { gap: 10px; margin-top: 8px; padding-top: 8px; }
  #viewControls .vc-group { gap: 10px; }
  #viewControls .toggle { font-size: 12px; }
  #viewControls .vc-spacer { flex: 0 0 100%; min-width: 0; height: 0; }
  #viewControls .clip-controls { flex-wrap: wrap; gap: 6px; }
  #viewControls .clip-label { padding-right: 0; }
  #viewControls .clip-range-label {
    min-width: 0; flex: 1 1 100%;
    order: 10;  /* push the readout to its own line below the buttons */
    font-size: 10px;
  }
}

/* Phones in portrait (≤520 px). Further compresses card chrome, stats
   rows, and the toolbar controls so a one-hand phone grip still shows
   both teams' data. */
@media (max-width: 520px) {
  .file-btn { padding: 6px 10px; font-size: 12px; }
  .status-pill { font-size: 11px; padding: 2px 8px; }

  #matchTotals { grid-template-columns: 1fr 1fr; gap: 4px 12px; }
  .mscore-val { font-size: 28px; }
  .mscore-sep { font-size: 18px; }

  /* Stats table body: tighter padding so more columns are visible per
     scroll-swipe. Table still scrolls horizontally via its wrapper. */
  .match-table th, .match-table td { padding: 7px 8px; font-size: 12px; }
  .match-table td.steamid { font-size: 11px; }

  .card { padding: 10px; }
  .card h3 { font-size: 16px; }

  /* Scoreboard at portrait-phone widths — squeeze tighter so it doesn't
     overlap the stage toolbars on a 320-pt-wide rink. */
  #scoreboard { gap: 8px; padding: 5px 10px; }
  #scoreboard .team { font-size: 15px; }

  /* Clip controls stack to one button per row at extreme widths. */
  #viewControls .clip-btn { flex: 1 1 calc(50% - 4px); justify-content: center; }
}

/* Respect iOS / Android safe-area insets on phones with notches /
   rounded corners. No-op on desktop (env() resolves to 0). */
@supports (padding: max(0px)) {
  main.wrap {
    padding-left:  max(8px, env(safe-area-inset-left));
    padding-right: max(8px, env(safe-area-inset-right));
  }
}
