/*
 * cpt-rough.css — rough-template baseline for Game and Player CPT pages.
 *
 * Loaded conditionally from functions.php on is_singular(['game_entry',
 * 'player_profile']). Per docs/cpt-structural-layouts.md §2 ("rough-
 * template intentional ugliness"), this file ships ONLY:
 *
 *   - Module wrapper (.cpt-module): dashed border, vertical rhythm,
 *     mono micro-label header
 *   - Stats table baseline (.stats-table) per design-system §14.1
 *   - Horizontal scroll wrapper (.table-scroll) for wide tables
 *   - .num right-alignment + tabular figures
 *   - .win / .loss inheriting tokens
 *
 * No colors beyond --ink/--ink-muted/--line-soft. No font sizes beyond
 * the mono micro-label rule. No transitions, hovers, interactions.
 * Visual treatment is Claude Design's pass after this rough render.
 */

/* Module wrapper — replaces the CPT-shells .placeholder-region treatment.
 * Empty .cpt-module divs (Game CPT shell pending real modules) render
 * the same dashed-border treatment as populated ones. Section label
 * comes from the inner <header class="cpt-module__label"> per layout
 * §3.3. */
.cpt-module {
	border: 1px dashed var(--line-soft);
	padding: 16px;
	margin-block: 12px;
}
.cpt-module__label {
	font-family: var(--font-mono);
	font-size: 0.75rem;
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	color: var(--ink-muted);
	margin: 0 0 12px;
	font-weight: 500;
}

.cpt-module__body {
	color: var(--ink);
}

/* Group sub-header inside team-stats / advanced-stats tables.
 * Same mono micro-label register, no border (the module wrapper carries it). */
.cpt-module__group-label {
	font-family: var(--font-mono);
	font-size: 0.75rem;
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	color: var(--ink-muted);
	margin: 18px 0 8px;
	font-weight: 500;
}
.cpt-module__group-label:first-child {
	margin-top: 0;
}

/* Canonical data-table header row (`.data-table thead th`) and its
 * non-table sibling (`.row-head__cell`) live in style.css since they're
 * design primitives used outside CPT-only surfaces. See style.css
 * §"Canonical header row" (added 2026-05-20). */

/* Stats table — surface-specific cell decoration only. The base
 * chrome (width, border-collapse, font-family, thead treatment, tbody
 * padding) is provided by `.data-table` in style.css §"Canonical body
 * cell treatment" + §"Canonical header row" via the `data-table` opt-in
 * class. Phase 3a (2026-05-22) removed the duplicate base block here;
 * what remains is the column-level cell decoration that `.data-table`
 * doesn't cover (mono+tabular numeric column, W/L color utilities,
 * totals row treatment). Per design-system §14.1. */
.stats-table .num {
	text-align: right;
	font-variant-numeric: tabular-nums;
	font-family: var(--font-mono);
}
.stats-table thead .num {
	text-align: right;
}
.stats-table .win {
	color: var(--win);
}
.stats-table .loss {
	color: var(--loss);
}
.stats-table tr.totals th[scope="row"],
.stats-table tr.totals td {
	font-weight: 700;
	border-top: 1px solid var(--line-soft);
}

/* Horizontal scroll wrapper for wide tables (box score, last-5 with QB
 * passing+rushing column set, advanced stats in 3-col compare).
 * Per layout §3.7. */
.table-scroll {
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
}

/* Player Header rules live in assets/css/player.css. Latest pass
 * (2026-05-21) replaced the 2026-05-17 navy-band header (.player-band,
 * .player-band__identity, .player-band__meta) with the Stadium
 * Scoreboard layout (.player-board, .player-board__top,
 * .player-board__marquee, .player-board__tiles, .player-tile). Old
 * .player-data / action-photo / state-badge markup is gone from
 * template-parts/cpt/player/player-header.php. */

/* Cross-link rail list — single-line text links per §4.12 / §5.9. */
.cpt-cross-links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}
.cpt-cross-links a {
	font-family: var(--font-mono);
	font-size: 0.75rem;
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
	color: var(--ink);
	text-decoration: none;
}
.cpt-cross-links a:hover {
	color: var(--ink);
	text-decoration: underline;
}

/* ======================================================================
 * Game CPT — completed-game identity zone + module zone layout.
 *
 * Ported from sandbox/UHND Game Recap.html (the design contract per
 * docs/decisions.md 2026-05-07 sandbox-precedence). Identity zone
 * (matchup header + tab strip) per design-system §19.8; tab strip
 * visual rules per §20.5 (sentence-case ink-contrast, no brand color);
 * module-zone grid per §19.8 with per-view layout flag.
 *
 * Phase A scope (2026-05-10): identity zone + tab strip + module-zone
 * grid scaffold. Content-module CSS overrides (clean register replacing
 * the dashed-border rough render) ship in Phase B alongside Series
 * History, Top Performers, and curated Team Stats / Advanced variants.
 * ====================================================================== */

/* Section divider — major boundary between recap story group and stats group,
 * and between stats group and Top Performers (design-system §14.4).
 * A hairline at the midpoint of the gap; the cpt-content gap:44px provides
 * spacing above and below. */
.cpt-layout .section-divide {
	border-top: 1px solid var(--line-soft);
}

.cpt-identity {
	margin-top: 8px;
}

/* Matchup header v2 — comp-driven, completed-game state */
.matchup-header {
	padding: 30px 0 26px;
}
/* .meta-line + .pill rules removed 2026-05-10 with the markup —
 * status pill + season-type line read as redundant once breadcrumbs
 * ship the season segment. */

.matchup-row {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	gap: 36px;
	align-items: center;
}
.matchup-row .team {
	display: flex;
	align-items: center;
	gap: 18px;
	min-width: 0;
}
.matchup-row .team--home { justify-content: flex-end; }
.matchup-row .team--away { justify-content: flex-start; }
.matchup-row .team-logo {
	width: 76px;
	height: 76px;
	object-fit: contain;
	flex-shrink: 0;
}
/* Team-mark base (.team-mark, --neutral, --ondark) lives in cards.css so it
 * ships in goldendome-bundle and styles chips on EVERY surface (schedule,
 * homepage, rail, …), not just the CPT pages cpt-rough.css loads on. Only the
 * matchup-band size override stays here. */
.matchup-row .team-mark {
	width: 76px;
	height: 76px;
	font-size: 20px;
}
.matchup-row .team-text {
	display: flex;
	flex-direction: column;
	gap: 3px;
	min-width: 0;
}
.matchup-row .team--home .team-text {
	align-items: flex-end;
	text-align: right;
}
.matchup-row .team--away .team-text {
	align-items: flex-start;
	text-align: left;
}
.matchup-row .rank-line {
	display: flex;
	gap: 12px;
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	font-weight: 600;
	letter-spacing: 0.04em;
	line-height: 1;
}
.matchup-row .rank-line .rank {
	display: inline-flex;
	gap: 5px;
	align-items: baseline;
}
.matchup-row .rank-line .rank-src {
	font-weight: 400;
	color: var(--ink-4);
	font-size: 10px;
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
}
.matchup-row .team-name {
	font-family: var(--font-serif);
	font-size: clamp(22px, 2.4vw, 30px);
	font-weight: 700;
	color: var(--nd-navy);
	letter-spacing: -0.012em;
	line-height: 1.04;
	margin-top: 2px;
	white-space: nowrap;
}
.matchup-row .team-record {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--type-micro-tracking);
	color: var(--ink-3);
	margin-top: 5px;
	text-transform: uppercase;
	font-weight: 500;
}
/* Loser dims so winner reads */
.matchup-header--final .team:not(.team--winner) .team-name {
	color: color-mix(in srgb, var(--nd-navy) 60%, var(--bg));
}

/* Score column */
.matchup-row .score-col {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	padding: 0 4px;
}
/* Status pill base + --final / --scheduled variants — moved to the
 * primitives block at style.css §"Status pill" 2026-05-22 with Phase 3d
 * of the CSS rebuild. Sitewide enqueue means every surface inherits;
 * the previous cpt-rough.css scoping (CPT-only) is no longer needed.
 * The --streak variant stays here (it's Opponent-CPT-only). Other
 * variants live in their per-surface sheets:
 *   - game.css §"Status pill — game band navy" (--win / --loss
 *     overrides on the navy band)
 *   - cpt-rough.css §"Opponent band ink flips" (status-pill ink on
 *     the opponent identity navy band) */

.matchup-row .final-label {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
}
.matchup-row .scoreline {
	display: flex;
	align-items: baseline;
	gap: 10px;
	font-family: var(--font-mono);
	line-height: 0.85;
}
.matchup-row .score {
	font-size: clamp(54px, 6vw, 74px);
	font-weight: 600;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.025em;
}
.matchup-row .scoreline .score--loser {
	color: color-mix(in srgb, var(--nd-navy) 50%, var(--bg));
}
.matchup-row .scoreline .dash {
	font-size: clamp(32px, 3.5vw, 45px);
	color: var(--ink-4);
	font-weight: 300;
	letter-spacing: 0;
	align-self: center;
	line-height: 1;
}
/* Preview-state placeholder slot inside the new matchup-row (rare —
 * normally preview games take the v1 path entirely). */
.matchup-row .score-col--preview {
	text-align: center;
}

/* Date / Venue / Network meta row — Recap-only, lives inside cpt-content
 * above Line Score (moved out of .matchup-header per Frank's 2026-05-10
 * call so the identity zone stays compact and the meta surfaces as a
 * content-column module instead of full-bleed chrome). */
.game-meta-row {
	display: flex;
	gap: 44px;
	flex-wrap: wrap;
}
.game-meta-row .meta-item-block {
	display: flex;
	flex-direction: column;
	gap: 3px;
}
.game-meta-row .meta-label {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}
.game-meta-row .meta-value {
	font-family: var(--font-sans);
	font-size: 14px;
	color: var(--text);
	font-weight: 500;
}

/* Game meta strip in identity zone (Option A — design-system §19.2 Module 2).
 * Single-row compact strip below .matchup-row; items separated by mid-dots.
 * Renders on all completed-game tabs. Suppresses when no fields populated. */
.game-meta-strip {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 4px 0;
	padding: 14px 0 4px;
	margin-top: 18px;
	border-top: 1px solid var(--line-soft);
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: 0.06em;
	line-height: 1.4;
}
.game-meta-strip .meta-sep {
	color: var(--ink-4);
	padding: 0 10px;
}

/* Tab strip per design-system §20.5: muted register, ink-contrast
 * active state, no brand color, 1px line-soft baseline */
.cpt-tabs {
	display: flex;
	gap: 32px;
	border-bottom: 1px solid var(--line-soft);
	margin-top: 4px;
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	-ms-overflow-style: none;
}
.cpt-tabs::-webkit-scrollbar {
	display: none;
}
.cpt-tabs .tab {
	position: relative;
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 500;
	color: var(--ink-3);
	text-decoration: none;
	padding: 12px 0 13px;
	letter-spacing: 0;
	transition: color .12s;
	white-space: nowrap;
}
.cpt-tabs .tab:hover {
	color: var(--text);
	text-decoration: none;
}
.cpt-tabs .tab--active {
	color: var(--nd-navy);
	font-weight: 600;
}
.cpt-tabs .tab--active::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -1px;
	height: 3px;
	background: var(--nd-navy);
}

/* Module zone — per-view layout grid */
.cpt-layout {
	display: grid;
	/* Column gap unified with the article `.layout` grid (was 56px) so the
	 * content↔rail gutter matches sitewide — unified rail shell 2026-05-30.
	 * On `--full` (single-column) views this is an inert row-gap. */
	gap: var(--rail-col-gap);
	padding: 36px 0 8px;
}
.cpt-layout--rail {
	/* Rail width unified with the article grid (was 320px). */
	grid-template-columns: minmax(0, 1fr) var(--rail-w);
}
.cpt-layout--full {
	grid-template-columns: minmax(0, 1fr);
}
.cpt-layout .cpt-content {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 44px;
}
.cpt-layout .cpt-rail {
	display: flex;
	flex-direction: column;
	/* Stacked-module gap unified with the article `.rail` (was 32px). */
	gap: var(--rail-gap);
}

/* Unified rail head — when a `.cpt-module` (the layout-aware cross-link region)
 * renders INSIDE the rail, its `.cpt-module__label` adopts the canonical
 * gold-underline `.rail-section-head` treatment so every rail across the site
 * shares one heading chrome (decision 2026-05-30; matches the recruiting
 * `.rail-head` and the article `.rail-section-head .title`). The mono
 * micro-label register is preserved for the SAME partial's full-width footer
 * use, which is scoped to `.cpt-layout .cpt-content .cpt-module__label` and is
 * unaffected by this more-specific rail-context rule. */
.cpt-rail .cpt-module__label {
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--nd-navy);
	padding-bottom: 10px;
	border-bottom: 2px solid var(--nd-gold);
	margin: 0 0 14px;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 10px;
}

