/* ═══════════════════════════════════════════════
   THEME — leagues override these variables
   ═══════════════════════════════════════════════ */
:root {
  --bg:          #0e0e14;
  --bg-card:     #16161f;
  --bg-panel:    #12121a;
  --border:      #23233a;
  --text:        #e8e8f0;
  --text-muted:  #888899;
  --team-a:      #e8445a;
  --team-b:      #29c4b0;
  --accent:      #e8445a;
  --cat-scoring: #f5a623;
  --cat-blocking:#7b6ff5;
  --cat-penalty: #f56342;
  --cat-power:   #e8445a;
  --cat-pack:    #3dc87a;
  --track-bg:    #1a1a2e;
  --track-band:  #22224a;
  --track-inner: #0b0b14;
  --font-display: Georgia, 'Times New Roman', serif;
  --font-body:    system-ui, -apple-system, sans-serif;
  --radius: 12px; --radius-sm: 7px;
  --shadow: 0 4px 24px rgba(0,0,0,0.5);
  --trans: 0.2s ease;
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body { background: var(--bg); color: var(--text); font-family: var(--font-body); font-size: 15px; line-height: 1.5; -webkit-font-smoothing: antialiased; }

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

header { padding: 12px 16px 10px; border-bottom: 1px solid var(--border); display: flex; flex-direction: column; gap: 8px; position: sticky; top: 0; background: var(--bg); z-index: 10; }
.header-top { display: flex; align-items: baseline; gap: 12px; }
.header-top h1 { font-family: var(--font-display); font-size: clamp(18px,3vw,24px); font-weight: 700; letter-spacing: -0.01em; }
.header-top .subtitle { font-size: 13px; color: var(--text-muted); opacity: 0.6; }

.filter-bar { display: flex; gap: 6px; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; }
.filter-bar::-webkit-scrollbar { display: none; }
.filter-btn { background: transparent; border: 1px solid var(--border); color: var(--text-muted); font-family: var(--font-body); font-size: 13px; font-weight: 600; letter-spacing: 0.02em; padding: 6px 14px; border-radius: 100px; cursor: pointer; transition: all var(--trans); opacity: 0.6; white-space: nowrap; flex-shrink: 0; }
.filter-btn:hover { opacity: 1; }
.filter-btn.active { opacity: 1; }
.filter-btn[data-cat="All"].active         { color: var(--text); background: var(--bg-card); }
.filter-btn[data-cat="Jamming"].active     { color: var(--cat-scoring);  border-color: var(--cat-scoring); }
.filter-btn[data-cat="Blocking"].active    { color: var(--cat-blocking); border-color: var(--cat-blocking); }
.filter-btn[data-cat="Penalties"].active   { color: var(--cat-penalty);  border-color: var(--cat-penalty); }
.filter-btn[data-cat="Power Jams"].active  { color: var(--cat-power);    border-color: var(--cat-power); }
.filter-btn[data-cat="Pack Rules"].active  { color: var(--cat-pack);     border-color: var(--cat-pack); }

.content { flex: 1; display: flex; overflow: hidden; }
.grid-area { flex: 1; overflow-y: auto; padding: 24px; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; align-items: start; }

.panel { width: 0; overflow: hidden; transition: width 0.35s cubic-bezier(0.4,0,0.2,1); border-left: 0px solid var(--border); background: var(--bg-panel); display: flex; flex-direction: column; }
.panel.open { width: min(420px,100vw); border-left-width: 1px; }
@media (max-width: 640px), (hover: none) and (pointer: coarse) {
  .panel.open { position: fixed; bottom:0; left:0; right:0; width:100%!important; height:70vh; border-left:none; border-top:1px solid var(--border); border-radius:16px 16px 0 0; z-index:20; }
  .grid { grid-template-columns: repeat(4, 1fr); gap: 6px; }
  .grid-area { padding: 12px; }
  .filter-btn { font-size: 10.5px; padding: 3px 8px; }
  .position-legend { gap: 12px; }
  .pos-item { font-size: 11px; gap: 5px; }
  .pos-dot { width: 18px; height: 18px; font-size: 9px; }
  .card-label { font-size: 7.5px; padding: 10px 4px 3px; }
  .ref-badge { font-size: 7.5px; padding: 2px 5px; }
  .dot { width: 5%; }
  .card-cat { font-size: 10px; }
  .card-title { font-size: 16px; }
  .card-teaser { font-size: 12px; }
}

/* ═══════════════════════════════════════════════
   DESKTOP HEADER — single row
   ═══════════════════════════════════════════════ */
@media (hover: hover) and (pointer: fine) {
  header { flex-direction: row; align-items: center; padding: 8px 16px; gap: 16px; }
  .position-legend { padding: 0; }
  .filter-bar { flex: 1; padding-bottom: 0; }
  /* Panel — tighter vertical spacing to keep content in viewport */
  .panel-header { padding:12px 20px 10px; }
  .panel-track-wrap { padding:8px 20px 4px; }
  .panel-track-box { width:90%; margin:0 auto; }
  .step-dots { margin-top:6px; }
  .panel-caption { padding:8px 20px 4px; }
  .panel-controls { padding:6px 20px 0; }
}

/* ═══════════════════════════════════════════════
   DESKTOP INLINE EXPANSION
   Selected card spans the full grid width and its
   body grows downward, pushing cards below it down.
   Side panel stays and shows the interactive steps.
   ═══════════════════════════════════════════════ */
@media (hover: hover) and (pointer: fine) {
  .card.selected { grid-column: 1 / -1 !important; order: -1; }
  /* JS rAF loop drives max-height so overflow is hidden until fully open */
  .card.selected .card-body { display: block !important; overflow: hidden; max-height: 0; padding: 0; }
}

/* ── Card ── */
.card {
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: hidden; cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, opacity 0.2s ease;
  display: flex; flex-direction: column;
  opacity: 0.65;
}
.card:hover { transform: translateY(-1px); box-shadow: var(--shadow); border-color: #33334a; opacity: 1; }
.card.selected {
  border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent);
  border-radius: var(--radius); opacity: 1;
  grid-column: span 2;
}

/* Track area */
.card-track { aspect-ratio: 5/3; position: relative; overflow: hidden; background: var(--track-inner); }

/* Thin category colour bar at top of every mini card */
.card-stripe { height: 3px; width: 100%; flex-shrink: 0; }

/* Tiny title overlay on mini cards */
.card-label {
  position: absolute; bottom: 0; left: 0; right: 0;
  padding: 18px 8px 6px;
  background: linear-gradient(transparent, rgba(0,0,0,0.72));
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: rgba(255,255,255,0.78);
  line-height: 1.25; pointer-events: none;
}
.card.selected .card-label { display: none; }

/* Card body hidden on mini, shown on selected */
.card-body { display: none; }
.card.selected .card-body { display: block; }
/* .cbi is the grid child that collapses to 0 on desktop */
.cbi { padding: 11px 13px 13px; overflow: hidden; min-height: 0; }

.card-cat { font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; margin-bottom: 4px; }
.card-title { font-family: var(--font-display); font-size: 20px; font-weight: 700; margin-bottom: 6px; }
.card-teaser { font-size: 14px; color: var(--text-muted); line-height: 1.45; }

/* ── Position legend ── */
.position-legend { display: flex; gap: 18px; align-items: center; padding: 4px 0 2px; }
.pos-item {
  position: relative; display: flex; align-items: center; gap: 7px;
  font-size: 14px; font-weight: 600; color: var(--text-muted); opacity: 0.75; cursor: default;
}
.pos-dot {
  width: 24px; height: 24px; border-radius: 50%;
  background: #2a2a42; border: 1.5px solid #4a4a6a;
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; flex-shrink: 0; color: #fff; font-weight: 700;
}
.pos-item::after {
  content: attr(data-tip); position: absolute; top: calc(100% + 6px); left: 0;
  background: #1e1e30; border: 1px solid var(--border); color: var(--text);
  font-size: 11px; font-weight: 400; padding: 5px 9px; border-radius: 6px;
  white-space: nowrap; pointer-events: none; opacity: 0; transform: translateY(-4px);
  transition: opacity 0.15s, transform 0.15s; z-index: 100;
}
.pos-item:hover::after { opacity: 1; transform: translateY(0); }

/* ── CSS Track ──
   Container is 100% × 100% of .card-track (aspect-ratio 5/3).
   All child positions use % of this container — scale-independent.
   Oval band: outer ellipse 86%×80% centered, inner cutout 52%×48% centered.
   Dot left/top values below are % of the container, measured to oval midline.
── */
.track { position: relative; width: 100%; height: 100%; background: var(--track-inner); }
.track-oval  { position:absolute; left:7%;  top:10%; width:86%; height:80%; background:var(--track-band);  border-radius:50%; }
.track-surface { position:absolute; left:7%; top:10%; width:86%; height:80%; border-radius:50%; box-shadow: inset 0 0 0 10% var(--track-bg); }
.track-inner-oval { position:absolute; left:24%; top:26%; width:52%; height:48%; background:var(--track-inner); border-radius:50%; }
.track-midline { position:absolute; left:15%; top:17%; width:70%; height:66%; border-radius:50%; border:1px dashed rgba(255,255,255,0.05); }
.track-zone { position:absolute; left:28%; top:22%; width:44%; height:56%; border-radius:50%; border:1.5px dashed var(--cat-pack); opacity:0; animation:zone-pulse 3s ease-in-out infinite; }

/* ── Dots ──
   transform:translate(-50%,-50%) centres each dot on its left/top point.
   All animation keyframes also include this translate so the centering holds.
── */
.dot { position:absolute; width:7%; aspect-ratio:1/1; border-radius:50%; transform:translate(-50%,-50%); }
.dot-a { background: var(--team-a); }
.dot-b { background: var(--team-b); }
.dot-jammer::after { display:none; }
.dot-box { left:4%!important; top:10%!important; animation:box-pulse 2s ease-in-out infinite!important; }

.ref-badge { position:absolute; bottom:4%; right:3%; background:rgba(0,0,0,0.5); border-radius:4px; padding:3px 7px; font-size:10px; font-weight:700; letter-spacing:0.06em; color:rgba(255,255,255,0.55); text-transform:uppercase; pointer-events:none; }

/* ── Panel ── */
.panel-inner { display:flex; flex-direction:column; height:100%; overflow-y:auto; }
.panel-header { padding:20px 20px 14px; border-bottom:1px solid var(--border); display:flex; align-items:flex-start; gap:10px; flex-shrink:0; }
.panel-header-text { flex:1; }
.panel-cat { font-size:10px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; margin-bottom:6px; }
.panel-title { font-family:var(--font-display); font-size:clamp(18px,4vw,22px); font-weight:700; letter-spacing:-0.02em; }
.close-btn { background:var(--bg-card); border:1px solid var(--border); color:var(--text-muted); width:30px; height:30px; border-radius:8px; cursor:pointer; font-size:14px; display:flex; align-items:center; justify-content:center; flex-shrink:0; transition:all var(--trans); }
.close-btn:hover { color:var(--text); }
.panel-track-wrap { padding:16px 20px 8px; flex-shrink:0; }
.panel-track-box { background:var(--track-inner); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; aspect-ratio:5/3; position:relative; }
.step-dots { display:flex; gap:6px; padding:0 20px; margin-top:10px; flex-shrink:0; }
.panel-track-box.paused * { animation-play-state: paused !important; }

.step-dot { height:3px; flex:1; background:var(--border); border-radius:2px; transition:background 0.3s,opacity 0.3s; cursor:pointer; }
.step-dot.done   { background:var(--accent); opacity:0.5; }
.step-dot.active { background:var(--accent); opacity:1; }
.panel-caption { padding:14px 20px 6px; flex-shrink:0; }
.step-num { font-size:10px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--text-muted); opacity:0.5; margin-bottom:6px; }
.caption-text { font-size:15px; line-height:1.55; min-height:48px; }
.panel-controls { display:flex; gap:8px; padding:10px 20px 0; flex-shrink:0; }
.ctrl-btn { background:var(--bg-card); border:1px solid var(--border); color:var(--text); font-family:var(--font-body); font-size:12px; font-weight:600; padding:7px 14px; border-radius:100px; cursor:pointer; transition:all var(--trans); }
.ctrl-btn:hover { border-color:#444; }
.ctrl-btn.primary { background:var(--accent); border-color:var(--accent); color:#fff; }
.ctrl-btn.primary:hover { opacity:0.88; }
.ctrl-btn:disabled { opacity:0.3; cursor:default; }
.legend { display:flex; gap:14px; padding:10px 20px 4px; flex-wrap:wrap; flex-shrink:0; }
.legend-item { display:flex; align-items:center; gap:6px; font-size:11px; color:var(--text-muted); opacity:0.55; }
.legend-dot { width:10px; height:10px; border-radius:50%; flex-shrink:0; }
.ref-signal-box { margin:10px 20px 4px; flex-shrink:0; }
.ref-signal-label { font-size:10px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--text-muted); opacity:0.5; margin-bottom:8px; }
.ref-signal-wrap { display:flex; gap:14px; align-items:center; }
.ref-signal-svg { width:72px; height:84px; flex-shrink:0; border-radius:8px; border:1px solid var(--border); }
.ref-signal-desc { font-size:12px; line-height:1.5; color:var(--text-muted); opacity:0.65; }
.why-box { margin:12px 20px 20px; background:var(--bg-card); border:1px solid var(--border); border-left:3px solid var(--accent); border-radius:0 var(--radius-sm) var(--radius-sm) 0; padding:12px 14px; flex-shrink:0; }
.why-label { font-size:10px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; margin-bottom:5px; opacity:0.8; }
.why-text { font-size:13px; line-height:1.5; color:var(--text-muted); opacity:0.65; }
.empty { grid-column:1/-1; text-align:center; padding:60px 20px; color:var(--text-muted); opacity:0.4; font-size:14px; }

@keyframes fade-in { from{opacity:0;transform:translateY(4px)} to{opacity:1;transform:translateY(0)} }
.caption-text.animate { animation:fade-in 0.3s ease forwards; }

/* ═══════════════════════════════════════════════
   DOT ANIMATIONS
   All left/top values are % of the .track container.
   Each keyframe ends with translate(-50%,-50%) to keep
   dot centred on the coordinate point.
   The oval midline passes through approximately:
     left-mid   16%, 50%
     top-mid    50%,  8%
     right-mid  84%, 50%
     bottom-mid 50%, 92%
   ═══════════════════════════════════════════════ */

/* Jammer B: full clockwise lap starting bottom-left */
@keyframes lap-b {
  0%   { left:18%; top:61%; transform:translate(-50%,-50%); }
  10%  { left:26%; top:73%; transform:translate(-50%,-50%); }
  20%  { left:50%; top:82%; transform:translate(-50%,-50%); }
  30%  { left:74%; top:73%; transform:translate(-50%,-50%); }
  40%  { left:84%; top:50%; transform:translate(-50%,-50%); }
  50%  { left:74%; top:27%; transform:translate(-50%,-50%); }
  60%  { left:50%; top:18%; transform:translate(-50%,-50%); }
  70%  { left:26%; top:27%; transform:translate(-50%,-50%); }
  80%  { left:18%; top:39%; transform:translate(-50%,-50%); }
  90%  { left:16%; top:50%; transform:translate(-50%,-50%); }
  100% { left:18%; top:61%; transform:translate(-50%,-50%); }
}

/* Jammer A: full clockwise lap starting top-right (half-lap offset) */
@keyframes lap-t {
  0%   { left:82%; top:39%; transform:translate(-50%,-50%); }
  10%  { left:74%; top:27%; transform:translate(-50%,-50%); }
  20%  { left:50%; top:18%; transform:translate(-50%,-50%); }
  30%  { left:26%; top:27%; transform:translate(-50%,-50%); }
  40%  { left:18%; top:39%; transform:translate(-50%,-50%); }
  50%  { left:18%; top:61%; transform:translate(-50%,-50%); }
  60%  { left:26%; top:73%; transform:translate(-50%,-50%); }
  70%  { left:50%; top:82%; transform:translate(-50%,-50%); }
  80%  { left:74%; top:73%; transform:translate(-50%,-50%); }
  90%  { left:82%; top:61%; transform:translate(-50%,-50%); }
  100% { left:82%; top:39%; transform:translate(-50%,-50%); }
}

/* Jammer approaches wall from left then bounces back */
@keyframes approach-b {
  0%   { left:18%; top:61%; transform:translate(-50%,-50%); }
  35%  { left:24%; top:29%; transform:translate(-50%,-50%); }
  50%  { left:30%; top:24%; transform:translate(-50%,-50%); }
  65%  { left:24%; top:29%; transform:translate(-50%,-50%); }
  82%  { left:16%; top:44%; transform:translate(-50%,-50%); }
  100% { left:18%; top:61%; transform:translate(-50%,-50%); }
}

/* Penalty box pulse — dot stays at fixed position */
@keyframes box-pulse {
  0%,100% { transform:translate(-50%,-50%) scale(1);   opacity:0.2; }
  50%     { transform:translate(-50%,-50%) scale(1.6); opacity:0.9; }
}

/* Blocker sent to penalty box — fades only (position handled inline) */
@keyframes to-box { 0%,8%{opacity:1} 28%,70%{opacity:0.1} 90%{opacity:0.6} 100%{opacity:1} }

/* Wall blockers micro-lean */
@keyframes wall-lean {
  0%,100% { transform:translate(-50%,-50%); }
  40%     { transform:translate(calc(-50% + 2px),-50%); }
  65%     { transform:translate(calc(-50% - 1px),-50%); }
}

/* Pack blockers shuffle */
@keyframes shuffle-a {
  0%,100% { transform:translate(-50%,-50%); }
  30%     { transform:translate(calc(-50% + 3px),calc(-50% - 2px)); }
  65%     { transform:translate(calc(-50% - 2px),calc(-50% + 2px)); }
}
@keyframes shuffle-b {
  0%,100% { transform:translate(-50%,-50%); }
  40%     { transform:translate(calc(-50% - 3px),calc(-50% + 2px)); }
  70%     { transform:translate(calc(-50% + 2px),calc(-50% - 2px)); }
}

/* Engagement zone pulse */
@keyframes zone-pulse { 0%,100%{opacity:0} 50%{opacity:0.35} }

/* Scoring +1 flash — mini card only, timed to jammer passing each blocker */
.score-pip { position:absolute; transform:translateX(-50%); font-size:10px; font-weight:900; color:var(--team-b); text-shadow:0 0 8px rgba(41,196,176,0.7); pointer-events:none; opacity:0; animation:score-flash 5s ease-in-out infinite; }
@keyframes score-flash {
  0%,38%,100% { opacity:0; transform:translateX(-50%) translateY(0); }
  52%,68%     { opacity:1; transform:translateX(-50%) translateY(-5px); }
  85%         { opacity:0; transform:translateX(-50%) translateY(-9px); }
}

/* Apex arc dashes flow along the path to show jump direction */
@keyframes dash-flow {
  from { stroke-dashoffset: 9; }
  to   { stroke-dashoffset: 0; }
}

/* Tripod brace: rocks side-to-side (skating backward, reading the jammer) */
@keyframes brace-rock {
  0%,100% { transform:translate(-50%,-50%); }
  25%     { transform:translate(calc(-50% + 4px),calc(-50% - 2px)); }
  75%     { transform:translate(calc(-50% - 4px),calc(-50% + 2px)); }
}

/* Apex jump: 8 frames tracing a smooth arc over the inner boundary.
   Takeoff from back-left of pack, arcs through the inner oval, lands front-right.
   scale() grows at peak to suggest airborne height; opacity dips slightly mid-air. */
@keyframes apex-arc {
  0%   { left:18%; top:61%; transform:translate(-50%,-50%) scale(1);    opacity:1;   }
  12%  { left:20%; top:50%; transform:translate(-50%,-50%) scale(1.1);  opacity:1;   }
  25%  { left:22%; top:38%; transform:translate(-50%,-50%) scale(1.35); opacity:0.9; }
  37%  { left:28%; top:28%; transform:translate(-50%,-50%) scale(1.55); opacity:0.8; }
  50%  { left:38%; top:22%; transform:translate(-50%,-50%) scale(1.55); opacity:0.8; }
  62%  { left:50%; top:20%; transform:translate(-50%,-50%) scale(1.3);  opacity:0.9; }
  75%  { left:60%; top:23%; transform:translate(-50%,-50%) scale(1.1);  opacity:1;   }
  87%  { left:68%; top:27%; transform:translate(-50%,-50%) scale(1);    opacity:1;   }
  100% { left:18%; top:61%; transform:translate(-50%,-50%) scale(1);    opacity:1;   }
}
