/*
 * L7 — public Research composition for MLB/NFL matchup slates and game detail.
 * This file owns route geometry. It consumes L2 roles and does not redefine tokens.
 */

body[data-ca-product="research"] {
  min-width: 0;
  overflow-x: clip;
}

.ca-public-page,
.ca-opening-desk {
  width: min(100%, var(--shell-max));
  margin: 0 auto;
  padding: var(--space-6) var(--shell-gutter) var(--space-9);
}

.ca-public-page__head,
.ca-opening-desk__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--space-6);
  padding: 0 0 var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-public-page__copy,
.ca-opening-desk__copy {
  min-width: 0;
}

.ca-public-page__eyebrow,
.ca-detail-eyebrow {
  margin: 0 0 var(--space-1);
  color: var(--text-accent);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-public-page__title,
.ca-opening-desk__title {
  margin: 0;
  font-size: clamp(var(--type-28), 3vw, var(--type-32));
  line-height: 1;
}

.ca-public-page__lede,
.ca-opening-desk__lede {
  max-width: 720px;
  margin: var(--space-2) 0 0;
  color: var(--text-secondary);
}

.ca-public-page__links {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2);
}

.ca-public-page__links a,
.ca-embedded-slate-head a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-weight: 700;
}

.ca-public-page__links a:hover,
.ca-embedded-slate-head a:hover {
  border-color: var(--border-accent);
  background: var(--accent-soft);
}

.ca-public-page__content {
  padding-top: var(--space-4);
}

.ca-desk-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3);
  margin-bottom: var(--space-3);
  background: var(--surface-panel);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--elevation-1);
}

.ca-desk-toolbar__primary,
.ca-desk-toolbar__secondary,
.ca-desk-dates {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.ca-desk-toolbar__primary {
  flex: 1;
}

.ca-desk-dates button,
.ca-desk-chip {
  min-height: var(--touch-min);
  white-space: nowrap;
}

.ca-desk-dates__today {
  min-width: 190px;
  color: var(--text-primary);
  font-weight: 700;
}

.ca-desk-search {
  display: block;
  width: min(100%, 360px);
  margin-left: auto;
}

.ca-desk-search input {
  width: 100%;
}

.ca-desk-chip.is-on {
  color: var(--text-accent);
  border-color: var(--border-accent);
  background: var(--accent-soft);
}

.ca-desk-count,
.ca-desk-window-label {
  color: var(--text-secondary);
  font-size: var(--type-meta);
  white-space: nowrap;
}

.ca-slate-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
  gap: var(--space-3);
}

.ca-kickoff-window + .ca-kickoff-window {
  margin-top: var(--space-5);
}

.ca-kickoff-window > header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 0 var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-3);
}

.ca-kickoff-window > header h2 {
  margin: 0;
  font-size: var(--type-18);
}

.ca-kickoff-window > header span {
  color: var(--text-meta);
  font-size: var(--type-meta);
}

.ca-matchup-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
  min-height: 272px;
  padding: var(--space-3);
  background: var(--surface-panel);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--elevation-1);
}

.ca-matchup-card::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  border-radius: var(--radius-md) 0 0 var(--radius-md);
  background: var(--accent);
}

.ca-matchup-card:hover,
.ca-matchup-card:focus-within {
  border-color: var(--border-strong);
  box-shadow: var(--elevation-2);
}

.ca-matchup-card.is-expanded {
  grid-column: 1 / -1;
}

.ca-matchup-card__head,
.ca-matchup-card__actions,
.ca-embedded-slate-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
}

.ca-matchup-card__head {
  min-height: 24px;
  padding-left: var(--space-1);
}

.ca-matchup-card__kick {
  min-width: 0;
  color: var(--text-primary);
  font-size: var(--type-14);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.ca-matchup-card__broadcast {
  display: inline-block;
  max-width: 20ch;
  margin-left: var(--space-2);
  padding-left: var(--space-2);
  border-left: 1px solid var(--border-default);
  color: var(--text-meta);
  font-size: var(--type-meta);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  vertical-align: bottom;
  white-space: nowrap;
}

.ca-status-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 24px;
  padding: var(--space-1) var(--space-2);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  color: var(--text-secondary);
  background: var(--surface-raised);
  font-size: var(--type-meta);
  font-weight: 700;
  white-space: nowrap;
}

.ca-status-chip.is-live,
.ca-status-chip.is-ok {
  color: var(--status-live);
  border-color: color-mix(in srgb, var(--status-live) 38%, transparent);
  background: color-mix(in srgb, var(--status-live) 12%, transparent);
}

.ca-status-chip.is-watch {
  color: var(--status-stale);
  border-color: color-mix(in srgb, var(--status-stale) 38%, transparent);
}

.ca-matchup-card__teams {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 24px minmax(0, 1fr);
  align-items: center;
  gap: var(--space-2);
  min-height: 64px;
  padding: var(--space-2) var(--space-1);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-matchup-card__club {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}

.ca-matchup-card__club--home {
  flex-direction: row-reverse;
  text-align: right;
}

.ca-matchup-logo,
.ca-detail-team__logo {
  display: block;
  flex: 0 0 auto;
  width: 52px;
  height: 52px;
  object-fit: contain;
}

.ca-matchup-card__club-copy {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.ca-matchup-card__name {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-16);
  font-weight: 700;
  line-height: 1.05;
}

.ca-matchup-card__record {
  margin-top: var(--space-1);
  color: var(--text-meta);
  font-size: var(--type-meta);
}

.ca-matchup-card__versus {
  color: var(--text-muted);
  font-size: var(--type-caps);
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
}

  .ca-matchup-card__summary,
  .ca-matchup-card__detail-grid,
.ca-matchup-card__environment {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
}

.ca-matchup-card__detail-grid,
.ca-matchup-card__environment {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.ca-matchup-card__fact {
  min-width: 0;
  padding: var(--space-2);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
}

.ca-matchup-card__fact > span,
.ca-matchup-card__fact > strong {
  display: block;
  min-width: 0;
}

.ca-matchup-card__fact > span {
  color: var(--text-meta);
  font-size: var(--type-meta);
}

.ca-matchup-card__fact > strong {
  margin-top: 0;
  color: var(--text-secondary);
  font-size: var(--type-meta);
  font-weight: 600;
  line-height: 1.25;
  overflow-wrap: anywhere;
}

.ca-matchup-card__fact > strong.is-ok { color: var(--status-ok); }
.ca-matchup-card__fact > strong.is-watch { color: var(--status-stale); }

.ca-matchup-card__actions {
  margin-top: auto;
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-subtle);
}

.ca-matchup-card__expand-btn,
.ca-matchup-card__detail-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: var(--touch-min);
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--type-meta);
  font-weight: 700;
}

.ca-matchup-card__expand-btn {
  color: var(--text-primary);
}

.ca-matchup-card__detail-link {
  color: var(--text-accent);
}

.ca-matchup-card__expand {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-3) 0 0;
  border-top: 1px solid var(--border-subtle);
}

.ca-matchup-card__expand[hidden] {
  display: none;
}

.ca-matchup-card__starters {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.ca-matchup-card__starter {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  padding: var(--space-3);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-matchup-card__shot {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--surface-raised);
}

.ca-matchup-card__shot--empty {
  border: 1px solid var(--border-default);
}

.ca-matchup-card__starter div,
.ca-matchup-card__starter span,
.ca-matchup-card__starter strong {
  display: block;
  min-width: 0;
}

.ca-matchup-card__starter-label {
  color: var(--text-meta);
  font-size: var(--type-caps);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}

.ca-matchup-card__starter strong {
  color: var(--text-primary);
  font-size: var(--type-14);
}

.ca-matchup-card__starter strong + span {
  color: var(--text-secondary);
  font-size: var(--type-meta);
}

.ca-loading-state,
.ca-error-state,
.ca-empty-state {
  display: grid;
  place-items: center;
  min-height: 220px;
  padding: var(--space-6);
  text-align: center;
  background: var(--surface-panel);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
}

.ca-error-state h2,
.ca-empty-state h2 {
  margin: 0;
}

.ca-opening-desk__head {
  grid-template-columns: 1fr;
}

.ca-opening-desk__slates {
  display: grid;
  gap: var(--space-7);
  padding-top: var(--space-6);
}

.ca-opening-sport__head,
.ca-embedded-slate-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
}

.ca-opening-sport__head h2 {
  margin: 0;
}

.ca-embedded-slate-head {
  align-items: center;
  color: var(--text-meta);
  font-size: var(--type-meta);
}

/* Factual game detail */
.ca-detail-page {
  width: min(100%, var(--shell-max));
  margin: 0 auto;
  padding: var(--space-5) var(--shell-gutter) var(--space-9);
}

.ca-detail-back {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch-min);
  margin-bottom: var(--space-2);
  color: var(--text-secondary);
  font-weight: 700;
}

.ca-detail-hero,
.ca-detail-section {
  background: var(--surface-panel);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--elevation-1);
}

.ca-detail-hero {
  position: relative;
  padding: var(--space-4);
  overflow: hidden;
}

.ca-detail-hero::before,
.ca-detail-section::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--accent);
}

.ca-detail-hero__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-detail-hero__teams {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(170px, auto) minmax(0, 1fr);
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-6) var(--space-4);
}

.ca-detail-team {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  min-width: 0;
}

.ca-detail-team--home {
  flex-direction: row-reverse;
  text-align: right;
}

.ca-detail-team__logo {
  width: 76px;
  height: 76px;
}

.ca-detail-team h1 {
  margin: 0;
  font-size: clamp(var(--type-24), 3vw, var(--type-32));
}

.ca-detail-team p,
.ca-detail-center p {
  margin: var(--space-1) 0 0;
  color: var(--text-secondary);
}

.ca-detail-center {
  text-align: center;
}

.ca-detail-center strong {
  display: block;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-24);
}

.ca-detail-facts {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
}

.ca-detail-fact {
  padding: var(--space-3);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-detail-fact span,
.ca-detail-fact strong {
  display: block;
}

.ca-detail-fact span {
  color: var(--text-meta);
  font-size: var(--type-caps);
  text-transform: uppercase;
  letter-spacing: var(--tracking-caps);
}

.ca-detail-fact strong {
  margin-top: var(--space-1);
  color: var(--text-primary);
  font-size: var(--type-14);
}

.ca-detail-nav {
  position: sticky;
  top: var(--shell-header-h);
  z-index: calc(var(--z-header) - 1);
  display: grid;
  grid-template-columns: repeat(6, minmax(max-content, 1fr));
  gap: var(--space-1);
  margin: var(--space-3) 0;
  padding: var(--space-1);
  overflow-x: auto;
  -ms-overflow-style: none;
  scrollbar-width: none;
  background: var(--surface-inset);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
}

.ca-detail-nav::-webkit-scrollbar { display: none; }

.ca-detail-nav a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--touch-min);
  min-height: var(--touch-min);
  padding: 0 var(--space-3);
  border-radius: var(--radius-xs);
  color: var(--text-secondary);
  font-size: var(--type-meta);
  font-weight: 700;
  white-space: nowrap;
}

.ca-detail-nav a:hover,
.ca-detail-nav a:focus-visible {
  color: var(--text-primary);
  background: var(--accent-soft);
}

.ca-detail-stack {
  display: grid;
  gap: var(--space-3);
}

.ca-detail-section {
  position: relative;
  padding: var(--space-4);
  overflow: hidden;
  scroll-margin-top: calc(var(--shell-header-h) + 60px);
}

.ca-detail-section__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.ca-detail-section__head h2 {
  margin: 0;
}

.ca-detail-section__head p {
  margin: 0;
  color: var(--text-meta);
  font-size: var(--type-meta);
}

.ca-detail-duo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.ca-detail-team-panel {
  min-width: 0;
  padding: var(--space-3);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-detail-team-panel__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.ca-detail-team-panel__head img {
  width: 44px;
  height: 44px;
  object-fit: contain;
}

.ca-detail-team-panel__head h3,
.ca-detail-team-panel__head p {
  margin: 0;
}

.ca-detail-team-panel__head p {
  color: var(--text-meta);
  font-size: var(--type-meta);
}

.ca-detail-list {
  display: grid;
  gap: 0;
  margin: 0;
}

.ca-detail-list div {
  display: grid;
  grid-template-columns: minmax(120px, 0.45fr) minmax(0, 1fr);
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--border-subtle);
}

.ca-detail-list dt {
  color: var(--text-meta);
}

.ca-detail-list dd {
  margin: 0;
  color: var(--text-primary);
  font-weight: 600;
  text-align: right;
  overflow-wrap: anywhere;
}

.ca-detail-source-note {
  color: var(--text-secondary);
  line-height: var(--leading-note);
  max-width: var(--measure-note);
}

/* What the bullpen table deliberately leaves out - tonight's starter and rotation
   arms who worked behind an opener - read as a footnote to the table it qualifies. */
.ca-bullpen-note {
  margin: var(--space-3) 0 0;
}

@media (max-width: 1100px) {
  .ca-slate-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-detail-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 820px) {
  .ca-public-page,
  .ca-opening-desk,
  .ca-detail-page {
    padding-inline: var(--shell-gutter-md);
  }
  .ca-public-page__head { grid-template-columns: 1fr; align-items: start; }
  .ca-public-page__links { justify-content: flex-start; }
  .ca-desk-toolbar { align-items: stretch; flex-direction: column; }
  .ca-desk-toolbar__primary,
  .ca-desk-toolbar__secondary { width: 100%; }
  .ca-desk-search { width: 100%; }
  .ca-detail-hero__teams {
    grid-template-columns: minmax(0, 1fr) minmax(72px, auto) minmax(0, 1fr);
    gap: var(--space-3);
    padding: var(--space-4) 0;
  }
  .ca-detail-team,
  .ca-detail-team--home { justify-content: center; flex-direction: column; text-align: center; }
}

@media (max-width: 680px) {
  .ca-public-page,
  .ca-opening-desk,
  .ca-detail-page {
    padding: var(--space-4) var(--shell-gutter-sm) var(--space-8);
  }
  .ca-slate-grid { grid-template-columns: 1fr; }
  .ca-matchup-card { min-height: 0; }
  .ca-matchup-card.is-expanded { grid-column: auto; }
  .ca-matchup-card__teams { grid-template-columns: minmax(0, 1fr) 16px minmax(0, 1fr); }
  .ca-matchup-card__club,
  .ca-matchup-card__club--home { flex-direction: column; gap: var(--space-1); text-align: center; }
  .ca-matchup-card__versus { display: block; }
  .ca-matchup-card__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-matchup-card__summary .ca-matchup-card__fact:last-child { grid-column: 1 / -1; }
  .ca-matchup-card__detail-grid,
  .ca-matchup-card__environment,
  .ca-matchup-card__starters,
  .ca-detail-facts,
  .ca-detail-duo { grid-template-columns: 1fr; }
  .ca-matchup-card__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-matchup-card__summary .ca-matchup-card__fact:last-child { grid-column: 1 / -1; }
  .ca-matchup-card__actions { align-items: stretch; }
  .ca-matchup-card__expand-btn,
  .ca-matchup-card__detail-link { flex: 1; min-width: 0; padding-inline: var(--space-2); text-align: center; }
  .ca-desk-toolbar__primary,
  .ca-desk-toolbar__secondary,
  .ca-desk-dates { align-items: stretch; flex-wrap: wrap; }
  .ca-desk-dates { width: 100%; }
  .ca-desk-dates__today { flex: 1; min-width: 0; }
  .ca-desk-search { order: 2; margin: 0; }
  .ca-desk-count { align-self: center; margin-left: auto; }
  .ca-opening-sport__head { align-items: flex-start; flex-direction: column; }
  .ca-detail-hero__meta { align-items: flex-start; flex-direction: column; }
  .ca-detail-hero { padding: var(--space-3); }
  .ca-detail-hero__teams { gap: var(--space-2); }
  .ca-detail-team { gap: var(--space-2); }
  .ca-detail-team__logo { width: 48px; height: 48px; }
  .ca-detail-team h1 { font-size: var(--type-16); line-height: 1.15; }
  .ca-detail-center strong { font-size: var(--type-20); }
  .ca-detail-center p { max-width: 90px; margin-inline: auto; font-size: var(--type-meta); line-height: 1.2; }
  .ca-detail-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
  .ca-detail-fact { padding: var(--space-2); }
  .ca-detail-list div { grid-template-columns: 1fr; gap: var(--space-1); }
  .ca-detail-list dd { text-align: left; }
}

@media (max-width: 420px) {
  .ca-matchup-card__name { font-size: var(--type-14); }
  .ca-matchup-logo { width: 44px; height: 44px; }
  .ca-matchup-card__head { align-items: flex-start; }
  .ca-matchup-card__broadcast { display: block; max-width: 24ch; margin: var(--space-1) 0 0; padding: 0; border: 0; }
}

/* ===========================================================================
 * DESK RESTORE - 2026-09-09
 * Implements design/GPT_IMAGE_PROMPTS_CHASE_DESK.md prompt 1/2/4 against the
 * existing public markup. Appended last so equal-specificity flat rules above
 * are superseded by source order. Public content stays factual: no projected
 * score, probability, market line, or edge metric appears in this file.
 * ======================================================================== */

body[data-ca-product="research"] {
  background-image: var(--canvas-ambient);
  background-attachment: fixed;
  background-repeat: no-repeat;
}

/* Desk masthead */
.ca-public-page__title,
.ca-opening-desk__title {
  font-size: var(--type-display);
  font-weight: 800;
  letter-spacing: -0.015em;
  line-height: 1.02;
  text-wrap: balance;
}

.ca-public-page__lede,
.ca-opening-desk__lede {
  max-width: 68ch;
  font-size: var(--type-16);
}

/* Slate boards. Each sport section and kickoff window is a lacquered board
   with the 3px violet edge, so the slate reads as one surface instead of
   loose cards on bare canvas. */
.ca-opening-sport,
.ca-kickoff-window,
.ca-slate-board {
  position: relative;
  padding: var(--space-5) var(--space-5) var(--space-5) calc(var(--space-5) + 3px);
  background: var(--surface-board);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  box-shadow: var(--elevation-2);
  overflow: hidden;
}

.ca-opening-sport::before,
.ca-kickoff-window::before,
.ca-slate-board::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--edge-brand);
}

.ca-opening-sport::after,
.ca-kickoff-window::after,
.ca-slate-board::after {
  content: "";
  position: absolute;
  inset: 0 0 auto 3px;
  height: 1px;
  background: var(--edge-glint);
}

.ca-kickoff-window + .ca-kickoff-window { margin-top: var(--space-4); }

.ca-opening-sport__head h2,
.ca-kickoff-window > header h2 {
  font-size: var(--type-section);
  font-weight: 800;
  letter-spacing: 0.01em;
}

.ca-kickoff-window > header {
  border-bottom: 1px solid var(--border-default);
  padding-bottom: var(--space-3);
}

