:root {
  color-scheme: light;
  --bg:        #f2ead6;
  --surface:   #fffdf7;
  --surface-2: #ece0c2;
  --line:      #d9cca4;
  --text-1:    #241b14;
  --text-2:    #5b4d3a;
  --muted:     #6b5d42;
  --crest-red:     #8b2635;
  --crest-red-ink: #6e1d29;
  --forest:        #33513f;
  --forest-ink:    #223829;
  --rain-100:  #dcebf3;
  --rain-300:  #8fc3de;
  --rain-500:  #4a8bab;
  --rain-700:  #3d7391;
  --wind:      #8a95a3;
  --wind-ink:  #5f6b78;
  --flag:      #b8924a;
  --flag-ink:  #8f6f34;
  --flag-on-bg: var(--flag-ink); /* --flag itself is 2.42:1 on --bg and fails as text there — use this alias for any gold text on parchment, --flag stays fine on --scoreboard (4.82:1) */
  --scoreboard: #212e34;
  --scoreboard-ink: #f2ead6;
  --scoreboard-line: #3a4b53;
  --focus:     #3d7391;
  /* "No reading yet" — must never look like a measured zero. Distinct
     from --muted, which is for ordinary de-emphasized text. */
  --pending:    #665842;
  --pending-bg: #e6dcc0;
  /* Impact/severity gets its own warm ramp so crest-red can go back to
     being chrome only (brand accent, illustration) rather than doing
     double duty as "bad" too. */
  --impact-100: #f0d9c4;
  --impact-300: #d99a63;
  --impact-500: #b5652e;
  --impact-700: #8a4419;
  /* Fixed (deliberately NOT theme-inverting) — the scoreboard header is
     dark in both site themes, so text sitting on it needs the same light
     value in both, not the sequential rain-100/300 ramp steps, which
     invert with the theme and go dark-on-near-black in dark mode (found
     while checking the new wordmark's dark-mode contrast: rain-300 came
     out to only 3.37:1 against the dark-theme scoreboard, and rain-100
     was worse still at 1.58:1 — a real pre-existing bug, not new). */
  --scoreboard-blue:      #8fc3de; /* 7.33:1 light scoreboard, 9.94:1 dark scoreboard */
  --scoreboard-blue-pale: #dcebf3; /* 11.44:1 light scoreboard, 15.53:1 dark scoreboard */
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:        #1b1712;
    --surface:   #262019;
    --surface-2: #302819;
    --line:      #443a28;
    --text-1:    #f3ecd9;
    --text-2:    #c9bd9e;
    --muted:     #9c8f74;
    --crest-red:     #d06975;
    --crest-red-ink: #d06975;
    --forest:        #5a8a6e;
    --forest-ink:    #7fb096;
    --rain-100:  #1c3a4a;
    --rain-300:  #3f6d85;
    --rain-500:  #6fa4c4;
    --rain-700:  #93bfd8;
    --wind:      #a9b4c0;
    --wind-ink:  #c3ccd6;
    --flag:      #d9b06a;
    --flag-ink:  #e8c483;
    --flag-on-bg: var(--flag-ink);
    --scoreboard: #14100c;
    --scoreboard-ink: #f3ecd9;
    --scoreboard-line: #302a20;
    --focus:     #93bfd8;
    --pending:    #d4c7ab;
    --pending-bg: #3a3226;
    --impact-100: #3d2a1a;
    --impact-300: #8a5530;
    --impact-500: #d99a63;
    --impact-700: #f0b587;
    --scoreboard-blue:      #8fc3de;
    --scoreboard-blue-pale: #dcebf3;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:        #1b1712;
  --surface:   #262019;
  --surface-2: #302819;
  --line:      #443a28;
  --text-1:    #f3ecd9;
  --text-2:    #c9bd9e;
  --muted:     #9c8f74;
  --crest-red:     #d06975;
  --crest-red-ink: #d06975;
  --forest:        #5a8a6e;
  --forest-ink:    #7fb096;
  --rain-100:  #1c3a4a;
  --rain-300:  #3f6d85;
  --rain-500:  #6fa4c4;
  --rain-700:  #93bfd8;
  --wind:      #a9b4c0;
  --wind-ink:  #c3ccd6;
  --flag:      #d9b06a;
  --flag-ink:  #e8c483;
  --flag-on-bg: var(--flag-ink);
  --scoreboard: #14100c;
  --scoreboard-ink: #f3ecd9;
  --scoreboard-line: #302a20;
  --focus:     #93bfd8;
  --pending:    #d4c7ab;
  --pending-bg: #3a3226;
  --impact-100: #3d2a1a;
  --impact-300: #8a5530;
  --impact-500: #d99a63;
  --impact-700: #f0b587;
  --scoreboard-blue:      #8fc3de;
  --scoreboard-blue-pale: #dcebf3;
}