/* "Games vs [opponent]" matchup-history rail module (template-parts/cpt/game/
 * matchup-history.php) — compact mono rows under the shared .rail-section head:
 * season · vs/at · W/L · score, each row a link to that game. */
.rail-matchups .matchup-list {
	list-style: none;
	margin: 0;
	padding: 0;
}
.rail-matchups .matchup-item + .matchup-item {
	border-top: 1px solid var(--line-soft);
}
.rail-matchups .matchup-item a {
	display: flex;
	align-items: baseline;
	gap: 8px;
	padding: 8px 0;
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--text);
	text-decoration: none;
}
.rail-matchups .matchup-item a:hover .mh-score,
.rail-matchups .matchup-item a:hover .mh-season {
	color: var(--accent-hover, var(--nd-navy));
}
/* Pre-cutoff meetings render as a static <a> with no href (not exposed) —
   strip the link affordance so they don't read as clickable. */
.rail-matchups .matchup-item--static a {
	cursor: default;
}
.rail-matchups .matchup-item--static a:hover .mh-score,
.rail-matchups .matchup-item--static a:hover .mh-season {
	color: inherit;
}
.rail-matchups .mh-season {
	font-weight: 700;
	color: var(--nd-navy);
	min-width: 3em;
}
.rail-matchups .mh-where {
	color: var(--ink-3);
	text-transform: lowercase;
}
.rail-matchups .mh-result {
	font-weight: 700;
}
.rail-matchups .mh-result--w { color: var(--nd-green); }
.rail-matchups .mh-result--l { color: var(--danger); }
.rail-matchups .mh-result--t,
.rail-matchups .mh-result--upcoming { color: var(--ink-3); }
.rail-matchups .mh-score {
	margin-left: auto;
	color: var(--ink-2);
}

/* Mobile collapse — rail-layout views drop the rail under the content */
@media (max-width: 900px) {
	.cpt-layout--rail {
		grid-template-columns: minmax(0, 1fr);
	}
	.matchup-row {
		grid-template-columns: 1fr;
		gap: 18px;
		justify-items: center;
	}
	.matchup-row .team--home,
	.matchup-row .team--away {
		justify-content: center;
	}
	.matchup-row .team--home .team-text,
	.matchup-row .team--away .team-text {
		align-items: center;
		text-align: center;
	}
}

/* ======================================================================
 * Game CPT comp-driven module CSS.
 *
 * Scoped to `.cpt-layout` — applies to every completed-game tab (Recap /
 * Team Stats / Advanced / Box Score). Original scope was Recap-only
 * (`.cpt-layout--view-recap`); widened 2026-05-10 per Frank's call to
 * bring the deep-data tabs into comp register alongside Recap.
 *
 * Modules go flush with the `.cpt-content` 44px gap (no dashed border,
 * no padding on the wrapper). `.cpt-module__label` headers inherit the
 * same comp `.micro-label` mono register. Recap-specific module markup
 * (series-history, recap-team-stats, recap-advanced, top-performers,
 * etc.) layers comp-driven typography and grids on top.
 *
 * Preview-state pages render against the old `.layout` wrapper (not
 * `.cpt-layout`), so this scope doesn't apply to them — preview keeps
 * the v1 rough render path unchanged.
 * ====================================================================== */

/* Flush content register — strip rough dashed border / padding for Recap */
.cpt-layout .cpt-content .cpt-module {
	border: 0;
	padding: 0;
	margin-block: 0;
}
.cpt-layout .cpt-content .cpt-module__label,
.cpt-layout .cpt-content .micro-label {
	display: block;
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
	margin: 0 0 16px;
}
/* When `.cpt-module__label` is used as a sub-section header INSIDE
 * `.cpt-module__body` (the Series Records sub-sections — Recent Meetings,
 * Rivalry Snapshot — and any other module that gets multiple primary
 * dividers), it needs breathing room above the preceding content. The
 * module-level label outside the body keeps margin-top: 0 from the rule
 * above. One rule covers every template; no per-template modifiers. */
.cpt-layout .cpt-content .cpt-module__body .cpt-module__label {
	margin-top: 32px;
}
.cpt-layout .cpt-content .module-head-row {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	margin-bottom: 16px;
	gap: 16px;
}
.cpt-layout .cpt-content .module-head-row .micro-label,
.cpt-layout .cpt-content .module-head-row .cpt-module__label {
	margin-bottom: 0;
}
.cpt-layout .cpt-content .full-link {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-green);
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}
.cpt-layout .cpt-content .full-link:hover {
	color: var(--nd-green-hover);
}

/* Series History */
.series-tally {
	display: grid;
	grid-template-columns: auto 1fr auto;
	gap: 28px;
	align-items: center;
	padding: 18px 0 26px;
	border-bottom: 1px solid var(--line-soft);
	margin-bottom: 14px;
}
.series-mark {
	width: 56px;
	height: 56px;
	object-fit: contain;
}
.series-mark.opp {
	opacity: 0.55;
}
.tally-text {
	text-align: center;
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.tally-frame {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}
.tally-record {
	font-family: var(--font-mono);
	font-size: 38px;
	font-weight: 600;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.015em;
	line-height: 1;
}
/* `.tally--medium` removed 2026-06-07 — series-tally.php (its only consumer)
 * moved to the rail and now sizes via `.rail-series` in game.css. The
 * `tally--heavy` / base variants stay (series-history.php still uses them). */
.cpt-module--series.tally--restrained .tally-record {
	font-size: 18px;
	font-family: var(--font-sans);
	font-weight: 600;
}
.cpt-module--series.tally--restrained .tally-frame {
	font-size: 10px;
	letter-spacing: 0.14em;
}
.cpt-module--series.tally--restrained .series-tally {
	grid-template-columns: 1fr;
	padding: 12px 0 18px;
}
.cpt-module--series.tally--restrained .series-mark { display: none; }

.series-meetings {
	list-style: none;
	margin: 0;
	padding: 0;
}
.series-meetings > li > a {
	display: grid;
	grid-template-columns: 26px 56px 1fr auto;
	gap: 18px;
	align-items: center;
	padding: 13px 0;
	border-bottom: 1px solid var(--line-soft);
	text-decoration: none;
	color: var(--text);
	transition: background .12s;
}
.series-meetings > li:last-child > a {
	border-bottom: 0;
}
.wl-tag {
	width: 22px;
	height: 22px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 700;
	border-radius: var(--radius-chip);
	color: #fff;
	letter-spacing: 0;
}
.wl-tag--win { background: var(--nd-green); }
.wl-tag--loss { background: var(--danger); }
.wl-tag--tie { background: var(--ink-3); }
.series-meetings .year {
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--ink-3);
	font-weight: 600;
	letter-spacing: 0.04em;
}
.series-meetings .score-line {
	font-family: var(--font-sans);
	font-size: 14px;
	color: var(--text);
	font-weight: 500;
}
.series-meetings .score-line .num {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	margin: 0 4px;
	font-weight: 600;
}
.series-meetings .score-line .venue {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-4);
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
	margin-left: 10px;
}
.series-meetings .arrow {
	color: var(--ink-3);
	font-family: var(--font-sans);
	font-size: 16px;
}
.series-meetings li a:hover {
	background: color-mix(in srgb, var(--nd-navy) 3%, transparent);
	text-decoration: none;
}
.series-meetings li a:hover .arrow { color: var(--nd-navy); }
.series-meetings li a:hover .score-line { color: var(--nd-navy); }
/* Unlinked meetings (no published game post, or pre-cutoff games that aren't
   exposed) render as an <a> without href — drop the hover tint and the "go to"
   arrow so the row doesn't read as clickable. */
.series-meetings > li > a:not([href]) { cursor: default; }
.series-meetings > li > a:not([href]) .arrow { visibility: hidden; }
.series-meetings li a:not([href]):hover { background: transparent; }
.series-meetings li a:not([href]):hover .arrow,
.series-meetings li a:not([href]):hover .score-line { color: inherit; }
.series-footer {
	display: inline-block;
	margin-top: 16px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-green);
	font-weight: 600;
	text-decoration: none;
}
.series-footer:hover {
	color: var(--nd-green-hover);
	text-decoration: none;
}

/* Compare table (curated team stats + advanced) */
/* Compare-table — surface-specific cell decoration only. Base chrome
 * (width, border-collapse, font-family, generic thead/tbody) is provided
 * by `.data-table` in style.css. Phase 3a (2026-05-22) removed the
 * duplicate base block; what remains is the cell decoration unique to
 * compare tables: serif team-h cells, mono home-val/away-val numeric
 * cells, sans stat-label cells, leader-row background wash. The
 * stat-h cells (column 2 in compare tables — "Stat" / "Metric") use a
 * centered alignment that overrides `.data-table thead th { text-align:
 * left }`; team-h cells override font-family + casing. */
.compare-table thead th {
	text-align: center;
}
.compare-table thead th.team-h {
	font-family: var(--font-serif);
	font-size: 14px;
	font-weight: 700;
	color: var(--nd-navy);
	text-transform: none;
	letter-spacing: 0;
}
.compare-table thead th.team-h.right { text-align: right; }
.compare-table thead th.team-h.left { text-align: left; }
.compare-table .home-val,
.compare-table .away-val {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	font-size: 15px;
	color: var(--text);
	width: 28%;
}
.compare-table .home-val { text-align: right; padding-right: 28px; }
.compare-table .away-val { text-align: left; padding-left: 28px; }
.compare-table .stat-label {
	text-align: center;
	font-family: var(--font-sans);
	font-size: 13px;
	color: var(--ink-3);
	font-weight: 500;
}
.compare-table .leader {
	background-color: var(--winner-bg);
	color: var(--winner-fg);
	font-weight: 700;
}
/* Triangle ▸ / ◂ pseudos removed 2026-05-21 — `--winner-bg` (pale navy
 * wash) now carries the leader signal on its own. Decision lives in
 * docs/decisions.md 2026-05-21 "Game CPT design pass". */

/* Top Performers */
.performers-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 16px;
}
.performer {
	padding: 16px 18px;
	border: 1px solid var(--line);
	display: flex;
	flex-direction: column;
	gap: 8px;
	transition: border-color .12s;
}
.performer:hover { border-color: var(--nd-navy); }
.performer .perf-cat {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
}
.performer .perf-name {
	font-family: var(--font-serif);
	font-size: 19px;
	font-weight: 700;
	color: var(--nd-navy);
	text-decoration: none;
	line-height: 1.15;
	letter-spacing: -0.005em;
}
.performer a.perf-name:hover {
	color: var(--accent-hover);
	text-decoration: none;
}
.performer .perf-stats {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	font-family: var(--font-sans);
	font-size: 12px;
	color: var(--ink-3);
	margin-top: 2px;
}
.performer .perf-stats span { white-space: nowrap; }
.performer .perf-stats .stat-sep {
	color: var(--ink-4);
	font-size: 11px;
	padding: 0 2px;
}
.performer .perf-stats strong {
	font-family: var(--font-mono);
	font-weight: 700;
	color: var(--text);
	font-variant-numeric: tabular-nums;
	margin-right: 3px;
	font-size: 13px;
}

@media (max-width: 900px) {
	.performers-grid { grid-template-columns: 1fr; }
}

/* ── Comp register for existing-module markup (all completed-game tabs) ──
 * The modules below were rewritten 2026-05-10 to comp markup. CSS is
 * scoped to .cpt-layout so all four tab views (Recap / Team Stats /
 * Advanced / Box Score) share the comp's .stats-table / .meta-grid /
 * etc. register. Preview-state pages still render against the v1 rough
 * .stats-table rules from elsewhere in this file.
 * ─────────────────────────────────────────────────────────────────── */

/* Comp's .stats-table base (used by Line Score and shared by curated
 * compare-tables). The global rough .stats-table rules are still in
 * effect on other tabs — these scoped rules win on Recap.
 *
 * Explicitly zeroing the outer table borders that the rough rule sets
 * (border-top + border-bottom on .stats-table) and forcing transparent
 * row backgrounds so customizer-stored zebra striping or other
 * accumulated table bg rules can't leak through. */
.cpt-layout .stats-table {
	width: 100%;
	border-collapse: collapse;
	border-top: 0;
	border-bottom: 0;
	font-family: var(--font-sans);
	font-size: 14px;
	background: transparent;
}
.cpt-layout .stats-table tbody tr,
.cpt-layout .stats-table tbody td,
.cpt-layout .stats-table tbody th,
.cpt-layout .compare-table tbody tr,
.cpt-layout .compare-table tbody td,
.cpt-layout .compare-table tbody th,
.cpt-layout .elo-table tbody tr,
.cpt-layout .elo-table tbody td {
	background: transparent;
}
.cpt-layout .stats-table th {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
	text-align: left;
	padding: 10px 12px;
	border-bottom: 1px solid var(--line);
}
.cpt-layout .stats-table th.num { text-align: right; }
.cpt-layout .stats-table th.center { text-align: center; }
.cpt-layout .stats-table th.team-h {
	font-family: var(--font-serif);
	font-size: 15px;
	font-weight: 700;
	color: var(--nd-navy);
	text-transform: none;
	letter-spacing: 0;
}
.cpt-layout .stats-table th.team-h.right { text-align: right; }
.cpt-layout .stats-table td {
	padding: 11px 12px;
	border-bottom: 1px solid var(--line-soft);
	color: var(--text);
}
.cpt-layout .stats-table tbody tr:last-child td { border-bottom: 0; }
.cpt-layout .stats-table .num {
	font-family: var(--font-mono);
	text-align: right;
	font-variant-numeric: tabular-nums;
	color: var(--text);
}
.cpt-layout .stats-table td:first-child { padding-left: 0; }
.cpt-layout .stats-table td:last-child { padding-right: 0; }
.cpt-layout .stats-table th:first-child { padding-left: 0; }
.cpt-layout .stats-table th:last-child { padding-right: 0; }