.ca-kickoff-window > header span,
.ca-desk-count,
.ca-desk-window-label {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Toolbar */
.ca-desk-toolbar {
  padding: var(--space-3) var(--space-4);
  background: var(--surface-board-raised);
  border-color: var(--border-default);
  box-shadow: var(--elevation-2);
  flex-wrap: wrap;
}

.ca-desk-dates button,
.ca-desk-chip,
.ca-desk-view-toggle button {
  background: var(--surface-inset);
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
  font-weight: 600;
}
.ca-desk-dates button:hover,
.ca-desk-chip:hover { background: var(--control-bg-hover); color: var(--text-primary); }

.ca-desk-dates__today {
  font-family: var(--font-display);
  font-size: var(--type-16);
  letter-spacing: 0.01em;
  color: var(--text-primary);
}

.ca-desk-chip.is-on {
  background: var(--accent-soft);
  border-color: var(--border-accent);
  color: var(--text-accent);
}

/* The grid. AUDIT D5: this was a flat repeat(3, 1fr), so a one-game kickoff
   window rendered a narrow card beside two empty tracks.

   A single auto-fit minmax() cannot express the documented breakpoints - the
   style lock and scripts/public_site_runtime_diag.py both want 3 columns at
   1440, 2 from 720 to 1099, and 1 below that, and no single track minimum
   yields 3-at-1440 and 2-at-720. So the counts stay explicit, and :has()
   handles the real D5 case: a window holding fewer cards than the track count
   drops to that many columns instead of leaving dead tracks. */
.ca-slate-grid { gap: var(--space-3); }

@media (min-width: 1100px) {
  .ca-slate-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ca-slate-grid:not(:has(> :nth-child(2))) { grid-template-columns: minmax(0, 1fr); }
  .ca-slate-grid:has(> :nth-child(2)):not(:has(> :nth-child(3))) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 620px) and (max-width: 1099px) {
  .ca-slate-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-slate-grid:not(:has(> :nth-child(2))) { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 619px) {
  .ca-slate-grid { grid-template-columns: minmax(0, 1fr); }
}

/* Matchup card */
.ca-matchup-card {
  gap: var(--space-3);
  padding: var(--space-4);
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  box-shadow: var(--elevation-2);
  transition: box-shadow var(--motion-base) var(--motion-ease),
              border-color var(--motion-base) var(--motion-ease);
}

.ca-matchup-card::before { background: var(--edge-brand); }

.ca-matchup-card:hover,
.ca-matchup-card:focus-within {
  border-color: var(--border-accent);
  box-shadow: var(--elevation-glow);
}

.ca-matchup-card__head {
  align-items: center;
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-matchup-card__kick {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  font-family: var(--font-display);
  font-size: var(--type-16);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: 0.01em;
}

.ca-matchup-card__broadcast {
  font-family: var(--font-ui);
  font-size: var(--type-meta);
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  text-transform: none;
  overflow-wrap: anywhere;
  white-space: normal;
}

/* Identity band: two inset fields, logo left, abbreviation as display type,
   full team name and record beneath. Full names stay visible per the public
   content rules; the abbreviation is a scan aid, not the identity. */
.ca-matchup-card__teams {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: stretch;
  gap: var(--space-2);
}

.ca-matchup-card__club {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  padding: var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-matchup-card__club--home { flex-direction: row; text-align: left; }

.ca-matchup-card__club .ca-matchup-logo,
.ca-matchup-card__club img {
  width: 40px;
  height: 40px;
  object-fit: contain;
  flex: 0 0 auto;
}

.ca-matchup-card__club-copy {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
  align-items: flex-start;
  text-align: left;
}

.ca-matchup-card__abbr {
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: 0.02em;
  color: var(--text-primary);
}

/* The club's name is the first thing a card is read for. It sat at 12px/500
   in a silver gradient - the smallest, faintest line on the card. */
.ca-matchup-card__name {
  font-family: var(--font-ui);
  font-size: var(--type-14);
  font-weight: 600;
  /* 1.12, not 1.2: a two-line name is the tallest thing in the club block,
     and the collapsed card is held to 350px (public_site_runtime_diag). */
  line-height: 1.12;
  color: var(--text-primary);
  white-space: normal;
  overflow-wrap: anywhere;
}

.ca-matchup-card__record {
  font-size: var(--type-meta);
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
}

.ca-matchup-card__versus {
  align-self: center;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Factual cells */
.ca-matchup-card__summary,
.ca-matchup-card__detail-grid,
.ca-matchup-card__environment {
  gap: var(--space-2);
}

.ca-matchup-card__fact {
  padding: var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-matchup-card__fact > span {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-matchup-card__fact > strong {
  font-size: var(--type-14);
  font-weight: 600;
  color: var(--text-primary);
}

/* Starter fields */
.ca-matchup-card__starter {
  padding: var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-matchup-card__starter strong {
  font-size: var(--type-14);
  font-weight: 700;
  color: var(--text-primary);
}

.ca-matchup-card__starter-label {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Actions */
.ca-matchup-card__actions {
  align-items: center;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border-subtle);
}

.ca-matchup-card__expand-btn {
  background: var(--surface-inset);
  border: 1px solid var(--border-default);
  color: var(--text-primary);
  font-weight: 600;
}
.ca-matchup-card__expand-btn:hover {
  background: var(--control-bg-hover);
  border-color: var(--border-accent);
}

.ca-matchup-card__detail-link {
  color: var(--text-accent);
  font-weight: 600;
}
.ca-matchup-card__detail-link:hover { color: var(--text-primary); }

.ca-matchup-card__updated {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Status chips read as lit controls rather than grey outlines. */
.ca-status-chip {
  font-family: var(--font-display);
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  white-space: nowrap;
}
.ca-status-chip.is-live {
  background: var(--tint-positive);
  border: 1px solid var(--mark-positive);
  color: var(--metric-elite);
}
.ca-status-chip.is-final {
  background: var(--surface-inset);
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
}
.ca-status-chip.is-ok {
  background: var(--accent-soft);
  border: 1px solid var(--border-accent);
  color: var(--metric-elite);
}
.ca-status-chip.is-watch {
  background: var(--tint-caution);
  border: 1px solid var(--mark-caution);
  color: var(--value-caution);
}
.ca-status-chip.is-muted {
  background: var(--surface-inset);
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
}

/* Expanded panel sits on the darker inset so it reads as beneath the card. */
.ca-matchup-card__expand {
  padding: var(--space-3);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

@media (max-width: 620px) {
  .ca-matchup-card__teams { grid-template-columns: minmax(0, 1fr); }
  .ca-matchup-card__versus { justify-self: start; }
}

/* --- Desk restore, pass 2: card rhythm ----------------------------------
 * Pass 1 restored the surfaces; these rules fix the geometry the first local
 * capture exposed - ragged card heights inside a row, a 3-line broadcast
 * string, and fact labels wrapping onto two lines inside a 130px cell. */

/* Cards in a row share a height, and the action row is pinned to the bottom so
 * the "Expand matchup" controls line up across the row. */
.ca-slate-grid { align-items: stretch; }
.ca-slate-grid > .ca-matchup-card { height: 100%; }
.ca-matchup-card__actions { margin-top: auto; }

/* The card header stays one line tall: time and status on the baseline, the
 * broadcast list clamped to a single line that ends at a word. */
.ca-matchup-card__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--space-3);
}

.ca-matchup-card__kick {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--space-2);
  min-width: 0;
}

.ca-matchup-card__broadcast {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-width: 0;
}

/* Identity band: a fixed logo track means the logo and the copy always sit
 * side by side, whatever intrinsic width the crest image reports. */
.ca-matchup-card__club {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr);
  align-items: center;
  column-gap: var(--space-3);
}
.ca-matchup-card__club > img,
.ca-matchup-card__club > .ca-matchup-logo,
.ca-matchup-card__club > .ca-team-logo-placeholder {
  grid-column: 1;
  width: 40px;
  height: 40px;
  justify-self: center;
}
.ca-matchup-card__club-copy { grid-column: 2; }

/* Fact cells: give the wide label the room it needs so "Probable starters"
 * stays on one line, and let the value wrap under it. */
.ca-matchup-card__summary {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1.2fr);
  align-items: stretch;
}

.ca-matchup-card__fact {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
}

.ca-matchup-card__fact > span {
  line-height: 1.2;
  letter-spacing: 0.05em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ca-matchup-card__fact > strong {
  line-height: 1.3;
  overflow-wrap: anywhere;
}

@media (max-width: 620px) {
  .ca-matchup-card__summary { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .ca-matchup-card__summary > .ca-matchup-card__fact:first-child { grid-column: 1 / -1; }
}

/* The base rule caps this at 20ch with white-space:nowrap, which is what cut
   "Broadcast not published" to "Broadcast not..." mid-word (AUDIT B6). The
   clamp above already ends the line at a word, so the character cap goes. */
.ca-matchup-card__broadcast {
  max-width: none;
  margin-left: 0;
  padding-left: var(--space-3);
  border-left: 1px solid var(--border-default);
  vertical-align: baseline;
}

/* On a phone the status chip takes the header's auto track and the broadcast
   list is squeezed to two characters ("D.."). Give it its own line there. */
@media (max-width: 620px) {
  .ca-matchup-card__kick {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--space-1);
  }
  .ca-matchup-card__broadcast {
    padding-left: 0;
    border-left: 0;
    -webkit-line-clamp: 2;
  }
}

/* --- Club-coloured abbreviation tab ---------------------------------------
 * Replaced the crest in the card identity band on 2026-09-09 (owner decision,
 * following the Model Center reference renderings). Ground and ink arrive as
 * --team-bg / --team-ink from MLBMAAssets.teamTabHtml, which derives the
 * ink from the ground's luminance, so a gold club gets dark text. An unknown
 * club sets neither and falls back to the neutral inset below.
 *
 * Player headshots are unaffected: they stay on the starter panels and the
 * profile pages, where a face is the subject rather than a club identity. */
.ca-team-tab {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  min-width: 58px;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-xs);
  background: var(--team-bg, var(--surface-inset));
  color: var(--team-ink, var(--text-primary));
  border: 1px solid var(--border-subtle);
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

.ca-matchup-card__club {
  grid-template-columns: auto minmax(0, 1fr);
}

.ca-matchup-card__tab { min-width: 58px; }

@media (max-width: 400px) {
  .ca-team-tab { min-width: 50px; font-size: var(--type-16); }
}

/* --- Collapsed card height contract ---------------------------------------
 * scripts/public_site_runtime_diag.py holds the collapsed card to 240-360px on
 * desktop, and the style lock says 272-350px. The identity tab and the fact
 * cells added rhythm that pushed it to 362-380px, so the internal spacing is
 * tightened rather than the content cut - every published fact stays. */
.ca-matchup-card {
  padding: var(--space-3);
  gap: var(--space-2);
}

.ca-matchup-card__club { padding: var(--space-2) var(--space-3); }

.ca-matchup-card__head { padding-bottom: var(--space-2); }

.ca-matchup-card__actions { padding-top: var(--space-2); }

.ca-matchup-card__fact { padding: var(--space-2) var(--space-3); }

/* --- Card text fitting at 3-column width ----------------------------------
 * Two defects visible on the live 1440px slate after the club tabs narrowed
 * the cells:
 *
 * 1. The fact label was nowrap + ellipsis, so a ~230px cell cut
 *    "Probable starters" to "PROBABLE START..." - the same mid-word clip this
 *    pass already fixed on the broadcast line. Labels wrap to two lines now.
 * 2. .ca-matchup-card__name used overflow-wrap:anywhere, which breaks INSIDE a
 *    word rather than at a space: "Washingto / n Nationals". break-word only
 *    breaks a word that cannot fit a line on its own, so multi-word club names
 *    wrap where they should. */
.ca-matchup-card__fact > span {
  white-space: normal;
  text-overflow: clip;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.ca-matchup-card__name {
  overflow-wrap: break-word;
  word-break: normal;
}

/* ===========================================================================
 * FLAT WIDE DESK - 2026-09-10
 *
 * Three corrections against the reference renderings:
 *
 * 1. DE-NEST. The slate had four levels of rounded container - section board >
 *    grid wrapper > card > inner field - so every card sat inside two boxes
 *    that carry no information. The renderings put cards DIRECTLY on the desk:
 *    a section is an eyebrow and a heading in open space, nothing more.
 * 2. FLATTEN. Ambient violet washes and lacquered gradients are gone (see
 *    chase-semantic.css). The desk is matte near-black; colour is reserved for
 *    team identity, status and data.
 * 3. WIDEN. The shell fills the display, and extra width buys more columns
 *    rather than wider cards.
 * ======================================================================== */

/* --- 1. De-nest: sections are headings in open space, not boards ---------- */
.ca-opening-sport,
.ca-kickoff-window,
.ca-slate-board {
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
}

/* The violet rail and the top glint belonged to the wrapper boards. With the
   wrappers gone the accent lives on the card itself, where it marks a game. */
.ca-opening-sport::before,
.ca-opening-sport::after,
.ca-kickoff-window::before,
.ca-kickoff-window::after,
.ca-slate-board::before,
.ca-slate-board::after {
  content: none;
}

.ca-opening-desk__slates {
  display: grid;
  gap: var(--space-9);
}

.ca-kickoff-window + .ca-kickoff-window { margin-top: var(--space-8); }

/* Section head: eyebrow over heading, count/action pushed right, one hairline
   under it. This is the whole chrome a section gets. */
.ca-opening-sport__head,
.ca-kickoff-window > header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
  margin-bottom: var(--space-4);
  padding: 0 0 var(--space-3);
  border-bottom: 1px solid var(--border-default);
}

.ca-opening-sport__head h2,
.ca-kickoff-window > header h2 {
  margin: 0;
  font-size: var(--type-section);
  font-weight: 800;
  letter-spacing: 0.01em;
}

/* The embedded slate header ("15 games" + "View full MLB slate") was a boxed
   strip inside the wrapper. It joins the section head line instead. */
.ca-embedded-slate-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  margin: 0 0 var(--space-4);
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
}

/* --- 2. Flat surfaces ----------------------------------------------------- */
.ca-desk-toolbar {
  padding: 0 0 var(--space-4);
  margin-bottom: var(--space-5);
  background: none;
  border: 0;
  border-bottom: 1px solid var(--border-default);
  border-radius: 0;
  box-shadow: none;
}

.ca-matchup-card {
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: none;
}

/* Hover reads as the edge lighting up, not the card floating. */
.ca-matchup-card:hover,
.ca-matchup-card:focus-within {
  border-color: var(--border-accent);
  box-shadow: none;
}

.ca-matchup-card__club,
.ca-matchup-card__fact,
.ca-matchup-card__starter,
.ca-matchup-card__expand {
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
}

/* --- 3. Width and columns -------------------------------------------------
 * More display buys more tracks. The counts at and below 1440 are held by
 * scripts/public_site_runtime_diag.py; the wider steps are additive. */
@media (min-width: 1680px) {
  .ca-slate-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .ca-slate-grid:not(:has(> :nth-child(2))) { grid-template-columns: minmax(0, 1fr); }
  .ca-slate-grid:has(> :nth-child(2)):not(:has(> :nth-child(3))) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .ca-slate-grid:has(> :nth-child(3)):not(:has(> :nth-child(4))) {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (min-width: 2080px) {
  .ca-slate-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

/* Page shell gutters follow the wider frame. */
.ca-public-page,
.ca-opening-desk {
  padding-left: var(--shell-gutter);
  padding-right: var(--shell-gutter);
}

/* ===========================================================================
 * WIDER CARDS, CHROME TITLES, TIGHTER MASTHEAD - 2026-09-10
 * ======================================================================== */

/* --- 1. Chrome display titles --------------------------------------------
 * .ca-page-title (Model Center, 404, glossary) already painted its h1 with the
 * metallic silver fill while the matchup routes rendered flat white, so the
 * site read as two different products. Same treatment everywhere now.
 * Guarded: without background-clip:text a transparent color would erase the
 * heading, so the fill only applies where the browser supports it. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .ca-public-page__title,
  .ca-opening-desk__title {
    background: var(--text-display-metal);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* --- 2. Wider cards -------------------------------------------------------
 * The previous pass bought extra COLUMNS with the extra width, which made each
 * card narrower - 457px at 1920 and 399px at 2560, against 453px at 1440. So
 * a bigger display produced a more cramped card: team names wrapped to two
 * lines and the fact labels wrapped at 2560.
 *
 * Extra width now goes into the cards. Three columns hold until the shell is
 * wide enough that a fourth still leaves each card above ~600px, which is
 * where the internals stop wrapping. Counts at and below 1440 are unchanged -
 * scripts/public_site_runtime_diag.py holds them. */
@media (min-width: 1441px) {
  .ca-slate-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ca-slate-grid:not(:has(> :nth-child(2))) { grid-template-columns: minmax(0, 1fr); }
  .ca-slate-grid:has(> :nth-child(2)):not(:has(> :nth-child(3))) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* No fourth column. The shell caps at 2100px, so four tracks can never exceed
   ~516px per card - narrower than the 613px three tracks give at 1920. Three
   columns hold all the way up, which puts ~690px into each card at 2560. */

/* --- 3. Let the card breathe ---------------------------------------------
 * With ~610px to work in, the internals get room back: the identity band and
 * the fact cells stop fighting for the same 130px.
 *
 * Scoped to 1441px and up. At 1440 the card is 453px and still holds three
 * columns, where the same padding pushed the collapsed card to 363px against
 * the 240-360px contract in scripts/public_site_runtime_diag.py. */
@media (min-width: 1441px) {
  .ca-matchup-card {
    padding: var(--space-4);
    gap: var(--space-3);
  }

  .ca-matchup-card__club { padding: var(--space-3); }

  .ca-matchup-card__fact { padding: var(--space-3); }

  /* The club name sits at reading size and on one line wherever it fits. */
  .ca-matchup-card__name {
    font-size: var(--type-14);
    line-height: 1.3;
  }
}

/* At a comfortable card width the label no longer needs the two-line clamp. */
@media (min-width: 1441px) {
  .ca-matchup-card__fact > span {
    -webkit-line-clamp: 1;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}

/* --- 4. Tighten the masthead ---------------------------------------------
 * The block above the first card ran ~270px of mostly empty space. */
.ca-public-page,
.ca-opening-desk {
  padding-top: var(--space-5);
  padding-bottom: var(--space-8);
}

.ca-public-page__head,
.ca-opening-desk__head {
  padding-bottom: var(--space-4);
}

.ca-public-page__lede,
.ca-opening-desk__lede {
  margin-top: var(--space-1);
}

.ca-opening-desk__slates { gap: var(--space-7); }

.ca-opening-sport__head,
.ca-kickoff-window > header { margin-bottom: var(--space-3); }

.ca-embedded-slate-head { margin-bottom: var(--space-3); }

/* --- Masthead density -----------------------------------------------------
 * At 1920 the band above the first card ran 364px, and most of it was the
 * standfirst wrapping to two lines inside a 68ch cap while ~900px of the row
 * sat empty. The reading cap is right for a paragraph; this line is a one-line
 * deck, so it gets the room it needs and the block loses a line. */
@media (min-width: 1200px) {
  .ca-public-page__lede,
  .ca-opening-desk__lede {
    max-width: 108ch;
  }
}

.ca-desk-toolbar { margin-bottom: var(--space-4); }

/* ===========================================================================
 * SYMMETRIC CARD BODY + COLLAPSED TOP CHROME - 2026-09-10
 * ======================================================================== */

/* --- Controls join the title row -----------------------------------------
 * The date/filter band was a row of its own holding three controls in a
 * 1561px track, most of it empty. It now sits opposite the title, which is
 * where the reference chrome puts it and removes a whole band. */
.ca-public-page__head,
.ca-opening-desk__head {
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  align-items: end;
  column-gap: var(--space-6);
}

.ca-public-page__controls { min-width: 0; justify-self: end; }

.ca-public-page__controls .ca-desk-toolbar {
  margin: 0;
  padding: 0;
  border: 0;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.ca-public-page__controls .ca-desk-toolbar__primary { flex: 0 0 auto; }
.ca-public-page__controls .ca-desk-toolbar__secondary { flex: 0 0 auto; }

/* The context strip already reports the slate size. */
.ca-public-page__controls .ca-desk-count { display: none; }

@media (max-width: 1100px) {
  .ca-public-page__head,
  .ca-opening-desk__head { grid-template-columns: minmax(0, 1fr); }
  .ca-public-page__controls { justify-self: start; }
  .ca-public-page__controls .ca-desk-toolbar { justify-content: flex-start; }
}

/* --- Starter faces --------------------------------------------------------
 * Two equal columns so the row stays symmetric whichever side has data. */
.ca-matchup-card__arms {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-2);
}

.ca-matchup-card__arm {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  align-items: center;
  column-gap: var(--space-3);
  min-width: 0;
  padding: var(--space-2) var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
}

.ca-matchup-card__arm .ca-matchup-card__shot {
  width: 36px;
  height: 36px;
  border-radius: var(--radius-pill);
  object-fit: cover;
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
}

.ca-matchup-card__arm-copy { display: grid; gap: 1px; min-width: 0; }

.ca-matchup-card__arm-name {
  font-size: var(--type-14);
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.25;
  overflow-wrap: break-word;
}

.ca-matchup-card__arm-meta {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* --- Meta strip: four equal cells ---------------------------------------- */
.ca-matchup-card__summary {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (min-width: 1441px) {
  .ca-matchup-card__summary { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (max-width: 620px) {
  .ca-matchup-card__arms { grid-template-columns: minmax(0, 1fr); }
  .ca-matchup-card__summary > .ca-matchup-card__fact:first-child { grid-column: auto; }
}

/* An absent season line is muted prose, not tracked caps - it was shouting
   "SEASON LINE NOT PUBLISHED" once per starter, twice per card. */
.ca-matchup-card__arm-meta.is-absent {
  font-family: var(--font-ui);
  font-size: var(--type-meta);
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-muted);
}

/* Secondary page links (Results) join the control row instead of stranding
   themselves on a line of their own under the title. */
.ca-public-page__head { row-gap: var(--space-2); }

.ca-public-page__links {
  grid-column: 2;
  justify-self: end;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0;
}

@media (max-width: 1100px) {
  .ca-public-page__links { grid-column: 1; justify-self: start; }
}

/* --- Team offensive context ----------------------------------------------
 * OSI / wRC+ / wOBA / ABQ with a league rank beside each, from the published
 * team-rankings snapshot. Value and rank sit together so the number always
 * reads as a description of the season, never as a forecast. */
.ca-ctx-duo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.ca-ctx-head {
  margin: 0 0 var(--space-2);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-ctx-strip {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
}

.ca-ctx-cell {
  display: grid;
  gap: 1px;
  padding: var(--space-2) var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  min-width: 0;
}

.ca-ctx-label {
  font-family: var(--font-display);
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  /* No uppercase transform: wRC+ and wOBA are proper metric names and
     "WRC+" / "WOBA" are simply wrong. The renderer supplies the exact
     casing. */
  color: var(--text-muted);
}

.ca-ctx-value {
  font-family: var(--font-display);
  font-size: var(--type-20);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}

.ca-ctx-rank {
  font-size: var(--type-meta);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 760px) {
  .ca-ctx-duo { grid-template-columns: minmax(0, 1fr); }
  .ca-ctx-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- NFL availability ------------------------------------------------------
 * Official injury-report designations. Status carries colour because it is a
 * factual severity, not a grade: out / doubtful / questionable. */
.ca-avail-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-1);
}

.ca-avail-row {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) minmax(0, auto) auto;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  min-width: 0;
}

.ca-avail-pos {
  font-family: var(--font-display);
  font-size: var(--type-meta);
  font-weight: 800;
  letter-spacing: .04em;
  color: var(--text-muted);
}

.ca-avail-name {
  font-size: var(--type-14);
  font-weight: 600;
  color: var(--text-primary);
  overflow-wrap: break-word;
  min-width: 0;
}

.ca-avail-detail {
  font-size: var(--type-meta);
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ca-avail-status {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 2px var(--space-2);
  border-radius: var(--radius-xs);
  white-space: nowrap;
}
.ca-avail-status.is-out { background: var(--tint-negative); color: var(--value-negative); }
.ca-avail-status.is-doubtful { background: var(--tint-caution); color: var(--value-caution); }
.ca-avail-status.is-questionable { background: var(--surface-inset); color: var(--text-secondary); }

.ca-avail-empty,
.ca-avail-more {
  margin: var(--space-2) 0 0;
  font-size: var(--type-meta);
  color: var(--text-muted);
}

@media (max-width: 620px) {
  .ca-avail-row { grid-template-columns: 34px minmax(0, 1fr) auto; }
  .ca-avail-detail { display: none; }
}

/* --- Club identity: crest first ------------------------------------------
 * Back to official crests (2026-09-10). The club colour stays as a 3px left
 * rule on the identity block - present enough to separate the two sides at a
 * glance, restrained enough that the crest is what carries the club, which is
 * what the matchup IA asks for.
 *
 * Crest sizing and variant selection are measured in mlbma_assets.js. */
.ca-matchup-card__club {
  grid-template-columns: 44px minmax(0, 1fr);
  border-left: 3px solid var(--team-accent, var(--border-default));
  padding-left: var(--space-3);
}

.ca-matchup-card__club .ca-matchup-logo,
.ca-matchup-card__club > img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  /* The crests are transparent PNGs served at 3x; let the browser scale them
     smoothly rather than pixel-doubling. */
  image-rendering: auto;
}

.ca-matchup-card__tab { display: none; }

@media (max-width: 400px) {
  .ca-matchup-card__club { grid-template-columns: 38px minmax(0, 1fr); }
  .ca-matchup-card__club .ca-matchup-logo,
  .ca-matchup-card__club > img { width: 38px; height: 38px; }
}

/* The four-cell strip clamped labels to one nowrap line, so at three columns
   "Lineup status" became "LINEUP STA...". Two lines, ending at a word. */
.ca-matchup-card__fact > span {
  white-space: normal;
  text-overflow: clip;
  -webkit-line-clamp: 2;
  line-height: 1.2;
}

@media (min-width: 1441px) {
  .ca-matchup-card__fact > span {
    -webkit-line-clamp: 2;
    white-space: normal;
    text-overflow: clip;
  }
}

/* --- Matchup breakdown evidence -------------------------------------------
 * Starter panels, the lineup-versus-starter tables and the league-relative
 * form grid. Flat surfaces, tabular numbers, every value beside its rank or
 * its sample. */
.ca-detail-stack-inner { display: grid; gap: var(--space-4); }

.ca-starter-panel,
.ca-lineup-panel,
.ca-form-panel {
  padding: var(--space-4);
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  min-width: 0;
}

.ca-starter-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-starter-shot {
  width: 72px;
  height: 72px;
  border-radius: var(--radius-pill);
  object-fit: cover;
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
  flex: 0 0 auto;
}

.ca-starter-team {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-starter-name {
  margin: 2px 0 0;
  font-family: var(--font-display);
  font-size: var(--type-section);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-lineup-panel > h3,
.ca-form-panel > h3 {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: 0 0 var(--space-1);
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  color: var(--text-primary);
}

/* The resolved context is stated, so the reader never has to rebuild it from
   filters: which lineup, home or away, against which hand. */
.ca-lineup-context {
  margin: 0 0 var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-accent);
}

.ca-lineup-scroll { overflow-x: auto; }

.ca-lineup-table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: var(--type-14);
  font-variant-numeric: tabular-nums;
}

.ca-lineup-table th {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border-default);
  white-space: nowrap;
}

.ca-lineup-table td {
  padding: var(--space-2) var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  /* Defers to the cell's own grade when it carries one. */
  color: var(--grade, var(--text-secondary));
}
.ca-lineup-table tbody tr:last-child td { border-bottom: 0; }

.ca-lineup-table .num { text-align: right; }
.ca-lineup-slot { color: var(--text-muted); font-family: var(--font-display); font-weight: 700; }
.ca-lineup-name { color: var(--text-primary); font-weight: 600; white-space: nowrap; }

.ca-form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 140px), 1fr));
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.ca-form-cell {
  display: grid;
  gap: 1px;
  padding: var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
}

.ca-form-label {
  font-family: var(--font-display);
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
}

.ca-form-value {
  font-family: var(--font-display);
  font-size: var(--type-24);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}

.ca-form-rank {
  font-size: var(--type-meta);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* A percentile bar carries one meaning only: where this rate sits in its own
   league pool. It is drawn from the value beside it, never from a rating. */
.ca-pct-bar {
  display: block;
  height: 4px;
  margin: var(--space-1) 0 3px;
  background: var(--surface-raised);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.ca-pct-bar__fill {
  display: block;
  height: 100%;
  min-width: 2px;
  background: var(--accent);
  border-radius: var(--radius-pill);
}

.ca-form-grid--tight {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 92px), 1fr));
  margin: 0 0 var(--space-3);
}
.ca-form-grid--tight .ca-form-value { font-size: var(--type-18); }

/* --- Pitch mix -------------------------------------------------------------
 * Each row is one offering: name, its share of this pitcher's own pitches,
 * the share as a number, then velocity and sample. The bars sum to 100%. */
.ca-arsenal-panel {
  padding: var(--space-4);
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  min-width: 0;
}

.ca-arsenal-panel > h3 {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-2);
  margin: 0 0 var(--space-1);
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  color: var(--text-primary);
}
.ca-arsenal-panel > h3 .ca-mirror__crest { margin-inline: 0; }

.ca-arsenal-list {
  display: grid;
  gap: var(--space-2);
  margin: var(--space-3) 0;
}

.ca-arsenal-row {
  display: grid;
  grid-template-columns: minmax(88px, 1fr) minmax(60px, 2fr) auto;
  grid-template-areas: "name bar pct" "meta meta meta";
  align-items: center;
  gap: 2px var(--space-3);
}

.ca-arsenal-name {
  grid-area: name;
  font-size: var(--type-14);
  color: var(--text-primary);
  font-weight: 600;
}

.ca-arsenal-bar {
  grid-area: bar;
  display: block;
  height: 8px;
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  overflow: hidden;
}

.ca-arsenal-bar__fill {
  display: block;
  height: 100%;
  background: var(--accent);
}

.ca-arsenal-pct {
  grid-area: pct;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--type-14);
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.ca-arsenal-meta {
  grid-area: meta;
  font-size: var(--type-meta);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* --- Bullpen workload ---------------------------------------------------- */
.ca-bullpen-subsection + .ca-bullpen-subsection {
  margin-top: var(--space-6);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border-default);
}

.ca-bullpen-subhead {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.ca-bullpen-subhead p,
.ca-bullpen-subhead h3 { margin: 0; }

.ca-bullpen-subhead p,
.ca-bullpen-subhead > span {
  color: var(--text-accent);
  font-family: var(--font-sans);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-bullpen-subhead h3 {
  margin-top: 2px;
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-18);
}

.ca-bullpen-subhead > span { color: var(--text-muted); }

.ca-bullpen-split-grid { align-items: stretch; }

.ca-bullpen-splits {
  min-width: 0;
  padding: var(--space-4);
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
}

.ca-bullpen-splits__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.ca-bullpen-splits__logo {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  object-fit: contain;
}

.ca-bullpen-splits__head h3,
.ca-bullpen-splits__head p { margin: 0; }
.ca-bullpen-splits__head h3 {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-18);
}
.ca-bullpen-splits__head p,
.ca-bullpen-splits__sample {
  color: var(--text-muted);
  font-size: var(--type-meta);
}

.ca-bullpen-splits__sample {
  margin: var(--space-3) 0 var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border-subtle);
  font-variant-numeric: tabular-nums;
}

.ca-bullpen-split-table {
  width: 100%;
  min-width: 600px;
  border-collapse: collapse;
  font-size: var(--type-data);
  font-variant-numeric: tabular-nums;
}

.ca-bullpen-split-table th,
.ca-bullpen-split-table td {
  padding: 9px var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-secondary);
  white-space: nowrap;
}

.ca-bullpen-split-table thead th {
  color: var(--text-muted);
  font-family: var(--font-sans);
  font-size: var(--type-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-bullpen-split-table th:first-child { padding-left: 0; text-align: left; }
.ca-bullpen-split-table td:last-child,
.ca-bullpen-split-table th:last-child { padding-right: 0; }
.ca-bullpen-split-table .num { text-align: right; }
.ca-bullpen-split-table tbody th { color: var(--text-primary); font-weight: 800; }
.ca-bullpen-split-table tbody tr:last-child th,
.ca-bullpen-split-table tbody tr:last-child td { border-bottom: 0; }

.ca-bullpen-split-table tr.is-matchup {
  background: color-mix(in srgb, var(--accent) 9%, transparent);
  box-shadow: inset 3px 0 0 var(--accent);
}

.ca-bullpen-split-table tr.is-matchup th:first-child { padding-left: var(--space-2); }
.ca-bullpen-split-table tr.is-matchup th span {
  display: inline-block;
  margin-left: 4px;
  padding: 1px 5px;
  border-radius: var(--radius-xs);
  background: var(--accent-soft);
  color: var(--accent-text);
  font-size: var(--type-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-bullpen-panel {
  padding: var(--space-4);
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  min-width: 0;
}

.ca-bullpen-panel > h3 {
  margin: 0 0 var(--space-1);
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  color: var(--text-primary);
}

/* An arm that worked yesterday and the day before is the one fact a workload
   table exists to surface, so it is marked rather than left to be counted. */
.ca-flag {
  display: inline-block;
  margin-left: var(--space-2);
  padding: 1px 6px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-accent);
}

.ca-coverage-result { display: grid; align-content: center; min-height: 66px; padding: var(--space-2) var(--space-3); }
.ca-coverage-result { border-right: 1px solid var(--border-subtle); }
.ca-coverage-result--def { border-right: 0; border-left: 1px solid var(--border-subtle); text-align: right; }
.ca-coverage-result strong {
  color: var(--grade, var(--text-primary));
  font-family: var(--font-display);
  font-size: var(--type-20);
  font-variant-numeric: tabular-nums;
}
.ca-coverage-result span { color: var(--text-muted); font-size: var(--type-meta); }

.ca-coverage-track {
  display: grid;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  gap: 3px;
  height: 12px;
}
.ca-coverage-track i {
  display: block;
  min-width: 0;
  height: 12px;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 1px;
}
.ca-coverage-track i.is-on { background: var(--accent); border-color: var(--accent); }

/* Two columns, split the way the confrontation is: that defence on one side,
   this offence on the other. */
.ca-scheme-duo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  align-items: start;
  gap: var(--space-3);
  margin-top: var(--space-3);
}

.ca-scheme-col { display: grid; align-content: start; gap: var(--space-3); min-width: 0; }

.ca-scheme-col__head {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-14);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-accent);
}

/* The bar sits under the label at its own scale, so a column of shares can be
   read by shape before any of the numbers are read at all. */
.ca-rate-bar {
  display: block;
  height: 3px;
  margin-top: 3px;
  background: var(--surface-raised);
  border-radius: var(--radius-pill);
  overflow: hidden;
}

.ca-rate-bar > span {
  display: block;
  height: 100%;
  min-width: 2px;
  background: var(--accent);
  border-radius: var(--radius-pill);
}

/* The segments are categories, not a scale, so they take the series palette
   rather than anything that reads as good-to-bad. */
.ca-stack {
  display: flex;
  height: 14px;
  border-radius: var(--radius-xs);
  overflow: hidden;
  border: 1px solid var(--border-subtle);
}

.ca-stack__seg { display: block; height: 100%; }

.ca-stack__key {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 3px var(--space-3);
  font-size: var(--type-meta);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.ca-stack__key li { display: flex; align-items: center; gap: 5px; }
.ca-stack__key strong { color: var(--text-primary); }

.ca-stack__swatch {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  flex: 0 0 auto;
}

.ca-stack__seg--1, .ca-stack__swatch--1 { background: var(--series-1); }
.ca-stack__seg--2, .ca-stack__swatch--2 { background: var(--series-2); }
.ca-stack__seg--3, .ca-stack__swatch--3 { background: var(--series-3); }
.ca-stack__seg--4, .ca-stack__swatch--4 { background: var(--series-4); }
.ca-stack__seg--5, .ca-stack__swatch--5 { background: var(--series-5); }
.ca-stack__seg--6, .ca-stack__swatch--6 { background: var(--series-6); }
.ca-stack__seg--7, .ca-stack__swatch--7 { background: var(--series-7); }

/* A designation is state, so it reads as a chip rather than as another word in
   the row. Out and doubtful carry the weight; questionable stays quieter. */
.ca-status-pill {
  display: inline-block;
  padding: 1px 7px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--border-default);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-secondary);
  white-space: nowrap;
}

.ca-status-pill[data-status="out"],
.ca-status-pill[data-status="injured-reserve"],
.ca-status-pill[data-status="suspension"],
.ca-status-pill[data-status="suspended"] {
  color: var(--status-error);
  border-color: var(--status-error);
}

.ca-status-pill[data-status="doubtful"],
.ca-status-pill[data-status="pup"] {
  color: var(--status-stale);
  border-color: var(--status-stale);
}

/* --- NFL starting units --------------------------------------------------
 * Formation rows follow the attached broadcast-board reference: portraits
 * lead, position and name share one plate, and availability stays attached. */
.ca-lineup-board {
  min-width: 0;
  padding: var(--space-4);
  background: var(--surface-board-raised);
  border: 1.5px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--elevation-1), inset 0 1px 0 var(--border-subtle);
}

.ca-lineup-board__head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-lineup-board__logo {
  width: 44px;
  height: 44px;
  object-fit: contain;
  flex: 0 0 auto;
}

.ca-lineup-board__head h3 {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--type-20);
  color: var(--text-primary);
}

.ca-lineup-board__head p {
  margin: 2px 0 0;
  font-size: var(--type-meta);
  color: var(--text-muted);
}

.ca-lineup-tabs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
  margin: var(--space-3) 0;
  padding: 4px;
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
}

