/**
 * NFL Lines — design-system additive styles.
 *
 * Loaded AFTER front.css. All selectors use the .nfl-ds-* prefix so they
 * don't collide with the pre-existing .nfl-* component styles. New tokens
 * (--nfl-good, --nfl-bad, --nfl-mid, --nfl-accent, --nfl-team-*) are added
 * to :root without touching the existing spacing/radius/typography tokens.
 *
 * Sections:
 *   1. :root tokens (meaning colors, per-team colors, chart palette)
 *   2. KPI tiles + strip
 *   3. Rank pills
 *   4. Delta bars
 *   5. Sticky header
 *   6. Section card
 *   7. Chart/table toggle
 *   8. Sortable table
 *   9. Sparkline
 *  10. Responsive
 *
 * @package NFL_Lines
 */

/* ================================================================
 * 1. Root tokens (additive — do not remove/override anything in front.css)
 * ================================================================ */
:root {
  /* Semantic meaning */
  --nfl-good:        #15803d;
  --nfl-bad:         #b91c1c;
  --nfl-mid:         #6b7280;
  --nfl-accent:      #2563eb;

  --nfl-good-bg:     #dcfce7;
  --nfl-bad-bg:      #fee2e2;
  --nfl-mid-bg:      #f3f4f6;
  --nfl-accent-bg:   #dbeafe;

  /* Surface tokens — alias to existing front.css names where applicable */
  --nfl-card-bg:       var(--nfl-color-bg,          #ffffff);
  --nfl-card-border:   var(--nfl-color-border-soft, #e6e8ec);
  --nfl-page-bg:       var(--nfl-color-bg-subtle,   #fafafa);
  --nfl-text:          var(--nfl-color-text,        #111827);
  --nfl-text-muted:    var(--nfl-color-text-muted,  #6b7280);
  --nfl-text-faint:    #9ca3af;

  /* Chart categorical palette */
  --nfl-chart-1:  #2563eb;
  --nfl-chart-2:  #15803d;
  --nfl-chart-3:  #b45309;
  --nfl-chart-4:  #b91c1c;
  --nfl-chart-5:  #6b21a8;
  --nfl-chart-6:  #0e7490;
  --nfl-chart-7:  #c2410c;
  --nfl-chart-8:  #4338ca;
  --nfl-chart-9:  #be123c;
  --nfl-chart-10: #4d7c0f;

  /* Per-team accent colors. Used sparingly (left stripe only). */
  --nfl-team-ARI: #97233F;
  --nfl-team-ATL: #A71930;
  --nfl-team-BAL: #241773;
  --nfl-team-BUF: #00338D;
  --nfl-team-CAR: #0085CA;
  --nfl-team-CHI: #0B162A;
  --nfl-team-CIN: #FB4F14;
  --nfl-team-CLE: #311D00;
  --nfl-team-DAL: #003594;
  --nfl-team-DEN: #FB4F14;
  --nfl-team-DET: #0076B6;
  --nfl-team-GB:  #203731;
  --nfl-team-HOU: #03202F;
  --nfl-team-IND: #002C5F;
  --nfl-team-JAX: #006778;
  --nfl-team-KC:  #E31837;
  --nfl-team-LV:  #000000;
  --nfl-team-LAC: #0080C6;
  --nfl-team-LAR: #003594;
  --nfl-team-MIA: #008E97;
  --nfl-team-MIN: #4F2683;
  --nfl-team-NE:  #002244;
  --nfl-team-NO:  #D3BC8D;
  --nfl-team-NYG: #0B2265;
  --nfl-team-NYJ: #125740;
  --nfl-team-PHI: #004C54;
  --nfl-team-PIT: #FFB612;
  --nfl-team-SF:  #AA0000;
  --nfl-team-SEA: #002244;
  --nfl-team-TB:  #D50A0A;
  --nfl-team-TEN: #0C2340;
  --nfl-team-WAS: #5A1414;
}

@media (prefers-color-scheme: dark) {
  :root {
    --nfl-good:      #22c55e;
    --nfl-bad:       #ef4444;
    --nfl-mid:       #9ca3af;
    --nfl-accent:    #60a5fa;
    --nfl-good-bg:   rgba(34, 197, 94, 0.15);
    --nfl-bad-bg:    rgba(239, 68, 68, 0.15);
    --nfl-mid-bg:    rgba(156, 163, 175, 0.1);
    --nfl-accent-bg: rgba(96, 165, 250, 0.15);
    --nfl-text-faint:#6b7078;
  }
}

/* ================================================================
 * 2. KPI tiles + strip — whitespace tuned to match the DistroKid density
 *    (see 2023 distrokid-earnings-analytics for reference).
 * ================================================================ */
.nfl-ds-kpi-strip {
  display: grid;
  /* v0.36.5.11.4.1 — 6 cols × 2 rows for the 12-tile strip. Clean
   * factorizations at every breakpoint (6×2 / 4×3 / 3×4) — zero
   * whitespace, no awkward fallback to single-column stack. */
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.4rem;
  width: 100%;
}

.nfl-ds-kpi {
  background: var(--nfl-card-bg);
  border: 1px solid var(--nfl-card-border);
  border-radius: 8px;
  /* v0.36.5.11.4.1 — densified. Strip used to be 9 tiles wrapping to
   * 3 rows of oversized tiles; now 12 tiles at compact size in 2 rows. */
  padding: 0.35rem 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
  min-height: 3.2rem;
  box-sizing: border-box;
}

.nfl-ds-kpi--good  { background: var(--nfl-good-bg);  }
.nfl-ds-kpi--bad   { background: var(--nfl-bad-bg);   }
.nfl-ds-kpi--mid   { background: var(--nfl-mid-bg);   }

.nfl-ds-kpi--stale {
  background: var(--nfl-mid-bg);
  opacity: 0.75;
}
.nfl-ds-kpi--stale .nfl-ds-kpi__value {
  color: var(--nfl-text-muted);
}

.nfl-ds-kpi__label {
  /* v0.36.5.11.4.1 — smaller label to match densified tile */
  font-size: 0.65rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--nfl-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.25;
}

.nfl-ds-kpi__value {
  /* v0.36.5.11.4.1 — smaller value (1.0-1.3rem clamped) to fit 6
   * tiles per row at desktop widths without truncating. */
  font-size: clamp(1.0rem, 1.4vw, 1.3rem);
  font-weight: 600;
  line-height: 1.15;
  color: var(--nfl-text);
  font-variant-numeric: tabular-nums;
}

.nfl-ds-kpi__meta {
  font-size: 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.1rem;
}

/* v0.36.5.1 — KPI tile sparkline.
 *
 * Sits between the value and the meta row. Uses currentColor on the
 * polyline so the modifier classes below can color it via a single
 * `color:` rule. Kept tight (16px tall) so it adds context without
 * pushing the value text down.
 */
.nfl-ds-kpi__spark {
  display: block;
  margin-top: 0.15rem;
  line-height: 0;
}

.nfl-ds-spark-svg {
  display: inline-block;
  vertical-align: middle;
  color: var(--nfl-text-muted);
}
.nfl-ds-spark-svg--good { color: var(--nfl-good); }
.nfl-ds-spark-svg--bad  { color: var(--nfl-bad);  }
.nfl-ds-spark-svg--mid  { color: var(--nfl-text-muted); }

/* Trend arrows on KPI tile meta row */
.nfl-ds-trend {
  display: inline-flex;
  align-items: center;
  font-weight: 600;
  font-size: 1rem;
  line-height: 1;
}
.nfl-ds-trend--up   { color: var(--nfl-good); }
.nfl-ds-trend--down { color: var(--nfl-bad);  }
.nfl-ds-trend--flat { color: var(--nfl-mid);  }

/* Tier badges */
.nfl-ds-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 9999px;
  font-size: var(--nfl-font-xs, 0.8125rem);
  font-weight: 600;
  line-height: 1.4;
}
.nfl-ds-badge--bronze   { background: #fce7d3; color: #7c3a00; border: 1px solid #e5a779; }
.nfl-ds-badge--silver   { background: #e5e7eb; color: #374151; border: 1px solid #9ca3af; }
.nfl-ds-badge--gold     { background: #fef3c7; color: #78350f; border: 1px solid #d97706; }
.nfl-ds-badge--platinum { background: #cffafe; color: #155e75; border: 1px solid #06b6d4; }

/* ================================================================
 * 3. Rank pills
 * ================================================================ */
.nfl-ds-rank {
  display: inline-flex;
  align-items: center;
  /* v0.36.5.11.4.1 — halved padding + smaller font for the densified strip */
  padding: 0.05rem 0.4rem;
  border-radius: 9999px;
  font-size: 0.62rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.4;
  min-width: 32px;
  justify-content: center;
}
.nfl-ds-rank--good {
  background: var(--nfl-good-bg);
  color: var(--nfl-good);
}
.nfl-ds-rank--bad {
  background: var(--nfl-bad-bg);
  color: var(--nfl-bad);
}
.nfl-ds-rank--mid {
  background: var(--nfl-mid-bg);
  color: var(--nfl-mid);
}

/* ================================================================
 * 4. Delta bars
 * ================================================================ */
.nfl-ds-delta {
  display: inline-flex;
  align-items: center;
  gap: var(--nfl-space-2, 0.5rem);
  min-width: 100px;
}

.nfl-ds-delta__track {
  position: relative;
  flex: 1;
  min-width: 40px;
  height: 8px;
  background: var(--nfl-mid-bg);
  border-radius: 4px;
  overflow: hidden;
}

.nfl-ds-delta__fill {
  position: absolute;
  top: 0;
  bottom: 0;
  min-width: 2px;
  border-radius: 4px;
  transition: width 0.18s ease-out;
}
.nfl-ds-delta__fill--good { background: var(--nfl-good); }
.nfl-ds-delta__fill--bad  { background: var(--nfl-bad);  }
.nfl-ds-delta__fill--mid  { background: var(--nfl-mid);  }

.nfl-ds-delta__zero {
  /* v0.36.5.5.3 — bumped from 1px / pale to 2px / readable so the
     league-avg pivot is actually visible. Track height is 8px; marker
     extends 2px past top and bottom for a clear tick. Centered at the
     50% pivot point of the track, which (by render_delta_bar's geometry
     using $range_each_side = max(|max-center|, |min-center|)) IS the
     center value's visual location regardless of where center sits in
     the raw [min, max] range. */
  position: absolute;
  top: -2px;
  bottom: -2px;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  background: var(--nfl-text);
  border-radius: 1px;
  z-index: 2;
}

.nfl-ds-delta__val {
  font-size: var(--nfl-font-xs, 0.8125rem);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
  color: var(--nfl-text);
  min-width: 44px;
  text-align: right;
}

/* ================================================================
 * 5. Sticky header — tighter padding
 * ================================================================ */
.nfl-ds-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: var(--nfl-card-bg);
  border-bottom: 1px solid var(--nfl-card-border);
  /* v0.36.5.11.4.1 — tighter padding + margin so sticky header occupies
   * less viewport when scrolled. */
  padding: 0.5rem 1rem;
  margin-bottom: 0.55rem;
}

.nfl-ds-header--team {
  border-left: 4px solid var(--nfl-ds-team-color, var(--nfl-accent));
  padding-left: calc(1rem - 4px);
}

.nfl-ds-header__row {
  display: flex;
  /* v0.36.5.11.4.1 — center-align so breadcrumb + h1 + switcher read
   * as a single horizontal line instead of stacking visually. */
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.nfl-ds-header__left h1 {
  margin: 0;
  font-size: clamp(1.15rem, 1.7vw, 1.4rem);
  line-height: 1.15;
  color: var(--nfl-text);
}

.nfl-ds-header__left .nfl-meta,
.nfl-ds-header__left p {
  margin: 0;
  font-size: 0.75rem;
  color: var(--nfl-text-muted);
}

.nfl-ds-header__right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.nfl-ds-header__kpi {
  /* v0.36.5.11.4.1 — tighter top margin */
  margin-top: 0.4rem;
}

/* ================================================================
 * 6. Section card — tighter padding per DistroKid reference
 * ================================================================ */
.nfl-ds-card {
  background: var(--nfl-card-bg);
  border: 1px solid var(--nfl-card-border);
  border-radius: 8px;
  padding: 0.65rem 0.85rem;
  margin-bottom: 0.85rem;
}

.nfl-ds-card__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  margin-bottom: 0.45rem;
  padding-bottom: 0.45rem;
  border-bottom: 1px solid var(--nfl-card-border);
}

.nfl-ds-card__titles {
  flex: 1;
  min-width: 0;
}

.nfl-ds-card__title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--nfl-text);
  line-height: 1.3;
}

.nfl-ds-card__subtitle {
  margin: 0.15rem 0 0;
  font-size: 0.82rem;
  color: var(--nfl-text-muted);
  line-height: 1.4;
}

.nfl-ds-card__body {
  font-size: var(--nfl-font-base, 1rem);
  color: var(--nfl-text);
}

/* ================================================================
 * 7. Chart/table toggle buttons
 * ================================================================ */
.nfl-ds-card__toggle {
  display: inline-flex;
  border: 1px solid var(--nfl-card-border);
  border-radius: var(--nfl-radius-sm, 4px);
  overflow: hidden;
  flex-shrink: 0;
}

.nfl-ds-toggle {
  background: var(--nfl-card-bg);
  color: var(--nfl-text-muted);
  border: 0;
  padding: 4px 10px;
  font-size: var(--nfl-font-sm, 0.9375rem);
  line-height: 1.4;
  cursor: pointer;
  transition: background 0.15s ease-out, color 0.15s ease-out;
  min-height: 32px;
}
.nfl-ds-toggle:hover {
  background: var(--nfl-mid-bg);
  color: var(--nfl-text);
}
.nfl-ds-toggle.is-active,
.nfl-ds-toggle[aria-pressed="true"] {
  background: var(--nfl-accent-bg);
  color: var(--nfl-accent);
}
.nfl-ds-toggle:focus-visible {
  outline: 2px solid var(--nfl-accent);
  outline-offset: -2px;
}

/* ================================================================
 * 8. Sortable table
 * ================================================================ */
.nfl-ds-table-wrap {
  overflow-x: auto;
  margin: 0 calc(-1 * var(--nfl-space-5, 1.5rem));
  padding: 0 var(--nfl-space-5, 1.5rem);
}

.nfl-ds-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--nfl-font-sm, 0.9375rem);
}

.nfl-ds-table__caption {
  caption-side: top;
  text-align: left;
  padding: var(--nfl-space-2, 0.5rem) 0;
  color: var(--nfl-text-muted);
  font-size: var(--nfl-font-sm, 0.9375rem);
}

.nfl-ds-th {
  text-align: left;
  padding: 0;
  background: var(--nfl-page-bg);
  border-bottom: 2px solid var(--nfl-card-border);
  font-weight: 600;
  color: var(--nfl-text);
  white-space: nowrap;
  position: relative;
}
.nfl-ds-th--numeric { text-align: right; }

.nfl-ds-th__btn {
  background: transparent;
  border: 0;
  padding: var(--nfl-space-2, 0.5rem) var(--nfl-space-3, 0.75rem);
  font: inherit;
  color: inherit;
  width: 100%;
  text-align: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  justify-content: flex-start;
  min-height: 36px;
}
.nfl-ds-th--numeric .nfl-ds-th__btn {
  justify-content: flex-end;
}

.nfl-ds-th__btn:hover {
  background: var(--nfl-mid-bg);
}
.nfl-ds-th__btn:focus-visible {
  outline: 2px solid var(--nfl-accent);
  outline-offset: -2px;
}

.nfl-ds-th__indicator {
  display: inline-block;
  width: 10px;
  opacity: 0.4;
  font-size: 0.75em;
}
.nfl-ds-th.is-sorted .nfl-ds-th__indicator { opacity: 1; }
.nfl-ds-th.is-sorted-asc  .nfl-ds-th__indicator::before { content: '▲'; }
.nfl-ds-th.is-sorted-desc .nfl-ds-th__indicator::before { content: '▼'; }

.nfl-ds-td {
  padding: var(--nfl-space-2, 0.5rem) var(--nfl-space-3, 0.75rem);
  border-bottom: 1px solid var(--nfl-card-border);
  color: var(--nfl-text);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}
.nfl-ds-td--numeric { text-align: right; }
.nfl-ds-td--empty {
  text-align: center;
  color: var(--nfl-text-muted);
  font-style: italic;
  padding: var(--nfl-space-4, 1rem);
}

.nfl-ds-td__dash { color: var(--nfl-text-faint); }

.nfl-ds-tr[data-nfl-row-href] {
  cursor: pointer;
  transition: background 0.12s ease-out;
}
.nfl-ds-tr[data-nfl-row-href]:hover {
  background: var(--nfl-mid-bg);
}

.nfl-ds-td__link {
  color: var(--nfl-accent);
  text-decoration: none;
}
.nfl-ds-td__link:hover { text-decoration: underline; }

/* ================================================================
 * 9. Sparkline
 * ================================================================ */
.nfl-ds-sparkline {
  display: inline-block;
  vertical-align: middle;
  position: relative;
}
.nfl-ds-sparkline__canvas {
  display: block;
  max-width: 100%;
  height: auto;
}

/* ================================================================
 * 10. Chart-specific card tweaks + empty state
 * ================================================================ */
.nfl-ds-card--chart .nfl-ds-chart {
  width: 100%;
}

.nfl-ds-empty {
  padding: var(--nfl-space-5, 1.5rem);
  text-align: center;
  color: var(--nfl-text-muted);
  font-style: italic;
  margin: 0;
}

/* ================================================================
 * 11. Responsive breakpoints (DistroKid-style progressive collapse)
 * ================================================================ */
/* v0.36.5.11.4.1 — clean 12-tile factorizations at every level.
 * Desktop: 6×2 (rule above at 112). Tablet portrait + large phone:
 * 4×3. Standard phone (down to 320px): 3×4. The old 2-col / 1-col
 * fallback for KPI strip was absurd for a 12-tile strip — scrapped. */
@media (max-width: 959px) {
  .nfl-ds-kpi-strip {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
@media (max-width: 479px) {
  .nfl-ds-kpi-strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .nfl-ds-header__row {
    flex-direction: column;
    align-items: stretch;
  }
  .nfl-ds-card {
    padding: 0.55rem 0.65rem;
  }
  .nfl-ds-table-wrap {
    margin: 0 -0.65rem;
    padding: 0 0.65rem;
  }
}

/* ================================================================
 * 12. Team page — v0.26.0 (Chat 2) page-specific layout
 *
 * Namespace: .nfl-tp* (team page) and .nfl-tp-card* (cards on that page).
 * These compose the design-system primitives; no primitive styles are
 * overridden — only layout glue.
 * ================================================================ */
.nfl-tp {
  /* Body background slightly darker than cards so cards visually pop. */
  background: var(--nfl-page-bg);
}

.nfl-tp__container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0.75rem 1rem 2rem;
}

/* -------------------------------------------------------------------------
 * v0.44.1.5 — page shells that emitted a container class with NO rule behind
 * it. /leaderboards/ and /account/ both render `<main class="site-main
 * nfl-lb|nfl-account">` + `<div class="nfl-XX__container">`, exactly like the
 * team page above — but nothing ever styled those two class names, so their
 * content ran edge-to-edge with no max-width, centering, or padding while
 * /teams/, /stats/ and /stat/ looked correct. Same geometry as .nfl-tp__*
 * so every template surface reads as one product.
 * ---------------------------------------------------------------------- */
.nfl-lb,
.nfl-account,
.nfl-stat-detail,
.nfl-stats-index {
  background: var(--nfl-page-bg);
}

.nfl-lb__container,
.nfl-account__container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0.75rem 1rem 2rem;
}

/* The primary nav renders ABOVE each page's container (outside it) on every
 * template surface, and `.nfl-nav` itself had no rule — only `.nfl-nav__list`
 * did — so the nav row sat flush against the viewport edge on all of them.
 * Match the container geometry so the nav lines up with the content beneath
 * it. The list keeps its own 20px inline padding, so this shell carries none. */
.nfl-nav {
  max-width: 1200px;
  margin: 0 auto;
}

.nfl-tp__notice {
  background: var(--nfl-bad-bg);
  color: var(--nfl-text);
  border: 1px solid var(--nfl-bad);
  border-radius: 6px;
  padding: 0.6rem 0.85rem;
  margin: 0.75rem auto 0;
  max-width: 1200px;
  font-size: 0.9rem;
}

/* Sticky-header content pieces */
.nfl-tp__breadcrumb {
  display: inline-block;
  font-size: 0.82rem;
  color: var(--nfl-text-muted);
  text-decoration: none;
  margin-bottom: 0.15rem;
}
.nfl-tp__breadcrumb:hover { color: var(--nfl-accent); text-decoration: underline; }

.nfl-tp__title {
  margin: 0;
  font-size: clamp(1.35rem, 2.2vw, 1.75rem);
  line-height: 1.2;
  color: var(--nfl-text);
  font-weight: 700;
}

.nfl-tp__meta {
  margin: 0.1rem 0 0;
  font-size: 0.8rem;
  color: var(--nfl-text-muted);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* v0.26.1 — compact team + year switcher in the sticky header right side.
 * Replaces the old .nfl-tp__year-form (year-only) plus the deleted
 * .nfl-tp__teams-strip 32-team grid at the bottom. Native <select>s
 * with <optgroup> for divisions = keyboard-friendly, accessible, zero-JS. */
.nfl-tp__switcher {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.nfl-tp__switcher-label {
  font-size: 0.78rem;
  color: var(--nfl-text-muted);
  white-space: nowrap;
  font-weight: 500;
}

.nfl-tp__switcher-select {
  font: inherit;
  font-size: 0.9rem;
  padding: 4px 8px;
  border: 1px solid var(--nfl-card-border);
  border-radius: 4px;
  background: var(--nfl-card-bg);
  color: var(--nfl-text);
  min-height: 32px;
  max-width: 240px;
}

/* The year form inside the switcher keeps its inline-flex alignment
 * so label + select + noscript button all sit on one line. */
.nfl-tp__switcher .nfl-tp__year-form {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
}

/* Two-column body (Section 2) */
.nfl-tp__cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.85rem;
  margin-top: 0.5rem;
  align-items: start;
}
.nfl-tp__col { min-width: 0; }

/* v0.33.0 — Principle #11 temporal separation.
 *
 * .nfl-tp__upcoming-slot wraps the matchup card at the top of a
 * current-season team page. Full width, accent border to signal
 * "this is what you came here for." Renders once per page.
 *
 * .nfl-tp-card--season-story is the historical-layout top card (empty
 * state until v0.36.0 wires seeded insights). Styled lighter than
 * upcoming-slot to signal "context, not call-to-action."
 */
.nfl-tp__upcoming-slot {
  margin: 0.5rem 0 1rem;
}
.nfl-tp__upcoming-slot .nfl-tp-card--matchup {
  border-top: 3px solid var(--nfl-accent, #0f62fe);
}
.nfl-tp-card--season-story {
  margin: 0.5rem 0 1rem;
  background: #fafbfc;
}
.nfl-tp-card--season-story .nfl-ds-card__title {
  color: var(--nfl-text-muted);
}

/* Matchup card meta line */
.nfl-tp-matchup__meta {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  color: var(--nfl-text-muted);
}

.nfl-tp-matchup__table th[scope="row"] {
  font-weight: 500;
  white-space: nowrap;
}

/* Triple strip (Section 4) */
.nfl-tp__triple {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.85rem;
  margin-top: 0.5rem;
  align-items: start;
}

/* Tile variant — cards in the triple strip are denser.
 * v0.26.1: tighter paddings + rank-pill column doesn't need to be
 * fixed-width; stat column gets elbow room so labels like
 * "Pass Cmp Opp · DEF" fit without forcing a horizontal scroll. */
.nfl-tp-card--tile .nfl-ds-card__subtitle {
  display: none;  /* saves vertical space; titles are self-describing */
}
.nfl-tp-card--tile .nfl-ds-table {
  font-size: 0.82rem;
  table-layout: auto;
}
.nfl-tp-card--tile .nfl-ds-th,
.nfl-tp-card--tile .nfl-ds-td {
  padding: 4px 6px;
}
.nfl-tp-card--tile .nfl-ds-td:first-child {
  word-break: break-word;
}
/* Shrink the rank pill specifically inside tiles so the last column
 * doesn't hog width. The pill remains legible; only the horizontal
 * padding is reduced. */
.nfl-tp-card--tile .nfl-ds-rank {
  padding: 1px 6px;
  font-size: 0.75rem;
}

/* Responsive — collapse cols / triples on narrower screens */
@media (max-width: 960px) {
  .nfl-tp__cols {
    grid-template-columns: 1fr;
  }
  .nfl-tp__triple {
    grid-template-columns: 1fr;
  }
}

/* Hide the old team-page classes that no longer ship in the v0.26.0
 * render. If any theme CSS still targets .nfl-team-page__* we don't
 * want it leaking styles to these unrelated elements. */
.nfl-tp .nfl-team-page__stats-row,
.nfl-tp .nfl-team-page__mid,
.nfl-tp .nfl-team-page__bottom { display: none; }

/* ======================================================================
 * Teams Index — v0.29.0
 * ====================================================================== */

.nfl-teams-index { padding: 0; }
.nfl-teams-index__container { max-width: 1200px; margin: 0 auto; padding: 16px; }

.nfl-teams-index__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0 16px 0;
  border-bottom: 1px solid var(--nfl-border, #e5e7eb);
  margin-bottom: 16px;
}
.nfl-teams-index__header-main { flex: 1 1 auto; }
.nfl-teams-index__title { margin: 0 0 4px 0; font-size: 1.75rem; }
.nfl-teams-index__subtitle { margin: 0; color: var(--nfl-muted, #6b7280); font-size: 0.875rem; }

.nfl-teams-index__year-form {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  flex: 0 0 auto;
}
.nfl-teams-index__year-form label {
  font-size: 0.75rem;
  color: var(--nfl-muted, #6b7280);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.nfl-teams-index__year-form select {
  padding: 4px 8px;
  border: 1px solid var(--nfl-border, #d1d5db);
  border-radius: 4px;
  background: #fff;
  font-size: 0.875rem;
}

/* KPI strip — 5 tiles, wraps on mobile. */
.nfl-teams-index__kpi-strip {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
  margin: 0 0 20px 0;
}
.nfl-teams-index__kpi {
  background: #fff;
  border: 1px solid var(--nfl-border, #e5e7eb);
  border-radius: 8px;
  padding: 12px 14px;
  position: relative;
  min-height: 96px;
}
.nfl-teams-index__kpi .nfl-ds-kpi-tile__label {
  font-size: 0.7rem;
  color: var(--nfl-muted, #6b7280);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 6px;
}
.nfl-teams-index__kpi .nfl-ds-kpi-tile__value {
  font-size: 1.25rem;
  font-weight: 600;
  margin-bottom: 4px;
  font-variant-numeric: tabular-nums;
}
.nfl-teams-index__kpi .nfl-ds-kpi-tile__hint {
  font-size: 0.75rem;
  color: var(--nfl-muted, #6b7280);
}
.nfl-teams-index__kpi-rank {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 0.6875rem;
  padding: 1px 6px;
  background: var(--nfl-accent-soft, #dbeafe);
  color: var(--nfl-accent, #1d4ed8);
  border-radius: 999px;
  font-weight: 600;
}

@media (max-width: 960px) {
  .nfl-teams-index__kpi-strip { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 520px) {
  .nfl-teams-index__kpi-strip { grid-template-columns: 1fr; }
  .nfl-teams-index__header { flex-direction: column; align-items: stretch; }
}

/* Cards section spacing */
.nfl-teams-index__card { margin: 0 0 20px 0; }

/* By-division grid: 4 compact cards, 2 cols on tablet, 1 col on mobile. */
.nfl-teams-index__div-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
@media (max-width: 1080px) { .nfl-teams-index__div-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .nfl-teams-index__div-grid { grid-template-columns: 1fr; } }

.nfl-teams-index__div-card {
  background: #fff;
  border: 1px solid var(--nfl-border, #e5e7eb);
  border-radius: 6px;
  padding: 10px 12px;
}
.nfl-teams-index__div-title {
  margin: 0 0 8px 0;
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--nfl-muted, #6b7280);
  border-bottom: 1px solid var(--nfl-border, #f3f4f6);
  padding-bottom: 4px;
}
.nfl-teams-index__div-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.nfl-teams-index__div-row { margin: 0; }
.nfl-teams-index__div-row-link {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  grid-template-areas:
    "abbr name   rank"
    "abbr record record"
    "abbr ats    divrec";
  column-gap: 8px;
  row-gap: 2px;
  padding: 6px 0;
  border-bottom: 1px solid var(--nfl-border, #f3f4f6);
  text-decoration: none;
  color: inherit;
  align-items: center;
}
.nfl-teams-index__div-row:last-child .nfl-teams-index__div-row-link { border-bottom: none; }
.nfl-teams-index__div-row-link:hover { background: var(--nfl-hover, #f9fafb); }
.nfl-teams-index__div-abbr {
  grid-area: abbr;
  font-weight: 700;
  font-size: 0.875rem;
}
.nfl-teams-index__div-name {
  grid-area: name;
  font-size: 0.8125rem;
}
.nfl-teams-index__div-rank {
  grid-area: rank;
  font-size: 0.6875rem;
}
.nfl-teams-index__div-record,
.nfl-teams-index__div-ats,
.nfl-teams-index__div-divrec {
  font-size: 0.75rem;
  color: var(--nfl-muted, #6b7280);
  font-variant-numeric: tabular-nums;
}
.nfl-teams-index__div-record { grid-area: record; }
.nfl-teams-index__div-ats    { grid-area: ats; }
.nfl-teams-index__div-divrec { grid-area: divrec; }
.nfl-teams-index__empty { margin: 0; color: var(--nfl-muted, #6b7280); font-size: 0.8125rem; }

/* ======================================================================
 * Team Page — v0.30.0 delta-bar panels
 * ====================================================================== */

.nfl-tp-deltapanel {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 4px 0;
}
.nfl-tp-deltapanel__row {
  display: grid;
  grid-template-columns: minmax(140px, 1.6fr) 64px 1fr 72px;
  align-items: center;
  gap: 10px;
}
.nfl-tp-deltapanel__label {
  font-size: 0.875rem;
  color: var(--nfl-text, #111827);
  font-weight: 500;
}
.nfl-tp-deltapanel__side {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--nfl-muted-bg, #f3f4f6);
  color: var(--nfl-muted, #6b7280);
  font-size: 0.625rem;
  font-weight: 600;
  letter-spacing: 0.05em;
}
.nfl-tp-deltapanel__val {
  font-variant-numeric: tabular-nums;
  font-size: 0.875rem;
  font-weight: 600;
  text-align: right;
  color: var(--nfl-text, #111827);
}
.nfl-tp-deltapanel__bar {
  /* The delta-bar primitive rendered inline; ensure it fills this column. */
  display: block;
  width: 100%;
}
.nfl-tp-deltapanel__bar .nfl-ds-delta {
  /* v0.36.5.5.2 — flex (not block) so the inner .nfl-ds-delta__track keeps
     its `flex: 1` stretching behavior. Pre-5.5.2 was `display: block`, which
     made `flex: 1` inert and collapsed the track to its `min-width: 40px`.
     At 40px the bar fill (e.g. 26.58% wide for val=228, center=214.812)
     became a ~10px gray smear next to the 1px vertical zero marker — read
     to operators as "no bar visible." Only surfaced on the Team Conversions
     Family Card because every other family renders a bespoke chart instead
     of the delta panel fallback. */
  display: flex;
  width: 100%;
}
.nfl-tp-deltapanel__rank {
  justify-self: end;
}
.nfl-tp-deltapanel__caption {
  margin: 10px 0 0 0;
  padding-top: 8px;
  border-top: 1px dashed var(--nfl-border, #e5e7eb);
  font-size: 0.75rem;
  color: var(--nfl-muted, #6b7280);
}

/* Top/Bottom 10 inside narrow tile: tighter columns. */
.nfl-tp-card--topbottom .nfl-tp-deltapanel__row {
  grid-template-columns: minmax(110px, 1.4fr) 48px 1fr 60px;
  gap: 8px;
}
.nfl-tp-card--topbottom .nfl-tp-deltapanel__label { font-size: 0.8125rem; }
.nfl-tp-card--topbottom .nfl-tp-deltapanel__val { font-size: 0.8125rem; }

@media (max-width: 620px) {
  .nfl-tp-deltapanel__row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "label rank"
      "bar bar"
      "val val";
    row-gap: 4px;
  }
  .nfl-tp-deltapanel__label { grid-area: label; }
  .nfl-tp-deltapanel__val   { grid-area: val;   text-align: left; }
  .nfl-tp-deltapanel__bar   { grid-area: bar; }
  .nfl-tp-deltapanel__rank  { grid-area: rank; }
}

/* ======================================================================
 * Team Page — v0.31.0 stat family grid
 * ====================================================================== */

/* Section heading (Offense / Defense) sits above the grid. */
.nfl-tp-section {
  margin: 24px 0;
}
.nfl-tp-section__heading {
  margin: 0 0 12px 0;
  padding-bottom: 6px;
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--nfl-text, #111827);
  border-bottom: 2px solid var(--nfl-border, #e5e7eb);
  letter-spacing: 0.02em;
}

/* Family grid wrapper */
.nfl-tp-family-grid {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Full-width row — single card takes the whole container */
.nfl-tp-family-grid__row--full {
  display: block;
}
.nfl-tp-family-grid__row--full > .nfl-tp-card--family {
  width: 100%;
}

/* Paired row — two cards side-by-side on desktop. */
.nfl-tp-family-grid__row--pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}

/* Tablet: stay two columns until we run out of room. */
@media (max-width: 900px) {
  .nfl-tp-family-grid__row--pair {
    grid-template-columns: 1fr;
  }
}

/* Family cards are slightly denser than monolithic cards. */
.nfl-tp-card--family {
  margin: 0;
}
.nfl-tp-card--family .nfl-ds-card__head {
  padding-bottom: 6px;
}
.nfl-tp-card--family .nfl-ds-card__title {
  font-size: 1rem;
}
.nfl-tp-card--family .nfl-ds-card__body {
  padding-top: 10px;
}

/* ==================================================================
 * v0.36.5.8 — Class M: Teams Index footer cards + Team Page footer nav
 * Adds team-color-chip primitive (no 5.3g equivalent existed; new in 5.8)
 * + 5 new card layouts + responsive breakpoints.
 * ================================================================== */

/* --- team-color-chip primitive (used by both /teams/ + team page nav) --- */
.nfl-ti-team-chip,
.nfl-tp-footer-nav__chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border: 1px solid var(--nfl-border, #e5e7eb);
  border-left: 4px solid var(--nfl-ds-team-color, var(--nfl-accent, #2563eb));
  border-radius: 6px;
  background: var(--nfl-muted-bg, #f9fafb);
  color: var(--nfl-text, #111827);
  text-decoration: none;
  font-size: 0.8125rem;
  transition: background 0.12s ease, transform 0.12s ease;
}
.nfl-ti-team-chip:hover,
.nfl-tp-footer-nav__chip:hover {
  background: var(--nfl-card-bg, #fff);
  transform: translateX(2px);
}
.nfl-ti-team-chip__abbr,
.nfl-tp-footer-nav__chip-abbr {
  font-weight: 700;
  font-size: 0.875rem;
  letter-spacing: 0.02em;
}
.nfl-ti-team-chip__name,
.nfl-tp-footer-nav__chip-name {
  color: var(--nfl-muted, #6b7280);
}
.nfl-ti-team-chip__tail,
.nfl-tp-footer-nav__chip-tail {
  margin-left: auto;
  color: var(--nfl-muted, #6b7280);
  font-variant-numeric: tabular-nums;
  font-size: 0.75rem;
}

/* --- M1a Conference Splits card --- */
.nfl-ti-conf-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.nfl-ti-conf-split__col {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.nfl-ti-conf-split__heading {
  margin: 0 0 4px 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--nfl-muted, #6b7280);
}
.nfl-ti-conf-split__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.nfl-ti-conf-split__list > li > a {
  width: 100%;
}

/* --- M1b Best/Worst leaderboard cards --- */
.nfl-ti-mini-lb {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.nfl-ti-mini-lb__col {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.nfl-ti-mini-lb__heading {
  margin: 0 0 4px 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.nfl-ti-mini-lb__col--good .nfl-ti-mini-lb__heading { color: var(--nfl-good, #16a34a); }
.nfl-ti-mini-lb__col--bad  .nfl-ti-mini-lb__heading { color: var(--nfl-bad,  #dc2626); }
.nfl-ti-mini-lb__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.nfl-ti-mini-lb__list > li > a {
  width: 100%;
}

/* --- M1c Algorithm Spread leaderboard --- */
.nfl-ti-algo-spread__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.nfl-ti-algo-spread__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 10px;
  border: 1px solid var(--nfl-border, #e5e7eb);
  border-radius: 6px;
  background: var(--nfl-muted-bg, #f9fafb);
  font-size: 0.8125rem;
}
.nfl-ti-algo-spread__game {
  font-weight: 600;
}
.nfl-ti-algo-spread__spread {
  color: var(--nfl-muted, #6b7280);
  font-variant-numeric: tabular-nums;
}

/* --- M1d Biggest Movers --- */
.nfl-ti-movers__list {
  margin: 0;
  padding: 0 0 0 20px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.nfl-ti-movers__list > li > a {
  width: 100%;
}

/* --- M2 Team Page footer nav --- */
.nfl-tp-footer-nav {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--nfl-border, #e5e7eb);
}
.nfl-tp-footer-nav__rail {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.nfl-tp-footer-nav__heading {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--nfl-muted, #6b7280);
}
.nfl-tp-footer-nav__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.nfl-tp-footer-nav__breadcrumb {
  margin-top: 8px;
}
.nfl-tp-footer-nav__breadcrumb-link {
  font-size: 0.875rem;
  color: var(--nfl-accent, #2563eb);
  text-decoration: none;
}
.nfl-tp-footer-nav__breadcrumb-link:hover {
  text-decoration: underline;
}
.nfl-tp-footer-nav__year-switcher {
  margin-top: 8px;
}

/* --- Responsive breakpoints --- */
@media (max-width: 720px) {
  .nfl-ti-conf-split { grid-template-columns: 1fr; }
}
@media (max-width: 540px) {
  .nfl-ti-mini-lb    { grid-template-columns: 1fr; }
  .nfl-ti-algo-spread__row { flex-wrap: wrap; gap: 4px; }
  .nfl-tp-footer-nav__chips { flex-direction: column; }
  .nfl-tp-footer-nav__chip  { width: 100%; }
}

/* --- v0.36.5.8.1 League Snapshot heatmap wrapper --- */
.nfl-teams-index__heatmap {
  /* Inherits Heatmap_Renderer base styles; this wrapper handles
     responsive overflow for the 32-column layout. */
  margin: 0;
}
.nfl-teams-index__heatmap .nfl-heatmap__grid-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.nfl-teams-index__heatmap .nfl-heatmap__grid {
  min-width: 900px;        /* 32 team cols + stat name col need space */
  font-variant-numeric: tabular-nums;
}
.nfl-teams-index__heatmap .nfl-heatmap__col-header {
  scroll-snap-align: start;
}
.nfl-teams-index__heatmap .nfl-heatmap__row-header {
  position: sticky;
  left: 0;
  background: var(--nfl-card-bg, #fff);
  z-index: 1;
}
@media (max-width: 960px) {
  .nfl-teams-index__heatmap .nfl-heatmap__grid-wrap { font-size: 0.75rem; }
}

/* ==================================================================
 * v0.36.5.10 — Family Card chart-view layout: scoring radar + drives bars
 * ================================================================== */
.nfl-tp-card--family .nfl-ds-chart canvas {
  /* Default canvas height for radar (320px set in PHP via height opt).
     Bar chart sets its own 260px. This rule is a safety net for
     responsive breakpoints below. */
  max-width: 100%;
}
@media (max-width: 540px) {
  /* Scoring radar axis labels collapse to short forms via CSS-only;
     the SVG text remains long but the parent narrows. Tighten font. */
  .nfl-tp-card--family .nfl-ds-chart {
    font-size: 0.6875rem;
  }
  /* Horizontal bar labels on drives card stay legible by allowing
     wrapping in the chart card's surrounding flow — Chart.js handles
     the canvas-internal text. Just give the card a bit more vertical
     room when narrow. */
  .nfl-tp-card--family[data-family="drives"] .nfl-ds-chart {
    min-height: 320px;
  }
}

/* ==================================================================
 * v0.36.5.11 — Passing/Rushing bubble charts + Scoring Composition card
 * ================================================================== */
.nfl-tp-card--scoring-composition .nfl-ds-chart {
  /* Single-row stacked bar: keep the canvas short, legend below. */
  max-width: 100%;
}
.nfl-tp-card--scoring-composition .nfl-ds-card__body {
  padding-bottom: 8px;
}
/* Bubble chart wrapper: percentile-rank axes need a touch more breathing
   room than the old 260px scatter — let canvas dictate via height opt. */
.nfl-tp-card--family[data-family="passing"] .nfl-ds-chart,
.nfl-tp-card--family[data-family="rushing"] .nfl-ds-chart {
  max-width: 100%;
}
@media (max-width: 540px) {
  /* Stacked-bar legend wraps below on mobile — Chart.js handles, but
     allow extra room so chips don't crowd. */
  .nfl-tp-card--scoring-composition .nfl-ds-chart {
    min-height: 220px;
  }
  /* Bubble dots are sized in px so they don't auto-shrink at narrow
     viewports — keep the chart from clipping. */
  .nfl-tp-card--family[data-family="passing"] .nfl-ds-chart,
  .nfl-tp-card--family[data-family="rushing"] .nfl-ds-chart {
    min-height: 280px;
  }
}

/* ==================================================================
 * v0.36.5.11.2 — Scoring Pair section (Off + Def Scoring side-by-side)
 *
 * Lives above the .nfl-tp-section--off / --def parent sections so each
 * Scoring & Efficiency card fills its half of a 2-column grid (radar
 * polygons fill their cells instead of rendering at ~30% in a
 * full-width card).
 * ================================================================== */
.nfl-tp-section--scoring-pair {
  margin-bottom: 14px;
}
.nfl-tp-section--scoring-pair__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 14px;
}
/* Match existing family-grid pair-row breakpoint (900px). Stack on
   tablet/mobile when paired side-by-side would crush each cell. */
@media (max-width: 900px) {
  .nfl-tp-section--scoring-pair__grid {
    grid-template-columns: 1fr;
  }
}

/* ==================================================================
 * v0.36.5.11.3 — KPI tile secondary line + Head-to-Head card layout
 * ================================================================== */

/* Secondary line on a KPI tile — additive helper used by Record (Pythag)
 * and SoS Rank (sos_pts) tiles. Sits between the value and the meta
 * (rank pill) row. Existing tiles that don't set $tile['secondary']
 * are unaffected. */
.nfl-ds-kpi__secondary {
  /* v0.36.5.11.4.1 — shrunk to match densified tile sizing */
  font-size: 0.7em;
  line-height: 1.2;
  opacity: 0.78;
  margin-top: 1px;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums;
}

/* Head-to-Head card body. Re-uses .nfl-ds-table — only need a few
 * alignment tweaks + the footnote treatment. */
.nfl-tp-card--h2h .nfl-ds-table th,
.nfl-tp-card--h2h .nfl-ds-table td {
  vertical-align: middle;
}
.nfl-tp-h2h__footnote {
  margin-top: 8px;
  font-size: 0.8em;
}

/* Mobile responsive: horizontal scroll on narrow viewport instead of
 * column wrap. .nfl-ds-table-wrap already has overflow-x:auto in the
 * DS base styles; just ensure the H2H wrapper inherits cleanly. */
@media (max-width: 540px) {
  .nfl-tp-card--h2h .nfl-ds-table-wrap {
    -webkit-overflow-scrolling: touch;
  }
}

/* ==================================================================
 * v0.36.5.11.4 — Streaks & Trends + Schedule Context + BP margin toggle
 * ================================================================== */

/* ==================================================================
 * v0.36.5.11.9 — Card-section wrapper + table layout + page-level
 * 2-column grid for betting-context cards. Replaces:
 *   - 5.11.4 Streaks & Trends bespoke layout (3-tile chip / 6-tile
 *     longest row / 3-col bucket grid). DEAD CODE removed.
 *   - 5.11.7 horizontal-strip layout (.nfl-tp-cut__rows / __row /
 *     __label / __games / __stat / __pct). DEAD CODE removed.
 *   - 5.11.8 intra-card 2-col bucket grid + readability tweaks.
 *     DEAD CODE removed.
 * Every cut on every betting-context card now speaks the same
 * visual language: a small <table>.
 * ================================================================== */

/* ---------- Cut section wrapper (carried forward from 5.11.7) ---------- */

.nfl-tp-cut {
  margin-bottom: 0.75rem;
}
.nfl-tp-cut:last-child {
  margin-bottom: 0;
}

.nfl-tp-cut__title {
  font-size: 0.85rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--nfl-ds-text-muted, #6a7280);
  margin: 0 0 0.4rem 0;
}

.nfl-tp-cut__empty {
  font-size: 0.8rem;
  font-style: italic;
  color: var(--nfl-ds-text-muted, #6a7280);
  padding: 0.25rem 0.5rem;
}

.nfl-tp-cut__footnote {
  margin: 0.6rem 0 0 0;
  font-size: 0.75rem;
  color: var(--nfl-ds-text-muted, #6a7280);
  font-style: italic;
}

/* ---------- Table layout (NEW in 5.11.9) ---------- */

/* Column model:
 *   Bucket          — left-aligned, takes remaining space
 *   G               — right-aligned integer
 *   SU / ATS / O/U  — right-aligned record (W-L or W-L-P)
 *   ATS%            — right-aligned, slightly bolder, summary
 */
.nfl-tp-cut__table {
  width: 100%;
  border-collapse: collapse;
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.35;
}

.nfl-tp-cut__th {
  font-weight: 500;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--nfl-ds-text-muted, #6a7280);
  padding: 0.25rem 0.5rem;
  border-bottom: 0.5px solid var(--nfl-ds-border-tertiary, rgba(0, 0, 0, 0.12));
  text-align: right;
  white-space: nowrap;
}

.nfl-tp-cut__th--bucket,
.nfl-tp-cut__td--bucket {
  text-align: left;
}

.nfl-tp-cut__td {
  padding: 0.3rem 0.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  font-weight: 400;
}

/* <th scope="row"> defaults to bold; we want body weight to match the
 * rest of the row */
.nfl-tp-cut__td--bucket {
  font-weight: 400;
}

.nfl-tp-cut__td--pct {
  font-weight: 500;
}

.nfl-tp-cut__table tbody tr {
  border-bottom: 0.5px solid var(--nfl-ds-border-tertiary, rgba(0, 0, 0, 0.06));
}
.nfl-tp-cut__table tbody tr:last-child {
  border-bottom: none;
}
.nfl-tp-cut__table tbody tr:hover {
  background: var(--nfl-ds-surface-2, rgba(0, 0, 0, 0.025));
}

/* Narrow variant for Streaks & Trends sub-tables (2 or 3 columns).
 * Doesn't reserve full card width — sizes to content. */
.nfl-tp-cut__table--narrow {
  width: auto;
  min-width: 60%;
}

/* ---------- Page-level 2-column grid for betting-context cards ---------- */

/* Left col (top→bottom):  Schedule Context, Weather
 * Right col (top→bottom): Streaks & Trends, Travel & Venue Context
 *
 * Each column is an independent flex stack; cards inside it size to
 * their content. At <720px the grid collapses to a single column and
 * cards stack vertically full-width. */
.nfl-tp-betting-context-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
  margin-bottom: 1rem;
  align-items: start;
}

.nfl-tp-betting-context-grid__col {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  min-width: 0;
  padding-bottom: 0.5rem;
}

@media (max-width: 720px) {
  .nfl-tp-betting-context-grid {
    grid-template-columns: 1fr;
    gap: 0.75rem;
  }
  .nfl-tp-betting-context-grid__col {
    padding-bottom: 0;
  }
}
/* ---------- Betting Profile margin toggle ---------- */

/* Margin columns are columns 8-11 of the BP table. CSS-only hide-by-default
 * via nth-child; "Show margins" button toggles a state attribute on the
 * wrap div. JS attached via assets/js/nfl-lines-charts.js (or inline if needed).
 */
.nfl-bp-margins-toolbar {
  margin-bottom: 8px;
  display: flex;
  justify-content: flex-end;
}
.nfl-bp-margins-wrap[data-bp-margins="hidden"] .nfl-ds-table th:nth-child(n+8),
.nfl-bp-margins-wrap[data-bp-margins="hidden"] .nfl-ds-table td:nth-child(n+8) {
  display: none;
}
.nfl-bp-margins-toggle[aria-pressed="true"] {
  background: var(--nfl-ds-accent, #2c5282);
  color: #fff;
}

/* ==================================================================
 * v0.36.5.12 — Visualization layer: Betting Profile Heatmap, Spread-
 * Role Performance, Vegas Accuracy.
 *
 * Color tokens shared across the heatmap cells and any future tier-
 * colored visuals. ATS% thresholds match Bucket_Grid_Renderer defaults.
 * ================================================================== */

:root {
  --nfl-ds-bp-cover:       #2f8a55;   /* ATS% ≥ 60 — clearly profitable */
  --nfl-ds-bp-cover-mid:   #87b87a;   /* 55-59 — leans cover */
  --nfl-ds-bp-neutral:     #d4d4d4;   /* 45-54 — near coin-flip */
  --nfl-ds-bp-nocover-mid: #d49d8a;   /* 40-44 — leans no-cover */
  --nfl-ds-bp-nocover:     #b04545;   /* < 40 — clearly losing */
}

/* ---------- Betting Profile Heatmap card ---------- */

.nfl-tp-bp-heatmap {
  margin-top: 0.25rem;
}

.nfl-tp-bp-heatmap__caption {
  margin: 0 0 0.5rem 0;
  font-size: 0.85rem;
  color: var(--nfl-ds-text-muted, #6a7280);
}

.nfl-tp-bp-heatmap__grid {
  display: grid;
  /* grid-template-columns set inline by renderer:
   *   12rem repeat(N, minmax(0, 1fr))
   * where N = max_bucket_count (default 5). */
  gap: 0.4rem;
  align-items: stretch;
}

.nfl-tp-bp-heatmap__row-label {
  font-size: 0.78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--nfl-ds-text-muted, #6a7280);
  padding: 0.5rem 0.25rem 0.5rem 0;
  align-self: center;
}

.nfl-tp-bp-heatmap__cell {
  padding: 0.4rem 0.5rem;
  border-radius: 4px;
  min-height: 3.2rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  color: var(--nfl-ds-text, #1d2327);
  line-height: 1.2;
}

.nfl-tp-bp-heatmap__cell-bucket {
  font-weight: 600;
  font-size: 0.78rem;
}
.nfl-tp-bp-heatmap__cell-record {
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
}
.nfl-tp-bp-heatmap__cell-count {
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
}

.nfl-tp-bp-heatmap__cell--good { background: var(--nfl-ds-bp-cover); }
.nfl-tp-bp-heatmap__cell--okay { background: var(--nfl-ds-bp-cover-mid); }
.nfl-tp-bp-heatmap__cell--mid  { background: var(--nfl-ds-bp-neutral); }
.nfl-tp-bp-heatmap__cell--meh  { background: var(--nfl-ds-bp-nocover-mid); }
.nfl-tp-bp-heatmap__cell--bad  { background: var(--nfl-ds-bp-nocover); color: #fff; }
.nfl-tp-bp-heatmap__cell--good { color: #fff; }

/* Invisible placeholder cell to consume grid slot when a row has fewer
 * than max_bucket_count buckets. Renderer emits these to keep rows
 * aligned. */
.nfl-tp-bp-heatmap__cell-placeholder {
  background: transparent;
}

.nfl-tp-bp-heatmap__row-empty {
  font-size: 0.85rem;
  font-style: italic;
  color: var(--nfl-ds-text-muted, #6a7280);
  padding: 0.5rem 0.25rem;
  align-self: center;
}

.nfl-tp-bp-heatmap__empty {
  font-size: 0.85rem;
  font-style: italic;
  color: var(--nfl-ds-text-muted, #6a7280);
  padding: 0.5rem 0;
}

.nfl-tp-bp-heatmap__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.6rem;
  font-size: 0.75rem;
  color: var(--nfl-ds-text-muted, #6a7280);
  align-items: center;
}
.nfl-tp-bp-heatmap__legend-title {
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.nfl-tp-bp-heatmap__legend-band {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-variant-numeric: tabular-nums;
}
.nfl-tp-bp-heatmap__legend-swatch {
  width: 0.9rem;
  height: 0.9rem;
  border-radius: 2px;
  display: inline-block;
}

/* ---------- Spread-Role Performance card ---------- */

.nfl-tp-card--spread-role .nfl-ds-card__body {
  padding-top: 0.25rem;
}

/* ---------- Vegas Accuracy card ---------- */

/* v0.36.5.12.1 — readability fix. Companion metrics are the headline
 * summary above the scatter; pre-5.12.1 they rendered in muted gray at
 * 0.75rem so the bias note read DARKER than the actual stat values.
 * Fix: body text color + 0.95rem + bold weight on labels. Bias note
 * stays muted+italic because it's the interpretive aside. */
.nfl-tp-vegas-accuracy__metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin-bottom: 0.75rem;
  font-size: 0.95rem;
  color: var(--nfl-ds-text, #1d2327);
  line-height: 1.4;
}
.nfl-tp-vegas-accuracy__metric {
  font-variant-numeric: tabular-nums;
}
.nfl-tp-vegas-accuracy__metric strong {
  font-weight: 600;
  margin-right: 0.4rem;
  color: var(--nfl-ds-text, #1d2327);
}
.nfl-tp-vegas-accuracy__bias-note {
  font-style: italic;
  color: var(--nfl-ds-text-muted, #6a7280);
  font-size: 0.85rem;
  margin-left: 0.3rem;
}

/* ---------- Mobile (<720px) ---------- */

@media (max-width: 720px) {
  .nfl-tp-bp-heatmap__grid {
    grid-template-columns: 8rem repeat(5, minmax(0, 1fr)) !important;
    gap: 0.25rem;
  }
  .nfl-tp-bp-heatmap__row-label {
    font-size: 0.72rem;
  }
  .nfl-tp-bp-heatmap__cell {
    padding: 0.3rem 0.35rem;
    min-height: 2.8rem;
  }
  .nfl-tp-bp-heatmap__cell-bucket  { font-size: 0.72rem; }
  .nfl-tp-bp-heatmap__cell-record  { font-size: 0.68rem; }
  .nfl-tp-bp-heatmap__cell-count   { font-size: 0.66rem; }
  .nfl-tp-vegas-accuracy__metrics {
    gap: 1rem;
    font-size: 0.9rem;
  }
}

/* ==================================================================
 * v0.36.5.13 — Weekly Results candlestick + FG-by-distance bar
 * ================================================================== */

/* ---------- Weekly Results candlestick card ---------- */

.nfl-tp-card--weekly-candlestick {
  /* baseline card chrome inherited from .nfl-tp-card */
}
.nfl-tp-weekly-candlestick__caption {
  font-size: 0.78rem;
  color: var(--nfl-ds-text-muted, #6a7280);
  margin-top: 0.5rem;
  font-style: italic;
}

/* ---------- Special Teams FG-by-distance bar block ---------- */

.nfl-tp-st-fg-by-distance {
  margin: 0.75rem 0;
  padding-top: 0.75rem;
  border-top: 1px solid var(--nfl-ds-border-tertiary, rgba(0, 0, 0, 0.1));
}
.nfl-tp-st-fg-by-distance__caption {
  font-size: 0.78rem;
  color: var(--nfl-ds-text-muted, #6a7280);
  margin-bottom: 0.4rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ---------- Mobile (<720px) ---------- */

@media (max-width: 720px) {
  .nfl-tp-card--weekly-candlestick .nfl-ds-chart {
    height: 280px !important;
  }
  .nfl-tp-st-fg-by-distance {
    margin-top: 0.5rem;
    padding-top: 0.5rem;
  }
}

/* ==================================================================
 * v0.36.5.14 — Division Comparison inline radar + multi-year sparkline
 *
 * Multi-year sparkline separators render via SVG attributes inside
 * Charts::render_inline_sparkline_svg (Phase 3B). No additional CSS
 * needed for the separators themselves — they style off the SVG
 * stroke/opacity attributes already on the <line> elements.
 * ================================================================== */

.nfl-tp-division-radar {
  margin-bottom: 1rem;
}
.nfl-tp-division-radar .nfl-ds-chart {
  max-width: 480px;
  margin: 0 auto;
}

@media (max-width: 720px) {
  .nfl-tp-division-radar .nfl-ds-chart {
    max-width: 100%;
  }
}

/* ==================================================================
 * v0.36.5.15 — Passing Profile callout + Remaining-Schedule SoS tile
 *
 * Passing Profile uses a 3-col desktop / 2-col mobile grid (6 tiles
 * lay out as 2 rows of 3 on desktop, 3 rows of 2 on mobile). Overrides
 * the default 6-col KPI strip grid for this card only via the
 * .nfl-tp-card--passing-profile ancestor selector.
 *
 * KPI strip is now 13 tiles (added RoS SoS). Existing 6-col grid wraps
 * the 13th tile naturally as an orphan in row 3 — no rules needed
 * unless visual install surfaces a problem worth fixing.
 * ================================================================== */

.nfl-tp-card--passing-profile .nfl-ds-kpi-strip {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.5rem;
}

@media (max-width: 720px) {
  .nfl-tp-card--passing-profile .nfl-ds-kpi-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ----------------------------------------------------------------------
 * v0.36.6.0 — Stat Trajectory card (Section 4 deep-dive analytic).
 * Picker sits above the chart; loading/error states inline with picker.
 * -------------------------------------------------------------------- */

.nfl-tp-card--stat-trajectory .stat-trajectory-controls {
  margin-bottom: 0.75rem;
}

.nfl-tp-card--stat-trajectory .stat-trajectory-picker-wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.nfl-tp-card--stat-trajectory .stat-trajectory-picker-label {
  font-weight: 600;
  color: var(--nfl-color-text, #111827);
}

.nfl-tp-card--stat-trajectory .stat-trajectory-picker {
  min-width: 16rem;
  max-width: 32rem;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-radius: 4px;
  background: #fff;
  font-size: 0.95rem;
}

.nfl-tp-card--stat-trajectory .stat-trajectory-picker:disabled {
  opacity: 0.6;
  cursor: progress;
}

.nfl-tp-card--stat-trajectory .stat-trajectory-loading {
  width: 1rem;
  height: 1rem;
  border: 2px solid var(--nfl-color-border, #e5e7eb);
  border-top-color: var(--nfl-color-text, #111827);
  border-radius: 50%;
  animation: nfl-stat-trajectory-spin 0.8s linear infinite;
}

.nfl-tp-card--stat-trajectory .stat-trajectory-error {
  color: var(--nfl-bad, #b91c1c);
  font-size: 0.9rem;
}

@keyframes nfl-stat-trajectory-spin {
  to { transform: rotate(360deg); }
}

@media (max-width: 720px) {
  .nfl-tp-card--stat-trajectory .stat-trajectory-picker {
    width: 100%;
    min-width: 0;
    max-width: none;
  }
}

/* ==========================================================================
 * SHARED CHROME LAYER — v0.45.1
 * ==========================================================================
 *
 * WHY THIS EXISTS. Everything above this comment covers components INSIDE a
 * page — card, KPI strip, badge, rank, table, sparkline, empty state, header,
 * delta. It never covered page CHROME: buttons, the page container, section
 * bands, grids, filter rows, pagers. So every §44 surface invented its own —
 * 3,179 lines across eight page sheets containing 121 independent `padding:`
 * declarations, 61 `border-radius`, 33 `grid-template-columns` and 25
 * `max-width`. That is why the pages don't read as one product, and it is the
 * retrofit surface v0.45.5 inherits.
 *
 * This layer is the canonical set. v0.45.1 (SITE HOME) is built ENTIRELY from
 * it with no page sheet of its own, and stands as the reference implementation.
 *
 * RULES FOR ANYONE TOUCHING THIS FILE:
 *   1. ADDITIVE ONLY. The 82 rules above this banner are byte-locked and
 *      asserted unchanged by v045-1-site-home-self-test against
 *      tests/fixtures/nfl-lines-ds-preship-0_44_8.css.txt. Every surface loads
 *      this file; editing an existing rule changes pages you are not building.
 *   2. Prefer extending a primitive here over adding a page sheet. Since
 *      v0.44.8 a new page-scoped stylesheet is the exception that needs
 *      justifying, not the default.
 *   3. Keep these STRUCTURAL — geometry, rhythm, states. Surface-specific
 *      opinion belongs to that surface.
 * ========================================================================== */

/* ---------------------------------------------------------------- page -- */

.nfl-ds-page {
  color: var(--nfl-text, #111827);
  font-size: 16px;
  line-height: 1.55;
}

.nfl-ds-page *,
.nfl-ds-page *::before,
.nfl-ds-page *::after { box-sizing: border-box; }

/* ⚠️ THE WIDTH RULE GOES ON THE FLEX ITEM, NOT INSIDE IT.
 *
 * GeneratePress lays its content area out with flex, so <main class="site-main">
 * IS the flex item — and a flex item with no width shrink-wraps to its own
 * content. Five cuts failed to fix this because every one adjusted something
 * INSIDE the box: a container at width:100% is 100% of a box that already
 * collapsed.
 *
 * The boards escaped it by accident, not design — their content is a
 * 3-column grid with explicit tracks, so it is intrinsically wide and forces
 * the item wide. The game pages' content is a table perfectly happy at 330px,
 * so the item collapses. Same markup, opposite outcome: that difference was
 * the tell, and it was visible in source the whole time.
 *
 * min-width: 0 matters as much as the width — a flex item defaults to
 * min-width:auto and refuses to shrink below its content, which is what makes
 * a wide table overflow the viewport instead of scrolling on a phone.
 */
.nfl-ds-main {
  width: 100%;
  min-width: 0;
  flex: 1 1 auto;
}

.nfl-ds-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0.75rem 1rem 2.5rem;
  /* ⚠️ v0.46.7 — WITHOUT THIS, A CONTAINER THAT LANDS INSIDE A FLEX PARENT
     SHRINK-WRAPS TO ITS CONTENT. GeneratePress lays its content area out with
     flex, so a page that emits a bare container instead of the theme's
     <main class="site-main"> wrapper becomes a flex item and renders at
     whatever its widest line needs — roughly a third of the page, with
     correct markup inside it. Three ships shipped that way. max-width still
     caps it at 1200; this only stops it collapsing. */
  width: 100%;
}

.nfl-ds-container--narrow { max-width: 900px; }
.nfl-ds-container--wide   { max-width: 1360px; }

/* --------------------------------------------------------------- bands -- */

/* A full-width section with its own background — the hero/closer shape every
   §44 page re-derived independently. */
.nfl-ds-band {
  border-radius: 14px;
  padding: 40px 24px;
  margin: 0 0 var(--nfl-ds-gap, 20px);
}

.nfl-ds-band--dark {
  background: var(--nfl-text, #111827);
  color: #fff;
}

.nfl-ds-band--dark h1,
.nfl-ds-band--dark h2,
.nfl-ds-band--dark h3 { color: #fff; }

.nfl-ds-band--accent { background: var(--nfl-accent-bg, #dbeafe); }
.nfl-ds-band--muted  { background: var(--nfl-page-bg, #fafafa); }
.nfl-ds-band--center { text-align: center; }

.nfl-ds-band__title {
  font-size: clamp(1.9rem, 4.4vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin: 0 0 14px;
}

.nfl-ds-band__sub {
  font-size: clamp(1rem, 1.6vw, 1.2rem);
  max-width: 62ch;
  margin: 0 auto 24px;
  opacity: 0.88;
}

.nfl-ds-band--dark .nfl-ds-band__sub { color: #d1d5db; opacity: 1; }

/* ------------------------------------------------------------- section -- */

.nfl-ds-section { margin: 0 0 var(--nfl-ds-gap, 20px); }

.nfl-ds-section__title {
  font-size: 1.5rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 6px;
}

.nfl-ds-section__lede {
  color: var(--nfl-text-muted, #6b7280);
  margin: 0 0 18px;
  max-width: 64ch;
}

.nfl-ds-section__meta {
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.875rem;
  margin: 0 0 12px;
}

/* ---------------------------------------------------------------- grid -- */

.nfl-ds-grid {
  display: grid;
  gap: var(--nfl-ds-gap, 20px);
  align-items: start;
}

.nfl-ds-grid--2    { grid-template-columns: repeat(2, 1fr); }
.nfl-ds-grid--3    { grid-template-columns: repeat(3, 1fr); }
.nfl-ds-grid--4    { grid-template-columns: repeat(4, 1fr); }
.nfl-ds-grid--auto { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.nfl-ds-grid--tight { gap: 12px; }

/* -------------------------------------------------------------- button -- */

.nfl-ds-btn {
  display: inline-block;
  padding: 11px 20px;
  border-radius: 9px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  background: var(--nfl-card-bg, #fff);
  color: var(--nfl-text, #111827);
  font-weight: 600;
  font-size: 0.95rem;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.12s ease, filter 0.12s ease;
}

.nfl-ds-btn:hover { filter: brightness(0.96); transform: translateY(-1px); }

.nfl-ds-btn:focus-visible {
  outline: 2px solid var(--nfl-accent, #2563eb);
  outline-offset: 2px;
}

.nfl-ds-btn--primary {
  background: var(--nfl-accent, #2563eb);
  border-color: var(--nfl-accent, #2563eb);
  color: #fff;
}

.nfl-ds-btn--ghost {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.45);
  color: #fff;
}

.nfl-ds-btn--lg { padding: 13px 26px; font-size: 1.05rem; font-weight: 700; }
.nfl-ds-btn--sm { padding: 8px 14px;  font-size: 0.88rem; }

.nfl-ds-btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  margin: 0;
}

.nfl-ds-btn-row--center { justify-content: center; }

/* -------------------------------------------------------------- filter -- */

.nfl-ds-filter {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 12px 16px;
  padding: 14px 16px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: 12px;
  background: var(--nfl-card-bg, #fff);
  margin: 0 0 var(--nfl-ds-gap, 20px);
}

.nfl-ds-filter__field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.875rem;
}

.nfl-ds-filter__label {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--nfl-text-muted, #6b7280);
}

.nfl-ds-filter__control {
  padding: 8px 10px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: 8px;
  font-size: 0.92rem;
  background: var(--nfl-card-bg, #fff);
  color: var(--nfl-text, #111827);
}

.nfl-ds-filter__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 11px;
  border-radius: 999px;
  background: var(--nfl-accent-bg, #dbeafe);
  color: var(--nfl-accent, #2563eb);
  font-size: 0.84rem;
  font-weight: 600;
}

/* --------------------------------------------------------------- pager -- */

.nfl-ds-pager {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 18px 0 0;
}

.nfl-ds-pager__link {
  display: inline-block;
  min-width: 34px;
  padding: 7px 10px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: 8px;
  text-align: center;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--nfl-accent, #2563eb);
}

.nfl-ds-pager__link:hover { background: var(--nfl-accent-bg, #dbeafe); }

.nfl-ds-pager__link--active {
  background: var(--nfl-accent, #2563eb);
  border-color: var(--nfl-accent, #2563eb);
  color: #fff;
}

.nfl-ds-pager__count {
  margin-left: auto;
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.875rem;
}

/* ------------------------------------------------------- media object -- */

/* Used by the blog carousel and any "thumb + text" row; nothing above this
   banner covered it, so the pattern was open-coded per surface. */
.nfl-ds-media { display: flex; flex-direction: column; gap: 10px; }

.nfl-ds-media__thumb {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 10px;
  background: var(--nfl-mid-bg, #f3f4f6);
}

.nfl-ds-media__title {
  font-weight: 700;
  font-size: 1rem;
  line-height: 1.3;
  margin: 0;
}

.nfl-ds-media__title a { color: var(--nfl-text, #111827); text-decoration: none; }
.nfl-ds-media__title a:hover { color: var(--nfl-accent, #2563eb); }

.nfl-ds-media__meta {
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.82rem;
  margin: 0;
}

/* ---- scroller: horizontal rail with snap, no JS ------------------------- */

.nfl-ds-scroller {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(260px, 1fr);
  gap: var(--nfl-ds-gap, 20px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 6px;
}

.nfl-ds-scroller > * { scroll-snap-align: start; }

/* -------------------------------------------------------- responsive   -- */

@media (max-width: 900px) {
  .nfl-ds-grid--3,
  .nfl-ds-grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 560px) {
  .nfl-ds-container { padding: 0.5rem 0.75rem 1.5rem; }
  .nfl-ds-band { padding: 28px 18px; }
  .nfl-ds-grid--2,
  .nfl-ds-grid--3,
  .nfl-ds-grid--4,
  .nfl-ds-grid--auto { grid-template-columns: 1fr; }
  .nfl-ds-btn { width: 100%; text-align: center; }
  .nfl-ds-btn-row .nfl-ds-btn { width: 100%; }
  .nfl-ds-scroller { grid-auto-columns: minmax(80%, 1fr); }
}

/* v0.45.2 — button states the layer was missing. Both were emitted by real
 * surfaces with no rule behind them: a disabled CTA looked identical to a live
 * one, and destructive actions looked identical to safe ones. */
.nfl-ds-btn--disabled,
.nfl-ds-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.nfl-ds-btn--danger {
  background: var(--nfl-bad-bg, #fee2e2);
  border-color: var(--nfl-bad, #b91c1c);
  color: var(--nfl-bad, #b91c1c);
}

.nfl-ds-btn--danger:hover { background: var(--nfl-bad, #b91c1c); color: #fff; }

/* v0.45.2 — a de-emphasised table row (an item that exists but is currently
 * inactive: a disabled data source, an archived record). Shared because more
 * than one board needs it. */
.nfl-ds-row--muted {
  opacity: 0.6;
}

.nfl-ds-row--muted td { font-style: italic; }

/* v0.45.4 — a consequential inline confirmation (a checkbox the member must
 * tick before a destructive request is filed) and a retention callout that has
 * to be read, not skimmed. Shared: any future irreversible action wants both. */
.nfl-ds-confirm {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  line-height: 1.45;
  cursor: pointer;
}

.nfl-ds-confirm input { margin-top: 3px; flex: 0 0 auto; }

.nfl-ds-callout {
  padding: 2px 0 2px 12px;
  border-left: 3px solid var(--nfl-accent, #2563eb);
  font-weight: 600;
}

/* ---------------------------------------------------------- copyfield -- */

/* v0.45.2 — a read-only field whose whole job is to be selected and copied
 * (share URLs, embed snippets). Added to the shared layer rather than a page
 * sheet because /compare/ is already URL-shareable and the planned
 * ratings-share ship will want the identical component.
 */
.nfl-ds-copyfield {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: 9px;
  background: var(--nfl-page-bg, #fafafa);
}

.nfl-ds-copyfield__label {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--nfl-text-muted, #6b7280);
  width: 100%;
}

.nfl-ds-copyfield__value {
  flex: 1 1 240px;
  min-width: 0;
  padding: 7px 9px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: 7px;
  background: var(--nfl-card-bg, #fff);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.82rem;
  color: var(--nfl-text, #111827);
  overflow-x: auto;
  white-space: nowrap;
}

.nfl-ds-copyfield__hint {
  width: 100%;
  color: var(--nfl-text-faint, #9ca3af);
  font-size: 0.8rem;
  margin: 0;
}

/* ==========================================================================
 * GEOMETRY SCALE — v0.45.5
 * ==========================================================================
 *
 * WHY. §44 shipped eight page sheets before this layer existed, and .45.3 added
 * a ninth. Each decided its own geometry, so across 3,588 lines the nine sheets
 * used NINE distinct border-radius values (3/6/7/8/9/10/12/14/999px) and
 * THIRTEEN distinct gaps for what are, conceptually, four shapes and one
 * spacing rhythm. That is what reads as "not one product" — colour was already
 * ~91% tokenised; geometry had no tokens at all.
 *
 * WHAT EACH RADIUS MEANS — pick by SHAPE, not by eye:
 *   pill    999px  chips, badges, status markers — anything fully rounded
 *   band     14px  full-width hero / closer sections
 *   card     12px  panels, cards, tables, scroll containers      (absorbed 10px)
 *   control   9px  buttons, inputs, selects, pager links          (absorbed 8px)
 *   badge     7px  small inline value markers (P/L, ATS%, counts) (absorbed 6px)
 *
 * The gap scale is the spacing rhythm; --nfl-gap-2 (8px) is the common case.
 *
 * ENFORCEMENT. v045-5-css-uniformity asserts that NO page sheet declares a
 * radius or gap outside this scale, with a short allowlist of genuine one-offs
 * that each carry a reason in the test. The sweep globs the sheet directory, so
 * a NEW page sheet is automatically in scope — it cannot dodge the check by not
 * being on a list. That gap (a gate that only ever checked within one page) is
 * exactly what let the drift happen.
 * ========================================================================== */

:root {
  /* radii — by shape */
  --nfl-radius-pill: 999px;
  --nfl-radius-band: 14px;
  --nfl-radius-card: 12px;
  --nfl-radius-control: 9px;
  --nfl-radius-badge: 7px;

  /* spacing rhythm */
  --nfl-gap-0: 4px;
  --nfl-gap-1: 6px;
  --nfl-gap-2: 8px;
  --nfl-gap-3: 10px;
  --nfl-gap-4: 12px;
  --nfl-gap-5: 16px;
  --nfl-gap-6: 20px;
  --nfl-gap-7: 28px;
}

/* v0.45.9a4 — A KPI STRIP THAT SIZES TO ITS CONTENT.
 *
 * The base .nfl-ds-kpi-strip is a fixed 6-column grid, right for the 12-tile
 * stats strip. Used with THREE tiles it still gave each a sixth of the row, so
 * "Every week" wrapped to "Ever / y / wee / k".
 *
 * My first attempt used grid with minmax(max-content, 1fr) and made it worse —
 * the tiles overlapped and clipped instead of wrapping. max-content inside a
 * grid track does not stop a track from being squeezed by its siblings.
 * FLEX is the right tool: each tile takes the width it needs and wraps when the
 * row runs out, which is exactly the behaviour wanted. */
.nfl-ds-kpi-strip--fit {
  display: flex;
  flex-wrap: wrap;
  gap: var(--nfl-gap-4, 12px);
  align-items: stretch;
}

/* No truncation anywhere in this variant — a clipped label is worse than a
   wrapped row. */
/* No truncation anywhere in this variant. The VALUE never wraps — "Every week"
   on two lines reads as two facts. The LABEL may wrap, because an equal-width
   tile cannot always hold "Graded, not summarized" on one line and clipping it
   is worse than a second line. */
.nfl-ds-kpi-strip--fit .nfl-ds-kpi__value {
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
}

.nfl-ds-kpi-strip--fit .nfl-ds-kpi__label {
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  line-height: 1.3;
}


/* v0.45.9a6 — the explainer stat chips, finished properly.
 *
 * The --fit variant stopped them wrapping mid-word, but three bare bordered
 * rectangles of unequal size is not a designed panel — the operator was right
 * that it looked unfinished. These are a stat strip: the VALUE is the thing you
 * read, the label is supporting. Equal height, a shared baseline, a quiet
 * surface, and enough room to breathe. */
/* flex-basis 0, not auto: `auto` sizes each tile to its own content, so "2018"
   stayed narrow while "Graded, not summarized" ran wide — three unequal boxes
   that wrapped 2 + 1 and left the row half empty. Basis 0 divides the row
   evenly, so the three tiles fill the space they are given and sit on one line.
   Content is centred because a stat tile reads as a unit, not a left-aligned
   label. */
.nfl-ds-kpi-strip--fit .nfl-ds-kpi {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 3px;
  min-height: 72px;
  padding: 14px 12px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: var(--nfl-radius-card, 12px);
  background: var(--nfl-card-bg, #fff);
}

.nfl-ds-kpi-strip--fit .nfl-ds-kpi__value {
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--nfl-text, #111827);
}

.nfl-ds-kpi-strip--fit .nfl-ds-kpi__label {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--nfl-text-muted, #6b7280);
}

/* MUST come after the base rule above. It previously sat earlier in the sheet,
   so the unconditional `flex: 1 1 0` overrode it at every width and the mobile
   stack never applied — equal specificity, later wins. On a narrow screen three
   equal columns are unreadable, so each tile takes the full row. */
@media (max-width: 560px) {
  .nfl-ds-kpi-strip--fit .nfl-ds-kpi { flex: 1 1 100%; }
}

/* ---- the week-by-week drill: nested season -> week -> games -------------- */

.nfl-home__drill-season,
.nfl-home__drill-week {
  border-top: 1px solid var(--nfl-card-border, #e6e8ec);
}

.nfl-home__drill-season > summary,
.nfl-home__drill-week > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 4px;
  cursor: pointer;
  list-style: none;
}

.nfl-home__drill-season > summary::-webkit-details-marker,
.nfl-home__drill-week > summary::-webkit-details-marker { display: none; }
.nfl-home__drill-season > summary::marker,
.nfl-home__drill-week > summary::marker { content: ''; }

.nfl-home__drill-season > summary:hover,
.nfl-home__drill-week > summary:hover { background: var(--nfl-page-bg, #fafafa); }

.nfl-home__drill-week { margin-left: 14px; }
.nfl-home__drill-week > summary { font-size: 0.92rem; }

.nfl-home__drill-games { font-size: 0.88rem; margin: 0 0 10px 14px; }


/* v0.46.12 (additive) — the simulated marker on the site-home record band:
   the §P13 pages carry their own sim class in the family sheet, but the
   front door is ds-only by design, so the convention gets a ds-layer hook. */
.nfl-ds-stat--sim .nfl-ds-stat__num { font-style: italic; }

.nfl-ds-stat__sim {
  font-size: 0.75em;
  font-weight: 400;
  color: var(--nfl-color-text-muted, #6b7280);
}


/* v0.46.12 (additive) — front-door primitives: the derived numbers strip,
   the record stat list, chips, plain lists, the accent card. */
.nfl-ds-statgrid { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--nfl-gap-4, 12px) var(--nfl-gap-6, 20px); }

.nfl-ds-statgrid--inline { justify-content: center; }

.nfl-ds-statgrid--n1,
.nfl-ds-statgrid--n2,
.nfl-ds-statgrid--n3,
.nfl-ds-statgrid--n4 { display: grid; gap: var(--nfl-gap-5, 16px); }
.nfl-ds-statgrid--n1 { grid-template-columns: minmax(0, 1fr); }
.nfl-ds-statgrid--n2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.nfl-ds-statgrid--n3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.nfl-ds-statgrid--n4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 780px) {
  .nfl-ds-statgrid--n3,
  .nfl-ds-statgrid--n4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* v0.46.13.2 — THE BAND LAYS OUT FOR WHAT IT HAS (J's ruling 4), IN THE DS
   LAYER because House_Record_Band is a ds-layer component rendered by BOTH
   homes. At .13.1 these rules were written into nfl-home.css, which the front
   door never loads (Site_Home chains front -> ds only) — so the front door
   emitted the modifier into nothing and kept the four-wide grid at n=2. Same
   defect as the chip, one level over: a shared component styled in a
   page-scoped sheet.
   The BASE rule stays flex — every existing statgrid consumer is unchanged.
   Only a band that declares its populated count switches to grid. */

}

.nfl-ds-stat { display: flex; flex-direction: column; gap: var(--nfl-gap-0, 4px); }

.nfl-ds-stat__num { font-weight: 700; font-variant-numeric: tabular-nums; }

.nfl-ds-stat__label { font-size: 0.85rem; color: var(--nfl-color-text-muted, #6b7280); }

.nfl-ds-chip { display: inline-block; font-size: 0.8rem; padding: 2px 8px; border-radius: 999px; background: var(--nfl-color-surface-2, #f3f4f6); color: var(--nfl-color-text, #111827); }

/* v0.46.13.1 — DARK-BAND VARIANT. The chip is a LIGHT pill; dropped on a dark
   band that sets color:#fff it renders white-on-light and is unreadable (J's
   ruling 3). This is the token, not a page patch, so the next dark surface
   inherits the fix instead of repeating the bug. Any chip inside a dark band
   also picks it up via the inheritance rule below. */
.nfl-ds-chip--on-dark,
.nfl-ds-band--dark .nfl-ds-chip {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.28);
}

.nfl-ds-muted { color: var(--nfl-color-text-muted, #6b7280); }

.nfl-ds-list { margin: 8px 0 0; padding-left: 18px; }

.nfl-ds-card--accent { border: 2px solid var(--nfl-color-accent, #2563eb); }


/* ===================================================== v0.46.14 §P3 ====== */
/* THE BUILDER PAGE'S FRONT-END CHROME.
   DECLARED DEVIATION: the spec says replace each admin component; the notices
   and tab bar live in the SHARED core that wp-admin runs, so twelve markup
   swaps there would put wp-admin at risk for no visual gain. Every rule below
   is SCOPED TO .nfl-algo-wrap, a class wp-admin never emits, so the admin page
   is unreachable from here by construction. */

.nfl-algo-wrap .notice {
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-left: 4px solid var(--nfl-color-accent, #2563eb);
  border-radius: var(--nfl-radius-card, 12px);
  background: var(--nfl-color-surface, #fff);
  box-shadow: none;
  padding: var(--nfl-gap-4, 12px) var(--nfl-gap-5, 16px);
  margin: var(--nfl-gap-5, 16px) 0;
}
.nfl-algo-wrap .notice p { margin: 0; }
.nfl-algo-wrap .notice-success { border-left-color: var(--nfl-color-good, #15803d); }
.nfl-algo-wrap .notice-warning { border-left-color: var(--nfl-color-warn, #b45309); }
.nfl-algo-wrap .notice-error   { border-left-color: var(--nfl-color-bad, #b91c1c); }

/* The tab bar reads as page sections, not wp-admin tabs. */
.nfl-algo-wrap .nav-tab-wrapper {
  border-bottom: 1px solid var(--nfl-color-border, #e5e7eb);
  display: flex;
  gap: var(--nfl-gap-2, 8px);
  margin: 0 0 var(--nfl-gap-6, 20px);
  padding: 0;
}
.nfl-algo-wrap .nav-tab {
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--nfl-color-text-muted, #6b7280);
  font-size: 0.95rem;
  font-weight: 600;
  margin: 0;
  padding: var(--nfl-gap-3, 10px) var(--nfl-gap-4, 12px);
  text-decoration: none;
}
.nfl-algo-wrap .nav-tab-active,
.nfl-algo-wrap .nav-tab:hover {
  color: var(--nfl-color-text, #111827);
  border-bottom-color: var(--nfl-color-accent, #2563eb);
  background: transparent;
}

/* Admin grey buttons read as ds buttons. */
.nfl-algo-wrap .button,
.nfl-algo-wrap .button-secondary {
  border-radius: var(--nfl-radius-control, 9px);
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  background: var(--nfl-color-surface, #fff);
  color: var(--nfl-color-text, #111827);
  box-shadow: none;
  padding: var(--nfl-gap-1, 6px) var(--nfl-gap-4, 12px);
  height: auto;
  line-height: 1.6;
}
.nfl-algo-wrap .button-primary {
  border-radius: var(--nfl-radius-control, 9px);
  border: 1px solid var(--nfl-color-accent, #2563eb);
  background: var(--nfl-color-accent, #2563eb);
  color: #fff;
  box-shadow: none;
  text-shadow: none;
  padding: var(--nfl-gap-1, 6px) var(--nfl-gap-4, 12px);
  height: auto;
  line-height: 1.6;
}

/* The database chooser: three real cards, not a cramped modal list. */
.nfl-algo-wrap .nfl-pr-modal__panel {
  border-radius: var(--nfl-radius-band, 14px);
  background: var(--nfl-color-surface, #fff);
  padding: var(--nfl-gap-7, 28px);
  max-width: 860px;
}
.nfl-algo-wrap .nfl-pr-db-modal__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--nfl-gap-5, 16px);
}
.nfl-algo-wrap .nfl-pr-db-modal__card {
  display: flex;
  flex-direction: column;
  gap: var(--nfl-gap-2, 8px);
  align-items: flex-start;
  text-align: left;
  width: 100%;
  height: 100%;
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-radius: var(--nfl-radius-card, 12px);
  background: var(--nfl-color-surface, #fff);
  padding: var(--nfl-gap-5, 16px);
  cursor: pointer;
}
.nfl-algo-wrap .nfl-pr-db-modal__card:hover:not(:disabled) { border-color: var(--nfl-color-accent, #2563eb); }
.nfl-algo-wrap .nfl-pr-db-modal__card:disabled { opacity: 0.45; cursor: not-allowed; }
.nfl-algo-wrap .nfl-pr-db-modal__letter {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--nfl-color-text, #111827);
}
.nfl-algo-wrap .nfl-pr-db-modal__name { font-weight: 600; }
.nfl-algo-wrap .nfl-pr-db-modal__desc {
  font-size: 0.85rem;
  color: var(--nfl-color-text-muted, #6b7280);
}

/* The delete control: a ds danger affordance, not a black-box red x. */
.nfl-algo-wrap .nfl-pr-delete,
.nfl-algo-wrap .nfl-pr-row-delete {
  border-radius: var(--nfl-radius-control, 9px);
  border: 1px solid var(--nfl-color-bad, #b91c1c);
  background: transparent;
  color: var(--nfl-color-bad, #b91c1c);
  padding: var(--nfl-gap-0, 4px) var(--nfl-gap-2, 8px);
}
.nfl-algo-wrap .nfl-pr-delete[disabled] { opacity: 0.45; cursor: not-allowed; }

/* The page header + flash. */
.nfl-algo-header { margin-bottom: var(--nfl-gap-6, 20px); }
.nfl-ds-flash {
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-left: 4px solid var(--nfl-color-accent, #2563eb);
  border-radius: var(--nfl-radius-card, 12px);
  padding: var(--nfl-gap-4, 12px) var(--nfl-gap-5, 16px);
  margin: var(--nfl-gap-5, 16px) 0;
}
.nfl-ds-flash--good { border-left-color: var(--nfl-color-good, #15803d); }
.nfl-ds-flash--warn { border-left-color: var(--nfl-color-warn, #b45309); }
.nfl-ds-workspace-strip { margin: var(--nfl-gap-4, 12px) 0; }


/* ===================================================== v0.46.15 §P4 ====== */
/* MY ALGORITHMS. The table is the page: every row visible together, and
   everything else behind the row's own disclosure. */

.nfl-algo-name-cell { display: flex; flex-direction: column; gap: var(--nfl-gap-0, 4px); }
.nfl-algo-name { font-weight: 600; }
.nfl-algo-sub { font-size: 0.85rem; }
.nfl-algo-edit-link { font-size: 0.85rem; }

/* The record is the row's anchor, so it reads as a figure, not body text. */
.nfl-algo-record-cell { white-space: nowrap; }
.nfl-algo-record { font-weight: 600; font-variant-numeric: tabular-nums; }
.nfl-algo-record__sim { font-size: 0.8rem; font-weight: 400; }

/* The one boxed element on the row. */
.nfl-algo-db-pill {
  display: inline-block;
  min-width: 1.6em;
  text-align: center;
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-radius: var(--nfl-radius-badge, 7px);
  padding: 0 var(--nfl-gap-1, 6px);
  font-weight: 600;
}
/* DB-disabled: a glyph with hover text beside the muted row, not a second box. */
.nfl-algo-db-off { color: var(--nfl-color-warn, #b45309); cursor: help; }
.nfl-algo-db-cell { text-align: center; white-space: nowrap; }
.nfl-algo-updated { white-space: nowrap; color: var(--nfl-color-text-muted, #6b7280); font-size: 0.85rem; }

.nfl-algo-help { margin: 0 0 var(--nfl-gap-4, 12px); font-size: 0.9rem; }

/* The disclosure. Closed on arrival; the row it belongs to reads as one unit. */
.nfl-algo-row-detail > td { padding: 0 0 var(--nfl-gap-4, 12px); border-top: 0; }
.nfl-algo-disclosure { border-top: 1px solid var(--nfl-color-border, #e5e7eb); }
.nfl-algo-disclosure__summary {
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--nfl-color-text-muted, #6b7280);
  padding: var(--nfl-gap-1, 6px) 0;
}
.nfl-algo-disclosure[open] .nfl-algo-disclosure__summary { color: var(--nfl-color-text, #111827); }
.nfl-algo-disclosure__body { padding: var(--nfl-gap-2, 8px) 0 var(--nfl-gap-4, 12px); }
.nfl-algo-probation { margin: 0 0 var(--nfl-gap-2, 8px); }
.nfl-algo-meta { margin: 0 0 var(--nfl-gap-2, 8px); font-size: 0.85rem; }

/* The actions cell is ONE row of small buttons, never a stack. */
.nfl-algo-actions { white-space: nowrap; }
.nfl-algo-actions .nfl-algo-inline-form { display: inline; }


/* =================================================== v0.46.15.1 §P15a ==== */
/* POWER RATINGS. The rating is the visual anchor; 32 rows must stay scannable
   and must survive 390px (L8). */
.nfl-ds-tabular { font-variant-numeric: tabular-nums; }
.nfl-ds-num { text-align: right; }
.nfl-ds-table-wrap { overflow-x: auto; }

.nfl-pr-ratings-table tbody tr:nth-child(odd) { background: var(--nfl-color-surface-2, #f9fafb); }
.nfl-pr-rating { font-weight: 700; }
.nfl-pr-team-abbr { font-weight: 600; }
.nfl-pr-team-name { color: var(--nfl-color-text-muted, #6b7280); }
.nfl-pr-div { color: var(--nfl-color-text-muted, #6b7280); white-space: nowrap; }
.nfl-pr-upcoming { margin-top: var(--nfl-gap-7, 28px); }

@media (max-width: 479px) {
  /* At 390px the division column is the first thing to go — the rating and the
     team are the page. */
  .nfl-pr-ratings-table .nfl-pr-div,
  .nfl-pr-ratings-table thead th:last-child { display: none; }
  .nfl-pr-team-name { display: none; }
}


/* =================================================== v0.46.15.2 §P1 ====== */
/* THE RECORD BAND'S MAGNITUDE BAR (the 2c "bar per window", ruled inline).
   Shared component: this renders on the front door AND /nfl-home/. The bar is
   centred on break-even — left of centre is under it, right is over — because
   the reader's question is "is this above the line", not "how do these windows
   compare to each other". */
.nfl-ds-stat__bar {
  display: block;
  height: 4px;
  margin-top: var(--nfl-gap-1, 6px);
  border-radius: var(--nfl-radius-pill, 999px);
  background: var(--nfl-color-surface-2, #f3f4f6);
  overflow: hidden;
}
.nfl-ds-stat__bar > i { display: block; height: 100%; }
.nfl-ds-stat__bar > i.nfl-ds-kpi--good { background: var(--nfl-color-good, #15803d); }
.nfl-ds-stat__bar > i.nfl-ds-kpi--mid  { background: var(--nfl-color-warn, #b45309); }
.nfl-ds-stat__bar > i.nfl-ds-kpi--bad  { background: var(--nfl-color-bad, #b91c1c); }

/* Two canvases side by side where there is room. DS-layer, not page-scoped:
   v045-1 S9 caught the bespoke class, and it was right — the builder home and
   §P8 want this same two-up, and a page-local version is how they diverge. */
/* ⛔ v0.46.20.1 — THE GRID GOES ON A WRAPPER HOLDING ONLY THE ITEMS BEING
   LAID OUT. A heading inside this became cell 1 and stranded a chart with a
   dead quarter beside it — the hole the operator photographed.
   auto-fit means ONE chart spans the full width instead of leaving half the
   row empty: a section that renders a chart either fills the other half or
   spans. */
.nfl-ds-chart-cols {
  display: grid;
  gap: var(--nfl-gap-5, 16px);
  align-items: start;
}
@media (min-width: 780px) {
  .nfl-ds-chart-cols { grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); }
}
.nfl-ds-chart-cols > * { min-width: 0; }


/* =============================================== v0.46.19.1 §P1-REDO ===== */
/* THE FRONT DOOR. J walked the shipped page and rejected it: "a gigantic
   fucking dark blob with a fucked up run-on sentence and two counters that
   mean nothing." No slab, no counters, and the live proof before the pitch.
   DS-layer because this page has no sheet of its own — front -> ds only. */

.nfl-ds-hero { padding: var(--nfl-gap-6, 20px) 0 var(--nfl-gap-5, 16px); }

/* v0.46.20.1 — CENTRED, and the boxes FILL the row rather than hugging their
   text. Ruled after the operator walked the page: the three boxes sat at a
   third of the band above them with everything left-ragged, so nothing on the
   page shared an edge. */
.nfl-ds-hero--center { text-align: center; }
.nfl-ds-hero--center .nfl-ds-hero__row { justify-items: stretch; }
.nfl-ds-hero--center .nfl-ds-hero__box { display: flex; align-items: center; justify-content: center; }
.nfl-ds-hero__title {
  font-size: clamp(1.75rem, 4vw, 2.6rem);
  line-height: 1.15;
  margin: 0 0 var(--nfl-gap-4, 12px);
}
/* v0.46.19.2 — THREE BOXES, ONE ROW. Stacking only at phone width: the point
   of the row is to keep the whole proposition above the fold. */
.nfl-ds-hero__row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--nfl-gap-4, 12px);
  margin-top: var(--nfl-gap-4, 12px);
}
.nfl-ds-hero__box {
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-radius: var(--nfl-radius-card, 12px);
  padding: var(--nfl-gap-4, 12px) var(--nfl-gap-5, 16px);
  font-size: 1rem;
  line-height: 1.4;
  /* Equal height regardless of text length — three boxes of different
     heights is the same ragged edge one level down. */
  min-height: 100%;
  box-sizing: border-box;
}
@media (max-width: 640px) {
  .nfl-ds-hero__row { grid-template-columns: 1fr; }
}

.nfl-ds-section--list { margin-bottom: var(--nfl-gap-7, 28px); }
.nfl-ds-list--plain {
  margin: 0;
  padding-left: 1.15rem;
  display: grid;
  gap: var(--nfl-gap-1, 6px);
}
@media (min-width: 780px) {
  .nfl-ds-list--plain { grid-template-columns: 1fr 1fr; gap: var(--nfl-gap-1, 6px) var(--nfl-gap-6, 20px); }
}

/* THE WAYS IN — every card carries live content, never a label and an arrow. */
.nfl-ds-ways { margin-bottom: var(--nfl-gap-7, 28px); }
.nfl-ds-ways__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: var(--nfl-gap-4, 12px);
}
.nfl-ds-ways__card {
  display: flex;
  flex-direction: column;
  gap: var(--nfl-gap-0, 4px);
  text-decoration: none;
  color: inherit;
}
.nfl-ds-ways__card:hover { border-color: var(--nfl-color-accent, #2563eb); }
.nfl-ds-ways__label { font-weight: 600; }
.nfl-ds-ways__live { font-size: 0.85rem; }

/* ============================================= v0.46.19.2 §P8-SHARE ====== */
/* THE SHARE AFFORDANCE — owner surfaces only, and the link is the artifact.
   Ratings are never shared: they ARE the picks. */
.nfl-ds-share { display: inline-flex; align-items: center; gap: var(--nfl-gap-2, 8px); }
.nfl-ds-share__url {
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-radius: var(--nfl-radius-control, 9px);
  padding: var(--nfl-gap-0, 4px) var(--nfl-gap-2, 8px);
  font-size: 0.8rem;
  max-width: 22ch;
  background: var(--nfl-color-surface-2, #f9fafb);
}

/* THE JOIN PROMPT — what the recipient of a share sees, naming the two things
   this page deliberately withholds. */
.nfl-ds-join-prompt {
  border-left: 4px solid var(--nfl-color-accent, #2563eb);
  margin-bottom: var(--nfl-gap-5, 16px);
}
.nfl-ds-join-prompt__line { margin: 0 0 var(--nfl-gap-2, 8px); font-weight: 600; }

/* ============================================== v0.46.21.1 FRONT DOOR ==== */
/* Every defect the operator photographed, in one place. */

/* §6 — THE HERO BOXES. Thin outline, text hard left, no weight, and the third
   (the invitation) looked identical to the two statements beside it. */
.nfl-ds-hero__box {
  text-align: center;
  background: var(--nfl-color-surface, #fff);
  border: 1px solid var(--nfl-color-border, #e5e7eb);
  border-radius: var(--nfl-radius-card, 12px);
  padding: var(--nfl-gap-5, 16px);
  font-size: 1rem;
  line-height: 1.45;
  min-height: 100%;
  box-sizing: border-box;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
/* Box three is the invitation and must not read as a third statement. */
.nfl-ds-hero__box:last-child {
  border-color: var(--nfl-color-accent, #2563eb);
  background: var(--nfl-accent-bg, #eff6ff);
  font-weight: 600;
}

/* §2 — A FULL-WIDTH BAND CARRIES FULL-WIDTH CONTENT. The week band holds the
   slate beside its text instead of ~60% empty space. */
.nfl-ds-band__cols {
  display: grid;
  gap: var(--nfl-gap-5, 16px);
  align-items: start;
}
@media (min-width: 780px) {
  .nfl-ds-band__cols { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); }
}
.nfl-ds-slate { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--nfl-gap-1, 6px); }
.nfl-ds-slate__game {
  display: flex;
  justify-content: space-between;
  gap: var(--nfl-gap-4, 12px);
  padding: var(--nfl-gap-1, 6px) var(--nfl-gap-3, 10px);
  border-radius: var(--nfl-radius-control, 9px);
  background: rgba(255, 255, 255, 0.6);
}
.nfl-ds-slate__teams { font-weight: 600; }
.nfl-ds-slate__more { margin: var(--nfl-gap-2, 8px) 0 0; font-size: 0.85rem; }

/* §3 — THE RECORD. The percentage is the headline; W-L-P is detail; the
   break-even line is MARKED on the bar rather than described in a sentence. */
.nfl-ds-stat--record { display: flex; flex-direction: column; gap: var(--nfl-gap-0, 4px); }
/* ⛔ v0.46.22.1 — THE GREEN BLOCK GOES. The percentage sat in a full-width
   green box spanning the card with everything stacked under it in small text —
   the old tile background left in place under a bigger number. The NUMBER
   carries the colour: green when it beats break-even, ordinary when it doesn't.
   And the tile contents are CENTRED, third time back from left-aligned. */
.nfl-ds-stat--record { text-align: center; align-items: center; }
.nfl-ds-stat--record .nfl-ds-kpi--good,
.nfl-ds-stat--record .nfl-ds-kpi--mid,
.nfl-ds-stat--record .nfl-ds-kpi--bad { background: none; padding: 0; }
.nfl-ds-stat__pct { font-size: 2rem; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.nfl-ds-stat__pct.nfl-ds-kpi--good { color: var(--nfl-color-good, #15803d); }
.nfl-ds-stat__pct.nfl-ds-kpi--mid,
.nfl-ds-stat__pct.nfl-ds-kpi--bad  { color: var(--nfl-color-text, #111827); }
.nfl-ds-stat__pct-unit { font-size: 1rem; font-weight: 700; margin-left: 1px; }
.nfl-ds-stat__detail { font-size: 0.85rem; color: var(--nfl-color-text-muted, #6b7280); }
.nfl-ds-stat__scale { font-size: 0.75rem; }
.nfl-ds-stat__bar { position: relative; }
.nfl-ds-stat__mark {
  position: absolute;
  top: -2px;
  bottom: -2px;
  width: 2px;
  background: var(--nfl-color-text, #111827);
  opacity: 0.55;
}

/* §5 — the list finally has a container. */
.nfl-ds-card--pad { padding: var(--nfl-gap-5, 16px) var(--nfl-gap-6, 20px); }

/* The week band's own paint and its intro column — a full-width band with
   full-width content needs both halves to have rules, or the "band" is just
   the left half with a background behind the rest. */
.nfl-ds-band--week { padding: var(--nfl-gap-6, 20px); border-radius: var(--nfl-radius-band, 14px); }
.nfl-ds-band__intro { display: flex; flex-direction: column; gap: var(--nfl-gap-2, 8px); }
.nfl-ds-slate__line { font-weight: 600; white-space: nowrap; }

/* ================================================= v0.46.22 WEEK BAND ==== */
/* ⛔ THE BAND IS THE GAMES. It rendered as a one-column list down the right of
   a full-width box with the intro in the left third and ~a third empty.
   THE GRID FLOWS: weeks 1-4 are 16 games, byes drop the middle of the season
   to 13-15, late weeks return to 16 — so a fixed row count leaves a white gap
   on a light week. The band grows and shrinks with its content. */
.nfl-ds-slate {
  list-style: none;
  margin: var(--nfl-gap-4, 12px) 0 0;
  padding: 0;
  display: grid;
  gap: var(--nfl-gap-3, 10px);
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* The final partial row is CENTRED: 13 games leaves one capsule under four,
     and left-aligned that reads as broken rather than deliberate. */
  justify-items: stretch;
  justify-content: center;
}
.nfl-ds-slate__game { display: block; }
.nfl-ds-slate__link {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--nfl-gap-1, 6px);
  padding: var(--nfl-gap-3, 10px);
  border-radius: var(--nfl-radius-card, 12px);
  background: rgba(255, 255, 255, 0.75);
  text-decoration: none;
  color: inherit;
  height: 100%;
  box-sizing: border-box;
  text-align: center;
}
.nfl-ds-slate__link:hover { background: #fff; }
.nfl-ds-slate__teams { font-weight: 700; white-space: nowrap; }
.nfl-ds-slate__at { opacity: 0.5; font-weight: 400; }
.nfl-ds-slate__lines { display: flex; gap: var(--nfl-gap-3, 10px); font-size: 0.82rem; }
.nfl-ds-slate__cap { color: var(--nfl-color-text-muted, #6b7280); }
.nfl-ds-slate__line--house .nfl-ds-tabular { font-weight: 700; }

/* Three columns divide 13/14/15 closer to even; four is the ruled default and
   this is the checked alternative at the width where four gets tight. */
@media (max-width: 1100px) {
  .nfl-ds-slate { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .nfl-ds-slate { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 460px) {
  /* L8 — stacks at phone width, same no-empty-cell rule. */
  .nfl-ds-slate { grid-template-columns: 1fr; }
}

/* ================================================ v0.46.22.1 §P11 ======= */
/* THE STICKY HEADER STOPS EATING THE VIEWPORT. It pinned a header row PLUS a
   6x2 grid of twelve tiles and never collapsed — roughly half the screen,
   permanently, so every chart below was read through a letterbox. The row
   still sticks; the grid sits unpinned beneath it. */
.nfl-ds-header__kpi--unpinned {
  position: static;
  margin: 0 0 var(--nfl-gap-5, 16px);
}
/* The pinned element is now the row alone, so it can afford to stay compact. */
.nfl-ds-header { max-height: 4.5rem; overflow: visible; }

/* §P11.2 item 3/4 — tile anatomy: the VALUE is the value and the rank is the
   sub-chip, on every tile including Power Rating and SoS Rank. */
.nfl-ds-kpi-tile__sub { font-size: 0.75rem; color: var(--nfl-color-text-muted, #6b7280); }

/* ⛔ v0.46.22.1 §BAND-FILL — the matchup card spans, and the grid follows it.
   The right column held only that card, so lifting it out would leave the
   two-column grid with one child and half a row empty — the same defect one
   step over. The grid is single-column now: the family cards fill the width
   and the matchup card spans above them. */
.nfl-tp__cols { grid-template-columns: 1fr; }
.nfl-tp__matchup-span { grid-column: 1 / -1; width: 100%; }


/* ==========================================================================
   v0.46.23 — THE SHARED WORKSPACE STRIP, STYLED WHERE IT LIVES
   ==========================================================================
   ⛔ REGISTER C16, THIRD OCCURRENCE. Workspace_Strip is a ds-layer component
   rendered on four surfaces (/nfl-home/, /algorithm/new/, /algorithm/{id}/edit/,
   /my-algorithms/ — and now /account/), but its inner rule `.nfl-home__meta`
   lived ONLY in nfl-home.css. Exactly one of those surfaces loads that sheet,
   so the strip has been rendering UNSTYLED on three pages since it was
   extracted at v0.46.14, and /account/ was about to become the fourth.
   A shared component is styled in the layer every consumer loads. The rule
   below is scoped to the strip, so the builder home's own .nfl-home__meta is
   untouched and that page is byte-unchanged in appearance.
   ========================================================================== */

.nfl-ds-workspace-strip .nfl-home__meta,
.nfl-ds-workspace-strip .nfl-home__meta--strip {
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.875rem;
  margin: 0;
}

.nfl-ds-workspace-strip {
  padding: var(--nfl-gap-3, 10px) var(--nfl-gap-4, 12px);
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: var(--nfl-radius-control, 9px);
  background: var(--nfl-page-bg, #fafafa);
}

.nfl-ds-workspace-strip a {
  color: var(--nfl-accent, #2563eb);
  font-weight: 600;
  text-decoration: none;
}

/* ==========================================================================
   v0.46.23 — THE MEMBER'S LIFETIME RECORD (§P16)
   ==========================================================================
   Cumulative first, then ONE CONTAINER PER ALGORITHM, closed on arrival (L2).
   The containers are <details>, so they work with JavaScript off; the chart
   bootstrap boots and resizes canvases on open, because a canvas built inside
   a closed <details> has no layout box and would otherwise open onto a blank
   square with no error.
   ========================================================================== */

.nfl-member-record__algos { margin-top: var(--nfl-gap-6, 20px); }

.nfl-member-record__algo {
  padding: 0;
  margin: 0 0 var(--nfl-gap-3, 10px);
}

.nfl-member-record__algo-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--nfl-gap-3, 10px);
  padding: var(--nfl-gap-4, 12px) var(--nfl-gap-5, 16px);
  cursor: pointer;
  font-weight: 600;
}

.nfl-member-record__algo-summary::-webkit-details-marker { display: none; }

.nfl-member-record__algo-summary::before {
  content: "\25B8";
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.8em;
}

.nfl-member-record__algo[open] > .nfl-member-record__algo-summary::before {
  content: "\25BE";
}

.nfl-member-record__algo-name { flex: 1 1 auto; min-width: 0; }

.nfl-member-record__algo-record {
  font-variant-numeric: tabular-nums;
  color: var(--nfl-text-muted, #6b7280);
  font-weight: 500;
}

.nfl-member-record__algo-pct {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
}

.nfl-member-record__algo-pct.is-above { color: var(--nfl-good, #15803d); }

.nfl-member-record__algo-body {
  padding: 0 var(--nfl-gap-5, 16px) var(--nfl-gap-5, 16px);
}

.nfl-member-record__nochart { margin: var(--nfl-gap-4, 12px) 0 0; }

@media (max-width: 560px) {
  .nfl-member-record__algo-summary { padding: var(--nfl-gap-3, 10px) var(--nfl-gap-4, 12px); }
}


/* ==========================================================================
   v0.46.24 — THE WRITING CARD, LIFTED INTO THE LAYER BEFORE THE THEME NEEDS IT
   ==========================================================================
   §P17's archive work lives in the CHILD THEME — a plugin has no business
   seizing the theme's category template, and an archive that vanishes when the
   plugin is deactivated is wrong. But the theme's post cards must look like the
   front door's writing band, and the way that goes wrong is a second copy of
   these rules in a sheet only one surface loads.

   That is register C16, and it has bitten twice: the record band styled in one
   home's sheet, and the shared workspace strip styled in another's. Both were
   found AFTER shipping. This is the same lesson applied BEFORE the bite: the
   card the theme will reuse is defined here, in the layer every surface loads,
   so the theme half is a template that borrows classes rather than a stylesheet
   that duplicates them.

   .nfl-ds-media already exists and is used by the front door's band; what
   follows is the ARCHIVE arrangement of the same card — a grid rather than a
   horizontal scroller — plus the excerpt and breadcrumb the archive needs and
   the front door does not.
   ========================================================================== */

.nfl-ds-postgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--nfl-gap-5, 16px);
  margin: var(--nfl-gap-5, 16px) 0 0;
}

.nfl-ds-media__excerpt {
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.94rem;
  margin: var(--nfl-gap-2, 8px) 0 0;
}

.nfl-ds-breadcrumb {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--nfl-gap-2, 8px);
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.875rem;
  margin: 0 0 var(--nfl-gap-4, 12px);
}

.nfl-ds-breadcrumb a {
  color: var(--nfl-accent, #2563eb);
  text-decoration: none;
}

.nfl-ds-breadcrumb a:hover { text-decoration: underline; }

/* v0.46.24 — the private toggle's state word, beside its control on
   /my-algorithms/. Lives here and not in a page sheet: the control renders from
   the shared row renderer, which more than one view reaches. */
.nfl-algo-visibility-state {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--nfl-text-muted, #6b7280);
  align-self: center;
}

.nfl-algo-visibility-state.is-private { color: var(--nfl-accent, #2563eb); }


/* ==========================================================================
   v0.46.25 — THE INSIGHTS DIARY (§P18)
   ==========================================================================
   The hub enqueues no sheet of its own and never has: it borrows
   .nfl-teams-index__* for its geometry, and those rules live HERE, in the layer
   every surface loads. That is the correct arrangement, not the C16 defect —
   so the diary's own rules go here too rather than growing this page its first
   private stylesheet.
   ========================================================================== */

.nfl-insights-hub__filters {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--nfl-gap-3, 10px);
  margin: 0 0 var(--nfl-gap-5, 16px);
  padding: var(--nfl-gap-4, 12px);
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: var(--nfl-radius-card, 12px);
  background: var(--nfl-page-bg, #fafafa);
}

.nfl-insights-hub__filter {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.8rem;
  color: var(--nfl-text-muted, #6b7280);
}

.nfl-insights-hub__clear {
  color: var(--nfl-accent, #2563eb);
  font-size: 0.875rem;
  align-self: center;
}

.nfl-insights-hub__list { list-style: none; margin: 0; padding: 0; }

.nfl-insights-hub__entry {
  padding: var(--nfl-gap-4, 12px) 0;
  border-bottom: 1px solid var(--nfl-card-border, #e6e8ec);
}

.nfl-insights-hub__entry:last-child { border-bottom: 0; }

.nfl-insights-hub__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--nfl-gap-2, 8px);
  margin: 0 0 4px;
  font-size: 0.8rem;
  color: var(--nfl-text-muted, #6b7280);
}

/* The phase word. Both halves of a game now survive, so telling them apart is
   the reader's whole problem. */
.nfl-insights-hub__phase {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.nfl-insights-hub__body { margin: 0; max-width: 78ch; }

.nfl-insights-hub__link { margin: 4px 0 0; font-size: 0.875rem; }

.nfl-insights-hub__link a { color: var(--nfl-accent, #2563eb); text-decoration: none; }

.nfl-insights-hub__link a:hover { text-decoration: underline; }

.nfl-insights-hub__trivia { padding: 0; margin: var(--nfl-gap-5, 16px) 0 0; }

.nfl-insights-hub__trivia-summary {
  padding: var(--nfl-gap-4, 12px) var(--nfl-gap-5, 16px);
  cursor: pointer;
  font-weight: 600;
}

.nfl-insights-hub__trivia-body { padding: 0 var(--nfl-gap-5, 16px) var(--nfl-gap-4, 12px); }

@media (max-width: 560px) {
  .nfl-insights-hub__filters { flex-direction: column; align-items: stretch; }
}


/* ==========================================================================
   v0.46.25.1 — THE FRONT DOOR (join · sign in · password)
   ==========================================================================
   These pages are the first thing a stranger ever sees, and until this ship
   they did not exist — a visitor got WordPress's grey login box. They live in
   the ds layer rather than a page sheet for the reason register C16 keeps
   teaching: the auth pages, the account page and the nav all render the same
   button primitives, and a second source of them is the drift v0.45.5 spent a
   whole ship collapsing.

   A single narrow column is the entire layout. There is deliberately nothing
   else on these pages: no nav rail, no promo band, no "why join" list. The one
   thing a person came here to do is the only thing offered.
   ========================================================================== */

.nfl-auth__container {
  max-width: 460px;
  margin: 0 auto;
  padding: 2rem 1rem 3rem;
}

.nfl-auth__card { padding: 26px 24px; }

.nfl-auth__title {
  font-size: clamp(1.4rem, 3vw, 1.9rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
  margin: 0 0 6px;
}

.nfl-auth__lede {
  color: var(--nfl-text-muted, #6b7280);
  margin: 0 0 18px;
}

.nfl-auth__form { margin: 0; }

.nfl-auth__field { margin: 0 0 14px; }

.nfl-auth__field label {
  display: block;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--nfl-text-muted, #6b7280);
  margin: 0 0 4px;
}

.nfl-auth__field input {
  width: 100%;
  padding: 11px 12px;
  font-size: 1rem;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: var(--nfl-radius-control, 9px);
  background: var(--nfl-card-bg, #fff);
  color: var(--nfl-text, #111827);
}

.nfl-auth__field input:focus {
  outline: 2px solid var(--nfl-accent, #2563eb);
  outline-offset: 1px;
}

.nfl-auth__actions { margin: 18px 0 0; }

.nfl-auth__actions .nfl-ds-btn { width: 100%; text-align: center; }

.nfl-auth__note {
  color: var(--nfl-text-muted, #6b7280);
  font-size: 0.9rem;
  margin: 16px 0 0;
}

.nfl-auth__alt {
  font-size: 0.9rem;
  margin: 10px 0 0;
}

.nfl-auth__alt a { color: var(--nfl-accent, #2563eb); }

/* ⛔ THE HONEYPOT. Hidden from people and from screen readers, present in the
   DOM for a naive bot to fill. NOT display:none — some bots skip those — and
   never `required`, or a real person using a reader-friendly stylesheet would
   be unable to submit. */
.nfl-auth__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The display-name form on /account/, which replaced the wp-admin profile
   link. Sits with the settings entries it belongs to. */
.nfl-account__profile-form { margin: var(--nfl-gap-4, 12px) 0 0; }

.nfl-account__profile-form input {
  padding: 9px 11px;
  border: 1px solid var(--nfl-card-border, #e6e8ec);
  border-radius: var(--nfl-radius-control, 9px);
  min-width: 220px;
}


/* v0.46.25.3 — THE METHOD LINE in the house record band. Two numbers cover the
   same games and differ only by METHOD, so the method has to be readable at a
   glance and must not compete with the percentage above it. */
.nfl-ds-stat__method {
  display: block;
  font-size: 0.8rem;
  line-height: 1.3;
  max-width: 24ch;
  margin: 2px auto 0;
}

/* ==========================================================================
   v0.46.26.4 — THE DIARY'S OWN SHELL CLASSES
   ==========================================================================
   `nfl-diary`, `nfl-diary__header` and `nfl-diary__seasons` were EMITTED WITH
   NO RULE ANYWHERE IN THE TREE — not stranded in a sheet the page failed to
   load, simply never written. They live in the ds layer rather than a page
   sheet because /predictions/ is mounted by the power-ratings module and has
   no page stylesheet of its own; giving it one would be a second source of
   layout for a page that borrows every other component.
   ========================================================================== */

.nfl-diary__container { max-width: 1200px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }

.nfl-diary__header { margin: 0 0 18px; }

.nfl-diary__seasons {
  display: flex;
  flex-wrap: wrap;
  gap: var(--nfl-gap-3, 8px);
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}

/* v0.46.26.4 — the diary's chart band. Layout only; the canvases come from the
   ds chart layer this page now loads. */
.nfl-diary__charts { margin: var(--nfl-gap-6, 20px) 0; }

/* v0.46.26.4 — the diary's outermost wrapper, emitted with no rule. */
.nfl-diary { display: block; }

/* ⛔ v0.46.26.5 — A SLATE ROW WITH NO LINK. Season and week are needed to build
   a matchup URL; where they are absent the row renders WITHOUT a link rather
   than guessing them and shipping a 404. It must still read as a row, not as a
   link that failed — so it carries the layout and drops the affordance. */
.nfl-ds-slate__link--nolink {
  cursor: default;
  color: inherit;
  text-decoration: none;
}