/* Line score */
.cpt-layout .line-score thead th { font-size: 11px; }
.cpt-layout .line-score thead th:not(.team-h):not(:first-child) {
	text-align: center;
	width: 11%;
}
.cpt-layout .line-score tbody .num { text-align: center; }
.cpt-layout .line-score .team-cell {
	display: flex;
	align-items: center;
	gap: 12px;
	font-family: var(--font-sans);
	font-size: 15px;
	font-weight: 600;
	color: var(--nd-navy);
	min-width: 180px;
}
.cpt-layout .line-score .team-cell img {
	width: 26px;
	height: 26px;
	object-fit: contain;
}
.cpt-layout .line-score .final-col {
	font-weight: 700;
	color: var(--nd-navy);
	padding-left: 18px;
	border-left: 1px solid var(--line-soft);
}
.cpt-layout .line-score .winner-row .final-col { color: var(--nd-navy); }

/* Game Context meta-grid (comp markup with .meta-row divs) */
.cpt-layout .meta-grid {
	display: flex;
	flex-direction: column;
	margin: 0;
}
.cpt-layout .meta-grid .meta-row {
	display: grid;
	grid-template-columns: 200px 1fr;
	gap: 24px;
	padding: 11px 0;
	border-bottom: 1px solid var(--line-soft);
}
.cpt-layout .meta-grid .meta-row:first-child { padding-top: 0; }
.cpt-layout .meta-grid .meta-row:last-child { border-bottom: 0; padding-bottom: 0; }
.cpt-layout .meta-grid dt {
	font-family: var(--font-sans);
	font-size: 13px;
	color: var(--ink-3);
	font-weight: 500;
	margin: 0;
}
.cpt-layout .meta-grid dd {
	margin: 0;
	font-family: var(--font-sans);
	font-size: 14px;
	color: var(--text);
	font-weight: 500;
}
.cpt-layout .meta-grid dd a { color: var(--nd-green); }
.cpt-layout .meta-grid dd a:hover { color: var(--nd-green-hover); }

/* Betting Lines */
.cpt-layout .betting-table .open {
	display: inline-block;
	margin-left: 6px;
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-4);
	font-weight: 400;
}
.cpt-layout .betting-table .provider-cell {
	font-family: var(--font-sans);
	font-weight: 600;
	color: var(--nd-navy);
	font-size: 13px;
}
.cpt-layout .betting-table .num strong {
	font-weight: 600;
	color: var(--text);
}

/* Weather */
.cpt-layout .weather-condition {
	font-family: var(--font-serif);
	font-size: 26px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0 0 18px;
	letter-spacing: -0.012em;
	display: flex;
	align-items: baseline;
	gap: 12px;
	flex-wrap: wrap;
}
.cpt-layout .weather-condition .impact {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ink-3);
}
.cpt-layout .weather-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
	gap: 0;
	margin: 0;
	border-top: 1px solid var(--line);
	border-bottom: 1px solid var(--line);
}
.cpt-layout .weather-grid > div {
	padding: 14px 16px;
	border-right: 1px solid var(--line-soft);
	display: flex;
	flex-direction: column;
	gap: 5px;
}
.cpt-layout .weather-grid > div:last-child { border-right: 0; }
.cpt-layout .weather-grid dt {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}
.cpt-layout .weather-grid dd {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 17px;
	font-weight: 600;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	letter-spacing: -0.01em;
}

/* ELO + Win Prob table */
/* `.elo-table` opts into canonical `.data-table` 2026-05-21 — the
 * width / border-collapse / font-family / thead / tbody-cell base
 * inherits from style.css §"Canonical body cell treatment" and
 * §"Canonical header row." This block now only carries elo-specific
 * cell decorations (team-cell, delta--pos/neg, win-prob ink). */
.cpt-layout .elo-table {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--font-sans);
	font-size: 14px;
}
/* thead / tbody base now inherits from canonical .data-table — only
 * elo-specific alignment lives here: every numeric column right-aligned
 * EXCEPT the first (team-name) cell which stays left-aligned. */
.cpt-layout .elo-table thead th { text-align: right; }
.cpt-layout .elo-table thead th:first-child { text-align: left; }
.cpt-layout .elo-table .team-cell {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: var(--font-sans);
	font-weight: 600;
	color: var(--nd-navy);
	font-size: 14px;
}
.cpt-layout .elo-table .team-cell img {
	width: 22px;
	height: 22px;
	object-fit: contain;
}
.cpt-layout .elo-table .num {
	font-family: var(--font-mono);
	text-align: right;
	font-variant-numeric: tabular-nums;
	font-size: 14px;
	font-weight: 600;
}
.cpt-layout .elo-table .delta--pos { color: var(--nd-green); }
.cpt-layout .elo-table .delta--neg { color: var(--danger); }
.cpt-layout .elo-table .win-prob {
	font-family: var(--font-mono);
	text-align: right;
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	color: var(--nd-navy);
}

/* Latest Coverage — single featured article.
 * Replaced the 3-up `.coverage-grid` + `.coverage-card` layout on 2026-05-11
 * per decisions.md entry "Recap Latest Coverage: featured-article render +
 * reposition". Single article, larger image, editorial headline register,
 * optional deck, byline meta + "View all coverage →" link below. */
.cpt-layout .coverage-featured {
	display: flex;
	flex-direction: column;
	gap: 14px;
	text-decoration: none;
	color: inherit;
}
.cpt-layout .coverage-featured__image {
	display: block;
	aspect-ratio: 16 / 9;
	width: 100%;
	background-size: cover;
	background-position: center;
	background-color: var(--bg-muted);
	border: 1px solid var(--line-soft);
}
.cpt-layout .coverage-featured__image--placeholder {
	background-image:
		repeating-linear-gradient(45deg,
			color-mix(in srgb, var(--ink-4) 18%, transparent) 0 6px,
			transparent 6px 14px);
}
.cpt-layout .coverage-featured__kicker {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
	margin-top: 4px;
}
.cpt-layout .coverage-featured__title {
	font-family: var(--font-serif);
	font-size: clamp(22px, 2.2vw, 28px);
	font-weight: 700;
	color: var(--nd-navy);
	line-height: 1.18;
	letter-spacing: -0.012em;
}
.cpt-layout .coverage-featured__deck {
	font-family: var(--font-serif);
	font-size: 16px;
	font-weight: 400;
	color: var(--ink-2);
	line-height: 1.5;
	letter-spacing: -0.002em;
	max-width: 68ch;
}
.cpt-layout .coverage-featured__byline {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: 0.1em;
	text-transform: uppercase;
}
.cpt-layout .coverage-featured:hover .coverage-featured__title { color: var(--accent-hover); }
.cpt-layout .coverage-more {
	display: inline-block;
	margin-top: 18px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-green);
	font-weight: 700;
	text-decoration: none;
}
.cpt-layout .coverage-more:hover { color: var(--nd-green-hover); }

/* Next Game sidebar card (template-parts/sidebar/next-game.php) */
.next-game-card {
	display: flex;
	flex-direction: column;
	gap: var(--card-gap);
}
/* .next-game-card__label eyebrow → canonical .micro-label--heavy (2026-06-06). */
.next-game-card__inner {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 14px 16px;
	border: 1px solid var(--line);
	border-radius: var(--r-card);
	text-decoration: none;
	color: inherit;
	transition: border-color .12s;
}
.next-game-card__inner:hover {
	border-color: var(--nd-navy);
	text-decoration: none;
}
.next-game-card__logo {
	width: 36px;
	height: 36px;
	object-fit: contain;
	flex-shrink: 0;
}
.next-game-card__meta {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 3px;
}
.next-game-card__opp {
	font-family: var(--font-sans);
	font-size: 15px;
	font-weight: 700;
	color: var(--nd-navy);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.next-game-card__detail {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: 0.04em;
}
.next-game-sep {
	color: var(--ink-4);
	padding: 0 4px;
}
.next-game-card__arrow {
	color: var(--ink-4);
	font-size: 14px;
	flex-shrink: 0;
	transition: color .12s;
}
.next-game-card__inner:hover .next-game-card__arrow {
	color: var(--nd-navy);
}

@media (max-width: 900px) {
	.cpt-layout .meta-grid .meta-row { grid-template-columns: 1fr; gap: 4px; }
	.cpt-layout .line-score .team-cell { min-width: 0; }
	.cpt-layout .line-score .team-cell .full-name { display: none; }
}

/* ======================================================================
 * Opponent CPT — rough-template baseline (docs/cpt-structural-layouts.md
 * §6, §5.9). Module wrapper / Claude-table register is inherited from the
 * shared `.cpt-layout .cpt-content .cpt-module` rules above; what follows
 * is only the opponent-specific structure (identity strip, log filters,
 * programs-table rank cells). No design polish — that iterates from the
 * rendered output.
 * ==================================================================== */

/* --- Opponent CPT series header — `.matchup-header--series`.
 * Built against references/opponent-cpt/UHND Opponent Header - USC.html:
 * a literal structural sibling of the Game CPT matchup header. It reuses
 * the .matchup-header / .matchup-row / .team* / .team-logo / .team-name /
 * .score-col / .scoreline / .dash / .game-meta-row / .meta-* vocabulary
 * declared above for the Game CPT; what follows is only the `--series`
 * deltas — the centre column carries the all-time series record (ND POV,
 * W–L–T) instead of a single-game score, the proportional lead bar runs
 * full content width as the header's base, and the bottom meta row is an
 * equal-column strip (Total / First / Last / Next meeting). The opponent's
 * CFBD `team.color` arrives as `--opp-color` on `.opp-identity` and tints
 * only the right side of the lead bar. */

/* Centre column — streak pill stacked above the record numerals. */
.matchup-header--series .score-col {
	gap: 14px;
}

/* Record numerals: ND-POV W–L–T, the page's largest type. Three figures +
 * two dashes, so the dash gap is tighter than the Game CPT's two-figure
 * scoreline. No loser-dim — a series record isn't a single-game win/loss. */
.matchup-header--series .scoreline {
	gap: 6px;
}
/* Series-record numerals are 20% smaller than the Game CPT scoreline —
 * three figures + two dashes need to read as the dominant feature
 * without crowding the team blocks beside them. */
.matchup-header--series .score {
	color: var(--nd-navy);
	font-size: clamp(45px, 5.1vw, 64px);
}
.matchup-header--series .scoreline .dash {
	font-size: clamp(27px, 3vw, 38px);
}

/* Full-content-width proportional lead bar — the visual base of the
 * header. ND gold from the left, opponent's CFBD team.color from the
 * right, neutral band where they meet. */
.matchup-header--series .lead-bar {
	position: relative;
	width: 100%;
	height: 10px;
	margin-top: 26px;
	overflow: hidden;
	border-radius: 2px;
	background: var(--bg-muted);
}
.matchup-header--series .lead-bar .fill {
	position: absolute;
	top: 0;
	bottom: 0;
}
.matchup-header--series .lead-bar .fill--nd  { background: var(--nd-gold); }
.matchup-header--series .lead-bar .fill--tie { background: color-mix(in srgb, var(--ink-3) 55%, var(--bg-muted)); }
.matchup-header--series .lead-bar .fill--opp { background: var(--opp-color, color-mix(in srgb, var(--nd-navy) 78%, var(--bg))); }

/* Bottom meta row — equal-width columns spanning the full content width,
 * separated by subtle vertical hairlines (no rules on the outer edges).
 * `flex: 1` per item means a suppressed "Next Meeting" column leaves the
 * remaining columns equal-width rather than three-quarters-width. */
.matchup-header--series .game-meta-row {
	display: flex;
	flex-wrap: nowrap;
	gap: 0;
	margin-top: 20px;
}
.matchup-header--series .game-meta-row .meta-item-block {
	flex: 1 1 0;
	min-width: 0;
	padding: 0 24px;
	/* Center each cell's label + value horizontally within its track,
	 * matching the centered three-column matchup row above (2026-05-21). */
	align-items: center;
	text-align: center;
}
.matchup-header--series .game-meta-row .meta-item-block:first-child {
	padding-left: 0;
}
.matchup-header--series .game-meta-row .meta-item-block:last-child {
	padding-right: 0;
}
.matchup-header--series .game-meta-row .meta-item-block + .meta-item-block {
	border-left: 1px solid var(--line-soft);
}
.matchup-header--series .game-meta-row .meta-value {
	overflow-wrap: anywhere;
}
.matchup-header--series .game-meta-row .meta-link {
	color: var(--nd-green);
	font-weight: 600;
	text-decoration: none;
}
.matchup-header--series .game-meta-row .meta-link:hover {
	text-decoration: underline;
}

/* Mobile — the base .matchup-row collapses to a single centred column at
 * ≤900px (Game CPT rule above); the meta row wraps two-per-row, then one.
 * Column borders drop on wrap so a column at the start of a wrapped row
 * doesn't get a border on the container's left edge. */
@media (max-width: 900px) {
	.matchup-header--series .lead-bar { margin-top: 22px; }
	.matchup-header--series .game-meta-row { flex-wrap: wrap; gap: 18px 0; }
	.matchup-header--series .game-meta-row .meta-item-block {
		flex: 1 1 calc(50% - 14px);
		padding: 0 14px;
	}
	.matchup-header--series .game-meta-row .meta-item-block:first-child,
	.matchup-header--series .game-meta-row .meta-item-block:last-child {
		padding: 0 14px;
	}
	.matchup-header--series .game-meta-row .meta-item-block + .meta-item-block {
		border-left: 0;
	}
}
@media (max-width: 520px) {
	.matchup-header--series .game-meta-row .meta-item-block { flex-basis: 100%; }
}

/* --- "ND won 3 straight" leads label — replaces the prior
 * `.status-pill--streak` chip per the 2026-05-21 navy-band comp.
 * Mono uppercase navy on cream; ink-flipped white inside the band
 * by the [data-treatment="band-tabs"] block below. The label is a
 * tight headline above the W-L-T numerals, not a separate visual. */
.matchup-header--series .leads-label {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--nd-navy);
}