.ca-lineup-tab {
  appearance: none;
  min-height: var(--touch-min);
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  transition: color 100ms ease-out, background 100ms ease-out, border-color 100ms ease-out;
}

.ca-lineup-tab:hover { color: var(--text-primary); background: var(--surface-raised); }
.ca-lineup-tab.is-on {
  color: var(--accent-text);
  background: var(--accent-soft);
  border-color: var(--accent-strong);
  box-shadow: inset 0 1px 0 var(--border-strong);
}
.ca-lineup-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.ca-lineup-unit[hidden] { display: none !important; }

.ca-lineup-unit__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
  margin-bottom: var(--space-3);
}

.ca-lineup-unit__meta strong {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-14);
}

.ca-lineup-unit__meta span {
  color: var(--text-muted);
  font-size: var(--type-meta);
  white-space: nowrap;
}

.ca-lineup-groups {
  display: grid;
  gap: var(--space-4);
  padding: var(--space-4);
  background: var(--surface-inset);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 var(--border-default);
}

.ca-lineup-group { min-width: 0; }

.ca-lineup-group > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 0 var(--space-2);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-lineup-group > header h4 {
  margin: 0;
  color: var(--text-accent);
  font-family: var(--font-sans);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-lineup-group > header span {
  color: var(--text-muted);
  font-size: var(--type-meta);
  font-variant-numeric: tabular-nums;
}

.ca-lineup-group__players {
  display: flex;
  justify-content: center;
  align-items: stretch;
  gap: var(--space-2);
  padding-top: var(--space-2);
}

.ca-lineup-player {
  position: relative;
  display: grid;
  grid-template-rows: 88px auto auto;
  align-content: start;
  flex: 1 1 0;
  max-width: 136px;
  min-width: 0;
  min-height: 156px;
  overflow: hidden;
  background: var(--surface-board-raised);
  border: 1.5px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: var(--elevation-1), inset 0 1px 0 var(--border-strong);
  transition: transform 100ms ease-out, border-color 100ms ease-out, box-shadow 100ms ease-out;
}

.ca-lineup-player:hover {
  transform: translateY(-2px);
  border-color: var(--accent-strong);
  box-shadow: var(--elevation-2), inset 0 2px 0 var(--accent-strong);
}

.ca-lineup-player__shot,
.ca-lineup-player__initials {
  width: 100%;
  height: 88px;
  border: 0;
  border-bottom: 1px solid var(--border-default);
  background: var(--surface-raised);
}

.ca-lineup-player__shot { object-fit: contain; object-position: center bottom; }

.ca-lineup-player__initials {
  display: grid;
  place-items: center;
  color: var(--text-accent);
  font-family: var(--font-display);
  font-size: var(--type-24);
  font-weight: 800;
  letter-spacing: .04em;
}

.ca-lineup-player__identity {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 3px;
  min-width: 0;
  min-height: 44px;
  padding: 5px 4px;
  background: var(--surface-field);
  border-bottom: 1px solid var(--border-subtle);
}
.ca-lineup-player__identity strong {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  line-height: 1.05;
  text-transform: uppercase;
  overflow-wrap: anywhere;
}

.ca-lineup-player__position {
  display: inline-grid;
  place-items: center;
  min-width: 30px;
  min-height: 26px;
  padding: 2px 3px;
  color: var(--text-primary);
  background: linear-gradient(180deg, var(--surface-elevated), var(--surface-inset));
  border: 1px solid var(--border-strong);
  border-radius: 2px;
  box-shadow: inset 0 1px 0 var(--border-subtle), inset 0 -1px 0 var(--surface-board);
  font-family: var(--font-sans);
  font-size: var(--type-meta);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
}

.ca-lineup-player__availability {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 3px 5px;
  min-width: 0;
  min-height: 27px;
  padding: 3px 5px;
  background: var(--surface-inset);
}

.ca-lineup-player__availability small {
  max-width: 100%;
  color: var(--text-muted);
  font-size: var(--type-meta);
  overflow-wrap: anywhere;
  text-align: center;
}

.ca-status-pill[data-status="active"] {
  color: var(--status-ok);
  border-color: var(--status-ok);
  background: var(--surface-inset);
}

.ca-status-pill[data-status="report-pending"] {
  color: var(--text-muted);
  border-color: var(--border-subtle);
  background: var(--surface-inset);
}

.ca-injury-report {
  margin-top: var(--space-3);
  border: 1px solid var(--accent-border);
  border-left: 3px solid var(--accent);
  background: var(--accent-soft);
}

.ca-injury-report summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: var(--touch-min);
  padding: 0 var(--space-3);
  color: var(--text-primary);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--type-16);
  font-weight: 800;
}

