/* 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; }

/* AdSense auto-relaxed (multiplex) unit rendered after the "In This Story" row
   (template-parts/article/ad-in-story.php). Lives inside .body-col and spans
   the full left-column width like the row above it. The native unit sizes its
   own height, so there is no fixed .ad-frame placeholder chrome. The 36px top
   margin matches the row's own top gap, so spacing reads the same whether the
   "In This Story" row is present or empty. Restores the Jannah banner_below
   "after post" ad slot lost in the goldendome migration. */
.in-story-ad { margin-top: 36px; }
.in-story-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-story-ad .adsbygoogle { display: block; }

/* 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; }
}


