/* G2 design-system tokens (knowledge/design-system/tokens). Dark player chrome. */
:root {
  --brand: #D32436;            /* color.brand.elite */
  --accent: #FABE23;           /* color.support.elite-accent */
  --success: #22C55E;
  --warning: #F59E0B;
  --danger: #EF4444;
  --n0: #FFFFFF; --n50: #F8FAFC; --n100: #F1F5F9; --n200: #E2E8F0; --n300: #CBD5E1;
  --n400: #94A3B8; --n500: #64748B; --n600: #475569; --n700: #334155; --n800: #1E293B; --n900: #0F172A;
  --bg: #0B1220;               /* one step below n900 for the player ground */
  --font: Inter, system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s8: 32px;
  --r-sm: 6px; --r-md: 12px; --r-lg: 16px; --r-full: 999px;
  --side-w: 300px;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  font-family: var(--font); font-size: 1rem; line-height: 1.55;
  color: var(--n100); background: var(--bg);
  display: grid; grid-template-columns: 1fr var(--side-w); grid-template-rows: auto 1fr;
  grid-template-areas: "top top" "player side";
  min-height: 100vh;
}
button { font: inherit; }
kbd { font-family: var(--mono); font-size: .8em; padding: 1px 5px; border: 1px solid var(--n600); border-radius: 4px; background: var(--n800); }
code { font-family: var(--mono); font-size: .85em; color: var(--n300); }
[hidden] { display: none !important; }

/* ---------- top bar ---------- */
.topbar {
  grid-area: top;
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--s4);
  padding: var(--s3) var(--s5);
  background: linear-gradient(180deg, var(--n900), var(--bg));
  border-bottom: 1px solid var(--n800);
}
.brand { display: flex; align-items: center; gap: var(--s3); }
.brand-shield { width: 40px; height: 40px; border-radius: var(--r-sm); }
.brand-text { display: flex; flex-direction: column; line-height: 1.1; }
.brand-name { font-weight: 700; font-size: 1.05rem; letter-spacing: .02em; }
.brand-sub { font-weight: 600; font-size: .74rem; color: var(--brand); text-transform: uppercase; letter-spacing: .14em; }
.game-title { text-align: center; }
.game-teams { font-weight: 700; font-size: 1.35rem; line-height: 1.3; }
.game-meta { font-size: .85rem; color: var(--n400); }
.game-meta .pill { display: inline-flex; align-items: center; gap: 6px; padding: 1px 10px; border-radius: var(--r-full); background: var(--n800); color: var(--n200); font-weight: 600; font-size: .74rem; text-transform: uppercase; letter-spacing: .08em; margin-right: var(--s2); }
.game-meta .pill.is-live { background: var(--brand); color: var(--n0); }
.league { display: flex; align-items: center; justify-content: flex-end; gap: var(--s2); }
.league-mark { width: 36px; height: 36px; }
.league-name { font-weight: 600; font-size: .85rem; color: var(--n300); }

/* ---------- player ---------- */
.player { grid-area: player; display: flex; flex-direction: column; min-width: 0; position: relative; }
.player:fullscreen { background: #000; }

/* ---- Fullscreen ---------------------------------------------------------
   Two things have to change, and they are written as separate rule blocks on
   purpose: an unknown pseudo-class invalidates an ENTIRE selector list in most
   engines, so combining :fullscreen with :-webkit-full-screen would silently
   kill the rule for everyone.

   1. Drop the stage's aspect-ratio and max-height. Out of fullscreen the stage
      is a 16/9 box inside a taller page. In fullscreen it IS the page, and on
      any monitor wider than 16:9 the 16/9 box is shorter than the screen —
      which left a dead black band under the controls.
   2. Hide the camera strip. Panes are still tappable to change camera, and the
      strip is the biggest thing standing between the viewer and the game. */
.player:fullscreen .stage {
  aspect-ratio: auto; max-height: none; min-height: 0; flex: 1 1 auto;
}
.player:-webkit-full-screen .stage {
  aspect-ratio: auto; max-height: none; min-height: 0; flex: 1 1 auto;
}
.player:fullscreen .camera-strip { display: none; }
.player:-webkit-full-screen .camera-strip { display: none; }

/* Let the controls keep their natural height and give everything else to the
   video, so the column adds up to exactly the screen with nothing left over. */
.player:fullscreen { height: 100%; }
.player:-webkit-full-screen { height: 100%; }
.player:fullscreen .controls { flex: 0 0 auto; }
.player:-webkit-full-screen .controls { flex: 0 0 auto; }

.stage {
  position: relative; background: #000; flex: 1 1 auto; min-height: 320px;
  aspect-ratio: 16 / 9; max-height: calc(100vh - 230px);
  display: grid; gap: 3px; overflow: hidden;
}
.stage.layout-1 { grid-template-columns: 1fr; grid-template-rows: 1fr; }
.stage.layout-2 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr; }
.stage.layout-3 { grid-template-columns: 2fr 1fr; grid-template-rows: 1fr 1fr; }
.stage.layout-3 .pane:nth-child(1) { grid-row: 1 / span 2; }
.stage.layout-4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.stage.layout-pip { grid-template-columns: 1fr; grid-template-rows: 1fr; }

