/* ============================================================
   Q92 SPORTS — Round 5C, "TURF BRAND"
   Round 5B "Stone" recoloured to the Q92 brand and rebuilt to be
   genuinely responsive. Same bones, same hierarchy, same
   components: ruled geometry, heavy condensed type set tight,
   square corners, no tilt, no glow, print grain, ~a third of the
   page carried by solid ink slabs.
   New ground: very light cool grey instead of warm stone.
   New identity: Q92 brand blue on light, cyan on dark.
   New signal: one crimson, reserved strictly for live.
   Built mobile-first-in-intent and verified at 390/768/1024/1440.
   No web fonts, no build step, no JavaScript.
   ============================================================ */

:root {
  /* ---- Ground: very light cool grey, six steps. Never pure white. ---- */
  --paper:    #fbfcfd;  /* lightest surface — cards, photo mats, hover  */
  --gray-100: #f7f8fa;  /* default panel fill                            */
  --gray-200: #f2f4f6;  /* the page ground                               */
  --gray-300: #e6eaee;  /* recessed / secondary fill                     */
  --gray-400: #ccd4db;  /* heavy rules, empty slots                      */
  --gray-500: #9aa5b0;  /* muted edges; 6.60:1 on ink, safe there        */

  /* ---- Ink: type and every line on the page. Neutral charcoal. ----
         Ratios measured against the ground (#f2f4f6).                 */
  --ink-900: #1c1f24;   /* 14.99:1 — the workhorse                      */
  --ink-800: #282d34;   /* 12.57:1                                      */
  --ink-700: #363c45;   /* 10.08:1 — body copy                          */
  --ink-500: #4a515b;   /*  7.27:1 — secondary copy                     */
  --ink-400: #5b636e;   /*  5.51:1 — labels                             */
  --ink-300: #667079;   /*  4.61:1 — the quietest type allowed          */

  /* ---- Brand: carries on LIGHT surfaces only. ----
         #0055a5 on ground 6.70:1 · white on #0055a5 7.39:1
         #0055a5 on ink 2.24:1 — never used there.                     */
  --brand:      #0055a5;
  --brand-deep: #003f7a;  /* 9.56:1 on ground — hover / pressed         */

  /* ---- Cyan: carries on DARK surfaces only. ----
         #4fc5d3 on ink 8.07:1 · ink on #4fc5d3 8.07:1
         #4fc5d3 on ground 1.86:1 — never a stroke or type on light.
         It may appear on light ONLY as a solid slab under ink type.   */
  --cyan:      #4fc5d3;
  --cyan-soft: #a5e4eb;   /* 11.72:1 on ink — quieter on-ink type       */

  /* ---- Live: the one signal colour. Live / in progress. Nothing
         else — not errors, not emphasis, not decoration. ----
         --live  fills (white on it 5.37:1) and live type on LIGHT
                 ground (4.87:1).
         --live-lit  live type and dots on CHARCOAL only (4.83:1).     */
  --live:     #d40f30;
  --live-lit: #ff4438;

  /* ---- Spacing, 4px rhythm ---- */
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 20px;  --sp-6: 24px;  --sp-8: 32px;  --sp-10: 40px;
  --sp-12: 48px; --sp-16: 64px; --sp-20: 80px;

  /* Minimum comfortable touch area. Every interactive element
     clears this at handset widths. */
  --tap: 44px;

  /* ---- Type ---- */
  --display: Impact, Haettenschweiler, "Franklin Gothic Bold", "Arial Narrow", "Helvetica Neue Condensed", sans-serif;
  --label: "Arial Narrow", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --body: "Helvetica Neue", Helvetica, Arial, sans-serif;

  --fs-mega: 108px;
  --fs-hero: 54px;
  --fs-head: 26px;
  --fs-sub: 19px;
  --fs-body: 15.5px;
  --fs-micro: 11px;

  --wrap: 1320px;
  --rail: 372px;
  --gap: var(--sp-8);   /* page gutter — narrows on small screens */

  /* ---- The ruled line. Dashed, drawn, never a clean CSS border.
         Ink on light grey, exactly as in 5B. ---- */
  --rule-h: repeating-linear-gradient(90deg,
      rgba(28,31,36,.62) 0 7px, rgba(28,31,36,.14) 7px 10px);
  --rule-v: repeating-linear-gradient(180deg,
      rgba(28,31,36,.50) 0 7px, rgba(28,31,36,.11) 7px 10px);
  --rule-faint: repeating-linear-gradient(90deg,
      rgba(28,31,36,.28) 0 7px, rgba(28,31,36,.07) 7px 10px);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--gray-200);
  color: var(--ink-700);
  font: 400 var(--fs-body)/1.6 var(--body);
  letter-spacing: .002em;
  text-rendering: optimizeLegibility;
}

/* Printed grit. On a light ground the grain must darken, not lighten. */
body::after {
  content: "";
  position: fixed; inset: 0;
  pointer-events: none;
  z-index: 60;
  opacity: .085;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/></filter><rect width='160' height='160' filter='url(%23n)'/></svg>");
}

a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { margin: 0; font-weight: 400; }
p { margin: 0; }
table { border-collapse: collapse; width: 100%; }

.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 var(--sp-8); }

/* ---------- shared line primitives ---------- */
.rule   { height: 1px; background: var(--rule-h); }
.rule-f { height: 1px; background: var(--rule-faint); }

/* Corner ticks — four short ruled strokes, now in ink */
.ticked { position: relative; }
.ticked::before, .ticked::after {
  content: ""; position: absolute; width: 14px; height: 14px;
  border-color: rgba(28,31,36,.55); border-style: solid; pointer-events: none;
}
.ticked::before { top: 0; left: 0; border-width: 1px 0 0 1px; }
.ticked::after  { bottom: 0; right: 0; border-width: 0 1px 1px 0; }

/* ---------- type primitives ---------- */
.label {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ink-400);
}

.disp {
  font-family: var(--display);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: -.012em;
  line-height: .88;
  color: var(--ink-900);
}

.num { font-variant-numeric: tabular-nums; }

/* Sport tag — the multi-sport marker. Neutral by design: sports are
   told apart by their name, not by a colour each. */
.sport {
  display: inline-block;
  padding: 4px 7px;
  border: 1px solid var(--gray-500);
  font: 700 10px/1 var(--label);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--ink-500);
  white-space: nowrap;
}
.sport.on-ink { border-color: rgba(251,252,253,.4); color: var(--gray-300); }

/* Same chip carrying a phrase rather than a sport — a full conference name
   ("Principals Athletic Conference (PAC-7)") is wider than a phone at this
   tracking, and nowrap made it push the page sideways. */
.sport--long {
  white-space: normal;
  text-align: right;
  line-height: 1.35;
  letter-spacing: .1em;
  max-width: 55%;
}

/* ============================================================
   THE WIRE — running score strip across the very top
   ============================================================ */
.wire {
  background: var(--ink-900);
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: stretch;
  overflow: hidden;
}
.wire-stamp {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 0 var(--sp-5);
  background: var(--brand);
  color: var(--paper);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .2em;
  text-transform: uppercase;
  white-space: nowrap;
}
.wire-stamp.is-quiet { background: var(--paper); color: var(--ink-900); }
.wire-window { overflow: hidden; position: relative; }
.wire-window::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, var(--ink-900), transparent 5%, transparent 94%, var(--ink-900));
}
.wire-track {
  display: flex; align-items: center; width: max-content;
  animation: wire 62s linear infinite;
}
.wire-track.is-static { animation: none; width: auto; }
@keyframes wire { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.tick {
  display: flex; align-items: baseline; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-5);
  font: 700 12px/1 var(--label);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--gray-500);
  white-space: nowrap;
  border-right: 1px solid rgba(251,252,253,.14);
}
.tick .t-team  { color: var(--gray-300); }
.tick .t-score { color: var(--paper); font-size: 14px; font-variant-numeric: tabular-nums; }
.tick .t-sport { color: var(--gray-500); letter-spacing: .16em; font-size: 10px; }
.tick .t-state { color: var(--gray-500); }
.tick.is-live .t-state { color: var(--live-lit); }
.tick:hover { background: rgba(251,252,253,.08); }

.dot {
  width: 7px; height: 7px; background: var(--live-lit);
  display: inline-block; align-self: center;
  animation: blip 1.8s ease-in-out infinite;
}
@keyframes blip { 0%,100% { opacity: 1; } 50% { opacity: .25; } }

/* ============================================================
   MASTHEAD — a solid ink bar. This is what carries the white logo.
   ============================================================ */
.masthead { background: var(--ink-900); }
.masthead-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-10);
  padding-top: var(--sp-6);
  padding-bottom: var(--sp-5);
}

.wordmark { display: flex; align-items: center; gap: 12px; }
.wordmark img { display: block; height: 46px; width: auto; }
.wordmark .tag {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--gray-500);
  border-left: 1px solid rgba(251,252,253,.3);
  padding-left: 12px;
  align-self: center;
}

.mainnav { display: flex; gap: var(--sp-6); }
.mainnav a {
  font: 700 13px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--gray-400);
  padding-bottom: 6px;
  border-bottom: 2px solid transparent;
}
.mainnav a:hover { color: var(--paper); }
.mainnav a.is-active { color: var(--cyan); border-bottom-color: var(--cyan); }

.onair {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  background: var(--brand); color: #fff;
  min-height: var(--tap);
  padding: 11px var(--sp-5);
  font: 700 12px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
}
.onair .dot { background: #fff; }
.onair:hover { background: #b80c29; }
.onair.is-quiet { background: var(--paper); color: var(--ink-900); }
.onair.is-quiet:hover { background: #fff; }

/* ---------- THE MEASURE STRIP — the signature line.
   Where Turf ran yard markers, Stone runs the sport index: the same
   full-width ruled bar with hash ticks, but it names the whole
   OHSAA calendar instead of a football field. ---------- */
.measure {
  position: relative;
  height: 36px;
  background: var(--ink-800);
  border-top: 1px solid rgba(251,252,253,.28);
  border-bottom: 3px solid var(--ink-900);
  overflow: hidden;
}
.measure .hashes {
  position: absolute; inset: 0;
  background: repeating-linear-gradient(90deg,
     rgba(251,252,253,.16) 0 1px, transparent 1px 26px);
}
.measure .marks {
  position: relative;
  display: flex; justify-content: space-between; align-items: center;
  height: 100%;
  max-width: var(--wrap); margin: 0 auto; padding: 0 var(--sp-8);
}
.measure .marks a {
  font: 700 11px/1 var(--label);
  letter-spacing: .2em; text-transform: uppercase;
  color: rgba(251,252,253,.62);
  padding: 4px 0;
  border-bottom: 2px solid transparent;
}
.measure .marks a:hover { color: var(--cyan-soft); }
.measure .marks a.in-season { color: #fff; border-bottom-color: var(--cyan); }

/* ============================================================
   PAGE GRID — a ruled line down the gutter
   ============================================================ */
.page {
  display: grid;
  grid-template-columns: 1fr 1px var(--rail);
  gap: var(--sp-10);
  padding-top: var(--sp-10);
  padding-bottom: var(--sp-20);
  align-items: start;
}
.gutter { align-self: stretch; background: var(--rule-v); min-height: 100%; }
.full { padding-top: var(--sp-10); }

/* ============================================================
   SECTION HEADS
   ============================================================ */
.sec-head {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-5);
  margin-bottom: var(--sp-6);
}
.sec-head h2 {
  font-family: var(--display);
  font-size: var(--fs-head);
  text-transform: uppercase;
  letter-spacing: -.005em;
  color: var(--ink-900);
}
.sec-head h2 em { font-style: normal; color: var(--ink-300); }
.sec-head .fill { height: 1px; background: var(--rule-faint); }
.sec-head .see-all {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-400);
}
.sec-head .see-all:hover { color: var(--brand); }

/* ============================================================
   PHOTO SLOTS
   Same contract as rounds 4 and 5: .slot.has-photo + --photo.
   New treatment: the night photographs are turned into warm
   monochrome prints and matted, so a dark image reads as a pasted
   print on a light sheet rather than a hole punched in the page.
   ============================================================ */
.mat {
  background: var(--paper);
  border: 1px solid var(--ink-900);
  padding: 7px;
}
.mat.tight { padding: 5px; }

.slot {
  position: relative;
  overflow: hidden;
  background: var(--gray-300);
  display: flex; align-items: flex-end;
}
/* Empty state: fine ruled registration hatch on stone. */
.slot::before {
  content: ""; position: absolute; inset: 0;
  background:
    repeating-linear-gradient(90deg, rgba(28,31,36,.13) 0 1px, transparent 1px 22px),
    repeating-linear-gradient(180deg, rgba(28,31,36,.09) 0 1px, transparent 1px 22px),
    linear-gradient(180deg, var(--gray-300), var(--gray-400));
}
.slot > * { position: relative; z-index: 2; }
.slot-tag {
  font: 700 10px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-500);
  padding: var(--sp-3);
}

/* Filled: the photo sits on ::before, softly desaturated, and comes up to
   full color when its card is hovered; the ramp lives on ::after so type
   stays legible in both states. (Replaces the old full-luminosity print.) */
a.mat { display: block; }
.slot.has-photo::before {
  content: "";
  background:
    var(--photo) center / cover no-repeat,
    linear-gradient(0deg, #55636f, #55636f);
  filter: saturate(.35);
  transition: filter .25s ease;
}
.slot.has-photo::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(251,252,253,.16) 0%, rgba(28,31,36,.05) 42%, rgba(28,31,36,.72) 100%);
}
/* Frames with no type over them keep a flatter, lighter ramp. */
.slot.has-photo.plain::after {
  background: linear-gradient(180deg, rgba(251,252,253,.18), rgba(28,31,36,.12));
}
.slot.has-photo:hover::before,
a:hover .slot.has-photo::before,
a:focus-visible .slot.has-photo::before {
  filter: saturate(1);
}
/* News cards hover as one unit: pointing at the image or the text brings the
   photo to full color AND turns the headline brand blue together. */
.photo-card .card-head a { transition: color .25s ease; }
.photo-card:hover .card-head a { color: var(--brand); }
.photo-card:hover .slot.has-photo::before { filter: saturate(1); }
.slot.has-photo .slot-tag { display: none; }

