/* Goldendome CSS bundle — auto-generated by goldendome_build_css_bundle() in functions.php.
 * Do not edit. Source files concatenated in order:
 *   /assets/css/tokens.css
 *   /assets/css/goldendome-base.css
 *   /assets/css/cards.css
 *   /style.css
 * Filename's numeric segment is the max source-file mtime at the time
 * of generation. Regen only fires in local dev when a source is newer
 * than the existing bundle; deployed pods always serve whatever bundle
 * file was baked into the image at build time.
 */

/* ===== /assets/css/tokens.css ===== */
/*
 * Goldendome — design tokens
 *
 * Mirrors the :root block in sandbox/article-template.html.
 * Per docs/decisions.md 2026-05-07 "Approved sandboxes are the canonical
 * source of design truth", this file ships only tokens currently in use
 * by an approved sandbox. Tokens documented in docs/tokens.md but not
 * referenced by any sandbox are candidates for future surfaces and live
 * in the doc, not here.
 *
 * Loaded at wp_enqueue_scripts priority 1 from goldendome/functions.php
 * so custom-property values are defined before any component CSS that
 * references them.
 *
 * Updates to this file MUST be mirrored to docs/tokens.md in the same commit.
 */

:root {
	/* Brand */
	--nd-navy: #0C2340;
	--nd-green: oklch(0.48 0.115 150);
	--nd-green-hover: oklch(0.43 0.12 150);
	--nd-green-soft: oklch(0.95 0.04 148);
	--nd-green-ink: oklch(0.35 0.1 150);

	/* Data-utility green — tonal system tuned 2026-05-16 refinement pass.
	 * Three tiers; the dark brand variant only reads cleanly on navy
	 * surfaces, so light-background uses get a medium utility variant
	 * that's lighter and less saturated:
	 *
	 *   --green-brand     dark ND brand green, navy-background uses only
	 *                     (schedule-strip live indicator, win pills, etc.).
	 *   --green-utility   medium green for card top-stripes + data-viz
	 *                     fills on LIGHT backgrounds (recruiting class
	 *                     position-group bars, BCR bar, stat-card stripes).
	 *   --nd-green-soft   pale tint, existing token kept for backgrounds.
	 *
	 * Green = utility / positive state. Gold remains editorial accent.
	 * See docs/design-system.md §5.5. */
	/* Tuned 2026-05-19 to a brighter, more yellow-leaning kelly green —
	 * chroma 0.14 → 0.19, hue 148 → 142, L 0.62 → 0.64. Prior values
	 * (0.62 0.14 148, then 0.62 0.08 150) read as muted sage on the
	 * recruiting class bars rather than the kelly green Frank wanted. */
	--green-utility: oklch(0.64 0.19 142);
	--nd-gold: oklch(0.72 0.14 82);
	--gold: var(--nd-gold);
	--gold-border: color-mix(in srgb, var(--nd-gold) 38%, transparent);
	--accent: var(--nd-navy);
	--accent-hover: #0a1c32;
	--accent-tint: rgba(12, 35, 64, 0.08);

	/* Surfaces & ink */
	--bg: oklch(0.985 0.006 85);
	--bg-sunk: oklch(0.97 0.008 82);
	--bg-elevated: oklch(0.995 0.004 85);
	--bg-muted: #EDECEA;
	/* Warm-tan tint at --bg-muted darkness. Used by the canonical header
	 * row (`.data-table thead th`, `.row-head__cell`). Hue + chroma
	 * borrowed from the --card-background family so headers sit in the
	 * same warm register as the warm-cream data cards; L dropped to
	 * ~0.93 so the band reads as a distinct band against the page bg.
	 * Added 2026-05-20 with the canonical-header lock-in. */
	--bg-header-row: oklch(0.93 0.020 80);
	--card: oklch(0.995 0.004 85);
	--card-raised: #ffffff;
	--text: oklch(0.22 0.015 70);
	--text-muted: oklch(0.52 0.01 75);
	--ink: var(--text);
	--ink-2: oklch(0.34 0.012 72);
	--ink-3: var(--text-muted);
	--ink-4: oklch(0.62 0.008 78);

	/* TEMPORARY — referenced by docs/cpt-structural-layouts.md §2 + §3.3
	 * mono micro-label rule. Aliases --ink-3 to satisfy the spec literally;
	 * remove this alias when Phase 6 docs reconciliation lands and either
	 * the spec switches to --ink-3 or a permanent token decision lands. */
	--ink-muted: var(--ink-3);
	--line: oklch(0.9 0.008 80);
	--line-soft: oklch(0.915 0.01 78);
	--line-strong: oklch(0.82 0.01 78);

	/* Video band — dark navy wrapper used by the video post template to host
	 * hero + related-videos in a "video destination" zone. Added 2026-05-17
	 * with the video template port. Note: the sandbox chose --nd-navy for
	 * this band (sandbox/video-post/video-post.html), which contradicts
	 * docs/design-system.md §13.5's preference for "subtle differentiation"
	 * and §17.2's reservation of --nd-navy for the homepage video band. Per
	 * the 2026-05-07 sandbox-precedence rule, sandbox wins; the homepage
	 * video band will need its own differentiator (likely a gold rule or
	 * internal pattern) when that surface is built. */
	--bg-video-band:           var(--nd-navy);
	--video-band-line:         rgba(255, 255, 255, 0.08);
	--video-band-line-strong:  rgba(255, 255, 255, 0.14);
	--video-band-ink:          rgba(255, 255, 255, 0.94);
	--video-band-ink-2:        rgba(255, 255, 255, 0.78);
	--video-band-ink-3:        rgba(255, 255, 255, 0.58);
	--video-band-ink-4:        rgba(255, 255, 255, 0.40);

	/* Status */
	--danger: #c41e1e;

	/* Public-site extensions */
	--win: var(--nd-green);
	--loss: var(--danger);
	--live: var(--nd-green);
	--upcoming: var(--ink-3);
	--final: var(--ink-2);
	--ad-frame: var(--line-soft);
	--ad-label-ink: var(--ink-4);

	/* Status pill — Game CPT identity zone (§19.2 Module 1) */
	--pill-final-bg: var(--bg-muted);
	--pill-final-fg: var(--ink-2);
	--pill-scheduled-bg: var(--bg-muted);
	--pill-scheduled-fg: var(--ink-3);
	/* Reserved: --pill-live-bg/fg, --pill-postponed-bg/fg (not yet built) */

	/* Winner emphasis — compare tables (§14.1). Updated 2026-05-21 from
	 * pale green + green ink + triangle pseudos to a pale-navy wash with
	 * inherited body ink, no pseudo arrows. The wash signals; the text
	 * stays in canonical body color. Pairs with the leader-bg removal in
	 * cpt-rough.css §"Compare table". */
	--winner-bg: color-mix(in srgb, var(--nd-navy) 6%, transparent);
	--winner-fg: var(--text);

	/* Type — faces */
	--font-sans: "Inter", system-ui, sans-serif;
	--font-serif: "Source Serif 4", Georgia, serif;
	--font-mono: "JetBrains Mono", ui-monospace, monospace;

	/* Type — ramp (origin: Press Room; values anchored in active sandboxes) */
	--type-doc-body-size: 18px;
	--type-doc-body-line: 1.7;
	--type-doc-body-measure: 75ch;
	--type-doc-h2-size: 22px;
	--type-doc-h2-weight: 600;
	--type-doc-h2-tracking: -0.005em;
	--type-doc-h3-size: 20px;
	--type-meta-size: 13px;
	--type-micro-size: 11px;
	--type-micro-tracking: 0.12em;
	--type-mono-label-size: 10px;
	--type-mono-label-tracking: 0.12em;

	/* Eyebrow / micro-label SIZE scale — added 2026-06-06 with the
	 * `.micro-label` canonical component (docs/components/eyebrow.md).
	 * The eyebrow's size dimension had drifted to raw 8.5/9/9.5/10/10.5/11/12/13px
	 * across ~118 hand-tuned rules; this is the 4-step scale the canonical
	 * component standardizes on (10px and 11px were already ~90 of those uses,
	 * so most rules don't move). Choose by visual prominence:
	 *   --label-sm (9px)  — dense inline labels, ad eyebrows
	 *   --label-md (10px) — default micro-label (module labels, table heads)
	 *   --label-lg (11px) — section heads, card eyebrows
	 *   --label-xl (12px) — the largest eyebrow tier (rare)
	 * --label-md == --type-mono-label-size, --label-lg == --type-micro-size
	 * (kept as aliases; new eyebrow CSS uses the --label-* names). */
	--label-sm: 9px;
	--label-md: 10px;
	--label-lg: 11px;
	--label-xl: 12px;

	/* Mono-tracking 3-tier scale — tokenized 2026-05-22 with Phase 3f of
	 * the CSS rebuild. Recognizes the existing typographic vocabulary:
	 *
	 *   --tracking-mono-tight (0.08em) — light uppercase tracking. Used
	 *     for body-flow mono labels in dense rows (schedule HOME/AWAY
	 *     chip, all-meetings prefix, rank-line sources), small navigation
	 *     labels, and inline meta where the surrounding letters are 9-11px.
	 *   --tracking-mono       (0.12em, aliased to --type-micro-tracking
	 *     above for backward compat) — moderate. The default for mono
	 *     micro-labels at 11px and below. Existing 0.12em rules don't
	 *     need to migrate.
	 *   --tracking-mono-loose (0.16em) — display tracking. Used for
	 *     section heads, hero kickers, card eyebrows, and the more
	 *     prominent .section-head .micro attribution where the label
	 *     itself is a feature.
	 *
	 * Choose by visual weight, not by font-size. Edge values (0.04em,
	 * 0.06em, 0.22em) stay raw in their original rules — they're
	 * intentional one-off tunings outside the 3-tier system. See
	 * docs/tokens.md and audit §3c for the analysis. */
	--tracking-mono-tight: 0.08em;
	--tracking-mono-loose: 0.16em;

	/* Type — ramp (NEW for public site) */
	--type-article-headline-size: clamp(2rem, 2.8vw, 2.75rem);
	--type-article-deck-size: clamp(1.0625rem, 1.4vw, 1.25rem);
	--type-card-feature-size: clamp(1.25rem, 1.8vw, 1.5rem);
	/* Hero overlay card — the largest serif tier on the homepage. Used by
	 * the §8.1.4 overlay-style lead card variant when it sits as the lead
	 * in the homepage hero region. One tier above --type-card-feature-size
	 * so the hierarchy guidance from §8.1.4 (headline at least one tier
	 * above nearby feature cards) holds automatically. */
	--type-card-hero-size: clamp(1.875rem, 3vw, 2.625rem);
	--type-card-tertiary-size: 0.9375rem;
	--type-section-title-size: 0.6875rem;
	--type-pullquote-size: clamp(1.25rem, 1.8vw, 1.625rem);

	/* Geometry */
	--radius: 6px;
	--r-card: 8px;       /* legacy card radius — three existing consumers
	                      * (.story-highlights, .next-game-card__inner, the
	                      * Recruiting Class .cpt-card). New card components
	                      * should adopt --radius-card. Migration of the two
	                      * legacy consumers tabled pending review. */
	--radius-card: 8px;  /* canonical card-corner radius. Bumped 5→8 in the
	                      * 2026-05-16 top-of-page polish brief — pairs with
	                      * the tinted card background and borderless card
	                      * chrome to read contemporary. */
	--r-input: 6px;
	--radius-pill: 9999px; /* fully-rounded "stadium" pill — filter chips
	                        * (schedule ALL/HOME/AWAY, season-archive year),
	                        * category filter pills. Tokenized 2026-06-06 (was
	                        * raw 9999px in 3 places). Distinct from --radius
	                        * (6px status pill) and --radius-chip (2px). */
	--radius-chip: 2px;  /* canonical chip / mini-pill corner radius. Used by
	                      * duration pills (video hero / playlist / related-
	                      * card), author badge, video-chip kicker, schedule-
	                      * row prefix (HOME/AWAY chip), W/L mini-tag, and any
	                      * other "tight rectangular chip on a media surface"
	                      * primitive. Distinct from --radius (6px, status
	                      * pills) and --radius-card (8px). Tokenized 2026-05-22
	                      * with Phase 3c of the CSS rebuild — see audit
	                      * §5 pill matrix. */
	--radius-media: 2px;  /* canonical card/thumbnail IMAGE-frame corner radius.
	                       * Added 2026-06-06: card thumbnails had drifted to raw
	                       * 2px/3px/4px/none across feature/hero/coverage/related/
	                       * recent/video cards (the "why is this card slightly
	                       * different" bug). Every editorial-card thumb frame uses
	                       * this. Same value as --radius-chip but a distinct
	                       * semantic role (image frame vs chip), so thumbs have an
	                       * obvious token to reach for instead of a raw px. */
	--card-gap: 10px;     /* canonical image↔text gap for editorial/link cards
	                       * (feature / video / related / next-game / coverage).
	                       * Added 2026-06-06: had drifted to 8/9/10px across the
	                       * card family. The hero card keeps its own larger,
	                       * deliberate spacing (it's a distinct prominent tier). */
	--rail-w: 300px;
	--rail-col-gap: 48px;     /* content↔rail grid column gap — unified rail shell 2026-05-30 */
	--rail-gap: 24px;         /* vertical gap between stacked rail modules — unified rail shell 2026-05-30 */

	/* Shadows */
	--shadow-card: 0 1px 0 oklch(1 0 0 / .9) inset, 0 1px 2px oklch(0.2 0.02 70 / .04), 0 2px 6px oklch(0.2 0.02 70 / .035);

	/* Layout */
	--page-max: 1280px;       /* default outer container (article, homepage, schedule) */
	--page-max-data: 1080px;  /* data-heavy CPT pages (recruiting class today; future
	                           * recruiting archive, season pages) — tighter container
	                           * brings tables closer to their content density.
	                           * Added 2026-05-16 cohesion-pass brief. */
	--page-pad: 32px;
	--utility-h: 44px;
	--masthead-h: 88px;
	--schedule-h: 64px;
	--sched-cell-w: 128px;
	/* Offset for anything that pins below the sticky .chrome header stack
	 * (utility + masthead + schedule rows), plus a 24px breathing gap. Matches
	 * the video-post .flanked-rail sticky offset so pinned rail content clears
	 * the header consistently across templates. */
	--rail-sticky-top: calc(var(--utility-h) + var(--masthead-h) + var(--schedule-h) + 24px);

	/* Module-heading rhythm — applies to CPT module headings (.cpt-module-head).
	 * First introduced 2026-05-16 with the recruiting-class polish pass; values
	 * tuned that same day in the cohesion-pass brief so above:below totals
	 * roughly 2:1 (heading visually attaches to the content below, not above).
	 *
	 *   --space-module-top              vertical gap above a module heading
	 *                                   (separates modules from each other and
	 *                                   from the identity zone above)
	 *   --space-module-heading-rule     gap between the h2 and the hairline
	 *                                   rule beneath it (tight; the rule
	 *                                   anchors the heading to its content)
	 *   --space-module-rule-content     gap between the hairline rule and the
	 *                                   module body (table, grid, etc.)
	 *
	 * Resulting ratio: above (48) : total-below (10 + 14 = 24) = 2 : 1.
	 * See docs/design-system.md §CPT module headings. */
	--space-module-top: 48px;
	--space-module-heading-rule: 10px;
	--space-module-rule-content: 14px;

	/* Homepage region rhythm — added 2026-05-18 with the homepage port. The
	 * homepage stacks ~12 regions (hero, ads, video band, modules, river
	 * segments, season leaders) more than any prior surface, so region cadence
	 * is a defining attribute. Two scales:
	 *
	 *   --region-gap         standard region-to-region vertical transition
	 *                        (between hero region and ad slot, between modules
	 *                        and rivers, etc.)
	 *   --region-gap-large   reserved for the navy video band's top margin and
	 *                        internal padding — the band is the strongest
	 *                        structural break on the page (only edge-to-edge
	 *                        dark region), so it earns more breathing room
	 *   --module-padding-y   internal padding for thematic modules (Next/Last
	 *                        Game, Recruiting) and ad regions (A2/B/C/D). Used
	 *                        for the rhythm-inside-a-region scale.
	 *
	 * See sandbox/homepage/homepage.md §13.9 for the rationale on the navy
	 * band getting --region-gap-large. */
	--region-gap: 48px;
	--region-gap-large: 72px;
	--module-padding-y: 36px;
}


/* ===== /assets/css/goldendome-base.css ===== */
/* =======================================================================
 * Goldendome — base styles
 *
 * Tokens-first replacement for the legacy Jannah `assets/css/base.css`
 * (2,350 lines of 2016-era normalize + universal reset + Jannah body
 * defaults). Authored 2026-05-23 as Phase 5 of the CSS rebuild
 * (`tasks/css-rebuild-plan.md`).
 *
 * Loaded at `wp_enqueue_scripts` priority 5 from `functions.php` — sits
 * between `goldendome-tokens` (priority 1) and the surface-specific
 * sheets (priority 90). Replaces `tie-css-base` (Jannah) in the cascade.
 *
 * What this file does NOT do:
 *   - It does NOT carry forward Jannah's universal `* { list-style: none }`
 *     reset. That rule was load-bearing on the L19 cascade gotcha
 *     (`tasks/lessons.md` L19) where bullets in semantic <ul>s required
 *     direct `<li>` targeting to render. Bullets now work via simple
 *     `list-style: disc` on the <ul> as expected.
 *   - It does NOT carry forward Jannah's universal `outline: none` reset.
 *     `:focus-visible` ring is set explicitly in Block 6 so keyboard
 *     navigation has visible focus by default.
 *   - It does NOT include WordPress widget classes (`.widget`, `.widget_*`).
 *     Per decision D1 (`docs/decisions.md` 2026-05-22), no redesigned
 *     surface renders WP widget output — page.php uses a code-defined
 *     rail. Widget classes stay deleted with `widgets.css` in Phase 6.
 *
 * Block structure (per `tasks/css-rebuild-plan.md` Phase 5):
 *   1. Normalize          — minimal modern normalization
 *   2. Universal reset    — margin/padding/box-sizing only
 *   3. Body baseline      — token-based fallback
 *   4. Heading defaults   — h1-h6 fallback sizes (every surface overrides)
 *   5. Link baseline      — inherit color + underline
 *   6. A11y utilities     — .screen-reader-text + :focus-visible ring
 *   7. Form input baseline — token-based input/textarea/select
 *   8. Button baseline    — .button + [type="submit"] + secondary variant
 *   9. Table reset        — minimal; .data-table opts in
 *  10. Gutenberg defaults — .wp-block-* + .alignfull / .alignwide / etc.
 * ===================================================================== */


/* ===== 1. Normalize ================================================== *
 * Minimal modern normalization. Most of normalize.css v4 (2016) is dead
 * weight in 2026 — modern browsers agree on form-element rendering, SVG
 * sizing, table-cell defaults, etc. Just the few cross-browser quirks
 * that still matter: hidden attribute, sub/sup baselines, button font
 * inheritance, textarea overflow. */

[hidden] {
	display: none !important;
}

sub,
sup {
	font-size: 0.75em;
	line-height: 0;
	position: relative;
	vertical-align: baseline;
}
sub { bottom: -0.25em; }
sup { top:    -0.5em; }

button,
input,
optgroup,
select,
textarea {
	font-family: inherit;
	font-size: inherit;
	line-height: inherit;
	color: inherit;
}

button,
[type="button"],
[type="reset"],
[type="submit"] {
	-webkit-appearance: button;
}

textarea {
	overflow: auto;
	resize: vertical;
}

img,
svg,
video,
canvas,
audio,
iframe,
embed,
object {
	display: block;
	max-width: 100%;
	height: auto;
}

/* SVG inherit currentColor unless explicitly set. */
svg {
	fill: currentColor;
}


/* ===== 2. Universal reset ============================================ *
 * Margin/padding/box-sizing only. NO list-style: none (was load-bearing
 * on cascade gotcha per L19). NO outline: none (keyboard a11y). */

* {
	padding: 0;
	margin: 0;
	box-sizing: border-box;
}
*::before,
*::after {
	box-sizing: border-box;
}


/* ===== 3. Body baseline ============================================== *
 * Token-based fallback. Most surfaces explicitly set their own font-size
 * inside their per-surface sheet (e.g., `.article-body p` is 18px serif
 * via --type-doc-body-size; .card font-sizes come from --type-card-*
 * clamps). This baseline catches the unstyled tail — admin surfaces,
 * edge cases, future surfaces that haven't been authored yet.
 *
 * Body font-size set conservatively at 14px to avoid cascading bumps on
 * unported surfaces. Modern default would be 16px; bump in a future
 * decision once visual audit confirms no regressions. */

html {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	/* Phase 7a (2026-05-23): companion to `body { overflow-x: clip }`
	 * below. Caps document-level horizontal scroll on the root element
	 * too, since `overflow-x: clip` on body alone doesn't propagate to
	 * the documentElement in all browsers. */
	overflow-x: clip;
}

body {
	background: var(--bg);
	color: var(--text);
	font-family: var(--font-sans);
	font-size: 14px;
	line-height: 1.55;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	font-feature-settings: "kern" 1;
	text-rendering: optimizeLegibility;
	/* Phase 7a (2026-05-23): sitewide clip on horizontal overflow.
	 * Acts as a safety net so any single element with overflow past
	 * viewport (long unbreakable strings, wide tables that escape their
	 * scroll wrappers, etc.) doesn't extend the page canvas wide and
	 * trigger horizontal scroll across the whole site. Container-level
	 * scroll containers (`.table-scroll-wrap`, `.schedule-games`) still
	 * scroll their own contents; this only stops document-level scroll. */
	overflow-x: clip;
}


/* ===== 4. Heading defaults =========================================== *
 * Fallback sizes for h1-h6. Every redesigned surface overrides these
 * (article H1, category band H1, scoreboard H1, etc.) — these only
 * surface on unstyled or admin contexts.
 *
 * Serif headlines per the locked typography spec (docs/design-system.md
 * §6.1). Each level gets a sensible default; surface overrides set
 * the spec-correct clamp() sizes for editorial layouts. */

h1, h2, h3, h4, h5, h6 {
	font-family: var(--font-serif);
	font-weight: 600;
	line-height: 1.2;
	color: var(--text);
	letter-spacing: -0.01em;
}

h1 { font-size: 32px; }
h2 { font-size: 22px; }
h3 { font-size: 20px; }
h4 { font-size: 18px; }
h5 { font-size: 16px; }
h6 { font-size: 14px; }


/* ===== 5. Link baseline ============================================== *
 * Color inherits from context so on-dark surfaces don't override.
 * Underline + 2px offset so descenders don't collide with the rule.
 * :hover gets the accent color from tokens. */

a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 2px;
	text-decoration-thickness: 1px;
}

a:hover {
	color: var(--accent-hover);
	text-decoration-thickness: 2px;
}

a:focus-visible {
	outline: 2px solid var(--nd-navy);
	outline-offset: 2px;
}


/* ===== 6. Accessibility utilities ==================================== */

/* Screen-reader-only utility (WP convention). Visually hidden but
 * announced by assistive tech. */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	-webkit-clip-path: inset(50%);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}
.screen-reader-text:focus {
	background-color: var(--card-raised);
	border-radius: var(--radius);
	box-shadow: 0 0 2px 2px var(--accent-tint);
	clip: auto !important;
	-webkit-clip-path: none;
	clip-path: none;
	color: var(--nd-navy);
	display: block;
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 600;
	height: auto;
	left: 5px;
	line-height: normal;
	padding: 15px 23px 14px;
	text-decoration: none;
	top: 5px;
	width: auto;
	z-index: 100000;
}

/* Default focus ring for keyboard navigation. Per-component focus rings
 * can override; this is the fallback so nothing renders without a
 * visible focus indicator. */
:focus-visible {
	outline: 2px solid var(--nd-navy);
	outline-offset: 2px;
}


/* ===== 7. Form input baseline ======================================== *
 * Per-surface forms (comment form, schedule filter, search) carry their
 * own chrome; this is the unstyled-form fallback. */

input,
textarea,
select {
	font-family: var(--font-sans);
	font-size: 14px;
	color: var(--text);
	background: var(--card-raised);
	border: 1px solid var(--line);
	border-radius: var(--r-input);
	padding: 10px 12px;
	max-width: 100%;
	display: inline-block;
}

input[type="checkbox"],
input[type="radio"] {
	padding: 0;
	width: auto;
	margin-right: 6px;
	vertical-align: middle;
}

input[type="file"] {
	padding: 6px 8px;
	background: var(--bg-muted);
}