/* --- Navy band treatment for the Opponent CPT identity zone --------- *
 * Locked 2026-05-21 against
 * `references/opponent-cpt/UHND Opponent - All Meetings _Navy Band_ -
 * standalone.html`. Activated by `data-treatment="band-tabs"` on
 * `.cpt-identity` — the partial sets it unconditionally so every
 * opponent profile renders against the navy band register.
 *
 * The ::before pseudo paints a full-viewport-width navy background
 * behind the matchup-header only. The cpt-tabs strip sits OUTSIDE the
 * pseudo's z-index, so it stays on cream below the band — mirrors the
 * Game CPT's split-treatment pattern.
 *
 * Pseudo geometry: `.page` (parent ancestor) centers itself on the
 * viewport via `margin: 0 auto`, so `left: 50%; transform: translateX(-50%);
 * width: 100vw` on the absolutely-positioned pseudo starts the navy band
 * at viewport x=0 regardless of how wide the page wrapper is. */
/* The 100vw ::before below intentionally overflows .page to bleed
 * edge-to-edge, but `100vw` includes the vertical-scrollbar gutter
 * (~15px on Windows) — so the pseudo overhangs the viewport's *visible*
 * width and the browser surfaces a horizontal scrollbar on the whole
 * document. Clip overflow at the body level (the only ancestor whose
 * width matches the visible viewport) so the bleed stays visual without
 * producing scroll. Scoped via `:has()` to opponent profile pages only
 * — we don't want to silently swallow horizontal overflow site-wide.
 *
 * Proper fix: migrate this surface to the Game CPT's `.game-band`
 * sibling-block pattern (see game.css §"Navy band"), which fills the
 * viewport via a normal background instead of a 100vw pseudo. Tracked
 * for follow-up. */
body:has(.cpt-identity[data-treatment="band-tabs"]) {
	overflow-x: clip;
}

.cpt-identity[data-treatment="band-tabs"] {
	margin-top: 18px;
}
.cpt-identity[data-treatment="band-tabs"] .matchup-header {
	position: relative;
	isolation: isolate;
	padding: 34px 0 30px;
	margin-bottom: 0;
}
.cpt-identity[data-treatment="band-tabs"] .matchup-header::before {
	content: "";
	position: absolute;
	inset: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 100vw;
	background: var(--nd-navy);
	z-index: -1;
}
/* Subtle gold-tinted hairline along the top of the band. */
.cpt-identity[data-treatment="band-tabs"] .matchup-header::after {
	content: "";
	position: absolute;
	top: 0;
	left: 50%;
	width: 100vw;
	height: 1px;
	transform: translateX(-50%);
	background: linear-gradient(90deg,
		transparent,
		color-mix(in srgb, var(--nd-gold) 32%, transparent) 20%,
		color-mix(in srgb, var(--nd-gold) 32%, transparent) 80%,
		transparent);
	z-index: 0;
}

/* Ink flips — text content reads on the navy band. */
.cpt-identity[data-treatment="band-tabs"] .matchup-header,
.cpt-identity[data-treatment="band-tabs"] .team-name,
.cpt-identity[data-treatment="band-tabs"] .leads-label,
.cpt-identity[data-treatment="band-tabs"] .score {
	color: #fff;
}
.cpt-identity[data-treatment="band-tabs"] .scoreline .dash {
	color: rgba(255, 255, 255, 0.3); /* Between --video-band-ink-3 (0.58) and -ink-4 (0.4) — intentionally faint scoreline separator. Off-ramp by design. */
}
.cpt-identity[data-treatment="band-tabs"] .team-record {
	color: var(--video-band-ink-3);
}
.cpt-identity[data-treatment="band-tabs"] .lead-bar {
	background: var(--video-band-line);
}
.cpt-identity[data-treatment="band-tabs"] .lead-bar .fill--tie {
	background: var(--video-band-ink-4);
}
.cpt-identity[data-treatment="band-tabs"] .game-meta-row {
	border-top-color: var(--video-band-line-strong);
}
.cpt-identity[data-treatment="band-tabs"] .game-meta-row .meta-item-block + .meta-item-block {
	border-left-color: var(--video-band-line-strong);
}
.cpt-identity[data-treatment="band-tabs"] .meta-label {
	color: var(--video-band-ink-3);
}
.cpt-identity[data-treatment="band-tabs"] .meta-value {
	color: #fff;
}
.cpt-identity[data-treatment="band-tabs"] .meta-value a,
.cpt-identity[data-treatment="band-tabs"] .meta-link {
	color: var(--nd-gold);
}
.cpt-identity[data-treatment="band-tabs"] .meta-link:hover {
	color: color-mix(in srgb, var(--nd-gold) 70%, #fff);
	text-decoration: none;
}
/* Slightly looser matchup-row gap inside the band so the centre column
 * doesn't crowd the team blocks at the band's wider visual register. */
.cpt-identity[data-treatment="band-tabs"] .matchup-row {
	gap: 40px;
}
/* Tabs sit on cream below the band — keep the .cpt-tabs strip out of
 * the dark-ink scope by reasserting its native ink. The pseudo only
 * covers .matchup-header, but the parent .cpt-identity's color
 * inheritance could otherwise drag tabs into white text. */
.cpt-identity[data-treatment="band-tabs"] .cpt-tabs {
	color: var(--ink-3);
}

/* Admin-only callout (missing rivalry article / essay) — dashed border so
 * it reads as an editorial to-do, never as a public element. */
.cpt-admin-callout {
	margin: 8px 0 0;
	padding: 8px 12px;
	border: 1px dashed var(--line-strong);
	font-family: var(--font-mono);
	font-size: var(--type-micro-size);
	letter-spacing: 0.02em;
	color: var(--ink-muted);
}
.cpt-module--admin-empty .cpt-admin-callout { margin-top: 12px; }

/* --- Module 2: rivalry hero (Round 1 polish 2026-05-12) ------------- */
.cpt-module--rivalry-hero {
	margin-block: 0 clamp(20px, 3vw, 32px);
}
.cpt-module--rivalry-hero .rivalry-hero__link {
	display: block;
	position: relative;
	color: inherit;
	text-decoration: none;
}
.cpt-module--rivalry-hero .rivalry-hero__media {
	margin: 0;
	position: relative;
	overflow: hidden;
	background: var(--bg-sunk);
}
.cpt-module--rivalry-hero .rivalry-hero__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: var(--rh-focal, center);
}
/* Title + CTA rules are scoped under .cpt-module--rivalry-hero so they
 * outrank Jannah's `.wf-active h2 { font-family: Raleway; }` rule that
 * would otherwise override the headline to a sans face. */
.cpt-module--rivalry-hero .rivalry-hero__eyebrow {
	display: block;
	font-family: var(--font-mono);
	font-size: var(--type-micro-size);
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
}
.cpt-module--rivalry-hero .rivalry-hero__title {
	margin: 6px 0 0;
	font-family: var(--font-serif);
	/* Capped tighter than --type-article-headline-size so it scales down
	 * inside the rivalry card instead of overflowing the image bounds. */
	font-size: clamp(1.75rem, 4vw, 3rem);
	line-height: 1.06;
	letter-spacing: -0.015em;
	font-weight: 700;
}
.cpt-module--rivalry-hero .rivalry-hero__cta {
	display: inline-block;
	margin-top: 14px;
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0;
}
/* Deck — same register as the Game CPT Latest Coverage deck
 * (.cpt-layout .coverage-featured__deck) so the rivalry hero and Latest
 * Coverage read as the same featured-article-card primitive. The deck
 * runs the full content-column width (matches the hero image above it);
 * no max-width cap. */
.cpt-module--rivalry-hero .rivalry-hero__deck {
	margin: 10px 0 0;
	font-family: var(--font-serif);
	font-size: 16px;
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: -0.002em;
	color: var(--ink-2);
}
/* Read-more text link below the deck — a discrete text CTA so the deck
 * above isn't part of the card's click target. Site-link register (green)
 * to distinguish it from the navy in-overlay CTA. */
.cpt-module--rivalry-hero .rivalry-hero__readmore {
	display: inline-block;
	margin-top: 12px;
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 600;
	color: var(--nd-green);
	text-decoration: none;
}
.cpt-module--rivalry-hero .rivalry-hero__readmore:hover {
	color: var(--nd-green-hover);
	text-decoration: underline;
}
/* Below-figure blocks: `.rivalry-hero__content` carries the deck +
 * read-more (outside the card's click target); `.rivalry-hero__headline`
 * carries the standard-variant in-link headline group (eyebrow + title
 * + on-card CTA). Same spacing rule for both. */
.cpt-module--rivalry-hero .rivalry-hero__content,
.cpt-module--rivalry-hero .rivalry-hero__headline {
	margin-top: 16px;
}
/* Standard variant register (when the eyebrow + title sit in the content
 * block, not on the image). Overlay variant overrides these below. */
.cpt-module--rivalry-hero .rivalry-hero__eyebrow { color: var(--ink-muted); }
.cpt-module--rivalry-hero .rivalry-hero__title   { color: var(--ink); }
.cpt-module--rivalry-hero .rivalry-hero__cta     { color: var(--accent); }
.cpt-module--rivalry-hero .rivalry-hero__link:hover .rivalry-hero__title { color: var(--accent-hover); }

/* Overlay variant — cinematic 21:9 crop with the editorial overlay
 * (eyebrow + headline + CTA) anchored to the left and vertically centred
 * over the photo. A left-to-right gradient gives the headline a contrast
 * layer that holds whatever's behind it in the image. The text block is
 * capped to 55% of the card so the photo's subject stays clearly visible
 * on the right. The headline scales with the viewport via clamp() — long
 * titles are NOT truncated, they scale down. On sub-tablet widths the
 * overlay unstacks to a content block below the image. The deck, when
 * present, renders below the image in `.rivalry-hero__content`. */
.rivalry-hero--overlay .rivalry-hero__media { aspect-ratio: 21 / 9; }
.rivalry-hero--overlay .rivalry-hero__media::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(to right,
		rgba(0, 0, 0, 0.7),
		rgba(0, 0, 0, 0.3) 50%,
		transparent 70%);
	pointer-events: none;
}
.rivalry-hero--overlay .rivalry-hero__overlay {
	position: absolute;
	inset: 0;
	max-width: 55%;
	/* Tighter horizontal padding (was clamp(24, 4vw, 48)) — at the prior
	 * value the inner text width on a 840px content column was only
	 * ~366px, which forced 5 lines for a 66-char title. */
	padding: clamp(20px, 3vw, 32px) clamp(20px, 2.5vw, 28px);
	z-index: 1;
	color: #fff;
	display: flex;
	flex-direction: column;
	justify-content: center;
}
.rivalry-hero--overlay .rivalry-hero__overlay .rivalry-hero__eyebrow {
	color: rgba(255, 255, 255, 0.82);
}
.rivalry-hero--overlay .rivalry-hero__overlay .rivalry-hero__title {
	color: #fff;
	/* Lower floor and ceiling than every prior pass — 28-44px range.
	 * Combined with the tighter padding above, this targets ≤3 lines
	 * at desktop content widths and lets the CTA fit inside the figure
	 * (the prior 32-48px range pushed content past the 21:9 bounds and
	 * the figure's overflow:hidden clipped the CTA). */
	font-size: clamp(1.75rem, 3vw, 2.75rem);
	line-height: 1.05;
}
.rivalry-hero--overlay .rivalry-hero__overlay .rivalry-hero__cta {
	color: rgba(255, 255, 255, 0.94);
}
.rivalry-hero--overlay .rivalry-hero__link:hover .rivalry-hero__title,
.rivalry-hero--overlay .rivalry-hero__link:hover .rivalry-hero__cta {
	color: #fff;
}
.rivalry-hero--overlay .rivalry-hero__link:hover .rivalry-hero__cta {
	text-decoration: underline;
}
/* Sub-tablet — the overlay treatment runs out of room at narrow widths.
 * Drop the absolute positioning + gradient and let the content flow below
 * the image, recoloured back to the standard ink register. */