.r-4x3   { aspect-ratio: 4 / 3; }
.r-3x2   { aspect-ratio: 3 / 2; }
.r-1x1   { aspect-ratio: 1 / 1; }
.r-21x9  { aspect-ratio: 21 / 9; }
.r-40x13 { aspect-ratio: 40 / 13; }
.r-16x9  { aspect-ratio: 16 / 9; }

.photo-credit {
  padding: 6px 2px 0;
  font: 400 10px/1.3 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-300);
}

/* ============================================================
   THE AREA SCOREBOARD — the primary object on the gameday page
   ============================================================ */
.areaboard { border: 1px solid var(--ink-900); background: var(--gray-100); }

.board-bar {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  background: var(--ink-900);
  color: var(--paper);
}
.board-bar h2 {
  font-family: var(--display);
  font-size: 30px; line-height: 1;
  text-transform: uppercase; letter-spacing: -.01em;
  color: var(--paper);
}
.board-bar .when {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--gray-400);
}
.board-count {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  background: var(--brand); color: #fff;
  padding: 7px var(--sp-3);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
}
.board-count .dot { background: #fff; }

.board-filters {
  display: flex; flex-wrap: wrap; gap: 0;
  border-bottom: 1px solid var(--ink-900);
  background: var(--gray-300);
}
.board-filters a {
  padding: 10px var(--sp-4);
  font: 700 11px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-500);
  border-right: 1px solid rgba(28,31,36,.2);
}
.board-filters a:hover { background: rgba(28,31,36,.07); color: var(--ink-900); }
.board-filters a.is-on { background: var(--paper); color: var(--ink-900); box-shadow: inset 0 -3px 0 var(--brand); }

/* Q92-9 amendment 2026-08-12: a compact, collapsed-by-default filter
   control for /news, so several filter dimensions don't dominate the page
   above the stories (R14c's visible/removable/shareable-URL/empty-state
   requirements are unchanged — this only changes the resting weight). */
.filter-disclosure {
  border: 1px solid var(--ink-900);
  background: var(--gray-300);
  margin-bottom: var(--sp-4);
}
.filter-disclosure summary {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 10px var(--sp-4);
  font: 700 11px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-900);
  cursor: pointer;
  list-style: none;
  min-height: var(--tap);
}
.filter-disclosure summary::-webkit-details-marker { display: none; }
.filter-disclosure summary::after { content: "+"; margin-left: auto; font-size: 14px; }
.filter-disclosure[open] summary { border-bottom: 1px solid rgba(28,31,36,.2); }
.filter-disclosure[open] summary::after { content: "\2212"; }
.filter-disclosure .board-filters { border-bottom: 0; }
.filter-disclosure .board-filters + .board-filters { border-top: 1px solid rgba(28,31,36,.2); }

.active-chips { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; margin-bottom: var(--sp-4); }
.active-chips a {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px var(--sp-3);
  font: 700 11px/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  background: var(--paper); color: var(--ink-900);
  border: 1px solid var(--ink-900);
}
.active-chips a:hover { background: var(--brand); color: #fff; border-color: var(--brand); }
.active-chips a.clear-all { border-color: transparent; background: transparent; text-decoration: underline; text-underline-offset: 3px; }

.board-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  background: rgba(28,31,36,.35);
}

/* one game */
.gamecard {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--gray-100);
  min-height: 148px;
}
a.gamecard:hover { background: var(--paper); }
.gc-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
}
.gc-state {
  font: 700 11px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-400);
  white-space: nowrap;
}
.gc-rows { display: flex; flex-direction: column; gap: 7px; }
.gc-row {
  display: grid; grid-template-columns: 3px 24px 1fr auto;
  align-items: center; gap: var(--sp-3);
  color: var(--ink-500);
}
.gc-row .bar { width: 3px; height: 17px; }
.gc-row .name {
  font: 700 15px/1 var(--label);
  letter-spacing: .05em; text-transform: uppercase;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gc-row .name small {
  display: block; margin-top: 3px;
  font: 400 10.5px/1 var(--label);
  letter-spacing: .12em; color: var(--ink-300);
}
.gc-row .val {
  font-family: var(--display); font-size: 26px; line-height: .9;
  font-variant-numeric: tabular-nums;
}
.gc-row.won { color: var(--ink-900); }
.gc-row .time {
  font: 700 13px/1 var(--label);
  letter-spacing: .12em; color: var(--ink-400);
}
.gc-foot {
  margin-top: auto;
  padding-top: var(--sp-3);
  border-top: 1px solid rgba(28,31,36,.16);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  font: 400 11px/1.3 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-400);
}
.gc-onq {
  font: 700 10px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-900);
  background: var(--cyan);
  padding: 4px 6px;
  white-space: nowrap;
}

/* LIVE = the card inverts to ink. On a stone board this is the
   loudest possible signal and needs no colour of its own. */
.gamecard.is-live {
  background: var(--ink-900);
  color: var(--gray-300);
  box-shadow: inset 4px 0 0 var(--live-lit);
}
a.gamecard.is-live:hover { background: #262a30; }
.gamecard.is-live .gc-state { color: var(--live-lit); display: inline-flex; align-items: center; gap: 7px; }
.gamecard.is-live .gc-row { color: var(--gray-400); }
.gamecard.is-live .gc-row.won { color: var(--paper); }
.gamecard.is-live .gc-row .name small { color: var(--gray-500); }
.gamecard.is-live .gc-foot { border-top-color: rgba(251,252,253,.2); color: var(--gray-500); }
.gamecard.is-live .gc-onq { color: var(--ink-900); }

/* upcoming reads quieter than final */
.gamecard.is-next { background: var(--gray-200); }
.gamecard.is-next .gc-row { color: var(--ink-500); }

/* a meet or a tournament, not a two-team game */
.gamecard.is-event { justify-content: center; }
.event-name {
  font-family: var(--display); font-size: 23px; line-height: .95;
  text-transform: uppercase; color: var(--ink-900);
}
.event-sub { font-size: 12.5px; line-height: 1.5; color: var(--ink-500); }

/* ============================================================
   LIVE ON Q92 — what the station is putting out right now
   ============================================================ */
.livebar {
  display: grid;
  grid-template-columns: 62px 1fr 1fr 1fr;
  border: 1px solid var(--ink-900);
  border-top: 0;
  background: var(--ink-900);
  color: var(--gray-300);
}
.livebar-spine {
  display: flex; align-items: center; justify-content: center;
  background: var(--brand);
  color: #fff;
  font: 700 12px/1 var(--label);
  letter-spacing: .3em; text-transform: uppercase;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  padding: var(--sp-5) 0;
}
.livebar.is-quiet .livebar-spine { background: var(--paper); color: var(--ink-900); }
.live-cell {
  padding: var(--sp-5);
  border-left: 1px solid rgba(251,252,253,.22);
  display: flex; flex-direction: column; gap: var(--sp-3);
}
.live-cell:first-of-type { border-left: 0; }
.live-kind {
  display: flex; align-items: center; gap: var(--sp-2);
  font: 700 10px/1 var(--label);
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--live-lit);
}
.live-kind.is-plain { color: var(--gray-500); }
.live-title {
  font-family: var(--display);
  font-size: 25px; line-height: .95;
  text-transform: uppercase; letter-spacing: -.008em;
  color: var(--paper);
}
.live-sub { font-size: 13px; line-height: 1.5; color: var(--gray-500); }
.live-sub strong { color: var(--gray-300); font-weight: 700; }
.live-acts { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: auto; padding-top: var(--sp-2); }

/* ============================================================
   THE FEATURED GAME — deliberately subordinate to the area board
   ============================================================ */
.feature {
  display: grid;
  grid-template-columns: 340px 1fr;
  gap: var(--sp-5);
  border: 1px solid var(--ink-900);
  background: var(--paper);
  padding: var(--sp-5);
  align-items: stretch;
}
.feature .mat { border-color: var(--ink-900); }

/* Q92-9, 2026-08-12: the two-column .feature above reserves its first 340px
   track for a photo. A featured game with no photo has nothing to fill that
   track, so the scoreline is auto-placed into it and the school name collides
   with the score. --solo drops to a single full-width column for that case. */
.feature--solo { grid-template-columns: 1fr; }
.feature-body { display: flex; flex-direction: column; gap: var(--sp-4); }
.feature-tags { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
/* the anchor game runs the slab at reduced scale — it must never
   compete with the area board above it */
.feature .scoreline { grid-template-columns: 1fr 88px 1fr; }
.feature .sl-team { padding: var(--sp-4); gap: var(--sp-3); }
.feature .sl-score { font-size: 58px; line-height: .8; }
.feature .sl-school { font-size: 22px; }
.feature .sl-mascot, .feature .sl-rec { font-size: 10.5px; letter-spacing: .12em; }
.feature .sl-colorbar { width: 34px; height: 3px; }
.feature .sl-clock { font-size: 21px; }
.feature .sl-mid { padding: var(--sp-4) var(--sp-2); }
.feature .sl-period { font-size: 10px; letter-spacing: .12em; }
.feature .situation { font-size: 11px; letter-spacing: .1em; }

/* the compact scoreboard slab */
.board { border: 1px solid var(--ink-900); background: var(--gray-100); }
.board-strip {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-5);
  background: var(--ink-900);
  color: var(--paper);
}
.board-strip .where {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--gray-400);
}
.chip-live {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  background: var(--live); color: #fff;
  padding: 6px var(--sp-3);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
}
.chip-live .dot { background: #fff; }

/* ============================================================
   Q92-16 — mobile sticky condensed scoreboard. Fixed to the very top of
   the viewport once the real scoreboard (.gc-board .board) has scrolled
   fully out of view (R1, driven by IntersectionObserver on that element
   in games/show.blade.php — not a hardcoded scroll distance). Hidden
   above the handset breakpoint at EVERY scroll position via `display:
   none` below (R2), independent of the JS visibility state, so a stale
   `is-visible` class can never leak through on desktop. One line, ~44px
   (R3/open-question-2) — score only, no play/pause control
   (open-question-1). Reuses .dot/badge-live's live signal, never a
   second live affordance (prototype parity).
   ============================================================ */
.gc-sticky-score {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 55;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  min-height: var(--tap);
  background: var(--ink-900);
  color: var(--paper);
  border-bottom: 1px solid var(--live);
  opacity: 0;
  transform: translateY(-100%);
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
.gc-sticky-score.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.gc-sticky-score .gss-team {
  display: flex; align-items: center; gap: var(--sp-2);
  min-width: 0;
}
.gc-sticky-score .gss-code {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--gray-400);
}
.gc-sticky-score .gss-score {
  font-family: var(--display);
  font-size: 20px; line-height: 1;
  color: var(--paper);
}
.gc-sticky-score .gss-mid {
  display: flex; align-items: center; gap: var(--sp-2);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--gray-400);
  flex-shrink: 0;
}
.gc-sticky-score .gss-mid .dot { background: var(--live-lit); }

/* R2/AC3 — absent above the handset breakpoint at ANY scroll position,
   even if the JS ever set .is-visible (belt-and-suspenders: the JS also
   never observes/sets it above this width, but this rule doesn't depend
   on that). */
@media (min-width: 431px) {
  .gc-sticky-score { display: none !important; }
}

.scoreline { display: grid; grid-template-columns: 1fr 132px 1fr; align-items: stretch; }
.sl-team {
  display: grid; grid-template-columns: 1fr auto;
  align-items: center; gap: var(--sp-4);
  padding: var(--sp-5);
  /* Q92-9 amendment 2026-08-12: without this, a grid item's automatic
     minimum width is its content's min-content size — for a long school
     name (e.g. "Garfield Heights") that can exceed the 1fr track the
     scoreline gives it, and the whole scoreline overflows instead of
     wrapping. min-width: 0 lets the track actually shrink to what's
     available so the name wraps within it. */
  min-width: 0;
}
.sl-team.home { grid-template-columns: auto 1fr; text-align: right; }
.sl-team.home .sl-id { order: 2; }
.sl-team.home .sl-score { order: 1; }

.sl-id { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.sl-team.home .sl-id { flex-direction: row-reverse; }
/* min-content keeps the column at least as wide as the longest school name.
   Without it the team mark takes its width from this stack, which collapses to
   nothing and breaks the name a letter per line. */
.sl-id-stack { display: flex; flex-direction: column; gap: 5px; min-width: min-content; }
.sl-school {
  min-width: 0; overflow-wrap: normal; word-break: normal;
  font-family: var(--display);
  font-size: 34px; line-height: .86;
  text-transform: uppercase; letter-spacing: -.015em;
  color: var(--ink-900);
}
.sl-mascot {
  font: 700 11.5px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-400);
}
.sl-rec {
  font: 400 11.5px/1.3 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-300);
}
/* The result, on a finished board. The leading score's colour says nothing on
   its own — a team ahead at halftime is drawn exactly the same way. */
.sl-outcome {
  font: 700 11.5px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-900);
}

.sl-colorbar { height: 4px; width: 46px; margin-bottom: 4px; }
.sl-team.home .sl-colorbar { margin-left: auto; }

/* The homepage's featured card sits beside a photo, so each team has roughly
   140px for a mark, a display-size school name AND a score. Side by side those
   cannot all fit, and forcing it either breaks the name mid-word or runs it
   under the score. Here the mark sits above the name instead. The gamecast's
   own scoreline is full width and keeps the side-by-side arrangement. */
.feature-body .sl-id { flex-direction: column; align-items: flex-start; gap: var(--sp-2); }
.feature-body .sl-team.home .sl-id { flex-direction: column; align-items: flex-end; }
.feature-body .scoreline { grid-template-columns: 1fr 92px 1fr; }
.feature-body .sl-team { gap: var(--sp-2); padding: var(--sp-4); }
.feature-body .sl-school { font-size: 21px; }
.feature-body .sl-score { font-size: 42px; }
.feature-body .sl-colorbar { width: 34px; }
.feature-body .team-mark--md { width: 30px; height: 30px; }
.feature-body .sl-rec { display: none; }