textarea {
	display: block;
	width: 100%;
	min-height: 100px;
}

input:focus,
textarea:focus,
select:focus {
	outline: 2px solid var(--nd-navy);
	outline-offset: 2px;
	border-color: var(--nd-navy);
}

::placeholder {
	color: var(--ink-3);
	opacity: 1;
}

label {
	display: inline-block;
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 600;
	color: var(--text);
	margin-bottom: 4px;
}

fieldset {
	border: 1px solid var(--line);
	border-radius: var(--radius);
	padding: 16px;
	margin: 0 0 16px;
}

legend {
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 600;
	padding: 0 6px;
}


/* ===== 8. Button baseline ============================================ *
 * Sitewide button primitive. Solid navy fill, white text, modest radius.
 * Per-surface buttons that need different chrome (schedule chips,
 * filter pills, etc.) opt out via their own classes. */

.button,
button.button,
input[type="submit"],
input[type="button"],
input[type="reset"],
button[type="submit"] {
	background: var(--nd-navy);
	color: #fff;
	border: 1px solid var(--nd-navy);
	border-radius: var(--r-input);
	padding: 10px 18px;
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: 0.01em;
	text-decoration: none;
	display: inline-block;
	cursor: pointer;
	transition: background .12s ease, border-color .12s ease, color .12s ease;
}

.button:hover,
button.button:hover,
input[type="submit"]:hover,
input[type="button"]:hover,
input[type="reset"]:hover,
button[type="submit"]:hover {
	background: var(--accent-hover);
	border-color: var(--accent-hover);
	color: #fff;
	text-decoration: none;
}

.button:focus-visible,
button:focus-visible,
input[type="submit"]:focus-visible,
input[type="button"]:focus-visible {
	outline: 2px solid var(--nd-gold);
	outline-offset: 2px;
}

/* Secondary / outline variant. Opt-in via .button--secondary. */
.button--secondary {
	background: transparent;
	color: var(--nd-navy);
}
.button--secondary:hover {
	background: var(--nd-navy);
	color: #fff;
}


/* ===== 9. Table reset ================================================ *
 * Minimal — strips Jannah's dotted-right-border default that redesigned
 * `.data-table` rules fought in 4+ places. `.data-table` (defined in
 * theme-root style.css §"Canonical body cell treatment") opts back in
 * to padding, hairlines, striping, header bg. Any non-`.data-table`
 * markup gets a clean unstyled table. */

table {
	border-collapse: collapse;
	width: 100%;
}

th,
td {
	border: 0;
	padding: 0;
	text-align: left;
	vertical-align: top;
}

caption {
	font-family: var(--font-mono);
	font-size: var(--type-mono-label-size);
	letter-spacing: var(--type-mono-label-tracking);
	text-transform: uppercase;
	color: var(--ink-3);
	padding: 8px 0;
	text-align: left;
	caption-side: top;
}


/* ===== 10. Gutenberg block defaults ================================== *
 * WP core block markup that arrives via `the_content()` on article,
 * page, and (rarely) CPT body content. Token-retoned versions of the
 * Jannah handlers that previously lived in `single.css:2641-2773`.
 *
 * Goldendome's article template (`single.php`) sets richer typography
 * on `.article-body` that wins via class specificity. These defaults
 * apply to:
 *   - page.php static-page content (rebuilt Phase 4b)
 *   - utility-page bodies (rebuilt Phase 4c)
 *   - any future surface that calls `the_content()` without a wrapping
 *     register class. */

/* Block paragraphs */
p {
	margin: 0 0 1em;
}
p:last-child {
	margin-bottom: 0;
}

/* Lists — vanilla defaults so semantic <ul>/<ol> render bullets/numbers
 * without per-surface workarounds. */
ul,
ol {
	margin: 0 0 1em;
	padding-left: 1.5em;
}
ul ul,
ol ol,
ul ol,
ol ul {
	margin-bottom: 0;
}
li {
	margin-bottom: 4px;
}
li:last-child {
	margin-bottom: 0;
}

/* Inline elements */
strong,
b {
	font-weight: 700;
}
em,
i {
	font-style: italic;
}
small {
	font-size: 0.875em;
}
mark {
	background: color-mix(in srgb, var(--nd-gold) 25%, transparent);
	color: var(--text);
	padding: 0 2px;
}
code,
kbd,
samp,
pre {
	font-family: var(--font-mono);
	font-size: 0.9em;
}
code {
	background: var(--bg-muted);
	padding: 1px 4px;
	border-radius: 3px;
}
pre {
	background: var(--bg-muted);
	padding: 12px 16px;
	border-radius: var(--radius);
	overflow-x: auto;
	margin: 0 0 1em;
}
pre code {
	background: transparent;
	padding: 0;
}

/* Blockquote — surface-specific overrides win (article template has
 * its own pull-quote/blockquote register). */
blockquote {
	margin: 0 0 1em;
	padding: 8px 0 8px 18px;
	border-left: 3px solid var(--nd-gold);
	color: var(--ink-2);
	font-family: var(--font-serif);
	font-style: italic;
}
blockquote p:last-child {
	margin-bottom: 0;
}

/* HR — token-aligned hairline */
hr {
	border: 0;
	border-top: 1px solid var(--line);
	margin: 24px 0;
}

/* Figures */
figure {
	margin: 0 0 1em;
}
figcaption {
	font-family: var(--font-mono);
	font-size: var(--type-micro-size);
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	color: var(--ink-3);
	margin-top: 6px;
}

/* WordPress alignment classes (legacy and current) */
.aligncenter {
	display: block;
	margin-left: auto;
	margin-right: auto;
}
.alignleft {
	float: left;
	margin: 0 18px 12px 0;
}
.alignright {
	float: right;
	margin: 0 0 12px 18px;
}
.alignnone {
	margin: 0 0 1em;
}
.alignfull {
	margin-left: calc(50% - 50vw);
	margin-right: calc(50% - 50vw);
	max-width: 100vw;
	width: 100vw;
}
.alignwide {
	margin-left: calc(50% - 45vw);
	margin-right: calc(50% - 45vw);
	max-width: 90vw;
	width: 90vw;
}

/* Gutenberg block classes — token-retoned versions of the
 * core-block treatments. */
.wp-block-image {
	margin: 0 0 1em;
}
.wp-block-image figcaption {
	text-align: center;
}

.wp-block-quote {
	margin: 0 0 1em;
	padding: 12px 0 12px 22px;
	border-left: 3px solid var(--nd-gold);
	font-family: var(--font-serif);
	font-style: italic;
	color: var(--ink-2);
}
.wp-block-quote cite {
	display: block;
	margin-top: 8px;
	font-family: var(--font-mono);
	font-size: var(--type-micro-size);
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	font-style: normal;
	color: var(--ink-3);
}

.wp-block-pullquote {
	margin: 24px 0;
	padding: 18px 24px;
	border-top: 3px solid var(--nd-navy);
	border-bottom: 3px solid var(--nd-navy);
	font-family: var(--font-serif);
	font-size: var(--type-pullquote-size);
	line-height: 1.35;
	text-align: center;
	color: var(--text);
}
.wp-block-pullquote cite {
	display: block;
	margin-top: 10px;
	font-family: var(--font-mono);
	font-size: var(--type-micro-size);
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	font-style: normal;
	color: var(--ink-3);
}

.wp-block-embed {
	margin: 0 0 1em;
}
.wp-block-embed figcaption {
	text-align: center;
}

.wp-block-table {
	margin: 0 0 1em;
}
.wp-block-table table {
	width: 100%;
}

/* Notre Dame NFL draft-history table. cfbd-sync writes this into the
 * 2007 draft-history post as `<figure class="wp-block-table
 * nd-draft-history is-style-stripes">`; the sync owns the markup, the
 * theme owns the look. Re-tone the block-table to the canonical
 * `.data-table` treatment (style.css §"Canonical body cell treatment")
 * so it reads like every other data table on the site instead of WP
 * core's grey zebra. Values mirror the canonical block exactly to avoid
 * drift; the `figure.` prefix on the stripe-suppress rules out-specifies
 * core's `.wp-block-table.is-style-stripes` regardless of load order. */
.nd-draft-history table {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--font-sans);
}
.nd-draft-history thead th {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
	text-align: left;
	background: var(--bg-header-row);
	padding: 10px 14px 12px;
	border: 0;
	border-bottom: 1px solid var(--line);
}
.nd-draft-history tbody td,
.nd-draft-history tbody th {
	padding: 14px;
	border: 0;
	border-bottom: 1px solid var(--line-soft);
	vertical-align: middle;
	color: var(--text);
	font-weight: 500;
}
.nd-draft-history tbody tr:hover {
	background: rgba(12, 35, 64, 0.025);
}
.nd-draft-history tbody tr:last-child td,
.nd-draft-history tbody tr:last-child th {
	border-bottom: 0;
}
/* Suppress WP core's is-style-stripes zebra so the canonical hover-only
 * treatment shows through. `figure.` lifts specificity to (0,3,3),
 * above core's (0,3,2) `nth-child(odd)` stripe. */
figure.nd-draft-history.is-style-stripes tbody tr:nth-child(odd),
figure.nd-draft-history.is-style-stripes tbody tr:nth-child(even) {
	background-color: transparent;
}
figure.nd-draft-history.is-style-stripes tbody tr:hover {
	background-color: rgba(12, 35, 64, 0.025);
}
/* Re-assert the canonical hairline dividers. WP core's table `style.min.css`
 * loads AFTER this bundle and zeroes the cell border color on the stripes
 * variant — `.wp-block-table.is-style-stripes td, th { border-color: #0000 }`
 * at (0,2,1) out-specifies the `.nd-draft-history tbody td` rule (0,1,2) above,
 * so without this the row dividers render transparent. The `figure.…
 * is-style-stripes` prefix lifts these back to (0,3,3)/(0,3,2) to win. */
figure.nd-draft-history.is-style-stripes tbody td,
figure.nd-draft-history.is-style-stripes tbody th {
	border-bottom: 1px solid var(--line-soft);
}
figure.nd-draft-history.is-style-stripes tbody tr:last-child td,
figure.nd-draft-history.is-style-stripes tbody tr:last-child th {
	border-bottom: 0;
}
figure.nd-draft-history.is-style-stripes thead th {
	border-bottom: 1px solid var(--line);
}
/* Core's `.wp-block-table thead { border-bottom: 3px solid }` (0,1,1) draws a
 * thick dark line on the thead element itself, and `.is-style-stripes`
 * (0,2,0) puts a stray `#f0f0f0` border under the whole figure. Reset both so
 * the only header/edge divider is the canonical 1px the cells carry above
 * (border-collapse otherwise prefers the wider 3px border at the shared edge). */
figure.nd-draft-history.is-style-stripes thead {
	border-bottom: 0;
}
figure.nd-draft-history.is-style-stripes {
	border-bottom: 0;
}

.wp-block-button {
	margin: 0 0 1em;
}
.wp-block-button__link {
	background: var(--nd-navy);
	color: #fff;
	border-radius: var(--r-input);
	padding: 10px 18px;
	font-family: var(--font-sans);
	font-weight: 600;
	text-decoration: none;
	display: inline-block;
	transition: background .12s ease;
}
.wp-block-button__link:hover {
	background: var(--accent-hover);
	color: #fff;
}

.wp-block-columns {
	display: flex;
	flex-wrap: wrap;
	gap: 24px;
	margin: 0 0 1em;
}
.wp-block-column {
	flex: 1 1 0;
	min-width: 0;
}

.wp-block-group {
	margin: 0 0 1em;
}

.wp-block-separator {
	border: 0;
	border-top: 1px solid var(--line);
	margin: 24px auto;
	max-width: 240px;
}

.has-text-align-left {
	text-align: left;
}
.has-text-align-center {
	text-align: center;
}
.has-text-align-right {
	text-align: right;
}

/* ===== Stats disclaimers (third-party data) ========================= */

/* Third-party-data note at the foot of the CFBD-stats CPT singles
 * (player / game / opponent / coach). Partial:
 * template-parts/cpt/stats-disclaimer.php. */
.stats-disclaimer {
	margin: 32px 0 0;
	padding-top: 16px;
	border-top: 1px solid var(--line-soft);
	font-family: var(--font-sans);
	font-size: var(--type-meta-size);
	line-height: 1.5;
	color: var(--ink-3);
}
.stats-disclaimer a {
	color: var(--accent);
	text-decoration: underline;
}

/* Per-player "derived season totals" footnote + the asterisk that marks
 * derived rows in the Career Season Stats table (cfbd-sync compiles those
 * seasons from the game log when CFBD's season endpoint omits them). */
.stats-derived-note {
	margin: 12px 0 0;
	font-family: var(--font-sans);
	font-size: var(--type-meta-size);
	line-height: 1.5;
	color: var(--ink-3);
}
.career-stats-table .derived-flag {
	margin-left: 2px;
	color: var(--ink-3);
	font-weight: 600;
}


/* ===== /assets/css/cards.css ===== */
/*
 * Goldendome — shared card primitives
 *
 * Canonical home for the `.feature-card` primitive (homepage news
 * features, category archives feature row, game-block article cards)
 * and the `.related-card .title` tertiary-register override used
 * wherever a tertiary card grid (news river, category river) needs
 * the sans/15px register from design-system §6.2 instead of the
 * article template's default serif/16.
 *
 * Promoted out of category.css + homepage.css 2026-05-22 as Phase 3b
 * of the CSS rebuild. Prior state shipped `.feature-card*` verbatim
 * in both files (homepage.css L13-14 header comment named this as a
 * known TODO). Both files now strip the duplicate; this is the single
 * source of truth.
 *
 * Loaded sitewide from functions.php at priority 75 so it stacks
 * above tokens (1) and below the theme-root child stylesheet (80).
 *
 * See:
 *   docs/components/cards.md — markup contract + variants
 *   docs/design-system.md §8 — card sensibility
 *   docs/design-system.md §6.2 — sans tertiary register
 */

/* ===== .team-mark ================================================= *
 *
 * No-trademark color-chip alternative to the team-logo <img> (see
 * inc/team-mark.php, docs/components/team-mark.md). Lives here — in the
 * sitewide bundle — so chips style on EVERY surface (schedule, homepage,
 * rail, sidebar, CPT bands), not just CPT pages. Fill + letter colors are
 * injected inline from synced team-color data (a data-driven exception to
 * tokens-not-values, docs/decisions.md 2026-07-07); structure stays
 * tokenized. Per-context sizing lives with each caller (e.g. .matchup-row
 * .team-mark in cpt-rough.css) or inline via the helper's inline_size.
 */
.team-mark {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	border-radius: 24%;
	font-family: var(--font-sans);
	font-weight: 800;
	letter-spacing: -0.02em;
	line-height: 1;
	overflow: hidden;
	background: var(--ink-4); /* neutral fallback; overridden inline when a team color exists */
	color: #fff; /* neutral fallback letter color; overridden inline */
}
/* Hairline ring for the both-colors-dark edge case on the navy band. */
.team-mark--ondark {
	box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.55);
}

/* ===== .feature-card =============================================== *
 *
 * The medium-tier editorial card: 16:9 image + optional kicker + serif
 * headline + optional serif italic deck + optional sans meta line. Used
 * by:
 *   - homepage hero region (feature column, horizontal variant)
 *   - homepage news river (vertical, in a 3-col grid)
 *   - homepage game-block article cards (horizontal, in column 2)
 *   - homepage recruiting module (vertical, in a 3-col grid)
 *   - category archive feature row (page 1 only, 2-up below the hero)
 *
 * Surface-specific variants (horizontal vs vertical, dense vs default)
 * are layered ON TOP of these base rules via parent-scope overrides
 * in homepage.css / category.css — those files contain only the
 * surface-specific deltas (different padding, hairline separators,
 * horizontal grid layout, etc.). */

.feature-card {
	display: flex;
	flex-direction: column;
	gap: var(--card-gap);
	text-decoration: none;
	color: inherit;
}

.feature-card__thumb {
	display: block;
	aspect-ratio: 16 / 9;
	background: var(--bg-muted);
	border-radius: var(--radius-media);
	overflow: hidden;
}
.feature-card__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.feature-card__kicker {
	font-family: var(--font-mono);
	font-size: var(--type-micro-size);
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
}

.feature-card__title {
	font-family: var(--font-serif);
	font-size: var(--type-card-feature-size);
	font-weight: 600;
	letter-spacing: -0.005em;
	line-height: 1.2;
	color: var(--nd-navy);
	margin: 0;
}

.feature-card__deck {
	font-family: var(--font-serif);
	font-size: 1rem;
	font-style: italic;
	line-height: 1.4;
	color: var(--text-muted);
	margin: 0;
}

.feature-card__meta {
	font-family: var(--font-sans);
	font-size: var(--type-meta-size);
	color: var(--ink-3);
}

.feature-card:hover .feature-card__title {
	color: var(--accent-hover);
}

/* ===== .related-card .title tertiary register ====================== *
 *
 * The shared `.related-card` partial (style.css §"Related articles")
 * defaults to serif/16 for the article-template related row. Two
 * tertiary-card grids on the site (homepage news river + category
 * river) need the design-system §6.2 sans/15px tertiary register
 * instead. Scoped override below covers both surfaces — same partial,
 * different visual context.
 *
 * Promoted 2026-05-22 alongside .feature-card. Prior state: identical
 * blocks in category.css L300-307 and homepage.css L346-353. */

.news-river .related-card .title,
.category-river .related-card .title {
	font-family: var(--font-sans);
	font-size: var(--type-card-tertiary-size);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.3;
	color: var(--nd-navy);
}

/* ===== .hero-card-overlay (design-system §8.1.4) ==================== *
 *
 * Overlay-style lead card: image fills the card behind a gradient
 * scrim; gold mono kicker + serif headline + sans byline sit on top of
 * the scrim in white. The only card variant that places text *on* the
 * image rather than below it. Markup partial:
 * template-parts/cards/hero-card-overlay.php.
 *
 * Used by:
 *   - homepage hero region (lead story — template-parts/homepage/hero-region.php)
 *   - Game CPT Latest Coverage (template-parts/cpt/game/latest-coverage.php)
 *
 * Promoted out of homepage.css 2026-07-04. Prior state scoped these
 * rules to homepage.css, which is not enqueued on Game CPT singles —
 * so the shared partial rendered raw on game pages (uncropped image,
 * plain-link kicker/headline/byline below it). Moving the primitive to
 * the sitewide bundle restores the intended overlay on every consumer.
 * Surface-specific deltas (the homepage hero-region grid stretch) stay
 * in homepage.css per the .feature-card pattern above. */

.hero-card-overlay {
	position: relative;
	display: block;
	text-decoration: none;
	color: #fff;
	border-radius: var(--radius-media);
	overflow: hidden;
	isolation: isolate;
	background: var(--bg-muted);
}
.hero-card-overlay:hover {
	text-decoration: none;
}
.hero-card-overlay__photo {
	display: block;
	aspect-ratio: 16 / 9;
	height: 100%; /* Stretch with the grid row so the card height matches the feature column (homepage). */
	min-height: 0;
}
.hero-card-overlay__photo img,
.hero-card-overlay__photo-placeholder {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
}
.hero-card-overlay__photo-placeholder {
	background: linear-gradient(
		135deg,
		color-mix(in srgb, var(--nd-navy) 92%, transparent) 0%,
		color-mix(in srgb, var(--nd-navy) 65%, transparent) 60%,
		color-mix(in srgb, var(--ink-2) 50%, transparent) 100%
	);
}
.hero-card-overlay__scrim {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(
		to top,
		rgba(0, 0, 0, 0.82) 0%,
		rgba(0, 0, 0, 0.62) 22%,
		rgba(0, 0, 0, 0.18) 55%,
		rgba(0, 0, 0, 0) 80%
	);
}
.hero-card-overlay__overlay {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: clamp(20px, 2.6vw, 36px) clamp(22px, 2.8vw, 40px) clamp(22px, 2.8vw, 36px);
	display: flex;
	flex-direction: column;
	gap: 14px;
}
/* .hero-card-overlay__kicker eyebrow → canonical .micro-label--lg --gold (2026-06-06).
 * Reassert here because the Game CPT nests the overlay inside
 * `.cpt-layout .cpt-content`, whose broad `.micro-label` rule
 * (cpt-rough.css, 0,3,0, loaded after the bundle) otherwise repaints
 * the kicker ink-3 — invisible on the scrim — and forces 12px + a
 * bottom margin. The 4-class selector (0,4,0) uses only the primitive's
 * own classes, so it holds in any surrounding context regardless of
 * cascade order. On the homepage (no `.cpt-layout` wrapper) it's inert. */
.hero-card-overlay .hero-card-overlay__kicker.micro-label.micro-label--gold {
	color: var(--nd-gold);
	font-size: var(--label-lg);
	margin: 0;
}
.hero-card-overlay__headline {
	font-family: var(--font-serif);
	font-size: var(--type-card-hero-size);
	font-weight: 700;
	letter-spacing: -0.018em;
	line-height: 1.05;
	color: #fff;
	margin: 0;
	text-wrap: balance;
	max-width: 24ch;
	text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
	transition: color 0.15s ease;
}
.hero-card-overlay:hover .hero-card-overlay__headline,
.hero-card-overlay:focus-visible .hero-card-overlay__headline {
	color: var(--nd-gold);
}
.hero-card-overlay__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	font-family: var(--font-sans);
	font-size: 13px;
	color: rgba(255, 255, 255, 0.78);
	margin-top: 2px;
}
.hero-card-overlay__byname {
	color: #fff;
	font-weight: 600;
}
.hero-card-overlay__dot {
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.45);
}

@media (max-width: 720px) {
	.hero-card-overlay__photo { aspect-ratio: 4 / 3; }
	.hero-card-overlay__overlay { padding: 18px 18px 18px; gap: 10px; }
	.hero-card-overlay__headline { font-size: 1.6rem; line-height: 1.08; max-width: none; }
	.hero-card-overlay__meta { font-size: 12px; }
}

@media (prefers-reduced-motion: reduce) {
	.hero-card-overlay__headline { transition: none; }
}


/* ===== /style.css ===== */
/*
  Theme Name:   Golden Dome
  Theme URI:    https://www.uhnd.com/
  Description:  Custom theme for UHND.com — Notre Dame football coverage site. Maintained internally.
  Author:       Frank Vitovitch
  Author URI:   https://www.uhnd.com/
  Version:      1.0.0
  License:      Proprietary — all rights reserved.
  Text Domain:  goldendome
  Tested up to: 6.9
  Requires at least: 5.0
*/

/* ======================================================================
 * Goldendome chrome — authored stylesheet.
 *
 * Phase 6d (2026-05-23): legacy block (~230 lines of Jannah-child
 * overrides on now-dead markup — `.magazine2`, `.mag-box`,
 * `.block-head-3`, `#schedule_table`, `.seasonnavbar`, `.entry-tags`,
 * `.taxonomy-info`, `#related-posts`, etc.) deleted. Every selector in
 * that block targeted Jannah markup that no redesigned surface emits.
 * Verified via HTML scan across homepage / coach / player / schedule /
 * category / about / search / 404 / article. The only utility worth
 * keeping is `.center` (preserved below — used by `.row-head__cell`).
 * ====================================================================== */

.center {
	text-align: center;
}

/* ======================================================================
 * Article-template port Phase 2.1b — sandbox chrome
 *
 * Lifted from sandbox/article-template.html (the first-order design
 * contract per docs/decisions.md 2026-05-07). Token references match
 * assets/css/tokens.css. Layout literals (728px ad width, 90px ad height,
 * 200px search min-width, etc.) are sandbox-as-starting-point per
 * CLAUDE.md "CSS Discipline" — Phase 5 prune pass tokenizes any that
 * recur or merit a semantic name.
 *
 * Coexists with Jannah's existing CSS at priority 10. This block loads
 * via tie_theme_child_styles_scripts (priority 80) so its declarations
 * win on shared selectors. New chrome uses semantic class names
 * (.utility-strip, .masthead, .schedule-strip) that don't collide with
 * Jannah's #main-nav / #tie-body selectors.
 * ====================================================================== */

/* Defensive: html and body fill the viewport so the full-bleed chrome
 * bands actually reach the viewport edges. Phase 2.1c dropped Jannah's
 * .background-overlay > #tie-container > #tie-wrapper but on builder
 * pages (homepage) something — likely a Jannah customizer or page-options
 * CSS emission keyed to has-builder / page-id — was still constraining
 * #tie-body's effective width, leaving white margins on either side of
 * the chrome bands. body#tie-body has higher specificity than the inline
 * customizer output; force full width and zero horizontal padding/margin.
 * Article pages were already rendering edge-to-edge, so this rule is a
 * no-op on those. */
