/* MLB Player Dashboard — Phase 1 styles.
   Scoped under #mlb-player-dashboard so nothing leaks into NBA/NFL views. */

/* When the dashboard is active, hide the workbench chrome declaratively so
   refresh/deep-link to /mlb/player/<slug> wins the race against the
   workbench scaffold builder. */
body.mlb-dashboard-active #workbench-columns,
body.mlb-dashboard-active #your-parlay-column,
body.mlb-dashboard-active #suggested-legs-column,
body.mlb-dashboard-active #schedule-container,
body.mlb-dashboard-active #sidebar,
body.mlb-dashboard-active #betting-slip {
  display: none !important;
}

#mlb-player-dashboard {
  width: 100%;
  padding: 8px 16px 40px;
  box-sizing: border-box;
}

/* On phones, drop the wrapper's left/right gutter so every card spans
   edge-to-edge. The cards keep their own border + 12px corner radius —
   that's the card identity, just hugging the screen edges instead of
   sitting inside a 16px gutter. Top/bottom padding stays so the header
   doesn't jam against the back-bar above it. */
@media (max-width: 1000px) {
  #mlb-player-dashboard {
    padding-left: 0;
    padding-right: 0;
  }
}

/* Clickable player names in dashboard cards (teammates, opposing players). */
.mlb-dash-player-link {
  color: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: color 120ms ease;
}
.mlb-dash-player-link:hover {
  color: #67e8f9;
  text-decoration: underline;
}

.mlb-dash-root {
  max-width: 1440px;
  margin: 0 auto;
}

/* ─────────── Header ─────────── */
.mlb-dash-header {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px 20px 16px;
  margin-bottom: 20px;
  background: linear-gradient(135deg, rgba(34, 211, 238, 0.06), rgba(255, 255, 255, 0.03) 60%);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.03);
}

/* Top bar inside the header card — holds the back link above the main
   identity + matchup row so they never overlap. */
.mlb-dash-topbar {
  display: flex;
  justify-content: flex-start;
}

/* Main content row: avatar | identity | snapshot | matchup. */
.mlb-dash-mainrow {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

/* Back link — plain teal text at the top-left of the header card. */
.mlb-dash-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px;
  background: transparent;
  border: none;
  color: #00F5D4;
  font-size: 0.78rem;
  font-weight: 600;
  cursor: pointer;
  transition: color 120ms ease, transform 120ms ease;
}
.mlb-dash-back:hover {
  color: #00D3BD;
  transform: translateX(-1px);
}
.mlb-dash-back:active { transform: translateX(-1px) scale(0.97); }

.mlb-dash-avatar {
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%, rgba(34, 211, 238, 0.18), rgba(15, 23, 42, 0.6) 70%);
  border: 1px solid rgba(255, 255, 255, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
}

.mlb-dash-avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  display: block;
}

/* When falling back to a team logo, don't crop — contain inside the circle */
.mlb-dash-avatar-img.is-fallback {
  object-fit: contain;
  padding: 10px;
}

.mlb-dash-identity {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
  padding-right: 8px;
}

.mlb-dash-player-name {
  font-size: 2rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: #f8fafc;
  line-height: 1.1;
}