* { box-sizing: border-box; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text-1);
  font-family: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; }
.wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding-inline: 20px;
}

/* ---------- masthead ---------- */
.masthead {
  background: var(--scoreboard);
  color: var(--scoreboard-ink);
  border-bottom: 3px double var(--flag);
  position: relative;
}
.masthead-inner {
  max-width: 1080px;
  margin: 0 auto;
  padding: 24px 20px 18px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 20px;
}
.masthead-mark {
  width: 40px;
  height: auto;
  flex: 0 0 auto;
  align-self: center;
}
@media (max-width: 640px) {
  .masthead-mark { width: 30px; }
}
/* Wraps the logo + wordmark as one link to the dashboard — display:contents
   keeps it out of the flex box model entirely, so .masthead-mark and .brand
   stay direct flex children of .masthead-inner exactly as before, with the
   anchor just making both clickable. */
.masthead-brand-link {
  display: contents;
  text-decoration: none;
}
/* Alfa Slab One sets heavier and wider than Rye did, so the wordmark
   drops a size step at every breakpoint to compensate. */
.brand-word {
  font-family: "Alfa Slab One", Georgia, serif;
  font-weight: 400;
  font-size: clamp(24px, 5vw, 36px);
  letter-spacing: 0.005em;
  line-height: 1;
  text-wrap: balance;
  text-shadow: 0 2px 0 rgba(0,0,0,0.25);
}
.brand-word b, .brand-word i { font-weight: inherit; font-style: normal; }
/* Split into three spans on purpose — a solid-color "CFBRAINK" reads as
   a typo, since nobody decodes the rain/rank pun without the color cue. */
.brand-word b { color: var(--flag); }      /* 4.82:1 on --scoreboard */
.brand-word i { color: var(--scoreboard-blue); }  /* 7.33:1 on --scoreboard */
/* For reuse anywhere the wordmark sits on parchment instead of the dark
   scoreboard header — not currently used on this site, but the flat
   --flag/--rain-300 pairing above fails contrast off the dark background,
   so this is here for whenever that placement happens. */
.on-parchment .brand-word b { color: var(--flag-on-bg); } /* 3.90:1 */
.on-parchment .brand-word i { color: var(--rain-700); }   /* 4.31:1 */
.brand-tag {
  display: block;
  font-family: "Oswald", sans-serif;
  font-weight: 600;
  font-size: 12.5px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--scoreboard-blue);
  margin-top: 4px;
}
.masthead-meta {
  font-family: "IBM Plex Mono", monospace;
  font-size: 13px;
  color: var(--scoreboard-blue-pale);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}
.masthead-nav {
  font-family: "Oswald", sans-serif;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  display: flex;
  gap: 18px;
}
.masthead-nav a { color: var(--scoreboard-blue-pale); text-decoration: none; }
.masthead-nav a:hover, .masthead-nav a.active { color: var(--flag); }
.masthead-sub {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 20px 18px;
  font-size: 14.5px;
  color: var(--scoreboard-blue-pale);
  max-width: 62ch;
}