html,
body#tie-body {
	width: 100%;
	max-width: none;
	margin: 0;
	padding: 0;
}
/* Body bg is `--bg` (warm cream) per docs/tokens.md and the comp at
 * sandbox/UHND Game Recap.html. Theme defaults didn't set this, so
 * pages without an explicit content surface (the game CPT views,
 * for example) were rendering against the browser-default white.
 * Set globally so chrome + content + footer share a coherent bg. */
body#tie-body {
	background: var(--bg);
}
/* Suppress the Jannah "card on white surface" pattern for Game and
 * Player CPT singles — the new design wants flat full-width content
 * against the body bg, not a constrained white card. The body class
 * `wrapper-has-shadow` (added by Jannah's body_class filter when the
 * customizer's site-wide shadow setting is on) and the generic
 * `#content` margin-top both interfere; reset both. */
body.single-game_entry #content,
body.single-player_profile #content {
	background: transparent;
	box-shadow: none;
	margin-top: 0;
	padding: 0;
}
body.single-game_entry #main-content-row,
body.single-player_profile #main-content-row {
	background: transparent;
	padding: 0;
}

/* Shared utilities used by chrome and (in later phases) body content */
.eyebrow {
	font-family: var(--font-mono);
	font-size: var(--type-mono-label-size);
	letter-spacing: var(--type-mono-label-tracking);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 500;
}
.section-title {
	font-family: var(--font-sans);
	font-size: var(--type-section-title-size);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .14em;
	color: var(--ink-2);
	margin: 0;
}

/* Status pill — canonical shared primitive (design-system §19.2a).
 * Used by:
 *   - Game CPT identity zone (Final / Scheduled / Win / Loss variants
 *     in cpt-rough.css + game.css)
 *   - Opponent CPT identity zone (Streak variant in cpt-rough.css)
 *   - Football schedule rows (Final / Scheduled variants — same tokens)
 *
 * Promoted to a sitewide primitive 2026-05-22 with Phase 3d of the
 * CSS rebuild. Previously defined in cpt-rough.css:422 (CPT-only enqueue)
 * AND duplicated in style.css:3256 under .schedule-page scope — that
 * duplicate is now gone. Surface-specific variant tokens (--pill-final-*,
 * --pill-scheduled-*) live in tokens.css; ink/bg overrides on dark
 * surfaces (Game CPT navy band, Opponent navy band) live in game.css
 * and cpt-rough.css's opponent-band block. */
.status-pill {
	display: inline-block;
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	font-weight: 700;
	padding: 4px 10px;
	border-radius: var(--radius);
	line-height: 1;
}
.status-pill--final {
	background-color: var(--pill-final-bg);
	color: var(--pill-final-fg);
}
.status-pill--scheduled {
	background-color: var(--pill-scheduled-bg);
	color: var(--pill-scheduled-fg);
}

/* Pagination — canonical sitewide primitive.
 *
 * Visual register matches the .schedule-filters__chip + .season-archive__year
 * pill family (mono tabular numerics, 9999px outlined chip → solid navy on
 * active) so paginated surfaces feel cohesive with the rest of the theme's
 * chip vocabulary. Prev / Next render in the same chip shape but pre-
 * filled with navy + uppercase mono labels — a visually distinct "go
 * forward" / "go back" affordance that still sits inside the chip family.
 *
 * Markup contract (rendered by goldendome_render_pagination() helper):
 *   <nav class="pagination-row" aria-label="…">
 *     <ul class="pagination-list">
 *       <li><a class="page-numbers prev" …>← Prev</a></li>
 *       <li><a class="page-numbers" …>1</a></li>
 *       <li><span class="page-numbers current" aria-current="page">2</span></li>
 *       <li><span class="page-numbers dots" aria-hidden="true">…</span></li>
 *       <li><a class="page-numbers next" …>Next →</a></li>
 *     </ul>
 *   </nav>
 *
 * Sitewide primitive — consumers: category / tag archives, utility
 * pages (search / author / date-archive), any future paginated
 * surface. Promoted from category.css 2026-05-22 with Phase 4c.
 * Restyled 2026-05-22 follow-up to match the chip-family register. */
.pagination-row {
	margin-top: 36px;
	padding-top: 20px;
	border-top: 1px solid var(--line-soft);
	display: flex;
	justify-content: center;
}
.pagination-list {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	list-style: none;
	margin: 0;
	padding: 0;
}
.pagination-list a,
.pagination-list span {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 32px;
	min-width: 32px;
	padding: 0 10px;
	background: var(--card-raised);
	border: 1px solid var(--line);
	border-radius: 9999px;
	color: var(--ink-2);
	font-family: var(--font-mono);
	font-variant-numeric: tabular-nums;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: var(--tracking-mono-tight);
	text-decoration: none;
	transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.pagination-list a:hover,
.pagination-list a:focus-visible {
	background: var(--bg-muted);
	border-color: var(--line-strong);
	color: var(--nd-navy);
	outline: none;
}
.pagination-list .current {
	background: var(--nd-navy);
	color: #fff;
	border-color: var(--nd-navy);
}
.pagination-list .dots {
	background: transparent;
	border-color: transparent;
	color: var(--ink-3);
	min-width: 24px;
	padding: 0 4px;
}
/* Prev / Next — filled-navy variant. Same chip shape, pre-active fill,
 * mono uppercase short labels. Wider padding for the label. */
.pagination-list .prev,
.pagination-list .next {
	background: var(--nd-navy);
	color: #fff;
	border-color: var(--nd-navy);
	padding: 0 14px;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-loose);
}
.pagination-list .prev:hover,
.pagination-list .prev:focus-visible,
.pagination-list .next:hover,
.pagination-list .next:focus-visible {
	background: var(--accent-hover);
	color: #fff;
	border-color: var(--accent-hover);
	outline: none;
}

.page {
	max-width: var(--page-max);
	margin: 0 auto;
	padding: 0 var(--page-pad);
}

/* A11y focus ring */
.chrome :focus-visible,
.top-ad-band :focus-visible {
	outline: 2px solid var(--nd-green);
	outline-offset: 2px;
	border-radius: 3px;
}

/* Chrome-scoped button reset.
 * Jannah's global button styles include a white background and border that
 * leak into chrome buttons (hamburger, share icons). Reset within chrome
 * surfaces only — broader reset deferred to Phase 5 CSS lift. */
.chrome button,
.top-ad-band button {
	font-family: inherit;
	cursor: pointer;
	border: 0;
	background: transparent;
	color: inherit;
	padding: 0;
}

/* Above-masthead ad band */
.top-ad-band {
	background: var(--bg-sunk);
	border-bottom: 1px solid var(--line-soft);
	padding: 8px 0 14px;
}
.top-ad-band .ad-label {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ad-label-ink);
	text-align: center;
	margin: 0 0 6px;
	font-weight: 500;
}
.top-ad-band .ad-frame {
	width: 728px;
	max-width: 100%;
	height: 90px;
	margin: 0 auto;
	border: 1px solid var(--ad-frame);
	background: var(--bg);
	display: grid;
	place-items: center;
	background-image: repeating-linear-gradient(45deg, var(--bg-muted) 0 8px, color-mix(in srgb, var(--bg-muted) 60%, var(--bg)) 8px 16px);
}
.top-ad-band .ad-frame .lbl {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: .1em;
	text-transform: uppercase;
	background: rgba(255, 255, 255, .7);
	padding: 4px 10px;
	border-radius: var(--radius-chip);
}

/* Sticky chrome wrapper */
.chrome {
	position: sticky;
	top: 0;
	z-index: 50;
	background: var(--bg-sunk);
	box-shadow: 0 1px 0 var(--line-soft);
}

/* Row 1 — utility strip (cream sunken band) */
.utility-strip {
	background: var(--bg-sunk);
	height: var(--utility-h);
	border-bottom: 1px solid var(--line-soft);
	color: var(--ink-2);
}
.utility-inner {
	max-width: var(--page-max);
	margin: 0 auto;
	height: 100%;
	padding: 0 var(--page-pad);
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 14px;
}
.utility-search {
	display: flex;
	align-items: center;
	gap: 8px;
	height: 22px;
	padding: 0 10px;
	background: #fff;
	border: 1px solid var(--line-soft);
	border-radius: 3px;
	color: var(--ink-3);
	font-family: var(--font-sans);
	font-size: 12px;
	min-width: 200px;
	text-decoration: none;
}
.utility-search:hover,
.utility-search:focus-within {
	border-color: var(--line-strong);
	color: var(--ink-2);
	text-decoration: none;
}
.utility-search svg {
	flex-shrink: 0;
	color: var(--ink-3);
}
.utility-search__submit {
	display: flex;
	align-items: center;
	padding: 0;
	margin: 0;
	border: 0;
	background: none;
	color: var(--ink-3);
	cursor: pointer;
}
.utility-search__field {
	flex: 1 1 auto;
	min-width: 0;
	padding: 0;
	margin: 0;
	border: 0;
	background: none;
	color: var(--ink-2);
	font-family: var(--font-sans);
	font-size: 12px;
	line-height: 22px;
}
.utility-search__field::placeholder {
	color: var(--ink-4);
}
.utility-search__field:focus {
	outline: none;
}
.utility-search__field::-webkit-search-cancel-button,
.utility-search__field::-webkit-search-decoration {
	-webkit-appearance: none;
	appearance: none;
}
.utility-social {
	display: flex;
	align-items: center;
	gap: 0;
	height: 100%;
}
.utility-social a {
	width: 28px;
	height: 28px;
	display: grid;
	place-items: center;
	color: var(--ink-3);
	border-radius: 3px;
	text-decoration: none;
}
.utility-social a:hover {
	color: var(--nd-navy);
	background: var(--accent-tint);
	text-decoration: none;
}
.utility-divider {
	width: 1px;
	height: 14px;
	background: var(--line);
	margin: 0 6px;
}

/* Row 2 — navy masthead */
.masthead {
	height: var(--masthead-h);
	background: var(--nd-navy);
	color: #fff;
	border-bottom: 1px solid color-mix(in srgb, var(--nd-gold) 25%, transparent);
}
.masthead-inner {
	max-width: var(--page-max);
	margin: 0 auto;
	height: 100%;
	padding: 0 var(--page-pad);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 40px;
}
.masthead .brand {
	display: flex;
	align-items: center;
	gap: 18px;
	height: 100%;
}
.masthead .hamburger {
	width: 36px;
	height: 36px;
	border-radius: 4px;
	display: grid;
	place-items: center;
	color: var(--video-band-ink-2);
}
.masthead .hamburger:hover {
	background: var(--video-band-line);
	color: #fff;
}
.masthead .logo {
	display: flex;
	align-items: center;
	height: 100%;
	text-decoration: none;
}
.masthead .logo:hover { text-decoration: none; }
.masthead .logo img {
	max-height: 48px;
	width: auto;
	max-width: 320px;
	display: block;
}

/* ── Primary drawer — universal hamburger nav (mobile + desktop) ─────
 *
 * Markup in template-parts/chrome/primary-drawer.php. JS lifecycle in
 * assets/js/primary-drawer.js. Triggered by .masthead .hamburger.
 *
 * Layout: full-viewport overlay with a left-anchored panel that slides
 * in from off-canvas. The `hidden` attribute is the JS-controlled state;
 * we override the default `[hidden] { display: none }` so the panel
 * stays in the DOM and the transform/opacity transitions can fire.
 *
 * Token-only. prefers-reduced-motion disables the slide animation.
 * Authored 2026-05-22 as Phase 1 of the CSS rebuild; pattern borrowed
 * structurally from Jannah's #mobile-menu in helpers.css:634-817 but
 * rebuilt fresh with tokens, vanilla-JS hooks, and an inverted (light)
 * panel surface. */

.primary-drawer {
	position: fixed;
	inset: 0;
	z-index: 100;
	visibility: visible;
	pointer-events: auto;
}
/* Override the user-agent `[hidden] { display: none }` so the panel
 * stays renderable for the transform/opacity transitions. */
.primary-drawer[hidden] {
	display: block;
	visibility: hidden;
	pointer-events: none;
}

.primary-drawer__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(12, 35, 64, 0.55);
	opacity: 0;
	transition: opacity 0.22s ease;
}
.primary-drawer:not([hidden]) .primary-drawer__backdrop {
	opacity: 1;
}

.primary-drawer__panel {
	position: absolute;
	top: 0;
	left: 0;
	height: 100%;
	width: 320px;
	max-width: 85vw;
	background: var(--bg);
	color: var(--text);
	display: flex;
	flex-direction: column;
	transform: translateX(-100%);
	transition: transform 0.25s ease;
	overflow-y: auto;
	box-shadow: 0 0 24px rgba(12, 35, 64, 0.18);
}
.primary-drawer:not([hidden]) .primary-drawer__panel {
	transform: translateX(0);
}

.primary-drawer__header {
	background: var(--nd-navy);
	color: #fff;
	padding: 0 18px;
	height: var(--masthead-h);
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-shrink: 0;
	border-bottom: 1px solid color-mix(in srgb, var(--nd-gold) 25%, transparent);
}
/* .primary-drawer__title eyebrow → canonical .micro-label--lg --gold (2026-06-06). */
.primary-drawer__close {
	width: 36px;
	height: 36px;
	border-radius: 4px;
	display: grid;
	place-items: center;
	color: var(--video-band-ink-2);
	background: transparent;
	border: 0;
	cursor: pointer;
	padding: 0;
}
.primary-drawer__close:hover,
.primary-drawer__close:focus-visible {
	background: var(--video-band-line);
	color: #fff;
	outline: none;
}

.primary-drawer__nav {
	flex: 1 1 auto;
	padding: 8px 0 24px;
}
.primary-drawer__menu,
.primary-drawer .sub-menu {
	list-style: none;
	margin: 0;
	padding: 0;
}
.primary-drawer__menu > li {
	border-bottom: 1px solid var(--line-soft);
	position: relative;
}
.primary-drawer__menu > li:last-child {
	border-bottom: 0;
}
.primary-drawer__menu a {
	display: block;
	padding: 14px 50px 14px 22px;
	font-family: var(--font-sans);
	font-size: 15px;
	font-weight: 600;
	letter-spacing: 0.02em;
	color: var(--nd-navy);
	text-decoration: none;
	line-height: 1.3;
}
.primary-drawer__menu a:hover,
.primary-drawer__menu a:focus-visible {
	background: var(--bg-sunk);
	color: var(--nd-navy);
	text-decoration: none;
	outline: none;
}
.primary-drawer__menu a[aria-current="page"] {
	color: var(--nd-navy);
	background: color-mix(in srgb, var(--nd-gold) 14%, transparent);
}

/* Expand chevron — injected by primary-drawer.js next to every
 * <li class="menu-item-has-children"> parent link. Toggling its
 * adjacent <li>.is-open class reveals/hides the nested <ul>. */
.primary-drawer__expand {
	position: absolute;
	right: 6px;
	top: 4px;
	width: 44px;
	height: 44px;
	display: grid;
	place-items: center;
	background: transparent;
	border: 0;
	cursor: pointer;
	color: var(--ink-3);
	padding: 0;
	transition: transform 0.2s ease, color 0.15s ease;
}
.primary-drawer__expand:hover,
.primary-drawer__expand:focus-visible {
	color: var(--nd-navy);
	outline: none;
}
.menu-item-has-children.is-open > .primary-drawer__expand {
	transform: rotate(180deg);
}

/* Nested sub-menus — collapsed by default, revealed via .is-open on
 * the parent <li>. Indented and slightly muted vs. the top-level. */
.primary-drawer .sub-menu {
	display: none;
	background: var(--bg-sunk);
	border-top: 1px solid var(--line-soft);
}
.primary-drawer .menu-item-has-children.is-open > .sub-menu {
	display: block;
}
.primary-drawer .sub-menu li {
	border-bottom: 1px solid var(--line-soft);
}
.primary-drawer .sub-menu li:last-child {
	border-bottom: 0;
}
.primary-drawer .sub-menu a {
	padding: 11px 22px 11px 38px;
	font-size: 14px;
	font-weight: 500;
	color: var(--ink-2);
}
.primary-drawer .sub-menu .sub-menu a {
	padding-left: 54px;
	font-size: 13px;
}

/* Reduced motion — instant open/close, no slide. */
@media (prefers-reduced-motion: reduce) {
	.primary-drawer__backdrop,
	.primary-drawer__panel,
	.primary-drawer__expand {
		transition: none;
	}
}

/* Primary nav — flat top-level row on desktop. Sub-menus + the "More"
 * overflow item live in the universal hamburger drawer
 * (template-parts/chrome/primary-drawer.php), not here. Hidden at
 * ≤720px by the masthead-mobile breakpoint below this block.
 * Simplified 2026-05-22 alongside the universal drawer (Phase 1 CSS
 * rebuild); prior version carried .nav-item.has-submenu chevron +
 * hover/focus-within .sub-menu reveal + a 320px navy dropdown panel
 * — all deleted now that the drawer carries the full hierarchy. */
.nav-primary {
	display: flex;
	align-items: stretch;
	gap: 0;
	height: 100%;
	position: relative;
}
.nav-item {
	display: inline-flex;
	align-items: stretch;
	height: 100%;
	position: relative;
}
.nav-item > a {
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: .1em;
	color: rgba(255, 255, 255, .85); /* Off-ramp: brighter than --video-band-ink-2 (0.78) for legible top-strip nav. */
	/* Phase 7a (2026-05-23): horizontal padding scales with viewport so the
	 * strip doesn't cram against the search/login chrome on intermediate
	 * widths (900-1100). 22px at full desktop; ~12px at the bottom of the
	 * visible range. Was P0-2 in the responsive audit. */
	padding: 0 clamp(12px, 1.5vw, 22px);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	position: relative;
	text-decoration: none;
	border-left: 1px solid var(--video-band-line-strong);
	transition: color .15s ease, background .15s ease;
}
.nav-item:last-child > a {
	border-right: 1px solid var(--video-band-line-strong);
}
.nav-item > a:hover {
	color: #fff;
	background: var(--video-band-line);
	text-decoration: none;
}
.nav-item > a[aria-current="page"] {
	color: #fff;
	/* Active-section wash: the recruiting-chart kelly green (--green-utility),
	 * cooled toward navy so it carries a slight blue cast (teal-leaning)
	 * rather than reading as a pure bright kelly green. Two knobs:
	 *   inner mix — green nudged ~18% toward --nd-navy = the blue wash;
	 *   outer mix — drawn at 48% over the navy strip = the brightness/presence.
	 * Gold underline below stays the primary accent. Frank's call 2026-05-30
	 * (dialed back + blue-shifted from the brighter 55% pure-green pass). */
	background: color-mix(in srgb, color-mix(in srgb, var(--green-utility) 82%, var(--nd-navy)) 48%, transparent);
}
.nav-item > a[aria-current="page"]::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: -1px;
	height: 3px;
	background: var(--nd-gold);
}

/* ── Masthead mobile layout (≤900px) ───────────────────────────────
 *
 * At narrow widths the desktop primary strip hides and the logo
 * centers horizontally in the masthead. The hamburger button stays
 * on the left edge as the universal nav trigger. Implementation uses
 * a 3-column CSS grid on .masthead-inner (hamburger | logo | empty
 * symmetry track) with `display: contents` on .brand so hamburger +
 * logo become direct grid children. Authored 2026-05-22 alongside
 * the universal hamburger drawer (Phase 1 of the CSS rebuild).
 *
 * Phase 7a (2026-05-23): breakpoint raised from 720px to 900px. The
 * drawer is universal on every viewport, so the primary strip is a
 * pure desktop enhancement — and the strip needs ~1000px to render
 * comfortably alongside the brand cluster and search/login icons.
 * Was P0-2 in the responsive audit. */
@media (max-width: 900px) {
	.nav-primary {
		display: none;
	}
	.masthead-inner {
		display: grid;
		grid-template-columns: 44px 1fr 44px;
		gap: 0;
	}
	.masthead .brand {
		display: contents;
	}
	.masthead .hamburger {
		grid-column: 1;
		justify-self: start;
	}
	.masthead .logo {
		grid-column: 2;
		justify-self: center;
	}
}

/* Row 3 — schedule strip */
.schedule-strip {
	/* Sandbox uses an oklch literal here, slightly more saturated than --bg-sunk.
	 * Phase 5 prune candidate: promote to --schedule-strip-bg if the value recurs. */
	background: oklch(0.955 0.012 80);
	height: var(--schedule-h);
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
	/* Phase 7a (2026-05-23): clip the strip's outer edges so its inner
	 * games row can horizontal-scroll without pushing the page canvas
	 * past viewport. Was P0-1 in the responsive audit — at 320px the
	 * strip's ~1,664px of fixed-width game cells (13 × 128px) extended
	 * the canvas to 1,124px+, forcing every page below it to scroll
	 * horizontally. Now the strip stays viewport-wide, games scroll
	 * inside .schedule-games. */
	overflow: hidden;
}
.schedule-inner {
	max-width: var(--page-max);
	margin: 0 auto;
	height: 100%;
	padding: 0 var(--page-pad);
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	align-items: center;
	gap: 18px;
}
.schedule-record {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1px;
	flex-shrink: 0;
	font-family: var(--font-sans);
	line-height: 1.15;
}
.schedule-record::after {
	content: "";
	position: absolute;
	top: 50%;
	right: -18px;
	transform: translateY(-50%);
	width: 1px;
	height: 32px;
	background: var(--line-strong);
}
.schedule-record .rec {
	font-size: 16px;
	font-weight: 700;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	letter-spacing: .01em;
	white-space: nowrap;
}
.schedule-record .rank {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--ink-3);
	letter-spacing: .06em;
	font-weight: 600;
	text-transform: uppercase;
	white-space: nowrap;
}
.schedule-games {
	display: flex;
	align-items: stretch;
	gap: 0;
	justify-content: center;
	height: 100%;
	/* Phase 7a (2026-05-23): at desktop the flex row holds the 7-game window
	 * cleanly within --page-max. min-width:0 keeps this grid child from
	 * pushing the parent past viewport when the row's natural content
	 * width exceeds the available track. At ≤900px the cell visibility
	 * collapses to one focal cell paginated by prev/next arrows — see
	 * the @media block below + `.schedule-games__nav` rules. */
	min-width: 0;
}

/* Prev / next focal navigation — visible only at narrow widths where the
 * flex row collapses to a single focal cell. */
.schedule-games__nav {
	display: none;
}
.sched-cell {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: flex-start;
	padding: 0 14px;
	height: 100%;
	width: var(--sched-cell-w);
	flex-shrink: 0;
	border-left: 1px solid var(--line-soft);
	text-decoration: none;
	color: inherit;
	position: relative;
	transition: background .12s ease;
}
.sched-cell:first-child { border-left: 0; }
.sched-cell:hover {
	background: rgba(12, 35, 64, 0.04);
	text-decoration: none;
}

/* Past cells — opponent on top, score below */
.sched-cell.past .s-match {
	font-family: var(--font-sans);
	font-size: 12.5px;
	font-weight: 700;
	color: var(--nd-navy);
	letter-spacing: .01em;
	display: flex;
	align-items: baseline;
	gap: 5px;
	margin-bottom: 3px;
}
.sched-cell.past .s-match .s-at {
	color: var(--ink-4);
	font-weight: 500;
	font-size: 11px;
}
.sched-cell.past .s-top {
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	color: var(--ink-3);
	font-variant-numeric: tabular-nums;
	letter-spacing: .02em;
	display: inline-flex;
	align-items: center;
	gap: 5px;
}
.sched-cell.past .s-wl { font-weight: 700; font-size: 10.5px; }
.sched-cell.past .s-wl.w { color: var(--nd-green); }
.sched-cell.past .s-wl.l { color: var(--danger); }

/* Future cells — opponent on top, date/time below */
.sched-cell.future .s-match {
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 700;
	color: var(--nd-navy);
	letter-spacing: .01em;
	display: flex;
	align-items: baseline;
	gap: 5px;
	margin-bottom: 4px;
}
.sched-cell.future .s-match .s-at {
	color: var(--ink-4);
	font-weight: 500;
	font-size: 11px;
}
.sched-cell.future .s-match .s-rank {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--ink-3);
	font-weight: 600;
	margin-right: 1px;
	letter-spacing: .02em;
}
.sched-cell.future .s-top {
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	color: var(--ink-3);
	display: flex;
	align-items: center;
	gap: 5px;
	font-variant-numeric: tabular-nums;
}
/* Bye cell */
.sched-cell.bye {
	justify-content: center;
	align-items: center;
	color: var(--ink-4);
}
.sched-cell.bye .s-lbl {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .18em;
	text-transform: uppercase;
	font-weight: 700;
}