.ca-injury-report summary:hover,
.ca-injury-report summary:focus-visible { color: var(--text-accent); background: var(--surface-hover); }
.ca-injury-report summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ca-injury-report__label { color: inherit; }
.ca-injury-report__count {
  padding: 4px 8px;
  color: var(--text-primary);
  border: 1px solid var(--accent-border);
  background: var(--surface-raised);
  font-family: var(--font-body);
  font-size: var(--type-meta);
}
.ca-injury-report .ca-avail-list { margin: var(--space-2) var(--space-3) var(--space-3); }

@media (max-width: 720px) {
  .ca-detail-nav {
    display: flex;
    top: var(--shell-header-h-phone);
  }
  .ca-detail-nav a { flex: 0 0 auto; }
  .ca-detail-section { scroll-margin-top: calc(var(--shell-header-h-phone) + 60px); }
}

@media (max-width: 1100px) {
  .ca-lineup-duo { grid-template-columns: 1fr; }
  .ca-lineup-player { max-width: 148px; }
}

@media (max-width: 520px) {
  .ca-lineup-board { padding: var(--space-3); }
  .ca-lineup-unit__meta { align-items: flex-start; flex-direction: column; }
  .ca-lineup-groups { padding: var(--space-3); }
  .ca-lineup-group__players { display: grid; grid-template-columns: 1fr; gap: 6px; }
  .ca-lineup-player {
    max-width: none;
    min-height: 78px;
    grid-template-columns: 72px minmax(0, 1fr);
    grid-template-rows: minmax(44px, auto) minmax(34px, auto);
  }
  .ca-lineup-player__shot,
  .ca-lineup-player__initials {
    grid-column: 1;
    grid-row: 1 / 3;
    width: 72px;
    height: 100%;
    min-height: 78px;
    border-right: 1px solid var(--border-default);
    border-bottom: 0;
  }
  .ca-lineup-player__identity { grid-column: 2; grid-row: 1; padding-inline: 7px; }
  .ca-lineup-player__availability {
    grid-column: 2;
    grid-row: 2;
    justify-content: flex-start;
    padding-inline: 7px;
  }
  .ca-lineup-player__availability small { max-width: none; }
  .ca-status-pill { white-space: normal; }
}

/* ===========================================================================
 * CARD: VENUE FIRST, WEATHER AS A SYMBOL, NUMBERS THAT CARRY THEIR GRADE
 * ======================================================================== */

/* Where the game is played is the first thing a reader orients on, so it gets
   the top edge of the card rather than fourth place in a row of small facts. */
.ca-matchup-card__venue {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px var(--space-2);
  padding: var(--space-2) var(--space-4);
  background: var(--surface-field);
  border-bottom: 1px solid var(--border-subtle);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  margin: calc(-1 * var(--space-4)) calc(-1 * var(--space-4)) var(--space-3);
}

.ca-matchup-card__venue-name {
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--text-primary);
  min-width: 0;
}

.ca-matchup-card__venue-city {
  font-size: var(--type-meta);
  color: var(--text-muted);
  min-width: 0;
}

.ca-matchup-card__venue .ca-status-chip { margin-left: auto; flex: 0 0 auto; }

/* Conditions read as a symbol first and words second. The symbol is a second
   channel, never the only one - the text stays beside it. */
.ca-matchup-card__wx {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--type-meta);
  color: var(--text-secondary);
  min-width: 0;
}

.ca-wx {
  flex: 0 0 auto;
  color: var(--text-accent);
}

/* The starter's ERA, graded against the published league baseline, so the
   number says how good it is without the reader having to know the league. */
/* The chip reads on one line. Stacking the value over its label made the
   starter row the tallest block on the card and pushed it out of the 272-350px
   band the style lock sets. */
.ca-matchup-card__arm-era {
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  gap: 4px;
  margin-left: auto;
  padding: 3px 7px;
  min-width: 46px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  flex: 0 0 auto;
}

.ca-matchup-card__arm-era i {
  font-style: normal;
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
}

/* The five-step grade chips, shared lineage with the rest of the desk. They
   colour the number itself and tint its frame; the value is never carried by
   colour alone, because the rank or the label always sits beside it. */

/* --- Chrome on every title and sub-title ---------------------------------
 * The metallic fill was reserved for page h1s while every section heading
 * under them rendered flat white, so a page read as two typographic systems
 * stacked. One treatment now, down to the panel headings.
 *
 * Guarded: without background-clip:text a transparent colour erases the text,
 * so the fill only applies where the browser supports it. Small uppercase
 * labels and table headers are deliberately excluded - a gradient across
 * 11px tracked caps reads as a rendering fault, not as chrome. The club name
 * on a card is excluded for the same reason: at card size the gradient's
 * dark band turned the most important word on the card grey. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .ca-public-page__title,
.ca-opening-desk__title,
.ca-opening-sport__head h2,
.ca-detail-section__head h2,
.ca-detail-team h1,
.ca-starter-name,
.ca-lineup-panel > h3,
.ca-form-panel > h3,
.ca-arsenal-panel > h3,
.ca-lineup-board__head h3,
.ca-bullpen-panel > h3,
.ca-matchup-card__venue-name {
    background: var(--text-display-metal);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

/* The building's own facts ride with its name rather than taking a cell in the
   row below, where they would sit beside things that change hour to hour. */
.ca-matchup-card__venue-tag {
  padding: 1px 6px;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  white-space: nowrap;
}

/* Two cells, one row, every card. A three-cell grid left the third alone on a
   row of its own and added sixty pixels of nothing to every card on the page. */
.ca-matchup-card__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* ===========================================================================
 * THE MIRRORED COMPARISON
 *
 * One metric per row, both clubs on one axis, bars growing out from a centre
 * column that names the metric. The reader compares by looking at one line
 * instead of carrying a number across a gutter.
 * ======================================================================== */
.ca-mirror {
  display: grid;
  gap: 0;
  margin: var(--space-3) 0 var(--space-4);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  background: var(--surface-board-raised);
  overflow: hidden;
}

.ca-mirror__head,
.ca-mirror__row {
  display: grid;
  grid-template-columns:
    minmax(64px, 88px) minmax(0, 1fr) minmax(120px, 190px) minmax(0, 1fr) minmax(64px, 88px);
  align-items: center;
  gap: var(--space-2) var(--space-3);
}

.ca-mirror__head {
  grid-template-columns: minmax(0, 1fr) minmax(120px, 190px) minmax(0, 1fr);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-field);
  border-bottom: 1px solid var(--border-default);
}

.ca-mirror__team {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-mirror__team--home { justify-content: flex-end; text-align: right; }

.ca-mirror__team i {
  display: block;
  font-style: normal;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-mirror__crest { width: 28px; height: 28px; object-fit: contain; flex: 0 0 auto; }

.ca-mirror__group {
  padding: var(--space-2) var(--space-4);
  background: var(--surface-field);
  border-bottom: 1px solid var(--border-subtle);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-mirror__axis {
  text-align: center;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-mirror__row {
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--border-subtle);
}
.ca-mirror__row:last-child { border-bottom: 0; }

.ca-mirror__label {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-secondary);
  line-height: 1.25;
}

.ca-mirror__value {
  display: flex;
  flex-direction: column;
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.ca-mirror__value i {
  font-style: normal;
  font-size: var(--type-meta);
  font-weight: 600;
  color: var(--text-muted);
}

.ca-mirror__value.is-absent { color: var(--text-muted); font-weight: 600; }

/* The away bar fills from the centre outward, so both bars grow away from the
   label and their tips are what the eye compares. */
.ca-mirror__track {
  display: flex;
  height: 10px;
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  overflow: hidden;
  min-width: 0;
}

/* The away bar grows leftward from the centre so both bars run outward from
   the label and their tips are what the eye compares. */
.ca-mirror__track--away { justify-content: flex-end; }

.ca-mirror__fill {
  display: block;
  height: 100%;
  background: var(--accent);
  min-width: 2px;
}

/* The better season carries the emphasis, so a scan down the column shows who
   wins each row before a single number is read. Never colour alone: the rank
   sits under every value and the bar length says the same thing. */
.ca-mirror__row.is-away .ca-mirror__track--away .ca-mirror__fill,
.ca-mirror__row.is-home .ca-mirror__track--home .ca-mirror__fill {
  background: var(--metric-elite);
}

/* Superseded further down: the losing side used to be dimmed to secondary
   text regardless of how good its season was, which outranked the grade on
   specificity and left a club ranked third in the league drawn in the same
   grey as one ranked thirtieth. The row's winner is carried by the bars. */
.ca-mirror__row.is-away .ca-mirror__value--home,
.ca-mirror__row.is-home .ca-mirror__value--away {
  color: var(--grade, var(--text-secondary));
}

@media (max-width: 720px) {
  /* Stacked, the mirror stops being a mirror, so each row becomes a plain
     three-part line: away, metric, home - still one row per metric. */
  .ca-mirror__head { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--space-2); }
  .ca-mirror__axis { display: none; }
  .ca-mirror__team { align-items: flex-start; font-size: var(--type-meta); line-height: 1.15; }
  .ca-mirror__team--home { grid-column: 2; }
  .ca-mirror__crest { width: 22px; height: 22px; }
  .ca-mirror__row {
    grid-template-columns: minmax(56px, auto) minmax(0, 1fr) minmax(56px, auto);
    padding: var(--space-2) var(--space-3);
  }
  .ca-mirror__row > .ca-mirror__track { display: none; }
  .ca-mirror__value { font-size: var(--type-14); }
}

/* The home value mirrors the away one, so its rank hangs off the same edge as
   its number rather than drifting back toward the centre. */
.ca-mirror__value--home { align-items: flex-end; text-align: right; }

/* --- Headline stats ------------------------------------------------------
 * The four numbers a scout reads first, at the size that says so. Everything
 * behind them stays in the list underneath, where "Batters Faced" belongs. */
.ca-stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 76px), 1fr));
  gap: var(--space-2);
  margin: 0 0 var(--space-3);
}

.ca-stat {
  display: grid;
  gap: 1px;
  padding: var(--space-2) var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  text-align: center;
}

.ca-stat__label {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-stat__value {
  font-family: var(--font-display);
  font-size: var(--type-24);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}

/* --- Tables that can be scanned -----------------------------------------
 * A batting order is read down one column at a time, so the rows alternate
 * and the name column carries the weight. Headers hold at the top of a long
 * scroll instead of leaving the reader guessing which column is which. */
.ca-lineup-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-board-raised);
}

.ca-lineup-table tbody tr:nth-child(even) { background: var(--surface-field); }
.ca-lineup-table tbody tr:hover { background: var(--surface-raised); }

.ca-lineup-table .ca-lineup-slot {
  font-size: var(--type-14);
  color: var(--text-accent);
  text-align: center;
}

/* --- Pitch mix, with weight ---------------------------------------------- */
.ca-arsenal-bar { height: 12px; }

.ca-arsenal-row:first-child .ca-arsenal-name,
.ca-arsenal-row:first-child .ca-arsenal-pct { color: var(--text-primary); }