/* ---------- stat tiles (shared with the blog's .stat-callout-row) ---------- */
.stat-label {
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--muted);
}
.stat-value {
  font-family: "Oswald", sans-serif;
  font-weight: 700;
  font-size: 32px;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}
.stat-value.rain { color: var(--rain-700); }
.stat-value.flag { color: var(--flag-ink); }
.stat-value.wind { color: var(--wind-ink); }
.stat-note {
  font-size: 12.5px;
  color: var(--text-2);
  line-height: 1.4;
}

section { margin-top: 34px; }
.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  gap: 24px;
  margin-top: 34px;
}
.chart-grid section { margin-top: 0; }
.chart-grid-feature { grid-column: 1 / -1; }
.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
  flex-wrap: wrap;
}
.section-head-left { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
h2 {
  font-family: "Oswald", sans-serif;
  font-weight: 600;
  font-size: 21px;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  margin: 0;
  text-wrap: balance;
}
.section-note { font-size: 13px; color: var(--muted); }
.section-link {
  font-family: "Oswald", sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--rain-700);
  text-decoration: none;
  white-space: nowrap;
}
.section-link:hover { color: var(--crest-red-ink); }
.section-link::after { content: ' \2192'; }

/* ---------- top-N bar chart ---------- */
.chart-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 18px 20px 20px;
}
.bar-row {
  display: grid;
  grid-template-columns: minmax(120px, 190px) 1fr 56px;
  align-items: center;
  gap: 14px;
  padding: 6px 0;
  border-radius: 6px;
  position: relative;
}
.bar-row + .bar-row { border-top: 1px solid var(--line); }
.bar-label {
  font-size: 13px;
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bar-label strong { color: var(--text-1); font-weight: 600; }
.bar-track {
  background: var(--surface-2);
  height: 12px;
  border-radius: 3px;
  position: relative;
}
.bar-fill {
  position: absolute;
  inset: 0 auto 0 0;
  height: 100%;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(90deg, var(--rain-300), var(--rain-500));
}
.bar-row:first-child .bar-fill { background: linear-gradient(90deg, var(--rain-500), var(--rain-700)); }
.bar-fill.wind { background: linear-gradient(90deg, var(--wind), var(--wind-ink)); }
.bar-row:first-child .bar-fill.wind { background: linear-gradient(90deg, var(--wind-ink), var(--wind-ink)); }
.bar-fill.outlier { background: linear-gradient(90deg, var(--impact-300), var(--impact-500)); }
.bar-row:first-child .bar-fill.outlier { background: linear-gradient(90deg, var(--impact-500), var(--impact-700)); }
.bar-fill.impact { background: linear-gradient(90deg, var(--impact-300), var(--impact-500)); }
.bar-row:first-child .bar-fill.impact { background: linear-gradient(90deg, var(--impact-500), var(--impact-700)); }
.bar-value {
  font-family: "IBM Plex Mono", monospace;
  font-size: 13px;
  font-weight: 500;
  color: var(--rain-700);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.bar-value.wind { color: var(--wind-ink); }
.bar-value.outlier { color: var(--impact-700); }
.bar-value.impact { color: var(--impact-700); }
.bar-row:focus-visible, .has-tip:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
.has-tip { position: relative; cursor: default; }
.has-tip::after {
  content: attr(data-tip);
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%) translateY(4px);
  background: var(--scoreboard);
  color: var(--scoreboard-ink);
  font-size: 12px;
  font-family: "IBM Plex Sans", sans-serif;
  white-space: nowrap;
  padding: 6px 9px;
  border-radius: 6px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 5;
  box-shadow: 0 4px 14px rgba(0,0,0,0.22);
}
.has-tip:hover::after, .has-tip:focus-visible::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* A tooltip anchored to a table header needs to wrap (an explanation is much
   longer than a chart bar's one-line stat), hang off the header's right
   edge rather than centering (this column sits near the right side of the
   table, so a centered box would run past the table-scroll container and
   get clipped), AND open downward instead of the base .has-tip's upward
   default — the header lives at the very top of .table-card, which has
   overflow:hidden for its rounded corners, so a tooltip opening upward
   renders outside the card's box and is silently clipped (found live:
   this is why the Impact column's tooltip wasn't appearing at all).
   Opening downward keeps it over the table body, still inside the card. */
.has-tip.wrap-tip::after {
  white-space: normal;
  width: 240px;
  left: auto;
  right: 0;
  bottom: auto;
  top: calc(100% + 8px);
  transform: translateY(-4px);
  /* Reset the table header's text styling (uppercase, tracked, bold) that
     would otherwise inherit into this pseudo-element's sentence-case body copy. */
  text-transform: none;
  letter-spacing: normal;
  font-weight: 400;
  line-height: 1.4;
}
.has-tip.wrap-tip:hover::after, .has-tip.wrap-tip:focus-visible::after {
  transform: translateY(0);
}

/* ---------- table ---------- */
.table-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  overflow: hidden;
}
.table-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
  flex-wrap: wrap;
}
.search {
  flex: 1 1 220px;
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 7px 11px;
}
.search svg { flex: none; color: var(--muted); }
.search input {
  border: none;
  background: transparent;
  outline: none;
  font: inherit;
  color: var(--text-1);
  width: 100%;
  font-size: 14px;
}
.search input::placeholder { color: var(--muted); }
.result-count {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12.5px;
  color: var(--muted);
  white-space: nowrap;
}
.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 700px; }
thead th {
  position: sticky;
  top: 0;
  background: var(--surface-2);
  text-align: left;
  padding: 10px 14px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}