/* Current/next-up — gold wash, no rules */
.sched-cell.next {
	background: color-mix(in srgb, var(--nd-gold) 14%, transparent);
}

.schedule-cta {
	font-family: var(--font-sans);
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
	color: var(--nd-navy);
	text-decoration: none;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	gap: 5px;
}
/* Default (desktop) CTA: "Full" + "Schedule →" sit inline on one row. The
 * l1/l2 spans came in with the mobile rework but had no base layout, so on
 * desktop l2's text + arrow wrapped to two lines and align-items:center
 * dropped "Full" to the vertical middle (misaligned read). Keep l2 inline
 * so the arrow stays beside the word and both labels share one baseline.
 * The ≤900px block restacks these vertically. */
.schedule-cta__l2 {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	white-space: nowrap;
}
.schedule-cta:hover {
	color: var(--accent-hover);
	text-decoration: none;
}
.schedule-cta:hover svg { transform: translateX(2px); }

/* Empty state — no games in current season */
.schedule-strip--empty .schedule-inner {
	display: flex;
	justify-content: center;
	align-items: center;
}
/* .schedule-empty-msg eyebrow → canonical .micro-label--lg (2026-06-06). */
.schedule-cta svg { transition: transform .15s ease; }

/* ── Schedule strip mobile — paginated focal-cell with arrows ────────
 * At ≤900px the games row collapses to a single visible focal cell
 * with prev/next arrows on either side. The default focal is the next
 * upcoming game when within 6 days of kickoff, else the just-played
 * game on gameday+1, else next upcoming (handled in PHP partial).
 * Arrows step the focal class through all season games.
 *
 * Mobile layout has three vertical-rule-separated zones for symmetry:
 *   record |◄ focal cell ►| Full schedule
 * The record-side rule lives on .schedule-record::after (carried over
 * from desktop). The games-side rule is added below on
 * .schedule-games::after so the focal-arrow zone has equal weight on
 * each side.
 *
 * Phase 7a (2026-05-23): replaces the brief horizontal-scroll workaround.
 * Frank's directive — paginated arrows, not touch-scroll. */
@media (max-width: 900px) {
	/* Three-column mobile layout: equal-width fixed sides for symmetry,
	 * middle takes the remainder. The fixed 80px sides accommodate
	 * "Schedule →" on line 2 of the CTA; "2026"/"0-0" on the left fits
	 * comfortably within the same width. All three columns center-align
	 * their content so the strip reads symmetrical across. */
	.schedule-inner {
		grid-template-columns: 80px minmax(0, 1fr) 80px;
		gap: 8px;
		padding: 0 10px;
	}
	/* Record column: stack year above record, center-align both. */
	.schedule-record {
		align-items: center;
		gap: 0;
	}
	.schedule-record .rec {
		display: flex;
		flex-direction: column;
		align-items: center;
		font-size: 12px;
		line-height: 1.1;
	}
	.schedule-record .rec__sep { display: none; }
	.schedule-record .rec__year {
		font-size: 11px;
		font-weight: 600;
		color: var(--ink-3);
		letter-spacing: .02em;
	}
	.schedule-record .rec__record {
		font-size: 14px;
		font-weight: 700;
		color: var(--nd-navy);
	}
	.schedule-record .rank {
		font-size: 9px;
		margin-top: 1px;
	}
	.schedule-games {
		display: grid;
		grid-template-columns: 24px minmax(0, 1fr) 24px;
		align-items: stretch;
		justify-content: stretch;
	}
	/* Focal cell is the main event on mobile — bump its content above the
	 * desktop sizes so the schedule strip reads "this week's game" loudly. */
	.sched-cell.is-focal.future .s-match,
	.sched-cell.is-focal.past .s-match {
		font-size: 15px;
	}
	.sched-cell.is-focal.future .s-top,
	.sched-cell.is-focal.past .s-top {
		font-size: 12px;
	}
	/* Soften the gold "next" wash on mobile so it accents the focal cell
	 * without competing with the now-larger text inside it. */
	.sched-cell.next {
		background: color-mix(in srgb, var(--nd-gold) 9%, transparent);
	}
	.schedule-games__nav {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		background: transparent;
		border: 0;
		padding: 0;
		cursor: pointer;
		color: var(--ink-2);
		transition: color .12s ease, background .12s ease;
	}
	.schedule-games__nav:hover:not(:disabled) {
		background: rgba(12, 35, 64, 0.04);
		color: var(--nd-navy);
	}
	.schedule-games__nav:focus-visible {
		outline: 2px solid var(--nd-navy);
		outline-offset: -2px;
	}
	.schedule-games__nav:disabled {
		opacity: 0.35;
		cursor: default;
	}
	.schedule-games__nav svg {
		width: 16px;
		height: 16px;
		display: block;
	}
	/* Hide every non-focal cell; the focal one fills the middle track.
	 * Center-align the focal cell content horizontally for symmetry with
	 * the now centered side columns. */
	.sched-cell {
		display: none;
		width: auto;
		border-left: 0;
		padding: 0 16px;
		align-items: center;
		justify-content: center;
	}
	.sched-cell.is-focal {
		display: flex;
	}

	/* Vertical rules flanking the games column. To guarantee
	 * pixel-identical rendering on both sides (the prior split between
	 * `.schedule-record::after` on the left and `.schedule-games::after`
	 * on the right rendered visually mismatched even with identical
	 * width/height/color tokens), both rules live on the same element
	 * via ::before + ::after, with mirror-symmetric left/right offsets.
	 *
	 * `content: none` on the original `.schedule-record::after` removes
	 * the pseudo entirely at this breakpoint. (Bare `display: none`
	 * leaves the pseudo in the rendering tree on some browsers and the
	 * 1px rule was visibly stacking with `.schedule-games::before` —
	 * occupying the same pixel position — giving the left border a
	 * subtly thicker appearance than the right.) */
	.schedule-record::after {
		content: none;
	}
	.schedule-games {
		position: relative;
	}
	.schedule-games::before,
	.schedule-games::after {
		content: "";
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		width: 1px;
		height: 32px;
		background: var(--line-strong);
	}
	.schedule-games::before { left:  -1px; }
	.schedule-games::after  { right: -1px; }

	/* CTA column: stack "Full" above "Schedule", center-aligned for
	 * symmetry with the record column on the left. The arrow is dropped on
	 * the stacked layout (see .schedule-cta__l2 below) — it widened line 2's
	 * box and made "Full" read off-center over the word. The whole cell is a
	 * tap target on mobile, so the arrow affordance isn't needed here; it
	 * stays on the single-line desktop CTA. */
	.schedule-cta {
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 0;
		font-size: 10px;
		line-height: 1.15;
		text-align: center;
	}
	.schedule-cta__l1 {
		font-size: 9px;
		color: var(--ink-3);
		font-weight: 600;
	}
	.schedule-cta__l2 {
		display: inline-flex;
		align-items: center;
		font-weight: 700;
	}
	/* Drop the trailing arrow on the stacked mobile CTA so "Full" centers
	 * cleanly over "Schedule" rather than over "Schedule + arrow". */
	.schedule-cta__l2 svg {
		display: none;
	}
}

/* Reading-progress bar — pinned to chrome bottom edge.
 * The width animates via the --progress custom property; JS that updates
 * it ships in Phase 2.1d (assets/js/reading-progress.js). */
.reading-bar {
	position: absolute;
	left: 0;
	right: 0;
	bottom: -1px;
	height: 2px;
	background: var(--nd-gold);
	width: var(--progress, 0%);
	transition: width .08s linear;
	pointer-events: none;
}

/* ======================================================================
 * Article-template port Phase 3.1b — breadcrumbs + article header lockup
 *
 * Lifted from sandbox lines 324-382. Token-based. Breadcrumb selectors
 * remap Rank Math's actual <div class="rank-math-breadcrumb"><p><a><span
 * class="separator"> markup to match the sandbox's gold mono uppercase
 * treatment, with a fallback for the <ol><li> form when Rank Math is
 * inactive.
 *
 * .article-body section here is the minimal Phase 3.1b version. Phase
 * 3.1c refines with story-highlights / blockquote / pull-quote / tweet
 * card / in-body ad / CPT-link decoration.
 * ====================================================================== */

/* Breadcrumbs — gold mono row */
.breadcrumbs {
	padding: 24px 0 12px;
}
.breadcrumbs ol,
.breadcrumbs .rank-math-breadcrumb {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	/* baseline (not center) so text aligns across items even when the
	 * 13px separator pseudo makes some <li> inline boxes taller than
	 * others (first li has no separator → shorter; others get a 13px
	 * dot via `li + li::before` → taller). With align-items: center,
	 * the shorter first item's text sat a pixel or two higher than the
	 * rest; baseline pins all text to a shared horizontal line. */
	align-items: baseline;
	gap: 0;
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--nd-gold);
	letter-spacing: .14em;
	text-transform: uppercase;
	font-weight: 600;
}
.breadcrumbs .rank-math-breadcrumb p {
	margin: 0;
	display: contents;
}
.breadcrumbs li {
	color: inherit;
}
/* !important required: Jannah customizer emits
 * `.rank-math-breadcrumb a { color: #006036 !important; }` (green) which
 * wins regardless of selector specificity. Per CLAUDE.md CSS Discipline. */
.breadcrumbs a,
.breadcrumbs .rank-math-breadcrumb a {
	color: var(--nd-gold) !important;
	text-decoration: none;
}
.breadcrumbs a:hover,
.breadcrumbs .rank-math-breadcrumb a:hover {
	color: color-mix(in srgb, var(--nd-gold) 70%, var(--nd-navy)) !important;
	text-decoration: none;
}
.breadcrumbs .separator {
	color: var(--gold-border);
	margin: 0 6px;
	font-size: 13px;
}
.breadcrumbs li + li::before {
	content: "·";
	color: var(--gold-border);
	margin: 0 6px;
	font-size: 13px;
}
.breadcrumbs li[aria-current="page"],
.breadcrumbs .rank-math-breadcrumb .last {
	color: var(--ink-2);
	font-weight: 600;
}

/* Mobile: keep the trail on a single line and scroll horizontally rather
 * than wrapping. Deep trails (e.g. HOME · FOOTBALL · ANALYSIS · DEFENSE)
 * wrapped to a second line on narrow viewports, eating vertical space
 * above the article. nowrap + overflow-x scrolls only when the trail
 * actually overflows — short trails still sit on one line with no scroll.
 * The scrollbar is hidden (swipe to reveal); top/bottom padding is also
 * trimmed since mobile has less room to spare. */
@media (max-width: 900px) {
	.breadcrumbs {
		padding: 16px 0 8px;
	}
	.breadcrumbs ol,
	.breadcrumbs .rank-math-breadcrumb {
		flex-wrap: nowrap;
		overflow-x: auto;
		/* Hide the scrollbar while keeping the row scrollable. */
		scrollbar-width: none;
		-ms-overflow-style: none;
		-webkit-overflow-scrolling: touch;
	}
	.breadcrumbs ol::-webkit-scrollbar,
	.breadcrumbs .rank-math-breadcrumb::-webkit-scrollbar {
		display: none;
	}
	/* Don't let flex shrink crumbs (which would wrap their text); keep
	 * each at its natural width so the row overflows and scrolls instead. */
	.breadcrumbs li {
		flex: 0 0 auto;
		white-space: nowrap;
	}
}

/* Article header lockup — full content-area width, H1 → rule → deck → byline.
 * Per Frank's 2026-05-08 decision, no kicker pill above the H1; category
 * context lives entirely in the Rank Math breadcrumbs above the article. */
.article-header {
	padding: 0 0 28px;
	border-bottom: 1px solid var(--line-soft);
}
/* .article-header parent prefix bumps specificity past .wf-active h1
 * (0,1,1 → 0,2,1) so Source Serif 4 wins regardless of whether
 * Jannah's Web Font Loader adds wf-active later in the page lifecycle.
 *
 * font-size uses !important because Jannah's customizer emits a bare
 * `h1 { font-size: 34px !important }` rule via theme-options that wins
 * regardless of selector specificity. Stripping that rule would require
 * digging into Jannah's customizer settings (and might affect other
 * surfaces); fighting !important with !important here is scoped to the
 * article headline only. Per CLAUDE.md CSS Discipline. */
.article-header h1.headline {
	font-family: var(--font-serif);
	font-size: var(--type-article-headline-size) !important;
	line-height: 1.06;
	letter-spacing: -.02em;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0;
	text-wrap: pretty;
}
.gold-rule {
	width: 48px;
	height: 3px;
	background: var(--nd-gold);
	margin: 18px 0 18px;
}
.deck {
	font-family: var(--font-serif);
	font-size: var(--type-article-deck-size);
	line-height: 1.45;
	color: var(--ink-2);
	margin: 0;
	font-style: italic;
	font-weight: 400;
	text-wrap: pretty;
}

/* Byline / meta — single line, hairlines top + bottom */
.byline-row {
	display: flex;
	align-items: center;
	gap: 14px;
	flex-wrap: wrap;
	padding: 14px 0;
	margin-top: 22px;
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
}
.byline {
	display: flex;
	align-items: center;
	gap: 10px;
}
.byline .avatar {
	width: 34px;
	height: 34px;
	border-radius: 50%;
	background: linear-gradient(135deg, var(--nd-navy), var(--ink-2));
	color: var(--nd-gold);
	display: grid;
	place-items: center;
	font-family: var(--font-serif);
	font-weight: 700;
	font-size: 13px;
	flex-shrink: 0;
	overflow: hidden;
}
.byline .avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 50%;
	display: block;
}
.byline .stack {
	display: flex;
	flex-direction: column;
	line-height: 1.2;
}
.byline .by {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-4);
	font-weight: 500;
	margin-bottom: 1px;
}
.byline .name {
	font-family: var(--font-sans);
	font-size: 13.5px;
	font-weight: 600;
	color: var(--nd-navy);
}
.byline .name a {
	color: inherit;
	text-decoration: none;
}
.byline .name a:hover {
	color: var(--accent-hover);
}
.byline-row .dot {
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: var(--ink-4);
	flex-shrink: 0;
}
.byline-row .meta-item {
	font-family: var(--font-sans);
	font-size: var(--type-meta-size);
	color: var(--ink-3);
	display: inline-flex;
	align-items: center;
	gap: 6px;
}
.byline-row .meta-item time {
	font-variant-numeric: tabular-nums;
}
.byline-row .meta-item.cmts {
	color: var(--nd-navy);
	font-weight: 600;
}
.byline-row .meta-item.cmts a {
	color: inherit;
	text-decoration: none;
}
.share-icons {
	margin-left: auto;
	display: flex;
	align-items: center;
	gap: 2px;
}
/* Copy-button icon swap: chain-link by default, checkmark while .is-copied
 * is active (added by assets/js/share.js for ~1.2s after a successful
 * clipboard write). Applies to .share-copy in every cluster — header
 * lockup, floating share rail, video hero. */
.share-copy .ic-check { display: none; }
.share-copy.is-copied .ic-link { display: none; }
.share-copy.is-copied .ic-check { display: block; }
.share-icons button,
.share-icons a {
	width: 32px;
	height: 32px;
	border-radius: 4px;
	color: var(--ink-3);
	display: grid;
	place-items: center;
	background: transparent;
	border: 0;
	padding: 0;
	cursor: pointer;
	text-decoration: none;
}
.share-icons button:hover,
.share-icons a:hover {
	color: var(--nd-navy);
	background: var(--accent-tint);
}
.share-icons .share-copy.is-copied {
	color: var(--nd-green);
	background: var(--accent-tint);
}
@media (prefers-reduced-motion: no-preference) {
	.share-icons button,
	.share-icons a {
		transition: color .15s ease, background-color .15s ease;
	}
}

/* ======================================================================
 * Article-template port Phase 3.1c — body-col positioning, featured
 * image, floating left share rail.
 *
 * Lifted from sandbox lines 392-434 (.body-col / .share-rail /
 * .featured / .featured-frame / .featured-meta / .caption /
 * .photo-credit). Phase 3.1d will introduce <div class="layout"> as the
 * outer body+rail grid; for 3.1c the .body-col stands alone (no rail
 * yet) and the .article-body's natural max-width handles its own
 * constraint.
 * ====================================================================== */

/* Body + rail grid — sandbox lines 384-393. body-col is 1fr of remaining
 * space after the rail (~868px on a 1216px content area); .rail is the
 * fixed 300px right column. Padding lives on .layout so .body-col can
 * stay flush against the grid's column. The rail is intentionally empty
 * in 3.1c — Phase 3.1d populates it with the six sandbox modules.
 *
 * Gap bumped 28 → 48 and rail 340 → 300 on 2026-05-18 to bring the visual
 * whitespace between article text and rail down to ~48px (was ~201px,
 * dominated by unused space inside .body-col between the 75ch measure
 * ceiling and the column's right edge). Article body now fills .body-col
 * so the ceiling no longer creates the right-side hole. */
.layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) var(--rail-w);
	gap: var(--rail-col-gap);
	padding: 32px 0 56px;
	position: relative;
}
/* Phase 7a (2026-05-23): rail collapses below body at narrow viewports.
 * Without this the fixed 300px rail eats most of the width at <900px,
 * leaving images / wide content in the body column to overflow the
 * viewport. Same stacking pattern as the CPT layouts. Was article 320
 * residual in the post-Phase-6 audit. */
@media (max-width: 900px) {
	.layout {
		grid-template-columns: minmax(0, 1fr);
		gap: 32px;
	}
}
.body-col {
	position: relative;
	min-width: 0;
}
.rail {
	/* Phase 3.1d populates. */
}

/* Floating share rail — absolute, anchored to .body-col's top-left. */
.share-rail {
	position: absolute;
	left: -72px;
	top: 80px;
	display: flex;
	flex-direction: column;
	gap: 6px;
	align-items: center;
	padding: 10px 6px;
}
.share-rail .label {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: var(--tracking-mono-loose);
	color: var(--ink-4);
	text-transform: uppercase;
	writing-mode: vertical-rl;
	transform: rotate(180deg);
	margin-bottom: 8px;
}
.share-rail button,
.share-rail a {
	width: 36px;
	height: 36px;
	border-radius: 4px;
	color: var(--ink-3);
	display: grid;
	place-items: center;
	border: 1px solid transparent;
	background: transparent;
	padding: 0;
	cursor: pointer;
	text-decoration: none;
}
.share-rail button:hover,
.share-rail a:hover {
	color: var(--nd-navy);
	background: var(--bg);
	border-color: var(--line-soft);
}
.share-rail .share-copy.is-copied {
	color: var(--nd-green);
	background: var(--bg);
	border-color: var(--line-soft);
}
@media (prefers-reduced-motion: no-preference) {
	.share-rail button,
	.share-rail a {
		transition: color .15s ease, background-color .15s ease, border-color .15s ease;
	}
}
@media (max-width: 900px) {
	.share-rail { display: none; }
}

/* Featured image — fills .body-col, 16:9 frame.
 * Was capped at --type-doc-body-measure (75ch) so it stayed aligned with
 * the body text; with the 2026-05-18 article-body widening (body fills
 * .body-col, gap bumped to 48), the featured image follows so the image
 * doesn't read narrower than the prose beneath it. */
.featured {
	margin: 0 0 28px;
}
.featured-frame {
	width: 100%;
	aspect-ratio: 16 / 9;
	overflow: hidden;
	border-radius: var(--radius-media);
	background: var(--bg-muted);
}
.featured-frame img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* Caption block — mirrors the recruit `.commitment-note` look/feel
 * (cpt-rough.css): cream gold-wash fill, 3px gold left rule, a mono-caps
 * gold eyebrow (the photo credit) over a serif body line (the caption).
 * The credit is emitted first in featured-image.php so it reads as the
 * eyebrow above the caption. */
.featured-meta {
	margin-top: 16px;
	padding: 14px 18px;
	border-left: 3px solid var(--nd-gold);
	background: color-mix(in srgb, var(--nd-gold) 6%, transparent);
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.featured-meta .caption {
	font-family: var(--font-serif);
	font-size: 14px;
	font-weight: 400;
	color: var(--ink-2);
	line-height: 1.5;
	/* Reset the uppercase the caption span would otherwise inherit from
	 * the base `figcaption` rule (goldendome-base.css:
	 * `figcaption { text-transform: uppercase }`). Without this the
	 * caption rendered in all caps. */
	text-transform: none;
	font-style: normal;
}
.featured-meta .photo-credit {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
}

/* Article body — minimal Phase 3.1b version (refined in 3.1c.2)
 *
 * 2026-05-18: max-width: var(--type-doc-body-measure) removed so the body
 * fills .body-col (~868px). The visual gap between article text and the
 * right rail is now the .layout grid's `gap: 48px` only — previously the
 * 75ch measure ceiling left ~173px of unused space inside .body-col on
 * top of the 28px gap, reading as a ~201px gutter. Inset callouts
 * (.story-highlights, .pullquote, .in-body-ad, .below) keep the 75ch cap
 * because they're intentionally constrained inserts. */
.article-body {
	font-family: var(--font-serif);
	font-size: var(--type-doc-body-size);
	line-height: var(--type-doc-body-line);
	color: var(--text);
	margin-top: 28px;
}
.article-body p {
	margin: 0 0 1.05em;
}
/* .page parent prefix bumps specificity past .wf-active h2 (0,1,1 → 0,2,1)
 * for the same Web Font Loader reason as h1.headline above. h3 gets the
 * same treatment — Gutenberg <h3 class="wp-block-heading"> is the most
 * common section heading inside the article body. */
.page .article-body h2 {
	font-family: var(--font-serif);
	font-size: var(--type-doc-h2-size);
	font-weight: var(--type-doc-h2-weight);
	letter-spacing: var(--type-doc-h2-tracking);
	line-height: 1.25;
	color: var(--nd-navy);
	margin: 1.8em 0 .5em;
}
.page .article-body h3 {
	font-family: var(--font-serif);
	font-size: var(--type-doc-h3-size);
	font-weight: var(--type-doc-h2-weight);
	letter-spacing: var(--type-doc-h2-tracking);
	line-height: 1.3;
	color: var(--nd-navy);
	margin: 1.6em 0 .4em;
}
.article-body a {
	color: var(--nd-navy);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}
.article-body a:hover {
	color: var(--accent-hover);
}

/* CPT link decoration — dotted underline on links to Player / Coach /
 * Game CPT permalinks. CSS-only; no the_content filter needed. */
.article-body a[href*="/football/players/"],
.article-body a[href*="/football/players-pods/"],
.article-body a[href*="/football/coaches/"],
.article-body a[href*="/football/games/"] {
	text-decoration: underline dotted;
	text-decoration-thickness: 1.5px;
	text-underline-offset: 3px;
}
.article-body a[href*="/football/players/"]:hover,
.article-body a[href*="/football/players-pods/"]:hover,
.article-body a[href*="/football/coaches/"]:hover,
.article-body a[href*="/football/games/"]:hover {
	text-decoration-style: solid;
}

/* ======================================================================
 * Article-template port Phase 3.1c.2 — body components
 *
 * Story highlights box, blockquote (gold left rule), pull-quote
 * (centered serif italic with gold open-quote glyph), in-body ad
 * frame. Lifted from sandbox lines 462-1041 with token references.
 * ====================================================================== */

/* Story highlights — gold left rule + bulleted list */
.story-highlights {
	border: 1px solid var(--line-soft);
	border-left: 3px solid var(--nd-gold);
	border-radius: var(--r-card);
	padding: 16px 20px 18px;
	margin: 0 0 1.4em;
	max-width: var(--type-doc-body-measure);
	background: var(--card);
}
.story-highlights__eyebrow {
	font-family: var(--font-mono);
	font-size: var(--type-mono-label-size);
	letter-spacing: var(--type-mono-label-tracking);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 500;
	margin: 0 0 10px;
}
.story-highlights ul {
	list-style: none;
	margin: 0;
	padding: 0;
}
.story-highlights li {
	font-family: var(--font-serif);
	font-size: 15.5px;
	line-height: 1.5;
	color: var(--text);
	margin: 0 0 .5em;
	padding-left: 16px;
	position: relative;
}
.story-highlights li:last-child {
	margin-bottom: 0;
}
.story-highlights li::before {
	content: "•";
	color: var(--nd-gold);
	position: absolute;
	left: 0;
	top: 0;
	font-weight: 700;
	font-size: 1.1em;
}

/* Blockquote — gold left rule, attribution in sans (for inline quoted
 * speech / external citations) */
.article-body blockquote,
.article-body .wp-block-quote {
	border-left: 3px solid var(--nd-gold);
	padding: 0 0 0 22px;
	margin: 1.4em 0;
	color: var(--ink-2);
	font-style: normal;
}
.article-body blockquote p,
.article-body .wp-block-quote p {
	font-family: var(--font-serif);
	font-size: var(--type-doc-body-size);
	line-height: 1.6;
	margin: 0 0 .5em;
}
.article-body blockquote cite,
.article-body .wp-block-quote cite,
.article-body blockquote .bq-attr,
.article-body .wp-block-quote .wp-block-quote__citation {
	display: block;
	font-family: var(--font-sans);
	font-style: normal;
	font-size: 13px;
	color: var(--ink-3);
	margin-top: .25em;
}

/* Pull-quote — centered serif italic with gold open-quote glyph (for
 * phrases pulled from the article body for visual emphasis) */
.article-body .wp-block-pullquote,
.article-body .pullquote {
	margin: 2em auto;
	padding: 24px 0;
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
	text-align: center;
	max-width: var(--type-doc-body-measure);
	position: relative;
}
.article-body .wp-block-pullquote::before,
.article-body .pullquote::before {
	content: "\201C";
	display: block;
	color: var(--nd-gold);
	font-family: var(--font-serif);
	font-size: 2em;
	line-height: 0.5;
	margin-bottom: 8px;
}
.article-body .wp-block-pullquote p,
.article-body .pullquote p,
.article-body .wp-block-pullquote blockquote {
	font-family: var(--font-serif);
	font-size: var(--type-pullquote-size);
	font-style: italic;
	color: var(--nd-navy);
	line-height: 1.35;
	margin: 0;
	border: 0;
	padding: 0;
}
.article-body .wp-block-pullquote cite,
.article-body .pullquote cite {
	display: block;
	font-family: var(--font-sans);
	font-style: normal;
	font-size: 13px;
	color: var(--ink-3);
	margin-top: .75em;
}

/* In-body ad — same treatment as the above-masthead ad band but
 * reduced bottom padding (it sits inside body flow). */
.in-body-ad {
	background: var(--bg-sunk);
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
	padding: 14px 0 16px;
	margin: 1.6em 0;
	max-width: var(--type-doc-body-measure);
}
.in-body-ad .ad-label {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ad-label-ink);
	text-align: center;
	margin: 0 0 6px;
	font-weight: 500;
}
.in-body-ad .ad-frame {
	width: 728px;
	max-width: 100%;
	height: 90px;
	margin: 0 auto;
	border: 1px solid var(--ad-frame);
	background: var(--bg);
	display: grid;
	place-items: center;
	background-image: repeating-linear-gradient(45deg, var(--bg-muted) 0 8px, color-mix(in srgb, var(--bg-muted) 60%, var(--bg)) 8px 16px);
}
.in-body-ad .ad-frame .lbl {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: .1em;
	text-transform: uppercase;
	background: rgba(255, 255, 255, .7);
	padding: 4px 10px;
	border-radius: var(--radius-chip);
}