@media (max-width: 720px) {
	.rivalry-hero--overlay .rivalry-hero__media {
		aspect-ratio: auto;
		overflow: visible;
	}
	.rivalry-hero--overlay .rivalry-hero__media::after { display: none; }
	.rivalry-hero--overlay .rivalry-hero__img {
		height: auto;
		aspect-ratio: 16 / 9;
	}
	.rivalry-hero--overlay .rivalry-hero__overlay {
		position: static;
		inset: auto;
		display: block;
		max-width: none;
		padding: 0;
		margin-top: 16px;
		color: var(--ink);
	}
	.rivalry-hero--overlay .rivalry-hero__overlay .rivalry-hero__eyebrow { color: var(--ink-muted); }
	.rivalry-hero--overlay .rivalry-hero__overlay .rivalry-hero__title   {
		color: var(--ink);
		font-size: clamp(1.5rem, 5vw, 2.25rem);
	}
	.rivalry-hero--overlay .rivalry-hero__overlay .rivalry-hero__cta     { color: var(--accent); }
}

/* Standard variant — slightly less wide 16:7 crop, hairline frame; all
 * content lives in `.rivalry-hero__content` below the image. */
.rivalry-hero--standard .rivalry-hero__media {
	aspect-ratio: 16 / 7;
	border: 1px solid var(--line-soft);
}

/* --- Module 9: all-meetings log ------------------------------------ */
/* The row body reuses .schedule-row* / .status-pill / .schedule-filters*
 * primitives from style.css for structure, but the typographic hierarchy
 * for the all-meetings table is module-local (96 historical rows have a
 * different scannability goal than a 13-row season schedule). Three-tier
 * hierarchy per row:
 *
 *   PRIMARY (visual peak): the season year (left anchor — serif, the
 *     scannable spine for "what happened in 2023?" lookup) + the
 *     opponent name + the W/L result.
 *   SECONDARY (supporting):  the full date ("Oct 17, 2025") + venue.
 *   TERTIARY (connective):   "vs."/"at", "#20" rank prefix, FINAL pill,
 *     "Recap" chevron link. Only the FINAL pill keeps a small-caps
 *     treatment — every other tertiary element drops mono uppercase
 *     tracking and renders in sentence-case sans.
 *
 * Typeface decision: serif for the year column only; sans for everything
 * else. The schedule template's opponent name is also serif, but here
 * the opponent is constant on every row — visual emphasis must shift to
 * the year, so the opponent line is overridden to sans. */

.cpt-module--all-meetings .schedule-row__anchor {
	/* Year (right-aligned serif) | full date (left-aligned sans) |
	 * opponent | venue | result | bowl | action. align-items inherits
	 * from the schedule's base rule (center) — we previously set
	 * `baseline` which made the rows feel jittery against varying cell
	 * heights.
	 *
	 * Track sizing rationale (2026-05-22 retune):
	 *  - Opp is CONSTANT across all 96 rows ("at USC" / "vs. USC"), so
	 *    it doesn't need a 1.5fr lion's share. Dropped to 1.1fr.
	 *  - Venue now carries "Stadium · City, ST" (sync added venue_name +
	 *    venue_state today), so it needs the wider slot. Bumped to 2.3fr.
	 *  - Result locked to fixed 156px (was `auto`). Same lesson the
	 *    schedule template learned 2026-05-21: `auto` is content-sized
	 *    per-row and made the header label drift off the body column.
	 *    Matches `.schedule-row__anchor`'s 156px in style.css.  */
	grid-template-columns: 56px 124px minmax(0, 1.1fr) minmax(0, 2.3fr) 156px 72px 100px;
}

/* Table header row above the meetings list — mirrors the row grid above
 * so each label aligns over its column. The cell modifier classes
 * (`.num` on Year + Bowl) inherit from canonical row-head cell styling.
 * Added 2026-05-21. */
.cpt-module--all-meetings .opponent-log__head {
	grid-template-columns: 56px 124px minmax(0, 1.1fr) minmax(0, 2.3fr) 156px 72px 100px;
	gap: 16px;
	padding: 0 8px;
}
/* Mirror the year column's right-align so the "Year" label lands over
 * the right-aligned numeral below. */
.cpt-module--all-meetings .opponent-log__head > .row-head__cell:first-child {
	text-align: right;
	padding-right: 12px;
}

/* Result column — left-align in this module (the schedule's base rule
 * uses `justify-content: flex-end` so the score column reads as a
 * right-edge numeric anchor, but here the Bowl + Action columns sit to
 * its right, so right-aligning Result strands it visually mid-row and
 * reads odd). Header label gets matching left-align via the absence of
 * `.num` on its row-head__cell (set in the PHP markup). */
.cpt-module--all-meetings .schedule-row__result {
	justify-content: flex-start;
}

/* This module only overrides the cells where its data shape differs
 * from the schedule template's. Everything else — opponent name, venue,
 * score column, FINAL pill, filter chips, section header, TV — inherits
 * its styling directly from the football-schedule primitives, so a
 * future change to the schedule row propagates here without any
 * module-local edit.
 *
 * Overrides we keep:
 *  - Year column (display tier; serif, right-aligned, 4-digit numeral).
 *  - Full-date column (no schedule equivalent — sans muted supporting
 *    metadata, left-aligned).
 *  - Connective tissue inside the opponent line (prefix + rank): the
 *    schedule renders these as mono small-caps tracked labels; per the
 *    earlier "drop small caps from vs./at/#rank" decision we put them
 *    in sentence-case sans here.
 *  - Recap chevron: same de-labeling — sentence case sans, not a mono
 *    small-caps action label. */

/* DISPLAY — year. Stepped down 24 → 20 → 18 across rounds; padding-right
 * gives the right-aligned numeral breathing room from the date column
 * track that sits immediately to its right. */
.cpt-module--all-meetings .schedule-row__date--year {
	display: block;
	font-family: var(--font-serif);
	font-size: 18px;
	font-weight: 700;
	line-height: 1;
	color: var(--nd-navy);
	text-align: right;
	padding-right: 12px;
	font-feature-settings: 'tnum';
	font-variant-numeric: tabular-nums;
}

/* Full date column — module-specific (the schedule template has no
 * single full-date cell, only the stacked MMM/day). Sans 14px muted,
 * left-aligned, reads as supporting metadata beside the year anchor. */
.cpt-module--all-meetings .schedule-row__date--full {
	display: block;
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.3;
	color: var(--ink-3);
	text-align: left;
}

/* Connective tissue inside the opponent line — schedule's base on these
 * is mono uppercase tracked. Drop that here so "vs."/"at" and "#20"
 * read as quiet supporting text, not labels. Opponent NAME itself is
 * left on schedule's base (serif 17px 600 ink) — see the "keep the
 * serif font in the table" call from 2026-05-14. */
.cpt-module--all-meetings .schedule-row__prefix {
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	color: var(--ink-3);
}
.cpt-module--all-meetings .schedule-row__opp-rank {
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--ink-2);
}

/* Venue / location — overrides only font-family (sans → serif), so the
 * location reads in the same editorial register as the opponent name
 * and the year. Size + color stay on schedule's base (13px ink-3),
 * which keeps it as supporting text rather than a competing peak. */
.cpt-module--all-meetings .schedule-row__venue {
	font-family: var(--font-serif);
}

/* Recap chevron — same de-labeling. Sentence case sans, not the mono
 * small-caps the schedule applies. */
.cpt-module--all-meetings .schedule-row__action {
	font-family: var(--font-sans);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
	color: var(--nd-navy);
}
.cpt-module--all-meetings .schedule-row__action-label {
	font-family: var(--font-sans);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
}

/* Mobile (≤768px). Year and full date stay in two columns side-by-side
 * (each keeps its own visual identity); content column gets what's left.
 * Year column shrinks to 52px; date column to 100px. */
@media (max-width: 768px) {
	.cpt-module--all-meetings .schedule-row__anchor {
		grid-template-columns: 52px 100px 1fr auto;
		grid-template-areas:
			"year date opponent action"
			"year date venue    result"
			"year date tv       tv";
	}
	.cpt-module--all-meetings .schedule-row__date--year   { grid-area: year; font-size: 22px; }
	.cpt-module--all-meetings .schedule-row__date--full   { grid-area: date; }
	.cpt-module--all-meetings .schedule-row__opp-line     { flex-wrap: wrap; }
	/* Filter chip rail — horizontal scroll so 10 chips don't wrap to 3+
	 * lines on phones. Same `scrollbar-width: none` / webkit-scrollbar
	 * pattern as `.cpt-tabs` elsewhere in this file. */
	.cpt-module--all-meetings .schedule-filters {
		flex-wrap: nowrap;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}
	.cpt-module--all-meetings .schedule-filters::-webkit-scrollbar {
		display: none;
	}
	.cpt-module--all-meetings .schedule-filters__chips {
		flex-wrap: nowrap;
		flex-shrink: 0;
	}
}

/* Sub-tablet (≤480px, phones). The chevron column drops (the whole row
 * is already a link). Year + date collapse to a single 64px left column
 * with the year stacked above the date — the row's left-edge anchor.
 * Opponent / venue / result / tv stack vertically to the right. */
@media (max-width: 480px) {
	.cpt-module--all-meetings .schedule-row__action {
		display: none;
	}
	.cpt-module--all-meetings .schedule-row__anchor {
		grid-template-columns: 64px 1fr;
		grid-template-areas:
			"year opponent"
			"date opponent"
			"date venue"
			"date result"
			"date tv";
		align-items: start;
	}
	.cpt-module--all-meetings .schedule-row__date--year { text-align: left; font-size: 22px; }
	.cpt-module--all-meetings .schedule-row__result     { justify-content: flex-start; }
}

.opponent-log-empty {
	font-family: var(--font-sans);
	color: var(--ink-muted);
	margin: 12px 0;
}

/* --- Module 10: programs comparison -------------------------------- */
.opponent-programs-table th.col-stat { width: 40%; }
.opponent-programs-table .col-rank { width: 9%; }
.opponent-programs-table .program-rank {
	font-size: 12px;
	color: var(--ink-4);
}
.opponent-programs-table .program-cell-empty {
	color: var(--ink-4);
}
/* Light separation between the optional row groups (championships / bowl /
 * honours / draft / AP). Defer the full grouped treatment to comp. */
.opponent-programs-table tbody tr.program-row--champ:first-of-type th,
.opponent-programs-table tbody tr.program-row--champ:first-of-type td,
.opponent-programs-table tbody tr.program-row--bowl:first-of-type th,
.opponent-programs-table tbody tr.program-row--bowl:first-of-type td,
.opponent-programs-table tbody tr.program-row--honors:first-of-type th,
.opponent-programs-table tbody tr.program-row--honors:first-of-type td,
.opponent-programs-table tbody tr.program-row--draft:first-of-type th,
.opponent-programs-table tbody tr.program-row--draft:first-of-type td,
.opponent-programs-table tbody tr.program-row--ap:first-of-type th,
.opponent-programs-table tbody tr.program-row--ap:first-of-type td {
	border-top: 1px solid var(--line-soft);
}

/* ─────────────────────────────────────────────────────────────────────
 * Player CPT — Profile + All Coverage module CSS, ported from the
 * Claude Design comps in `references/player-cpt/`. Scoped tightly to
 * the player views via the `.cpt-layout--view-{slug}` modifier where
 * needed; otherwise shared component blocks.
 * ───────────────────────────────────────────────────────────────────── */

/* Module head row — shared by Recruitment, WEPA, Last 5, Latest Coverage */
.cpt-layout--view-profile .module-head-row,
.cpt-layout--view-coverage .module-head-row {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	margin-bottom: 16px;
	gap: 16px;
}
.cpt-layout--view-profile .module-head-row .micro-label,
.cpt-layout--view-coverage .module-head-row .micro-label {
	margin-bottom: 0;
}
.cpt-layout--view-profile .micro-label,
.cpt-layout--view-coverage .micro-label {
	display: block;
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
	margin-bottom: 16px;
}
.cpt-layout--view-profile .full-link,
.cpt-layout--view-coverage .full-link {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-green);
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}
.cpt-layout--view-profile .full-link:hover,
.cpt-layout--view-coverage .full-link:hover {
	color: var(--nd-green-hover);
}