/* ---- Banner layouts: one wide shot across the full width, a strip of the
   remaining angles on the other edge. -------------------------------------

   Row sizing is `1fr auto`, not a fixed split. The strip panes carry
   aspect-ratio 16/9, so the strip row sizes itself to exactly the height those
   panes need at the current width — which changes with the column count — and
   the banner takes whatever is left. Two panes across therefore gives a
   shorter banner than four, which is what you want, and no pane in the strip
   is ever letterboxed. */
.stage.is-banner { grid-template-rows: 1fr auto; }
.stage.layout-b2 { grid-template-columns: repeat(2, 1fr); }
.stage.layout-b3 { grid-template-columns: repeat(3, 1fr); }
.stage.layout-b4 { grid-template-columns: repeat(4, 1fr); }

.stage.is-banner .pane:first-child { grid-column: 1 / -1; grid-row: 1; }
.stage.is-banner .pane:not(:first-child) { grid-row: 2; aspect-ratio: 16 / 9; }

/* Flipped: the wide shot moves to the bottom, the strip to the top. */
.stage.is-banner.is-flipped { grid-template-rows: auto 1fr; }
.stage.is-banner.is-flipped .pane:first-child { grid-row: 2; }
.stage.is-banner.is-flipped .pane:not(:first-child) { grid-row: 1; }

/* The banner is much wider than 16:9, so the source has to be cropped rather
   than letterboxed — `contain` would leave two huge black bars.

   --banner-focus is the vertical anchor: higher keeps more of the BOTTOM of
   the frame and so crops more off the top. 70% is tuned for the home-plate
   camera, where the top third is sky and the catcher sits low in frame. Drop
   it toward 50% for a centre-field camera, where the action is higher up. */
.stage.is-banner .pane:first-child video {
  object-fit: cover;
  object-position: 50% var(--banner-focus, 70%);
}
.stage.is-banner .pane:first-child canvas { object-fit: cover; }

/* The banner is the primary pane but a full-width red ring around it is noisy,
   so mark it the same way the single-pane layout does: not at all. */
.stage.is-banner .pane:first-child.is-primary::before { display: none; }

.layouts .layout-sep {
  width: 1px; align-self: stretch; margin: 0 2px;
  background: var(--n700); opacity: .55;
}
.layouts #btnFlip svg { width: 22px; height: 15px; fill: currentColor; }
.layouts #btnFlip { padding: 6px 8px; }
.layouts #btnFlip.is-active { border-color: var(--brand); background: rgba(211,36,54,.18); }
.layouts #btnFlip:disabled { opacity: .35; cursor: not-allowed; }
.stage.layout-pip .pane:nth-child(2) {
  position: absolute; right: var(--s4); bottom: var(--s4); width: 30%; min-width: 180px; aspect-ratio: 16/9;
  border: 2px solid var(--n0); border-radius: var(--r-md); box-shadow: 0 8px 28px rgba(0,0,0,.6); z-index: 4; /* above a primary pane's state overlay (3), below the game-state overlay (5) */
  overflow: hidden; cursor: pointer;
}
.stage.layout-pip .pane:nth-child(2) .pane-label { font-size: .74rem; }
.stage.layout-pip .pane:nth-child(2)::after {
  content: "Tap to swap"; position: absolute; right: 8px; top: 8px; font-size: .68rem; font-weight: 600;
  padding: 2px 8px; border-radius: var(--r-full); background: rgba(15,23,42,.75); color: var(--n200);
}

.pane { position: relative; background: var(--n900); overflow: hidden; cursor: pointer; outline: 0; }
.pane:focus-visible { box-shadow: inset 0 0 0 3px var(--accent); }
.pane.is-primary::before { content: ""; position: absolute; inset: 0; pointer-events: none; box-shadow: inset 0 0 0 2px var(--brand); z-index: 1; }
.stage.layout-1 .pane.is-primary::before, .stage.layout-pip .pane.is-primary::before { display: none; }
.pane video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; display: block; background: #000; }
.pane canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; background: #0B1220; }