/* --- The hero, at the scale a hero needs -------------------------------- */
.ca-detail-center strong {
  font-family: var(--font-display);
  font-size: clamp(30px, 2rem + 1.4vw, 50px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.015em;
  font-variant-numeric: tabular-nums;
}

.ca-detail-team h1 {
  font-size: clamp(22px, 1rem + 1.3vw, 34px);
  line-height: 1.08;
  text-wrap: balance;
}

/* ===========================================================================
 * THE GRADE RAMP - LAST, ON PURPOSE
 *
 * A graded number is applied on top of a component that already sets its own
 * colour (.ca-stat__value, .ca-ctx-value), and at equal specificity the later
 * rule wins. Stated once here at the end of the route layer, the grade always
 * beats the component it decorates instead of silently losing to whichever
 * block happened to be written second.
 *
 * Colour is never the only channel: every graded number has its rank, its
 * label or its bar beside it.
 * ======================================================================== */
/* Each grade publishes its colour as --grade as well as painting itself.
   `.ca-lineup-table td` is one class plus one element, which outranks a bare
   `.c-elite`, so every graded figure inside a table rendered in the default
   text colour and the colour coding silently did nothing. Rather than escalate
   specificity rule by rule, a context that wants to defer to a grade reads the
   custom property with its own colour as the fallback - custom properties are
   not subject to the cascade conflict that caused this. */
.c-elite { --grade: var(--metric-elite); }
.c-good  { --grade: var(--metric-good); }
.c-mid   { --grade: var(--metric-mid); }
.c-weak  { --grade: var(--metric-weak); }
.c-poor  { --grade: var(--metric-poor); }
.c-na    { --grade: var(--text-muted); }

.c-elite, .c-good, .c-mid, .c-weak, .c-poor, .c-na {
  color: var(--grade);
  border-color: var(--grade);
}

/* Inside a bordered frame the grade tints the frame too; inline in a table it
   must not draw a box round a single figure. */
.ca-ctx-value.c-elite, .ca-ctx-value.c-good, .ca-ctx-value.c-mid,
.ca-ctx-value.c-weak, .ca-ctx-value.c-poor,
.ca-stat__value.c-elite, .ca-stat__value.c-good, .ca-stat__value.c-mid,
.ca-stat__value.c-weak, .ca-stat__value.c-poor { border-color: transparent; }

/* ===========================================================================
 * THE STYLE LOCK'S OWN NUMBERS
 *
 * design/GPT_IMAGE_PROMPTS_CHASE_DESK.md fixes the collapsed card at 272-350px
 * with three compact factual cells. The card had drifted to 449px, and the
 * extra height had been bought by dropping a cell — so it was failing the
 * measurement twice over. The rhythm below holds the whole anatomy the owner
 * has asked for (venue strip, starter faces, three cells) inside the band.
 * ======================================================================== */
.ca-matchup-card {
  /* No max-height. A clamp would squeeze the flex children rather than fail
     loudly, so a longer team name would quietly compress the card instead of
     showing that the rhythm no longer fits. The rhythm does the work, and
     public_site_runtime_diag holds the 272-350px band.

     The target is the middle of that band, not its ceiling. Sitting exactly on
     350 meant CI's font stack rounded one pixel higher than this machine's and
     failed the gate on a rendering difference rather than a design one. */
  gap: 5px;
}

.ca-matchup-card__venue {
  padding: 4px var(--space-3);
  margin: calc(-1 * var(--space-3)) calc(-1 * var(--space-3)) 0;
  flex-wrap: nowrap;
  overflow: hidden;
}

.ca-matchup-card__venue-name,
.ca-matchup-card__venue-city { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ca-matchup-card__venue-city { flex: 0 1 auto; }

/* One line, always. The broadcast has its own cell now, so nothing here wraps. */
.ca-matchup-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 0;
  padding-left: 0;
  white-space: nowrap;
  overflow: hidden;
}

.ca-matchup-card__teams { min-height: 0; padding: 4px var(--space-1); }
.ca-matchup-card__club { padding: var(--space-1) var(--space-2); }

.ca-matchup-card__arm { padding: 3px var(--space-2); }
.ca-matchup-card__arm-era { padding: 1px 6px; min-width: 42px; }

.ca-matchup-card__summary { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.ca-matchup-card__fact {
  padding: 6px var(--space-2);
  min-width: 0;
}
.ca-matchup-card__fact strong {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ca-matchup-card__actions { padding-top: var(--space-1); }

@media (max-width: 720px) {
  /* Stacked, a fixed ceiling would clip; the anatomy is the same, the height
     is whatever one column of it needs. */
  .ca-matchup-card { max-height: none; }
  .ca-matchup-card__summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---------------------------------------------------------------------------
 * Violet is reserved.
 *
 * The style lock is explicit: #9A6BFF is for active navigation, the 3px card
 * edge, links and focus - "not data grading". Every bar that describes a
 * number now takes the metric ramp instead, which is also the honest signal:
 * a bar that says how good a rate is should not be the same colour as a link.
 * ------------------------------------------------------------------------ */
.ca-pct-bar__fill,
.ca-arsenal-bar__fill,
.ca-mirror__fill,
.ca-rate-bar > span { background: var(--metric-neutral); }

.ca-mirror__row.is-away .ca-mirror__track--away .ca-mirror__fill,
.ca-mirror__row.is-home .ca-mirror__track--home .ca-mirror__fill {
  background: var(--metric-elite);
}

/* The analysis hero carries the crests at the size the rendering draws them -
   roughly 100px at the outer edges, so identity lands before anything else. */
.ca-detail-team__logo { width: 96px; height: 96px; object-fit: contain; }

@media (max-width: 720px) {
  .ca-detail-team__logo { width: 56px; height: 56px; }
}

/* ===========================================================================
 * STATS WITHOUT BOXES
 *
 * Border, fill and radius each say "separate object". Stamped on every stat
 * cell they said it about forty times on one page, so nothing read as more
 * important than anything else and the numbers themselves fought their own
 * frames for attention.
 *
 * The grouping is carried by a single hairline between cells instead. The
 * panel around the group is still a panel; the cells inside it are just
 * columns of type.
 * ======================================================================== */
.ca-stat,
.ca-form-cell,
.ca-ctx-cell,
.ca-matchup-card__fact {
  background: none;
  border: 0;
  border-radius: 0;
  padding: var(--space-2) var(--space-3);
}

/* One hairline between cells, none on the outside - so the row reads as one
   object divided, not as a strip of separate ones. */
.ca-stat-row,
.ca-form-grid,
.ca-ctx-strip,
.ca-matchup-card__summary {
  gap: 0;
}

.ca-stat + .ca-stat,
.ca-form-cell + .ca-form-cell,
.ca-ctx-cell + .ca-ctx-cell,
.ca-matchup-card__fact + .ca-matchup-card__fact {
  border-left: 1px solid var(--border-subtle);
}

/* When the grid wraps, the cell that starts a new row must not carry a divider
   on its left edge - it is the first of its row, not a continuation. */
.ca-form-grid { row-gap: var(--space-3); }
.ca-stat-row { row-gap: var(--space-2); }

.ca-stat { text-align: left; }
.ca-stat__value { line-height: 1.1; }

/* The ERA chip on a card keeps its frame: it is a badge on a person's row, not
   a cell in a group, and without an edge it would read as loose text beside a
   headshot. */
.ca-matchup-card__arm-era { border: 1px solid var(--border-default); }

/* ===========================================================================
 * DISCLOSURE
 *
 * The legacy Team Rankings board lives here now: inside the matchup, behind a
 * summary, rather than as a public destination of its own. A reader who wants
 * the league gets the league; everyone else gets the two clubs in front of
 * them.
 * ======================================================================== */
.ca-disclosure {
  margin-top: var(--space-3);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  background: var(--surface-field);
}

.ca-disclosure > summary {
  cursor: pointer;
  padding: var(--space-3);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-accent);
  list-style: none;
}

.ca-disclosure > summary::-webkit-details-marker { display: none; }

.ca-disclosure > summary::after {
  content: " +";
  font-weight: 800;
}
.ca-disclosure[open] > summary::after { content: " \2212"; }

.ca-disclosure > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.ca-disclosure__body {
  padding: 0 var(--space-3) var(--space-3);
  border-top: 1px solid var(--border-subtle);
}
.ca-disclosure__body > .ca-lineup-context { padding-top: var(--space-3); }

/* The rank rides with its value rather than taking a column of its own, so
   thirty rows of seven metrics stay one screen wide. */
.ca-league-table td.num i {
  font-style: normal;
  font-size: var(--type-meta);
  font-weight: 600;
  color: var(--text-muted);
  margin-left: 5px;
}

/* The two clubs in this game are marked so they can be found without hunting
   down thirty rows - by weight and a label, not by colour alone. */
.ca-league-table tbody tr.is-here { background: var(--surface-raised); }
.ca-league-table tbody tr.is-here .ca-lineup-name { color: var(--text-primary); font-weight: 800; }

/* ===========================================================================
 * CLUB COLOUR, WHERE IT ANSWERS "WHOSE SIDE IS THIS"
 *
 * The style lock reserves brand violet from data grading, and that rule holds:
 * nothing below encodes how good a number is. What these hues encode is
 * identity - a club's own published colour, on that club's own side of a
 * two-sided chart - so the reader stops counting columns to work out which bar
 * belongs to whom. Length still carries the value and the rank still sits
 * beside it, so the chart survives with the colour removed.
 * ======================================================================== */
.ca-mirror__track--away .ca-mirror__fill[data-club] { background: var(--club-away, var(--metric-neutral)); }
.ca-mirror__track--home .ca-mirror__fill[data-club] { background: var(--club-home, var(--metric-neutral)); }

/* The winning side still takes the emphasis colour: that IS a statement about
   the number, so it overrides identity where the two would compete. */
.ca-mirror__row.is-away .ca-mirror__track--away .ca-mirror__fill,
.ca-mirror__row.is-home .ca-mirror__track--home .ca-mirror__fill {
  background: var(--metric-elite);
}

/* The crest plates in the mirror head carry a hairline of the club's colour,
   so the header states the same identity the bars below it use. */
.ca-mirror__head { border-bottom-width: 1px; }

/* --- Pitch families ------------------------------------------------------
 * An arsenal reads by shape before it reads by number. These are categories -
 * a slider is not "better" than a fastball - so they take the series palette,
 * never the metric ramp. */
.ca-arsenal-row[data-pitch="heat"] .ca-arsenal-bar__fill { background: var(--series-7); }
.ca-arsenal-row[data-pitch="break"] .ca-arsenal-bar__fill { background: var(--series-3); }
.ca-arsenal-row[data-pitch="offspeed"] .ca-arsenal-bar__fill { background: var(--series-4); }
.ca-arsenal-row[data-pitch="other"] .ca-arsenal-bar__fill { background: var(--series-6); }

/* The family is named as well as coloured, so the grouping is never carried by
   hue alone. */
.ca-arsenal-row[data-pitch]::after {
  grid-area: meta;
  justify-self: end;
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}
.ca-arsenal-row[data-pitch="heat"]::after { content: "Fastball"; }
.ca-arsenal-row[data-pitch="break"]::after { content: "Breaking"; }
.ca-arsenal-row[data-pitch="offspeed"]::after { content: "Offspeed"; }
.ca-arsenal-row[data-pitch="other"]::after { content: "Other"; }

.ca-arsenal-row { grid-template-areas: "name bar pct" "meta meta after"; }
.ca-arsenal-row { grid-template-columns: minmax(88px, 1fr) minmax(60px, 2fr) auto; }

/* ===========================================================================
 * THE OPPONENT'S HISTORY AGAINST THE PITCH
 *
 * A usage share only means something beside what the other lineup has done
 * with that pitch. The rank is a chip so it can be scanned down the column;
 * the number is always printed, so the colour is a second reading of a fact
 * that is already legible without it.
 * ======================================================================== */
.ca-arsenal-opp {
  grid-area: opp;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 3px var(--space-2);
  padding-top: 3px;
  font-size: var(--type-meta);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.ca-arsenal-opp__label {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-arsenal-opp strong {
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-arsenal-opp__whiff,
.ca-arsenal-opp__n { color: var(--text-muted); }

.ca-arsenal-row {
  grid-template-areas: "name bar pct" "meta meta after" "opp opp opp";
  row-gap: 2px;
}

/* One rank chip, one meaning, everywhere it appears. */
.ca-rank {
  display: inline-block;
  margin-left: 3px;
  padding: 0 5px;
  border-radius: var(--radius-xs);
  border: 1px solid currentColor;
  font-family: var(--font-display);
  font-size: var(--type-meta);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* A sample count in pill form: same shape as a rank, no tier colour, so an
   ungraded thin split reads in the same rhythm as a graded one. */
.ca-rank.is-sample { color: var(--text-muted); border-color: var(--border-default); }

/* ===========================================================================
 * LAST TEN GAMES
 *
 * The quickest read of form there is: ten squares, oldest to newest, each one
 * a game with its own score. Won and lost are carried by the letter as well as
 * the colour, so the strip survives being printed in grey.
 * ======================================================================== */
.ca-recent-stack { display: grid; gap: var(--space-3); }

.ca-recent {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
}

.ca-recent__team {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-recent__crest { width: 24px; height: 24px; object-fit: contain; flex: 0 0 auto; }

.ca-recent__record {
  display: flex;
  flex-direction: column;
  font-family: var(--font-display);
  font-size: var(--type-18);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
}
.ca-recent__record i {
  font-style: normal;
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-recent__games { display: flex; flex-wrap: wrap; gap: 4px; margin-left: auto; }

.ca-recent__game {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 0;
  min-width: 40px;
  padding: 3px 4px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xs);
  font-variant-numeric: tabular-nums;
}

.ca-recent__game abbr {
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  text-decoration: none;
  border: 0;
}

.ca-recent__game i { font-style: normal; font-size: var(--type-meta); color: var(--text-muted); }

.ca-recent__game.is-win { color: var(--metric-elite); border-color: var(--metric-elite); }
.ca-recent__game.is-loss { color: var(--metric-poor); border-color: var(--metric-poor); }

.ca-recent__pending { font-size: var(--type-14); color: var(--text-muted); }

/* ===========================================================================
 * CONDITIONS AS A READING, NOT A SENTENCE
 * ======================================================================== */
.ca-wx-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  margin-bottom: var(--space-3);
}

.ca-wx-tile {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
}

.ca-wx-tile__mark { display: flex; color: var(--text-accent); }
.ca-wx-glyph { display: block; }

.ca-wx-tile__read { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px var(--space-3); }

.ca-wx-tile__read strong {
  font-family: var(--font-display);
  font-size: var(--type-24);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}

.ca-wx-tile__cond { font-size: var(--type-14); color: var(--text-secondary); }

.ca-wx-tile__wind {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--type-meta);
  color: var(--text-muted);
}

.ca-wx-arrow { flex: 0 0 auto; color: var(--text-accent); }

/* ===========================================================================
 * PITCH MIX AS A TABLE
 *
 * Five parallel readings of the same shape, read down a column rather than
 * across a stack of rows. Usage carries a bar and a grade for how heavily the
 * pitch is leaned on; the percentage is printed beside it, so the colour is a
 * second reading of something already legible.
 * ======================================================================== */
.ca-usage {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  justify-content: flex-end;
  min-width: 118px;
}

.ca-usage__bar {
  display: block;
  flex: 1 1 auto;
  min-width: 44px;
  height: 8px;
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xs);
  overflow: hidden;
}

.ca-usage__bar > span { display: block; height: 100%; background: currentColor; }

.ca-usage b {
  font-family: var(--font-display);
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  min-width: 46px;
  text-align: right;
}

/* How heavily the pitch is leaned on - not how good it is. */
.u-primary   { color: var(--series-1); }
.u-secondary { color: var(--series-2); }
.u-tertiary  { color: var(--series-3); }
.u-rare      { color: var(--text-muted); }

.ca-arsenal-table td.num { white-space: nowrap; }
.ca-arsenal-table tbody tr:nth-child(even) { background: var(--surface-field); }

/* The most recent outing, and what the arm does to each side of the plate -
   both named in the architecture as starter content and neither previously
   fetched. */
.ca-last-start {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px var(--space-2);
  margin: 0 0 var(--space-3);
  font-size: var(--type-meta);
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.ca-last-start > span {
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-split-block { margin: 0 0 var(--space-3); }

.ca-split-block h4 {
  margin: 0 0 var(--space-2);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-split-table { min-width: 0; }

/* Ten squares, one per ten per cent. A grid is read at a glance the way a bar
   is not - four filled is "about forty per cent" before the eye reaches the
   number, and the number is printed beside it regardless. */
.ca-usage__grid {
  display: inline-grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 2px;
  flex: 0 0 auto;
}

.ca-usage__grid > i {
  display: block;
  width: 7px;
  height: 12px;
  border-radius: 1px;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
}

.ca-usage__grid > i.is-on { background: currentColor; border-color: currentColor; }

.ca-usage { min-width: 150px; }
.ca-usage__bar { display: none; }

@media (max-width: 720px) {
  .ca-usage__grid > i { width: 5px; height: 10px; }
  .ca-usage { min-width: 120px; }
}

/* ===========================================================================
 * THE TREND LINE
 *
 * The graphic the earlier card carried, rebuilt on what the data holds. Every
 * point's value and its league rank are printed underneath: a chart nobody can
 * read the numbers off is decoration.
 * ======================================================================== */
.ca-spark {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
  min-width: 0;
}

.ca-spark__chart {
  display: block;
  flex: 0 0 auto;
  overflow: visible;
}

.ca-spark__chart polyline {
  fill: none;
  stroke: var(--club, var(--metric-neutral));
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.ca-spark__chart circle {
  fill: var(--club, var(--metric-neutral));
}

/* The most recent window is the one being read, so it carries the weight. */
.ca-spark__chart circle.is-now {
  fill: var(--text-primary);
  stroke: var(--club, var(--metric-neutral));
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.ca-spark__read { display: flex; gap: var(--space-3); flex-wrap: wrap; }

.ca-spark__step {
  display: grid;
  justify-items: center;
  gap: 1px;
  font-variant-numeric: tabular-nums;
}

.ca-spark__step i {
  font-style: normal;
  font-family: var(--font-display);
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  color: var(--text-muted);
}

.ca-spark__step b {
  font-family: var(--font-display);
  font-size: var(--type-14);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-spark__step .ca-rank { margin-left: 0; }

@media (max-width: 720px) {
  .ca-spark__chart { width: 120px; }
}

/* ===========================================================================
 * THE MIRROR IS RED AND GREEN
 *
 * Club colour answered "whose bar is this" and left the reader working out
 * which side was better. Two colours with one meaning instead: green leads the
 * row, red trails it. The rank under every value says the same thing, so the
 * chart survives with the colour removed.
 * ======================================================================== */
.ca-mirror__fill,
.ca-mirror__fill[data-club] { background: var(--metric-poor); }

.ca-mirror__row.is-away .ca-mirror__track--away .ca-mirror__fill,
.ca-mirror__row.is-home .ca-mirror__track--home .ca-mirror__fill {
  background: var(--metric-elite);
}

/* The figure and its rank grade themselves against the thirty-club pool, the
   same ramp every other number on this page uses.
 *
 * They used to take the row's winner: the losing side went red whatever it had
 * done, so a club ranked 16th of 30 was painted the colour of failure because
 * the other club was 15th - while three sections up red meant "poor". Two
 * different meanings for the same colour on the same page is worse than no
 * colour at all.
 *
 * Which side leads is still shown, and shown better: the winning bar fills
 * green and the losing bar red, so the comparison is read off the bars - where
 * length already carries it - and the grade is read off the numbers. */
.ca-mirror__row .ca-mirror__value { color: var(--grade, var(--text-primary)); }
/* Full strength: at 78% a red rank measured 3.5:1 on the panel. */
.ca-mirror__value i { color: inherit; }

/* ===========================================================================
 * TEAM PROFILE RADAR
 *
 * Two webs, both clubs on each. Every axis is a percentile, which is the only
 * honest way to put OSI, wRC+ and xwOBA on one shape. Away and home take the
 * same two colours as the mirror, so a reader who has learned one has learned
 * the other.
 * ======================================================================== */
/* Two webs, side by side and close enough to be read as a pair. An auto-fit
   grid across the full panel width left a third of the section empty between
   them, which made two shapes look like two unrelated charts. */
.ca-radar-duo {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5) var(--space-8);
  margin-bottom: var(--space-4);
}

/* Up to 520px each. At 320px the pair filled a quarter of a 1440 panel and read
   as a thumbnail. The 400px basis keeps the pair side by side down to a
   tablet-width panel instead of stacking at the first squeeze. The type inside
   does not scale with the box: fitRadar() redraws at the drawn width and sets
   --radar-k, so every size below is a screen size at any column width. */
.ca-radar-duo > .ca-radar { flex: 1 1 400px; max-width: 520px; min-width: 0; }
.ca-radar svg { width: 100%; height: auto; max-width: 520px; }

.ca-radar { margin: 0; display: grid; justify-items: center; gap: var(--space-2); }

.ca-radar figcaption {
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-secondary);
}

.ca-radar svg { overflow: visible; }

.ca-radar__ring,
.ca-radar__spoke {
  fill: none;
  stroke: var(--border-subtle);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.ca-radar__ring.is-outer { stroke: var(--border-default); }

/* Both shapes stay readable where they cross. A flat 18% fill let the larger
   club's polygon bury the smaller one, so the pair read as a single lumpy
   outline; a lighter fill plus `screen` makes the overlap BRIGHTER than either
   shape alone, which is exactly the region a reader is looking for. The stroke
   carries each club's outline at full strength either way. */
.ca-radar__area {
  stroke-width: 2.5;
  stroke-linejoin: round;
  fill-opacity: 0.2;
  mix-blend-mode: screen;
  vector-effect: non-scaling-stroke;
}
.ca-radar__area.is-away { stroke: var(--series-1); fill: var(--series-1); }
.ca-radar__area.is-home { stroke: var(--series-4); fill: var(--series-4); }

/* The vertex marks ring themselves in the panel colour so two clubs sitting on
   the same point still read as two points. */
.ca-radar__dot { stroke: var(--surface-board); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.ca-radar__dot.is-away { fill: var(--series-1); }
.ca-radar__dot.is-home { fill: var(--series-4); }

/* Mixed-case names, so no caps tracking: spacing built for capitals opens the
   gaps inside lower-case words and makes them slower to read. */
.ca-radar__label {
  font-family: var(--font-display);
  font-size: calc(var(--type-15) * var(--radar-k, 1));
  font-weight: 700;
  letter-spacing: 0.01em;
  fill: var(--text-primary);
}

.ca-radar-key {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-6);
  margin: 0 0 var(--space-3);
  font-size: var(--type-14);
  font-weight: 600;
  color: var(--text-primary);
}

.ca-radar-key__item { display: inline-flex; align-items: center; gap: var(--space-2); }

.ca-radar-key__swatch {
  display: inline-block;
  flex: 0 0 auto;
  width: 14px;
  height: 14px;
  border-radius: 3px;
}
.ca-radar-key__swatch.is-away { background: var(--series-1); }
.ca-radar-key__swatch.is-home { background: var(--series-4); }

/* --- pitch count by day ------------------------------------------------- */
.ca-pc-table td.num, .ca-pc-table th.num { min-width: 44px; text-align: center; }
.ca-pc { font-family: var(--font-display); font-weight: 800;
         font-variant-numeric: tabular-nums; color: var(--text-muted); }
/* A usage heat scale, cool to hot across its whole range.
 *
 * Read this one as availability, not as quality: green is an arm that is fresh
 * enough to go tonight, red is one that has been leaned on. That is the same
 * direction as every other green and red on the desk - green is the good
 * outcome for the reader's question - even though the question here is "can he
 * pitch" rather than "is he good". The count is printed in every cell, so the
 * shade is always a second reading of a number that is already there. */
.ca-pc, .ca-pc-total { transition: none; }
/* A zero is a count, not a disabled control: it recedes by weight, and stays
   readable - the disabled grey measured 2.3:1. */
.ca-pc.p-zero  { color: var(--text-meta); font-weight: 500; }
.ca-pc.p-touch { background: var(--tint-positive); color: var(--metric-elite); }
.ca-pc.p-light { background: var(--tint-positive); color: var(--metric-good); }
.ca-pc.p-full  { background: var(--tint-caution); color: var(--metric-watch); }
.ca-pc.p-heavy { background: var(--tint-negative); color: var(--metric-poor); }

/* The two summary columns take the same ramp on thresholds scaled to the days
   they cover, and keep their heavier frame so the eye still reads them as
   totals rather than as two more days. */
.ca-pc-total.p-zero  { color: var(--text-meta); font-weight: 500; }
.ca-pc-total.p-full  { color: var(--metric-watch); }
.ca-pc-total.p-heavy { color: var(--metric-poor); }
.ca-pc-total { font-family: var(--font-display); font-weight: 800;
               color: var(--text-primary); background: var(--surface-field);
               font-variant-numeric: tabular-nums; }
.ca-bullpen__crest { width: 22px; height: 22px; object-fit: contain; margin-right: 6px; }
.ca-bullpen-panel > h3 { display: flex; align-items: center; }

/* --- conditions in the banner ------------------------------------------- */
.ca-wx-fact { display: inline-flex; align-items: center; gap: 6px; }
.ca-wx-glyph--sm { width: 18px; height: 18px; color: var(--text-accent); }

/* ---------------------------------------------------------------------------
 * CARD HEIGHT: ONE LONG NAME MUST NOT RAISE THE WHOLE ROW
 *
 * Grid rows stretch to their tallest member, so "Los Angeles Dodgers" wrapping
 * to a second line, or a two-line pitcher name, pushed every card in the row
 * past the 350px ceiling the style lock fixes - and the extra height was blank
 * space on the other eleven cards. Both names clamp to two lines and then
 * ellipsis, which holds the card inside its band without hiding a club: the
 * crest is beside the name and the full text stays in the title attribute.
 * ------------------------------------------------------------------------ */
.ca-matchup-card__name,
.ca-matchup-card__arm-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  min-width: 0;
}

/* A pitcher's name is short enough to sit on one line at this size; when one
   does not, ellipsis costs a surname and saves seventeen points of height on
   every card in the row. The club name keeps its two lines - truncating
   "Los Angeles Do..." is not a trade worth making. */
.ca-matchup-card__arm-name {
  -webkit-line-clamp: 1;
  line-clamp: 1;
}

/* ---------------------------------------------------------------------------
 * CARD HEIGHT BUDGET
 *
 * The style lock caps the collapsed card at 350px and the card had reached
 * 348 - inside the band, but with no room for the font-metric difference
 * between this machine and CI, which is the exact one-pixel gap that failed a
 * deploy once already. The two points below are whitespace, not content: the
 * stack gap comes down a point, and the collapsed detail drawer stops
 * reserving a gap while it is empty. That is about fourteen points of
 * headroom, and the card reads no tighter for it.
 * ------------------------------------------------------------------------ */
.ca-matchup-card { gap: 4px; }

/* The drawer carries the `hidden` attribute when collapsed, but a display rule
   on the class overrode the UA's `display:none`, so a hidden element was still
   a flex item claiming a gap. It is now actually hidden when it says it is. */
.ca-matchup-card__expand[hidden] { display: none; }

/* The venue strip runs one line of 14px display type but inherited the page's
   body line-height, so it reserved 36 points for an 18-point line. Setting the
   leading it actually needs returns the last of the headroom. */
.ca-matchup-card__venue { line-height: 1.3; }
.ca-matchup-card__venue .ca-status-chip { line-height: 1.2; }

/* ---------------------------------------------------------------------------
 * TABLE COLUMN WIDTHS
 *
 * `width: 100%` on a table with one long text column and several short numeric
 * ones gives every spare pixel to the text column, so a nine-row batting order
 * sat with its name column 700px wide and its four rate columns crowded into
 * the right margin - four numbers a reader is asked to compare down the page,
 * placed as far from each other as the panel allows.
 *
 * The numeric columns take a fixed share and the name column absorbs what is
 * left, which is the arrangement the eye needs: the figures line up in narrow
 * tracks close enough to scan across as well as down.
 * ------------------------------------------------------------------------ */
.ca-lineup-table th.num,
.ca-lineup-table td.num { width: 4.5rem; }

.ca-lineup-table thead th:first-child,
.ca-lineup-table tbody td:first-child { width: 2.5rem; }

/* The batter's name is the one column that should take the slack. */
.ca-lineup-table .ca-lineup-name { width: auto; }

/* The pitch-count matrix is the exception: it is all numbers, so its day
   columns stay on the narrower track they set for themselves. */
.ca-pc-table th.num,
.ca-pc-table td.num { width: 3.25rem; }

/* Splits carry ten columns in a panel half the page wide; each needs less. */
.ca-split-table th.num,
.ca-split-table td.num { width: 3.5rem; }

/* The split label is shorthand and must stay on its line; if a longer label
   ever lands here the table scrolls rather than growing three rows tall. */
.ca-split-table tbody td:first-child,
.ca-split-table thead th:first-child { white-space: nowrap; width: 5rem; }

/* ===========================================================================
 * THE DESK SYMBOL SET
 * ---------------------------------------------------------------------------
 * Glyphs from Lucide (ISC), vendored in dashboard/chase_icons.js. One weight,
 * one size relationship to the type beside them, on currentColor - so a symbol
 * inherits the colour of its row and a grade class tints the glyph with its
 * number rather than leaving a grey mark next to a green figure.
 *
 * They sit beside a label, never instead of one, so nothing here needs to
 * carry a tooltip or an aria-label; each is aria-hidden and the word next to
 * it is what a screen reader announces.
 * ======================================================================== */
.ca-ico {
  flex: 0 0 auto;
  vertical-align: -0.15em;
  /* Slightly lighter than the type it sits next to: at 16px a 2px stroke reads
     heavier than 600-weight text and the symbol starts shouting over the word. */
  stroke-width: 1.75;
}

/* Weather is the one symbol on the card that carries information the text also
   carries, so it takes the accent and becomes the thing the eye lands on. */
.ca-ico--wx { color: var(--text-accent); stroke-width: 2; }

.ca-matchup-card__ico {
  margin-right: 5px;
  color: var(--text-muted);
}

/* The venue glyph leads the card's top edge, so it takes the venue's own
   weight rather than the muted caption grey. */
.ca-matchup-card__ico--venue { color: var(--text-accent); margin-right: 6px; }

.ca-matchup-card__fact span { display: inline-flex; align-items: center; }
.ca-matchup-card__kick { display: inline-flex; align-items: center; }
.ca-matchup-card__venue { align-items: center; }

/* Inside a chip the glyph is small and takes the chip's colour. */
.ca-matchup-card__venue-tag {
  display: inline-flex;
  align-items: center;
  gap: 3px;
}
.ca-matchup-card__venue-tag .ca-ico { color: inherit; }

/* --- Reliever roles ------------------------------------------------------
 * Read off the season each arm has already had - saves, holds, games finished
 * - so the tag is a record, not a depth chart somebody typed. An arm whose
 * usage has no shape carries no tag at all: "Middle" on every row would be a
 * column of noise.
 *
 * The closer takes the accent because he is the one name a reader is looking
 * for; the rest are quiet labels. */
.ca-role {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--surface-elevated);
  color: var(--text-muted);
  border: 1px solid var(--border-subtle);
}

.ca-role[data-role="closer"] {
  background: var(--accent-soft);
  color: var(--accent-text);
  border-color: var(--accent-strong);
}

.ca-role[data-role="set-up"] { color: var(--text-secondary); }

/* --- An axis that answers for itself ------------------------------------ */
.ca-radar__axis { cursor: help; }
.ca-radar__hit { fill: transparent; }

.ca-radar__axis:focus { outline: none; }
.ca-radar__axis:focus-visible .ca-radar__hit {
  stroke: var(--accent);
  stroke-width: 2;
  fill: var(--accent-soft);
}

/* The axis being read lights up across the whole web - its name, its spoke and
   both clubs' points on it - so the card's numbers can be found on the shape. */
.ca-radar__axis.is-active .ca-radar__label { fill: var(--text-accent); }
.ca-radar__spoke.is-active { stroke: var(--text-muted); stroke-width: 1.5; }
.ca-radar__dot.is-active { stroke: var(--text-primary); stroke-width: 2; }

/* --- The axis readout ----------------------------------------------------
 * HTML at reading size on an opaque card. The first readout was SVG inside the
 * web: it scaled with the box to about 10px, sat on a 60% black the spokes
 * showed through, and covered the axis names beside it. wireRadarReadout()
 * places it outside the name it belongs to. */
.ca-radar { position: relative; }

.ca-radar__card {
  position: absolute;
  z-index: 5;
  width: min(340px, calc(100vw - 48px));
  padding: var(--space-3) var(--space-4) var(--space-2);
  background: var(--surface-raised);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--elevation-3);
  color: var(--text-secondary);
  text-align: left;
  pointer-events: none;
}
.ca-radar__card[hidden] { display: none; }

.ca-radar__card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--type-16);
  font-weight: 800;
  line-height: var(--leading-tight);
  color: var(--text-primary);
}

.ca-radar__card-head span {
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}

.ca-radar__card-means {
  margin: var(--space-1) 0 var(--space-2);
  font-size: var(--type-meta);
  line-height: 1.45;
  color: var(--text-secondary);
}

.ca-radar__card-row {
  display: grid;
  grid-template-columns: 3.6em auto minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--space-3);
  padding: var(--space-2) 0;
  border-top: 1px solid var(--border-subtle);
  font-size: var(--type-14);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.ca-radar__card-club {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-radar__card .ca-radar-key__swatch { width: 10px; height: 10px; border-radius: 2px; }

.ca-radar__card-row b {
  font-size: var(--type-16);
  font-weight: 800;
  color: var(--text-primary);
}

.ca-radar__card-row b.is-absent {
  font-size: var(--type-14);
  font-weight: 600;
  color: var(--text-muted);
}

/* --- Symbols on the section stack ---------------------------------------- */
.ca-detail-section__head h2 { display: flex; align-items: center; gap: 9px; }

.ca-detail-section__ico {
  flex: 0 0 auto;
  color: var(--text-accent);
  /* The heading is chrome-filled via background-clip, which would clip the
     glyph to the gradient too; the icon opts out and keeps its own colour. */
  -webkit-background-clip: initial;
  background-clip: initial;
}

.ca-detail-nav a { display: inline-flex; align-items: center; gap: 6px; }
.ca-detail-nav__ico { color: var(--text-muted); }
.ca-detail-nav a:hover .ca-detail-nav__ico,
.ca-detail-nav a:focus-visible .ca-detail-nav__ico { color: var(--text-accent); }

@media (max-width: 560px) {
  .ca-detail-section__head { align-items: flex-start; flex-direction: column; gap: 2px; }

  .ca-coverage-result { min-height: 62px; padding: 6px var(--space-2); }
  .ca-coverage-result strong { font-size: var(--type-16); }
  .ca-coverage-result span { font-size: var(--type-meta); line-height: 1.3; }

  .ca-coverage-track { grid-column: 1 / -1; grid-row: 2; gap: 2px; }

  .ca-radar-duo { gap: var(--space-5); margin-bottom: var(--space-3); }
  .ca-radar-duo > .ca-radar { flex-basis: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .ca-lineup-tab,
.ca-lineup-player { transition: none; }
}

/* What the row measures, under its name. A situation label like "Under
   Pressure" is a phrase, not a definition, and the definition costs one line. */
.ca-sit__means {
  display: block;
  font-size: var(--type-meta);
  color: var(--text-muted);
  line-height: 1.35;
}

.ca-sit-table th.num, .ca-sit-table td.num { width: 8rem; }
.ca-sit-table td:first-child { width: auto; }

/* The handedness column had no width of its own, so it split the leftover
   space with the batter's name - and because the two lineup panels hold names
   of different lengths, the same column landed at a different x in each. Two
   tables side by side that do not line up read as a rendering fault. A fixed,
   centred track fixes both: the letter sits under its own heading, and the
   column is in the same place in both panels. */
.ca-lineup-table th.ca-lineup-bats,
.ca-lineup-table td.ca-lineup-bats {
  width: 3.5rem;
  text-align: center;
}

/* The lineup heading is the crest and the split, nothing else. */
.ca-lineup-head { display: flex; align-items: center; gap: 8px; }
.ca-lineup-head__crest { width: 26px; height: 26px; object-fit: contain; flex: 0 0 auto; }

/* Run value needs room for a signed figure and its percentile chip. */
.ca-arsenal-table th.num, .ca-arsenal-table td.num { width: 6.5rem; }

/* Segmented rank meter: every analytical meter uses the same ten-cell visual
   language and the same red-yellow-green grade ramp. */
.ca-segment-meter {
  display: grid;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  gap: 3px;
  width: 100%;
  min-width: 0;
}

.ca-segment-meter.is-reverse { direction: rtl; }
.ca-segment-meter i {
  display: block;
  height: 10px;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 1px;
}
.ca-segment-meter i.is-on { background: var(--grade); border-color: var(--grade); }
.ca-pct-bar.ca-segment-meter { height: auto; background: transparent; overflow: visible; }

.ca-mirror__track { height: auto; border: 0; background: transparent; overflow: visible; }
.ca-mirror__track .ca-segment-meter { flex: 1 1 auto; }

/* ===========================================================================
 * BLACK PREMIUM SURFACE - 2026-09-15
 *
 * Owner direction: the desk read as immature because every object was boxed -
 * a bordered card holding a bordered group holding bordered tiles holding
 * bordered chips, on three blue-grey fills. Measured on the live slate, 37% of
 * sized elements drew a frame on three or more sides. This pass makes the desk
 * one black surface with objects embedded in it:
 *
 * 1. One slab per object. A card or a section is a single lifted black with a
 *    hairline of top light; nothing inside it draws a frame of its own.
 * 2. Separation by tone and space, never by outline. A panel inside a section
 *    is a well - one step darker - so it reads as carved in, not stacked on.
 * 3. Violet stays on navigation, links and focus. The 3px rail down every card
 *    and section is gone: fifteen rails on one page were segmentation, not
 *    brand. Club colour keeps its tab, because that answers "whose side".
 * ======================================================================== */

/* --- Slate card: one slab ------------------------------------------------ */
.ca-matchup-card {
  background: var(--surface-card);
  border: 1px solid var(--border-card);
  border-radius: var(--radius-md);
  box-shadow: var(--elevation-card);
}
.ca-matchup-card::before { content: none; }
.ca-matchup-card:hover,
.ca-matchup-card:focus-within {
  border-color: var(--border-hover);
  box-shadow: var(--elevation-card);
}

.ca-matchup-card__venue {
  background: none;
  border-bottom: 0;
}
.ca-matchup-card__head { border-bottom: 0; }
.ca-matchup-card__teams {
  background: none;
  border: 0;
}

/* Inner tiles step one tone up and draw no frame. The club's 3px colour tab is
   the one edge left on the card. */
.ca-matchup-card__club,
.ca-matchup-card__arm,
.ca-matchup-card__starter,
.ca-avail-row {
  background: var(--surface-field);
  border-top-color: transparent;
  border-right-color: transparent;
  border-bottom-color: transparent;
}
.ca-matchup-card__arm,
.ca-matchup-card__starter,
.ca-avail-row { border-left-color: transparent; }

.ca-matchup-card__arm .ca-matchup-card__shot,
.ca-matchup-card__shot--empty { border-color: transparent; }

/* A grade chip carries its grade as a tint of its own colour, not as a frame.
   The number and its label still sit inside it, so colour is never alone. */
.ca-matchup-card .ca-matchup-card__arm-era,
.ca-detail-page .ca-rank {
  border-color: transparent;
  background: color-mix(in srgb, currentColor 14%, transparent);
}

.ca-matchup-card__fact + .ca-matchup-card__fact,
.ca-matchup-card__broadcast { border-left-color: var(--border-card); }
.ca-matchup-card__actions { border-top: 0; }
.ca-matchup-card__expand {
  background: var(--surface-well);
  border-color: transparent;
}
.ca-matchup-card__expand-btn {
  background: var(--surface-field);
  border-color: transparent;
}
.ca-matchup-card__expand-btn:hover { background: var(--control-bg-hover); }
.ca-matchup-card__venue-tag {
  background: var(--surface-field);
  border-color: transparent;
}

.ca-status-chip,
.ca-status-chip.is-final,
.ca-status-chip.is-muted {
  background: var(--surface-field);
  border-color: transparent;
}
.ca-status-chip.is-live,
.ca-status-chip.is-watch,
.ca-status-chip.is-ok {
  border-color: transparent;
  background: color-mix(in srgb, currentColor 14%, transparent);
}

/* Small titles are type, not chrome. A silver gradient across a 14px venue
   name or a panel heading reads as effect; the page title keeps the metal. */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .ca-matchup-card__venue-name,
.ca-matchup-card__name,
.ca-starter-name,
.ca-lineup-panel > h3,
.ca-form-panel > h3,
.ca-arsenal-panel > h3,
.ca-lineup-board__head h3,
.ca-bullpen-panel > h3 {
    background: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: var(--text-primary);
  }
}

/* --- Page chrome: headings in open space, controls as tone -------------- */
.ca-public-page__head,
.ca-opening-desk__head,
.ca-opening-sport__head,
.ca-kickoff-window > header,
.ca-desk-toolbar { border-bottom-color: transparent; }

.ca-desk-dates button,
.ca-desk-dates__btn,
.ca-desk-dates__now,
.ca-desk-chip,
.ca-desk-view-toggle button,
.ca-public-page__links a,
.ca-embedded-slate-head a {
  background: var(--surface-field);
  border-color: transparent;
}
.ca-desk-dates button:hover,
.ca-desk-chip:hover,
.ca-public-page__links a:hover,
.ca-embedded-slate-head a:hover { background: var(--control-bg-hover); }
.ca-desk-chip.is-on {
  background: var(--control-bg-active);
  border-color: transparent;
  color: var(--text-accent);
}

.ca-loading-state,
.ca-error-state,
.ca-empty-state {
  background: var(--surface-card);
  border-color: var(--border-card);
}

/* --- Matchup analysis: sections are slabs, panels are wells ------------- */
.ca-detail-hero,
.ca-detail-section {
  background: var(--surface-card);
  border-color: var(--border-card);
  box-shadow: var(--elevation-card);
}
.ca-detail-hero::before,
.ca-detail-section::before { content: none; }
.ca-detail-hero__meta { border-bottom-color: var(--border-card); }

.ca-detail-nav {
  background: color-mix(in srgb, var(--surface-canvas) 90%, transparent);
  border-color: transparent;
  box-shadow: 0 1px 0 var(--border-card);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}

.ca-detail-fact,
.ca-detail-team-panel {
  background: var(--surface-well);
  border-color: transparent;
}

.ca-starter-panel,
.ca-lineup-panel,
.ca-form-panel,
.ca-arsenal-panel,
.ca-bullpen-panel,
.ca-mirror,
.ca-lineup-board {
  background: var(--surface-well);
  border-color: transparent;
  box-shadow: none;
}
.ca-mirror__head,
.ca-lineup-table thead th { background: none; }

.ca-starter-head,
.ca-mirror__head,
.ca-lineup-board__head,
.ca-lineup-table th { border-bottom-color: var(--border-card); }

.ca-starter-shot { border-color: transparent; }

.ca-recent,
.ca-wx-tile,
.ca-disclosure,
.ca-lineup-groups,
.ca-lineup-tabs,
.ca-lineup-player,
.ca-role,
.ca-flag,
.ca-stack {
  border-color: transparent;
  box-shadow: none;
}

/* Meters and tracks are fills. An outlined empty pip, repeated down a table,
   is exactly the line texture this pass removes. */
.ca-arsenal-bar,
.ca-usage__bar,
.ca-mirror__track,
.ca-usage__grid > i,
.ca-segment-meter i,
.ca-coverage-track i { border-color: transparent; }
.ca-usage__grid > i,
.ca-segment-meter i,
.ca-coverage-track i { background: var(--surface-raised); }

.ca-recent__game { border-color: var(--border-card); }

.ca-lineup-table tbody tr:nth-child(even),
.ca-arsenal-table tbody tr:nth-child(even) {
  background: color-mix(in srgb, var(--surface-field) 55%, transparent);
}

/* --- Phone: the kickoff line wraps instead of running into the weather ---
 * At 390px "Tuesday · 6:40 PM ET" overflowed its nowrap box and printed
 * straight into "91° · Clear" ("ET91°"). */

@media (max-width: 720px) {
  .ca-matchup-card__head {
    flex-wrap: wrap;
    row-gap: 2px;
    white-space: normal;
  }
}

/* ===========================================================================
 * NFL MATCHUP WORKBENCH - 2026-09-23
 * Directional team matchup first, observed player volume second, then the
 * existing scheme and availability evidence. Scoped to NFL so MLB/CFB keep
 * their established information rhythm.
 * ======================================================================== */
body[data-sport="nfl"] .ca-detail-nav {
  grid-template-columns: repeat(7, minmax(max-content, 1fr));
}

.ca-nfl-board-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
}

.ca-nfl-board-head span {
  color: var(--text-accent);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-nfl-board-head h3,
.ca-nfl-board-head p { margin: 0; }
.ca-nfl-board-head p { color: var(--text-muted); font-size: var(--type-meta); }

.ca-nfl-signal {
  display: grid;
  align-content: start;
  gap: 4px;
  min-width: 0;
  padding: var(--space-3);
  background: var(--surface-field);
  border-top: 2px solid var(--metric-good);
  border-radius: var(--radius-xs);
}

.ca-nfl-signal span { color: var(--text-accent); font-size: var(--type-caps); font-weight: 800; text-transform: uppercase; }
.ca-nfl-signal strong { color: var(--text-primary); font-size: var(--type-16); }
.ca-nfl-signal small { color: var(--text-muted); font-size: var(--type-meta); font-variant-numeric: tabular-nums; }

.ca-nfl-board-head { margin-top: var(--space-4); }

.ca-nfl-matchup-duo,
.ca-production-duo,
.ca-player-volume-duo {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-3);
}

.ca-production-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: var(--space-3);
  margin: var(--space-5) 0 var(--space-2);
}

.ca-production-head span {
  color: var(--text-muted);
  font-size: var(--type-meta);
}

.ca-production-head span {
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-production-head h3,
.ca-production-head p { margin: 0; }

.ca-production-head p { color: var(--text-secondary); font-size: var(--type-meta); }

@media (max-width: 680px) {
  .ca-bullpen-subhead { align-items: flex-start; flex-direction: column; gap: var(--space-1); }
  .ca-bullpen-splits,
  .ca-bullpen-panel { padding: var(--space-3); }
}

.ca-production-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.ca-production-stat {
  display: grid;
  align-content: start;
  gap: 3px;
  min-width: 0;
  padding: var(--space-3);
  border-right: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--border-subtle);
}

.ca-production-stat:nth-child(3n) { border-right: 0; }
.ca-production-stat:nth-last-child(-n+3) { border-bottom: 0; }

.ca-production-stat span {
  color: var(--text-muted);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-production-stat strong {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-20);
  font-variant-numeric: tabular-nums;
}

.ca-production-stat small { color: var(--text-secondary); font-size: var(--type-meta); }

.ca-ranking-detail {
  margin-top: var(--space-3);
  background: var(--surface-field);
  border-radius: var(--radius-sm);
}

.ca-ranking-detail > summary {
  min-height: var(--touch-min);
  padding: var(--space-3);
  cursor: pointer;
  color: var(--text-primary);
  font-weight: 800;
}

.ca-ranking-detail > summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.ca-ranking-detail__body {
  margin: 0;
  padding: 0 var(--space-3) var(--space-3);
}

.ca-ranking-detail__body { display: grid; gap: var(--space-3); }

@media (max-width: 980px) {
  .ca-nfl-matchup-duo,
  .ca-production-duo,
  .ca-player-volume-duo { grid-template-columns: 1fr; }
}

@media (max-width: 680px) {
  body[data-sport="nfl"] .ca-detail-hero__teams {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-3) var(--space-2);
    padding: var(--space-3) 0;
  }
  body[data-sport="nfl"] .ca-detail-center {
    grid-column: 1 / -1;
    grid-row: 1;
  }
  body[data-sport="nfl"] .ca-detail-team--away {
    grid-column: 1;
    grid-row: 2;
  }
  body[data-sport="nfl"] .ca-detail-team--home {
    grid-column: 2;
    grid-row: 2;
  }
  body[data-sport="nfl"] .ca-detail-team h1 { overflow-wrap: normal; word-break: normal; }
  .ca-production-head { align-items: start; flex-direction: column; }

  .ca-production-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ca-production-stat:nth-child(3n) { border-right: 1px solid var(--border-subtle); }
  .ca-production-stat:nth-child(2n) { border-right: 0; }
  .ca-production-stat:nth-last-child(-n+3) { border-bottom: 1px solid var(--border-subtle); }
  .ca-production-stat:nth-last-child(-n+2) { border-bottom: 0; }

  .ca-nfl-board-head { align-items: start; flex-direction: column; gap: 3px; }
}

@media (max-width: 390px) {
  .ca-detail-facts { grid-template-columns: 1fr; }
}

/* ===========================================================================
 * NFL DESK IN THE MLB TABLE LANGUAGE - 2026-09-26
 * The NFL matchup is built from the MLB components (.ca-starter-panel,
 * .ca-form-panel + .ca-split-table, .ca-arsenal-panel + .ca-arsenal-table).
 * These rules only add what the NFL data needs on top of them.
 * ======================================================================== */

/* A split under its sample floor: printed, never graded. Colour, not opacity -
   faded text failed the 2026-09-15 legibility scan. */
.ca-lineup-table tr.is-thin td,
.ca-lineup-table td.is-thin { color: var(--text-2); }

/* The carry count beside a YPC in Run Direction. */
.ca-arsenal-table td.num small {
  font-size: var(--type-meta);
  color: var(--text-2);
  margin-left: 4px;
  font-variant-numeric: tabular-nums;
}

/* Row labels in a possession panel name the club ("Chargers Offense"), which is
   longer than the MLB split labels the column was sized for. */
.ca-form-panel .ca-split-table tbody td:first-child,
.ca-form-panel .ca-split-table thead th:first-child { width: auto; min-width: 8.5rem; }

/* A second block inside a club-split panel gets the same air the starter
   panel gives its splits. */
.ca-form-panel .ca-split-block { margin-top: var(--space-4); }
.ca-form-panel .ca-split-block > .ca-lineup-context { margin: 0 0 var(--space-2); }

/* The opposing defense's rate for a look, beside the back's result in it.
   Context, not a grade: set off by a rule and kept in the secondary ink. */
.ca-split-table th.ca-opp-shows,
.ca-split-table td.ca-opp-shows {
  color: var(--text-2);
  border-left: 1px solid var(--border-subtle);
  padding-left: var(--space-3);
}

/* On a phone the matchup columns are the point of an NFL table, so they are
   what stays on screen: the usage squares give way to the percentage they
   already print, row labels wrap, and the result chips sit under their value. */
@media (max-width: 560px) {
  .ca-nfl-mix { min-width: 0; }
  .ca-nfl-mix th, .ca-nfl-mix td,
  .ca-nfl-split th, .ca-nfl-split td { padding-left: var(--space-1); padding-right: var(--space-1); }
  .ca-nfl-mix th, .ca-nfl-split th { white-space: normal; vertical-align: bottom; }
  .ca-nfl-mix .ca-usage__grid { display: none; }
  .ca-nfl-mix .ca-usage { min-width: 0; }
  .ca-nfl-mix th.num,
  .ca-nfl-mix td.num { width: auto; white-space: normal; }
  .ca-nfl-mix td.num .ca-rank { display: block; margin: 2px 0 0 auto; width: max-content; }
  .ca-nfl-mix td.ca-lineup-name { white-space: normal; }
  .ca-nfl-split tbody td:first-child { white-space: normal; min-width: 6.5rem; }
  .ca-nfl-split .ca-thin-tag { margin-left: 0; }
  .ca-form-panel .ca-split-table tbody td:first-child,
  .ca-form-panel .ca-split-table thead th:first-child { min-width: 0; white-space: normal; }
}

/* The section nav is one row on every sport. A fixed six-track grid wrapped
   MLB's nine anchors onto a second sticky row, costing ~50px of every screen;
   the row scrolls sideways only when it truly cannot fit. */
.ca-detail-nav {
  grid-auto-flow: column;
  grid-template-columns: none;
  grid-auto-columns: minmax(max-content, 1fr);
}

/* A family row inside a split table (Coverage, Pass Rush, Box, Shells). */
.ca-split-table tr.ca-split-group th {
  padding: var(--space-3) var(--space-3) var(--space-1);
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-2);
  background: transparent;
  border-bottom: 1px solid var(--border-default);
}
.ca-split-table tbody tr.ca-split-group:first-child th { padding-top: var(--space-2); }

/* The sample-floor tag. Grey alone was invisible: every ungraded number on the
   desk is already that grey, so a thin row now says so in words. */
.ca-thin-tag {
  display: inline-block;
  margin-left: 6px;
  padding: 0 5px;
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-2);
  border: 1px solid var(--border-default);
  border-radius: 3px;
  vertical-align: 1px;
  white-space: nowrap;
}

/* A carry count under the Run Direction floor, and a figure resting on it. */
.ca-arsenal-table td.num.is-low-cell:not(:has(small)),
.ca-arsenal-table td.num small.is-low {
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}

/* The NFL pairs carry wider tables than MLB's (a matchup column in every row),
   so they tighten before they stack, and stack before a table has to scroll:
   below 1380px each club gets the full width, which keeps the other club's
   result column on screen on a laptop or tablet. */
@media (max-width: 1400px) {
  .ca-nfl-duo .ca-lineup-table th,
  .ca-nfl-duo .ca-lineup-table td { padding-left: var(--space-2); padding-right: var(--space-2); }
  .ca-nfl-duo .ca-arsenal-table th.num,
  .ca-nfl-duo .ca-arsenal-table td.num { width: auto; }
}
@media (max-width: 1379px) {
  .ca-nfl-duo { grid-template-columns: minmax(0, 1fr); }
}

/* League marker beside a frequency: the club's league rank as a rank pill
   (.ca-rank, tier-coloured). Owner direction 2026-10-01 replaced the up/down
   arrows with it. */
.ca-freq-mark { margin-left: 4px; }
/* A marked figure keeps its marker on the same line (phones stack it instead). */
@media (min-width: 561px) {
  .ca-nfl-split td.num,
  .ca-nfl-mix td.num { white-space: nowrap; }
}
.ca-stat__label .ca-thin-tag { margin-left: 4px; }
@media (max-width: 560px) {
  /* In a phone mix table the marker sits under its percentage, like the rank chips. */
  .ca-nfl-mix td.num .ca-freq-mark { display: block; margin: 2px 0 0 auto; width: max-content; }
}

/* ===========================================================================
 * EVIDENCE WINDOW - restored 2026-09-27 (owner direction), without its
 * explanatory copy. Rules as they stood before 2026-09-26.
 * ======================================================================== */
/* --- Season scope control ------------------------------------------------ */
.ca-analysis-scope {
  display: grid;
  grid-template-columns: minmax(180px, auto) auto minmax(240px, 1fr);
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-board-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  box-shadow: inset 3px 0 0 var(--accent), inset 0 1px 0 var(--border-subtle);
}

.ca-analysis-scope > div:first-child { display: grid; gap: 2px; }
.ca-analysis-scope > div:first-child strong {
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--type-16);
}