/* Module 2 — Recruitment block (Profile view).
 * Top border dropped 2026-05-21 — the canonical `.section-head`
 * above the grid already provides its own bottom hairline; stacking
 * a second one here read as a doubled rule. Bottom border kept so
 * the grid still closes visually under the last data row. */
.recruitment-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 0;
	border-bottom: 1px solid var(--line);
}
.recruitment-grid > div {
	padding: 16px 18px;
	border-right: 1px solid var(--line-soft);
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.recruitment-grid > div:last-child {
	border-right: 0;
}
.recruitment-grid dt {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
	margin: 0;
}
.recruitment-grid dd {
	margin: 0;
	font-family: var(--font-mono);
	font-size: 22px;
	font-weight: 600;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	letter-spacing: -.005em;
}
/* Star rating primitive — used by the Player CPT recruitment block
 * (.recruitment-grid) and the Recruiting Class roster (.recruits-table).
 * Optional .stars wrapper keeps a row of stars on a single line with
 * no separator characters between glyphs. */
.stars {
	display: inline-block;
	white-space: nowrap;
	line-height: 1;
}
.star {
	color: var(--nd-gold);
	margin-right: 2px;
}
.star.off {
	color: var(--line-soft);
}
.recruitment-grid dd small {
	display: block;
	font-family: var(--font-sans);
	font-size: 12px;
	font-weight: 500;
	color: var(--ink-3);
	letter-spacing: 0;
	margin-top: 3px;
	text-transform: none;
}
.recruitment-attribution {
	margin: 8px 0 0;
	font-family: var(--font-sans);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: 0;
	line-height: 1.4;
	text-align: right;
}
.recruitment-attribution a {
	color: var(--ink-3);
	text-decoration: underline;
	text-underline-offset: 2px;
}
.recruitment-attribution a:hover {
	color: var(--accent-hover);
}
.commitment-note {
	margin-top: 16px;
	padding: 14px 18px;
	border-left: 3px solid var(--nd-gold);
	background: color-mix(in srgb, var(--nd-gold) 6%, transparent);
	font-family: var(--font-serif);
	font-size: 15px;
	line-height: 1.5;
	color: var(--ink-2);
}
.commitment-note .date {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
	display: block;
	margin-bottom: 4px;
}
.offer-cluster {
	margin-top: 16px;
	display: flex;
	flex-direction: column;
	gap: 10px;
}
.offer-cluster .offer-head {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}
.offer-cluster .offer-list {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}
.offer-cluster .offer {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 5px 9px;
	border: 1px solid var(--line);
	font-family: var(--font-sans);
	font-size: 12px;
	font-weight: 500;
	color: var(--ink-2);
	background: var(--bg-elevated);
	letter-spacing: .005em;
}
.offer-cluster .offer.committed {
	color: var(--nd-navy);
	border-color: var(--nd-navy);
	background: color-mix(in srgb, var(--nd-navy) 5%, transparent);
	font-weight: 700;
}
.offer-cluster .offer.committed::after {
	content: "★";
	color: var(--nd-gold);
	font-size: 11px;
	margin-left: 2px;
}

/* Module 3 — WEPA v2 per §19.3 Module 3.
 *
 * Small composed module: single header (title + subtitle, tooltip on title) +
 * 1–2 horizontal cells with vertical hairlines between them. No color shift
 * on positive/negative — sign carries the editorial signal (decision #42). */
.cpt-module--wepa .wepa-header {
	display: flex;
	align-items: baseline;
	gap: 16px;
	margin-bottom: 18px;
}
.cpt-module--wepa .wepa-title {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .22em;
	text-transform: uppercase;
	color: var(--nd-navy);
	font-weight: 700;
	display: inline-flex;
	align-items: center;
	gap: 6px;
}
.cpt-module--wepa .wepa-subtitle {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}

/* Tooltip — `?` icon adjacent to the title. Hover/focus reveals the body. */
.cpt-module--wepa .wepa-tip-wrap {
	position: relative;
	display: inline-flex;
}
.cpt-module--wepa .wepa-tip-btn {
	appearance: none;
	background: transparent;
	border: 1px solid var(--line);
	border-radius: 50%;
	width: 16px;
	height: 16px;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-mono);
	font-size: 10px;
	line-height: 1;
	color: var(--ink-3);
	cursor: help;
	transition: color .12s, border-color .12s;
}
.cpt-module--wepa .wepa-tip-btn:hover,
.cpt-module--wepa .wepa-tip-btn:focus-visible {
	color: var(--nd-navy);
	border-color: var(--nd-navy);
	outline: none;
}
.cpt-module--wepa .wepa-tip-body {
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
	top: calc(100% + 8px);
	z-index: 10;
	min-width: 220px;
	max-width: 320px;
	padding: 10px 12px;
	background: var(--nd-navy);
	color: #fff;
	font-family: var(--font-sans);
	font-size: 12.5px;
	font-weight: 400;
	line-height: 1.45;
	letter-spacing: 0;
	text-transform: none;
	border-radius: 3px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, .15);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity .12s, visibility .12s;
}
.cpt-module--wepa .wepa-tip-wrap:hover .wepa-tip-body,
.cpt-module--wepa .wepa-tip-wrap:focus-within .wepa-tip-body {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

/* Cells row.
 * Top border dropped 2026-05-21 — same reasoning as .recruitment-grid
 * above; the section-head's bottom hairline is the divider. Bottom
 * border kept so the cells row closes visually. */
.cpt-module--wepa .wepa-cells {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(0, 1fr);
	border-bottom: 1px solid var(--line);
	padding: 22px 0;
}
.cpt-module--wepa .wepa-cells--single {
	grid-template-columns: 1fr;
}
.cpt-module--wepa .wepa-cell {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding: 0 32px;
	border-left: 1px solid var(--line-soft);
	min-width: 0;
}
.cpt-module--wepa .wepa-cell:first-child {
	border-left: 0;
	padding-left: 0;
}
.cpt-module--wepa .wepa-cell__label {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
}
.cpt-module--wepa .wepa-cell__value {
	font-family: var(--font-mono);
	font-size: 38px;
	font-weight: 600;
	color: var(--text);
	font-variant-numeric: tabular-nums;
	letter-spacing: -.025em;
	line-height: 1;
}
.cpt-module--wepa .wepa-cell__denom {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: .04em;
	font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
	.cpt-module--wepa .wepa-cells {
		grid-auto-flow: row;
		grid-auto-columns: auto;
		grid-template-columns: 1fr;
	}
	.cpt-module--wepa .wepa-cell {
		padding: 18px 0;
		border-left: 0;
		border-top: 1px solid var(--line-soft);
	}
	.cpt-module--wepa .wepa-cell:first-child {
		border-top: 0;
		padding-top: 0;
	}
	.cpt-module--wepa .wepa-cell:last-child {
		padding-bottom: 0;
	}
}

/* Module 4 — Last 5 games table (Profile view)
 *
 * Three identity columns + N stat columns. Header row uses serif bold (matches
 * other editorial chrome — see article kicker/byline). Data rows separated by
 * soft hairlines. Explicit background resets defeat Jannah parent striping on
 * tr:nth-child(odd/even).
 */
/* `.last-games-table` base (width / border-collapse / font-family /
 * thead treatment / tbody-cell padding) now inherits from style.css
 * §"Canonical body cell treatment" + §"Canonical header row" via the
 * `data-table` opt-in class on the <table> markup (2026-05-21).
 * Surface-specific cell decoration follows below. */

/* Date — small mono, muted */
.last-games-table .lg-date {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .03em;
	color: var(--ink-3);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/* Opponent — sans, navy, linked to game post */
.last-games-table .lg-opponent {
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 600;
	color: var(--nd-navy);
}
.last-games-table .lg-opponent .at {
	color: var(--ink-4);
	font-weight: 500;
	margin-right: 4px;
}
.last-games-table .lg-opponent a {
	color: inherit;
	text-decoration: none;
}
.last-games-table .lg-opponent a:hover {
	color: var(--accent-hover);
}

/* Outcome — W/L pill + mono score */
.last-games-table .lg-outcome {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .03em;
	font-variant-numeric: tabular-nums;
	color: var(--ink-3);
	white-space: nowrap;
}
.last-games-table .lg-outcome .wl {
	font-weight: 700;
	margin-right: 6px;
}
.last-games-table .lg-outcome .wl.w { color: var(--nd-green); }
.last-games-table .lg-outcome .wl.l { color: var(--loss); }
.last-games-table .lg-outcome .wl.t { color: var(--ink-3); }
.last-games-table .lg-outcome .score {
	color: var(--text);
	font-weight: 600;
}

/* Stat columns — right-aligned mono numerics */
.last-games-table .num {
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	text-align: right;
	font-weight: 600;
	color: var(--text);
	font-size: 12px;
}
.last-games-table .num.lead {
	color: var(--nd-navy);
}

/* Module 7 — Latest Coverage sampler (Profile view) */
.coverage-sampler {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 20px;
}
.coverage-card {
	display: flex;
	flex-direction: column;
	gap: var(--card-gap);
	text-decoration: none;
	color: inherit;
}
.coverage-card .thumb {
	aspect-ratio: 16 / 9;
	background: var(--bg-muted);
	background-image: repeating-linear-gradient(45deg, color-mix(in srgb, var(--ink-4) 18%, transparent) 0 6px, transparent 6px 14px);
	border: 1px solid var(--line-soft);
	border-radius: var(--radius-media);
	overflow: hidden;
}
.coverage-card .thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.coverage-card .kicker {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
}
.coverage-card .title {
	font-family: var(--font-serif);
	font-size: 16px;
	font-weight: 700;
	color: var(--nd-navy);
	line-height: 1.25;
	letter-spacing: -.005em;
}
/* .coverage-card .meta-mini → canonical .meta-mini (2026-06-06). */
.coverage-card:hover .title {
	color: var(--accent-hover);
}

/* All Coverage view — hero + list + bulleted archive */
.coverage-list-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin-top: 28px;
}
.coverage-list-head .count {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--type-micro-tracking);
	color: var(--ink-3);
	font-weight: 500;
}
.coverage-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}
.coverage-list li {
	border-bottom: 1px solid var(--line-soft);
}
.coverage-list li:last-child {
	border-bottom: 0;
}
.coverage-list li a {
	display: grid;
	grid-template-columns: 160px 1fr;
	gap: 22px;
	align-items: start;
	padding: 22px 0;
	text-decoration: none;
	color: inherit;
}
.coverage-list .row-thumb {
	aspect-ratio: 16 / 9;
	background: var(--bg-muted);
	background-image: repeating-linear-gradient(45deg, color-mix(in srgb, var(--ink-4) 16%, var(--bg-muted)) 0 4px, var(--bg-muted) 4px 10px);
	border: 1px solid var(--line-soft);
	border-radius: var(--radius-media);
	overflow: hidden;
}
.coverage-list .row-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.coverage-list .row-body {
	display: flex;
	flex-direction: column;
	gap: 6px;
	min-width: 0;
}
.coverage-list .row-kicker {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
}
.coverage-list .row-title {
	font-family: var(--font-serif);
	font-size: 19px !important;
	font-weight: 600 !important;
	color: var(--nd-navy);
	line-height: 1.25;
	letter-spacing: -.005em;
	margin: 2px 0 4px;
	text-wrap: pretty;
}
.coverage-list .row-meta {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	font-family: var(--font-mono);
	font-size: 10.5px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 500;
}
.coverage-list .row-meta .author {
	color: var(--nd-navy);
	font-weight: 600;
}
.coverage-list .row-meta .dot {
	width: 3px;
	height: 3px;
	background: var(--ink-4);
	border-radius: 50%;
	display: inline-block;
}
.coverage-list .row-meta .cmts {
	display: inline-flex;
	align-items: center;
	gap: 4px;
}
.coverage-list li a:hover .row-title {
	color: var(--accent-hover);
}

.coverage-archive {
	margin-top: 36px;
}
.coverage-archive .archive-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 8px;
}
.coverage-archive .archive-head .count {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--type-micro-tracking);
	color: var(--ink-3);
	font-weight: 500;
}
.coverage-archive .year-head {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
	padding: 18px 0 8px;
	border-bottom: 1px solid var(--line);
	margin-bottom: 0;
}
.coverage-archive .year-head:first-of-type {
	padding-top: 10px;
}
.coverage-archive-list {
	list-style: none;
	margin: 0;
	padding: 0;
}
.coverage-archive-list li {
	display: grid;
	grid-template-columns: 12px 1fr auto;
	column-gap: 12px;
	align-items: start;
	padding: 9px 0;
}
/* The bullet and category have no text in common with the title, so baseline
 * alignment can't reach a clean "visual center of the title's first line."
 * Instead we top-align everything and use explicit margins to center each
 * piece on the title's first-line optical center (≈ 10px from the row top:
 * title is 14.5px × 1.4 line-height ≈ 20px line box, cap-height ≈ 10px → its
 * optical center sits ~10px from top of line). Works whether the title is
 * one line or two — bullet + category stay anchored to line 1.
 */