/* ======================================================================
 * Article-template port Phase 3.1d — below-body region
 *
 * Tags row, author bio (full), and related-articles 3-card grid.
 * Lifted from sandbox lines 694-780. .below is the wrapper that
 * constrains content to the body measure (75ch); .below.related-wrap
 * lifts that constraint so the related grid spans the full article
 * (1216px) content area.
 * ====================================================================== */

.below {
	padding: 40px 0 0;
	border-top: 1px solid var(--line-strong);
	margin-top: 32px;
	/* Match the left column (.body-col) width so the below-body region —
	   tags, author bio, comments — aligns with the article body and the
	   "In This Story" row above it (2026-05-30). 100% here is the full
	   content box (same as .layout); subtract the rail + grid gap to land
	   on the body-col width. Was capped at the 75ch reading measure. */
	max-width: calc(100% - var(--rail-w) - 48px);
}
.below.related-wrap {
	max-width: none;
}
/* Below 900px the rail collapses (see .layout), so the below-body region
   takes the full width — the calc above would otherwise crush it. */
@media (max-width: 900px) {
	.below {
		max-width: none;
	}
}

/* Tags row — plain #tag links separated by gap */
.tags-row {
	display: flex;
	flex-wrap: wrap;
	gap: 18px;
	margin: 0 0 32px;
	list-style: none;
	padding: 0;
}
.tags-row a {
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 500;
	color: var(--nd-navy);
	text-decoration: none;
}
.tags-row a:hover {
	color: var(--nd-green);
	text-decoration: underline;
}

/* Author bio (full) */
.bio-full {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 16px;
	padding: 20px 0 28px;
	border-bottom: 1px solid var(--line-soft);
	margin-bottom: 36px;
	align-items: start;
}
.bio-full > img,
.bio-full .avatar {
	width: 60px;
	height: 60px;
	border-radius: 50%;
	flex-shrink: 0;
	object-fit: cover;
	display: block;
}
.bio-full .head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 12px;
	margin-bottom: 6px;
}
.bio-full .name {
	font-family: var(--font-serif);
	font-size: 20px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0;
	letter-spacing: -.01em;
}
.bio-full .name a {
	color: inherit;
	text-decoration: none;
}
.bio-full .name a:hover {
	color: var(--accent-hover);
}
.bio-full .role {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .14em;
	color: var(--ink-3);
	text-transform: uppercase;
	font-weight: 600;
}
.bio-full .text {
	font-family: var(--font-serif);
	font-size: 15.5px;
	line-height: 1.55;
	color: var(--ink-2);
	margin: 0 0 10px;
	/* Visual truncation at 3 lines so long bios don't dominate the
	 * below-body region. The "More from [author] →" link in .links
	 * below points to the full author archive where the complete bio
	 * is available. Full text remains in the DOM for assistive tech. */
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
}
.bio-full .links {
	display: flex;
	gap: 18px;
	font-family: var(--font-sans);
	font-size: 12.5px;
	flex-wrap: wrap;
}
.bio-full .links a {
	color: var(--ink-3);
	font-weight: 500;
	text-decoration: none;
}
.bio-full .links a:hover {
	color: var(--nd-navy);
}

/* Related articles — 3 cards, hairline-thumbed, escapes the body measure */
.related {
	margin-top: 8px;
}
.related h2 {
	font-family: var(--font-serif);
	font-size: 24px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0 0 18px;
	padding-bottom: 10px;
	border-bottom: 2px solid var(--nd-gold);
	letter-spacing: -.005em;
}
.related-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 24px;
}
.related-card {
	display: flex;
	flex-direction: column;
	gap: var(--card-gap);
	text-decoration: none;
	color: inherit;
}
.related-card .thumb {
	aspect-ratio: 16 / 9;
	background: var(--bg-muted);
	border-radius: var(--radius-media);
	overflow: hidden;
	background-image: repeating-linear-gradient(45deg, color-mix(in srgb, var(--ink-4) 16%, var(--bg-muted)) 0 6px, var(--bg-muted) 6px 14px);
}
.related-card .thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.related-card .kicker-sm {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
	margin-top: 4px;
}
.related-card .title {
	font-family: var(--font-serif);
	font-size: 16px;
	font-weight: 600;
	color: var(--nd-navy);
	line-height: 1.25;
	margin: 2px 0 0;
}
/* Canonical card meta-line eyebrow (mono, 10px, tight tracking, ink-3).
 * Consolidated 2026-06-06 from 5 near-identical per-card copies
 * (related-card / recent-item / coverage-card / recruiting recent-item /
 * utility) that had drifted to 0.08/0.1/0.16em tracking. Sitewide so every
 * `.meta-mini` element inherits it; only per-surface deltas stay scoped. */
.meta-mini {
	font-family: var(--font-mono);
	font-size: var(--label-md);
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
	color: var(--ink-3);
}
.related-card .meta-mini { margin-top: 4px; }
.related-card:hover .title {
	color: var(--accent-hover);
}

/* ======================================================================
 * Article-template port Phase 4.0 — right rail (initial three modules)
 *
 * Lifted from sandbox/article-template.html lines 543-691. This commit
 * ships .rail (column container), .rail-section + .rail-section-head
 * (gold-underline section heads), .recent-list / .recent-item (Recent
 * on UHND module), and .rail-ad (ad placeholders, both 300×250 medium
 * and 300×600 half-page variants).
 *
 * Deferred to follow-up commits (markup + CSS together, since the CSS
 * is dead code without the markup): .game-module (Game CPT Up Next —
 * needs new ACF betting_line + kick_venue_full), .player-module
 * (Featured Player — reads existing featured_player ACF), .affiliate
 * (needs new ACF Options page).
 * ====================================================================== */

.rail {
	display: flex;
	flex-direction: column;
	gap: var(--rail-gap);
	min-width: 0;
}
.rail-section {
	display: flex;
	flex-direction: column;
	gap: 0;
}
.rail-section-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 10px;
	padding: 0 0 10px;
	border-bottom: 2px solid var(--nd-gold);
	margin-bottom: 14px;
}
.rail-section-head .title {
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: .14em;
	color: var(--nd-navy);
}
.rail-section-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;
}
.rail-section-head .more:hover {
	color: var(--nd-navy);
	text-decoration: none;
}

/* Recent on UHND — 80×60 thumb + 3-line-clamped serif title + mono meta */
.recent-list {
	display: flex;
	flex-direction: column;
	gap: 14px;
}
.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);
}
.recent-item:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}
.recent-item:hover {
	text-decoration: none;
}
.recent-item:hover .title {
	color: var(--accent-hover);
}
.recent-item .thumb {
	width: 80px;
	height: 60px;
	background: var(--bg-muted);
	border-radius: var(--radius-media);
	overflow: hidden;
	background-image: repeating-linear-gradient(45deg, color-mix(in srgb, var(--ink-4) 18%, var(--bg-muted)) 0 4px, var(--bg-muted) 4px 10px);
}
.recent-item .thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.recent-item .body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}
.recent-item .body .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;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
/* .recent-item .meta-mini → canonical .meta-mini (2026-06-06). */

/* Rail ads — hatch placeholder until ad-tech wires real slots */
.rail-ad .ad-label {
	margin: 0;
	padding: 0 0 6px;
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ad-label-ink);
	text-align: center;
	font-weight: 500;
}
.rail-ad .ad-frame {
	border: 1px solid var(--ad-frame);
	background: var(--bg);
	display: grid;
	place-items: center;
	background-image: repeating-linear-gradient(45deg, var(--bg-muted) 0 8px, color-mix(in srgb, var(--bg-muted) 60%, var(--bg)) 8px 16px);
}
.rail-ad.medium .ad-frame {
	height: 250px;
}
.rail-ad.half-page .ad-frame {
	height: 600px;
}
.rail-ad .ad-frame .lbl {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: .1em;
	text-transform: uppercase;
	background: rgba(255, 255, 255, .7);
	padding: 4px 10px;
	border-radius: var(--radius-chip);
}

/* ======================================================================
 * "The Game" rail widget — template-parts/rail/game.php
 *
 * Flush, headliner-style block modelled on the recruiting-class .top-rated
 * card (cpt-rough.css §3509): transparent background, serif name + mono
 * ranks, hairline footer rule. Two stacked team rows (Notre Dame always on
 * top), one rank per team, a single square opponent logo right-aligned, and
 * a state-aware footer (final score+W/L, or kickoff·TV + betting line).
 * Replaces the prior navy .game-module (2026-05-30 redesign — see decisions).
 * ====================================================================== */
.rail-game {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas:
		"teams logo"
		"foot  foot";
	column-gap: 14px;
	align-items: center;
	text-decoration: none;
	color: inherit;
}
.rail-game:hover { text-decoration: none; }
.rail-game:hover .rg-name { color: var(--accent-hover); }

.rg-teams {
	grid-area: teams;
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}
.rg-team {
	display: grid;
	grid-template-columns: 2.4em minmax(0, 1fr) auto;
	align-items: baseline;
	column-gap: 8px;
}
.rail-game.is--preview .rg-team {
	grid-template-columns: 2.4em minmax(0, 1fr);
}
.rg-rank {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	font-variant-numeric: tabular-nums;
	letter-spacing: .02em;
}
.rg-name {
	font-family: var(--font-serif);
	font-size: 18px;
	font-weight: 600;
	color: var(--nd-navy);
	line-height: 1.2;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.rg-score {
	font-family: var(--font-mono);
	font-size: 18px;
	font-weight: 700;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
}
.rg-team.is-loser .rg-name,
.rg-team.is-loser .rg-score {
	color: var(--ink-3);
	font-weight: 500;
}

.rg-logo {
	grid-area: logo;
	display: grid;
	place-items: center;
}
.rg-logo img {
	width: 52px;
	height: 52px;
	object-fit: contain;
	display: block;
}
.rg-logo-fallback {
	width: 52px;
	height: 52px;
	border-radius: 4px;
	display: grid;
	place-items: center;
	background: var(--bg-muted);
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: .03em;
	color: var(--ink-2);
}

.rg-foot {
	grid-area: foot;
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px solid var(--line-soft);
	display: flex;
	flex-direction: column;
	gap: 3px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: .04em;
	color: var(--ink-3);
}
.rg-foot .rg-wl {
	font-weight: 700;
}
.rg-foot .rg-wl--w { color: var(--nd-green); }
.rg-foot .rg-wl--l { color: var(--danger); }
.rg-foot .rg-line { color: var(--ink-2); }

/* ======================================================================
 * Snack Media ad units (Publisher ID 4861) — live-fill behaviour.
 *
 * The placeholder frames (.top-ad-band / .in-body-ad / .rail-ad .ad-frame and
 * the homepage .ad-unit--leaderboard) carry a fixed size + hatch background for
 * the unfilled design. Once the Snack loader mounts a unit (a bare
 * <div id="snack-*">), drop the hatch and relax the size lock so the served
 * creative — which can be taller/wider than the placeholder (e.g. 970×250 top,
 * 300×600 sidebar) — isn't clipped, and reserve a min-height to limit layout
 * shift. Pixel values are fixed IAB ad dimensions, not design tokens (see
 * docs/decisions.md 2026-05-29 ad-dimension exception); min-heights mirror the
 * media partner's CSS in docs/adcodeinstructions.md.
 * ====================================================================== */
/* Drop the placeholder hatch + size lock once a Snack unit mounts; the frame
 * then hugs the unit div sized below. */
.top-ad-band .ad-frame:has(> [id^="snack-"]),
.in-body-ad .ad-frame:has(> [id^="snack-"]),
.rail-ad .ad-frame:has(> [id^="snack-"]),
.ad-unit--leaderboard:has(> [id^="snack-"]) {
	background-image: none;
	height: auto;
	min-height: 0;
}

/* Size the Snack unit DIVS directly — this is the mechanism the media partner's
 * loader reads to choose a creative, so it both reserves the slot and steers the
 * served size. We own this in-theme now; it previously lived in the Snack
 * theme-options head CSS, which forced #snack-top to 250px !important and made
 * the leaderboard band too tall. Reserve the intended size; the unit expands if
 * a taller creative serves. Width caps keep the loader from serving a wide
 * leaderboard into the narrow rail. Px are fixed IAB ad sizes, not tokens. */
#snack-incontent-slim-1,
#snack-incontent-slim-2,
#snack-incontent-slim-3,
#snack-section {
	min-height: 90px;
	text-align: center;
	margin: 0 auto;
}

/* Header leaderboard — slim unit (728×90 / 970×90 / 468×60; never a tall
 * billboard). Open the slot to full width up to 970 so Snack can serve the wide
 * 970×90, and center whatever serves. Drop the inner frame box (the band itself
 * frames it) so a 970 ad isn't clipped or pushed off-center. */
.top-ad-band .ad-frame:has(> #snack-top-slim) {
	width: 100%;
	max-width: 990px;
	margin-inline: auto;
	border: 0;
	background: none;
}
#snack-top-slim {
	display: block;
	width: 100%;
	min-height: 90px;
	text-align: center;
	margin: 0 auto;
}
#snack-sidebar-1,
#snack-sidebar-3 {
	min-height: 250px;   /* 300×250 medrec */
	max-width: 300px;
	text-align: center;
	margin: 0 auto;
}
#snack-sidebar-2 {
	min-height: 600px;   /* 300×600 half-page */
	max-width: 300px;
	text-align: center;
	margin: 0 auto;
}

@media (max-width: 727px) {
	#snack-incontent-slim-1,
	#snack-incontent-slim-2,
	#snack-incontent-slim-3 { min-height: 250px; } /* medrec on mobile */
	#snack-top-slim,
	#snack-section { min-height: 100px; }
}

/* Rail ads only render in the true two-column layout (>900px), where .rail is a
 * fixed 300px column the medrec/half-page units fit. At <=900px the .layout grid
 * collapses to one column and .rail stacks full-width — a sidebar slot would then
 * size wide and pull a wide creative — so hide it there (covers tablet and the
 * media partner's no-sidebar-on-mobile rule in one breakpoint). */
@media (max-width: 900px) {
	.rail-ad:has([id^="snack-sidebar-"]) { display: none; }
}

/* Sticky last rail ad — the final ad unit in a rail pins below the sticky
 * .chrome header once the reader scrolls to it, so the rail's last impression
 * stays in view while the taller content column keeps scrolling (the rail is a
 * grid item stretched to the content column's height, so the last flex child
 * has empty space below it to stick within). Only the LAST rail ad sticks;
 * earlier rail ads scroll away normally. Every rail-bearing template ends its
 * rail with an ad partial (ad-half-page, or ad-mrec on the recruiting rails),
 * so :last-child targets that ad. Gated to the two-column layout (>900px);
 * below that the rail stacks and sidebar ads are hidden. */
@media (min-width: 901px) {
	.rail > .rail-ad:last-child {
		position: sticky;
		top: var(--rail-sticky-top);
	}
}

/* Schedule page — section-break ad between the schedule rows and the Browse All
 * Seasons archive (template-parts/schedule/page-shell.php). Centered slim band
 * with hairline rules so it reads as a section divider; the unit (#snack-incontent-slim-2)
 * is sized by the slim group above (728×90 desktop / medrec mobile, no tall units). */
.schedule-ad {
	margin: 36px 0;
	padding: 14px 0 16px;
	background: var(--bg-sunk);
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
	text-align: center;
}
.schedule-ad .ad-label {
	font-family: var(--font-mono);
	font-size: 9px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ad-label-ink);
	margin: 0 0 6px;
	font-weight: 500;
}
.schedule-ad .ad-frame {
	width: 728px;
	max-width: 100%;
	margin: 0 auto;
	display: grid;
	place-items: center;
}

/* ======================================================================
 * Article-template port Phase 3.1e — comments thread
 *
 * Lifted from sandbox/article-template.html lines 720-763 (CSS) and
 * 1216-1295 (markup). No-chrome list with hairline-separated comments,
 * .replies wrapper for the navy reply gutter, and .is-author tint for
 * post-author replies.
 *
 * Markup deviations from sandbox documented in docs/decisions.md
 * 2026-05-09: vote-stub buttons and notify-on-reply checkbox omitted
 * pending backend wiring; the WP reply control renders as
 * <a class="comment-reply-link"> (not <button>) and is styled to match.
 * The .comment.is-author { display:block } rule corrects a sandbox
 * grid-with-one-child layout bug for replies (.comment .auto 1fr grid
 * leaves the .c-content shrink-wrapped without it).
 * ====================================================================== */

.comments {
	margin-bottom: 48px;
}
.comments-head {
	display: flex;
	align-items: baseline;
	gap: 12px;
	margin-bottom: 18px;
}
.comments-head h2 {
	font-family: var(--font-serif);
	font-size: 24px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0;
	letter-spacing: -.005em;
}
.comments-head .count {
	font-family: var(--font-mono);
	font-size: 11px;
	color: var(--ink-3);
	letter-spacing: var(--type-micro-tracking);
}

/* Comment form — textarea with green focus ring + navy submit button */
.comment-form {
	display: grid;
	gap: 10px;
	margin-bottom: 28px;
}
.comment-form textarea {
	font-family: var(--font-sans);
	font-size: 14px;
	color: var(--text);
	border: 1px solid var(--line);
	border-radius: var(--r-input);
	padding: 10px 12px;
	min-height: 80px;
	resize: vertical;
	background: var(--bg);
	width: 100%;
}
.comment-form textarea:focus {
	outline: none;
	border-color: var(--nd-green);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--nd-green) 14%, transparent);
}
.comment-form .row {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 12px;
	flex-wrap: wrap;
}
.comment-form label {
	font-family: var(--font-sans);
	font-size: 12.5px;
	color: var(--ink-3);
	display: flex;
	align-items: center;
	gap: 6px;
}
.comment-form .comment-submit,
.comment-form button[type="submit"] {
	background: var(--nd-navy);
	color: #fff;
	font-family: var(--font-sans);
	font-size: 12.5px;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	padding: 10px 18px;
	border: 0;
	border-radius: var(--r-input);
	cursor: pointer;
}
.comment-form .comment-submit:hover,
.comment-form button[type="submit"]:hover {
	background: var(--accent-hover);
}
.comment-form-loggedout {
	font-family: var(--font-sans);
	font-size: 13.5px;
	color: var(--ink-3);
	margin: 0 0 28px;
}
.comment-form-loggedout a {
	color: var(--nd-navy);
	font-weight: 600;
}

/* Comment list — hairline-separated via the adjacent-sibling pattern below. */
.comment-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}
/* Single divider between top-level comments using the adjacent-sibling
 * pattern. Resets Jannah's legacy `.comment-list .comment` box from
 * assets/css/single.css lines 1267-1280 (border-bottom + margin-bottom
 * + padding-bottom + overflow:hidden) which doubled up with our top
 * rule and added an extra 20px-each gap. Specificity matched at (0,2,0)
 * so source order decides; goldendome style.css loads after Jannah
 * single.css. Symmetric 18px padding above and below the rule. */
.comment-list .comment {
	padding: 18px 0;
	margin: 0;
	border: 0;
	overflow: visible;
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 14px;
}
.comment-list > .comment + .comment {
	border-top: 1px solid var(--line-soft);
}
.comment .avatar {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	background: var(--bg-muted);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 700;
	color: var(--nd-navy);
	font-style: normal;
}
.comment img.avatar {
	object-fit: cover;
}

/* Header / body / actions */
.comment .c-head {
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
	margin-bottom: 4px;
}
.comment .c-name {
	font-family: var(--font-sans);
	font-size: 13.5px;
	font-weight: 600;
	color: var(--nd-navy);
	text-decoration: none;
}
.comment .c-name:hover {
	color: var(--accent-hover);
}
.comment .c-time {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--ink-3);
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
}
.comment .c-body {
	font-family: var(--font-sans);
	font-size: 14.5px;
	color: var(--text);
	line-height: 1.55;
	margin: 0;
}
/* Multi-paragraph bodies — strip default <p> margins; gap between paragraphs. */
.comment .c-body p {
	margin: 0;
}
.comment .c-body p + p {
	margin-top: 8px;
}
.comment .c-actions {
	display: flex;
	gap: 14px;
	margin-top: 6px;
	font-family: var(--font-sans);
	font-size: 12px;
	color: var(--ink-3);
}
.comment .c-actions button,
.comment .c-actions .comment-reply-link {
	background: transparent;
	border: 0;
	padding: 0;
	color: inherit;
	font: inherit;
	text-decoration: none;
	cursor: pointer;
}
.comment .c-actions button:hover,
.comment .c-actions .comment-reply-link:hover {
	color: var(--nd-navy);
}

/* Replies — indent-only hierarchy. Sandbox shipped a 2px line-soft left
 * rule on .replies, but it competed visually with the gold rule on
 * .is-author .c-content (parallel doubled rules on author replies). Per
 * docs/decisions.md 2026-05-09 in-browser tuning, the grey rule is
 * dropped and 18px padding-left alone carries the nesting cue. */
.comment .replies {
	margin-top: 14px;
	padding-left: 18px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}
/* Replies are <div class="comment"> — break the depth-0 grid so .c-content
 * fills the available width (the depth-0 .auto 1fr grid leaves a single-
 * child .c-content shrink-wrapped). Block layout matches sandbox visual. */
/* Replies — block layout escapes the depth-0 grid; full reset of any
 * legacy borders/padding/margin so .replies' gap is the only spacing. */
.comment .replies .comment {
	display: block;
	padding: 0;
	margin: 0;
	border: 0;
}