.ca-analysis-scope__eyebrow {
  color: var(--text-accent);
  font-family: var(--font-sans);
  font-size: var(--type-caps);
  font-weight: 800;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
}

.ca-season-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px;
  background: var(--surface-field);
  border: 1px solid var(--border-subtle);
  border-radius: 0;
}

.ca-season-toggle__btn {
  appearance: none;
  min-height: var(--touch-min);
  border: 0;
  cursor: pointer;
  padding: 5px 12px;
  border-radius: 0;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: var(--type-meta);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.ca-season-toggle__btn:hover { color: var(--text-primary); }
.ca-season-toggle__btn.is-on {
  background: var(--accent-soft);
  color: var(--accent-text);
  box-shadow: inset 0 0 0 1px var(--accent-strong);
}
.ca-season-toggle__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.ca-season-toggle__note {
  grid-column: 1 / -1;
  margin: 0;
  font-size: var(--type-meta);
  color: var(--metric-watch);
}

@media (max-width: 980px) {
  .ca-analysis-scope { grid-template-columns: 1fr auto; }
}
@media (max-width: 560px) {
  .ca-analysis-scope { grid-template-columns: 1fr; padding: var(--space-3); }
  .ca-season-toggle { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  .ca-season-toggle__btn { transition: none; }
}
.ca-season-toggle { border-color: transparent; box-shadow: none; }

/* ===========================================================================
 * ONE TABLE GRID - 2026-09-27 (owner direction: page-wide congruency)
 * Every NFL table lays out on fixed tracks, so the same column sits at the
 * same place in every table down the page: the label column is one width,
 * the figures share what is left evenly. A split table and a mix table each
 * keep their own label width, applied to every table of that kind.
 * ======================================================================== */
@media (min-width: 561px) {
  .ca-nfl-split,
  .ca-nfl-mix { table-layout: fixed; width: 100%; }
  .ca-nfl-split thead th:first-child,
  .ca-nfl-split tbody td:first-child { width: 26%; }
  .ca-nfl-mix thead th:first-child,
  .ca-nfl-mix tbody td:first-child { width: 22%; }
  .ca-nfl-mix thead th:nth-child(2) { width: 24%; }
  .ca-nfl-mix .ca-usage { min-width: 0; }
  /* Figures share what the label leaves, evenly; nothing is ever clipped. */
  .ca-nfl-split th.num, .ca-nfl-split td.num,
  .ca-nfl-mix th.num, .ca-nfl-mix td.num { width: auto; }
  .ca-nfl-split thead th, .ca-nfl-mix thead th { white-space: normal; }
  .ca-nfl-split tbody td:first-child,
  .ca-nfl-mix tbody td:first-child { white-space: normal; overflow-wrap: anywhere; }
  /* Owner 2026-10-01: the figure columns read crowded. A wider gutter between
     them; the value and its rank pill keep one line where the column allows. */
}

/* The usage squares need room the percentage does not: they show where the
   usage column is wide (a full-width stacked table, or a wide desktop pair)
   and step aside elsewhere, leaving the percentage and its league marker. */
@media (min-width: 1380px) and (max-width: 1599px), (max-width: 899px) {
  .ca-nfl-mix .ca-usage__grid { display: none; }
}

/* A sample count beside a graded figure stays neutral; only the figure is graded. */
.ca-nfl-split td.num small,
.ca-nfl-mix td.num small { color: var(--text-2); margin-left: 4px; font-size: var(--type-meta); }

/* Every graded NFL number carries its rank pill. Where a column is too narrow
   for both on one line the pill wraps under the number instead of clipping. */
.ca-nfl-split td.num .ca-rank,
.ca-nfl-mix td.num .ca-rank { margin-left: 2px; padding: 0 3px; letter-spacing: -0.02em; }
.ca-nfl-split td.num,
.ca-nfl-mix td.num { white-space: normal; }
.ca-nfl-split th.num,
.ca-nfl-mix th.num { padding-left: var(--space-1); padding-right: var(--space-1); }
.ca-nfl-split td.num,
.ca-nfl-mix td.num { padding-left: var(--space-1); padding-right: var(--space-1); }
/* Side-by-side duos between 1380 and 1599px are the tightest the split tables
   get; the row label gives up a little so every rank pill stays on its line. */
@media (min-width: 1380px) and (max-width: 1599px) {
  .ca-nfl-split thead th:first-child,
  .ca-nfl-split tbody td:first-child { width: 18%; }
}
@media (max-width: 899px), (min-width: 1380px) and (max-width: 1439px) {
  .ca-nfl-split td.num .ca-rank,
  .ca-nfl-mix td.num .ca-rank { padding: 0 2px; margin-left: 1px; letter-spacing: -0.04em; }
  .ca-nfl-split td.num, .ca-nfl-mix td.num { padding-left: 2px; padding-right: 2px; }
}
@media (min-width: 561px) and (max-width: 899px), (min-width: 1380px) and (max-width: 1439px) {
  .ca-nfl-split thead th:first-child,
  .ca-nfl-split tbody td:first-child { width: 16%; }
}

/* ===========================================================================
 * NFL DESK: TABS AND ONE CLUB AT A TIME
 *
 * The desk reads one group of sections at a time. The tab bar and, where the
 * two clubs' panels stack, the club switch stay stuck under the header.
 * ======================================================================== */
.ca-nfl-bar {
  position: sticky;
  top: var(--shell-header-h);
  z-index: calc(var(--z-header) - 1);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin: var(--space-3) 0;
  background: color-mix(in srgb, var(--surface-canvas) 90%, transparent);
  box-shadow: 0 1px 0 var(--border-card);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.ca-nfl-bar .ca-detail-nav {
  position: static;
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  background: transparent;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  grid-template-columns: repeat(7, minmax(max-content, 1fr));
}
.ca-nfl-tabs a.is-on {
  color: var(--accent-text);
  background: var(--accent-soft);
  box-shadow: inset 0 -2px 0 var(--accent-strong);
}
.ca-nfl-tabs a.is-on .ca-detail-nav__ico { color: var(--text-accent); }

.ca-detail-stack[data-nfl-tab]:not([data-nfl-tab="all"]) > .ca-detail-section:not(.is-tab-on) { display: none; }
.ca-detail-stack[data-nfl-tab] > .ca-detail-section { scroll-margin-top: calc(var(--shell-header-h) + 72px); }

.ca-nfl-club {
  display: none;
  flex: 0 0 auto;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.ca-nfl-club__btn {
  appearance: none;
  min-height: var(--touch-min);
  border: 0;
  cursor: pointer;
  padding: 0 var(--space-3);
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-sans);
  font-size: var(--type-meta);
  font-weight: 700;
  white-space: nowrap;
}
.ca-nfl-club__btn + .ca-nfl-club__btn { border-left: 1px solid var(--border-default); }
.ca-nfl-club__btn:hover { color: var(--text-primary); }
.ca-nfl-club__btn.is-on {
  background: var(--accent-soft);
  color: var(--accent-text);
  box-shadow: inset 0 0 0 1px var(--accent-strong);
}
.ca-nfl-club__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ca-club-label-short { display: none; }

/* The two clubs sit side by side from 1380px; narrower, they stack, so the
   switch appears and the chosen club's panel is the one on screen. */
@media (max-width: 1379px) {
  .ca-nfl-club { display: inline-flex; }
  .ca-detail-stack[data-club="away"] .ca-detail-duo > :nth-child(2),
  .ca-detail-stack[data-club="home"] .ca-detail-duo > :nth-child(1) { display: none; }
}

@media (max-width: 899px) {
  .ca-nfl-bar {
    top: var(--shell-header-h-phone);
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-1);
    padding-bottom: var(--space-1);
  }
  .ca-nfl-bar .ca-detail-nav { display: flex; }
  .ca-nfl-bar .ca-detail-nav a { flex: 0 0 auto; }
  .ca-nfl-club { display: flex; }
  .ca-nfl-club__btn { flex: 1 1 0; }
  .ca-detail-stack[data-nfl-tab] > .ca-detail-section {
    scroll-margin-top: calc(var(--shell-header-h-phone) + 120px);
  }
}

/* Phone tables: the row label stays pinned while the figures scroll, and a
   rank pill sits under its figure. */
@media (max-width: 560px) {
  [data-sport="cfb"] .ca-nfl-club__btn { padding-inline: var(--space-2); }
  [data-sport="cfb"] .ca-club-label-full { display: none; }
  [data-sport="cfb"] .ca-club-label-short { display: inline; }
  .ca-nfl-split thead th:first-child,
  .ca-nfl-split tbody td:first-child,
  .ca-nfl-mix thead th:first-child,
  .ca-nfl-mix tbody td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--surface-board-raised);
    box-shadow: 1px 0 0 var(--border-card);
  }
  .ca-nfl-split tbody td:first-child { min-width: 6rem; max-width: 7.5rem; }
  .ca-nfl-split td.num .ca-rank,
  .ca-nfl-mix td.num .ca-rank { display: block; margin: 2px 0 0 auto; width: max-content; }
  .ca-nfl-split th.num, .ca-nfl-split td.num { min-width: 3.4rem; }
}