thead th:hover { color: var(--text-1); }
thead th.sorted { color: var(--rain-700); }
thead th .arrow { font-size: 10px; margin-left: 3px; opacity: 0.7; }
thead th:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
tbody td {
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover { background: var(--surface-2); }
.col-matchup { min-width: 220px; }
.away { color: var(--text-2); }
.home { color: var(--text-1); font-weight: 600; }
.col-score, .col-date { font-family: "IBM Plex Mono", monospace; font-variant-numeric: tabular-nums; color: var(--text-2); white-space: nowrap; }
.col-ou, .col-model, .col-edge { font-family: "IBM Plex Mono", monospace; font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.col-ou, .col-model { color: var(--text-1); }
.col-edge { color: var(--text-2); font-size: 12.5px; }
/* Edge is the number this whole module exists to surface, so its
   magnitude gets a visual tier instead of uniform gray — a bigger
   disagreement with the market should be easier to spot scanning down
   the column, not just readable one row at a time. */
.edge-low { color: var(--muted); font-weight: 400; }
.edge-mid { color: var(--text-1); font-weight: 500; }
.edge-high { color: var(--rain-700); font-weight: 700; }
.col-conditions { color: var(--text-2); font-size: 13px; }
.col-score { white-space: nowrap; }
.col-score-figure {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text-1);
}
.live-badge, .final-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 4px;
  vertical-align: middle;
}
.final-badge {
  color: var(--muted);
  background: color-mix(in srgb, var(--muted) 16%, transparent);
}
.live-badge {
  color: var(--forest-ink);
  background: color-mix(in srgb, var(--forest) 20%, transparent);
}
.neutral-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wind-ink);
  background: color-mix(in srgb, var(--wind) 18%, transparent);
  padding: 2px 6px;
  border-radius: 4px;
  vertical-align: middle;
}
/* AP Top 25 rank, inline before a team name — distinct from .rank-badge
   (the leaderboard's row-position number, a different concept). */