.sl-score {
  font-family: var(--display);
  font-size: var(--fs-mega);
  line-height: .78;
  letter-spacing: -.03em;
  color: var(--ink-300);
  font-variant-numeric: tabular-nums;
  /* Q92-14 R17: .sl-team's "auto" score column has no min-content
     protection (unlike .sl-id-stack's min-width:min-content below), so at
     narrow widths the grid's negative-space distribution shrinks it below
     the score digits' own rendered width. The digits then overflow their
     box — on the home side that box sits BEFORE the name column, so the
     overflow paints directly over .sl-school. min-width:max-content pins
     the track to the score's real size so it never overlaps the name. */
  min-width: max-content;
}
.sl-score.is-leading { color: var(--ink-900); }

.sl-mid {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2);
  border-left: 1px solid rgba(28,31,36,.28);
  border-right: 1px solid rgba(28,31,36,.28);
  padding: var(--sp-5) var(--sp-3);
  background: var(--gray-200);
}
.sl-clock {
  font-family: var(--display);
  font-size: 28px; line-height: 1;
  color: var(--ink-900);
  font-variant-numeric: tabular-nums;
}
.sl-period {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-400);
  text-align: center;
}

/* the sport-specific situation strip (football down/distance,
   soccer shots, volleyball set score — one slot, many sports) */
.situation {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-3) var(--sp-5);
  border-top: 1px solid rgba(28,31,36,.28);
  background: var(--gray-300);
  font: 700 12px/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-700);
}
.situation .poss { display: inline-flex; align-items: center; gap: var(--sp-2); }
.situation .poss i { width: 0; height: 0; border: 5px solid transparent; border-left-color: var(--ink-900); }
.situation .down { color: var(--ink-400); }

.board-foot {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid rgba(28,31,36,.28);
}
.board-foot .crew { font: 400 12.5px/1.4 var(--body); color: var(--ink-400); }
.board-foot .crew strong { color: var(--ink-800); font-weight: 700; }

/* Audio-bar footprint, not a 16:9 stage — the YouTube stream is audio over a
   placeholder image, so it gets a short strip (YouTube's embed terms want the
   player visible, so it can't collapse to a bare audio control). */
.broadcast-video { position: relative; width: 100%; height: 200px; }

/* "QCast powered by SIL" attribution strip on the game board. Type-based
   mark until a real SIL logo asset lands — swap the <strong> for an <img>. */
/* Broadcast lower-third lockup: Q mark chip + wordmark + stacked credit,
   flanked by hairlines that fade out. Swap the .qcast-badge-q chip for a
   real SIL logo <img> when the asset exists. */
.qcast-badge {
  display: flex; align-items: center; gap: var(--sp-5);
  padding: var(--sp-3) var(--sp-6);
  background: linear-gradient(180deg, #23262c 0%, var(--ink-900) 100%);
  color: #fff;
}
.qcast-badge-rule { flex: 1; height: 1px; background: linear-gradient(90deg, transparent, rgba(255,255,255,.25)); }
.qcast-badge-rule:last-child { background: linear-gradient(90deg, rgba(255,255,255,.25), transparent); }
.qcast-badge-lockup { display: inline-flex; align-items: center; gap: var(--sp-3); }
.qcast-badge-name {
  font: 800 17px/1 var(--label); letter-spacing: .2em; text-transform: uppercase; color: #fff;
  padding: 6px 12px 6px 14px; /* extra left offsets the tracking on the last letter */
  background: rgba(0,85,165,.55); border-radius: 3px;
}
.qcast-badge-by { display: inline-flex; flex-direction: column; gap: 2px; text-decoration: none; }
.qcast-badge-by span { font: 700 8.5px/1 var(--label); letter-spacing: .22em; text-transform: uppercase; color: rgba(255,255,255,.45); }
.qcast-badge-by strong { font: 800 11px/1 var(--label); letter-spacing: .1em; text-transform: uppercase; color: var(--info); transition: color .2s ease; }
.qcast-badge-by:hover strong { color: #fff; }
@media (max-width: 700px) {
  .qcast-badge { padding: var(--sp-3) var(--sp-4); gap: var(--sp-3); }
  .qcast-badge-name { font-size: 14px; }
}

/* Standing AI disclosure, directly under the QCast lockup. Deliberately the
   quietest thing on the board: --ink-300 is the palette's floor for type, so
   it reads as a footnote rather than a warning, but it is always there. */
.ai-note {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  width: 100%;
  padding: var(--sp-2) var(--sp-6);
  border: 0; border-top: 1px solid var(--gray-300);
  background: var(--gray-100);
  font: 400 11.5px/1.45 var(--body); color: var(--ink-300);
  text-align: left; cursor: pointer;
}
.ai-note:hover { background: var(--gray-200); color: var(--ink-500); }
.ai-note:focus-visible { outline: 3px solid var(--brand); outline-offset: -3px; }
.ai-note-mark {
  flex: none;
  padding: 3px 4px 3px 5px; /* extra left offsets the tracking on the last letter */
  border: 1px solid var(--gray-400); border-radius: 2px;
  font: 800 8.5px/1 var(--label); letter-spacing: .16em; color: var(--ink-400);
}
.ai-note-cta { text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
@media (max-width: 700px) {
  .ai-note { padding: var(--sp-2) var(--sp-4); }
}

/* The explainer dialog behind .ai-note. Same overlay weight and z-index as the
   article lightbox so the two modals on the site behave alike. */
.ai-modal {
  position: fixed; inset: 0; z-index: 1000;
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-4);
  background: rgba(28,31,36,.82);
}
body.has-modal-open { overflow: hidden; }
.ai-modal-card {
  position: relative;
  width: min(560px, 100%); max-height: 88vh; overflow-y: auto;
  padding: var(--sp-8);
  background: var(--paper); border: 1px solid var(--ink-900);
}
.ai-modal-close {
  position: absolute; top: 0; right: 0;
  min-width: 44px; min-height: 44px;
  display: flex; align-items: center; justify-content: center;
  border: 0; background: none; cursor: pointer;
  font: 400 26px/1 var(--body); color: var(--ink-400);
}
.ai-modal-close:hover { color: var(--ink-900); }
.ai-modal-close:focus-visible { outline: 3px solid var(--brand); outline-offset: -3px; }
.ai-modal-eyebrow {
  display: block; margin-bottom: var(--sp-2);
  font: 700 9.5px/1 var(--label); letter-spacing: .22em; text-transform: uppercase; color: var(--ink-400);
}
.ai-modal-card h2 {
  margin: 0 0 var(--sp-4);
  font: 400 30px/1 var(--display); text-transform: uppercase; letter-spacing: -.005em; color: var(--ink-900);
}
.ai-modal-card p { margin: 0 0 var(--sp-4); font: 400 15px/1.6 var(--body); color: var(--ink-700); }
.ai-modal-badge {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  margin-bottom: var(--sp-4); padding: var(--sp-4);
  background: var(--gray-200); border-left: 3px solid var(--brand);
}
.ai-modal-badge p { margin: 0; font-size: 14px; }
.ai-modal-badge strong { color: var(--ink-900); }
.ai-modal-badge-mark {
  flex: none;
  padding: 5px 6px 5px 8px; /* extra left offsets the tracking on the last letter */
  background: var(--brand); color: #fff;
  font: 800 11px/1 var(--label); letter-spacing: .16em;
}
.ai-modal-card .ai-modal-warn {
  padding-left: var(--sp-4); border-left: 3px solid var(--live);
  font-size: 14px; color: var(--ink-500);
}
.ai-modal-link {
  display: inline-block;
  font: 700 11px/1 var(--label); letter-spacing: .12em; text-transform: uppercase;
  color: var(--brand); text-decoration: none; border-bottom: 1px solid currentColor; padding-bottom: 2px;
}
.ai-modal-link:hover { color: var(--brand-deep); }
@media (max-width: 700px) {
  .ai-modal-card { padding: var(--sp-6); }
  .ai-modal-card h2 { font-size: 24px; }
}
.broadcast-video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ============================================================
   BUTTONS
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 12px var(--sp-5);
  font: 700 12px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  border: 1px solid transparent;
  min-height: var(--tap);
  cursor: pointer;
}
.btn-ink   { background: var(--ink-900); color: var(--paper); }
.btn-ink:hover { background: var(--ink-700); }
.btn-line  { border-color: var(--ink-900); color: var(--ink-900); background: transparent; }
.btn-line:hover { background: rgba(28,31,36,.08); border-color: var(--brand); color: var(--brand); }
.btn-brand { background: var(--brand); color: #fff; }
.btn-brand:hover { background: var(--brand-deep); }
.btn-cyan  { background: var(--cyan); color: var(--ink-900); }
.btn-cyan:hover { background: var(--cyan-soft); }
.btn-paper { background: var(--paper); color: var(--ink-900); }
.btn-paper:hover { background: #fff; }
.btn-ghost { border-color: rgba(251,252,253,.5); color: var(--paper); background: transparent; }
.btn-ghost:hover { background: rgba(251,252,253,.12); }
.btn[disabled], .btn.is-disabled {
  border-color: rgba(28,31,36,.22); color: var(--ink-300);
  background: transparent; cursor: not-allowed;
}

/* ============================================================
   BADGES
   ============================================================ */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px var(--sp-2);
  font: 700 10px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  border: 1px solid var(--gray-500);
  color: var(--ink-500);
  white-space: nowrap;
}
.badge-final { color: var(--ink-500); }
.badge-live  { border-color: var(--live); color: var(--live); }
.badge-live .dot { background: var(--live); }          /* on light */
.panel-head .badge-live .dot { background: var(--live-lit); }  /* on ink */
.badge-air   { border-color: var(--brand); color: var(--brand); }
.badge-ink   { background: var(--ink-900); color: var(--paper); border-color: var(--ink-900); }
.badge-play  { border-color: var(--gray-500); color: var(--ink-500); }
/* The red-zone marker in the situation strip. Carries the same red as the
   field's own red-zone wash below it, so the badge and the shaded twenty yards
   read as one fact rather than two unrelated marks. */
.badge-redzone { border-color: var(--live); color: var(--live); background: rgba(212, 15, 48, .08); }
/* Scoring plays. Recoloured to the scoring team inside .play.is-score; this is
   the base so the badge is never left unstyled elsewhere. */
.badge-score { background: var(--brand); color: var(--paper); border-color: var(--brand); }

/* ============================================================
   STORIES
   ============================================================ */
.lead-story { display: block; }
/* The ratio is a floor, not a ceiling: the caption is bottom-aligned inside
   a clipped frame, so a tall caption would lose its headline off the top.
   min-height: fit-content lets the frame grow instead. */
.lead-story .slot { min-height: fit-content; aspect-ratio: 16 / 9; }
/* A lead story with no photo: the caption is set in the on-photo (white)
   palette, so the photoless ground goes to ink rather than showing white
   text on the light hatch. */
.lead-story .slot.plain { background: var(--ink-900); }
.lead-story .slot.plain::before {
  background:
    repeating-linear-gradient(90deg, rgba(255,255,255,.07) 0 1px, transparent 1px 22px),
    repeating-linear-gradient(180deg, rgba(255,255,255,.05) 0 1px, transparent 1px 22px),
    linear-gradient(180deg, rgba(28,31,36,0), rgba(0,0,0,.35));
}
.lead-cap { padding: var(--sp-5) var(--sp-6) var(--sp-6); width: 100%; }
.kicker {
  display: inline-block;
  background: var(--ink-900); color: var(--paper);
  padding: 5px var(--sp-2);
  font: 700 10px/1 var(--label);
  letter-spacing: .2em; text-transform: uppercase;
  margin-bottom: var(--sp-3);
}
.kicker.on-photo { background: var(--paper); color: var(--ink-900); }
.lead-head {
  font-family: var(--display);
  font-size: var(--fs-hero);
  line-height: .92;
  text-transform: uppercase;
  letter-spacing: -.018em;
  color: var(--ink-900);
  max-width: 22ch;
  text-wrap: balance;
}
.lead-head.on-photo { color: #fff; }
.lead-head a:hover { color: var(--brand); text-decoration: underline; text-underline-offset: 5px; }
.dek {
  margin-top: var(--sp-3);
  max-width: 62ch;
  color: var(--ink-700);
  font-size: 15.5px; line-height: 1.6;
  text-wrap: pretty;
}
.dek.on-photo { color: rgba(255,255,255,.9); }
/* Excerpt lengths vary wildly; the lead frame keeps its shape by showing
   only the opening lines. */
.lead-cap .dek { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; }
.byline {
  display: block;
  margin-top: var(--sp-3);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-400);
}
.byline.on-photo { color: rgba(255,255,255,.72); }

.story-list { display: flex; flex-direction: column; }
.story-row {
  display: grid;
  grid-template-columns: 208px 1fr;
  gap: var(--sp-5);
  padding: var(--sp-5) 0;
  border-top: 1px solid rgba(28,31,36,.2);
  align-items: start;
}
/* A story with no photograph keeps the same measure as one that has
   a photograph — the picture column becomes a ruled margin instead of
   collapsing, so the column keeps its rhythm. */
.story-row.no-photo > div { grid-column: 2; }
.story-row.no-photo::before {
  content: ""; grid-column: 1; align-self: stretch;
  width: 1px; margin-left: 104px; background: var(--rule-v);
}
.story-row:first-child { border-top: 0; padding-top: 0; }
.story-head {
  font-family: var(--display);
  font-size: 25px; line-height: 1;
  text-transform: uppercase; letter-spacing: -.008em;
  color: var(--ink-900);
  max-width: 30ch;
  text-wrap: balance;
}
.story-row:hover .story-head { color: var(--brand); text-decoration: underline; text-underline-offset: 4px; }
.story-row .kicker { margin-bottom: var(--sp-2); }
.story-row .byline { margin-top: var(--sp-2); }
.story-tags { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-2); flex-wrap: wrap; }

/* text-led card — the answer to "we have no photograph of volleyball" */
.card {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-5);
  background: var(--paper);
  border: 1px solid var(--ink-900);
}
a.card:hover { background: #fff; }
.card.is-quiet { background: var(--gray-100); border-color: rgba(28,31,36,.35); }
a.card:hover .card-head { color: var(--brand); }
.card-head {
  font-family: var(--display); font-size: 24px; line-height: .98;
  text-transform: uppercase; letter-spacing: -.008em; color: var(--ink-900);
  text-wrap: balance;
}
.card-dek { font-size: 13.5px; line-height: 1.55; color: var(--ink-500); }
.card-rule { height: 1px; background: var(--rule-faint); }

/* photo card, for the frames we actually have */
.photo-card { display: flex; flex-direction: column; }
.photo-card .card { border-top: 0; }

/* compact headline list */
.headlines { display: flex; flex-direction: column; }
.headlines a {
  display: grid; grid-template-columns: 108px 1fr;
  gap: var(--sp-4); align-items: baseline;
  padding: var(--sp-3) 0;
  border-top: 1px solid rgba(28,31,36,.16);
}
.headlines a:first-child { border-top: 0; }
.headlines a:hover .hl-text { color: var(--brand); text-decoration: underline; text-underline-offset: 3px; }
.hl-sport {
  font: 700 10px/1.4 var(--label);
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-300);
}
.hl-text { font-size: 15px; line-height: 1.45; color: var(--ink-800); }