/* ---- Pane loading state -------------------------------------------------
   Shown from the moment a stream is requested until a frame is actually on
   screen. Sits above the video but below the label, so the viewer can still
   see which camera they are waiting on. */
.pane-loading {
  position: absolute; inset: 0; z-index: 3; display: flex;
  flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s3); padding: var(--s4); text-align: center;
  background: rgba(11,18,32,.72); backdrop-filter: blur(2px);
  pointer-events: none;
}
.pane-loading .spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid rgba(255,255,255,.16);
  border-top-color: var(--brand);
  animation: pane-spin .85s linear infinite;
}
.pane-loading .load-title { font-size: .95rem; font-weight: 600; color: var(--n0); }
.pane-loading .load-sub {
  font-size: .8rem; color: var(--n400); max-width: 30ch; line-height: 1.4;
}
@keyframes pane-spin { to { transform: rotate(360deg); } }

/* Small panes in a banner strip or a 4-up have no room for the copy. */
.stage.layout-4 .pane-loading .load-sub,
.stage.is-banner .pane:not(:first-child) .pane-loading .load-sub { display: none; }
.stage.is-banner .pane:not(:first-child) .pane-loading .spinner,
.stage.layout-4 .pane-loading .spinner { width: 26px; height: 26px; border-width: 2.5px; }
.stage.is-banner .pane:not(:first-child) .pane-loading .load-title { font-size: .82rem; }

/* Respect a reduced-motion preference: keep the state, drop the spin. */
@media (prefers-reduced-motion: reduce) {
  .pane-loading .spinner { animation-duration: 3s; }
}
.pane-label {
  position: absolute; left: var(--s3); top: var(--s3); z-index: 2; display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--r-full); background: rgba(15,23,42,.78); color: var(--n0);
  font-size: .85rem; font-weight: 600; letter-spacing: .01em; backdrop-filter: blur(4px);
}
.pane-label .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.pane-label .dot.off { background: var(--n500); }
.pane-change {
  position: absolute; right: var(--s3); top: var(--s3); z-index: 2; opacity: 0; transition: opacity .15s;
  padding: 3px 10px; border-radius: var(--r-full); background: rgba(15,23,42,.78); color: var(--n200); font-size: .74rem; font-weight: 600; border: 0; cursor: pointer;
}
.pane:hover .pane-change { opacity: 1; }
.stage.layout-pip .pane:nth-child(2) .pane-change { display: none; }

.pane-state {
  position: absolute; inset: 0; z-index: 3; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2);
  background: radial-gradient(ellipse at center, var(--n800), var(--n900)); color: var(--n200); text-align: center; padding: var(--s6);
}
.pane-state .title { font-weight: 600; font-size: 1.05rem; }
.pane-state .sub { font-size: .85rem; color: var(--n400); }
.pane-state svg { width: 36px; height: 36px; fill: var(--n500); }

.game-state {
  position: absolute; left: 0; right: 0; top: 0; z-index: 5; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2);
  background: rgba(11,18,32,.88); color: var(--n0); text-align: center; padding: var(--s8); backdrop-filter: blur(6px);
}
.game-state .title { font-size: 1.75rem; font-weight: 700; line-height: 1.2; }
.game-state .sub { color: var(--n300); }

/* ---------- controls ---------- */
.controls { background: var(--n900); border-top: 1px solid var(--n800); padding: var(--s2) var(--s4) var(--s3); display: flex; flex-direction: column; gap: var(--s2); }
.timeline-row { display: flex; align-items: center; gap: var(--s3); }
.actions-row { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); flex-wrap: wrap; }
.group { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }

.btn {
  display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: var(--r-sm);
  border: 1px solid var(--n700); background: var(--n800); color: var(--n100); cursor: pointer; font-weight: 500; font-size: .85rem; line-height: 1.2;
}
.btn:hover { background: var(--n700); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.btn svg { width: 16px; height: 16px; fill: currentColor; }
.btn.icon { padding: 6px; width: 34px; height: 34px; justify-content: center; }
.btn.icon svg { width: 20px; height: 20px; }
.btn.primary { background: var(--brand); border-color: var(--brand); color: var(--n0); font-weight: 600; }
.btn.primary:hover { filter: brightness(1.1); }
.btn.live { font-weight: 700; letter-spacing: .08em; color: var(--n300); }
.btn.live .live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--n500); }
.btn.live.is-live { background: var(--brand); border-color: var(--brand); color: var(--n0); }
.btn.live.is-live .live-dot { background: var(--n0); animation: pulse 1.4s infinite; }
.btn.live[disabled] { opacity: .5; cursor: not-allowed; }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }

.timecode { font-family: var(--mono); font-size: .85rem; min-width: 64px; text-align: right; color: var(--n200); }
.timecode.is-live { color: var(--brand); font-weight: 700; }

.timeline { flex: 1 1 auto; position: relative; padding: 10px 0; cursor: pointer; }
.timeline:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.timeline-track { position: relative; height: 6px; border-radius: 3px; background: var(--n700); }
.timeline-buffer { position: absolute; inset: 0; border-radius: 3px; background: linear-gradient(90deg, var(--n600), var(--n500)); }
.timeline-playhead { position: absolute; top: 50%; width: 14px; height: 14px; border-radius: 50%; background: var(--n0); transform: translate(-50%, -50%); box-shadow: 0 0 0 3px rgba(211,36,54,.35); z-index: 2; }
.timeline-markers { position: absolute; inset: 0; }
.marker { position: absolute; top: -5px; width: 3px; height: 16px; background: var(--accent); transform: translateX(-50%); border-radius: 2px; cursor: pointer; }
.marker:hover { background: var(--n0); }
.marker.is-clip { background: var(--success); }
.marker.is-stale { opacity: .3; }
.timeline-window { position: absolute; left: 0; top: -6px; font-family: var(--mono); font-size: .68rem; color: var(--n500); }

.layouts .layout-btn { padding: 6px 8px; }
.layouts .layout-btn.is-active { border-color: var(--brand); background: rgba(211,36,54,.18); }
.layouts .layout-btn svg { width: 22px; height: 15px; fill: currentColor; }

.preset-wrap { position: relative; }
.menu { position: absolute; bottom: calc(100% + 6px); left: 0; z-index: 20; min-width: 240px; padding: var(--s1); border-radius: var(--r-md); background: var(--n800); border: 1px solid var(--n700); box-shadow: 0 12px 32px rgba(0,0,0,.5); }
.menu button { display: flex; flex-direction: column; align-items: flex-start; width: 100%; gap: 2px; padding: 8px 10px; border: 0; background: transparent; color: var(--n100); border-radius: var(--r-sm); cursor: pointer; text-align: left; }
.menu button:hover { background: var(--n700); }
.menu button .sub { font-size: .74rem; color: var(--n400); }
.menu button[disabled] { opacity: .45; cursor: not-allowed; }

/* ---------- camera strip ---------- */
.camera-strip { display: flex; gap: var(--s2); padding: var(--s3) var(--s4); overflow-x: auto; background: var(--bg); border-top: 1px solid var(--n800); }
.cam-chip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: var(--r-full);
  border: 1px solid var(--n700); background: var(--n800); color: var(--n200); cursor: pointer; font-size: .85rem; font-weight: 500; white-space: nowrap;
}
.cam-chip:hover { background: var(--n700); }
.cam-chip.is-current { border-color: var(--brand); background: rgba(211,36,54,.18); color: var(--n0); }
.cam-chip.is-onscreen:not(.is-current) { border-color: var(--n500); }
.cam-chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
.cam-chip .dot.off { background: var(--n500); }
.cam-chip.is-off { color: var(--n400); }

/* ---------- side ---------- */
.side { grid-area: side; border-left: 1px solid var(--n800); background: var(--n900); overflow-y: auto; display: flex; flex-direction: column; }
.panel { padding: var(--s4) var(--s4) var(--s3); border-bottom: 1px solid var(--n800); }
.panel h2 { margin: 0 0 var(--s2); font-size: .95rem; font-weight: 600; display: flex; align-items: center; gap: var(--s2); }
.panel h2 .count { font-size: .74rem; font-weight: 600; color: var(--n300); background: var(--n800); border-radius: var(--r-full); padding: 0 8px; }
.panel.note p { font-size: .85rem; color: var(--n400); margin: var(--s2) 0 0; }
.panel .warn { color: var(--warning); }
.list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--s1); }
.list .empty { font-size: .85rem; color: var(--n500); }
.item { display: grid; grid-template-columns: 1fr auto; gap: var(--s1) var(--s2); align-items: center; padding: 8px 10px; border-radius: var(--r-sm); background: var(--n800); }
.item:hover { background: var(--n700); }
.item .t { font-weight: 600; font-size: .85rem; cursor: pointer; }
.item .m { grid-column: 1; font-size: .74rem; color: var(--n400); font-family: var(--mono); }
.item .ops { grid-row: 1 / span 2; display: flex; gap: 4px; }
.item .ops button { border: 0; background: transparent; color: var(--n400); cursor: pointer; padding: 4px; border-radius: 4px; }
.item .ops button:hover { color: var(--n0); background: var(--n600); }
.item .ops svg { width: 16px; height: 16px; fill: currentColor; }