/* Phone: the matchup banner's facts read two across, and the evidence window
   is one row - its label beside the two windows. */
@media (max-width: 560px) {
  .ca-detail-page .ca-detail-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
  .ca-detail-page .ca-detail-fact { padding: var(--space-2); }
  .ca-analysis-scope {
    grid-template-columns: auto 1fr;
    gap: var(--space-2);
    padding: var(--space-2) var(--space-3);
  }
  .ca-analysis-scope > div:first-child strong { display: none; }
  .ca-analysis-scope .ca-season-toggle { justify-self: end; }
  .ca-analysis-scope .ca-season-toggle__btn { padding: 5px 10px; }
}

/* Ball carriers: the touchdown count needs little room; the graded figures
   take what it leaves so a percentile pill stays on its figure's line. */
@media (min-width: 561px) {
  .ca-nfl-carriers .ca-nfl-split thead th:last-child { width: 8%; }
}

/* ---------------------------------------------------------------------
 * MLB playoff depth (2026-09-28): Lineup Versus Pitch Mix, the reliever
 * table and the bullpen mix. Same table language as the lineup and pitch
 * mix tables; the wide ones scroll inside their panel on a phone.
 * ------------------------------------------------------------------ */
.ca-metric-switch { margin-bottom: var(--space-3); }
.ca-pitch-matchup + .ca-pitch-matchup,
.ca-relief-arms + .ca-relief-arms { margin-top: var(--space-4); }
.ca-pitch-matchup-table { min-width: 760px; }
.ca-pitch-matchup-table th.num small {
  display: block;
  color: var(--text-meta);
  font-size: var(--type-meta);
  font-weight: 700;
}
.ca-pitch-matchup-table td.num { white-space: nowrap; }
.ca-pitch-matchup-table td.ca-vs-line { color: var(--text-secondary); }
.ca-vs-none { color: var(--text-meta); }
.ca-relief-table { min-width: 1120px; }
.ca-relief-table td.num { white-space: nowrap; }
.ca-relief-table td.ca-lineup-name { white-space: nowrap; }
.ca-bullpen-split-table td.num { white-space: nowrap; }