/* pull quote — an off-day device */
.pullquote {
  border-top: 3px solid var(--ink-900);
  border-bottom: 1px solid rgba(28,31,36,.3);
  padding: var(--sp-5) 0;
  margin: var(--sp-6) 0;
}
.pullquote q {
  font-family: var(--display);
  font-size: 27px; line-height: 1.05;
  text-transform: uppercase; letter-spacing: -.01em;
  color: var(--ink-900);
  quotes: "\201C" "\201D";
}
.pullquote .attrib {
  margin-top: var(--sp-3);
  font: 700 11px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-400);
}

/* ============================================================
   PANELS — sidebar and gamecast modules
   ============================================================ */
.panel { border: 1px solid var(--ink-900); background: var(--gray-100); }
.panel + .panel { margin-top: var(--sp-8); }
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--ink-900);
  color: var(--paper);
}
.panel-head h3 {
  font-family: var(--display);
  font-size: 19px; line-height: 1;
  text-transform: uppercase; letter-spacing: -.005em;
  color: var(--paper);
}
.panel-head .see-all,
.panel-head .meta {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--gray-500);
}
.panel-head .see-all:hover { color: var(--paper); }
.panel-head-status { display: flex; align-items: center; gap: var(--sp-3); }
.panel-head .badge { border-color: rgba(251,252,253,.45); color: var(--gray-400); }
.panel-head .badge-live { border-color: var(--live-lit); color: var(--live-lit); }
.panel-body > * + * { border-top: 1px solid rgba(28,31,36,.16); }

/* Sponsor ad slots (<x-ad-slot/>). The creative fills the rail width. */
.panel + .ad-slot, .ad-slot + .panel { margin-top: var(--sp-8); }
.ad-slot-article-footer { margin-top: var(--sp-8); }

/* Pagination (partials/pagination). */
.pager { display: flex; flex-wrap: wrap; gap: 6px; }
.pager-link {
  display: inline-block;
  padding: 8px 12px;
  border: 1px solid var(--ink-900);
  background: var(--paper);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-500);
}
a.pager-link:hover { color: var(--brand); border-color: var(--brand); }
.pager-link.is-current { background: var(--ink-900); color: var(--paper); }
.pager-link.is-disabled, .pager-link.is-gap { opacity: .4; }
.pager-count {
  margin-top: var(--sp-3);
  font: 400 11.5px/1 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-500);
}
.ad-slot a, .ad-slot img { display: block; }
.ad-slot img { width: 100%; height: auto; }
.panel-note {
  padding: var(--sp-3) var(--sp-4);
  background: var(--gray-300);
  font: 400 11.5px/1.45 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-500);
}

/* ---------- team mark: crest/logo plate ----------
   One neutral treatment behind every school mark, crest or real
   logo alike, so near-white marks (Boardman, Buchtel, Chardon,
   Garfield Heights) and near-black marks (Perry, Buchtel's griffin)
   read the same against both light cards and the dark ticker/live
   surfaces. Never recolors the art — the plate and ring sit behind
   it. Fixed square box, object-fit: contain, never stretched. */
.team-mark {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--gray-300);
  box-shadow: inset 0 0 0 1px rgba(28,31,36,.18);
  overflow: hidden;
  align-self: center;
}
.team-mark img { width: 76%; height: 76%; object-fit: contain; display: block; }
.team-mark--xs { width: 20px; height: 20px; }
.team-mark--sm { width: 24px; height: 24px; }
.team-mark--md { width: 44px; height: 44px; box-shadow: inset 0 0 0 1.5px rgba(28,31,36,.18); }
.team-mark--lg { width: 64px; height: 64px; box-shadow: inset 0 0 0 2px rgba(28,31,36,.18); }
/* on dark ink surfaces (ticker, live gamecards) the ring reads
   against paper-on-ink instead of ink-on-paper — same plate color,
   a hair more contrast so the ring doesn't wash out */
.tick .team-mark, .gamecard.is-live .team-mark {
  box-shadow: inset 0 0 0 1px rgba(28,31,36,.28);
}

/* ---------- schedule row ---------- */
.sched {
  display: grid;
  grid-template-columns: 64px 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
}
a.sched:hover { background: var(--paper); }
.sched-when {
  display: flex; flex-direction: column; gap: 3px;
  font: 400 11px/1 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-300);
}
.sched-when b {
  font-family: var(--display);
  font-size: 15px; font-weight: 400; letter-spacing: .02em;
  color: var(--ink-900);
}
.matchup { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.side {
  display: flex; align-items: center; gap: var(--sp-2);
  font: 700 13.5px/1 var(--label);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-800);
}
.side .at { color: var(--ink-300); font-weight: 400; letter-spacing: .14em; }
.swatch { width: 3px; height: 13px; flex: 0 0 3px; }
.meta {
  font: 400 11.5px/1.3 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-400);
}

/* ---------- score row (compact recap) ---------- */
.score {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
}
a.score:hover { background: var(--paper); }
.score .meta .is-live { color: var(--live); font-weight: 700; }
.score-teams { display: flex; flex-direction: column; gap: 5px; }
.score-line {
  display: grid; grid-template-columns: 1fr auto;
  align-items: center; gap: var(--sp-3);
  color: var(--ink-400);
}
.score-line .team {
  display: flex; align-items: center; gap: var(--sp-2);
  font: 700 13.5px/1 var(--label);
  letter-spacing: .06em; text-transform: uppercase;
}
.score-line .val {
  font-family: var(--display); font-size: 19px; line-height: 1;
  font-variant-numeric: tabular-nums;
}
.score-line.won { color: var(--ink-900); }

/* ---------- standings ---------- */
.standings { font-variant-numeric: tabular-nums; }
.standings th {
  text-align: left;
  padding: var(--sp-2) var(--sp-4);
  font: 700 10px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-400);
  border-bottom: 1px solid rgba(28,31,36,.3);
}
.standings th.n, .standings td.n { text-align: right; width: 54px; white-space: nowrap; }
.standings td {
  padding: 9px var(--sp-4);
  border-bottom: 1px solid rgba(28,31,36,.12);
  font: 700 13.5px/1 var(--label);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-800);
}
.standings tr:last-child td { border-bottom: 0; }
.standings tbody tr:hover td { background: var(--paper); }
.team-cell { display: flex; align-items: center; gap: var(--sp-2); }

/* ---------- on air / broadcast card ---------- */
.onair-card > .mat { border: 0; padding: 0; }
.onair-body { padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3); }
.onair-title {
  font-family: var(--display); font-size: 22px; line-height: 1;
  text-transform: uppercase; color: var(--ink-900);
}
.onair-sub { font-size: 13.5px; line-height: 1.55; color: var(--ink-500); }
.stream-note {
  font: 400 11px/1.3 var(--label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-300);
}

/* broadcast slate row — used on the off-day page */
.slate {
  display: grid; grid-template-columns: 58px 1fr;
  gap: var(--sp-3); padding: var(--sp-3) var(--sp-4);
}
.slate .day {
  font-family: var(--display); font-size: 15px; line-height: 1.1;
  text-transform: uppercase; color: var(--ink-900);
}
.slate .what { font-size: 13px; line-height: 1.45; color: var(--ink-700); }
.slate .what b { display: block; font-weight: 700; color: var(--ink-900); }

/* ============================================================
   GAMECAST
   ============================================================ */
.gc-hero { position: relative; background: var(--ink-900); }
.gc-hero .slot { aspect-ratio: 40 / 13; }

/* Q92-13 R5: the no-photo default — sport-aware field markings over a
   time-of-day ground, built from the home school's colour. --home-color
   and --away-accent are set inline per game (App\Support\GamecastHero).
   The band-specific ::before rules below have higher specificity than the
   base `.slot::before` empty-state hatch pattern, so they replace it
   outright here — this is a designed background, not a placeholder. */
.hero-fallback {
  background: linear-gradient(90deg,
    var(--away-accent, var(--ink-900)) 0 50%,
    var(--home-color, var(--ink-900)) 50% 100%);
}
/* Time-of-day tint: photo heroes only (2026-08-20) — on the colour
   fallback it buried the team colours, and the 50/50 split IS the design
   there. Dialled back from the original strengths so the photo still
   reads. The colour fallback keeps a single faint top-light so the flat
   fills don't look untreated. */
.gc-hero .slot::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
}
.hero-fallback::before {
  background: linear-gradient(180deg, rgba(255,255,255,.08) 0%, rgba(255,255,255,0) 45%);
}
.has-photo.band-afternoon::before {
  background: linear-gradient(180deg, rgba(255,255,255,.10) 0%, rgba(255,255,255,0) 55%, rgba(28,31,36,.10) 100%);
}
.has-photo.band-dusk::before {
  background: linear-gradient(180deg, rgba(255,170,90,.14) 0%, rgba(120,60,110,.08) 55%, rgba(20,15,35,.18) 100%);
}
.has-photo.band-night::before {
  background: linear-gradient(180deg, rgba(10,20,60,.18) 0%, rgba(5,8,20,.28) 60%, rgba(0,0,0,.35) 100%);
}
.hero-fallback .hero-markings {
  position: absolute; inset: 0; z-index: 2;
  width: 100%; height: 100%;
  color: rgba(255,255,255,.16);
  mix-blend-mode: overlay;
}

/* Q92-13 amendments (2026-08-12, 2026-08-13): a photo earns its height; the
   generated field-mark placeholder does not — at the photo's aspect ratio
   it pushed the score and the rest of the page too far down for no gain.
   Shortens the placeholder only; .slot.has-photo keeps the 40/13 ratio set
   above. */
.gc-hero .slot.hero-fallback { aspect-ratio: 8 / 1; width: 100%; min-height: 190px; }

/* Q92-13 R4: legibility scrim — guarantees a dark backdrop behind the
   header text regardless of what's behind it (bright photo, dark photo,
   or the colour fallback in either state). Extends upward beyond the
   caption's own box so it reads as a proper scrim, not a strip glued to
   the text baseline. */
.gc-hero-cap { position: absolute; inset: auto 0 0 0; padding-bottom: var(--sp-8); }
.gc-hero-cap::before {
  content: ""; position: absolute; inset: -160px 0 0 0; z-index: 0;
  background: linear-gradient(180deg, rgba(28,31,36,0) 0%, rgba(28,31,36,.55) 55%, rgba(28,31,36,.92) 100%);
  pointer-events: none;
}
.gc-hero-cap .wrap { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: stretch; gap: var(--sp-3); }
.gc-hero-cap .gc-where { align-self: flex-end; }
.gc-title {
  font-family: var(--display);
  font-size: 62px; line-height: .88;
  text-transform: uppercase; letter-spacing: -.02em;
  color: #fff;
}
/* Matchup billing: each name stands on its own side of the split field —
   visitor outlined on the away half, host solid on the home half, the
   "AT" chip pinned to the seam. Mirrors the 50/50 ground behind it. */
.gc-title {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  column-gap: var(--sp-5);
  width: 100%;
}
.gc-title-away { justify-self: end; text-align: right; }
.gc-title-home { justify-self: start; }
.gc-title-away {
  color: transparent;
  -webkit-text-stroke: 2px rgba(255,255,255,.9);
}
@supports not (-webkit-text-stroke: 2px #fff) {
  .gc-title-away { color: rgba(255,255,255,.72); }
}
.gc-title-at {
  display: inline-block;
  font: 700 0.26em/1 var(--label);
  letter-spacing: .26em;
  color: rgba(255,255,255,.85);
  border: 1px solid rgba(255,255,255,.4);
  padding: 5px 7px 4px 9px; /* extra left absorbs the tracking on the final glyph */
  vertical-align: 0.42em;
  margin-right: 4px;
}
.gc-where {
  display: inline-flex; align-items: center; gap: 12px;
  font: 700 12px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: rgba(255,255,255,.85);
  white-space: nowrap;
  padding-bottom: 10px; /* optically aligns with the display face's baseline */
}
.gc-where::before {
  content: ""; width: 28px; height: 2px;
  background: rgba(255,255,255,.55);
}

.gc-board { margin-top: calc(var(--sp-8) * -1); position: relative; z-index: 3; }
.gc-board .board { background: var(--paper); }
.gc-board .sl-score { font-size: 128px; }
.gc-board .sl-school { font-size: 42px; }

.gc-grid {
  display: grid;
  grid-template-columns: 1fr 1px var(--rail);
  gap: var(--sp-10);
  padding-top: var(--sp-12);
  padding-bottom: var(--sp-20);
  align-items: start;
}

/* The gamecast's three groups — what is happening now, the game so far, and
   reference. The gap between groups has to read as bigger than the gap between
   two panels inside one, or the headings are decoration rather than structure. */
.gc-section + .gc-section { margin-top: var(--sp-12); }

/* ---------- play by play ---------- */
/* Q92-14 R7 correction: a fixed-height scroll region so the panel doesn't
   grow with the play count — newest eligible play stays pinned at the
   top, everything older scrolls beneath it. */