/* Author replies — 4% navy tint with gold left rule on the .c-content wrap */
.comment.is-author .c-content {
	background: color-mix(in srgb, var(--nd-navy) 4%, transparent);
	border-left: 2px solid var(--nd-gold);
	padding: 10px 14px;
	border-radius: 0 var(--r-input) var(--r-input) 0;
}
.author-badge {
	font-family: var(--font-mono);
	font-size: 8.5px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	background: var(--nd-navy);
	color: var(--nd-gold);
	padding: 2px 6px;
	font-weight: 700;
	border-radius: var(--radius-chip);
}

/* ======================================================================
 * Article-template port Phase 2.1c — sandbox footer
 *
 * Lifted from sandbox/article-template.html lines 783-813. Token-based.
 * 4-column grid (1.4fr brand + 3 × 1fr menu columns) with a utility
 * strip below for copyright + legal links.
 * ====================================================================== */

footer.site-footer {
	background: var(--nd-navy);
	color: var(--video-band-ink-2);
	margin-top: 56px;
	/* Reserve a navy band equal to the Snack/pbstck bottom-anchored
	 * adhesion ad's height (published by assets/js/sticky-ad-spacer.js)
	 * so the fixed ad docks below the footer content instead of
	 * overlaying it. 0 when no sticky ad is present. */
	padding-bottom: var(--snack-sticky-h, 0px);
}
.footer-top {
	padding: 48px 0 36px;
	border-bottom: 1px solid var(--video-band-line);
}
.footer-inner {
	max-width: var(--page-max);
	margin: 0 auto;
	padding: 0 var(--page-pad);
}
/* Footer link hub — brand + four columns (Opponents double-wide for its two
 * name sub-columns). Matches references/UHND-Refactor-05-30-2026_10_55_PM.png. */
.footer-cols {
	display: grid;
	grid-template-columns: 1.5fr 1fr 1fr 1.7fr 1fr;
	gap: 32px;
}
/* Footer collapse at narrow viewports: at tablet drop to 2-up with the brand
 * spanning the row; at small mobile stack everything. */
@media (max-width: 1024px) {
	.footer-cols {
		grid-template-columns: 1fr 1fr;
		gap: 28px 24px;
	}
	.footer-brand {
		grid-column: 1 / -1;
	}
}
@media (max-width: 480px) {
	.footer-cols {
		grid-template-columns: 1fr;
	}
}

/* Opponents — two name sub-columns + a gold "All Opponents" link below. */
.footer-col--wide .footer-opplist {
	display: block;
	column-count: 2;
	column-gap: 28px;
	gap: 0;
}
.footer-opplist li {
	margin-bottom: 10px;
	break-inside: avoid;
}
.footer-col .footer-col__more {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin-top: 16px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	text-decoration: none;
}
.footer-col .footer-col__more:hover {
	color: #fff;
}

/* More column — Follow row with chip-style social buttons. */
.footer-follow {
	display: flex;
	align-items: center;
	gap: 14px;
	margin-top: 22px;
	padding-top: 18px;
	border-top: 1px solid var(--video-band-line);
}
.footer-follow__label {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--video-band-ink-3);
	font-weight: 700;
}
.footer-social {
	display: flex;
	gap: 10px;
}
.footer-social a {
	width: 34px;
	height: 34px;
	border-radius: 8px;
	border: 1px solid var(--video-band-line);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: rgba(255, 255, 255, .85);
}
.footer-social a:hover {
	color: var(--nd-gold);
	border-color: var(--nd-gold);
}
.footer-brand .logo {
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}
.footer-brand .logo:hover { text-decoration: none; }
.footer-brand .logo img {
	max-height: 40px;
	width: auto;
	max-width: 100%;
	display: block;
}
.footer-brand p {
	font-family: var(--font-serif);
	font-size: 14px;
	line-height: 1.55;
	color: var(--video-band-ink-2);
	max-width: 36ch;
	margin: 14px 0 0;
}
.footer-col h3 {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: var(--tracking-mono-loose);
	color: var(--nd-gold);
	font-weight: 700;
	text-transform: uppercase;
	margin: 0 0 14px;
}
.footer-col h3::before {
	content: "";
	display: block;
	width: 22px;
	height: 2px;
	background: var(--nd-gold);
	margin-bottom: 16px;
}
.footer-col ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 10px;
}
.footer-col a {
	color: rgba(255, 255, 255, .85);
	font-family: var(--font-sans);
	font-size: 13.5px;
	text-decoration: none;
}
.footer-col a:hover {
	color: var(--nd-gold);
	text-decoration: none;
}
.footer-utility {
	display: flex;
	justify-content: space-between;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
	padding: 18px 0;
	font-family: var(--font-sans);
	font-size: 11.5px;
	color: var(--video-band-ink-3);
}
.footer-utility a {
	color: inherit;
	margin-left: 18px;
	text-decoration: none;
}
.footer-utility a:hover {
	color: rgba(255, 255, 255, .85);
	text-decoration: none;
}

/* ============================================================
   Schedule page — /football/schedule/year/{slug}/ and aliases
   ============================================================ */

/* Strip the inherited .page horizontal constraints so
 * .schedule-page__container is the sole horizontal container.
 * Without this, .page applies max-width:--page-max + padding:0 --page-pad
 * AND the nested .schedule-page__container applies them again — content
 * lands at --page-pad × 2 from the edge. Same pattern as .page--home in
 * homepage.css and .page--category in category.css. Scoped to horizontal
 * only so .schedule-page's padding-top/bottom below still applies. */
.page.schedule-page {
	max-width: none;
	margin-left: 0;
	margin-right: 0;
	padding-left: 0;
	padding-right: 0;
}
.schedule-page {
	/* No padding-top — the canonical breadcrumb partial that opens every
	 * `.schedule-page` surface already supplies 24px of top padding
	 * (`.breadcrumbs { padding: 24px 0 12px }`). Stacking another 24px
	 * here pushed the trail 48px from the top while article surfaces
	 * sit at 24px — same breadcrumb partial, different surrounding
	 * chrome. Aligned 2026-05-26 with the Rank Math breadcrumb retire-
	 * ment, which made the inconsistency more visible. Affects: schedule,
	 * recruiting class single, recruiting classes index (all three use
	 * `<main class="page schedule-page ...">`). */
	padding-bottom: 48px;
}
.schedule-page__container {
	max-width: var(--page-max);
	margin: 0 auto;
	padding-left: var(--page-pad);
	padding-right: var(--page-pad);
}

/* ── Canonical page header row (title + selector) ──
 * Shared by the football schedule and recruiting class detail (and any
 * future redesigned page that uses this chrome). The earlier simpler
 * `.schedule-page__header` flex rule was superseded in the 2026-05-19
 * unification: both surfaces now render `<header class="schedule-page__header">`
 * containing an inner div with H1 + .gold-rule (+ optional .deck) on
 * the left and a `.header-picker` dropdown on the right.
 *
 * H1 size: 20% smaller than the original standalone recruiting comp's
 * 2.25–3.25rem range so it sits in better proportion with the gold rule
 * and adjacent picker. Originally `clamp(2.25rem, 3.4vw, 3.25rem)`. */
.schedule-page__header {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	align-items: end;
	gap: 32px;
	margin: 0;
	padding: 4px 0 28px;
	border-bottom: 1px solid var(--line-soft);
}
/* The .page prefix on .schedule-page__title bumps specificity past
 * .wf-active h1 (0,1,1 → 0,2,1) so the serif font wins regardless of
 * Web Font Loader timing. Both surfaces ship a .schedule-page__title
 * class on their H1.
 *
 * font-size uses !important because Jannah's customizer emits a bare
 * `h1 { font-size: 34px !important }` rule that wins on the football
 * schedule but (for context-dependent cascade reasons) not the
 * recruiting class — so without !important the two H1s render at
 * 34px vs 34.816px. Fighting !important with !important here keeps
 * the two surfaces in lockstep. Same pattern as .article-header
 * h1.headline above; see the rationale at style.css §1145. */
.page .schedule-page__header .schedule-page__title {
	font-family: var(--font-serif);
	font-size: clamp(1.8rem, 2.72vw, 2.6rem) !important;
	line-height: 1.04;
	letter-spacing: -.02em;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0;
	text-wrap: balance;
}
.schedule-page__header .gold-rule {
	width: 48px;
	height: 3px;
	background: var(--nd-gold);
	margin: 14px 0 0;
}
.schedule-page__header .deck {
	font-family: var(--font-serif);
	font-style: italic;
	font-size: 17px;
	line-height: 1.45;
	color: var(--ink-2);
	margin: 14px 0 0;
	text-wrap: pretty;
}

.schedule-page__empty {
	padding: 48px 24px;
	text-align: center;
	color: var(--ink-3);
	font-family: var(--font-sans);
	font-size: 15px;
}

/* Head-coach subhead — sits between page header and stat-strip on
 * historical (snapshot) seasons that carry a `head_coach` field. The
 * block hides itself on seasons without the field (modern era).
 * Spec: docs/templates/schedule.md §15.5. */
.schedule-page__coach {
	margin: 12px 0 16px 0;
	display: flex;
	align-items: baseline;
	gap: 10px;
	flex-wrap: wrap;
}
/* .schedule-page__coach-label eyebrow → canonical .micro-label--micro --heavy (2026-06-06). */
.schedule-page__coach-name {
	font-family: var(--font-serif);
	font-size: 18px;
	font-weight: 600;
	color: var(--ink);
	line-height: 1.2;
}

/* ── Metrics strip (canonical stat row) ──
 * Default 4-cell layout (recruiting class). Use `.metrics-strip--6`
 * for the 6-cell football schedule variant. Cell styling, label/
 * value typography, and the gold first-cell accent are shared.
 * Schedule renders this as a `<dl>` with `<dt class="lbl">` /
 * `<dd class="val">` pairs for screen-reader semantics; recruiting
 * uses `<span>` children. The `margin: 0` resets on .lbl/.val
 * neutralize the UA `<dt>`/`<dd>` margins. */
.metrics-strip {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	margin: 0 0 24px;
	border-top: 1px solid var(--line);
	border-bottom: 1px solid var(--line);
	background: var(--card-raised);
}
.metrics-strip--6 {
	grid-template-columns: repeat(6, minmax(0, 1fr));
}
.metric-cell {
	/* Padding tightened 22 → 16 on 2026-05-20 to reduce stat-strip
	 * vertical footprint on both the schedule and recruiting class
	 * pages (Frank: "too big, take up less vertical space"). Combined
	 * with the val font-size drop 42 → 36 below, the strip shrinks
	 * from ~140px to ~105px tall. */
	padding: 16px;
	border-left: 1px solid var(--line-soft);
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.metric-cell:first-child {
	border-left: 0;
}
.metric-cell .lbl {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
	margin: 0;
}
.metric-cell .val {
	font-family: var(--font-serif);
	font-weight: 700;
	font-size: 36px; /* 42 → 36 (2026-05-20) to tighten stat-strip vertical rhythm */
	line-height: 1;
	color: var(--nd-navy);
	letter-spacing: -.015em;
	font-variant-numeric: tabular-nums;
	display: flex;
	align-items: baseline;
	gap: 6px;
	margin: 0;
}
.metric-cell .val .hash {
	color: var(--nd-gold);
	font-family: var(--font-serif);
	font-weight: 500;
	font-size: 26px; /* 30 → 26 to keep proportional with the val drop */
	letter-spacing: 0;
}
.metric-cell .sub {
	font-family: var(--font-mono);
	font-size: 10.5px;
	letter-spacing: .04em;
	color: var(--ink-4);
	font-weight: 500;
	display: flex;
	align-items: center;
	gap: 6px;
}
.metric-cell .sub .delta--up {
	color: var(--nd-green);
	font-weight: 700;
}
.metric-cell .sub .delta--down {
	color: var(--danger);
	font-weight: 700;
}
.metrics-strip > .metric-cell:first-child::before {
	content: "";
	position: absolute;
	top: -1px;
	left: 0;
	height: 3px;
	background: var(--nd-gold);
	width: 42px;
}

/* ── Section head (canonical reusable primitive) ──
 * Serif H2 + mono count + right-aligned mono .micro attribution
 * over a bottom hairline rule. Used by:
 *   - Recruiting class detail (BCR / Position Groups / Commits modules)
 *   - Football schedule (full games list)
 *   - Future body-col modules across the site
 * Spec + anatomy: docs/components/section-head.md.
 *
 * Markup contract:
 *   <div class="section-head">
 *     <h2>
 *       {Section title}
 *       <span class="count">{N units}</span>      ← optional
 *     </h2>
 *     <span class="micro">{attribution}</span>     ← optional
 *   </div>
 */
.section-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 18px;
	padding-bottom: 12px;
	border-bottom: 1px solid var(--line);
}
/* font-family/font-size use !important because Jannah's Web Font
 * Loader injects `.wf-active h2 { font-family: 'Raleway' !important }`
 * (sans-serif) once fonts load, and the customizer emits a bare
 * `h2 { font-size: ... !important }` rule. Same pattern + rationale
 * as the article headline at style.css §1145 and the schedule-page
 * title at §"Canonical page header row". */
.section-head h2 {
	font-family: var(--font-serif) !important;
	font-weight: 600;
	font-size: 22px !important;
	letter-spacing: -.005em;
	color: var(--nd-navy);
	margin: 0;
	display: flex;
	align-items: baseline;
	gap: 10px;
}
.section-head h2 .count {
	font-family: var(--font-mono);
	font-size: 12px;
	font-weight: 500;
	color: var(--ink-3);
	letter-spacing: .06em;
}
.section-head .micro {
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 600;
}

/* Season selector — native <details> / <summary> dropdown */
.schedule-season-nav {
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	position: relative;
}
.schedule-season-nav summary.schedule-season-nav__toggle {
	list-style: none; /* hide native disclosure marker */
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 8px 14px;
	background: var(--card-raised);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	color: var(--nd-navy);
	font-weight: 600;
	transition: border-color .15s ease, background .15s ease;
	user-select: none;
}
.schedule-season-nav summary.schedule-season-nav__toggle::-webkit-details-marker {
	display: none;
}
.schedule-season-nav summary.schedule-season-nav__toggle:hover {
	border-color: var(--line-strong);
	background: var(--bg-muted);
}
.schedule-season-nav[open] summary.schedule-season-nav__toggle {
	border-color: var(--nd-navy);
}
.schedule-season-nav__caret {
	font-size: 10px;
	color: var(--ink-3);
	transition: transform .15s ease;
}
.schedule-season-nav[open] .schedule-season-nav__caret {
	transform: rotate(180deg);
}
.schedule-season-nav__list {
	position: absolute;
	top: calc(100% + 4px);
	right: 0;
	z-index: 20;
	min-width: 140px;
	max-height: 320px;
	overflow-y: auto;
	margin: 0;
	padding: 6px 0;
	list-style: none;
	background: var(--card-raised);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	box-shadow: var(--shadow-card);
}
.schedule-season-nav__list li {
	margin: 0;
	padding: 0;
}
.schedule-season-nav__link {
	display: block;
	padding: 8px 14px;
	color: var(--ink-2);
	text-decoration: none;
	font-weight: 600;
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: 0.06em;
}
.schedule-season-nav__link:hover,
.schedule-season-nav__link:focus-visible {
	background: var(--bg-muted);
	color: var(--nd-navy);
}
.schedule-season-nav__link.is-active {
	color: var(--nd-navy);
	background: var(--accent-tint);
}

/* ── Season picker panel (schedule page) ──
 * Wider 2-zone dropdown: decade tabs on top, year grid below. Used
 * only by the football schedule's season selector — the recruiting
 * class-selector keeps the simpler `.schedule-season-nav__list` flat
 * list since it only carries ~10 classes.
 *
 * The active-decade swap is data-driven: setting
 * `data-active-decade="{decade}"` on .season-picker__years hides every
 * <li> whose data-decade attribute doesn't match. JS toggles this; the
 * no-JS fallback (panel rendered without the attribute) shows all
 * years stacked, still navigable. */
.season-picker__panel {
	position: absolute;
	top: calc(100% + 4px);
	right: 0;
	z-index: 20;
	width: 440px;
	max-width: calc(100vw - 32px);
	margin: 0;
	padding: 14px 12px 12px;
	list-style: none;
	background: var(--card-raised);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	box-shadow: var(--shadow-card);
}
.season-picker__decades {
	display: flex;
	flex-wrap: wrap;
	gap: 2px 4px;
	padding-bottom: 10px;
	margin-bottom: 10px;
	border-bottom: 1px solid var(--line-soft);
}
.season-picker__decade-tab {
	appearance: none;
	border: 0;
	background: transparent;
	cursor: pointer;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	color: var(--ink-3);
	padding: 6px 8px;
	border-radius: 3px;
	transition: color .15s ease, background .15s ease;
}
.season-picker__decade-tab:hover,
.season-picker__decade-tab:focus-visible {
	color: var(--nd-navy);
	background: var(--bg-muted);
	outline: none;
}
.season-picker__decade-tab.is-active {
	color: var(--nd-navy);
	box-shadow: inset 0 -2px 0 var(--nd-gold);
	border-radius: 0;
}
.season-picker__years {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2px 6px;
	margin: 0;
	padding: 0;
	list-style: none;
	max-height: 260px;
	overflow-y: auto;
}
.season-picker__years > li {
	margin: 0;
	padding: 0;
}
/* JS-driven decade swap: when the `data-active-decade` attribute is
 * present on the <ul>, hide every <li> whose decade doesn't match.
 * Without the attribute (no-JS path), this rule has nothing to hide
 * so every year shows — degraded but functional. */
.season-picker__years[data-active-decade="1900"] > li:not([data-decade="1900"]),
.season-picker__years[data-active-decade="1910"] > li:not([data-decade="1910"]),
.season-picker__years[data-active-decade="1920"] > li:not([data-decade="1920"]),
.season-picker__years[data-active-decade="1930"] > li:not([data-decade="1930"]),
.season-picker__years[data-active-decade="1940"] > li:not([data-decade="1940"]),
.season-picker__years[data-active-decade="1950"] > li:not([data-decade="1950"]),
.season-picker__years[data-active-decade="1960"] > li:not([data-decade="1960"]),
.season-picker__years[data-active-decade="1970"] > li:not([data-decade="1970"]),
.season-picker__years[data-active-decade="1980"] > li:not([data-decade="1980"]),
.season-picker__years[data-active-decade="1990"] > li:not([data-decade="1990"]),
.season-picker__years[data-active-decade="2000"] > li:not([data-decade="2000"]),
.season-picker__years[data-active-decade="2010"] > li:not([data-decade="2010"]),
.season-picker__years[data-active-decade="2020"] > li:not([data-decade="2020"]),
.season-picker__years[data-active-decade="2030"] > li:not([data-decade="2030"]) {
	display: none;
}

/* ── Season archive (footer nav) ──
 * Below-the-rows browse-all-seasons region. Each decade is a single
 * row: decade label on the left, a 10-column year-pill grid on the
 * right that stretches edge-to-edge. Years run ASC inside a decade
 * (1980 → 1989) so the row reads as a chronological timeline;
 * incomplete decades (e.g. the current 2020s) leave trailing cells
 * empty. Decade rows themselves are stacked DESC (newest decade
 * row first). Year pills reuse the schedule filter-chip primitive
 * defined above; mobile reflow is intentionally deferred. */
.season-archive {
	margin-top: 48px;
}
.season-archive__decade {
	display: grid;
	grid-template-columns: 80px 1fr;
	align-items: center;
	gap: 16px;
	padding: 14px 0;
	border-bottom: 1px solid var(--line-soft);
}
.season-archive__decade:last-child {
	border-bottom: 0;
}
/* Decade label — soft serif tag. Serif font handles the lowercase-s
 * x-height differential against the digits (a problem mono couldn't
 * solve). Square corners + a 3px navy right-edge accent intentionally
 * break the link affordance — the year pills next door are rounded
 * with borders, so the label needs a different shape to read as a
 * "tag, not a button". Right-edge bar points toward the year row it
 * labels. Background bumped to --bg-muted for visibility. Same 30px
 * height as the year pills for vertical rhythm. */
.season-archive__decade-label {
	display: inline-flex;
	align-items: center;
	justify-content: flex-start;
	height: 30px;
	padding: 0 12px;
	background: var(--bg-muted);
	border-right: 3px solid var(--nd-navy);
	border-radius: 0;
	font-family: var(--font-serif);
	font-size: 15px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0;
	line-height: 1;
}
.season-archive__years {
	display: grid;
	grid-template-columns: repeat(10, 1fr);
	gap: 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.season-archive__years > li {
	margin: 0;
	padding: 0;
	min-width: 0;
}
.season-archive__year {
	width: 100%;
	font-variant-numeric: tabular-nums;
}

/* Phase 7a (2026-05-23): Browse All Seasons grid responsive collapse.
 * At desktop the 10-column year grid reads cleanly; below 760 the cells
 * compress past the year-label width (4 digits + chip padding needs
 * ~40-50px). Drop to 5-col at ≤760px, stack the decade label above
 * the years at ≤520px so the label has full row width. Was P1-2 in
 * the responsive audit. */
@media (max-width: 760px) {
	.season-archive__years {
		grid-template-columns: repeat(5, 1fr);
	}
}
@media (max-width: 520px) {
	.season-archive__decade {
		grid-template-columns: 1fr;
		gap: 8px;
	}
	.season-archive__decade-label {
		justify-self: start;
	}
}

/* ── Header picker (labeled dropdown) ──
 * Shared by both the recruiting class header (CLASS · YEAR) and the
 * football schedule season selector (SEASON · YEAR). The labeled two-
 * part chip is the canonical page-header dropdown style across
 * redesigned pages. Overrides the base .schedule-season-nav pill
 * appearance with a borderless-on-the-inside, hairline-divided
 * LABEL/VALUE structure. */
.schedule-season-nav.header-picker {
	display: inline-flex;
	align-items: center;
	height: 42px;
}
.schedule-season-nav.header-picker .schedule-season-nav__toggle.header-picker__toggle {
	border: 1px solid var(--line-strong);
	background: var(--card-raised);
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--nd-navy);
	height: 100%;
	padding: 0;
	border-radius: 0;
	gap: 0;
}
.schedule-season-nav.header-picker .header-picker__label {
	padding: 0 10px 0 14px;
	color: var(--ink-3);
	font-size: 10px;
	border-right: 1px solid var(--line-soft);
	height: 100%;
	display: inline-flex;
	align-items: center;
}
.schedule-season-nav.header-picker .header-picker__value {
	padding: 0 12px;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	color: var(--nd-navy);
}
.schedule-season-nav.header-picker .schedule-season-nav__caret.header-picker__caret {
	opacity: .55;
	font-size: 10px;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
	.schedule-season-nav__caret,
	.schedule-season-nav summary.schedule-season-nav__toggle {
		transition: none;
	}
}

/* Filter chips + season archive years — shared pill primitive.
 *
 * Both surfaces render the same mono-uppercase outlined pill that
 * flips to a solid-navy state when active. Combining the selectors
 * here (rather than factoring to a `.pill` class) keeps the existing
 * BEM names intact and adds zero markup churn on either side. */
.schedule-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 16px;
	margin: 0 0 16px 0;
}
.schedule-filters__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}
.schedule-filters__chip,
.season-archive__year {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 30px;
	padding: 0 14px;
	border: 1px solid var(--line);
	border-radius: var(--radius-pill);
	background: var(--card-raised);
	color: var(--ink-2);
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	cursor: pointer;
	text-decoration: none;
	transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.schedule-filters__chip:hover,
.season-archive__year:hover {
	background: var(--bg-muted);
	border-color: var(--line-strong);
	color: var(--nd-navy);
}
.schedule-filters__chip:focus-visible,
.season-archive__year:focus-visible {
	outline: 2px solid var(--nd-navy);
	outline-offset: 2px;
}
.schedule-filters__chip.is-active,
.season-archive__year.is-active {
	background: var(--nd-navy);
	border-color: var(--nd-navy);
	color: var(--card-raised);
}
/* .schedule-filters__status eyebrow → canonical .micro-label--lg --tight (2026-06-06). */
@media (prefers-reduced-motion: reduce) {
	.schedule-filters__chip,
	.season-archive__year {
		transition: none;
	}
}

/* ===== Roster page ================================================
 * The roster reuses the schedule-page chrome above (.schedule-page*,
 * .schedule-filters__chip, .deck) + the canonical .data-table. Only the
 * per-chip count, the transfer badge, and the wide-table mobile scroll
 * are roster-specific. See template-football-roster.php. */

/* Player count inside a position chip — subtler than the uppercase label,
 * and opacity-based so it stays legible on the active (navy) chip too. */
.schedule-filters__count {
	margin-left: 4px;
	font-weight: 400;
	opacity: 0.65;
}

/* Transfer indicator after a player name — prior school as a small pill. */
.roster-table__transfer {
	display: inline-block;
	margin-left: 8px;
	padding: 1px 7px;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 500;
	letter-spacing: .02em;
	color: var(--ink-2);
	background: var(--bg-sunk);
	border: 1px solid var(--line);
	border-radius: 9999px;
	vertical-align: middle;
}

/* Seven columns get tight on phones — let the table scroll rather than
 * crush the hometown column. */
@media (max-width: 760px) {
	.roster-table {
		display: block;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
	}
}

/* Status pill — the schedule-page scoped duplicate that lived here
 * was removed 2026-05-22 with Phase 3d of the CSS rebuild. The
 * canonical primitive now lives sitewide at style.css §"Status pill"
 * (near the top of the file); the schedule page inherits it without
 * a per-surface override. */

/* Schedule rows — list of games, anchor wraps each entire row */
.schedule-rows {
	list-style: none;
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--line);
}
.schedule-row {
	border-bottom: 1px solid var(--line-soft);
}