.mlb-dash-player-meta {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.mlb-dash-chip {
  display: inline-flex;
  align-items: center;
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(148, 163, 184, 0.14);
  color: #cbd5e1;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  border: 1px solid rgba(255, 255, 255, 0.04);
}

.mlb-dash-chip-team {
  background: rgba(34, 211, 238, 0.14);
  color: #67e8f9;
  border-color: rgba(34, 211, 238, 0.28);
  gap: 6px;
}

.mlb-dash-chip-logo {
  width: 18px;
  height: 18px;
  object-fit: contain;
  display: inline-block;
  vertical-align: middle;
}

.mlb-dash-chip-hand {
  background: rgba(192, 132, 252, 0.14);
  color: #d8b4fe;
  border-color: rgba(192, 132, 252, 0.28);
}

/* Header stat snapshot — sits between identity block and matchup card.
   BA / SLG / ISO / EV / B% for the current matchup bucket (vs-SP-hand
   if known, else season). Height-matches the matchup card via
   `align-self: stretch` on both. */
.mlb-dash-snapshot {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 10px 18px;
  background: rgba(15, 23, 42, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 10px;
  align-self: stretch;
  min-width: 280px;
}

.mlb-snap-head {
  display: flex; align-items: baseline;
  margin-bottom: 6px;
}
.mlb-snap-head-label {
  font-size: 0.62rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted, #64748b);
}

.mlb-snap-cells {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}
/* Pitcher snapshot has 6 stats (ERA / WHIP / K/9 / BB/9 / IP / GS)
   instead of the batter's 5, so widen the grid to keep everything
   on a single row. */
.mlb-pdash-snapshot .mlb-snap-cells {
  grid-template-columns: repeat(6, 1fr);
}
.mlb-snap-cell {
  display: flex; flex-direction: column; align-items: center;
  justify-content: center;
  padding: 2px 10px;
  min-width: 0;
}
.mlb-snap-cell + .mlb-snap-cell {
  border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.mlb-snap-cell-label {
  font-size: 0.58rem; font-weight: 700;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted, #64748b);
  margin-bottom: 2px;
}
.mlb-snap-cell-val {
  font-size: 0.95rem; font-weight: 700;
  color: #f1f5f9;
  font-variant-numeric: tabular-nums;
}

.mlb-snap-green-3 { color: #86efac; }
.mlb-snap-green-2 { color: #a7f3d0; }
.mlb-snap-green-1 { color: #d9f99d; }
.mlb-snap-red-2   { color: #fca5a5; }
.mlb-snap-red-3   { color: #f87171; }

/* Matchup card — right side of header. 4-column grid with uppercase
   labels above each value and subtle vertical dividers between columns. */
.mlb-dash-matchup-strip {
  display: flex;
  align-items: stretch;
  margin-left: auto;
  background: rgba(15, 23, 42, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.07);
  border-radius: 10px;
  overflow: hidden;
  align-self: stretch;
}

.mlb-dash-ms-col {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 10px 18px;
  min-width: 0;
}

.mlb-dash-ms-col + .mlb-dash-ms-col {
  border-left: 1px solid rgba(255, 255, 255, 0.08);
}

.mlb-dash-ms-label {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--muted, #64748b);
  text-transform: uppercase;
}

.mlb-dash-ms-val {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.88rem;
  font-weight: 700;
  color: #f1f5f9;
  white-space: nowrap;
}

.mlb-dash-ms-team {
  font-weight: 700;
  color: #f8fafc;
  letter-spacing: 0.02em;
}

.mlb-dash-ms-logo {
  width: 18px;
  height: 18px;
  object-fit: contain;
  flex-shrink: 0;
}

.mlb-dash-ms-hand {
  color: #d8b4fe;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 1px 6px;
  border-radius: 4px;
  background: rgba(192, 132, 252, 0.12);
  border: 1px solid rgba(192, 132, 252, 0.25);
}

@media (max-width: 1000px) {
  .mlb-dash-header { gap: 8px; padding: 10px 14px 14px; }
  .mlb-dash-mainrow { gap: 12px; }
  .mlb-dash-player-name { font-size: 1.3rem; }
  .mlb-dash-avatar { width: 52px; height: 52px; }
  /* Hide the BA/SLG/ISO/EV/B% snapshot card on mobile so the avatar +
     identity (PHOTO + name + team/hand chips) sit on the same row as
     the OPP / PITCHER / FIRST PITCH / VENUE matchup strip. The snapshot
     duplicates info that's available deeper in the dashboard cards
     below — fine to drop on narrow screens. */
  .mlb-dash-snapshot { display: none !important; }
  /* Let the matchup strip sit beside the identity rather than forcing
     its own full-width row. Sized to content (flex: 0 1 auto) so the
     last cell ("Venue") doesn't stretch into empty space — the strip
     hugs its columns and `margin-left: auto` pins it to the right edge.
     Can still shrink if the row gets cramped. */
  .mlb-dash-matchup-strip { margin-left: auto; flex: 0 1 auto; min-width: 0; }
  .mlb-dash-ms-col { padding: 6px 10px; }
  .mlb-dash-ms-label { font-size: 0.55rem; }
  .mlb-dash-ms-val { font-size: 0.78rem; }
}

/* ─────────── Grid layout ─────────── */
/* 5-column grid lets us give the Prop Performance chart 3/5 (60 %) and
   the denser Matchup card 2/5 (40 %) — the old 3-col split forced
   66 % / 33 % which made the chart too wide and the stat tables
   cramped. Same ratio flipped for Q3 (2/5) vs Q4 (3/5). */
.mlb-dash-grid {
  display: grid;
  /* 10 tracks so we can do exact 50/50 splits (5+5) for the Q4/Q5 row
     while still supporting 40/60 (4+6) and 60/40 elsewhere. */
  grid-template-columns: repeat(20, 1fr);
  gap: 16px;
}

@media (max-width: 1100px) {
  .mlb-dash-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
}

@media (max-width: 1000px) {
  .mlb-dash-grid { grid-template-columns: 1fr; gap: 12px; }
}

.mlb-dash-card {
  position: relative;
  background: var(--card-bg, #111827);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  padding: 16px 16px 14px;
  display: flex;
  flex-direction: column;
  min-height: 240px;
  overflow: hidden;
  transition: transform 140ms ease, box-shadow 140ms ease, border-color 140ms ease;
}

/* Left accent strip removed — cleaner card edges. The `--card-accent`
   variable is still referenced by some card-titles below, so it stays
   defined by the `.mlb-dash-accent-*` helpers, just no longer painted. */

.mlb-dash-card:hover {
  transform: translateY(-1px);
  border-color: rgba(255, 255, 255, 0.14);
  box-shadow: 0 6px 20px -8px rgba(0, 0, 0, 0.45);
}

/* Accent colors per card */
.mlb-dash-accent-cyan   { --card-accent: #22d3ee; }
.mlb-dash-accent-purple { --card-accent: #c084fc; }
.mlb-dash-accent-blue   { --card-accent: #60a5fa; }
.mlb-dash-accent-orange { --card-accent: #fb923c; }
.mlb-dash-accent-yellow { --card-accent: #fbbf24; }
.mlb-dash-accent-green  { --card-accent: #4ade80; }
.mlb-dash-accent-red    { --card-accent: #f87171; }

/* Grid spans (within the 5-col grid). */
.mlb-dash-card-full { grid-column: 1 / -1; }   /* full row */
.mlb-dash-card-two  { grid-column: span 12; }  /* 60 % — wider half */
.mlb-dash-card-one  { grid-column: span 8; }   /* 40 % — narrower half */

/* Row-specific spans:
   - Q3 (Batting Order) is now full-width on its own row so all 15
     columns fit comfortably.
   - Q4 (Exit Velocity) and Q5 (Season Splits) share the next row 50/50. */
#mlb-dash-q3 { grid-column: 1 / -1; }
#mlb-dash-q4 { grid-column: span 10; }
#mlb-dash-q5 { grid-column: span 10; }
#mlb-dash-q6 { grid-column: span 10; }
#mlb-dash-q7 { grid-column: span 10; }

@media (max-width: 1100px) {
  .mlb-dash-card-full { grid-column: 1 / -1; }
  .mlb-dash-card-two  { grid-column: 1 / -1; }
  .mlb-dash-card-one  { grid-column: 1 / -1; }
  /* ID-scoped overrides also need to stack at narrow widths so the
     row doesn't become two thin half-cards. */
  #mlb-dash-q3,
  #mlb-dash-q4,
  #mlb-dash-q5 { grid-column: 1 / -1; }
}

@media (max-width: 1000px) {
  .mlb-dash-card-full,
  .mlb-dash-card-two,
  .mlb-dash-card-one { grid-column: auto; }
  /* The default `#mlb-dash-q4`/`q5`/`q6`/`q7` rules above use
     `grid-column: span 10`. Inside the single-column (1fr) mobile grid,
     `span 10` creates 9 implicit zero-width tracks and the card's
     placement can land partially outside the explicit column — so the
     visible card width ends up narrower than the row. Force every Q
     section to span the full row by ID so each card claims the entire
     viewport width on mobile. ID specificity is required to beat the
     ID-scoped defaults; class-only rules above don't. */
  #mlb-dash-q1,
  #mlb-dash-q2,
  #mlb-dash-q3,
  #mlb-dash-q4,
  #mlb-dash-q5,
  #mlb-dash-q6,
  #mlb-dash-q7 {
    grid-column: 1 / -1;
  }
}

.mlb-dash-card-title {
  font-size: 0.74rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--card-accent, #94a3b8);
  margin: 0 0 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  opacity: 0.9;
}

.mlb-dash-card-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 200px;
}

.mlb-dash-spinner,
.mlb-dash-coming-soon,
.mlb-dash-empty,
.mlb-dash-error {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted, #94a3b8);
  font-size: 0.88rem;
  font-style: italic;
}

.mlb-dash-error { color: #fca5a5; }

/* ─────────── Shimmer skeletons ─────────── */
/* GPU-composited shimmer: static base block + translateX pseudo-element.
   Cheaper than animating background-position (which forces a CPU repaint
   each frame on every block). */
@keyframes mlbShimmer {
  100% { transform: translateX(100%); }
}

.mlb-skel-block {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.045);
}

.mlb-skel-block::after {
  content: '';
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(
    90deg,
    transparent 0,
    rgba(255, 255, 255, 0.06) 50%,
    transparent 100%
  );
  animation: mlbShimmer 1.5s ease-in-out infinite;
  will-change: transform;
}

.mlb-skel { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; }

.mlb-skel-q1 .mlb-skel-chart { flex: 1 1 auto; height: auto; min-height: 200px; }

.mlb-skel-row-tabs {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.mlb-skel-chip    { width: 78px; height: 24px; border-radius: 6px; }
.mlb-skel-chip-sm { width: 42px; height: 22px; border-radius: 999px; }

.mlb-skel-row-lg { height: 56px; }
.mlb-skel-row-md { height: 40px; }
.mlb-skel-row-sm { height: 28px; }

.mlb-skel-chart  { height: 220px; border-radius: 8px; }

.mlb-skel-q3 { display: block; }
.mlb-skel-q3-col { display: flex; flex-direction: column; gap: 6px; }

.mlb-skel-q4-stats {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
}
.mlb-skel-stat { height: 46px; }

@media (max-width: 1320px) {
  .mlb-skel-q4-stats { grid-template-columns: repeat(3, 1fr); }
}

.mlb-skel-q67 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  justify-items: center;
  padding-top: 8px;
}
.mlb-skel-canvas    { width: 100%; max-width: 400px; aspect-ratio: 1;       border-radius: 8px; }
.mlb-skel-canvas-sm { width: 100%; max-width: 300px; aspect-ratio: 300/340; border-radius: 8px; }

@media (max-width: 1000px) {
  .mlb-skel-q3 { grid-template-columns: 1fr; }
  /* .mlb-skel-q67 stays 2-column on mobile — Spray Chart and Strike Zone
     keep their side-by-side fields. The skeletons must match the loaded
     content (.q6-dual / .q7-dual also stay 2-column at this breakpoint),
     otherwise the layout shifts when data lands. */
  .mlb-skel-q4-stats { grid-template-columns: repeat(3, 1fr); }
}

/* ─────────── Q1 specifics ─────────── */
/* Single-row prop picker — scrolls horizontally when the prop list
   doesn't fit. Chip styling unchanged, just no wrap. */
.q1-tabs {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  margin-bottom: 10px;
  padding-bottom: 4px;  /* leave room for any scrollbar */
}
.q1-tabs::-webkit-scrollbar { height: 4px; }
.q1-tabs::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.12);
  border-radius: 2px;
}
.q1-tab { flex-shrink: 0; }

.q1-tab {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--text-soft, #cbd5e1);
  padding: 4px 10px;
  border-radius: 6px;
  font-size: 0.78rem;
  cursor: pointer;
  transition: all 80ms ease;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.q1-tab:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.15);
}
.q1-tab.active {
  background: rgba(0, 245, 212, 0.12);
  border-color: #00F5D4;
  color: #00F5D4;
}
.q1-tab .tab-line {
  font-weight: 600;
  opacity: 0.75;
  font-size: 0.7rem;
}

/* Stat cards row — replaces the old footer (Last X: Y/Z + window chips).
   Each card is also the window picker; the active card has a teal outline
   on top of the green/red hit-rate fill. */
.q1-stat-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 10px;
}

.q1-stat-card {
  font: inherit;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 7px 4px 8px;
  text-align: center;
  cursor: pointer;
  color: #ffffff;
  transition: filter 0.15s, border-color 0.15s, transform 0.15s;
}
.q1-stat-card:hover { filter: brightness(1.08); }
.q1-stat-card:active { transform: scale(0.98); }
.q1-stat-card.active { border-color: #00F5D4; box-shadow: 0 0 0 1px #00F5D4 inset; }

.q1-stat-card--green   { background: #15803d; }
.q1-stat-card--red     { background: #b91c1c; }
.q1-stat-card--neutral { background: rgba(255, 255, 255, 0.05); color: #94a3b8; }

.q1-stat-card__label {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  opacity: 0.85;
  margin-bottom: 3px;
}
.q1-stat-card__count {
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.92rem;
  font-weight: 700;
  line-height: 1.1;
}
.q1-stat-card__pct {
  font-size: 0.74rem;
  font-weight: 600;
  opacity: 0.92;
  margin-top: 2px;
}


/* Wrap is a flex column — the holder grows into the remaining height
   between the prop tabs above and the footer below. `min-height: 0` on
   every level is the classic fix for `overflow: auto` inside a flex
   column: without it, a tall child's intrinsic height pushes the chain
   open and the card grows instead of scrolling. */
.q1-chart-wrap {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

/* Outer holder caps at the remaining card-body height and scrolls
   vertically when many rows are rendered. Card width already matches
   chart width (Q1 is span-2). */
.q1-chart-holder {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Inner box sized by renderChart() based on row count — its height
   determines how tall the canvas can grow before the holder scrolls. */
.q1-chart-inner {
  position: relative;
  width: 100%;
  min-height: 100%;
}

/* Mobile: the card-body's min-height (200px) is mostly consumed by the
   tabs + prop panel + stat-cards row, leaving the flex chart-holder with
   ~0 effective height — Chart.js renders into a 0-tall canvas and the
   bars never appear. Force a real minimum on the holder so Chart.js has
   a sized container to draw into. */
@media (max-width: 1000px) {
  .q1-chart-holder { min-height: 200px; }
}

/* Prop panel — sits between the prop tabs and the chart. Acts as a remote
   control for the matching workbench .suggested-prop: line stepper, add to
   parlay, and grade ring all bind back to the source card. */
.q1-prop-panel {
  --ring-color: #94a3b8;
  display: flex;
  align-items: stretch;
  gap: 14px;
  padding: 10px 12px;
  margin: 6px 0 10px;
  background: rgba(15, 23, 42, 0.5);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 10px;
}

/* Hit-rate fallback path uses the original tier vocab (excellent / good /
   average / poor / bad). Model-probability path uses the popup's vocab
   (great / good / neutral / poor / bad) with the same colors as the
   central-circle border in the breakdown popup so the ring color and
   the popup color always agree. */
.q1-prop-panel[data-tier="excellent"] { --ring-color: #00F5D4; }
.q1-prop-panel[data-tier="great"]     { --ring-color: #4ade80; }
.q1-prop-panel[data-tier="good"]      { --ring-color: #a3e635; }
.q1-prop-panel[data-tier="neutral"]   { --ring-color: #fbbf24; }
.q1-prop-panel[data-tier="average"]   { --ring-color: #fbbf24; }
.q1-prop-panel[data-tier="poor"]      { --ring-color: #f97316; }
.q1-prop-panel[data-tier="bad"]       { --ring-color: #ef4444; }

.q1-pp-main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
}

.q1-pp-line-row {
  display: flex;
  align-items: center;
  gap: 8px;
}

.q1-pp-step {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: rgba(0, 245, 212, 0.08);
  border: 1px solid rgba(0, 245, 212, 0.35);
  color: #00F5D4;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  transition: background 0.15s, border-color 0.15s;
}
.q1-pp-step:hover {
  background: rgba(0, 245, 212, 0.14);
  border-color: rgba(0, 245, 212, 0.55);
}
.q1-pp-step:active { transform: scale(0.95); }
.q1-pp-step:disabled { opacity: 0.45; cursor: default; }
.q1-pp-step:disabled:hover {
  background: rgba(0, 245, 212, 0.08);
  border-color: rgba(0, 245, 212, 0.35);
}

.q1-pp-line-pill {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 6px 14px;
  background: rgba(15, 23, 42, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 999px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.92rem;
  font-weight: 600;
}
.q1-pp-line-val { color: #f8fafc; }
.q1-pp-line-sep { color: #475569; }
.q1-pp-odds-val { color: #f8fafc; }

.q1-pp-add {
  display: block;
  width: 100%;
  padding: 8px 0;
  background: rgba(0, 245, 212, 0.08);
  color: #00F5D4;
  border: 1px solid rgba(0, 245, 212, 0.35);
  border-radius: 6px;
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.q1-pp-add:hover {
  background: rgba(0, 245, 212, 0.14);
  border-color: rgba(0, 245, 212, 0.55);
}
.q1-pp-add:disabled { opacity: 0.45; cursor: default; }
.q1-pp-add:disabled:hover {
  background: rgba(0, 245, 212, 0.08);
  border-color: rgba(0, 245, 212, 0.35);
}
.q1-pp-add.in-parlay {
  background: rgba(74, 222, 128, 0.12);
  color: #4ade80;
  border-color: rgba(74, 222, 128, 0.35);
}
.q1-pp-add.in-parlay:hover { background: rgba(74, 222, 128, 0.22); }

.q1-pp-rating {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 64px;
  border-radius: 8px;
  transition: background 0.15s, transform 0.15s;
}
.q1-pp-rating.is-clickable { cursor: pointer; }
.q1-pp-rating.is-clickable:hover { background: rgba(255, 255, 255, 0.04); }
.q1-pp-rating.is-clickable:active { transform: scale(0.97); }
.q1-pp-rating.is-clickable:focus-visible {
  outline: 2px solid var(--ring-color);
  outline-offset: 2px;
}

.q1-pp-rating-ring {
  --pct: 0;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  position: relative;
  background:
    conic-gradient(var(--ring-color) calc(var(--pct) * 1%), rgba(255, 255, 255, 0.08) 0);
  display: flex;
  align-items: center;
  justify-content: center;
}
.q1-pp-rating-ring::before {
  content: '';
  position: absolute;
  inset: 4px;
  border-radius: 50%;
  background: var(--card-bg, #111827);
}
.q1-pp-rating-num {
  position: relative;
  z-index: 1;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--ring-color);
}
.q1-pp-rating-label {
  font-size: 0.6rem;
  font-weight: 600;
  color: #94a3b8;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ─────────── Q2 Matchup ─────────── */
.q2-wrap {
  display: flex;
  flex-direction: column;
  gap: 18px;
}

/* Matchup card title strip — "MATCHUP" label on the left, season pills
   anchored on the right. Flex override of the default card-title block. */
.mlb-dash-card-title.q2-card-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  text-transform: none;  /* title text keeps its styled uppercase via child */
  letter-spacing: 0;
}
.q2-card-title-text {
  font-size: .74rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--card-accent, #94a3b8);
}

/* ───────── Q2 Weather mode layout overrides ─────────
   The shared weather panel (game-detail tab) puts Ball Flight + score
   in the right column and Conditions Detail full-width below. For Q2's
   narrower card we swap: Conditions Detail fills the right column, and
   Ball Flight + score become a single bottom row. Reordering of the
   conditions cards is pure CSS `order` based on the render order. */

/* Bottom row — "Ball Flight Model" header + 4-across card grid that
   includes the hitting-conditions score so every cell shares height. */
.q2-weather-layout .q2-wx-bottom-row {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.q2-weather-layout .q2-wx-bottom-row > .wx-panel-title {
  margin: 0;
}
.q2-weather-layout .q2-wx-bottom-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  align-items: stretch;
}
.q2-weather-layout .q2-wx-bottom-cards > * {
  /* Force all 4 cards (3 carry + 1 score) to the same height. */
  min-height: 0;
  align-self: stretch;
}
/* Compact ball-flight cards in the dashboard weather tab — trims padding
   + value size so the four cards don't tower next to the field diagram.
   The flex column with justify-content: center vertically centers the
   stacked text (TO LF / value / breakdown) since the carry-cards stretch
   to match the pitcher-score card's height. */
.q2-weather-layout .q2-wx-bottom-cards .wx-carry-card {
  padding: 4px 12px 0px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.q2-weather-layout .q2-wx-bottom-cards .wx-carry-dir { margin-bottom: 1px; }
.q2-weather-layout .q2-wx-bottom-cards .wx-carry-val {
  font-size: 18px;
  margin-bottom: 0px;
}
.q2-weather-layout .q2-wx-bottom-cards .wx-carry-breakdown {
  font-size: 9px;
  margin-bottom: 0;
}

/* Pull the Q2 card's bottom edge closer to the ball-flight row when the
   weather tab is active. Default Q2 (matchup mode) keeps the 14px footer. */
#mlb-dash-q2:has(.q2-weather-layout) { padding-bottom: 6px; }

/* Slightly taller Q1 — gives the chart bars a touch more room without
   widening the card. Adds 4px to the default 14px bottom padding. */
#mlb-dash-q1 { padding-bottom: 18px; }

/* Tighten the gap between the field SVG and the venue caption by ~20%. */
.q2-weather-layout .wx-split-left { gap: 0px; }
.q2-weather-layout .wx-split-left .wx-venue-caption { padding-top: 0px; }
/* Pull the Wind / Forecast / Humidity labels 2px closer to the top edge —
   game-detail base sets `padding: 4px 0 8px` on the strip; tighten just
   the dashboard. */
.q2-weather-layout .wx-split-left .wh-strip { padding-top: 0; }

/* Conditions title above the right-column grid — compact and aligned
   with the left strip's Wind/Forecast/Humidity labels (which sit
   ~10px from the top of their card). */
.q2-weather-layout .wx-split-right > .wx-physics {
  margin-top: 0;
  padding-top: 0;
}
.q2-weather-layout .wx-split-right > .wx-physics > .wx-panel-title {
  margin: 0 0 12px;
  /* Match the strip's Wind / Forecast / Humidity labels on the left. */
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #94a3b8;
}
/* Give each conditions card a subtle rounded tile look so the 3x3 grid
   reads as discrete cards instead of floating text. */
.q2-weather-layout .wx-physics-grid .wx-phys-card {
  background: rgba(148, 163, 184, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 10px;
  padding: 10px 12px;
}

/* Conditions cards: 3-col grid with CSS `order` remapping the render
   sequence into the matchup-relevant order (winds on top, env in the
   middle, humidity + sun glare at the bottom). The 6px gap (vs the
   game-detail page's 8px) buys back ~4px of total height across the
   three rows so Q2's Weather tab matches the matchup-tab height and
   doesn't push Q1 taller in the same dashboard row. */
.q2-weather-layout .wx-physics-grid {
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.q2-weather-layout .wx-physics-grid > :nth-child(1) { order: 5; } /* Air Density */
.q2-weather-layout .wx-physics-grid > :nth-child(2) { order: 2; } /* Wind → CF */
.q2-weather-layout .wx-physics-grid > :nth-child(3) { order: 4; } /* Crosswind */
.q2-weather-layout .wx-physics-grid > :nth-child(4) { order: 6; } /* Density Altitude */
.q2-weather-layout .wx-physics-grid > :nth-child(5) { order: 1; } /* Wind → LF */
.q2-weather-layout .wx-physics-grid > :nth-child(6) { order: 3; } /* Wind → RF */
.q2-weather-layout .wx-physics-grid > :nth-child(7) { order: 7; } /* Humidity / Spin */
.q2-weather-layout .wx-physics-grid > :nth-child(8) { order: 8; } /* Sun Glare */

/* Pin Q2's card height so toggling between Stats and Pitch Mix modes
   doesn't reshuffle the grid row. Stats mode's 3 tables + legend is
   the taller of the two layouts; pitch-mix fills the same space (with
   empty room at the bottom if the table's short). */
#mlb-dash-q2 { min-height: 564px; }

/* Right side of the title row holds mode + season pill groups. */
.q2-title-right {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* Stats ⇄ Pitch Mix mode toggle — segmented control. */
.q2-mode-pills {
  display: inline-flex;
  gap: 2px;
  background: rgba(148, 163, 184, .06);
  border: 1px solid rgba(255, 255, 255, .06);
  border-radius: 999px;
  padding: 2px;
}
.q2-mode-pill {
  background: transparent;
  border: none;
  color: #94a3b8;
  font-size: .65rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  cursor: pointer;
  letter-spacing: .04em;
  text-transform: uppercase;
  transition: color 120ms ease, background-color 120ms ease;
}
.q2-mode-pill:hover:not(.is-active) { color: #e2e8f0; }
.q2-mode-pill.is-active {
  color: #0a1628;
  background: rgba(0, 211, 189, 0.75);
}

/* ───────── Pitch Mix mode ───────── */
.q2-pm { display: flex; flex-direction: column; gap: 16px; }
.q2-pm-header { display: flex; flex-direction: column; gap: 2px; }
.q2-pm-matchup-title {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
  font-size: 1.05rem; font-weight: 700; color: #f8fafc;
}
.q2-pm-name { color: #f8fafc; }
.q2-pm-vs {
  color: #64748b; font-weight: 600;
  font-size: .82rem; text-transform: lowercase;
  letter-spacing: .04em;
  margin: 0 2px;
}
/* L/R/S palette mirrors the batting-order hand chips. */
.q2-pm-hand {
  font-size: .62rem; font-weight: 700;
  letter-spacing: .4px;
  padding: 2px 7px; border-radius: 4px;
}
.q2-pm-hand-r { background: rgba(239,68,68,.14);  color: #fca5a5; }
.q2-pm-hand-l { background: rgba(79,143,247,.14); color: #7dd3fc; }
.q2-pm-hand-s { background: rgba(168,85,247,.14); color: #d8b4fe; }

.q2-pm-rating {
  background: rgba(148, 163, 184, .05);
  border: 1px solid rgba(255, 255, 255, .06);
  border-radius: 10px;
  padding: 14px 16px;
}
.q2-pm-rating-row {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 10px;
}
.q2-pm-rating-label {
  font-size: .7rem; font-weight: 700; letter-spacing: 1px;
  color: #94a3b8; text-transform: uppercase;
}
.q2-pm-rating-score { display: flex; align-items: baseline; gap: 6px; }
.q2-pm-rating-num { font-size: 1.5rem; font-weight: 700; color: #f8fafc; }
.q2-pm-rating-denom { font-size: .78rem; color: #64748b; }
.q2-pm-rating-tag {
  margin-left: 10px; font-size: .8rem; font-weight: 700; color: #86efac;
}
.q2-pm-rating.q2-pm-red-2 .q2-pm-rating-tag,
.q2-pm-rating.q2-pm-red-3 .q2-pm-rating-tag { color: #fca5a5; }
.q2-pm-rating.q2-pm-green-3 .q2-pm-rating-tag { color: #bbf7d0; }
.q2-pm-rating-track {
  position: relative; height: 8px; border-radius: 999px;
  background: rgba(255, 255, 255, .06); overflow: hidden;
}
.q2-pm-rating-fill {
  position: absolute; inset: 0 auto 0 0;
  background: linear-gradient(90deg, rgba(34, 197, 94, .6), rgba(34, 197, 94, .95));
  border-radius: 999px; transition: width 200ms ease;
}
.q2-pm-rating.q2-pm-red-2 .q2-pm-rating-fill,
.q2-pm-rating.q2-pm-red-3 .q2-pm-rating-fill {
  background: linear-gradient(90deg, rgba(239, 68, 68, .6), rgba(239, 68, 68, .95));
}

.q2-pm-table {
  width: 100%; border-collapse: collapse; font-size: .82rem;
}
.q2-pm-table th {
  text-align: left; padding: 8px 8px;
  font-size: .6rem; font-weight: 700; letter-spacing: .6px;
  color: #64748b; text-transform: uppercase;
  border-bottom: 1px solid rgba(255, 255, 255, .06);
}
.q2-pm-table td {
  padding: 10px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, .04);
  color: #cbd5e1; vertical-align: middle;
}
.q2-pm-table tr:last-child td { border-bottom: none; }

.q2-pm-pitch { font-weight: 600; color: #f1f5f9; }
.q2-pm-usage { color: #94a3b8; font-size: .78rem; }
.q2-pm-velo  { color: #64748b; font-size: .66rem; margin-top: 2px; }

.q2-pm-batter, .q2-pm-pitcher { font-weight: 700; width: 72px; }
.q2-pm-batter.is-pos, .q2-pm-pitcher.is-pos { color: #86efac; }
.q2-pm-batter.is-neg, .q2-pm-pitcher.is-neg { color: #fca5a5; }
.q2-pm-batter-head { text-align: right !important; }
.q2-pm-batter { text-align: right; }
.q2-pm-ab {
  font-size: .62rem; font-weight: 600;
  color: #64748b; margin-top: 2px; letter-spacing: .3px;
}

.q2-pm-edge-head { text-align: center !important; color: #64748b; }
.q2-pm-edge-cell { padding: 0 8px; }
.q2-pm-edge-track {
  position: relative; height: 22px;
  background: rgba(255, 255, 255, .04); border-radius: 4px;
}
.q2-pm-edge-track::before {
  content: ''; position: absolute; left: 50%; top: 2px; bottom: 2px;
  width: 1px; background: rgba(255, 255, 255, .14);
}
.q2-pm-edge-fill {
  position: absolute; top: 0; bottom: 0;
  border-radius: 3px;
  display: flex; align-items: center;
}
.q2-pm-edge-batter {
  left: 50%;
  background: linear-gradient(90deg, rgba(34, 197, 94, .35), rgba(34, 197, 94, .85));
  justify-content: flex-end; padding-right: 6px;
}
.q2-pm-edge-pitcher {
  right: 50%;
  background: linear-gradient(90deg, rgba(239, 68, 68, .85), rgba(239, 68, 68, .35));
  justify-content: flex-start; padding-left: 6px;
}
.q2-pm-edge-val {
  font-size: .72rem; font-weight: 700;
  color: #f8fafc; white-space: nowrap; pointer-events: none;
}

.q2-pm-empty {
  text-align: center; padding: 20px;
  color: #64748b; font-style: italic;
}
.q2-pm-foot {
  font-size: .7rem; color: #64748b; line-height: 1.55;
}

/* Compact season pill group — lives inline in the card title now. */
.q2-season-pills {
  display: inline-flex;
  gap: 2px;
  background: rgba(148, 163, 184, .06);
  border: 1px solid rgba(255, 255, 255, .06);
  border-radius: 999px;
  padding: 2px;
}
.q2-season-pill {
  background: transparent;
  border: none;
  color: #94a3b8;
  font-size: .7rem;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  cursor: pointer;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  transition: color 120ms ease, background-color 120ms ease;
}
.q2-season-pill:hover:not(.is-active) { color: #e2e8f0; }
.q2-season-pill.is-active {
  color: #0a1628;
  background: rgba(0, 211, 189, 0.75);
}

/* Color legend at the bottom of the matchup card — single-sentence reminder
   that the whole card reads from the batter's perspective. */
.q2-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  font-size: 0.7rem;
  color: #94a3b8;
  letter-spacing: 0.02em;
}
.q2-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.q2-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.q2-legend-green { background: rgba(34, 197, 94, 0.75); }
.q2-legend-red   { background: rgba(239, 68, 68, 0.75); }

/* Dim matchup body during a season-pill reload — skip the card title so
   the pills stay interactive. */
.mlb-dash-card-body.q2-is-loading .q2-wrap {
  opacity: 0.45;
  transition: opacity 120ms ease;
  pointer-events: none;
}

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

.q2-section-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.q2-section-title {
  font-size: 0.95rem;
  font-weight: 700;
  color: #f8fafc;
  letter-spacing: 0.01em;
}

.q2-hand {
  color: #c084fc;
  font-size: 0.74rem;
  font-weight: 700;
  margin-left: 2px;
  letter-spacing: 0.03em;
}

.q2-vs-lbl {
  color: var(--muted, #94a3b8);
  font-weight: 500;
  font-size: 0.88rem;
  margin: 0 4px;
}

.q2-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
}

.q2-table th {
  color: var(--muted, #94a3b8);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.66rem;
  padding: 5px 8px;
  text-align: center;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.q2-table th:first-child {
  text-align: left;
}

.q2-table td {
  padding: 6px 8px;
  text-align: center;
  font-variant-numeric: tabular-nums;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

.q2-cell-label {
  text-align: left !important;
  font-weight: 600;
  color: var(--text-soft, #cbd5e1);
  white-space: nowrap;
}

.q2-empty {
  color: var(--muted, #94a3b8);
  font-style: italic;
  font-size: 0.82rem;
  padding: 8px 0;
}

.q2-empty-cell {
  color: var(--muted, #94a3b8);
  font-style: italic;
  text-align: center !important;
}

/* Color tiers — same ramp as Q5 */
.q2-table .q2-green-3 { background: rgba(34, 197, 94, 0.30); color: #bbf7d0; font-weight: 700; }
.q2-table .q2-green-2 { background: rgba(34, 197, 94, 0.18); color: #d9f99d; }
.q2-table .q2-green-1 { background: rgba(34, 197, 94, 0.09); color: #ecfccb; }
.q2-table .q2-red-1   { background: rgba(239, 68, 68, 0.10); color: #fed7aa; }
.q2-table .q2-red-2   { background: rgba(239, 68, 68, 0.20); color: #fca5a5; }
.q2-table .q2-red-3   { background: rgba(239, 68, 68, 0.32); color: #fecaca; font-weight: 700; }

/* ─────────── Q3 Batting Order ─────────── */
.q3-wrap {
  display: block;
}

/* The team-code label is now baked into the card title (e.g. "LAD
   Batting Order"), so the inner label is redundant — hide it. */
.q3-team-header { display: none; }

/* Stat-mode toggle (Season ↔ vs <Hand>HP) — sits inline next to the
   team-prefixed card title. Compact pill pair styled neutrally so it
   doesn't compete with the cyan title text. */
.q3-mode-toggle {
  display: inline-flex;
  margin-left: 12px;
  vertical-align: middle;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.q3-mode-toggle-pitcher {
  margin-left: 10px;
}
.q3-mode-pill {
  appearance: none;
  background: transparent;
  border: none;
  padding: 3px 10px;
  color: var(--muted, #94a3b8);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}
.q3-mode-pill:hover { color: #f1f5f9; }
.q3-mode-pill.is-active {
  background: rgba(34, 211, 238, 0.18);
  color: #67e8f9;
}
.q3-mode-pill + .q3-mode-pill {
  border-left: 1px solid rgba(255, 255, 255, 0.08);
}

/* Q3's title row uses the same 10:9 column split as the table beneath
   it (10 batter columns, 9 vs-Opp-SP columns), so each title block
   sits over its own section's leftmost column. Scoped to Q3 so the
   other cards' titles aren't affected. The pitcher dashboard's Q5
   card (`#mlb-pdash-q5`) reuses the same q3-* classes for an inverted
   version of this card and shares the layout. */
#mlb-dash-q3 .mlb-dash-card-title,
#mlb-pdash-q5 .mlb-dash-card-title {
  display: flex;
  align-items: center;
}
/* The 10-batter / 9-pitcher column count would suggest a 10:9 flex
   split, but the Player column is much wider than any numeric column
   (avatar + stacked names + bat-side pill), so the actual visual
   boundary in the table sits further right than 10/19. Tuned by eye
   to land the vs-block just above the AB column. */
#mlb-dash-q3 .q3-card-title-text,
#mlb-pdash-q5 .q3-card-title-text {
  flex: 11;
  text-align: left;
}
.q3-card-vs {
  flex: 9;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--muted, #cbd5e1);
  text-transform: none;
  letter-spacing: 0;
}

.q3-lineup-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.q3-lineup-table th {
  font-weight: 600;
  color: var(--muted, #94a3b8);
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 0.78rem;
}

/* Numeric columns are right-aligned in the cells (standard for stats);
   align their headers the same way so each label sits directly above
   its values. The first two columns (# and Player) keep the default
   left alignment. */
.q3-lineup-table thead th:nth-child(n+3) {
  text-align: right;
}

.q3-lineup-table td {
  padding: 6px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  font-variant-numeric: tabular-nums;
}

.q3-row-highlight {
  background: rgba(34, 211, 238, 0.10);
}

.q3-cell-ord {
  width: 24px;
  color: var(--muted, #94a3b8);
  font-weight: 700;
}

.q3-cell-name {
  font-weight: 600;
  /* Shrink to content so the name doesn't absorb all the remaining
     horizontal space when the table is wider than its other columns
     need. The trailing 1% width is a CSS idiom that resolves to
     "content width" in tables once paired with white-space:nowrap. */
  width: 1%;
  white-space: nowrap;
  padding-right: 16px;
}

/* Avatar + stacked-name layout inside the player cell. */
.q3-name-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  color: inherit;
  vertical-align: middle;
}
.q3-name-link.mlb-dash-player-link:hover .q3-name-last,
.q3-name-link.mlb-dash-player-link:hover .q3-name-first {
  color: #67e8f9;
}
.q3-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center top;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.q3-avatar.is-fallback {
  object-fit: contain;
  padding: 5px;
}
.q3-name-text {
  display: inline-flex;
  flex-direction: column;
  line-height: 1.15;
}
.q3-name-first {
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--muted, #cbd5e1);
}
.q3-name-last {
  font-size: 1rem;
  font-weight: 700;
  color: #f1f5f9;
}

.q3-cell-pos {
  color: var(--muted, #94a3b8);
  font-size: 0.72rem;
  font-weight: 500;
  margin-left: 6px;
}

/* Bat-side pill next to the batter's name. Color-coded so a quick scan
   shows handedness distribution: cyan = right, pink = left, purple = switch. */
.q3-cell-side {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 7px;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
  border: 1px solid transparent;
}
.q3-cell-side.q3-side-r {
  color: #7dd3fc;
  background: rgba(56, 189, 248, 0.12);
  border-color: rgba(56, 189, 248, 0.28);
}
.q3-cell-side.q3-side-l {
  color: #fda4af;
  background: rgba(244, 114, 182, 0.12);
  border-color: rgba(244, 114, 182, 0.30);
}
.q3-cell-side.q3-side-s {
  color: #d8b4fe;
  background: rgba(192, 132, 252, 0.14);
  border-color: rgba(192, 132, 252, 0.30);
}

/* Pitcher hand badge inside the "vs <Opp SP>" group header — same
   palette as the bat-side pills for consistency. */
.q3-vs-hand {
  display: inline-block;
  margin-left: 6px;
  padding: 2px 7px;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
  border: 1px solid transparent;
}
.q3-vs-hand.q3-vs-hand-r {
  color: #7dd3fc;
  background: rgba(56, 189, 248, 0.12);
  border-color: rgba(56, 189, 248, 0.28);
}
.q3-vs-hand.q3-vs-hand-l {
  color: #fda4af;
  background: rgba(244, 114, 182, 0.12);
  border-color: rgba(244, 114, 182, 0.30);
}

.q3-cell-hr {
  text-align: right;
  font-weight: 600;
  color: #fbbf24;
  width: 36px;
}

.q3-cell-avg, .q3-cell-slg, .q3-cell-ops, .q3-cell-iso, .q3-cell-ev, .q3-cell-brl {
  text-align: right;
  width: 48px;
}

/* Hits / at-bats fraction next to the slash line. Slightly muted since
   it's context, not the headline number. */
.q3-cell-hab {
  text-align: right;
  width: 64px;
  color: var(--muted, #94a3b8);
  font-variant-numeric: tabular-nums;
}

/* "vs Opp SP" column group — three numeric columns (AVG/OPS/K%) with a
   subtle left divider so the eye separates the season slash line from
   the pitcher-matchup metrics. */
.q3-vs-group {
  text-align: center;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted, #94a3b8);
  border-left: 1px solid rgba(255, 255, 255, 0.06);
  padding-bottom: 2px !important;
}
.q3-th-vs {
  border-left: none;
}
.q3-th-vs:first-of-type {
  border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.q3-cell-vs {
  text-align: right;
  width: 48px;
  color: #cbd5e1;
}
/* AB now leads the vs-Opp-SP group, so the left-divider moves here. */
.q3-cell-vs-ab {
  border-left: 1px solid rgba(255, 255, 255, 0.06);
  width: 44px;
  color: var(--muted, #94a3b8);
  font-variant-numeric: tabular-nums;
}

.q3-empty {
  text-align: center !important;
  color: var(--muted, #94a3b8);
  font-style: italic;
  padding: 12px !important;
}

.q3-pitcher-row {
  margin-top: 8px;
  padding: 6px 8px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 6px;
  font-size: 0.78rem;
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.q3-sp-badge {
  background: #7c3aed;
  color: #fff;
  padding: 1px 6px;
  border-radius: 3px;
  font-weight: 700;
  font-size: 0.66rem;
  letter-spacing: 0.04em;
}

.q3-sp-name {
  font-weight: 600;
  flex: 1 1 auto;
}

.q3-sp-stat {
  color: var(--muted, #94a3b8);
  font-variant-numeric: tabular-nums;
  font-size: 0.72rem;
}

/* ─────────── Q4 Exit Velocity ─────────── */
.q4-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: 100%;
}

/* "Pitch:" label next to the pitch-type checkbox group. */
.q4-filter-label {
  font-size: 11px;
  font-weight: 700;
  color: #94a3b8;
  text-transform: uppercase;
  letter-spacing: .06em;
  align-self: center;
}

/* Pitch chip in the dedicated Pitch column. */
.q4-cell-pitch {
  display: inline-block;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 600;
  color: #cbd5e1;
  background: rgba(148,163,184,.08);
  border: 1px solid rgba(255,255,255,.06);
  border-radius: 4px;
  text-transform: none;
  letter-spacing: 0;
}
.q4-cell-pitch-empty {
  color: #64748b;
  background: transparent;
  border-color: transparent;
}

.q4-summary {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
}

@media (max-width: 1000px) {
  .q4-summary { grid-template-columns: repeat(3, 1fr); }
}

/* Q4 now sits next to Q3 as a span-2 card and has room to grow — give
   event rows and stat boxes a bit more breathing room. */
#mlb-dash-q4 .q4-stat {
  padding: 10px 6px;
}
#mlb-dash-q4 .q4-stat-value {
  font-size: 1.15rem;
}
#mlb-dash-q4 .q4-table-wrap {
  max-height: 360px;
}

.q4-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 6px 4px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 6px;
}

.q4-stat-label {
  font-size: 0.66rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted, #94a3b8);
  margin-bottom: 2px;
}

.q4-stat-value {
  font-size: 1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: #f8fafc;
}

.q4-unit {
  font-size: 0.68rem;
  font-weight: 400;
  color: var(--muted, #94a3b8);
  margin-left: 2px;
}

.q4-table-wrap {
  overflow-y: auto;
  max-height: 280px;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 6px;
}

.q4-events-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.76rem;
}

.q4-events-table th {
  position: sticky;
  top: 0;
  background: var(--card-bg, #111827);
  font-weight: 600;
  color: var(--muted, #94a3b8);
  text-align: left;
  padding: 6px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: 0.66rem;
}

.q4-events-table td {
  padding: 4px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  font-variant-numeric: tabular-nums;
}

.q4-cell-date { color: var(--muted, #94a3b8); width: 48px; }
.q4-cell-pitcher { font-weight: 500; }
.q4-cell-hand {
  color: var(--muted, #94a3b8);
  font-size: 0.68rem;
  margin-left: 4px;
}
.q4-cell-result {
  color: var(--text-soft, #cbd5e1);
  text-transform: capitalize;
}
.q4-cell-ev.q4-ev-hard { color: #4ade80; font-weight: 700; }
.q4-cell-ev.q4-ev-soft { color: var(--text-soft, #cbd5e1); }
.q4-cell-la, .q4-cell-dist { text-align: right; }

/* ─────────── Q5 Team Splits ─────────── */
.q5-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.q5-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.q5-title {
  font-size: 0.86rem;
  font-weight: 700;
  color: #f8fafc;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.q5-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.q5-tab {
  background: none;
  border: none;
  color: var(--muted, #94a3b8);
  padding: 6px 14px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  cursor: pointer;
  position: relative;
  text-transform: uppercase;
  transition: color 80ms ease;
}

.q5-tab:hover {
  color: var(--text, #e2e8f0);
}

.q5-tab.active {
  color: #22d3ee;
}

.q5-tab.active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: #22d3ee;
}

.q5-table-wrap {
  overflow-x: auto;
  max-height: 420px;
  overflow-y: auto;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 6px;
}

.q5-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
}

.q5-table th {
  position: sticky;
  top: 0;
  background: var(--card-bg, #111827);
  color: var(--muted, #94a3b8);
  font-weight: 600;
  text-align: right;
  padding: 6px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  text-transform: uppercase;
  font-size: 0.66rem;
  letter-spacing: 0.04em;
}

.q5-table th.q5-cell-player,
.q5-table th.q5-cell-hab {
  text-align: left;
}

.q5-table td {
  padding: 5px 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.q5-cell-player {
  text-align: left !important;
  font-weight: 500;
  white-space: nowrap;
}

.q5-cell-hab {
  text-align: left !important;
  color: var(--text-soft, #cbd5e1);
}

.q5-hand {
  color: var(--muted, #94a3b8);
  font-size: 0.68rem;
  margin-left: 6px;
  font-weight: 500;
}

/* Color tiers for stat cells — saturated green = strong, red = weak. */
.q5-table .q5-green-3 { background: rgba(34, 197, 94, 0.30); color: #bbf7d0; font-weight: 600; }
.q5-table .q5-green-2 { background: rgba(34, 197, 94, 0.18); color: #d9f99d; }
.q5-table .q5-green-1 { background: rgba(34, 197, 94, 0.09); color: #ecfccb; }
.q5-table .q5-red-1   { background: rgba(239, 68, 68, 0.10); color: #fed7aa; }
.q5-table .q5-red-2   { background: rgba(239, 68, 68, 0.20); color: #fca5a5; }
.q5-table .q5-red-3   { background: rgba(239, 68, 68, 0.32); color: #fecaca; font-weight: 600; }

/* ─────────── Shared filter bar (used by Q6 + Q7) ─────────── */
.q-filter-bar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.q-filter-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: 0.74rem;
  color: var(--text-soft, #cbd5e1);
}

.q-range-sel {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--text, #e2e8f0);
  padding: 3px 8px;
  border-radius: 4px;
  font-size: 0.74rem;
  cursor: pointer;
}

.q-range-sel:focus {
  outline: none;
  border-color: #22d3ee;
}

.q-cb-group {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  padding: 4px 8px;
  background: rgba(255, 255, 255, 0.03);
  border-radius: 4px;
}

.q-cb {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  user-select: none;
  padding: 2px 0;
  font-size: 0.72rem;
}

.q-cb input[type="checkbox"] {
  appearance: none;
  width: 11px;
  height: 11px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.04);
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
}

.q-cb input[type="checkbox"]:checked {
  background: #22d3ee;
  border-color: #22d3ee;
}

.q-cb input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 2px;
  top: -1px;
  width: 4px;
  height: 7px;
  border: solid #0f172a;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.q-cb-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  display: inline-block;
}

.q-sep {
  color: var(--muted, #94a3b8);
  opacity: 0.4;
  font-weight: 300;
  padding: 0 2px;
}

.q-reset-btn {
  margin-left: auto;
  background: rgba(239, 68, 68, 0.12);
  border: 1px solid rgba(239, 68, 68, 0.4);
  color: #fca5a5;
  padding: 3px 10px;
  border-radius: 4px;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 80ms ease;
}

.q-reset-btn:hover {
  background: rgba(239, 68, 68, 0.2);
  color: #fecaca;
}

/* ─────────── Q6 Spray Chart ─────────── */
.q6-wrap { display: flex; flex-direction: column; gap: 10px; position: relative; flex: 1; }

/* Title row hosts the section name + pitch-types dropdown + range
   selector + reset button. Strips the uppercase/letter-spacing
   inherited from .mlb-dash-card-title for the action controls. */
#mlb-dash-q6 .mlb-dash-card-title,
#mlb-dash-q7 .mlb-dash-card-title {
  display: flex;
  align-items: center;
  gap: 12px;
}
.q6-title-actions {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 500;
  font-size: 0.88rem;
}
.q6-title-actions .q-reset-btn {
  margin-left: 0;
  padding: 5px 14px;
  font-size: 0.86rem;
}
.q6-title-actions .q-range-sel {
  padding: 5px 10px;
  font-size: 0.86rem;
}

/* Bottom filter row — centered pill under the two charts. The
   `margin-top: auto` pushes it to the bottom of its flex parent
   (q6-wrap / q7-wrap), so the pill rows in Q6 and Q7 anchor to the
   bottom of each card and visually align across them. */
.q6-filter-bar-bottom {
  border-bottom: none;
  padding-top: 6px;
  display: flex;
  justify-content: center;
  margin-top: auto;
}
.q6-filter-pill {
  justify-content: center;
  font-size: 0.95rem;
  gap: 14px;
  padding: 10px 18px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  flex-wrap: nowrap;
}
.q6-filter-pill .q-sep {
  padding: 0 4px;
}


/* Pill chip — hides native checkbox, fills with --cb-color when active. */
.q-cb-pill {
  --cb-color: #22d3ee;
  font-size: 0.92rem;
  font-weight: 600;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--cb-color);
  color: var(--cb-color);
  background: transparent;
  cursor: pointer;
  user-select: none;
  opacity: 0.55;
  display: inline-flex;
  align-items: center;
  line-height: 1;
}
.q-cb-pill:hover { opacity: 0.85; }
.q-cb-pill.is-on {
  background: var(--cb-color);
  color: #0f172a;
  opacity: 1;
}
.q-cb-pill input[type="checkbox"] {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* Pitch types dropdown — styled to match the native All Games <select>
   sitting next to it. Click the button → popover of checkboxes. */
.q6-pitch-dd { position: relative; display: inline-flex; }
.q6-pitch-dd-btn {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--text, #e2e8f0);
  padding: 5px 10px;
  border-radius: 4px;
  font-size: 0.86rem;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  line-height: 1.2;
}
.q6-pitch-dd-btn:hover { border-color: rgba(255, 255, 255, 0.22); }
.q6-pitch-dd-count {
  color: var(--muted, #94a3b8);
  font-weight: 500;
  display: inline-block;
  min-width: 36px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.q6-pitch-dd-chev { font-size: 0.7rem; opacity: 0.7; }

/* Popover panel sits above the field — needs a higher stacking
   context than the canvas-wrap below it. We give the title row its
   own stacking context (z-index: 5) so any absolute child of the
   title can paint over the body content. */
#mlb-dash-q6 .mlb-dash-card-title,
#mlb-dash-q7 .mlb-dash-card-title {
  position: relative;
  z-index: 5;
}
.q6-pitch-dd-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 100;
  background: rgba(15, 23, 42, 0.98);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 6px;
  padding: 10px 14px;
  display: grid;
  grid-template-columns: repeat(2, max-content);
  gap: 8px 18px;
  min-width: 160px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
  font-size: 0.92rem;
}
.q6-pitch-dd-panel[hidden] { display: none; }

/* Pitcher's Mix toggle — sits in the title row alongside Pitch Types
   and All Games. Reuses the .q6-pitch-dd-btn base for consistent
   sizing; lights up cyan when active. */
.q6-pmix-toggle.is-on {
  background: #22d3ee;
  border-color: #22d3ee;
  color: #0f172a;
}

/* Range dropdown — same button styling (.q6-pitch-dd-btn) as pitch
   types. Panel below uses identical chrome but renders a single
   highlighted-current list of options. */
.q6-range-dd { position: relative; display: inline-flex; }
.q6-range-dd-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 100;
  background: rgba(15, 23, 42, 0.98);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 6px;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 130px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}
.q6-range-dd-panel[hidden] { display: none; }

/* Segmented season toggle. Absolute-positioned at the top-right of
   the body so it lines up with the player-name row (which is the
   first child of q6-dual). */
.q6-season-toggle {
  position: absolute;
  top: 0;
  right: 4px;
  z-index: 2;
  display: inline-flex;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  padding: 2px;
  gap: 2px;
  background: rgba(15, 23, 42, 0.55);
}
.q6-season-btn {
  background: transparent;
  border: 0;
  color: var(--muted, #94a3b8);
  padding: 4px 12px;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  border-radius: 999px;
  font-family: inherit;
  font-variant-numeric: tabular-nums;
  transition: background 80ms ease, color 80ms ease;
}
.q6-season-btn:hover { color: #f8fafc; }
.q6-season-btn.is-current {
  background: #22d3ee;
  color: #0f172a;
}
.q6-range-opt {
  background: transparent;
  border: 0;
  color: var(--text, #e2e8f0);
  padding: 6px 12px;
  text-align: left;
  font-size: 0.9rem;
  cursor: pointer;
  border-radius: 4px;
  font-family: inherit;
}
.q6-range-opt:hover { background: rgba(255, 255, 255, 0.08); }
.q6-range-opt.is-current {
  background: rgba(34, 211, 238, 0.15);
  color: #22d3ee;
  font-weight: 600;
}

.q6-pitch-dd-panel .q-cb {
  font-size: 0.92rem;
  gap: 8px;
  padding: 3px 0;
  min-width: 130px;
  display: inline-flex;
  align-items: center;
}
.q6-pitch-dd-panel .q-cb-name { flex: 1; }
.q6-pitch-dd-panel .q-cb-pct {
  margin-left: auto;
  color: var(--muted, #94a3b8);
  font-size: 0.85em;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.q6-pitch-dd-panel .q-cb input[type="checkbox"] {
  width: 15px;
  height: 15px;
}
.q6-pitch-dd-panel .q-cb input[type="checkbox"]:checked::after {
  left: 4px;
  top: 0px;
  width: 5px;
  height: 9px;
  border-width: 0 2px 2px 0;
}

.q6-header {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.q6-count {
  font-size: 0.82rem;
  color: var(--text-soft, #cbd5e1);
  font-weight: 500;
}

.q6-legend {
  display: flex;
  gap: 12px;
  font-size: 0.74rem;
  flex-wrap: wrap;
}

.q6-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--muted, #94a3b8);
}

.q6-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
}

.q6-dual {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
/* Spray Chart's two fields (e.g. season vs recent / vs LHP vs RHP) stay
   side-by-side on mobile too. The card's full-width row gives each chart
   roughly 50% of the viewport, which is still readable for a square
   spray plot — better than a stacked layout that doubles the scroll. */

.q6-chart-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
}
#mlb-dash-q6 .q6-chart-col > .q6-canvas-wrap {
  margin-top: -14px;
}

.q6-chart-label {
  font-size: 0.88rem;
  font-weight: 600;
  color: #f8fafc;
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 10px;
  width: 100%;
  max-width: 680px;
  padding-left: 4px;
}

.q6-avatar-wrap {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
}
.q6-avatar {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  object-fit: cover;
  display: block;
}
.q6-avatar.is-fallback {
  display: inline-block;
}
.q6-avatar-badge {
  position: absolute;
  bottom: -10px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(15, 23, 42, 0.95);
  color: #22d3ee;
  border: 1px solid #22d3ee;
  font-size: 0.58rem;
  font-weight: 700;
  padding: 1px 6px;
  border-radius: 999px;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
}

.q6-name-stack {
  display: inline-flex;
  flex-direction: column;
  line-height: 1.1;
  text-align: left;
}
.q6-name-first {
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--muted, #94a3b8);
}
.q6-name-last {
  font-size: 1.25rem;
  font-weight: 700;
  color: #f8fafc;
}
a.q6-name-stack { text-decoration: none; }
a.q6-name-stack:hover .q6-name-last { color: #22d3ee; }

.q6-chart-count {
  color: var(--muted, #94a3b8);
  font-weight: 600;
  font-size: 0.78rem;
  display: inline-block;
  min-width: 36px;
  text-align: center;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  font-variant-numeric: tabular-nums;
}

/* Spray-chart container — aspect tuned to the field's natural shape
   (the diamond is ~roughly 4:3 within its viewBox), so the SVG inside
   is cropped tight on the field with no wasted gutters. */
.q6-canvas-wrap {
  width: 100%;
  max-width: 680px;
  aspect-ratio: 640 / 545;
  position: relative;
  overflow: hidden;
}

/* Field background. Positioned to mimic the original SVG viewBox crop
   (viewBox 130 50 640 515, image at 0,0,900,540). Sits on its own GPU
   layer so dot redraws never invalidate or re-rasterize this image. */
.q6-bg-img {
  position: absolute;
  width: 140.625%;   /* 900 / 640 */
  height: 99.083%;   /* 540 / 545 */
  left: -20.3125%;   /* -130 / 640 */
  top: -0.917%;      /* -5 / 545 */
  pointer-events: none;
  user-select: none;
  display: block;
  will-change: transform;
  transform: translateZ(0);
  isolation: isolate;
}

/* All dots are box-shadows on this single 1×1 div. Toggling a filter
   sets one CSS property and triggers exactly one element repaint —
   no canvas, no SVG render tree, no per-element state changes.
   `border-radius: 50%` makes each shadow render as a circle. */
.q6-dots-shadow {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  border-radius: 50%;
  pointer-events: none;
  /* Promote so the shadow paint stays on its own GPU layer. */
  will-change: box-shadow;
  transform: translateZ(0);
}

.q6-empty-text {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.35);
  font-family: system-ui, sans-serif;
  font-size: 22px;
  pointer-events: none;
}

.q6-canvas { width: 100%; height: 100%; display: block; }

.q6-empty-chart {
  padding: 40px 10px;
}

.q6-summary {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  width: 100%;
  font-variant-numeric: tabular-nums;
}

/* One pill per result type — colored dot + label + count (or % when
   the user has toggled). Click any chip to flip count ↔ percentage.
   Chips for deactivated result filters are not rendered at all. */
.q6-sum-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.55);
  border: 1px solid var(--c);
  font-size: 0.78rem;
  line-height: 1;
  cursor: pointer;
  user-select: none;
  transition: background 80ms ease;
}
.q6-sum-pill:hover {
  background: rgba(15, 23, 42, 0.85);
}
.q6-sum-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--c);
  flex-shrink: 0;
}
.q6-sum-name {
  color: #f8fafc;
  font-weight: 600;
}
.q6-sum-val {
  color: rgba(248, 250, 252, 0.7);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* ─────────── Q7 Strike Zone ─────────── */
.q7-wrap {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
  position: relative;
}

.q7-dual {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
/* Strike Zone's two squares stay side-by-side on mobile — same reasoning
   as .q6-dual above. The squares scale with the column width and remain
   legible at half-viewport on a phone. */

.q7-chart-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: center;
}

.q7-col-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  max-width: 256px;
  gap: 10px;
}

.q7-chart-label {
  font-size: 0.88rem;
  font-weight: 600;
  color: #f8fafc;
  display: flex;
  align-items: flex-end;
  gap: 10px;
  min-width: 0;
}

.q7-view-toggle {
  display: inline-flex;
  gap: 2px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  padding: 2px;
}

.q7-vbtn {
  background: transparent;
  border: none;
  color: var(--muted, #94a3b8);
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.7rem;
  cursor: pointer;
  transition: all 80ms ease;
}

.q7-vbtn:hover { color: var(--text, #e2e8f0); }

.q7-vbtn.active {
  background: rgba(239, 68, 68, 0.18);
  color: #fca5a5;
  font-weight: 600;
}

.q7-canvas-wrap {
  width: 100%;
  max-width: 256px;
  aspect-ratio: 300 / 340;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.q7-canvas {
  width: 100%;
  height: 100%;
  display: block;
}

.q7-empty-chart {
  padding: 40px 10px;
}

/* Player-summary stat blocks under the heatmaps. Two stacked rows
   (batter + pitcher), each: small uppercase name, then a 13-col grid
   of header labels above a value row. */
.q7-stats-wrap {
  display: none; /* Hidden for now — markup still rendered, easy to flip back. */
  flex-direction: column;
  gap: 12px;
  padding: 4px 2px 0;
}
.q7-stats-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.q7-stats-name {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted, #94a3b8);
}
.q7-stats-grid {
  display: grid;
  grid-template-columns: repeat(13, 1fr);
  background: rgba(255, 255, 255, 0.02);
  border-radius: 6px;
  padding: 6px 4px;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.q7-stats-h {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: rgba(148, 163, 184, 0.85);
  padding: 2px 4px;
}
.q7-stats-v {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text, #e2e8f0);
  padding: 4px 4px 2px;
}

.q7-legend {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: center;
  font-size: 0.72rem;
  color: var(--muted, #94a3b8);
}

.q7-scale-bar {
  width: 120px;
  height: 10px;
  border-radius: 2px;
  background: linear-gradient(90deg,
    rgba(59,130,246,0.75) 0%,
    rgba(147,90,148,0.75) 50%,
    rgba(255,80,50,0.75) 100%);
}

.q7-scale-label {
  font-size: 0.7rem;
}

.q7-zone-label {
  margin-left: auto;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted, #94a3b8);
}

/* Q3 "vs Opp SP" tier coloring — mirrors Q2's batter-POV scheme.
   Green = favorable matchup for the batter, red = favorable for the
   pitcher. Scoped to the lineup table so it can't bleed into other Q3
   cells. */
.q3-lineup-table .q3-green-3 { background: rgba(34, 197, 94, 0.30); color: #bbf7d0; font-weight: 700; }
.q3-lineup-table .q3-green-2 { background: rgba(34, 197, 94, 0.18); color: #d9f99d; }
.q3-lineup-table .q3-green-1 { background: rgba(34, 197, 94, 0.09); color: #ecfccb; }
.q3-lineup-table .q3-red-1   { background: rgba(239, 68, 68, 0.10); color: #fed7aa; }
.q3-lineup-table .q3-red-2   { background: rgba(239, 68, 68, 0.20); color: #fca5a5; }
.q3-lineup-table .q3-red-3   { background: rgba(239, 68, 68, 0.32); color: #fecaca; font-weight: 700; }

/* Opposing-pitcher mini avatar in the column-group header. Same
   29 px footprint as a sized-down version of .q3-avatar so it sits
   neatly inline with the "vs <Name>" label and hand pill. */
.q3-vs-group-inner {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.q3-vs-avatar {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center top;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid rgba(255, 255, 255, 0.06);
  flex-shrink: 0;
}
.q3-vs-avatar.is-fallback {
  object-fit: contain;
  padding: 4px;
}
.q3-vs-name {
  white-space: nowrap;
}

/* Color legend — mirrors Q2's stats-tab legend for visual parity. */
.q3-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  font-size: 0.82rem;
  color: #94a3b8;
  letter-spacing: 0.02em;
}
.q3-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.q3-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.q3-legend-green { background: rgba(34, 197, 94, 0.75); }
.q3-legend-red   { background: rgba(239, 68, 68, 0.75); }

/* ────────────────────────────────────────────────────────────────────
   MOBILE TYPOGRAPHY BUMP
   ────────────────────────────────────────────────────────────────────
   On phone-sized viewports, the default desktop type sizes read too
   small once the cards stack to single column. This block bumps the
   major UI text + button sizes ~25% across the dashboard, scoped under
   #mlb-player-dashboard so nothing leaks into the workbench or the
   pitcher dashboard.

   Intentionally NOT bumped (already comfortable at default sizes):
     • .q1-stat-cards / .q1-stat-card* (L5/L15/L50/Season buttons)
     • Spray Chart canvas / .q6-* internals
     • Strike Zone canvas / .q7-* internals

   We grow vertically only — no horizontal container widths change, so
   tables may scroll horizontally if a row truly doesn't fit at the new
   text size. That's the explicit tradeoff. */
@media (max-width: 1000px) {
  /* ─── Header chrome ─── */
  #mlb-player-dashboard .mlb-dash-back        { font-size: 1.15rem; padding: 8px 12px; }
  #mlb-player-dashboard .mlb-dash-player-name { font-size: 1.6rem; }
  #mlb-player-dashboard .mlb-dash-chip        { font-size: 1rem; padding: 6px 14px; }
  #mlb-player-dashboard .mlb-dash-ms-label    { font-size: 0.7rem; }
  #mlb-player-dashboard .mlb-dash-ms-val      { font-size: 1rem; }
  #mlb-player-dashboard .mlb-dash-ms-hand     { font-size: 0.78rem; }
  #mlb-player-dashboard .mlb-dash-ms-col      { padding: 8px 12px; }

  /* ─── Section headers (PROP PERFORMANCE, MATCHUP, BATTING ORDER, …)
         Each section's title takes one of two shapes after its JS runs:
           1. Plain text inside <header class="mlb-dash-card-title">
              (Q1 / Q4 / Q5 — never wrapped post-render).
           2. A wrapper span inside the header (Q2 .q2-card-title-text,
              Q3 .q3-card-title-text, Q6/Q7 .q6-title-text), placed
              alongside sibling action controls.
         The wrappers inherit font-size in theory, but the
         q2-card-title-row variant resets text-transform/letter-spacing
         on the parent and the wrapper overrides them — those resets
         interact with font-size in some browsers via the cascade order
         and the wrapped MATCHUP / SPRAY CHART / STRIKE ZONE titles
         can render visibly smaller than the plain Q1/Q4/Q5 titles.

         Force every title text variant to one explicit size with
         !important. Listing the wrapper classes by name (rather than
         using `> *`) avoids accidentally resizing the sibling action
         controls — .q6-title-actions, .q2-mode-pills, .q3-card-vs —
         which have their own intentional smaller sizes. */
  #mlb-player-dashboard .mlb-dash-card-title,
  #mlb-player-dashboard .q2-card-title-text,
  #mlb-player-dashboard .q3-card-title-text,
  #mlb-player-dashboard .q6-title-text {
    font-size: 18px !important;
  }

  #mlb-player-dashboard .q2-card-title-text {
    font-size: 20px !important;
  }

    #mlb-player-dashboard #mlb-dash-q4 .mlb-dash-card-title,
  #mlb-player-dashboard #mlb-dash-q5 .mlb-dash-card-title {                                                                                             
    font-size: 12px !important;
  }  

  /* ─── Q1: prop tabs + line stepper / score (skips .q1-stat-cards) ─── */
  #mlb-player-dashboard .q1-tab               { font-size: 1.15rem; padding: 10px 16px; }
  #mlb-player-dashboard .q1-prop-panel        { font-size: 1rem; }
  #mlb-player-dashboard .q1-prop-panel button { font-size: 1rem; }

  /* ─── Q1 prop-panel mobile re-layout ─────────────────────────────
     Desktop:  [step] [    line pill    ] [step] | [Score]
               [          Add to Parlay        ] |
     Mobile:   [           line pill           ] [       ]
               [ − ][ + ][ Add to Parlay      ] [ Score ]
                                                 [ (big) ]
     Score spans both rows on the right and is enlarged; the bottom row
     packs −, +, and Add to Parlay together so the steppers don't take
     up the entire width on their own. `display: contents` on the two
     intermediate boxes hoists every leaf up to the grid on
     .q1-prop-panel so a single grid-template-areas drives placement. */
  #mlb-player-dashboard .q1-prop-panel {
    display: grid;
    /* Three equal-width action cells (−, +, Add to Parlay) so the
       steppers don't dwarf the parlay button. Score spans both rows on
       the right and sizes from its own min-width below. */
    grid-template-columns: 1fr 1fr 1fr auto;
    grid-template-rows: auto auto;
    grid-template-areas:
      "pill pill pill score"
      "down up   add  score";
    column-gap: 8px;
    row-gap: 10px;
    align-items: stretch;
  }
  #mlb-player-dashboard .q1-pp-main,
  #mlb-player-dashboard .q1-pp-line-row { display: contents; }

  #mlb-player-dashboard .q1-pp-line-pill {
    grid-area: pill;
    padding: 12px 18px;
    font-size: 1.1rem;
  }
  #mlb-player-dashboard .q1-pp-step-down { grid-area: down; }
  #mlb-player-dashboard .q1-pp-step-up   { grid-area: up; }
  /* Steppers + Add to Parlay share size: same height (48px), same
     border-radius (9px — splits the difference between the desktop
     stepper's 12px and the desktop add button's 6px), and equal width
     via the grid above. */
  #mlb-player-dashboard .q1-pp-step {
    width: 100%;
    height: 48px;
    border-radius: 9px;
    font-size: 1.5rem;
  }
  #mlb-player-dashboard .q1-pp-add {
    grid-area: add;
    width: auto;        /* override desktop's `width: 100%` so the
                           button hugs its grid cell instead of
                           forcing its own row */
    height: 48px;       /* match the steppers' explicit height; relying
                           on `align-self: stretch` alone left a small
                           drift due to the desktop rule's vertical
                           padding still contributing to the intrinsic
                           min-height */
    box-sizing: border-box;
    padding: 0 16px;
    font-size: 1rem;
    border-radius: 9px;
  }

  /* Score occupies the full right column on both rows — gives the ring
     room to grow without forcing the rest of the panel taller. Width
     override unsticks the desktop's hard 64px limit so the column sizes
     to the new ring. The thicker ring (inset 4px → 6px on the inner
     mask) reads more clearly at the larger size. */
  #mlb-player-dashboard .q1-pp-rating {
    grid-area: score;
    align-self: stretch;
    width: auto;
    min-width: 88px;
    padding: 8px 4px;
    gap: 6px;
  }
  #mlb-player-dashboard .q1-pp-rating-ring        { width: 76px; height: 76px; }
  #mlb-player-dashboard .q1-pp-rating-ring::before { inset: 6px; }
  #mlb-player-dashboard .q1-pp-rating-num         { font-size: 1.05rem; }
  #mlb-player-dashboard .q1-pp-rating-label       { font-size: 0.78rem; }

  /* ─── Q2: matchup card (stats / pitch mix / weather tabs, tables) ─── */
  #mlb-player-dashboard .q2-mode-pill         { font-size: 0.92rem; padding: 8px 14px; }
  #mlb-player-dashboard .q2-pm-table          { font-size: 0.95rem; }
  #mlb-player-dashboard .q2-pm-table th       { font-size: 0.75rem; }
  #mlb-player-dashboard .q2-table             { font-size: 0.95rem; }
  #mlb-player-dashboard .q2-table th          { font-size: 0.78rem; }
  #mlb-player-dashboard .q2-pm-rating-num     { font-size: 1.85rem; }
  #mlb-player-dashboard .q2-pm-rating-denom   { font-size: 0.95rem; }
  #mlb-player-dashboard .q2-pm-rating-label   { font-size: 0.85rem; }
  #mlb-player-dashboard .q2-pm-rating-tag     { font-size: 0.95rem; }
  #mlb-player-dashboard .q2-pm-usage          { font-size: 0.95rem; }
  #mlb-player-dashboard .q2-pm-velo           { font-size: 0.82rem; }
  #mlb-player-dashboard .q2-cell-label        { font-size: 0.88rem; }

  /* ─── Q3: batting order. Tables get bigger cells; the wrapper still
         can scroll horizontally if columns don't fit. ─── */
  #mlb-player-dashboard #mlb-dash-q3 table    { font-size: 0.95rem; }
  #mlb-player-dashboard #mlb-dash-q3 th       { font-size: 0.78rem; }

  /* ─── Q4: exit velocity stats + recent-events table ─── */
  #mlb-player-dashboard .q4-stat-value        { font-size: 1.4rem; }
  #mlb-player-dashboard .q4-stat-label        { font-size: 0.85rem; }
  #mlb-player-dashboard #mlb-dash-q4 table    { font-size: 0.95rem; }
  #mlb-player-dashboard #mlb-dash-q4 th       { font-size: 0.78rem; }

  /* ─── Q5: team splits — tabs, table headers/cells ─── */
  #mlb-player-dashboard .q5-tab               { font-size: 0.95rem; padding: 8px 14px; }
  #mlb-player-dashboard .q5-table             { font-size: 0.95rem; }
  #mlb-player-dashboard .q5-table th          { font-size: 0.78rem; }
}