/* ---------- sheets ---------- */
.sheet { position: fixed; inset: 0; z-index: 50; display: flex; align-items: center; justify-content: center; background: rgba(0,0,0,.6); padding: var(--s4); }
.sheet-card { width: min(560px, 100%); max-height: 90vh; overflow: auto; background: var(--n900); border: 1px solid var(--n700); border-radius: var(--r-lg); box-shadow: 0 24px 64px rgba(0,0,0,.6); }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: var(--s4) var(--s5); border-bottom: 1px solid var(--n800); }
.sheet-head h3 { margin: 0; font-size: 1.05rem; font-weight: 600; }
.picker-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s2); padding: var(--s4) var(--s5) var(--s5); }
.pick {
  display: flex; align-items: center; gap: var(--s3); padding: var(--s3); border-radius: var(--r-md); border: 1px solid var(--n700); background: var(--n800); color: var(--n100); cursor: pointer; text-align: left;
}
.pick:hover { background: var(--n700); }
.pick.is-current { border-color: var(--brand); }
.pick.is-off { opacity: .55; }
.pick .thumb { width: 56px; height: 36px; border-radius: 4px; background: linear-gradient(135deg, var(--n700), var(--n900)); flex: 0 0 auto; display: grid; place-items: center; font-size: .68rem; color: var(--n400); font-family: var(--mono); }
.pick .name { font-weight: 600; font-size: .85rem; }
.pick .st { font-size: .74rem; color: var(--n400); }
.clip-form, .demo-form { padding: var(--s4) var(--s5) var(--s5); display: flex; flex-direction: column; gap: var(--s3); }
.clip-form label, .demo-form label { display: flex; flex-direction: column; gap: 4px; font-size: .85rem; color: var(--n300); }
.clip-form input, .demo-form select { font: inherit; padding: 8px 10px; border-radius: var(--r-sm); border: 1px solid var(--n700); background: var(--n800); color: var(--n0); }
.clip-range { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.clip-range label { flex-direction: row; align-items: center; gap: var(--s2); }
.clip-range input { width: 70px; }
.clip-cams { display: flex; flex-wrap: wrap; gap: var(--s2); }
.clip-cams label { flex-direction: row; align-items: center; gap: 6px; padding: 6px 10px; border-radius: var(--r-full); background: var(--n800); border: 1px solid var(--n700); }
.hint { font-size: .8rem; color: var(--n500); margin: 0; padding: 0 var(--s5) var(--s4); }
.clip-form .hint { padding: 0; }
.sheet-actions { display: flex; justify-content: flex-end; }
.demo-form .row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }

.toast { position: fixed; left: 50%; bottom: 28px; transform: translateX(-50%); z-index: 60; max-width: min(560px, 90vw); padding: 10px 16px; border-radius: var(--r-md); background: var(--n800); color: var(--n0); border: 1px solid var(--n600); box-shadow: 0 12px 32px rgba(0,0,0,.5); font-size: .85rem; }
.toast code { color: var(--accent); word-break: break-all; }

/* ---------- responsive ---------- */
@media (max-width: 980px) {
  body { grid-template-columns: 1fr; grid-template-areas: "top" "player" "side"; }
  .side { border-left: 0; border-top: 1px solid var(--n800); }
  .topbar { grid-template-columns: auto 1fr auto; }
  .game-teams { font-size: 1.05rem; }
  .stage { max-height: none; }
  /* A 3- or 4-wide strip is unreadable on a phone; wrap it to two columns and
     let the strip take two rows. */
  .stage.layout-b3, .stage.layout-b4 { grid-template-columns: repeat(2, 1fr); }
  .stage.is-banner .pane:not(:first-child) { grid-row: auto; }
  .stage.is-banner .pane:first-child { grid-row: 1; }
  .stage.is-banner.is-flipped .pane:first-child { grid-row: 99; }
}
@media (max-width: 640px) {
  .league-name, .brand-text { display: none; }
  .actions-row { justify-content: center; }
  .stage.layout-pip .pane:nth-child(2) { width: 42%; min-width: 120px; right: var(--s2); bottom: var(--s2); }
  .stage.layout-pip .pane:nth-child(2)::after { display: none; }
}