/* Shamrock Series banner — full-row pill below the game row.
 * Rendered when row['is_shamrock_series'] is true (cfbd_shamrock_series
 * canonical → editorial shamrock_series fallback). Background uses
 * --green-utility (kelly green) to match the recruiting-page data bars.
 * aria-hidden because the screen-reader context lives in the anchor's
 * aria-label. */
.schedule-row__banner {
	/* Shared anatomy for all banner flavors (Shamrock + Bowl). Color is
	 * the only thing that varies per flavor — the layout, typography,
	 * and inset are constant so readers learn the shape once. */
	color: var(--nd-navy);
	font-family: var(--font-mono);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	/* Left padding doubled (8 → 16) for a small inset; vertical
	 * padding tightened to 5px so the banner reads as a slim ribbon
	 * sitting under its row rather than a second full row. */
	padding: 5px 8px 5px 16px;
	display: flex;
	align-items: center;
	gap: 6px;
}
.schedule-row__banner--shamrock {
	/* 70% transparent = 30% opaque green mix. */
	background: color-mix(in srgb, var(--green-utility) 30%, transparent);
}
.schedule-row__banner--bowl {
	/* Muted navy wash. Iterated from the original gold 18% (collided with
	 * the warm-tan `--bg-header-row` introduced 2026-05-20) → gold 45%
	 * (too loud) → 12% navy here. Bowl games = postseason / championship
	 * stage so navy is the meaningful semantic; the 12% mix keeps it light
	 * enough not to read as "somber" while staying hue-far from both the
	 * warm-tan header row (hue 80) and the Shamrock banner's green (hue 142).
	 * Navy banner text inside stays legible because the cream page bg
	 * dilutes the wash to a pale slate tint. */
	background: color-mix(in srgb, var(--nd-navy) 12%, transparent);
}
.schedule-row__banner-icon {
	/* Up chevron pointing at the game row above the banner. Mirrors the
	 * masthead submenu chevron — same viewBox + stroke, path flipped. */
	flex-shrink: 0;
}

/* ─── Canonical eyebrow / micro-label (locked 2026-06-06) ─────────────
 * THE single source of truth for the mono-uppercase "eyebrow" label used
 * across the site (module labels, section heads, card kickers, table-group
 * labels, meta tags). Before this, the pattern had fragmented into ~118
 * hand-rolled rules across ~84 value combinations — exactly the drift the
 * design system exists to prevent. All eyebrows should now use this class +
 * a modifier instead of re-declaring the recipe.
 *
 * Built only from tokens: the --label-* size scale + the mono-tracking 3-tier
 * scale (tokens.css). Base = the default 10px / loose-tracking / ink-3 / 600
 * eyebrow. Modifiers compose:
 *   size: .micro-label--sm (9px) · (base 10px) · --lg (11px) · --xl (12px)
 *   tone: --gold (accent) · --muted (ink-4) · --on-dark (navy-band surfaces)
 *   tracking: --tight (0.08em) when set on a dense inline row
 * Document: docs/components/eyebrow.md. New eyebrow CSS must not re-declare
 * font-family:var(--font-mono)+text-transform:uppercase — use this class. */
.micro-label {
	font-family: var(--font-mono);
	text-transform: uppercase;
	line-height: 1;
	font-weight: 600;
	font-size: var(--label-md);
	letter-spacing: var(--tracking-mono-loose);
	color: var(--ink-3);
}
.micro-label--sm { font-size: var(--label-sm); }
.micro-label--lg { font-size: var(--label-lg); }
.micro-label--xl { font-size: var(--label-xl); }
.micro-label--tight { letter-spacing: var(--tracking-mono-tight); }
.micro-label--micro { letter-spacing: var(--type-micro-tracking); }
.micro-label--gold { color: var(--nd-gold); font-weight: 700; }
.micro-label--muted { color: var(--ink-4); }
.micro-label--heavy { font-weight: 700; }
.micro-label--on-dark { color: var(--video-band-ink-2); }

/* ─── Canonical header row (locked 2026-05-20) ────────────────────────
 * Shared between data tables and non-table row-lists. Two opt-ins:
 *   - <table class="data-table">  → cells styled via `thead th`
 *   - <div class="row-head">      → cells styled via `.row-head__cell`
 * Modifier classes on the cell: `.center`, `.num`.
 *
 * Table consumer needs the four border resets to strip Jannah's default
 * `table thead th` borders + horizontal padding (no grid gap between
 * cells). Non-table consumer relies on the wrapping grid for column
 * layout, so it carries vertical padding only. */
.data-table thead th,
.row-head__cell {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
	text-align: left;
	background: var(--bg-header-row);
	border-bottom: 1px solid var(--line);
}
/* Wrapper tint so the inter-cell grid gap in non-table consumers
 * doesn't show the page bg through, breaking the band visually. Tables
 * don't need this (cells butt up against each other, no gap). */
.row-head {
	background: var(--bg-header-row);
}
.data-table thead th {
	padding: 10px 14px 12px;
	border-top: 0;
	border-right: 0;
	border-left: 0;
}
.row-head__cell {
	padding: 10px 0 12px;
}
.data-table thead th.center,
.row-head__cell.center { text-align: center; }
.data-table thead th.num,
.row-head__cell.num { text-align: right; }
/* Body cell alignment modifiers — mirror the thead modifiers so `.num`
 * and `.center` work consistently across the whole column without
 * per-surface overrides. */
.data-table tbody td.num,
.data-table tbody th.num { text-align: right; }
.data-table tbody td.center,
.data-table tbody th.center { text-align: center; }
/* Sortable-table button reset. js/sortable-table.js wraps each
 * sortable header label in <button class="sort-btn"> for keyboard a11y;
 * the native button styling (grey wash, sans-serif font reset) masks
 * the canonical thead treatment so we force full inheritance. */
.data-table thead th .sort-btn {
	appearance: none;
	background: transparent;
	border: 0;
	margin: 0;
	padding: 0;
	font: inherit;
	color: inherit;
	letter-spacing: inherit;
	text-transform: inherit;
	text-align: inherit;
	cursor: pointer;
}

/* Canonical body cell treatment (promoted 2026-05-21 from
 * `.recruiting-page .commits-table tbody td` in cpt-rough.css §"Commits
 * table"). Pairs with the `.data-table thead th` block above so every
 * surface that opts into `.data-table` inherits the full recruiting-
 * class table look: 14px padding, soft hairline divider, subtle navy
 * hover wash, last-row no-border. Surface-specific column widths /
 * alignment overrides stay scoped to each surface. */
.data-table {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--font-sans);
}

/* Phase 7a (2026-05-23): wide-table responsive scroll at narrow viewports.
 * The Jannah-era `assets/js/single.js` script wraps every <table> inside
 * `.the-post` with `<div class="table-is-responsive">`. That wrapper's
 * default overflow was `visible` (the corresponding Jannah CSS was
 * deleted in Phase 6b). Add the overflow handling here so wide tables
 * scroll horizontally inside the wrapper at narrow viewports instead of
 * pushing the page canvas wide.
 *
 * Tables NOT wrapped (.data-table consumers in PHP partials that don't
 * route through `the_content`) get their own block-level scroll
 * container via .table-scroll-wrap (a small wrapper authored alongside
 * each consumer that needs it — see template-parts/cpt/coach/
 * coach-hc-record.php etc.). Was P1-3 in the responsive audit. */
@media (max-width: 760px) {
	.table-is-responsive,
	.table-scroll-wrap {
		overflow-x: auto;
		max-width: 100%;
		-webkit-overflow-scrolling: touch;
	}
}
.data-table tbody td,
.data-table tbody th {
	padding: 14px;
	border-bottom: 1px solid var(--line-soft);
	vertical-align: middle;
	color: var(--text);
	font-weight: 500;
}
.data-table tbody tr:hover {
	background: rgba(12, 35, 64, 0.025);
}
.data-table tbody tr:last-child td,
.data-table tbody tr:last-child th {
	border-bottom: 0;
}
/* Suppress Jannah's default `td/th` right-border + `tr:nth-child(even)`
 * striping so canonical rendering wins without per-surface resets. */
.data-table td,
.data-table th {
	border-right: 0;
}
.data-table tr:nth-child(even) {
	background: transparent;
}
/* Canonical linked-cell treatment, promoted from the recruiting-class commits
 * table (`.player-text .name`): navy, no underline at rest, accent + underline
 * on hover. Applies to every `.data-table` consumer (roster, players archive,
 * opponent meetings, …) so linked rows read consistently instead of falling
 * back to the default green underlined article-link style. */
.data-table tbody a {
	color: var(--nd-navy);
	font-weight: 600;
	text-decoration: none;
}
.data-table tbody a:hover {
	color: var(--accent-hover);
	text-decoration: underline;
}

/* TablePress tables are reskinned to the .data-table look in a separate sheet
 * (assets/css/tablepress-skin.css) that loads AFTER TablePress's own
 * default.css — see goldendome_enqueue_tablepress_skin() + docs/decisions.md
 * 2026-06-06. It can't live in this bundle: default.css loads later and
 * redeclares TablePress's theming variables on `.tablepress`, so a bundle-level
 * remap (equal specificity, earlier source order) silently loses. */

/* Schedule rows header — non-table opt-in consumer of `.row-head__cell`.
 * Mirrors the .schedule-row__anchor grid so labels align with the row
 * columns below. Hidden at the same breakpoint the row reflows so we
 * don't surface a key whose columns no longer exist.
 *
 * Column widths locked in three places (header / anchor / static) so
 * every row aligns vertically across the table — see the .schedule-row
 * grid comment below for the per-track rationale. */
.schedule-rows-head {
	display: grid;
	grid-template-columns: 64px minmax(0, 1.6fr) minmax(0, 1.2fr) 156px 100px 110px;
	gap: 16px;
	padding: 0 8px;
}
/* When the header sits directly above the rows list, suppress the
 * list's border-top so the header's border-bottom is the only divider
 * (rather than two stacked lines reading as a double rule). */
.schedule-rows-head + .schedule-rows {
	border-top: 0;
}

.schedule-row__anchor {
	display: grid;
	/* Track widths (fixed per-row so every row + the header align on the
	 * same vertical x-positions — `auto` on Result was content-sized
	 * per-row and made Venue/TV drift, 2026-05-21 fix):
	 *   64px   Date (mono month + day stack)
	 *   1.6fr  Opponent (logo + name + prefix + rank)
	 *   1.2fr  Venue (name · city, state — ellipsis if needed)
	 *   156px  Result (Final pill + W/L letter + score, or kickoff time,
	 *          or TBA — sized for the widest case, the Final + score combo)
	 *   100px  TV (network name, mono, widened from 72 so PEACOCK / ESPN2 /
	 *          FOX Sports don't ellipsis-clip)
	 *   110px  Action ("GAME CENTER ›", 11px mono uppercase + .1em tracking;
	 *          110 includes a small buffer over the measured ~100 to keep
	 *          the arrow from kissing the row edge) */
	grid-template-columns: 64px minmax(0, 1.6fr) minmax(0, 1.2fr) 156px 100px 110px;
	align-items: center;
	gap: 16px;
	padding: 14px 8px;
	color: var(--ink);
	text-decoration: none;
	transition: background .12s ease;
}
.schedule-row__anchor:hover {
	background: var(--bg-elevated);
}
.schedule-row__anchor:focus-visible {
	outline: 2px solid var(--nd-navy);
	outline-offset: -2px;
	background: var(--bg-elevated);
}

/* Date column */
.schedule-row__date {
	display: flex;
	flex-direction: column;
	align-items: center;
	font-family: var(--font-mono);
	line-height: 1;
}
.schedule-row__date-month {
	font-size: 11px;
	letter-spacing: var(--type-micro-tracking);
	color: var(--ink-3);
	text-transform: uppercase;
	font-weight: 700;
}
.schedule-row__date-day {
	font-size: 22px;
	font-weight: 700;
	color: var(--nd-navy);
	margin-top: 4px;
	font-feature-settings: 'tnum';
	font-variant-numeric: tabular-nums;
}

/* Opponent column */
.schedule-row__opponent {
	display: flex;
	align-items: center;
	gap: 12px;
	min-width: 0;
}
.schedule-row__logo {
	width: 40px;
	height: 40px;
	object-fit: contain;
	flex-shrink: 0;
}
.schedule-row__opp-text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}
.schedule-row__opp-line {
	display: flex;
	align-items: baseline;
	gap: 6px;
	font-family: var(--font-serif);
	font-size: 17px;
	font-weight: 600;
	color: var(--ink);
	line-height: 1.25;
}
/* Home / Away / Neutral chip — replaces the abbreviated "vs." / "at"
 * text 2026-05-21. The opponent column previously read as `{opp logo}
 * {opp name}` with no Notre Dame anchor, so a row visually scanned as
 * one team rather than a matchup. The chip carries the location signal
 * directly ("HOME" / "AWAY" / "NEUT") so the reader doesn't have to
 * recall that the whole page is Notre Dame's schedule to parse a row.
 * Same mono register as the previous prefix; adds only a muted bg +
 * micro padding to read as a labeled chip rather than inline text. */
.schedule-row__prefix {
	display: inline-flex;
	align-items: center;
	font-family: var(--font-mono);
	font-size: 10.5px;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-tight);
	color: var(--ink-2);
	font-weight: 700;
	background: var(--bg-muted);
	padding: 2px 6px;
	border-radius: var(--radius-chip);
	white-space: nowrap;
	flex-shrink: 0;
}
.schedule-row__opp-rank {
	font-family: var(--font-mono);
	font-size: 12px;
	font-weight: 700;
	color: var(--ink-2);
	font-feature-settings: 'tnum';
	font-variant-numeric: tabular-nums;
}
.schedule-row__opp-name {
	font-weight: 600;
}

/* Venue column */
.schedule-row__venue {
	font-family: var(--font-sans);
	font-size: 13px;
	color: var(--ink-3);
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* Result column */
.schedule-row__result {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: var(--font-mono);
	font-size: 13px;
	color: var(--ink-2);
	font-feature-settings: 'tnum';
	font-variant-numeric: tabular-nums;
	justify-content: flex-end;
}
.schedule-row__wl {
	display: inline-flex;
	align-items: baseline;
	gap: 6px;
	font-weight: 700;
	color: var(--ink);
}
.schedule-row__wl-letter {
	display: inline-block;
	min-width: 1ch;
	font-weight: 800;
}
.schedule-row__wl--w .schedule-row__wl-letter { color: var(--win); }
.schedule-row__wl--l .schedule-row__wl-letter { color: var(--loss); }
.schedule-row__no-score {
	color: var(--ink-3);
	font-weight: 600;
}
.schedule-row__time {
	font-weight: 600;
	color: var(--ink-2);
}
/* TV column — own grid cell since 2026-05-12. */
.schedule-row__tv {
	font-family: var(--font-mono);
	font-size: 12px;
	color: var(--ink-2);
	font-weight: 700;
	letter-spacing: 0.04em;
	text-align: right;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.schedule-row__network {
	color: var(--ink-2);
	font-weight: 700;
}

/* Action column */
.schedule-row__action {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	font-family: var(--font-mono);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--nd-navy);
	justify-content: flex-end;
	white-space: nowrap;
}
.schedule-row__action-arrow {
	font-size: 14px;
	transition: transform .12s ease;
}
.schedule-row__anchor:hover .schedule-row__action-arrow {
	transform: translateX(2px);
}

/* Static (snapshot-driven) row — pre-2005 historical seasons.
 *
 * Wrapper-only difference from the anchor row (no href, no hover, no
 * focus state). Grid geometry is shared with .schedule-row__anchor —
 * venue + TV cells render per-row when populated, suppress per-row when
 * empty (data-driven, not mode-driven).
 *
 * Revised 2026-05-20 after the wiki sidecar landed; previous version
 * had a separate 3-column grid that over-suppressed columns based on a
 * CFBD-only data assumption. See docs/decisions.md 2026-05-20
 * "Schedule row template unifies across modern + snapshot" and
 * docs/templates/schedule.md §15.4. */
.schedule-row__static {
	display: grid;
	/* Same locked grid as `.schedule-row__anchor` so snapshot rows align
	 * with modern rows across the same column positions. See the comment
	 * on `.schedule-row__anchor` above for per-track rationale. */
	grid-template-columns: 64px minmax(0, 1.6fr) minmax(0, 1.2fr) 156px 100px 110px;
	align-items: center;
	gap: 16px;
	padding: 14px 8px;
	color: var(--ink);
}

/* Empty cells inside the unified grid — venue / TV / action slots that
 * carry no content on rows where the underlying field is absent. We
 * keep the cell in the markup (so grid tracks stay aligned across the
 * list) but suppress visual weight. */
.schedule-row__venue--empty,
.schedule-row__tv--empty,
.schedule-row__action--empty {
	min-height: 1px;
}

/* Wikipedia attribution — single page-level link rendered beneath the
 * schedule table on snapshot seasons (season ≤ 2004). Replaces the
 * per-row glyph treatment that shipped in the first Phase 4.6 cut;
 * one link per page is enough for the CC BY-SA carve-out and keeps
 * the row geometry uncluttered.
 * Spec: docs/templates/schedule.md §15.12. */
.schedule-page__attribution {
	margin: 16px 0 0;
	padding-top: 12px;
	border-top: 1px solid var(--line-soft);
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: 0.06em;
	color: var(--ink-3);
	text-align: right;
}
.schedule-page__attribution a {
	color: var(--ink-2);
	text-decoration: underline;
	text-underline-offset: 2px;
	text-decoration-color: var(--line);
	transition: color .12s ease, text-decoration-color .12s ease;
}
.schedule-page__attribution a:hover,
.schedule-page__attribution a:focus-visible {
	color: var(--nd-navy);
	text-decoration-color: var(--nd-navy);
}
.schedule-page__attribution a:focus-visible {
	outline: 2px solid var(--nd-navy);
	outline-offset: 2px;
	border-radius: 2px;
}

/* Bye row */
.schedule-row--bye {
	display: grid;
	grid-template-columns: 64px 1fr;
	align-items: center;
	gap: 16px;
	padding: 10px 8px;
	background: var(--bg-sunk);
	color: var(--ink-3);
}
.schedule-row__bye-date {
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--type-micro-tracking);
	text-transform: uppercase;
	font-weight: 700;
	text-align: center;
	color: var(--ink-3);
}
.schedule-row__bye-label {
	font-family: var(--font-sans);
	font-size: 13px;
	font-weight: 500;
	color: var(--ink-3);
}

/* Mobile (≤ 1080px) — shared header + metrics-strip reflow.
 * Used by both the football schedule and recruiting class headers.
 * The recruiting class detail's body/rail collapse at the same
 * breakpoint lives in cpt-rough.css next to the rest of its
 * recruiting-only rules. */
@media (max-width: 1080px) {
	.schedule-page__header {
		grid-template-columns: 1fr;
	}
	.metrics-strip {
		grid-template-columns: repeat(2, 1fr);
	}
	.metrics-strip > .metric-cell:nth-child(3) {
		border-left: 0;
		border-top: 1px solid var(--line-soft);
	}
	.metrics-strip > .metric-cell:nth-child(4) {
		border-top: 1px solid var(--line-soft);
	}

	/* 6-cell variant (schedule): reflow to 3 columns so values stay
	 * legible at the 36px val size. Row 2 cells gain a hairline top
	 * to mirror the top/bottom strip rule. */
	.metrics-strip--6 {
		grid-template-columns: repeat(3, 1fr);
	}
	.metrics-strip--6 > .metric-cell:nth-child(4) {
		border-left: 0;
		border-top: 1px solid var(--line-soft);
	}
	.metrics-strip--6 > .metric-cell:nth-child(n+5) {
		border-top: 1px solid var(--line-soft);
	}
}

/* Mobile — schedule rows reflow */
@media (max-width: 768px) {
	.schedule-season-nav__list,
	.season-picker__panel {
		left: 0;
		right: auto;
	}
	.season-picker__panel {
		width: auto;
	}
	.season-picker__years {
		grid-template-columns: repeat(3, 1fr);
	}

	/* Schedule row: stacked card layout on small viewports. Header row
	 * hides — its 6-column grid no longer maps to the reflowed body. */
	.schedule-rows-head { display: none; }
	.schedule-row__anchor {
		grid-template-columns: 52px 1fr auto;
		grid-template-areas:
			"date opponent action"
			"date venue    result"
			"date tv       tv";
		gap: 6px 12px;
		padding: 12px 8px;
	}
	.schedule-row__date { grid-area: date; }
	.schedule-row__opponent { grid-area: opponent; }
	.schedule-row__venue { grid-area: venue; font-size: 12px; }
	.schedule-row__result { grid-area: result; justify-content: flex-end; font-size: 12px; }
	.schedule-row__tv { grid-area: tv; text-align: left; font-size: 11px; }
	.schedule-row__tv:empty { display: none; }
	.schedule-row__action { grid-area: action; font-size: 10px; }
	.schedule-row__opp-line { font-size: 15px; }
	.schedule-row__logo { width: 32px; height: 32px; }
	.schedule-row__date-day { font-size: 18px; }

	.schedule-row--bye {
		grid-template-columns: 52px 1fr;
	}

	/* Static row mobile reflow — mirror the anchor row's mobile grid so
	 * snapshot rows stack identically to modern rows. Snapshot rows have
	 * no action chip and no per-row wiki glyph (attribution lives once
	 * per page below the table), so the action grid slot stays empty
	 * and collapses via the .--empty rule below. */
	.schedule-row__static {
		grid-template-columns: 52px 1fr auto;
		grid-template-areas:
			"date opponent ."
			"date venue    result"
			"date tv       tv";
		gap: 6px 12px;
		padding: 12px 8px;
	}
	.schedule-row__venue--empty,
	.schedule-row__tv--empty,
	.schedule-row__action--empty { display: none; }
}

/* Schedule rows ≤520: on row 1 the opponent name shares space with the
 * decorative "GAME CENTER ›" action chip, and long single-word opponents
 * ("Wisconsin", "Northwestern") overflow their grid cell and run under the
 * chip text (responsive audit P1-A, 2026-06-05). The whole row is already a
 * tap target, so the chip's text label is redundant on small screens —
 * collapse it to just the chevron, freeing the width for the name.
 * overflow-wrap guards against any remaining over-long token. */
@media (max-width: 520px) {
	.schedule-row__action-label { display: none; }
	.schedule-row__opp-name { overflow-wrap: anywhere; }
}

/* ============================================================
   Recruiting Class page — /recruiting/{year}/
   Page chrome reuses the football schedule page's primitives:
   .schedule-page container, .schedule-page__header / __title (now
   shared, defined in cpt-rough.css), and the .metrics-strip /
   .metric-cell stat row (also shared, with a --6 variant for the
   schedule's 6-cell version). The recruits table itself uses the
   .last-games-table primitive from cpt-rough.css; its recruit-
   specific column tweaks live alongside in cpt-rough.css
   (§recruits-table).
   ============================================================ */

/* Recruiting page uses the article-template .layout grid (rail provides
 * the narrowing effect) — outer container stays at the default --page-max.
 * The --page-max-data token remains in tokens.css for future single-column
 * data pages.
 *
 * The .body-col stacks its modules with a consistent gap matching the
 * article rail's rhythm. Modules (BCR card, Position Groups h2+bars,
 * Commits h2+table) carry their own top spacing via .cpt-module-head's
 * --space-module-top margin.
 *
 * Vertical padding on .layout is zeroed here so the shell matches the
 * schedule page. The base .layout rule (style.css §1334) supplies
 * 32px/56px top/bottom for article templates, but on this page the
 * outer .schedule-page already provides 24/48 — stacking both produced
 * a visibly inflated shell (104px of bottom whitespace vs the schedule
 * page's 48). The stat strip sits above .layout in PHP, so the first
 * body module's own top margin still separates it from the stat band. */