.rank-badge-inline {
  display: inline-block;
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  font-weight: 600;
  color: var(--flag-ink);
  background: color-mix(in srgb, var(--flag) 18%, transparent);
  padding: 1px 5px;
  border-radius: 3px;
  vertical-align: middle;
}
.col-venue { color: var(--text-2); }
.col-venue .state { color: var(--muted); font-family: "IBM Plex Mono", monospace; font-size: 12px; }
/* min-width lives on the td (a layout hint the table algorithm can use);
   display:flex does NOT — a td needs to stay display:table-cell or the
   browser can drop it out of normal table-row layout entirely (found via
   a phone-width screenshot: at a narrow enough column width this
   actually happened, stacking the Precip and Impact cells on top of each
   other instead of side by side). .weather-cell below carries the flex
   row for each cell's own content instead. */
.col-precip { min-width: 130px; }
.weather-cell { display: flex; align-items: center; gap: 8px; }
.precip-figure {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  width: 46px;
  text-align: right;
  color: var(--text-1);
}
.precip-figure.dash { color: var(--pending); font-weight: 400; }
.precip-figure::after { content: ' in'; font-size: 11px; color: var(--muted); }
.precip-figure.dash::after { content: ''; }
.mini-track { flex: 1; height: 6px; background: var(--surface-2); border-radius: 3px; min-width: 40px; max-width: 90px; }
.mini-fill { height: 100%; border-radius: 3px; background: var(--rain-500); }
.mini-fill-impact { height: 100%; border-radius: 3px; background: var(--impact-500); }
.mini-fill-wind { height: 100%; border-radius: 3px; background: var(--wind-ink); }
.wet-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--flag-ink);
  background: color-mix(in srgb, var(--flag) 18%, transparent);
  padding: 2px 6px;
  border-radius: 4px;
  vertical-align: middle;
}
.snow-badge {
  display: inline-block;
  margin-left: 6px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--rain-700);
  background: color-mix(in srgb, var(--rain-500) 18%, transparent);
  padding: 2px 6px;
  border-radius: 4px;
  vertical-align: middle;
}
.pending-badge {
  display: inline-block;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.85em;
  font-weight: 500;
  color: var(--pending);
  background: var(--pending-bg);
  padding: 1px 7px;
  border-radius: 3px;
}
.empty-row td { text-align: center; padding: 32px; color: var(--muted); font-size: 14px; }

.col-to { white-space: nowrap; }
.to-figure {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  color: var(--forest-ink);
  font-weight: 500;
}
.to-figure.dash { color: var(--pending); }
.col-wind { white-space: nowrap; }
.wind-figure {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  color: var(--text-1);
}
.wind-figure.dash { color: var(--pending); }
.wind-figure::after { content: ' mph'; font-size: 11px; color: var(--muted); }
.wind-figure.dash::after { content: ''; }
.col-impact { min-width: 130px; }
.impact-figure {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  width: 46px;
  text-align: right;
  color: var(--impact-700);
}
.impact-figure.dash { color: var(--pending); font-weight: 400; }
.impact-figure::after { content: ' yd'; font-size: 11px; color: var(--muted); }
.impact-figure.dash::after { content: ''; }
.col-detail-h, .col-detail { width: 32px; text-align: center; padding-left: 4px; padding-right: 10px; }
.game-row { cursor: default; }
.detail-toggle {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--muted);
  font-size: 11px;
  padding: 4px 6px;
  border-radius: 4px;
  line-height: 1;
}
.detail-toggle:hover { color: var(--rain-700); background: var(--surface-2); }
.detail-toggle:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; }
.detail-row td { padding: 0; border-bottom: 1px solid var(--line); background: var(--surface-2); }
.stat-grid { padding: 14px 18px 16px; display: flex; flex-direction: column; gap: 2px; }
.stat-grid-row {
  display: grid;
  grid-template-columns: 1fr 90px 90px;
  gap: 10px;
  padding: 4px 0;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.stat-grid-label { color: var(--text-2); }
.stat-grid-val { color: var(--forest-ink); text-align: right; font-family: "IBM Plex Mono", monospace; font-weight: 500; }
.stat-grid-head { font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--muted); border-bottom: 1px solid var(--line); padding-bottom: 6px; margin-bottom: 4px; }
.stat-grid-head span:nth-child(2), .stat-grid-head span:nth-child(3) { text-align: right; font-family: "IBM Plex Mono", monospace; text-transform: none; letter-spacing: 0; font-size: 12px; }
/* Venue/wind are per-game facts, not per-team stats, so they don't fit
   the away/home stat_grid_row grid below — a single summary line above
   it instead. Only shown here on mobile, where the compact row hides
   Venue/Wind to make room; desktop already shows both in the row. */