.coverage-archive-list .bullet {
	width: 5px;
	height: 5px;
	background: var(--nd-gold);
	border-radius: 50%;
	justify-self: center;
	margin-top: 8px;
}
.coverage-archive-list .archive-title {
	font-family: var(--font-sans);
	font-size: 14.5px;
	font-weight: 500;
	color: var(--nd-navy);
	text-decoration: none;
	line-height: 1.4;
	text-wrap: pretty;
}
.coverage-archive-list .archive-title:hover {
	color: var(--accent-hover);
}
.coverage-archive-list .archive-date {
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--ink-3);
	font-variant-numeric: tabular-nums;
	font-weight: 500;
	letter-spacing: .02em;
	margin-right: 4px;
	white-space: nowrap;
}
.coverage-archive-list .archive-sep {
	color: var(--ink-4);
	margin-right: 6px;
}
.coverage-archive-list .archive-title-text {
	color: inherit;
}
.coverage-archive-list .archive-category {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
	white-space: nowrap;
	/* Title's first line is 14.5px × 1.4 ≈ 20px. Give the category the same
	 * line-height so its 10px text centers in an equal-height line box —
	 * vertical centers line up automatically without margin nudges. */
	line-height: calc(14.5px * 1.4);
}

/* Mobile collapse for player module zones */
@media (max-width: 900px) {
	.recruitment-grid {
		grid-template-columns: repeat(2, 1fr);
	}
	.recruitment-grid > div:nth-child(2) {
		border-right: 0;
	}
	.recruitment-grid > div:nth-child(1),
	.recruitment-grid > div:nth-child(2) {
		border-bottom: 1px solid var(--line-soft);
	}
	.coverage-sampler {
		grid-template-columns: 1fr;
	}
	.coverage-list li a {
		grid-template-columns: 120px 1fr;
		gap: 14px;
	}
	.coverage-archive-list li {
		grid-template-columns: 8px 1fr;
	}
	.coverage-archive-list .archive-category {
		grid-column: 2 / -1;
		margin-top: 2px;
	}
}

/* Phase 7a (2026-05-23): coverage-list narrow-viewport stack.
 * At ≤520px the 120px thumb + body side-by-side layout leaves ~120px
 * for the body column at typical viewport widths, forcing serif titles
 * to break ugly or push past the right edge. Stack thumb above body
 * for cleaner reading + better tap targets. Was P1-4 in the responsive
 * audit. */
@media (max-width: 520px) {
	.coverage-list li a {
		grid-template-columns: 1fr;
		gap: 10px;
	}
	.coverage-list .row-thumb {
		max-width: 100%;
		aspect-ratio: 16 / 9;
	}
}


/* ========================================================================
   RECRUITING CLASS CPT — Claude Design comp port (2026-05-17)
   All styles scoped under .recruiting-page so they don't bleed onto the
   other CPTs that share cpt-rough.css. Comp source:
   references/UHND Recruiting Class - standalone.html
   ======================================================================== */

/* `.schedule-season-nav.header-picker` (the labeled LABEL · VALUE
 * picker shared by the football schedule and recruiting class
 * headers) lives in style.css §"Header picker" — defined alongside
 * the base .schedule-season-nav rules so both surfaces' selectors
 * resolve consistently regardless of cpt-rough.css enqueue. */

/* ── Breadcrumbs override (gold uppercase mono per comp) ── */
.recruiting-page .breadcrumbs {
	padding: 28px 0 14px;
}
.recruiting-page .breadcrumbs ol {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}
.recruiting-page .breadcrumbs li {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--nd-gold);
	letter-spacing: .14em;
	text-transform: uppercase;
	font-weight: 600;
}
.recruiting-page .breadcrumbs li a {
	color: var(--nd-gold);
	text-decoration: none;
}
.recruiting-page .breadcrumbs li a:hover {
	color: color-mix(in srgb, var(--nd-gold) 70%, var(--nd-navy));
	text-decoration: none;
}
.recruiting-page .breadcrumbs li[aria-current="page"],
.recruiting-page .breadcrumbs li .current {
	color: var(--ink-2);
	font-weight: 600;
}
.recruiting-page .breadcrumbs li + li::before {
	content: "·";
	color: var(--gold-border);
	margin-right: 6px;
	font-size: 13px;
}

/* Shared page-primitive rules — `.schedule-page__header`, `.schedule-page__title`,
 * `.gold-rule`, `.deck`, `.metrics-strip` / `.metric-cell` / `.lbl` / `.val` /
 * `.sub` — live in style.css alongside `.schedule-page` and `.schedule-page__container`.
 * They were moved out of `.recruiting-page` scope in the 2026-05-19 unification so
 * the football schedule and recruiting class detail share one set of header +
 * stat-strip rules. style.css is loaded on both surfaces; cpt-rough.css is not. */

/* ── Layout grid (body + rail) ──
 * Padding zeroed so the recruiting page shell matches the schedule page
 * (both share .schedule-page + .schedule-page__container). The outer
 * .schedule-page rule supplies 24/48 top/bottom shell padding; modules
 * inside .body-col contribute their own top spacing via
 * .cpt-module-head's --space-module-top margin. The earlier
 * `padding: 36px 0 64px` stacked on top of the .schedule-page 24/48,
 * producing ~60/112 of vertical shell padding vs the schedule page's
 * 24/48 — visually inconsistent with the rest of the site. */
.recruiting-page .layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) var(--rail-w);
	gap: var(--rail-col-gap);
}
.recruiting-page .body-col {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 48px;
}
.recruiting-page .rail {
	display: flex;
	flex-direction: column;
	/* Stacked-module gap unified with the article `.rail` (was 32px). */
	gap: var(--rail-gap);
	min-width: 0;
}

/* `.section-head` (serif H2 + mono count + right-aligned .micro
 * attribution + bottom hairline rule) is the canonical reusable
 * section header — promoted out of .recruiting-page scope in the
 * 2026-05-20 unification so the football schedule's games list can
 * use the same chrome. Rules live in style.css §"Section head" so
 * surfaces that don't enqueue cpt-rough.css still pick them up.
 * Spec: docs/components/section-head.md. */

/* ── Blue Chip Ratio module ── */

/* Tooltip — "What is Blue Chip Ratio?" trigger in the section-head's
 * right cell. Mirrors the .wepa-tip-* pattern but the body anchors to
 * the trigger's right edge (rather than centered) because the trigger
 * sits at the right edge of the section-head row. */
.recruiting-page .bcr-tip-wrap {
	position: relative;
	display: inline-flex;
}
.recruiting-page .bcr-tip-btn {
	appearance: none;
	background: transparent;
	border: 0;
	padding: 0;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .04em;
	color: var(--ink-3);
	cursor: help;
	transition: color .12s;
}
.recruiting-page .bcr-tip-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 16px;
	height: 16px;
	border: 1px solid currentColor;
	border-radius: 50%;
	font-size: 10px;
	line-height: 1;
	transition: color .12s, border-color .12s;
}
.recruiting-page .bcr-tip-btn:hover,
.recruiting-page .bcr-tip-btn:focus-visible {
	color: var(--nd-navy);
	outline: none;
}
.recruiting-page .bcr-tip-body {
	position: absolute;
	right: 0;
	top: calc(100% + 8px);
	z-index: 10;
	width: max-content;
	min-width: 240px;
	max-width: 360px;
	padding: 10px 12px;
	background: var(--nd-navy);
	color: #fff;
	font-family: var(--font-sans);
	font-size: 12.5px;
	font-weight: 400;
	line-height: 1.45;
	letter-spacing: 0;
	text-transform: none;
	border-radius: 3px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, .15);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity .12s, visibility .12s;
}
.recruiting-page .bcr-tip-wrap:hover .bcr-tip-body,
.recruiting-page .bcr-tip-wrap:focus-within .bcr-tip-body {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

.recruiting-page .bcr {
	background: transparent;
	border: 0;
	padding: 4px 0 0;
}
.recruiting-page .bcr-row {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: center;
	gap: 36px;
}
.recruiting-page .bcr-graphic {
	min-width: 0;
}
.recruiting-page .bcr-row .right {
	font-family: var(--font-serif);
	font-weight: 600;
	color: var(--nd-navy);
	letter-spacing: -.02em;
	line-height: 1;
	display: inline-flex;
	align-items: baseline;
	gap: 4px;
	padding: 18px 22px 16px;
	border: 1px solid var(--line-strong);
	background: var(--card-raised);
	position: relative;
}
.recruiting-page .bcr-row .right::before {
	content: "";
	position: absolute;
	top: -1px;
	left: -1px;
	width: 34px;
	height: 3px;
	background: var(--nd-gold);
}
.recruiting-page .bcr-row .right .pct {
	font-size: 54px;
	font-variant-numeric: tabular-nums;
}
.recruiting-page .bcr-row .right .sym {
	font-size: 22px;
	color: var(--ink-3);
	font-family: var(--font-mono);
	font-weight: 500;
}
.recruiting-page .bcr-bar {
	position: relative;
	height: 14px;
	background: color-mix(in srgb, var(--green-utility) 8%, var(--bg-muted));
	overflow: visible;
}
.recruiting-page .bcr-bar .fill {
	position: absolute;
	inset: 0 auto 0 0;
	height: 100%;
	background: linear-gradient(90deg, color-mix(in srgb, var(--green-utility) 80%, var(--nd-navy)), var(--green-utility));
}
.recruiting-page .bcr-bar .threshold {
	position: absolute;
	top: -6px;
	bottom: -6px;
	left: 50%;
	width: 1px;
	background: var(--nd-navy);
}
.recruiting-page .bcr-bar .threshold::after {
	content: "";
	position: absolute;
	left: -3px;
	top: -2px;
	width: 7px;
	height: 3px;
	background: var(--nd-navy);
}
.recruiting-page .bcr-axis {
	position: relative;
	height: 18px;
	margin-top: 8px;
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-4);
	font-weight: 600;
}
.recruiting-page .bcr-axis .marker {
	position: absolute;
	left: 0;
	transform: translateX(-50%);
}
.recruiting-page .bcr-axis .marker--threshold {
	left: 50%;
	color: var(--nd-navy);
}
.recruiting-page .bcr-axis .marker--threshold strong {
	color: var(--nd-navy);
	font-weight: 700;
}
.recruiting-page .bcr-axis .marker--end {
	left: 100%;
	transform: translateX(-100%);
}
.recruiting-page .bcr-foot {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	margin-top: 22px;
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
	gap: 0;
}
.recruiting-page .bcr-foot .item {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 14px 18px;
	border-left: 1px solid var(--line-soft);
}
.recruiting-page .bcr-foot .item:first-child {
	border-left: 0;
	padding-left: 0;
}
.recruiting-page .bcr-foot .item:last-child {
	padding-right: 0;
}
.recruiting-page .bcr-foot .item .k {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-4);
	font-weight: 600;
}
.recruiting-page .bcr-foot .item .v {
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 600;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
}
.recruiting-page .bcr-foot .item .v small {
	font-family: var(--font-mono);
	font-weight: 500;
	color: var(--ink-3);
	font-size: 11px;
	margin-left: 4px;
}
/* Narrow viewports: the 4-col strip squeezes each cell to ~36px of usable
 * width, so the "nationally" sub-label on Top 100 / Top 300 overflows into
 * the next column (responsive audit P2-B, 2026-06-05). Drop to 2 columns
 * and reset the per-cell left hairline + padding so wrapped cells don't
 * carry a stray border (mirrors the player-hero bio reflow). */
@media (max-width: 560px) {
	.recruiting-page .bcr-foot {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		row-gap: 16px;
	}
	.recruiting-page .bcr-foot .item,
	.recruiting-page .bcr-foot .item:first-child,
	.recruiting-page .bcr-foot .item:last-child {
		border-left: 0;
		padding: 0 14px 0 0;
	}
}
.recruiting-page .bcr-pending {
	font-family: var(--font-sans);
	font-size: 13px;
	color: var(--ink-3);
	line-height: 1.5;
	margin: 0;
}

/* Jannah's single.css applies `border-right: 1px dotted` to every
 * `td` / `th` and a full border on `thead th`. Strip those for the
 * pos-table + rc-archive-table (neither opts into `.data-table` yet —
 * the commits-table now inherits this reset canonically from
 * style.css §"Canonical body cell treatment"). */
.recruiting-page .pos-table td,
.recruiting-page .pos-table th,
.recruiting-page .rc-archive-table td,
.recruiting-page .rc-archive-table th {
	border-right: 0;
}
.recruiting-page .rc-archive-table thead th {
	border-top: 0;
	border-left: 0;
}
.recruiting-page .pos-table tr:nth-child(even),
.recruiting-page .rc-archive-table tr:nth-child(even) {
	background: transparent;
}