.recruiting-page .layout {
	padding-top: 0;
	padding-bottom: 0;
}
.recruiting-page .body-col {
	display: flex;
	flex-direction: column;
	gap: 0;            /* gap comes from each module's own top margin */
}
.recruiting-page .rail {
	display: flex;
	flex-direction: column;
	gap: 28px;
}
@media (max-width: 900px) {
	.recruiting-page .layout {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Empty-state note when no sync data is present on a draft post. */
.recruiting-page__empty {
	margin: 0 0 24px 0;
	padding: 16px 18px;
	font-family: var(--font-mono);
	font-size: 12px;
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
	color: var(--ink-3);
	background: var(--bg-elevated);
	border: 1px solid var(--line-soft);
	border-radius: var(--radius);
	text-align: center;
}

/* Position-group module reuses the .performers-grid / .performer card
 * primitive from cpt-rough.css §Top Performers — no recruiting-page CSS
 * additions needed for that module. Wrapper class is .cpt-module--positions. */

/* =====================================================================
   VIDEO POST TEMPLATE — lifted from sandbox/video-post/video-post.html
   2026-05-17. Loaded only when single-video.php renders (tie_post_head
   = 'video' postmeta routes through the template_include filter in
   functions.php). All 570 existing video posts pick up these styles.

   Region order matches the .video-post article in single-video.php:
   breadcrumbs (full-width) → .video-band wrap [hero + related-videos] →
   editorial → cpt-row → flanked [main + rail] → related-articles.

   Tags, author bio, comments, related-card, rail-ad — reuse the article
   template's existing CSS (lines 1660-1810 in this file); not relifted.
   ===================================================================== */

/* --- Video band: dark navy wrapper around hero + related-videos --- */
.video-band {
	background: var(--bg-video-band);
	color: var(--video-band-ink);
	margin-top: 16px;
	position: relative;
}
.video-band::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	height: 1px;
	background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--nd-gold) 30%, transparent) 20%, color-mix(in srgb, var(--nd-gold) 30%, transparent) 80%, transparent);
}
.video-band .page { padding-top: 0; padding-bottom: 0; }

/* --- Hero region: 65/35 split, video left, meta right --- */
.video-post .hero {
	display: grid;
	grid-template-columns: 65fr 35fr;
	gap: 36px;
	align-items: start;
	padding: 36px 0;
	border-bottom: 1px solid var(--line-soft);
}
.hero-video {
	position: relative;
	width: 100%;
	aspect-ratio: 16 / 9;
	background: linear-gradient(135deg, color-mix(in srgb, var(--nd-navy) 92%, transparent) 0%, color-mix(in srgb, var(--nd-navy) 70%, transparent) 60%, color-mix(in srgb, var(--ink-2) 70%, transparent) 100%);
	border: 1px solid var(--line);
	border-radius: 2px;
	overflow: hidden;
	display: grid;
	place-items: center;
	cursor: pointer;
}
.hero-video__poster {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: 0;
}
.hero-video__iframe {
	width: 100%;
	aspect-ratio: 16 / 9;
	border: 1px solid var(--video-band-line-strong);
	border-radius: 2px;
	background: #000;
}
.hero-video .thumb-label {
	position: absolute;
	left: 18px;
	top: 18px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-family: var(--font-mono);
	font-size: 10px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: color-mix(in srgb, white 80%, transparent);
	background: rgba(0, 0, 0, 0.4);
	padding: 6px 10px;
	border-radius: 2px;
	backdrop-filter: blur(4px);
}

/* --- Play overlay (also used by .video-card thumbnails) --- */
.play-overlay {
	position: relative;
	z-index: 1;
	width: 88px;
	height: 88px;
	border-radius: 50%;
	background: rgba(12, 35, 64, 0.78);
	border: 1px solid rgba(255, 255, 255, 0.18);
	display: grid;
	place-items: center;
	transition: transform 0.15s ease, background 0.15s ease;
}
.hero-video:hover .play-overlay { transform: scale(1.06); background: rgba(12, 35, 64, 0.88); }
.play-overlay .triangle {
	width: 0;
	height: 0;
	border-left: 24px solid #fff;
	border-top: 14px solid transparent;
	border-bottom: 14px solid transparent;
	margin-left: 6px;
}
.duration-pill {
	position: absolute;
	right: 14px;
	bottom: 14px;
	z-index: 2;
	font-family: var(--font-mono);
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.02em;
	font-variant-numeric: tabular-nums;
	color: #fff;
	background: rgba(12, 35, 64, 0.88);
	padding: 3px 8px;
	border-radius: var(--radius-chip);
	border: 1px solid rgba(255, 255, 255, 0.12);
}

/* --- Hero right column (meta) --- */
.hero-meta { display: flex; flex-direction: column; gap: 14px; min-width: 0; padding-top: 2px; }
.hero-kicker {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: var(--font-mono);
	font-size: 11px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--nd-gold);
	font-weight: 700;
}
.hero-kicker .video-chip {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: 0.18em;
	color: var(--nd-navy);
	background: color-mix(in srgb, var(--nd-gold) 22%, transparent);
	padding: 3px 7px;
	border-radius: var(--radius-chip);
	font-weight: 700;
}
.hero-kicker .video-chip svg { margin-right: 2px; }
.hero-kicker a { color: inherit; }
.hero-headline {
	font-family: var(--font-serif);
	font-size: var(--type-card-feature-size);
	line-height: 1.12;
	letter-spacing: -0.015em;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0;
	text-wrap: pretty;
}
.hero-deck {
	font-family: var(--font-serif);
	font-size: 17px;
	line-height: 1.5;
	color: var(--ink-2);
	margin: 0;
	text-wrap: pretty;
}
.hero-meta-row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
	padding: 12px 0;
	border-top: 1px solid var(--line-soft);
	border-bottom: 1px solid var(--line-soft);
}
.hero-byline { display: flex; align-items: center; gap: 9px; min-width: 0; }
.video-post .avatar {
	width: 30px;
	height: 30px;
	border-radius: 50%;
	background: linear-gradient(135deg, var(--nd-navy), var(--ink-2));
	color: var(--nd-gold);
	display: grid;
	place-items: center;
	font-family: var(--font-serif);
	font-weight: 700;
	font-size: 11px;
	flex-shrink: 0;
}
.hero-byline .name { font-family: var(--font-sans); font-size: 13px; font-weight: 600; color: var(--nd-navy); }
.hero-byline .name a { color: inherit; }
.hero-meta-row .dot { width: 3px; height: 3px; border-radius: 50%; background: var(--ink-4); flex-shrink: 0; }
.hero-meta-row .meta-item { font-family: var(--font-sans); font-size: 12.5px; color: var(--ink-3); display: inline-flex; align-items: center; gap: 5px; }
.hero-meta-row .meta-item.duration {
	font-family: var(--font-mono);
	font-weight: 600;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.02em;
}
.hero-meta-row .meta-item.duration svg { color: var(--ink-3); }
.hero-meta-row .meta-item.cmts { color: var(--nd-navy); font-weight: 600; }
.hero-meta-row .meta-item time { font-variant-numeric: tabular-nums; }

.hero-actions { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 14px; }
.youtube-link {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-family: var(--font-sans);
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: 0.04em;
	color: var(--nd-navy);
	text-decoration: none;
}
.youtube-link svg.yt { color: #FF0000; }
.youtube-link:hover { color: var(--accent-hover); text-decoration: none; }
.youtube-link .arr { transition: transform 0.15s ease; }
.youtube-link:hover .arr { transform: translateX(2px); }
.share-icons { display: flex; align-items: center; gap: 2px; }
.share-icons .lbl {
	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;
	margin-right: 6px;
}
.share-icons button,
.share-icons a {
	width: 30px;
	height: 30px;
	border-radius: 4px;
	color: var(--ink-3);
	display: grid;
	place-items: center;
}
.share-icons button:hover,
.share-icons a:hover { color: var(--nd-navy); background: var(--accent-tint); text-decoration: none; }

/* --- Video band scoped overrides (flip ink/hairlines for dark UI) --- */
.video-band .hero { border-bottom: 1px solid var(--video-band-line); }
.video-band .hero-video {
	border-color: var(--video-band-line-strong);
	background: linear-gradient(135deg, #050a14 0%, #0a1426 60%, #131b2e 100%);
}
.video-band .hero-headline { color: var(--video-band-ink); }
.video-band .hero-deck { color: var(--video-band-ink-2); }
.video-band .hero-kicker { color: var(--nd-gold); }
/* Category link stays gold inside the navy band (matches the parent kicker
 * ink) instead of flipping to white. Updated 2026-05-21 per Frank's design
 * call — the gold link is the brand signal for the categorical context. */
.video-band .hero-kicker a { color: var(--nd-gold); }
.video-band .hero-kicker a:hover {
	color: color-mix(in srgb, var(--nd-gold) 70%, #fff);
}
.video-band .hero-kicker .video-chip {
	background: var(--video-band-line);
	color: var(--video-band-ink);
	border: 1px solid var(--video-band-line);
}
.video-band .hero-meta-row {
	border-top: 1px solid var(--video-band-line);
	border-bottom: 1px solid var(--video-band-line);
}
.video-band .hero-byline .name,
.video-band .hero-byline .name a { color: var(--video-band-ink); }
.video-band .avatar {
	background: linear-gradient(135deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.06));
	border: 1px solid var(--video-band-line);
}
.video-band .hero-meta-row .dot { background: var(--video-band-ink-4); }
.video-band .hero-meta-row .meta-item { color: var(--video-band-ink-3); }
.video-band .hero-meta-row .meta-item.duration { color: var(--video-band-ink); }
.video-band .hero-meta-row .meta-item.duration svg { color: var(--video-band-ink-3); }
.video-band .hero-meta-row .meta-item.cmts { color: var(--video-band-ink); }
.video-band .youtube-link { color: var(--video-band-ink); }
.video-band .youtube-link:hover { color: #fff; }
.video-band .share-icons .lbl { color: var(--video-band-ink-4); }
.video-band .share-icons button,
.video-band .share-icons a { color: var(--video-band-ink-2); }
.video-band .share-icons button:hover,
.video-band .share-icons a:hover { color: #fff; background: var(--video-band-line); }
.video-band .share-icons .share-copy.is-copied { color: #fff; background: var(--video-band-line-strong); }
.video-band .thumb-label { background: rgba(0, 0, 0, 0.5); }

/* --- Related videos strip: 4 cards across (2 at <=1024px, scroll <=760px) --- */
.related-videos { padding: 30px 0 40px; }
.related-videos-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 10px;
	margin-bottom: 18px;
}
.related-videos-head .eyebrow {
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-loose);
	color: var(--nd-navy);
}
.related-videos-head .more {
	font-family: var(--font-sans);
	font-size: 11px;
	color: var(--ink-3);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-tight);
	text-decoration: none;
}
.related-videos-head .more:hover { color: var(--nd-navy); }
.video-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px; }
.video-card { display: flex; flex-direction: column; gap: var(--card-gap); text-decoration: none; color: inherit; }
.video-card:hover { text-decoration: none; }
.video-card:hover .vc-title { color: var(--accent-hover); }
.vc-thumb {
	position: relative;
	aspect-ratio: 16 / 9;
	background: linear-gradient(135deg, color-mix(in srgb, var(--nd-navy) 80%, transparent) 0%, color-mix(in srgb, var(--ink-2) 60%, transparent) 100%);
	border: 1px solid var(--line);
	border-radius: var(--radius-media);
	overflow: hidden;
	display: grid;
	place-items: center;
}
.vc-thumb__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: 0;
}
.vc-thumb::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: rgba(12, 35, 64, 0.40);
	transition: background 0.15s ease;
}
.video-card:hover .vc-thumb::after { background: rgba(12, 35, 64, 0.28); }
.video-card .play-overlay {
	width: 48px;
	height: 48px;
	z-index: 2;
}
.video-card .play-overlay .triangle {
	border-left-width: 13px;
	border-top-width: 8px;
	border-bottom-width: 8px;
	margin-left: 3px;
}
.vc-duration {
	position: absolute;
	right: 8px;
	bottom: 8px;
	z-index: 3;
	font-family: var(--font-mono);
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 0.02em;
	color: #fff;
	background: rgba(12, 35, 64, 0.88);
	padding: 2px 6px;
	border-radius: var(--radius-chip);
	font-variant-numeric: tabular-nums;
}
.vc-title {
	font-family: var(--font-serif);
	font-size: 16px;
	font-weight: 600;
	color: var(--nd-navy);
	line-height: 1.25;
	margin: 2px 0 0;
	text-wrap: pretty;
}
.vc-date {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--ink-3);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	margin-top: 2px;
}
.video-band .vc-thumb {
	border-color: var(--video-band-line-strong);
	background: linear-gradient(135deg, #050a14 0%, #131b2e 100%);
}
.video-band .vc-title { color: var(--video-band-ink); }
.video-band .video-card:hover .vc-title { color: #fff; }
.video-band .vc-date { color: var(--video-band-ink-3); }

/* --- Editorial wrapper: centered 68ch serif body --- */
.video-post .editorial {
	max-width: var(--type-doc-body-measure);
	margin: 48px auto 36px;
	font-family: var(--font-serif);
	font-size: var(--type-doc-body-size);
	line-height: var(--type-doc-body-line);
	color: var(--text);
}
.video-post .editorial p { margin: 0 0 1.05em; }
.video-post .editorial p:last-child { margin-bottom: 0; }
.video-post .editorial a {
	color: var(--nd-navy);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 2px;
}
.video-post .editorial a:hover { color: var(--accent-hover); }
.video-post .editorial a.cpt {
	text-decoration: dotted underline;
	text-decoration-thickness: 1.5px;
	text-underline-offset: 3px;
}
.video-post .editorial a.cpt:hover { text-decoration: solid underline; }

/* --- CPT row Variant B: equal-billing horizontal cards --- */
.cpt-row-section { padding: 0 0 44px; }
.cpt-row-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 10px;
	margin-bottom: 14px;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--line-soft);
}
.cpt-row-head .eyebrow {
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-loose);
	color: var(--nd-navy);
}
.cpt-row-head .count {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--ink-3);
	letter-spacing: 0.14em;
}
.cpt-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; }
.cpt-mod {
	display: flex;
	flex-direction: column;
	background: var(--card-raised);
	border: 1px solid var(--line-soft);
	border-radius: var(--r-card);
	text-decoration: none;
	color: inherit;
	min-height: 170px;
	overflow: hidden;
	transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.cpt-mod:hover {
	text-decoration: none;
	border-color: var(--line-strong);
	transform: translateY(-1px);
	box-shadow: var(--shadow-card);
}
.cpt-mod .cm-eyebrow {
	font-family: var(--font-mono);
	font-size: 9.5px;
	letter-spacing: var(--tracking-mono-loose);
	text-transform: uppercase;
	color: var(--ink-3);
	font-weight: 700;
	padding: 11px 14px 0;
}
.cpt-mod .cm-eyebrow.player { color: var(--nd-navy); }
.cpt-mod .cm-eyebrow.game   { color: var(--nd-gold); }
.cpt-mod .cm-eyebrow.coach  { color: var(--nd-navy); }
.cpt-mod .cm-eyebrow.opponent { color: var(--ink-3); }
.cpt-mod .cm-body { padding: 8px 14px 14px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.cpt-mod .cm-foot {
	margin-top: auto;
	padding: 9px 14px;
	border-top: 1px solid var(--line-soft);
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: var(--tracking-mono-tight);
	text-transform: uppercase;
	color: var(--nd-navy);
	display: flex;
	align-items: center;
	justify-content: space-between;
}
.cpt-mod .cm-foot .arr { transition: transform 0.15s ease; }
.cpt-mod:hover .cm-foot .arr { transform: translateX(2px); }

/* Player / coach card body (Variant B) */
.cpt-mod.player .cm-body,
.cpt-mod.coach .cm-body { flex-direction: row; align-items: flex-start; gap: 12px; }
.cpt-mod.player .pic,
.cpt-mod.coach .pic {
	width: 54px;
	height: 54px;
	border-radius: 50%;
	flex-shrink: 0;
	background: linear-gradient(135deg, var(--nd-navy), var(--ink-2));
	color: var(--nd-gold);
	display: grid;
	place-items: center;
	font-family: var(--font-serif);
	font-weight: 700;
	font-size: 17px;
	overflow: hidden;
}
.cpt-mod.player .pic img,
.cpt-mod.coach .pic img { width: 100%; height: 100%; object-fit: cover; }
.cpt-mod.player .pm-meta,
.cpt-mod.coach .pm-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cpt-mod.player .pm-name,
.cpt-mod.coach .pm-name {
	font-family: var(--font-serif);
	font-size: 16.5px;
	font-weight: 600;
	color: var(--nd-navy);
	line-height: 1.15;
	margin: 0;
}
.cpt-mod.player .pm-pos,
.cpt-mod.coach .pm-pos {
	font-family: var(--font-sans);
	font-size: 11.5px;
	color: var(--ink-3);
	margin: 2px 0 0;
}

/* "In This Story" article row (template-parts/article/cpt-row.php) — tagged
   players + coaches. Lives inside .body-col, so it spans the full left-column
   width. Equal-width cards via auto-fill grid: every card is one track wide
   regardless of how many land in the last row (auto-fill keeps empty tracks,
   so a lone trailing card matches the others rather than stretching). Cards
   are headshot + name only — no eyebrow, no Profile foot (the whole card is
   the link). (2026-05-29.) */
.in-this-story.cpt-row-section { margin-top: 36px; padding-bottom: 0; }
.in-this-story .cpt-row {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 16px;
}
.in-this-story .cpt-mod { min-height: 0; }
.in-this-story .cpt-mod.player .cm-body,
.in-this-story .cpt-mod.coach .cm-body {
	flex-direction: row;
	align-items: center;
	gap: 14px;
	padding: 16px;
}
.in-this-story .cpt-mod.player .pic,
.in-this-story .cpt-mod.coach .pic {
	width: 72px;
	height: 72px;
	font-size: 22px;
}
.in-this-story .cpt-mod .pm-name { font-size: 17.5px; }

/* Game card body (Variant B — equal-billing, NOT the heavier Variant A) */
.cpt-mod.game .cm-body { display: flex; flex-direction: column; gap: 10px; padding-top: 10px; }
.cpt-mod.game .gm-matchup {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 6px;
}
.cpt-mod.game .gm-matchup .team { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.cpt-mod.game .gm-matchup .helmet {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	background: color-mix(in srgb, var(--nd-navy) 10%, transparent);
	display: grid;
	place-items: center;
	font-family: var(--font-serif);
	font-weight: 700;
	font-size: 13px;
	color: var(--nd-navy);
	border: 1px solid var(--line-soft);
	object-fit: contain;
}
.cpt-mod.game .gm-matchup .helmet.nd {
	background: var(--nd-navy);
	color: var(--nd-gold);
	border: 1px solid var(--nd-navy);
}
.cpt-mod.game .gm-matchup .score {
	font-family: var(--font-mono);
	font-size: 18px;
	font-weight: 700;
	color: var(--nd-navy);
	font-variant-numeric: tabular-nums;
	line-height: 1;
}
.cpt-mod.game .gm-matchup .score.l { color: var(--ink-3); }
.cpt-mod.game .gm-matchup .vs {
	font-family: var(--font-mono);
	font-size: 10px;
	color: var(--ink-4);
	letter-spacing: 0.14em;
	text-transform: uppercase;
}
.cpt-mod.game .gm-result { display: flex; align-items: center; gap: 8px; font-family: var(--font-sans); font-size: 11.5px; }
.cpt-mod.game .gm-result .wl {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	height: 18px;
	border-radius: var(--radius-chip);
	font-family: var(--font-mono);
	font-weight: 700;
	font-size: 10px;
	background: var(--nd-green-soft);
	color: var(--nd-green-ink);
}
.cpt-mod.game .gm-result .where { color: var(--ink-3); font-size: 11px; }

/* --- Rail-flanked section: main 68ch + sticky ad rail --- */
.video-post .flanked {
	display: grid;
	grid-template-columns: minmax(0, 1fr) var(--rail-w);
	gap: var(--rail-col-gap);
	padding: 0 0 64px;
	align-items: start;
}
.video-post .flanked-main { max-width: var(--type-doc-body-measure); min-width: 0; }
.video-post .flanked-rail {
	display: flex;
	flex-direction: column;
	gap: var(--rail-gap);
	position: sticky;
	top: calc(var(--utility-h) + var(--masthead-h) + var(--schedule-h) + 24px);
	align-self: start;
}

/* --- Extended notes: optional editorial block below comments --- */
.extended-notes {
	padding: 32px 0 8px;
	border-top: 1px solid var(--line-soft);
	margin-bottom: 40px;
}
.extended-notes .eyebrow {
	font-family: var(--font-sans);
	font-size: 11px;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: var(--tracking-mono-loose);
	color: var(--nd-navy);
	margin: 0 0 18px;
	display: flex;
	align-items: baseline;
	gap: 10px;
}
.extended-notes .eyebrow::before {
	content: "";
	width: 14px;
	height: 2px;
	background: var(--nd-gold);
	display: inline-block;
}
.extended-notes-body {
	font-family: var(--font-serif);
	font-size: var(--type-doc-body-size);
	line-height: var(--type-doc-body-line);
	color: var(--text);
}
.extended-notes-body p { margin: 0 0 1.05em; }
.extended-notes-body p:last-child { margin-bottom: 0; }
.extended-notes-body h3 {
	font-family: var(--font-serif);
	font-size: 18px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 1.6em 0 0.35em;
	letter-spacing: -0.005em;
}

/* --- Related articles wrapper: section heading + top rule.
   Card markup (.related-grid / .related-card) is already styled by the
   article template at lines ~1775-1810; this just adds the wrapper
   chrome. Renamed wrapper class so the video template can evolve
   independently of the article template's .related. --- */
.related-articles { padding: 32px 0 56px; border-top: 1px solid var(--line-strong); }
.related-articles h2 {
	font-family: var(--font-serif);
	font-size: 24px;
	font-weight: 600;
	color: var(--nd-navy);
	margin: 0 0 22px;
	padding-bottom: 10px;
	border-bottom: 2px solid var(--nd-gold);
}

/* --- Mobile breakpoints. Chrome mobile is already in style.css from the
   article-template lift; only video-specific responsive rules here. --- */
@media (max-width: 1024px) {
	.video-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 22px; }
	.cpt-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Rail collapse aligned to the sitewide 900px breakpoint (was 920) so every
   page type drops its rail at the same width — unified rail shell 2026-05-30. */
@media (max-width: 900px) {
	.video-post .flanked { grid-template-columns: 1fr; gap: 32px; }
	.video-post .flanked-rail { flex-direction: row; flex-wrap: wrap; gap: var(--rail-gap); position: static; width: 100%; }
	.video-post .flanked-rail .rail-ad { flex: 1 1 280px; }
	/* "More Videos" recent-list takes its own full-width row in the wrapped
	   horizontal rail (the ad units flow beside each other above/below it). */
	.video-post .flanked-rail .rail-section { flex: 1 1 100%; }
}

@media (max-width: 760px) {
	.video-post .hero { grid-template-columns: 1fr; gap: 18px; padding: 14px 0 28px; }
	.hero-headline { font-size: 1.5rem; }
	.hero-deck { font-size: 16px; }
	.hero-actions { flex-direction: column; align-items: flex-start; gap: 10px; }

	.video-grid {
		grid-template-columns: none;
		display: flex;
		gap: 14px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		margin: 0 calc(var(--page-pad) * -1);
		padding: 0 var(--page-pad) 4px;
		scrollbar-width: none;
	}
	.video-grid::-webkit-scrollbar { display: none; }
	.video-card { flex: 0 0 78%; scroll-snap-align: start; }

	.cpt-row {
		grid-template-columns: none;
		display: flex;
		gap: 14px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		margin: 0 calc(var(--page-pad) * -1);
		padding: 0 var(--page-pad) 4px;
		scrollbar-width: none;
	}
	.cpt-row::-webkit-scrollbar { display: none; }
	.cpt-mod { flex: 0 0 78%; scroll-snap-align: start; min-height: 160px; }

	.video-post .editorial { margin: 32px 0 28px; }
}