.stat-grid-context { font-size: 12px; color: var(--muted); padding-bottom: 8px; margin-bottom: 6px; border-bottom: 1px solid var(--line); }

/* ---------- pagination ---------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid var(--line);
  flex-wrap: wrap;
}
.pagination-pages { display: flex; align-items: center; gap: 4px; }
.page-btn {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12.5px;
  color: var(--text-2);
  background: none;
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 5px 10px;
  cursor: pointer;
}
.page-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--text-1); }
.page-btn:disabled { opacity: 0.4; cursor: default; }
.page-btn.current { background: var(--rain-700); border-color: var(--rain-700); color: var(--scoreboard-ink); }
.page-size {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--muted);
}
.page-size select {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12.5px;
  color: var(--text-1);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 6px;
  padding: 4px 8px;
}

/* ---------- leaderboard page ---------- */
.rank-badge {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  color: var(--muted);
  width: 28px;
  text-align: right;
  flex: none;
}
.leaderboard-row .bar-label { display: flex; align-items: baseline; gap: 8px; }
.metric-toggle {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 8px;
  overflow: hidden;
}
.metric-toggle a {
  font-family: "Oswald", sans-serif;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  padding: 7px 14px;
  color: var(--text-2);
  background: var(--surface);
}
.metric-toggle a + a { border-left: 1px solid var(--line); }
.metric-toggle a.active { background: var(--rain-700); color: var(--scoreboard-ink); }

/* ---------- blog ---------- */
.post-list { display: flex; flex-direction: column; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.post-card {
  background: var(--surface);
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-decoration: none;
  color: inherit;
}
.post-card:hover { background: var(--surface-2); }
.post-card-title {
  font-family: "Oswald", sans-serif;
  font-weight: 600;
  font-size: 19px;
  letter-spacing: 0.01em;
  color: var(--text-1);
}
.post-card-meta {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.post-card-excerpt { font-size: 14px; color: var(--text-2); line-height: 1.5; }

.article {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 32px clamp(20px, 5vw, 56px) 44px;
}
.article-meta {
  font-family: "IBM Plex Mono", monospace;
  font-size: 12.5px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 10px;
}
.article h1 {
  font-family: "Oswald", sans-serif;
  font-weight: 700;
  font-size: clamp(26px, 4vw, 36px);
  letter-spacing: 0.01em;
  line-height: 1.15;
  margin: 0 0 18px;
  text-wrap: balance;
}
.article .lede {
  font-size: 17px;
  color: var(--text-2);
  line-height: 1.55;
  margin-bottom: 28px;
  max-width: 62ch;
}
.article h2 {
  text-transform: none;
  letter-spacing: 0;
  font-size: 22px;
  margin-top: 36px;
  margin-bottom: 12px;
}
.article p {
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--text-1);
  max-width: 66ch;
  margin: 0 0 16px;
}
.article ul, .article ol { max-width: 66ch; font-size: 15.5px; line-height: 1.7; color: var(--text-1); padding-left: 22px; margin: 0 0 16px; }
.article li { margin-bottom: 6px; }
.article strong { color: var(--text-1); }
.article a { color: var(--rain-700); text-decoration-color: color-mix(in srgb, var(--rain-700) 40%, transparent); }
.article code { font-family: "IBM Plex Mono", monospace; background: var(--surface-2); padding: 1px 5px; border-radius: 4px; font-size: 0.9em; }
.article figure { margin: 24px 0; }
.article figcaption { font-size: 12.5px; color: var(--muted); margin-top: 8px; }
.stat-callout-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; margin: 24px 0; }
.stat-callout { background: var(--surface); padding: 16px; }
.stat-callout .stat-value { font-size: 24px; }