/* ── Position groups (table form) ── */
.recruiting-page .pos-table {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--font-sans);
}
.recruiting-page .pos-table tbody td {
	padding: 14px;
	border-bottom: 1px solid var(--line-soft);
	vertical-align: middle;
}
.recruiting-page .pos-table tbody tr:last-child td {
	border-bottom: 0;
}
.recruiting-page .pos-pos {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 42px;
	height: 24px;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .06em;
	color: var(--nd-navy);
	background: var(--bg-sunk);
	border: 1px solid var(--line-soft);
}
.recruiting-page .pos-count {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: .02em;
	padding-left: 12px;
	font-weight: 500;
}
.recruiting-page .pos-bar-cell {
	padding-left: 18px;
	padding-right: 18px;
	min-width: 280px;
}
.recruiting-page .pos-bar {
	position: relative;
	height: 6px;
	background: color-mix(in srgb, var(--green-utility) 8%, var(--bg-muted));
}
.recruiting-page .pos-bar .f {
	position: absolute;
	inset: 0 auto 0 0;
	background: var(--green-utility);
}
.recruiting-page .pos-rating,
.recruiting-page .pos-stars {
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--text);
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	text-align: right;
	white-space: nowrap;
	letter-spacing: .02em;
}
.recruiting-page .pos-stars {
	color: var(--nd-gold);
}
.recruiting-page .pos-stars::after {
	content: "★";
	margin-left: 3px;
	color: var(--nd-gold);
}

/* ── Commits table ── */
.recruiting-page .commits-tools {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 16px;
	flex-wrap: wrap;
}
.recruiting-page .tool-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 30px;
	padding: 0 12px;
	background: var(--card-raised);
	border: 1px solid var(--line-soft);
	font-family: var(--font-mono);
	font-size: 10.5px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--ink-2);
	font-weight: 600;
	cursor: default;
}
.recruiting-page .tool-chip.is-active {
	background: var(--nd-navy);
	color: #fff;
	border-color: var(--nd-navy);
}
.recruiting-page .tool-chip .cnt {
	font-family: var(--font-mono);
	color: var(--ink-4);
	font-weight: 500;
	margin-left: 2px;
}
.recruiting-page .tool-chip.is-active .cnt {
	color: rgba(255,255,255,.55);
}
/* `.recruiting-page .commits-table` base rules (width / border-collapse /
 * font-family / cell padding / divider / hover wash / last-child no-border)
 * now inherit from style.css §"Canonical body cell treatment" via the
 * `data-table` opt-in class on the <table> markup. Surface-specific
 * column widths + cell decoration follow below. */
.recruiting-page .commits-table .col-rank {
	width: 38px;
	padding-left: 0;
}
.recruiting-page .commits-table .col-rank .r {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-4);
	font-weight: 500;
	letter-spacing: .04em;
}
.recruiting-page .commits-table .col-player {
	min-width: 240px;
}
.recruiting-page .commits-table .col-pos {
	width: 64px;
	text-align: center;
}
.recruiting-page .commits-table .col-rating {
	width: 170px;
}
.recruiting-page .commits-table .col-rank-cell {
	width: 130px;
}
.recruiting-page .commits-table .col-home {
	min-width: 200px;
}
.recruiting-page .player-cell {
	display: flex;
	align-items: center;
	gap: 12px;
}
.recruiting-page .player-text {
	display: flex;
	flex-direction: column;
	line-height: 1.2;
	min-width: 0;
}
.recruiting-page .player-text .name {
	font-family: var(--font-sans);
	font-size: 14.5px;
	font-weight: 600;
	color: var(--nd-navy);
	text-decoration: none;
	letter-spacing: -.005em;
}
/* Only real links (a.name) get the hover affordance. Recruits with no
 * published player_profile render a <span class="name"> plain-text
 * fallback (see goldendome_resolve_recruit_player_url) — scoping :hover
 * to the anchor keeps those spans from looking/behaving like dead links. */
.recruiting-page .player-text a.name:hover {
	color: var(--accent-hover);
	text-decoration: underline;
}
.recruiting-page .player-text .meta {
	font-family: var(--font-mono);
	font-size: 10.5px;
	color: var(--ink-3);
	margin-top: 3px;
	letter-spacing: .02em;
	font-weight: 500;
	display: flex;
	align-items: center;
	gap: 6px;
}
.recruiting-page .player-text .meta .sep {
	color: var(--line-strong);
}
.recruiting-page .pos-pill {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 22px;
	font-family: var(--font-mono);
	font-size: 10.5px;
	font-weight: 700;
	letter-spacing: .04em;
	color: var(--nd-navy);
	background: var(--bg-sunk);
	border: 1px solid var(--line-soft);
}
.recruiting-page .rating-cell {
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.recruiting-page .rating-cell .stars {
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--nd-gold);
	letter-spacing: var(--tracking-mono-tight);
	line-height: 1;
}
.recruiting-page .rating-cell .stars .off {
	color: var(--line-soft);
}
.recruiting-page .rating-cell .composite {
	font-family: var(--font-mono);
	font-size: 11.5px;
	color: var(--text);
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	letter-spacing: .02em;
}
.recruiting-page .rank-cell {
	display: flex;
	flex-direction: column;
	gap: 3px;
	font-family: var(--font-mono);
	font-size: 12px;
}
.recruiting-page .rank-cell .row {
	display: flex;
	align-items: baseline;
	gap: 6px;
}
.recruiting-page .rank-cell .row .v {
	color: var(--nd-navy);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	letter-spacing: .01em;
}
.recruiting-page .rank-cell .row .k {
	font-size: 9.5px;
	color: var(--ink-4);
	letter-spacing: .14em;
	text-transform: uppercase;
	font-weight: 600;
}
.recruiting-page .home-cell {
	display: flex;
	flex-direction: column;
	line-height: 1.25;
}
.recruiting-page .home-cell .school {
	font-family: var(--font-sans);
	font-size: 13.5px;
	font-weight: 500;
	color: var(--text);
}
.recruiting-page .home-cell .city {
	font-family: var(--font-mono);
	font-size: 10.5px;
	color: var(--ink-3);
	margin-top: 3px;
	letter-spacing: .04em;
}

/* ── Right rail blocks ── */
.recruiting-page .rail-section {
	display: flex;
	flex-direction: column;
	gap: 0;
}
.recruiting-page .rail-section .rail-head {
	font-family: var(--font-sans);
	font-size: 11px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--nd-navy);
	font-weight: 700;
	padding-bottom: 10px;
	border-bottom: 2px solid var(--nd-gold);
	margin-bottom: 14px;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 10px;
}
.recruiting-page .rail-section .rail-head .more {
	font-family: var(--font-sans);
	font-size: 11px;
	color: var(--ink-3);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-tight);
	text-decoration: none;
}
.recruiting-page .rail-section .rail-head .more:hover {
	color: var(--nd-navy);
	text-decoration: none;
}

/* Class navigator (prev / next class) */
.recruiting-page .class-nav {
	display: flex;
	align-items: stretch;
	justify-content: space-between;
	border: 1px solid var(--line-soft);
	background: var(--card-raised);
}
.recruiting-page .class-nav a {
	flex: 1;
	padding: 14px;
	display: flex;
	flex-direction: column;
	gap: 3px;
	text-decoration: none;
	color: inherit;
	font-family: var(--font-sans);
}
.recruiting-page .class-nav a + a {
	border-left: 1px solid var(--line-soft);
}
.recruiting-page .class-nav a:hover {
	background: var(--bg-sunk);
	text-decoration: none;
}
.recruiting-page .class-nav a .dir {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-4);
	font-weight: 600;
	display: flex;
	align-items: center;
	gap: 4px;
}
.recruiting-page .class-nav a .yr {
	font-family: var(--font-serif);
	font-size: 18px;
	font-weight: 600;
	color: var(--nd-navy);
	letter-spacing: -.01em;
}
.recruiting-page .class-nav a .yr small {
	font-family: var(--font-mono);
	font-weight: 500;
	font-size: 11px;
	color: var(--ink-3);
	margin-left: 6px;
	letter-spacing: .04em;
}
.recruiting-page .class-nav a.next {
	text-align: right;
	align-items: flex-end;
}

/* Top-rated commit card */
.recruiting-page .top-rated {
	background: transparent;
	border-top: 0;
	border-bottom: 1px solid var(--line);
	padding: 4px 0 20px;
	position: relative;
}
.recruiting-page .top-rated .eyebrow {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
	margin-bottom: 10px;
}
.recruiting-page .top-rated .name {
	font-family: var(--font-serif);
	font-size: 22px;
	font-weight: 600;
	color: var(--nd-navy);
	line-height: 1.1;
	letter-spacing: -.01em;
	margin: 0;
}
.recruiting-page .top-rated .meta {
	font-family: var(--font-mono);
	font-size: 10.5px;
	color: var(--ink-3);
	letter-spacing: .04em;
	margin-top: 6px;
	font-weight: 500;
	display: flex;
	align-items: center;
	gap: 6px;
	flex-wrap: wrap;
}
.recruiting-page .top-rated .meta .sep {
	color: var(--line-strong);
}
.recruiting-page .top-rated .stars-row {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-top: 14px;
	padding-top: 12px;
	border-top: 1px solid var(--line-soft);
}
.recruiting-page .top-rated .stars-row .stars {
	font-family: var(--font-mono);
	font-size: 14px;
	color: var(--nd-gold);
	letter-spacing: .1em;
	line-height: 1;
}
.recruiting-page .top-rated .stars-row .composite {
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--nd-navy);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	letter-spacing: .02em;
}
.recruiting-page .top-rated .stars-row .sub {
	margin-left: auto;
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}

/* Recruiting recent posts list (rail) */
.recruiting-page .recent-list {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
.recruiting-page .recent-item {
	display: grid;
	grid-template-columns: 80px 1fr;
	gap: 12px;
	text-decoration: none;
	color: inherit;
	padding-bottom: 14px;
	border-bottom: 1px solid var(--line-soft);
}
.recruiting-page .recent-item:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}
.recruiting-page .recent-item:hover .title {
	color: var(--accent-hover);
}
.recruiting-page .recent-item:hover {
	text-decoration: none;
}
.recruiting-page .recent-item .thumb {
	width: 80px;
	height: 60px;
	background: var(--bg-muted);
	border-radius: var(--radius-media);
	overflow: hidden;
}
.recruiting-page .recent-item .thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}
.recruiting-page .recent-item .body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}
.recruiting-page .recent-item .kicker-sm {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
}
.recruiting-page .recent-item .title {
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 600;
	color: var(--nd-navy);
	line-height: 1.3;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* .recruiting-page .recent-item .meta-mini → canonical .meta-mini (2026-06-06). */

/* Ad slot wrapper (rail) */
.recruiting-page .ad-rail-wrap .rail-head {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: .18em;
	color: var(--ink-4);
	text-align: center;
	font-weight: 500;
	border-bottom: 0;
	padding-bottom: 0;
	margin-bottom: 0;
	text-transform: uppercase;
	justify-content: center;
}

/* ── Mobile (≤ 1080px) — recruiting layout collapse ──
 * Shared header + metrics-strip mobile reflow rules live in style.css
 * (since they apply to both the schedule and recruiting class pages).
 * Only the recruiting-only body/rail collapse remains here. */
@media (max-width: 1080px) {
	.recruiting-page .layout {
		grid-template-columns: 1fr;
	}
	.recruiting-page .rail {
		order: 2;
	}
}

/* ========================================================================
   RECRUITING CLASSES ARCHIVE TABLE — preserved from Phase 21
   ======================================================================== */
.cpt-module--rc-archive {
	border: 0;
	padding: 0;
	margin-block: 32px 0;
}
.rc-archive-table {
	width: 100%;
	table-layout: fixed;
}
.rc-archive-table .rca-col-year    { width: 16%; }
.rc-archive-table .rca-col-rank    { width: 14%; }
.rc-archive-table .rca-col-commits { width: 14%; }
.rc-archive-table .rca-col-stars   { width: 16%; }
.rc-archive-table .rca-col-points  { width: 18%; }
.rc-archive-table .rca-col-bcr     { width: 22%; }
/* Below the .table-scroll-wrap breakpoint (≤760) the six fixed-percentage
 * columns squeeze far enough that the Comp Pts / BCR numbers collide
 * (responsive audit P2-C, 2026-06-05). Give the table a readable floor so
 * it scrolls horizontally inside .table-scroll-wrap instead of overlapping;
 * the percentage column widths then resolve against this min-width. */
@media (max-width: 760px) {
	.rc-archive-table { min-width: 540px; }
}
.rc-archive-table .rca-year {
	font-family: var(--font-serif);
	font-size: 16px;
	font-weight: 600;
	color: var(--nd-navy);
}
.rc-archive-table .rca-year a {
	color: inherit;
	text-decoration: none;
}
.rc-archive-table .rca-year a:hover,
.rc-archive-table .rca-year a:focus {
	color: var(--accent-hover);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}
.rc-archive-table .rca-num {
	font-family: var(--font-mono);
	font-feature-settings: 'tnum';
	font-variant-numeric: tabular-nums;
	font-size: 13px;
	font-weight: 700;
	color: var(--nd-navy);
	white-space: nowrap;
	text-align: center;
}
.rc-archive-table tbody tr:hover {
	background: var(--bg-elevated);
}