.panel-body.pbp {
  max-height: 520px;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.pbp .play {
  display: grid;
  grid-template-columns: 66px 1fr;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border-top: 1px solid rgba(28,31,36,.14);
}
.pbp .play:first-child { border-top: 0; }
.play-clock {
  font-family: var(--display); font-size: 17px; line-height: 1.2;
  color: var(--ink-400); font-variant-numeric: tabular-nums;
}
.play-head { display: block; font-size: 14.5px; line-height: 1.55; color: var(--ink-700); }
.play-sub {
  display: block;
  margin-top: 5px;
  font: 700 10.5px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-300);
}
/* A scoring play — the one thing a reader scanning a long list is looking for.
   The highlight itself is a fixed gold wash rather than the scoring team's
   colour, and that is deliberate: a school colour cannot be relied on to
   highlight anything. Hoover's primary is #000000, so colouring the row by team
   produced a black bar on a grey list — technically the right team, visually no
   highlight at all. Gold marks every score identically no matter who scored it,
   and the team is carried by the badge instead, where --score-team arrives with
   a pre-checked readable --score-team-ink so a black or a near-yellow school
   colour both hold up.

   Gold is scoped to this row and is not a brand token. The palette's one signal
   colour, crimson, stays reserved for live. */
.play.is-score {
  --score-wash: #fdf4d8;
  --score-rule: #c8971b;

  position: relative;
  background: var(--score-wash);
  border-left: 4px solid var(--score-rule);
}
.play.is-score .play-head { color: var(--ink-900); font-weight: 700; }
.play.is-score .play-clock { color: var(--ink-900); }
.play.is-score .play-desc {
  font: 400 20px/1.15 var(--display);
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--ink-900);
}
.play.is-score .badge-score {
  background: var(--score-team, var(--ink-900));
  color: var(--score-team-ink, var(--paper));
  border-color: var(--score-team, var(--ink-900));
}
/* A scoring play the extractor flagged as a touchdown but never attributed to a
   team. The row still highlights — a score is a score — but nothing claims who
   scored it or for how many, because nothing here knows. */
.play.is-score .badge-unattributed {
  background: none;
  border-color: var(--score-rule);
  color: var(--ink-700);
}
.play-score-after { color: var(--ink-500); }
.play.is-score .play-score-after { color: var(--ink-900); }

/* A snap the broadcast talked over, reconstructed from the down chain. Held
   back rather than highlighted — it is a gap being accounted for, not news —
   but marked clearly enough that nobody mistakes it for a failed extraction. */
.play.is-reconstructed {
  background: repeating-linear-gradient(
    135deg,
    transparent 0, transparent 6px,
    rgba(28,31,36,.04) 6px, rgba(28,31,36,.04) 12px
  );
  border-left: 4px solid var(--gray-400);
}
.play.is-reconstructed .play-desc { color: var(--ink-400); font-style: italic; }
.badge-reconstructed {
  border-color: var(--gray-500);
  color: var(--ink-400);
  cursor: help;
}

/* End of a quarter — the list runs newest-first, so the break is ruled
   above the last play of the quarter, where the next quarter begins. */
.play.ends-quarter { border-top: 2px solid var(--ink-900); }
.play-quarter-end {
  display: block; margin-bottom: var(--sp-2);
  font: 700 10px/1 var(--label);
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--ink-400);
}

/* ---------- line score ---------- */
.linescore { width: 100%; font-variant-numeric: tabular-nums; }
.linescore th {
  padding: var(--sp-2) var(--sp-3);
  text-align: center;
  font: 700 10px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-400);
  border-bottom: 1px solid rgba(28,31,36,.3);
}
.linescore td {
  padding: var(--sp-3);
  text-align: center;
  font-family: var(--display); font-size: 20px; line-height: 1;
  color: var(--ink-500);
  border-bottom: 1px solid rgba(28,31,36,.12);
}
.linescore tr:last-child td { border-bottom: 0; }
.linescore td.tm {
  text-align: left;
  font: 700 13.5px/1 var(--label);
  letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-900);
}
.linescore td.tot { color: var(--ink-900); }

/* Q92-14 R9: quarter recaps, shown by default (no longer a collapsed
   <details>). Direct children of .panel-body already get the standard
   ruled separator from `.panel-body > * + *`. */
.qtr-recap { padding: var(--sp-3) var(--sp-4); }
.qtr-recap .sched-when { margin-bottom: var(--sp-1); }
.qtr-recap .onair-sub { margin: 0; }

/* ---------- generic data table (drives, etc.) ---------- */
.tbl { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.tbl th {
  padding: var(--sp-2) var(--sp-3);
  text-align: center;
  font: 700 10px/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-400);
  border-bottom: 1px solid rgba(28,31,36,.3);
}
.tbl th.l { text-align: left; }
.tbl td {
  padding: var(--sp-3);
  text-align: center;
  font: 400 13.5px/1.3 var(--label);
  color: var(--ink-700);
  border-bottom: 1px solid rgba(28,31,36,.12);
}
.tbl td.l { text-align: left; }
.tbl tr:last-child td { border-bottom: 0; }

/* ---------- team stats ---------- */
.statline { padding: var(--sp-4); border-top: 1px solid rgba(28,31,36,.14); }
.statline:first-child { border-top: 0; }
.stat-top { display: grid; grid-template-columns: 70px 1fr 70px; align-items: baseline; gap: var(--sp-3); }
.stat-val {
  font-family: var(--display); font-size: 25px; line-height: 1;
  color: var(--ink-900); font-variant-numeric: tabular-nums;
}
.stat-val.b { text-align: right; }
.stat-label {
  text-align: center;
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--ink-400);
}
.stat-bar { display: flex; height: 6px; margin-top: var(--sp-3); background: rgba(28,31,36,.14); }
/* Each side's own colour is set inline from the school, so these are the
   fallback for a school with no colour on file. */
.stat-bar i.fa { background: var(--brand); }
.stat-bar i.fb { background: var(--gray-400); }

/* Names the two columns of the team comparison, which carried no team
   identity at all until 2026-08-19. */
.stat-teams {
  display: flex; justify-content: space-between; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid rgba(28,31,36,.14);
}
.stat-team {
  display: inline-flex; align-items: center;
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-700);
}
.stat-dot--trailing { margin-right: 0; margin-left: var(--sp-2); }

/* The player's team, next to their name, where the colour dot alone used to
   be the only answer. */
.stat-team-code {
  margin-left: var(--sp-2);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .12em; color: var(--ink-400);
}

/* Q92-23 R1 — Team/Player tabs (stats panel). Tab buttons reuse the
   badge/label type scale rather than inventing a new one; the active
   state is a bottom rule, same idiom as .mainnav a.is-active. */
.stat-tabs { display: flex; gap: var(--sp-2); padding: 0 var(--sp-4); border-bottom: 1px solid rgba(28,31,36,.14); }
.stat-tab {
  appearance: none; background: none; border: none; cursor: pointer;
  padding: var(--sp-3) var(--sp-2);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-400);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.stat-tab.is-active { color: var(--ink-900); border-bottom-color: var(--brand); }
.stat-group { padding: var(--sp-4) 0; border-top: 1px solid rgba(28,31,36,.14); }
.stat-group:first-child { border-top: 0; }
.stat-group-head {
  padding: 0 var(--sp-4) var(--sp-2);
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-400);
}
.stat-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: var(--sp-2); }
[x-cloak] { display: none !important; }

/* ---------- rosters ----------
   One column of number / name / position rows at every width, capped and
   scrolled like the play-by-play so a 74-name roster cannot run away with the
   page. The number column is fixed width so the digits line up in a scannable
   gutter — the whole reason a roster is published by number, and what the old
   two-column grid destroyed. Deliberately NOT columned on wide screens: a
   numbered list read down one column and then jumped back up to the top of the
   next is harder to scan than a single run, and the height cap is already
   doing the work that columns would have been for. */
/* Two school names have to share one row at any width, so each tab takes half
   and truncates rather than pushing the row wider than the screen. */
.roster-tabs .stat-tab {
  flex: 1 1 50%;
  min-width: 0;
  text-align: left;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Each roster tab wears its school's colour — a chip beside the name and
   the active underline (--team-color set inline per game; falls back to
   the brand blue for a school with no colour on file). */
.roster-tabs .stat-tab::before {
  content: ""; display: inline-block;
  width: 14px; height: 4px;
  margin-right: var(--sp-2);
  vertical-align: 2px;
  background: var(--team-color, var(--brand));
  opacity: .35;
}
.roster-tabs .stat-tab.is-active { border-bottom-color: var(--team-color, var(--brand)); }
.roster-tabs .stat-tab.is-active::before { opacity: 1; }
.panel-body.roster { max-height: 460px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.roster-list { list-style: none; margin: 0; padding: 0; }
/* Row padding rather than container padding, matching the play-by-play, so the
   rules between rows run the full width of the panel. */
.roster-row {
  display: grid;
  grid-template-columns: 34px 1fr auto auto;
  align-items: baseline;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  border-top: 1px solid rgba(28,31,36,.14);
}
.roster-row:first-child { border-top: 0; }
.roster-num {
  font-family: var(--display); font-size: 16px;
  font-variant-numeric: tabular-nums; text-align: right;
  color: var(--ink-400);
}
.roster-name { font-size: 14.5px; color: var(--ink-800); }
.roster-pos {
  font: 700 10px/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-300);
  text-align: right;
  min-width: 52px;
}
/* Height/weight, when the roster file carried them — quiet data column
   between name and position; empty for teams without measurements. */
.roster-size {
  font: 500 11px/1 var(--label);
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  color: var(--ink-400);
  text-align: right;
  white-space: nowrap;
}

/* Q92-23 amendment (AC9a/AC9b) — the situation area is its own bordered
   block (no .panel-head bar) so the field never reads as a widget boxed
   inside a card. .panel + .panel's margin-top doesn't reach it (each
   gamecast panel is a separate Livewire root, one DOM level below its
   own wire:key wrapper, so the adjacent-sibling selector never actually
   matched between components) — margin-bottom here stands in for that
   spacing directly. */
.panel--situation {
  border: 1px solid var(--ink-900);
  background: var(--gray-100);
  padding: var(--sp-4);
  margin-bottom: var(--sp-8);
}
.situation-strip {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  font: 700 12px/1 var(--label);
  letter-spacing: .04em;
  color: var(--ink-800);
}
.situation-poss { font-size: 10px; }
.situation-sep { color: var(--ink-400); }
/* Marks a spot the engine worked out from the yardage rather than one the
   announcers called. */
.situation-est {
  margin-left: .3em;
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-400);
}

/* Q92-23 R4 — the field. Two end zones (team colour, crest, code) flank the
   0-100 playing field the feed's coordinates are already scaled to (away goal
   = 0, home goal = 100, per the feed README).

   The palette below is deliberately NOT drawn from the brand tokens. These are
   paint and grass — a depiction of a physical object — not interface colour,
   and the two broadcast marker colours are the ones every viewer already reads
   without a legend: blue is the line of scrimmage, yellow is the line to gain.
   Reaching for --brand or --cyan here would say "Q92" where the graphic needs
   to say "football". The one exception is the red-zone wash, which borrows the
   live crimson's hue because the red zone IS red; it tints turf rather than
   marking anything as live.

   Everything is drawn with gradients and nine number spans. No images, no
   JavaScript, one repaint per marker move. */
.field {
  --turf:          #1e3a28;
  --turf-mown:     #23452f;
  --paint:         rgba(255,255,255,.66);
  --paint-strong:  rgba(255,255,255,.9);
  --los:           #2f7fe0;
  --to-gain:       #ffd400;

  display: flex; align-items: stretch;
  width: 100%; height: 168px;
  border: 1px solid var(--ink-900);
  overflow: hidden;
}

/* ---- End zones ---- */
.field__endzone {
  position: relative;
  flex: 0 0 9%;            /* 10 of a 120-yard field, near enough at this size */
  display: flex; align-items: center; justify-content: center;
  background: var(--endzone-fill, var(--ink-900));
  overflow: hidden;
}
/* The white goal line, painted on the field side of every end zone. */
.field__endzone::after {
  content: ""; position: absolute; top: 0; bottom: 0; width: 2px;
  background: var(--paint-strong);
}
.field__endzone:first-child::after { right: 0; }
.field__endzone:last-child::after { left: 0; }

/* A crest is a full-colour PNG dropped on an arbitrary team colour, so it is
   flattened to a watermark and pushed the OPPOSITE way from its background —
   lifted toward white on a dark end zone, pressed toward black on a pale one.
   Left as-is it vanishes entirely on Hoover's black. */
.field__crest {
  position: absolute; inset: 10% 5%;
  width: auto; height: auto; max-width: 90%; max-height: 80%;
  margin: auto;
  object-fit: contain;
}
.field__endzone.is-dark .field__crest {
  opacity: .3;
  filter: grayscale(1) brightness(3) contrast(.7);
}
.field__endzone.is-light .field__crest {
  opacity: .26;
  filter: grayscale(1) brightness(.25) contrast(1.4);
}
.field__code {
  position: relative; z-index: 1;
  writing-mode: vertical-rl; transform: rotate(180deg);
  font: 400 25px/1 var(--display);
  letter-spacing: .16em;
  color: var(--endzone-ink, var(--paper));
  text-shadow: 0 1px 0 rgba(0,0,0,.28);
}

/* ---- The playing field ---- */
.field__play { position: relative; flex: 1 1 auto; overflow: hidden; }

/* Three stacked gradients, back to front: mown stripes every ten yards, the
   goal-line-to-goal-line grass, and a vignette that keeps the middle of the
   field from reading as flat as the sidelines. */
.field__turf {
  position: absolute; inset: 0;
  background-color: var(--turf);
  background-image:
    linear-gradient(to bottom, rgba(0,0,0,.28), transparent 22%, transparent 78%, rgba(0,0,0,.34)),
    repeating-linear-gradient(to right,
      var(--paint) 0, var(--paint) 1px,
      transparent 1px, transparent 5%,
      rgba(255,255,255,.28) 5%, rgba(255,255,255,.28) calc(5% + 1px),
      transparent calc(5% + 1px), transparent 10%),
    repeating-linear-gradient(to right,
      var(--turf-mown) 0, var(--turf-mown) 10%,
      var(--turf) 10%, var(--turf) 20%);
}
/* Hash marks — two rows a third of the way in from each sideline, one yard
   apart, exactly as they are painted. */