footer {
  max-width: 1080px;
  margin: 40px auto 0;
  padding: 18px 20px 32px;
  font-size: 12.5px;
  color: var(--muted);
  border-top: 1px solid var(--line);
}
footer code {
  font-family: "IBM Plex Mono", monospace;
  background: var(--surface-2);
  padding: 1px 5px;
  border-radius: 4px;
}

@media (max-width: 640px) {
  .bar-row { grid-template-columns: 96px 1fr 48px; gap: 8px; }
  .bar-label { font-size: 12px; }
  .stat-callout-row { grid-template-columns: repeat(2, 1fr); }

  /* Wet games table: Venue/TO/Wind/Impact move into the tap-to-expand
     detail panel (see buildDetailHtml's stat-grid-context line) instead
     of forcing horizontal scroll to see them — Kickoff/Matchup/Score/
     Precip/the expand chevron are what's left in the compact row. Precip
     stays: it's this table's namesake sort key. A real phone-width
     screenshot showed Impact was the one column still forcing a small
     scroll even after every other fix below, so it's the one that moves;
     it's also already the star of its own "Highest-impact kickoffs"
     module further up the page. Both the "-h" header class and the plain
     body-cell class are hidden together; hiding only one previously left
     the header row one column out of alignment with the body rows below
     it (the original bug report). */
  .col-venue-h, .col-venue, .col-to-h, .col-to, .col-wind-h, .col-wind,
  .col-impact-h, .col-impact { display: none; }

  /* Predictions table: Posted O/U and Model are the two inputs Edge is
     already the difference of, so on a narrow screen only Edge (the
     headline number) stays, alongside Kickoff/Matchup/Score/Conditions. */
  .col-ou-h, .col-ou, .col-model-h, .col-model { display: none; }

  /* Fewer columns need less width to be useful — letting the table
     shrink (instead of holding the desktop 700px floor) is what actually
     removes the horizontal scroll, not just hiding cells. A screenshot at
     phone width caught that .col-matchup's 220px floor was the actual
     remaining blocker even after hiding columns and shortening dates —
     team names wrap fine at a narrower width, so the floor just isn't
     needed here the way it is on desktop's single-line layout. */
  table { min-width: 0; }
  .col-matchup { min-width: 0; }
  .col-conditions { white-space: normal; }
  .col-score { white-space: normal; }

  /* .col-precip/.col-impact's 130px min-width (and the mini-track bar's
     own 40-90px range) are sized for desktop's roomier row — measured at
     phone width, Precip alone was still 170px, the single largest column
     after hiding Venue/TO/Wind. Shrinking both here is what actually
     closes the remaining horizontal-scroll gap. */
  .col-precip { min-width: 0; }
  .weather-cell { display: inline-flex; gap: 4px; }
  .precip-figure::after { content: ''; }
  /* The mini-bar mostly earns its keep in the Top-5 chart modules, where
     it's the only way to compare rows at a glance — in this sortable/
     filterable table it was still costing ~30-40px per column after
     shrinking, measured against a real phone-width layout, for a
     comparison the sort arrows already give you more directly. */
  .mini-track { display: none; }
  .precip-figure, .impact-figure { width: auto; }

  /* 14px of horizontal cell padding per side was costing 28px per
     column — trivial with 4-5 desktop columns, but ~170px total across
     6 columns at phone width, more than any single column above. */
  thead th, tbody td { padding-left: 8px; padding-right: 8px; }

  /* Comfortable tap targets matter more without a mouse-hover fallback —
     desktop's tighter density stays as-is, this only widens the phone-
     width hit area. */
  .page-btn { padding: 9px 13px; }
  .detail-toggle { padding: 8px 10px; font-size: 13px; }
}

@media (prefers-reduced-motion: reduce) {
  .has-tip::after { transition: none; }
}