.ca-bullpen-split-table { min-width: 760px; }

/* Batter versus pitcher (2026-09-28). */
.ca-bvp + .ca-bvp { margin-top: var(--space-4); }
.ca-bvp-table { min-width: 980px; }
.ca-bvp-table td.num { white-space: nowrap; }
.ca-bvp-table tr.ca-bvp-season td { color: var(--text-secondary); font-size: var(--type-meta); }
.ca-bvp-table tr.ca-bvp-season td.ca-lineup-name { padding-left: var(--space-4); }
.ca-bvp-never {
  margin: var(--space-2) 0 0;
  color: var(--text-secondary);
  font-size: var(--type-meta);
}
.ca-bvp-never strong { color: var(--text-primary); }

/* Offensive index splits under Club Batting Splits (2026-09-28). */
.ca-index-head {
  margin: var(--space-4) 0 var(--space-2);
  font-family: var(--font-display);
  font-size: var(--type-caps);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.ca-index-table td.num { white-space: nowrap; }

/* Player tables line up across both clubs (2026-09-28). With automatic
   layout each table sized its columns to its own names and values, so the
   away and home tables stacked one above the other landed at different x.
   Fixed layout with set tracks puts every column in the same place in both. */
.ca-pitch-matchup-table,
.ca-bvp-table,
.ca-relief-table { table-layout: fixed; }
.ca-pitch-matchup-table th:nth-child(1) { width: 2.5rem; }
.ca-pitch-matchup-table th:nth-child(2) { width: 13rem; }
.ca-pitch-matchup-table th:nth-child(3) { width: 3.5rem; }
.ca-pitch-matchup-table th.ca-pm-pitch { width: 7rem; }
.ca-bvp-table th:nth-child(1) { width: 13rem; }
.ca-bvp-table th:nth-child(2) { width: 3.5rem; }
.ca-bvp-table th:nth-child(n+3):nth-child(-n+8) { width: 3.5rem; }
.ca-bvp-table th:nth-child(n+9):nth-child(-n+12) { width: 5rem; }
.ca-bvp-table th:nth-child(13) { width: 7rem; }
.ca-relief-table th:nth-child(1) { width: 15rem; }
.ca-relief-table th:nth-child(2) { width: 2.5rem; }
.ca-relief-table th:nth-child(3) { width: 3rem; }
.ca-relief-table th:nth-child(4) { width: 4rem; }
.ca-pitch-matchup-table td.ca-lineup-name,
.ca-bvp-table td.ca-lineup-name,
.ca-relief-table td.ca-lineup-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The last column takes the slack, so the pitch tracks keep their width
   whether the starter throws four pitches or five. */
.ca-pitch-matchup-table th:last-child { width: auto; }
.ca-bvp-table th:last-child { width: auto; }

/* Runs versus starter hand and the head-to-head table (2026-09-28). */
.ca-runs-hand-controls { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.ca-runs-hand-table td.num,
.ca-h2h-table td.num { white-space: nowrap; }
.ca-h2h-table { margin-bottom: var(--space-3); }

/* Pitch Mix fits its panel (2026-09-28): the opposing club's name made the
   xwOBA header one long line and pushed Contact off the edge. Headers wrap,
   and the tracks are fixed so both starters' tables line up. */
.ca-arsenal-panel .ca-arsenal-table { table-layout: fixed; min-width: 0; }
.ca-arsenal-panel .ca-arsenal-table thead th { white-space: normal; line-height: 1.2; }
.ca-arsenal-panel .ca-arsenal-table th:nth-child(1) { width: auto; }
.ca-arsenal-panel .ca-arsenal-table th:nth-child(2) { width: 9.5rem; }
.ca-arsenal-panel .ca-arsenal-table th:nth-child(3) { width: 3.75rem; }
.ca-arsenal-panel .ca-arsenal-table th:nth-child(4) { width: 6.5rem; }
.ca-arsenal-panel .ca-arsenal-table th:nth-child(n+5) { width: 7rem; }
/* NFL mix tables (usage, results, "faced") are not pitch-mix tables: the
   fixed 3.75rem third column above crushed their last figure column and
   clipped its header (owner 2026-10-01: "too bunched up"). The label takes a
   fixed share and every figure column splits the rest evenly. */
.ca-arsenal-panel .ca-arsenal-table.ca-nfl-mix th:nth-child(1) { width: 34%; }
.ca-arsenal-panel .ca-arsenal-table.ca-nfl-mix th:nth-child(n+2) { width: auto; }

/* Matchup audit (2026-09-28). Every away | home pair of tables uses fixed
   layout, so the two clubs' columns sit at the same x. The first-column
   widths need the doubled class: `.ca-lineup-table thead th:first-child`
   (2.5rem, sized for the lineup slot) otherwise wins and squeezes a name
   column to 40px. A day off in the workload grid prints 0 on the dim
   p-zero shade rather than a dash. */
.ca-lineup-table.ca-bvp-table thead th:first-child { width: 13rem; }
.ca-lineup-table.ca-relief-table thead th:first-child { width: 17rem; }
.ca-lineup-table.ca-split-table { table-layout: fixed; }
.ca-lineup-table.ca-split-table thead th:first-child { width: 9.5rem; }
.ca-lineup-table.ca-runs-hand-table thead th:first-child { width: 12rem; }
.ca-bullpen-split-table { table-layout: fixed; min-width: 600px; }
.ca-bullpen-split-table thead th:first-child { width: 7.5rem; }
.ca-bullpen-split-table td.num { font-size: var(--type-meta); }
.ca-lineup-table.ca-pc-table { table-layout: fixed; }
.ca-lineup-table.ca-pc-table thead th:first-child { width: 15rem; }
.ca-pc-table td.ca-lineup-name { white-space: normal; }
/* Seven graded columns with rank pills do not fit half the page: the two
   bullpen unit tables stack, full width, with room for the Tonight tag. */
.ca-detail-duo.ca-bullpen-split-grid { grid-template-columns: minmax(0, 1fr); }
.ca-bullpen-split-table thead th:first-child { width: 11rem; }
.ca-bullpen-split-table td.num { font-size: inherit; }

/* Season Series (2026-09-28): the three series facts fill the row evenly,
   the head-to-head reads in two club panels, and the strip carries only the
   games themselves. */
.ca-detail-facts.ca-series-facts { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ca-series-duo { margin: var(--space-3) 0; }
.ca-lineup-table.ca-split-table.ca-h2h-table thead th:first-child { width: 14rem; }
.ca-series-strip__note {
  display: block;
  font-style: normal;
  font-size: var(--type-meta);
  color: var(--text-meta);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
@media (max-width: 720px) {
  .ca-detail-facts.ca-series-facts { grid-template-columns: minmax(0, 1fr); }
}

/* Pitch Mix carries eight columns (K% and the opponent's AVG added): the two
   starters' tables stack full width rather than cramming half the page. */
#arsenal .ca-detail-duo { grid-template-columns: minmax(0, 1fr); }

/* CFB desk (2026-09-29): row labels carry the school name ("New Mexico State
   Defense"), which needs a wider label track than the NFL's nicknames. */
.ca-cfb-panel .ca-lineup-table.ca-split-table thead th:first-child { width: 14rem; }
.ca-cfb-panel .ca-lineup-table td:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ca-cfb-panel td[colspan] { text-align: center; }
/* Values never wrap under their pill. */
.ca-cfb-panel td.num { white-space: nowrap; }

/* ====================================================================
 * CFB MATCHUP LEDGER - 2026-10-03 (owner: compare stats better and more
 * congruently). Every unit comparison is one four-column table: stat, the
 * offense (or away school) with its FBS rank, two bars drawn out from the
 * centre to each side's FBS place, the defense (or home school). The two
 * directions sit side by side with identical rows, so a stat reads across
 * both panels on one line. Bars take the grade colour of their figure.
 * ================================================================== */
/* Fixed columns that fit the panel: the generic lineup table's 560px floor
   would push a phone panel into a side scroll. */
.ca-cfb-ledger-table { table-layout: fixed; width: 100%; min-width: 0; }
.ca-cfb-ledger-table .ca-ledger-col-stat { width: 28%; }
.ca-cfb-ledger-table .ca-ledger-col-val { width: 24%; }
.ca-cfb-ledger-table .ca-ledger-col-bars { width: 24%; }
.ca-cfb-panel .ca-cfb-ledger-table thead th:first-child { width: auto; }
.ca-cfb-ledger-table thead th { vertical-align: bottom; }
.ca-cfb-ledger-table tbody tr,
.ca-cfb-ledger-table tbody tr:nth-child(even) { background: none; }
.ca-cfb-ledger-table tbody tr:not(.ca-ledger-group):hover { background: var(--surface-raised); }
.ca-cfb-ledger-table th.num.ca-ledger-right,
.ca-cfb-ledger-table td.num.ca-ledger-right { text-align: left; }
.ca-cfb-ledger-table td.num.ca-ledger-right .ca-rank { margin-left: 3px; }
.ca-ledger-school {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-primary);
}
.ca-cfb-ledger-table tr.ca-ledger-group th {
  padding-top: var(--space-4);
  padding-bottom: var(--space-1);
  border-bottom: 1px solid var(--border-subtle);
  background: none;
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-meta);
}
.ca-cfb-ledger-table tbody tr.ca-ledger-group:first-child th { padding-top: var(--space-2); }
.ca-cfb-ledger-table .ca-ledger-bars { padding-left: var(--space-2); padding-right: var(--space-2); }
.ca-ledger-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px;
  align-items: center;
}
.ca-ledger-bar {
  display: flex;
  height: 8px;
  overflow: hidden;
  background: var(--surface-well);
  border-color: transparent;
}
.ca-ledger-bar.is-left { justify-content: flex-end; border-radius: var(--radius-pill) 0 0 var(--radius-pill); }
.ca-ledger-bar.is-right { border-radius: 0 var(--radius-pill) var(--radius-pill) 0; }
.ca-ledger-bar i {
  display: block;
  height: 100%;
  background: var(--grade, var(--text-muted));
}
/* A school-against-school ledger (SP+, special teams) is one table, set at
   the width of one side of a pair so it reads like the panels around it. */
@media (min-width: 1380px) {
  .ca-cfb-h2h { width: calc(50% - var(--space-2)); margin-left: auto; margin-right: auto; }
}
@media (max-width: 720px) {
  .ca-cfb-ledger-table .ca-ledger-col-stat { width: 32%; }
  .ca-cfb-ledger-table .ca-ledger-col-val { width: 25%; }
  .ca-cfb-ledger-table .ca-ledger-col-bars { width: 18%; }
  .ca-cfb-panel .ca-cfb-ledger-table tbody td:first-child { white-space: normal; overflow: visible; }
  /* The panel title names both schools; the column heads keep the unit. */
  .ca-ledger-school { display: none; }
  .ca-cfb-ledger-table th,
  .ca-cfb-ledger-table td { padding-left: var(--space-1); padding-right: var(--space-1); }
  .ca-cfb-ledger-table td.num .ca-rank { display: block; width: max-content; margin: 2px 0 0 auto; }
  .ca-cfb-ledger-table td.num.ca-ledger-right .ca-rank { margin: 2px 0 0; }
}

/* ====================================================================
 * NFL TABLE SPACING + EVEN PILLS - 2026-10-01 (owner: "too bunched up",
 * "not everything is represented the same"). Last in the file so it wins
 * over the tighter 2026-09-27 gutters. A table where any pill would wrap
 * gets .is-stacked (nflEvenPills) and every pill in it sits under its figure.
 * ======================================================================== */
@media (min-width: 561px) {
  .ca-nfl-mix th.num, .ca-nfl-mix td.num { padding-left: var(--space-5); padding-right: var(--space-2); }
  .ca-nfl-split th.num, .ca-nfl-split td.num { padding-left: var(--space-3); padding-right: var(--space-2); }
  .ca-nfl-split td.num .ca-rank, .ca-nfl-mix td.num .ca-rank { margin-left: var(--space-1); }
}
.ca-nfl-split.is-stacked td.num .ca-rank,
.ca-nfl-mix.is-stacked td.num .ca-rank { display: block; margin: 2px 0 0 auto; width: max-content; }
/* Receiver stat switch (2026-10-01): one look matrix per stat. */
.ca-rec-metric__bar { display: flex; flex-wrap: wrap; gap: var(--space-1); margin: 0 0 var(--space-2); }
.ca-rec-metric__btn {
  min-height: 36px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-xs);
  background: transparent;
  color: var(--text-secondary);
  font: inherit;
  font-size: var(--type-meta);
  font-weight: 700;
  cursor: pointer;
}
.ca-rec-metric__btn.is-on { color: var(--text-primary); border-color: var(--accent-strong); background: var(--accent-soft); }
.ca-rec-metric__btn:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 2px; }
/* NFL game log (2026-10-01): a margin strip above a game-by-game table.
   The strip's bars take the grade ramp (up = good, down = poor); the
   outlined bar is the noise-adjusted margin beside the final one. */
#game-log .ca-detail-duo { grid-template-columns: minmax(0, 1fr); }
.ca-log-strip { margin: 0 0 var(--space-3); }
.ca-log-strip svg { display: block; max-width: 100%; height: auto; overflow: visible; }
.ca-log-strip line { stroke: var(--border-card); stroke-width: 1; }
.ca-log-strip text { fill: var(--text-meta); font-size: var(--type-meta); text-anchor: middle; }
.ca-log-bar.is-up { fill: var(--metric-good); }
.ca-log-bar.is-down { fill: var(--metric-poor); }
.ca-log-bar--adj { fill: transparent !important; stroke-width: 1.5; }
.ca-log-bar--adj.is-up { stroke: var(--metric-good); }
.ca-log-bar--adj.is-down { stroke: var(--metric-poor); }
.ca-log-strip figcaption {
  display: flex; align-items: center; gap: var(--space-2);
  margin-top: var(--space-1); color: var(--text-meta); font-size: var(--type-meta);
}
.ca-log-key { display: inline-block; width: 10px; height: 10px; border-radius: 2px; background: var(--text-secondary); }
.ca-log-key--adj { background: transparent; border: 1.5px solid var(--text-secondary); margin-left: var(--space-2); }
.ca-log-panel .ca-lineup-table.ca-split-table thead th:first-child { width: 8rem; }
.ca-log-panel td.num { white-space: nowrap; }
.ca-log-result b { font-weight: 800; margin-right: 2px; }
.ca-log-result[data-result="W"] b { color: var(--metric-good); }
.ca-log-result[data-result="L"] b { color: var(--metric-poor); }
.ca-log-season td { border-top: 1px solid var(--border-card); font-weight: 700; }
.ca-log-strip text.ca-log-figure { fill: var(--text-secondary); font-weight: 700; }

/* CFB QB and ball-carrier rows: the volume behind the line, under the name. */
.ca-qb-volume { display: block; color: var(--text-muted); font-size: var(--type-meta); font-variant-numeric: tabular-nums; }

/* ====================================================================
 * CFB PLAYER HEADSHOTS - 2026-10-03. Quarterback and ball-carrier rows
 * lead with the player's ESPN portrait (initials where ESPN has none).
 * ================================================================== */
.ca-cfb-player {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}
.ca-cfb-player__shot {
  flex: 0 0 auto;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  object-fit: cover;
  object-position: center top;
}
.ca-cfb-player__shot.is-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 800;
  color: var(--text-secondary);
}
.ca-cfb-player__id {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ca-cfb-panel .ca-lineup-table.ca-split-table thead th:first-child { width: 16.5rem; }
@media (max-width: 720px) {
  .ca-cfb-player__shot { width: 32px; height: 32px; }
}

/* CFB card quarterbacks (2026-10-03): a portrait ESPN does not have reads as
   the player's initials in the same circle. */
.ca-matchup-card__shot--empty {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: var(--type-caps);
  font-weight: 800;
  color: var(--text-secondary);
}