.field__turf::after {
  content: ""; position: absolute; inset: 0;
  background-image:
    repeating-linear-gradient(to right, var(--paint) 0, var(--paint) 1px, transparent 1px, transparent 1%),
    repeating-linear-gradient(to right, var(--paint) 0, var(--paint) 1px, transparent 1px, transparent 1%);
  background-size: 100% 7px, 100% 7px;
  background-position: 0 28%, 0 58%;
  background-repeat: no-repeat;
  opacity: .55;
}

/* Painted yard numbers, sat below the lower hash row rather than dead centre —
   where a real field puts them, and it leaves the middle band clear for the
   ball and the two lines, which used to land on top of a number. */
.field__yard {
  position: absolute; top: 74%;
  transform: translate(-50%, -50%);
  font: 400 25px/1 var(--display);
  letter-spacing: .04em;
  color: rgba(255,255,255,.58);
  text-shadow: 0 1px 2px rgba(0,0,0,.45);
  pointer-events: none;
}
.field__yard.is-fifty { color: rgba(255,255,255,.8); font-size: 29px; }

/* The direction arrow beside each number, pointing at the goal line it counts
   down to. Nothing beside the 50, which counts down to neither. */
.field__yard::after {
  content: ""; position: absolute; top: 50%;
  width: 0; height: 0;
  transform: translateY(-50%);
  border-top: 5px solid transparent; border-bottom: 5px solid transparent;
  opacity: .8;
}
.field__yard.is-toward-away::after {
  right: 100%; margin-right: 4px;
  border-right: 6px solid rgba(255,255,255,.58);
}
.field__yard.is-toward-home::after {
  left: 100%; margin-left: 4px;
  border-left: 6px solid rgba(255,255,255,.58);
}

/* ---- Broadcast markers ---- */
.field__firstdown {
  position: absolute; top: 0; bottom: 0; width: 3px;
  background: var(--to-gain);
  box-shadow: 0 0 0 1px rgba(0,0,0,.45), 0 0 12px rgba(255,212,0,.5);
}
.field__los {
  position: absolute; top: 0; bottom: 0; width: 3px;
  background: var(--los);
  box-shadow: 0 0 0 1px rgba(0,0,0,.45), 0 0 12px rgba(47,127,224,.55);
}
/* The ball itself — a prolate spheroid with laces, seated on the line of
   scrimmage and ringed in the colour of whoever has it. */
.field__ball {
  position: absolute; top: 50%; z-index: 2;
  width: 30px; height: 19px;
  transform: translate(-50%, -50%);
  border-radius: 50% / 50%;
  background: radial-gradient(120% 150% at 30% 25%, #a4501f 0%, #7b3610 62%, #5d2709 100%);
  box-shadow:
    0 0 0 2px var(--ball-ring, var(--paper)),
    0 3px 6px rgba(0,0,0,.5);
}
/* Laces — the long seam, then the cross stitches over it. Drawn as two
   pseudo-elements because one stack of box-shadows read as a dash. */
.field__ball::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 13px; height: 2px;
  transform: translate(-50%, -50%);
  background: var(--paint-strong);
  border-radius: 1px;
}
.field__ball::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 11px; height: 7px;
  transform: translate(-50%, -50%);
  background-image: repeating-linear-gradient(to right,
    var(--paint-strong) 0, var(--paint-strong) 2px,
    transparent 2px, transparent 5px);
}
/* The spot, printed above the ball. Feed text, so it stays type and never
   becomes an icon. */
.field__spot {
  position: absolute; top: var(--sp-2); z-index: 2;
  transform: translateX(-50%);
  padding: 2px var(--sp-2);
  background: var(--ink-900);
  font: 700 10.5px/1.4 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--paper);
  white-space: nowrap;
}

/* Attack direction: three chevrons that fade away from the ball, pointing the
   way the offence is going. Sat in the clear band above the upper hash row —
   below, they crowded whichever yard number they landed next to. */
.field__drive {
  position: absolute; top: var(--sp-3);
  display: flex; gap: 3px;
}
.field__drive span {
  width: 0; height: 0;
  border-top: 7px solid transparent; border-bottom: 7px solid transparent;
}
.field__drive--right { right: var(--sp-3); }
.field__drive--left  { left: var(--sp-3); flex-direction: row-reverse; }
.field__drive--right span { border-left: 9px solid var(--paint-strong); }
.field__drive--left  span { border-right: 9px solid var(--paint-strong); }
.field__drive span:nth-child(2) { opacity: .6; }
.field__drive span:nth-child(3) { opacity: .3; }

/* Red zone — the last twenty yards of the end being attacked, and ONLY those
   twenty. Tinting the turf itself (the first attempt) recoloured all 100 yards
   and read as a mud field rather than as a marked-off zone. */
.field__redzone {
  position: absolute; top: 0; bottom: 0;
  width: 20%;
  background: linear-gradient(to right, rgba(212,15,48,.28), rgba(212,15,48,.1));
  border-right: 1px solid rgba(255,255,255,.35);
}
.field__redzone--right {
  right: 0;
  background: linear-gradient(to left, rgba(212,15,48,.28), rgba(212,15,48,.1));
  border-right: 0;
  border-left: 1px solid rgba(255,255,255,.35);
}
.field__redzone--left { left: 0; }

/* ============================================================
   STATES
   ============================================================ */
.state {
  padding: var(--sp-8) var(--sp-5);
  text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-3);
}
.state-mark {
  font-family: var(--display); font-size: 34px; line-height: 1;
  color: var(--ink-400);
  border: 1px solid rgba(28,31,36,.3);
  padding: var(--sp-3) var(--sp-5);
}
.state-copy { font-size: 13.5px; line-height: 1.55; color: var(--ink-500); max-width: 34ch; }
.skel { height: 12px; background: rgba(28,31,36,.14); animation: pull 1.4s ease-in-out infinite; }
.skel.w-70 { width: 70%; } .skel.w-45 { width: 45%; } .skel.w-90 { width: 90%; }
@keyframes pull { 0%,100% { opacity: .4; } 50% { opacity: .85; } }
.skel-stack { display: flex; flex-direction: column; gap: var(--sp-3); padding: var(--sp-4); }
.panel.is-error { border-width: 3px; }
.panel.is-error .panel-head .badge { border-color: var(--cyan); color: var(--cyan); }
.panel.is-error .panel-body {
  background:
    repeating-linear-gradient(45deg, rgba(28,31,36,.06) 0 6px, transparent 6px 13px),
    var(--gray-300);
}

/* ============================================================
   COMPONENT SHEET furniture
   ============================================================ */
.sheet-intro { padding-top: var(--sp-12); }
.sheet-title {
  font-family: var(--display);
  font-size: 68px; line-height: .9;
  text-transform: uppercase; letter-spacing: -.022em;
  color: var(--ink-900);
}
.sheet-lede { margin-top: var(--sp-4); max-width: 66ch; color: var(--ink-500); }
.sheet-sec { padding: var(--sp-12) 0; border-top: 1px solid rgba(28,31,36,.22); }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-8); align-items: start; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); align-items: start; }
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-5); align-items: start; }
.cluster { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: center; }
.stack-6 > * + * { margin-top: var(--sp-6); }
.stack-4 > * + * { margin-top: var(--sp-4); }

.swatch-card { border: 1px solid var(--ink-900); background: var(--paper); }
.swatch-chip { height: 82px; border-bottom: 1px solid var(--ink-900); }
.swatch-meta { padding: var(--sp-3); }
.swatch-name {
  font: 700 12px/1 var(--label);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-900);
}
.swatch-role { margin-top: 6px; font-size: 12px; line-height: 1.45; color: var(--ink-400); }

.spec {
  font: 400 11.5px/1.4 var(--label);
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-400);
  margin-top: var(--sp-2);
}
.type-row { padding: var(--sp-5) 0; border-top: 1px solid rgba(28,31,36,.14); }
.type-row:first-child { border-top: 0; }
.on-dark { background: var(--ink-900); padding: var(--sp-5); }

/* ============================================================
   FOOTER — the second dark bar, and the second home of the logo
   ============================================================ */
.station-footer { background: var(--ink-900); color: var(--gray-400); }
.footer-strip {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  gap: var(--sp-10);
  padding-top: var(--sp-12);
  padding-bottom: var(--sp-10);
}
.footer-blurb { margin-top: var(--sp-4); max-width: 44ch; color: var(--gray-500); font-size: 13.5px; line-height: 1.6; }
.footer-col h4 {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--gray-500);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid rgba(251,252,253,.25);
  margin-bottom: var(--sp-3);
}
.footer-col a {
  display: block;
  padding: 5px 0;
  font: 700 13px/1.2 var(--label);
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--gray-300);
}
.footer-col a:hover { color: var(--cyan); }
.footer-legal {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  padding-top: var(--sp-5); padding-bottom: var(--sp-8);
  border-top: 1px solid rgba(251,252,253,.18);
  font: 400 11px/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--gray-500);
}

/* ============================================================
   TABLES ALWAYS SCROLL INSIDE THEMSELVES
   A wide table is the classic cause of a phone page scrolling
   sideways. Every table on the site is wrapped in .tscroll, so the
   table scrolls and the page body never does.
   ============================================================ */
.tscroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.tscroll .standings { min-width: 300px; }
.tscroll .linescore { min-width: 336px; }

/* Grid children must be allowed to shrink, or long words and wide
   tables push the whole page sideways. */
.page > *, .gc-grid > * { min-width: 0; }

/* The short form of the wire date only exists at handset widths. */
.w-short { display: none; }

/* A horizontal rail: nowrap, thumb-scrollable, snapped, with a soft
   right edge so it is obvious there is more beyond the screen. */
.rail-x {
  flex-wrap: nowrap;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
}
.rail-x::-webkit-scrollbar { display: none; }
.rail-x > * { flex: 0 0 auto; scroll-snap-align: start; }

/* ============================================================
   1180 — the rail tightens before it collapses
   ============================================================ */
@media (max-width: 1180px) {
  :root { --rail: 300px; --gap: var(--sp-6); }
  .page, .gc-grid { gap: var(--sp-6); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
  .feature { grid-template-columns: 280px 1fr; }
}

/* ============================================================
   900 — the two-column page becomes one column
   1024px still runs the full two-column layout, as it should.
   ============================================================ */
@media (max-width: 900px) {
  :root { --fs-mega: 84px; --fs-hero: 42px; }
  .page, .gc-grid { grid-template-columns: 1fr; }
  .gutter { display: none; }
  .board-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .livebar { grid-template-columns: 48px 1fr; }
  .live-cell { border-left: 0; border-top: 1px solid rgba(251,252,253,.22); }
  .live-cell:first-of-type { border-top: 0; }
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
  .footer-strip { grid-template-columns: 1fr 1fr; }
  .feature { grid-template-columns: 1fr; }
  .gc-title { font-size: 42px; }
  .gc-board .sl-score { font-size: 84px; }
  .gc-board .sl-school { font-size: 30px; }
}

/* ============================================================
   900 — MASTHEAD, SPORT INDEX AND FILTERS BECOME THUMB RAILS
   Measured: at 768px the desktop masthead row needs 999px, so the
   nav has to change form here, not at the handset breakpoint.
   Nothing is hidden — every nav item and all ten sports stay
   reachable, they just scroll under the thumb.
   ============================================================ */
@media (max-width: 900px) {
  /* ---- masthead: the logo keeps its dark bar, the site nav
          becomes a thumb rail rather than disappearing ---- */
  .masthead-row {
    grid-template-columns: 1fr auto;
    gap: var(--sp-3);
    padding-top: var(--sp-4);
    padding-bottom: 0;
  }
  .masthead-row .wordmark { grid-area: 1 / 1; }
  .masthead-row .onair { grid-area: 1 / 2; justify-self: end; }
  .masthead-row .mainnav { grid-row: 2; }
  .wordmark img { height: 32px; }
  .wordmark .tag { display: none; }
  .onair { padding: 0 var(--sp-4); font-size: 11px; letter-spacing: .1em; }

  .mainnav {
    grid-column: 1 / -1;
    gap: 0;
    margin: var(--sp-3) calc(var(--sp-4) * -1) 0;
    padding: 0 var(--sp-4);
    border-top: 1px solid rgba(251,252,253,.18);
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-left: var(--sp-4);   /* or snapping eats the rail's left padding */
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  }
  .mainnav::-webkit-scrollbar { display: none; }
  .mainnav a {
    flex: 0 0 auto;
    scroll-snap-align: start;
    display: flex; align-items: center;
    min-height: var(--tap);
    padding: 0 var(--sp-4) 0 0;
    margin-right: var(--sp-4);
    border-bottom-width: 3px;
    font-size: 12px;
  }

  /* ---- the sport index: all ten sports stay, none hidden.
          It becomes a snapped thumb rail with a faded right edge. ---- */
  .measure { height: auto; }
  .measure .marks {
    justify-content: flex-start;
    gap: 0;
    padding: 0 var(--sp-4);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-left: var(--sp-4);   /* or snapping eats the rail's left padding */
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  }
  .measure .marks::-webkit-scrollbar { display: none; }
  .measure .marks a {
    flex: 0 0 auto;
    scroll-snap-align: start;
    display: flex; align-items: center;
    min-height: var(--tap);
    padding: 0 var(--sp-4) 0 0;
    margin-right: var(--sp-4);
    font-size: 12px; letter-spacing: .14em;
    border-bottom-width: 3px;
  }

  .board-filters {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-left: var(--sp-4);   /* or snapping eats the rail's left padding */
    scrollbar-width: none;
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
  }
  .board-filters::-webkit-scrollbar { display: none; }
  .board-filters a {
    flex: 0 0 auto;
    scroll-snap-align: start;
    display: flex; align-items: center;
    min-height: var(--tap);
    padding: 0 var(--sp-4);
    white-space: nowrap;
  }


  /* the off-day wire is static rather than scrolling, so at these
     widths its headlines must be swipeable or they are simply lost */
  .wire-track.is-static {
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scroll-padding-left: var(--sp-4);   /* or snapping eats the rail's left padding */
    scrollbar-width: none;
  }
  .wire-track.is-static::-webkit-scrollbar { display: none; }
  .wire-track.is-static > * { scroll-snap-align: start; }

  /* thumb-sized secondary links */
  .wordmark { min-height: var(--tap); }
  .sec-head .see-all,
  .panel-head .see-all {
    display: inline-flex; align-items: center;
    min-height: var(--tap);
  }
  .panel-head { padding-top: 0; padding-bottom: 0; min-height: 48px; }
  .footer-legal a { display: inline-flex; align-items: center; min-height: var(--tap); }
  .footer-col a { display: flex; align-items: center; min-height: var(--tap); padding: 0; }

  /* A single-line headline link is only ~26px tall. Pad the hit area
     out to 44px and pull the same amount back off the margin, so the
     target grows and the layout does not move. */
  .lead-head a, .story-head a, .card-head a, .onair-title a, .live-title a {
    display: block;
    padding-block: 13px;
    margin-block: -13px;
  }
}

/* ============================================================
   767 — THE HANDSET PASS
   Designed at 390px and verified there, not reflowed into it.
   ============================================================ */
@media (max-width: 767px) {
  :root {
    --fs-mega: 60px;
    --fs-hero: 30px;
    --fs-head: 21px;
    --fs-body: 16px;      /* body copy never drops below 16px:
                             smaller than this makes iOS zoom on tap */
    --gap: var(--sp-4);
  }
  body { font-size: 16px; }
  .wrap { padding: 0 var(--sp-4); }
  .page { padding-top: var(--sp-6); padding-bottom: var(--sp-12); }
  .full { padding-top: var(--sp-6); }

  /* ---- the wire: short date, thumb-sized ticks ---- */
  .w-long { display: none; }
  .w-short { display: inline; }
  .wire-stamp { padding: 0 var(--sp-3); font-size: 10px; letter-spacing: .12em; }
  .tick { min-height: var(--tap); padding: var(--sp-3) var(--sp-4); }

  /* ---- Live on Q92 leads on a phone.
          It is the station's own product and the reason most people
          open the site on a Friday night, so it goes above the board
          rather than a screen and a half below it. The spine turns
          from a vertical rail into a horizontal header bar. ---- */
  .board-section { display: flex; flex-direction: column; }
  .board-section .livebar {
    order: -1;
    border: 1px solid var(--ink-900);
    margin-bottom: var(--sp-5);
  }
  .livebar { grid-template-columns: 1fr; }
  .livebar-spine {
    writing-mode: horizontal-tb;
    transform: none;
    justify-content: flex-start;
    letter-spacing: .26em;
    padding: 0 var(--sp-4);
    min-height: var(--tap);
  }
  .live-cell { padding: var(--sp-4); gap: var(--sp-2); }
  .live-title { font-size: 22px; }
  .live-sub { font-size: 15px; }
  .live-acts { gap: var(--sp-2); padding-top: var(--sp-1); }
  .live-acts .btn { flex: 1 1 auto; }

  /* ---- the area board: twelve games as one scannable column.
          At this width a card sheds its league/round footer and its
          venue line and keeps only what you scan for — sport, state,
          both teams, both scores, and whether Q92 is carrying it. ---- */
  .board-bar {
    grid-template-columns: 1fr auto;
    gap: var(--sp-2) var(--sp-3);
    padding: var(--sp-4);
  }
  .board-bar h2 { font-size: 23px; }
  .board-bar .when {
    grid-column: 1 / -1; grid-row: 2;
    font-size: 10px; letter-spacing: .12em; line-height: 1.5;
  }
  .board-grid { grid-template-columns: minmax(0, 1fr); }
  .gamecard {
    min-height: 0;
    padding: var(--sp-3) var(--sp-4);
    gap: var(--sp-2);
  }
  .gc-rows { gap: 6px; }
  .gc-row .name { font-size: 15px; }
  .gc-row .val { font-size: 25px; }
  .gc-foot { margin-top: 0; padding-top: var(--sp-2); border-top: 0; justify-content: flex-end; }
  .gc-foot > span:not(.gc-onq) { display: none; }
  .gc-foot:not(:has(.gc-onq)) { display: none; }
  .event-name { font-size: 21px; }

  /* ---- section heads: the ruled fill has no room left, so the
          headline takes the width and the link stays on the right ---- */
  .sec-head { grid-template-columns: 1fr auto; gap: var(--sp-4); }
  .sec-head .fill { display: none; }

  /* ---- the featured game slab. Three columns still fit at this
          width, but only if each side sheds its record line — the
          school, the mascot and the score are what people read. ---- */
  .feature { padding: var(--sp-4); gap: var(--sp-4); }
  .feature .sl-rec { display: none; }
  .feature .sl-mascot {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .scoreline { grid-template-columns: 1fr 74px 1fr; }
  .sl-team { padding: var(--sp-3); gap: var(--sp-2); }
  .sl-colorbar { width: 30px; }
  .sl-id { gap: var(--sp-2); }
  .team-mark--md { width: 34px; height: 34px; }
  .team-mark--lg { width: 44px; height: 44px; }
  .feature .sl-score { font-size: 40px; }
  .feature .sl-school { font-size: 17px; }
  .feature .sl-mascot, .feature .sl-rec { font-size: 9.5px; letter-spacing: .1em; }
  .sl-mid { padding: var(--sp-3) var(--sp-1); }
  .sl-clock { font-size: 19px; }
  .situation {
    flex-direction: column; align-items: flex-start; gap: var(--sp-2);
    padding: var(--sp-3) var(--sp-4); font-size: 10.5px; letter-spacing: .1em;
  }
  .board-foot { flex-direction: column; align-items: stretch; gap: var(--sp-3); padding: var(--sp-4); }
  .board-foot .cluster .btn { flex: 1 1 auto; }
  .board-strip { padding: var(--sp-3) var(--sp-4); }

  .panel--situation { padding: var(--sp-3); }
  .situation-strip { flex-wrap: wrap; font-size: 10.5px; letter-spacing: .02em; }
  /* At handset widths the numbers and hash marks crowd into noise long before
     the markers do, so the geometry thins out and the markers stay. */
  .field { height: 116px; }
  .field__endzone { flex-basis: 13%; }
  .field__code { font-size: 17px; letter-spacing: .1em; }
  .field__crest { display: none; }
  .field__yard { top: 72%; font-size: 15px; }
  .field__yard.is-fifty { font-size: 18px; }
  .field__yard:nth-of-type(even) { display: none; }
  .field__yard::after { display: none; }
  .field__turf::after { display: none; }
  .field__ball { width: 22px; height: 14px; }
  .field__ball::after { width: 8px; }
  .field__spot { top: var(--sp-1); font-size: 9.5px; letter-spacing: .06em; }
  .field__drive { top: var(--sp-2); }

  /* ---- gamecast ---- */
  .gc-hero .slot { aspect-ratio: 4 / 3; }
  /* Handsets: the colour field earns less height than a photo — enough
     ground for the split to read, no dead acreage above the title. */
  .gc-hero .slot.hero-fallback { aspect-ratio: 16 / 5; min-height: 150px; }
  .gc-hero-cap { padding-bottom: var(--sp-5); }
  .gc-hero-cap::before { inset: -90px 0 0 0; }
  .gc-hero-cap .wrap { flex-direction: column; align-items: flex-start; gap: var(--sp-3); }
  /* Handsets: keep the split billing — smaller type, each name centered
     on its own half and free to wrap to two lines. */
  .gc-title { font-size: 24px; column-gap: var(--sp-3); align-items: center; }
  .gc-title-away, .gc-title-home { justify-self: center; text-align: center; line-height: .92; }
  .gc-title-at { vertical-align: 0; }
  .gc-where { font-size: 10px; letter-spacing: .14em; padding-bottom: 0; }
  .gc-where::before { width: 20px; }
  .gc-board { margin-top: calc(var(--sp-5) * -1); }
  .gc-board .sl-score { font-size: 46px; }
  .gc-board .sl-school { font-size: 19px; }
  /* Handsets: the hero right above already names mascot and town — the
     board sheds that line the same way the homepage feature slab sheds
     its record line at this width. */
  .gc-board .sl-mascot { display: none; }
  .gc-grid { padding-top: var(--sp-8); padding-bottom: var(--sp-12); }
  .panel-body.pbp { max-height: 380px; }
  .pbp .play { grid-template-columns: 54px 1fr; padding: var(--sp-3) var(--sp-4); }
  .play-head { font-size: 16px; }
  .stat-top { grid-template-columns: 56px 1fr 56px; }

  /* ---- photography: no letterbox slivers at this width ---- */
  .r-40x13 { aspect-ratio: 4 / 3; }
  .r-21x9  { aspect-ratio: 16 / 9; }
  .lead-story .slot { min-height: fit-content; aspect-ratio: 4 / 3; }
  .mat { padding: 5px; }

  /* ---- stories ---- */
  .lead-cap { padding: var(--sp-4); }
  .lead-head { max-width: none; }
  .dek { font-size: 16px; max-width: none; }
  .story-row { grid-template-columns: 1fr; gap: var(--sp-3); padding: var(--sp-5) 0; }
  .story-row.no-photo > div { grid-column: 1; }
  .story-row.no-photo::before { display: none; }
  .story-head { font-size: 21px; max-width: none; }
  .card { padding: var(--sp-4); }
  .card-head { font-size: 20px; }
  .card-dek { font-size: 15px; }
  .headlines a {
    grid-template-columns: 1fr; gap: 3px; align-items: start;
    min-height: var(--tap); padding: var(--sp-3) 0;
  }
  .hl-text { font-size: 16px; }
  .pullquote q { font-size: 21px; }

  /* ---- panels, schedule and score rows ---- */
  .panel + .panel { margin-top: var(--sp-6); }
  /* Tighter than desktop, but still clearly wider than the panel gap above. */
  .gc-section + .gc-section { margin-top: var(--sp-10); }
  /* A roster is the longest list on the page and the least urgent, so it gives
     up the most height on a phone. */
  .panel-body.roster { max-height: 320px; }
  .panel-head { padding: var(--sp-3) var(--sp-4); }
  .sched {
    grid-template-columns: 56px 1fr;
    row-gap: var(--sp-2);
    min-height: var(--tap);
    padding: var(--sp-3) var(--sp-4);
  }
  /* The status word ("scheduled") is wider than the 56px column and adds
     nothing on a phone — the time is the fact, live games wear a badge. */
  .sched-when .sched-status { display: none; }
  .sched > .badge, .sched > .meta:last-child { grid-column: 2; justify-self: start; }
  .score { min-height: var(--tap); }
  .onair-sub { font-size: 15px; }
  .state-copy { font-size: 15px; }

  /* ---- component sheet ---- */
  .sheet-intro { padding-top: var(--sp-8); }
  .sheet-title { font-size: 36px; }
  .sheet-sec { padding: var(--sp-8) 0; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }

  /* ---- footer ---- */
  .footer-strip { grid-template-columns: 1fr 1fr; gap: var(--sp-6); padding-top: var(--sp-8); padding-bottom: var(--sp-6); }
  .footer-legal { flex-direction: column; gap: var(--sp-2); line-height: 1.5; }
}

/* ============================================================
   430 — the last step down, for a 390px handset
   ============================================================ */
@media (max-width: 430px) {
  :root { --fs-mega: 52px; --fs-hero: 27px; }
  .gc-title { font-size: 24px; }
  .gc-board .sl-score { font-size: 40px; }
  .gc-board .sl-school { font-size: 15px; }
  /* Q92-14 R17: at a 390px handset the side-by-side mark+name (.sl-id)
     doesn't have room next to the score column — a single-word school
     name (e.g. "MASSILLON") hits its own min-content width, refuses to
     break (overflow-wrap/word-break: normal, by design), and overflows
     past .sl-id's edge straight into the score. Same fix already used
     for the homepage's .feature-body: stack the mark above the name so
     the name gets the column's full width instead of sharing it. */
  .gc-board .sl-id { flex-direction: column; align-items: flex-start; gap: 2px; }
  .gc-board .sl-team.home .sl-id { flex-direction: column; align-items: flex-end; }
  .gc-board .sl-mascot { display: none; }
  .gc-board .sl-team { padding: var(--sp-2); gap: var(--sp-1); }
  .gc-board .sl-colorbar { width: 26px; }
  .gc-board .team-mark--lg { width: 28px; height: 28px; }
  .feature .sl-school { font-size: 15px; }
  .feature .sl-score { font-size: 36px; }
  .scoreline { grid-template-columns: 1fr 56px 1fr; }
  .feature .sl-mascot { display: none; }
  .feature .sl-team { padding: var(--sp-2); gap: var(--sp-1); }
  .feature .sl-school { font-size: 14px; }
  .feature .sl-score { font-size: 32px; }
  .sl-id { gap: 6px; }
  .team-mark--md { width: 28px; height: 28px; }
  .team-mark--lg { width: 36px; height: 36px; }
  .sheet-title { font-size: 32px; }
  .footer-strip { grid-template-columns: 1fr; }

  /* Q92-16 R5 — the sticky strip only ever exists at this breakpoint, so
     the offset only needs to apply here: an in-page anchor jump lands
     with its target's top clear of the fixed strip instead of tucked
     underneath it. General [id] selector so this keeps working for any
     future anchor target, not just today's panels. */
  [id] { scroll-margin-top: calc(var(--tap) + var(--sp-3)); }

  /* Q92-14 R17 follow-up: the drive summary table (.tbl, drives-panel
     only — no other table uses this class) fits inside its .tscroll box
     at 390px, but reaching the Result column meant scrolling sideways
     inside it, which reads poorly even though it's correctly contained.
     Restack each row into two lines: drive/offense/result stay on one
     line (result pinned to the far right — it's what people actually
     read), plays+yards drop to a smaller, muted second line indented
     under the offense name. Real <table> markup is unchanged — only
     display/grid-position change here — so desktop (untouched, this is
     all inside the 430px query) and screen readers reading the DOM in
     source order both still see five ordinary cells. Header row is
     dropped visually: a two-line card has no single row for <thead> to
     label, and there's nothing here for it to usefully anchor to. */
  .tbl thead { display: none; }
  .tbl, .tbl tbody { display: block; width: 100%; }
  .tbl tr {
    display: grid;
    grid-template-columns: auto auto auto 1fr;
    column-gap: var(--sp-2);
    row-gap: 2px;
    padding: var(--sp-3) var(--sp-4);
    border-bottom: 1px solid rgba(28,31,36,.12);
  }
  .tbl tr:last-child { border-bottom: 0; }
  .tbl td { display: block; padding: 0; border-bottom: 0; text-align: left; min-width: 0; }
  .tbl td:nth-child(1) { grid-column: 1; grid-row: 1; } /* drive */
  .tbl td:nth-child(2) { grid-column: 2; grid-row: 1; } /* offense */
  .tbl td:nth-child(5) { grid-column: 4; grid-row: 1; text-align: right; } /* result */
  .tbl td:nth-child(3),
  .tbl td:nth-child(4) {
    grid-row: 2;
    font-size: 11.5px;
    letter-spacing: .04em;
    color: var(--ink-400);
  }
  .tbl td:nth-child(3) { grid-column: 2; } /* plays */
  .tbl td:nth-child(3)::after { content: " " attr(data-unit); }
  .tbl td:nth-child(4) { grid-column: 3; } /* yards */
  .tbl td:nth-child(4)::before { content: "\00b7\0020"; }
  .tbl td:nth-child(4)::after { content: " " attr(data-unit); }
}

@media (prefers-reduced-motion: reduce) {
  .wire-track { animation: none; }
  .dot, .skel { animation: none; }
  .rail-x, .mainnav, .measure .marks, .board-filters { scroll-behavior: auto; }
  /* Q92-16 R7 — the strip still appears/disappears, just with no
     transition: the is-visible class flips state instantly. */
  .gc-sticky-score { transition: none; }
}

/* ============================================================
   THE MOBILE SPECIMEN — component sheet only
   A hard 390px frame that renders the handset treatment at any
   viewport, so the phone design can be reviewed on a desktop
   without resizing the window. These rules restate the handset
   geometry inside .phone; they never affect the real pages.
   ============================================================ */
.phone-set {
  display: grid;
  /* minmax(0,…) so neither column can take an intrinsic minimum from
     the specimen inside it and push the sheet sideways */
  grid-template-columns: minmax(0, 390px) minmax(0, 1fr);
  gap: var(--sp-8); align-items: start;
}
.phone-set > * { min-width: 0; }
.phone {
  width: 390px; max-width: 100%;
  border: 1px solid var(--ink-900);
  background: var(--gray-200);
  overflow: hidden;
}
.phone-cap {
  padding: var(--sp-2) var(--sp-3);
  background: var(--ink-900); color: var(--gray-500);
  font: 700 10px/1 var(--label); letter-spacing: .2em; text-transform: uppercase;
}
.phone .wrap { padding: 0 var(--sp-4); max-width: none; }
.phone .masthead-row { grid-template-columns: 1fr auto; gap: var(--sp-3); padding: var(--sp-4) 0 0; }
.phone .wordmark img { height: 32px; }
.phone .wordmark .tag { display: none; }
.phone .onair { padding: 0 var(--sp-4); font-size: 11px; letter-spacing: .1em; min-height: var(--tap); }
.phone .mainnav {
  grid-column: 1 / -1; gap: 0; margin: var(--sp-3) calc(var(--sp-4) * -1) 0;
  padding: 0 var(--sp-4); border-top: 1px solid rgba(251,252,253,.18);
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg,#000 calc(100% - 34px),transparent);
          mask-image: linear-gradient(90deg,#000 calc(100% - 34px),transparent);
}
.phone .mainnav::-webkit-scrollbar { display: none; }
.phone .mainnav a {
  flex: 0 0 auto; display: flex; align-items: center; min-height: var(--tap);
  padding: 0 var(--sp-4) 0 0; margin-right: var(--sp-4);
  border-bottom-width: 3px; font-size: 12px;
}
.phone .measure { height: auto; }
.phone .measure .marks {
  justify-content: flex-start; gap: 0; padding: 0 var(--sp-4);
  overflow-x: auto; scrollbar-width: none; max-width: none;
  -webkit-mask-image: linear-gradient(90deg,#000 calc(100% - 34px),transparent);
          mask-image: linear-gradient(90deg,#000 calc(100% - 34px),transparent);
}
.phone .measure .marks::-webkit-scrollbar { display: none; }
.phone .measure .marks a {
  flex: 0 0 auto; display: flex; align-items: center; min-height: var(--tap);
  padding: 0 var(--sp-4) 0 0; margin-right: var(--sp-4);
  font-size: 12px; letter-spacing: .14em; border-bottom-width: 3px;
}
.phone .livebar { grid-template-columns: 1fr; border: 1px solid var(--ink-900); }
.phone .livebar-spine {
  writing-mode: horizontal-tb; transform: none; justify-content: flex-start;
  letter-spacing: .26em; padding: 0 var(--sp-4); min-height: var(--tap);
}
.phone .live-cell { border-left: 0; border-top: 1px solid rgba(251,252,253,.22); padding: var(--sp-4); gap: var(--sp-2); }
.phone .live-cell:first-of-type { border-top: 0; }
.phone .live-title { font-size: 22px; }
.phone .live-sub { font-size: 15px; }
.phone .live-acts .btn { flex: 1 1 auto; }
.phone .board-bar { grid-template-columns: 1fr auto; gap: var(--sp-2) var(--sp-3); padding: var(--sp-4); }
.phone .board-bar h2 { font-size: 23px; }
.phone .board-bar .when { grid-column: 1 / -1; grid-row: 2; font-size: 10px; letter-spacing: .12em; line-height: 1.5; }
.phone .board-filters {
  flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none;
  -webkit-mask-image: linear-gradient(90deg,#000 calc(100% - 34px),transparent);
          mask-image: linear-gradient(90deg,#000 calc(100% - 34px),transparent);
}
.phone .board-filters::-webkit-scrollbar { display: none; }
.phone .board-filters a { flex: 0 0 auto; display: flex; align-items: center; min-height: var(--tap); padding: 0 var(--sp-4); white-space: nowrap; }
.phone .board-grid { grid-template-columns: minmax(0, 1fr); }
.phone .gamecard { min-height: 0; padding: var(--sp-3) var(--sp-4); gap: var(--sp-2); }
.phone .gc-rows { gap: 6px; }
.phone .gc-row .name { font-size: 15px; }
.phone .gc-row .val { font-size: 25px; }
.phone .gc-foot { margin-top: 0; padding-top: var(--sp-2); border-top: 0; justify-content: flex-end; }
.phone .gc-foot > span:not(.gc-onq) { display: none; }
.phone .gc-foot:not(:has(.gc-onq)) { display: none; }

/* the tap-target diagram */
.tap-demo { display: flex; flex-wrap: wrap; gap: var(--sp-4); }
.tap-fig { position: relative; display: inline-flex; }
.tap-fig::after {
  content: ""; position: absolute; inset: 50% auto auto 0;
  width: 44px; height: 44px; transform: translateY(-50%);
  border: 1px dashed var(--brand); pointer-events: none;
}
.spec-list { margin: 0; padding: 0; list-style: none; }
.spec-list li {
  display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: var(--sp-4);
  padding: var(--sp-3) 0; border-top: 1px solid rgba(28,31,36,.16);
  font-size: 14.5px; line-height: 1.5; color: var(--ink-500);
}
.spec-list li:first-child { border-top: 0; }
.spec-list b {
  font: 700 12px/1.5 var(--label); letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-900);
}
@media (max-width: 900px) {
  .phone-set { grid-template-columns: minmax(0, 1fr); }
  .phone { width: 100%; }
}

/* ============================================================
   SOCIAL WALL (Q92 2026-08-19) — /social filter chips + cards
   ============================================================ */
.social-filters { display: flex; flex-direction: column; gap: var(--sp-3); margin-top: var(--sp-4); }
.filter-row { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.filter-label {
  flex: none; font: 700 10px/1 var(--label); letter-spacing: .16em; text-transform: uppercase;
  color: var(--gray-500); width: 52px;
}
.filter-clear {
  font: 700 11px/1 var(--label); letter-spacing: .08em; text-transform: uppercase;
  color: var(--brand); text-decoration: none; white-space: nowrap;
}
.filter-clear:hover { color: var(--brand-deep); }

/* Platform picker: one connected segmented control, not three loose pills. */
.social-segment { display: inline-flex; border: 1px solid var(--ink-900); }
.social-segment .seg {
  padding: 8px 16px; font: 700 11px/1 var(--label); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-500); text-decoration: none; white-space: nowrap;
  transition: color .2s ease, background .2s ease;
}
.social-segment .seg + .seg { border-left: 1px solid var(--ink-900); }
.social-segment .seg:hover { color: var(--brand); }
.social-segment .seg.is-active { background: var(--ink-900); color: #fff; }

.social-chips { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; min-width: 0; }
.chip .x { margin-left: 6px; font-size: 12px; line-height: 0; }

/* Mobile: chip rows scroll sideways instead of stacking into a wall. */
@media (max-width: 700px) {
  .social-chips {
    flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; padding-bottom: 2px;
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  .social-chips::-webkit-scrollbar { display: none; }
  .chip { padding: 9px 14px; } /* bigger tap target */
  .social-segment { width: 100%; }
  .social-segment .seg { flex: 1; text-align: center; }
  .filter-row { flex-wrap: wrap; row-gap: var(--sp-2); }
  .filter-label { width: auto; }
}
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border: 1px solid var(--gray-500); border-radius: 999px;
  font: 700 11px/1 var(--label); letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-500); text-decoration: none; white-space: nowrap;
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
.chip:hover { color: var(--brand); border-color: var(--brand); }
.chip.is-active { background: var(--brand); border-color: var(--brand); color: #fff; }
.chip.is-active:hover { background: var(--brand-deep); }

.social-card .cluster { align-items: center; }
.social-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font: 700 10px/1 var(--label); letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-500);
}
.social-badge::before {
  content: ""; width: 8px; height: 8px; border-radius: 999px; display: inline-block;
}
.social-badge--instagram::before { background: linear-gradient(45deg, #f58529, #dd2a7b 55%, #8134af); }
.social-badge--x::before { background: var(--ink-900); }

.social-engage { display: flex; gap: var(--sp-4); margin-top: var(--sp-2); }
.social-engage span { font: 400 11.5px/1.3 var(--label); letter-spacing: .1em; text-transform: uppercase; color: var(--ink-400); }

/* Social wall grid: 3-up on desktop, 2-up on mid widths, 1 on mobile. */
.social-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); align-items: start; }
@media (max-width: 1100px) { .social-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 700px) { .social-grid { grid-template-columns: 1fr; } }

/* Social cards diverge from the news treatment: these are the platforms'
   own photos, shown FULL COLOR always (no monochrome-print rest state),
   and the mat + body fuse into one bordered card with a hover lift. */
.social-card { border: 1px solid var(--ink-900); background: var(--paper); display: flex; flex-direction: column;
  transition: box-shadow .25s ease, transform .25s ease; }
.social-card:hover { box-shadow: 0 10px 28px rgba(28,31,36,.14); transform: translateY(-2px); }
.social-card .mat { border: 0; padding: 0; }
.social-card .slot.has-photo::before { filter: saturate(1); }
.social-card .card { border: 0; flex: 1; }
.social-card .card-dek { font-size: 14px; color: var(--ink-700, var(--ink-500)); }
.social-card .social-view {
  margin-top: auto; align-self: flex-start;
  font: 700 11px/1 var(--label); letter-spacing: .12em; text-transform: uppercase;
  color: var(--brand); text-decoration: none;
}
.social-card .social-view:hover { color: var(--brand-deep); }
@media (prefers-reduced-motion: reduce) { .social-card, .social-card:hover { transform: none; transition: none; } }

/* Platform identity: a slim accent strip across the top of each card —
   Instagram's gradient vs X's ink — plus a matching link color, so the two
   sources scan apart at a glance without shouting. */
.social-card--instagram, .social-card--x { position: relative; }
.social-card--instagram::before, .social-card--x::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 3px; z-index: 2; pointer-events: none;
}
.social-card--instagram::before { background: linear-gradient(90deg, #f58529, #dd2a7b 55%, #8134af); }
.social-card--x::before { background: var(--ink-900); }
.social-card--instagram .social-badge { color: #b0246a; }
.social-card--instagram .social-view { color: #b0246a; }
.social-card--instagram .social-view:hover { color: #8134af; }
.social-card--x .social-badge { color: var(--ink-900); }
.social-card--x .social-view { color: var(--ink-900); }
.social-card--x .social-view:hover { color: var(--ink-500); }

/* Badge shows the platform's actual glyph; the identity dot retires. */
.social-badge::before { display: none; }
.social-badge svg { width: 15px; height: 15px; display: block; }

/* Article share row — plain intent links, no third-party embeds. */
.share-row { display: flex; gap: var(--sp-2); margin-top: var(--sp-4); }
.share-btn {
  appearance: none; cursor: pointer;
  background: none; border: 1px solid rgba(28,31,36,.25);
  padding: 7px 12px 6px;
  font: 700 10px/1 var(--label);
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--ink-600, #4b5563);
  text-decoration: none;
}
.share-btn:hover { border-color: var(--ink-900); color: var(--ink-900); }

/* Sortable roster headers on the program page. */
.th-sort {
  appearance: none; background: none; border: none; cursor: pointer;
  padding: 0; font: inherit; color: inherit;
  letter-spacing: inherit; text-transform: inherit;
}
.th-sort-arrow { margin-left: 4px; font-size: 8px; vertical-align: 1px; }

/* Presenting sponsor (2026-08-20, enlarged same day) — a full-width banner on
   /scores and a large chip in the homepage board bar. Ground stays ink-900
   everywhere so a white sponsor logo always reads. */
.presenting-banner {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-5);
  background: var(--ink-900);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-6);
  border-left: 4px solid var(--brand);
}
.presenting-banner .pb-label {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--gray-400);
}
.presenting-banner .ad-slot img { display: block; height: 52px; width: auto; }
.presented-by { display: inline-flex; align-items: center; gap: var(--sp-3); }
.presented-by .pb-label {
  font: 700 var(--fs-micro)/1 var(--label);
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--gray-400);
}
.presented-by .ad-slot img { display: block; height: 38px; width: auto; }
.board-right { display: inline-flex; align-items: center; gap: var(--sp-5); justify-self: end; }
@media (max-width: 720px) {
  .presenting-banner .ad-slot img { height: 36px; }
  .board-bar .presented-by { display: none; } /* the dark bar is tight on phones; the banner still shows */
}
