/* ==========================================================================
   YARDLINE — block internals + the 3D FX layer
   --------------------------------------------------------------------------
   The YARDLINE theme ships ZERO CSS by design (SPEC 1.1). This is the one
   sanctioned stylesheet in the build: it styles the internals of the plugin's
   33 dynamic blocks, which block attributes cannot reach, and it carries the
   whole "super modern 3D FX" layer the product is sold on. It is registered as
   every block's `style` handle, so it also reaches the editor-canvas iframe.

   RULES THIS FILE OBEYS — please keep them if you edit it
   ------------------------------------------------------
   1. EVERY colour is `var(--wp--preset--color--<slug>, <dark fallback>)`, read
      ONCE into the `--sfgi-*` tokens below and consumed only through those.
      A literal hex applied to a surface is a light-mode bug. Hexes appear in
      exactly three places in this file:
        a) the fallback slot of a `var(--wp--preset--color--*)` lookup,
        b) the `:root.sfgi-light` block at the very bottom, which DEFINES the
           light presets (definitions, not applications),
        c) `--sfgi-on-photo`, text that sits on photography and must stay light
           in both schemes (mirrors GX_ONPHOTO in the theme's tools/lib.php).
   2. A mid-bright brand colour is a BACKGROUND colour, not a text colour.
      Blaze `#ff5a1f` is 6.5:1 on the night ground but only 2.9:1 on the light
      one. Anything that paints a colour onto TEXT uses the `*-ink` token
      (`--sfgi-accent-ink`, `--sfgi-turf-ink`, `--sfgi-gold-ink`, …), which
      aliases the preset in dark and darkens toward `ink` in light. Text ON a
      bright fill uses `--sfgi-on-bright`.
   3. The DEPTH LADDER is the identity (SPEC 2). Every surface declares a
      storey — `--sfgi-d0` … `--sfgi-d4` — and each rung is a soft ambient
      shadow PLUS an `inset 0 1px 0` bright top edge, which is what makes a
      rectangle read as a lit slab instead of a box with a drop shadow.
      Hairlines are `--sfgi-ring` (an inset ring that costs no layout width),
      never a 1px border.
   4. Mobile-first. The base rules are safe at 390px; layout widens at
      `min-width: 600px`, `min-width: 769px` and `min-width: 1025px`, matching
      the stepfox-looks device keys (mobile <=768, tablet <=1024) exactly.
      Wide content scrolls inside `.sfgi-scroll`; the page never scrolls
      sideways.
   5. Every animation and every transform is switched off under
      `prefers-reduced-motion: reduce`, and every pointer effect is gated on
      `(pointer: fine)` as well.
   6. All motion is scoped under `body.sfgi-fx`, a class assets/fx.js adds on
      load — a no-JS visitor gets a clean, flat, complete page.

   THE CLASS CONTRACT — what the block PHP is expected to emit
   ----------------------------------------------------------
   Shared atoms, usable inside any block:
     .sfgi-panel .sfgi-card .sfgi-glass      surfaces on the depth ladder
     .sfgi-head .sfgi-title .sfgi-eyebrow .sfgi-more
     .sfgi-chip (.is-live .is-final .is-win .is-loss .is-gold .is-neon)
     .sfgi-btn (.sfgi-btn--ghost .sfgi-btn--gold) .sfgi-pill
     .sfgi-crest .sfgi-face .sfgi-i (icon svg) .sfgi-num .sfgi-record
     .sfgi-track > .sfgi-bar (width from inline --sfgi-pct)
     .sfgi-meta .sfgi-kv .sfgi-empty .sfgi-scroll .sfgi-col-optional
     .sfgi-filters .sfgi-filter-count .sfgi-noresults
     th.sfgi-sortable[data-sort] + .sfgi-sort-arrow
   FX hooks (assets/fx.js):
     .sfgi-tilt          pointer tilt + glare, JS writes --rx --ry --mx --my
     .sfgi-reveal        IntersectionObserver adds .is-in, --i staggers
     .sfgi-layer[data-depth]   parallax layer inside a tilting card
     .sfgi-holo          holographic foil (player / champion cards)
     .sfgi-field         the perspective yard-line plane (needs NO children)
     .sfgi-count[data-to]      odometer counter
     header.sfgi-hdr-tuck      sticky header whose ticker scrolls away;
                               JS writes --sfgi-hdr-tuck (the strip's height)
     [data-sfgi-countdown]     live countdown, unix seconds
     .sfgi-strip > .sfgi-strip__track   marquee
     .sfgi-scheme-toggle       light/dark switch
     .sfgi-bracket .sfgi-bk-team[data-team]   winner-path highlight
   Inline custom properties the PHP may set (the only inline styles allowed):
     --sfgi-team / --sfgi-team-2   team livery, from stepfox_gi_team_vars()
     --sfgi-pct                    fill width on a bar
     --i                           reveal stagger index
   ========================================================================== */

:root {
	/* ---- palette bridge: preset first, stadium-night literal as fallback -- */
	--sfgi-base:     var(--wp--preset--color--base, #05070c);
	--sfgi-panel:    var(--wp--preset--color--panel, #0c111c);
	--sfgi-panel-2:  var(--wp--preset--color--panel-2, #131a29);
	--sfgi-line:     var(--wp--preset--color--line, rgba(255, 255, 255, 0.09));
	--sfgi-ink:      var(--wp--preset--color--ink, #f3f6fb);
	--sfgi-muted:    var(--wp--preset--color--muted, #8b97ad);
	--sfgi-accent:   var(--wp--preset--color--accent, #ff5a1f);
	--sfgi-accent-2: var(--wp--preset--color--accent-2, #ffc93c);
	--sfgi-neon:     var(--wp--preset--color--neon, #00e5ff);
	--sfgi-violet:   var(--wp--preset--color--violet, #7b5cff);
	--sfgi-turf:     var(--wp--preset--color--turf, #00d67f);
	--sfgi-gold:     var(--wp--preset--color--gold, #ffd24a);
	--sfgi-glass:    var(--wp--preset--color--glass, rgba(5, 7, 12, 0.82));
	--sfgi-glass-2:  var(--wp--preset--color--glass-2, rgba(19, 26, 41, 0.66));
	--sfgi-edge:     var(--wp--preset--color--edge, rgba(255, 255, 255, 0.10));

	/* ---- colour-as-TEXT variants (rule 2) --------------------------------
	   In the night scheme the brand colours already clear 4.5:1 on `base`, so
	   these alias the presets. `:root.sfgi-light` re-mixes them toward the
	   dark ink. Never paint a brand colour on small text directly. */
	--sfgi-accent-ink: var(--wp--preset--color--accent, #ff5a1f);
	--sfgi-turf-ink:   var(--wp--preset--color--turf, #00d67f);
	--sfgi-gold-ink:   var(--wp--preset--color--gold, #ffd24a);
	--sfgi-neon-ink:   var(--wp--preset--color--neon, #00e5ff);
	--sfgi-violet-ink: var(--wp--preset--color--violet, #7b5cff);

	/* Text sitting ON a bright fill (blaze, turf, gold, neon). Every one of
	   those is a light colour, so the label goes dark in BOTH schemes — in
	   light mode this token is re-pointed at `ink`, which is itself dark. */
	--sfgi-on-bright: var(--wp--preset--color--base, #05070c);

	/* Text on photography. Deliberately a literal and NOT `ink`: over artwork
	   the caption stays light whatever the scheme does (rule 1c). */
	--sfgi-on-photo:     #ffffff;
	--sfgi-on-photo-dim: rgba(255, 255, 255, 0.74);

	/* ---- geometry (SPEC 2, mirrors GX_R / GX_R_SM / GX_R_LG) ---- */
	--sfgi-r:      14px;
	--sfgi-r-sm:   8px;
	--sfgi-r-lg:   22px;
	--sfgi-pill:   999px;
	--sfgi-gap:    16px;
	--sfgi-gap-sm: 10px;
	--sfgi-pad:    18px;

	/* ---- the depth ladder (mirror of GX_D0..GX_D4 in tools/lib.php) ---- */
	--sfgi-d0: inset 0 1px 0 rgba(255, 255, 255, 0.06);
	--sfgi-d1: 0 2px 10px rgba(0, 0, 0, 0.40), inset 0 1px 0 rgba(255, 255, 255, 0.07);
	--sfgi-d2: 0 12px 30px rgba(0, 0, 0, 0.50), inset 0 1px 0 rgba(255, 255, 255, 0.09);
	--sfgi-d3: 0 26px 60px rgba(0, 0, 0, 0.62), inset 0 1px 0 rgba(255, 255, 255, 0.11);
	--sfgi-d4: 0 44px 96px rgba(0, 0, 0, 0.70), inset 0 1px 0 rgba(255, 255, 255, 0.13);
	--sfgi-d2-hi: 0 26px 60px rgba(0, 0, 0, 0.62), 0 0 0 1px color-mix(in srgb, var(--sfgi-accent) 42%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.14);
	--sfgi-d3-hi: 0 44px 96px rgba(0, 0, 0, 0.72), 0 0 0 1px color-mix(in srgb, var(--sfgi-neon) 40%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.16);

	/* Hairlines that hug a radius and cost no layout width. Never a border. */
	--sfgi-ring:      inset 0 0 0 1px rgba(255, 255, 255, 0.10);
	--sfgi-ring-hot:  inset 0 0 0 1px color-mix(in srgb, var(--sfgi-accent) 55%, transparent);
	--sfgi-ring-neon: inset 0 0 0 1px color-mix(in srgb, var(--sfgi-neon) 45%, transparent);
	--sfgi-ring-gold: inset 0 0 0 1px color-mix(in srgb, var(--sfgi-gold) 50%, transparent);

	/* The top-left light wash every surface carries. Combined with the inset
	   top edge of the depth ladder it is what sells the "lit slab" read. */
	--sfgi-sheen: linear-gradient(165deg, rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0.012) 34%, rgba(255, 255, 255, 0) 62%);
	--sfgi-glass-blur: blur(18px) saturate(1.4);

	/* Photo scrim, bottom-weighted so the top of the picture stays clean. */
	--sfgi-scrim: linear-gradient(180deg, rgba(5, 7, 12, 0) 16%, rgba(5, 7, 12, 0.58) 56%, rgba(5, 7, 12, 0.96) 100%);

	/* ---- signature gradients, built from tokens so light mode follows ---- */
	--sfgi-g-brand: linear-gradient(135deg, var(--sfgi-accent) 0%, var(--sfgi-accent-2) 100%);
	--sfgi-g-holo:  linear-gradient(115deg, var(--sfgi-neon) 0%, var(--sfgi-violet) 52%, var(--sfgi-accent) 100%);
	--sfgi-g-turf:  linear-gradient(180deg, color-mix(in srgb, var(--sfgi-turf) 16%, transparent) 0%, transparent 100%);

	/* ---- motion ---- */
	--sfgi-ease:  cubic-bezier(.2, .7, .3, 1);
	--sfgi-t:     .26s;
	--sfgi-t-fast: .16s;
	--sfgi-persp: 1000px;

	/* ---- type (SPEC 2) ---- */
	--sfgi-f-display: var(--wp--preset--font-family--anton, Anton, "Arial Narrow", Impact, sans-serif);
	--sfgi-f-ui:      var(--wp--preset--font-family--barlow, "Barlow Condensed", "Arial Narrow", sans-serif);
	--sfgi-f-body:    var(--wp--preset--font-family--inter, Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
	--sfgi-f-num:     var(--wp--preset--font-family--rajdhani, Rajdhani, "DIN Alternate", ui-monospace, monospace);
}

/* ==========================================================================
   BASE GUARDS
   Nothing here paints. It stops the plugin's markup pushing the page sideways
   at 390px and normalises the browser defaults on the semantic elements the
   blocks emit.
   ========================================================================== */

[class^="sfgi-"],
[class*=" sfgi-"],
[class^="sfgi-"] *,
[class*=" sfgi-"] * {
	box-sizing: border-box;
}

[class^="sfgi-"],
[class*=" sfgi-"] {
	max-width: 100%;
	font-family: var(--sfgi-f-body);
	color: var(--sfgi-ink);
}

/* :where() keeps this a zero-specificity DEFAULT: the theme's stepfox-looks
 * attribute styles (mirrored to .block_* classes on loop clones, which are
 * only 0,1,0) must always be able to override it. Without :where() this
 * selector is (0,1,1) and silently beats every mirrored height/size on all
 * loop iterations after the first — the styled-first-card bug. */
:where([class^="sfgi-"] img,
[class*=" sfgi-"] img) {
	max-width: 100%;
	height: auto;
	display: block;
}

/* Zero the theme/browser margins on text inside plugin components.
   The selectors deliberately skip <body> and <html>: the effects layer stamps
   `sfgi-fx sfgi-fx-reveal` on <body> at runtime, and a bare attribute selector
   matched from there — every paragraph and heading in post content on BOTH
   Yardline editions lost its spacing (found 2026-09-14). :where() keeps the
   specificity at (0,1,1) so component rules such as .sfgi-bio__prose p still
   win on source order exactly as before. */
[class^="sfgi-"]:where(:not(body, html)) p,
[class*=" sfgi-"]:where(:not(body, html)) p,
[class^="sfgi-"]:where(:not(body, html)) h1,
[class*=" sfgi-"]:where(:not(body, html)) h1,
[class^="sfgi-"]:where(:not(body, html)) h2,
[class*=" sfgi-"]:where(:not(body, html)) h2,
[class^="sfgi-"]:where(:not(body, html)) h3,
[class*=" sfgi-"]:where(:not(body, html)) h3,
[class^="sfgi-"]:where(:not(body, html)) h4,
[class*=" sfgi-"]:where(:not(body, html)) h4 {
	margin: 0;
}

[class^="sfgi-"] ul,
[class*=" sfgi-"] ul,
[class^="sfgi-"] ol,
[class*=" sfgi-"] ol {
	margin: 0;
	padding: 0;
	list-style: none;
}

[class^="sfgi-"] table,
[class*=" sfgi-"] table {
	width: 100%;
	border-collapse: collapse;
	border-spacing: 0;
	font-variant-numeric: tabular-nums;
}

/* :where() zeroes this reset's specificity, and that is the whole point.
 * `[class^="sfgi-"] button` scores (0,1,1) — an attribute selector PLUS a type
 * selector — which outranks every single-class component rule in this file.
 * .sfgi-pill (0,1,0) was therefore losing padding, font, size, weight, colour
 * AND background to it: the sort pills rendered as bare 15px Inter text with
 * no fill, wrapped in a hairline ring. A normalise must always sit UNDER the
 * things it normalises, so the selector list goes inside :where() and the rule
 * drops to (0,0,1) — beaten by any class, still applied to a bare button. */
:where([class^="sfgi-"], [class*=" sfgi-"]) button {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
}

.sfgi-eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	font-family: var(--sfgi-f-ui);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--sfgi-accent-ink);
}
.sfgi-more .sfgi-i { transition: transform var(--sfgi-t-fast) var(--sfgi-ease); }
.sfgi-more:hover .sfgi-i { transform: translateX(3px); }

/* The mandatory empty state (SPEC 4.2). A block never renders nothing. */
.sfgi-empty {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 22px 18px;
	border-radius: var(--sfgi-r);
	background: color-mix(in srgb, var(--sfgi-panel) 70%, transparent);
	box-shadow: var(--sfgi-ring);
	color: var(--sfgi-muted);
	font-size: 13px;
	line-height: 1.5;
}
.sfgi-empty::before {
	content: "";
	width: 3px;
	align-self: stretch;
	border-radius: 2px;
	background: var(--sfgi-g-brand);
	opacity: 0.55;
	flex: 0 0 auto;
}

/* ==========================================================================
   ATOMS
   ========================================================================== */

/* ---- icons ---- */
.sfgi-i {
	width: 18px;
	height: 18px;
	flex: 0 0 auto;
	stroke-width: 1.7;
	vertical-align: middle;
}
.sfgi-i--xs { width: 12px; height: 12px; }

/* ---- team crest ---- */
.sfgi-crest {
	width: 40px;
	height: 40px;
	flex: 0 0 auto;
	border-radius: 50%;
	object-fit: contain;
	background:
		radial-gradient(circle at 50% 32%, color-mix(in srgb, var(--sfgi-team, var(--sfgi-accent)) 26%, transparent), transparent 68%),
		var(--sfgi-panel-2);
	box-shadow: var(--sfgi-ring), 0 4px 14px rgba(0, 0, 0, 0.35);
	padding: 3px;
}

/* The shared demo crest cards have opaque square backgrounds. Clip the artwork
 * itself in every theme and size, including generated thumbnail variants. */
img[src*="/gridiron-crest-"][src*="-v2"] {
	/* .sfgi-crest adds padding:3px and the <img> is content-box, so
	 * .sfgi-f-crest img{width:100%} made the image 30px wide inside a 24px
	 * overflow:hidden field: the round clip fell outside the visible window
	 * and the badge rendered as a cut square. Let the opaque crest card fill
	 * its own box first, then clip. */
	box-sizing: border-box;
	padding: 0;
	clip-path: circle(50%);
}

/* ---- player headshot ---- */
.sfgi-face {
	width: 44px;
	height: 44px;
	flex: 0 0 auto;
	border-radius: 50%;
	object-fit: cover;
	object-position: 50% 16%;
	background: var(--sfgi-panel-2);
	box-shadow: var(--sfgi-ring), 0 6px 18px rgba(0, 0, 0, 0.4);
}
.sfgi-face--mono {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--sfgi-f-num);
	font-weight: 700;
	color: var(--sfgi-muted);
}

/* ---- chips / badges ---- */
.sfgi-chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 10px;
	border-radius: var(--sfgi-pill);
	font-family: var(--sfgi-f-ui);
	font-size: 11px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	white-space: nowrap;
	color: var(--sfgi-muted);
	background: color-mix(in srgb, var(--sfgi-panel-2) 78%, transparent);
	box-shadow: var(--sfgi-ring);
	text-decoration: none;
}
.sfgi-chip.is-ink   { color: var(--sfgi-ink); }
.sfgi-chip.is-hot   { color: var(--sfgi-accent-ink); box-shadow: var(--sfgi-ring-hot); }
.sfgi-chip.is-neon  { color: var(--sfgi-neon-ink); box-shadow: var(--sfgi-ring-neon); }
.sfgi-chip.is-gold  { color: var(--sfgi-gold-ink); box-shadow: var(--sfgi-ring-gold); }
.sfgi-chip.is-win   { color: var(--sfgi-turf-ink); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sfgi-turf) 45%, transparent); }
.sfgi-chip.is-loss  { color: var(--sfgi-muted); }
.sfgi-chip.is-final { color: var(--sfgi-ink); }
.sfgi-chip.is-solid {
	color: var(--sfgi-on-bright);
	background: var(--sfgi-g-brand);
	box-shadow: 0 6px 18px color-mix(in srgb, var(--sfgi-accent) 32%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.25);
}
.sfgi-chip.is-team {
	color: var(--sfgi-ink);
	background: color-mix(in srgb, var(--sfgi-team, var(--sfgi-accent)) 22%, transparent);
	box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--sfgi-team, var(--sfgi-accent)) 45%, transparent);
}

/* LIVE — blaze fill, dark label, and the pulse ring the FX layer animates. */
.sfgi-chip.is-live,
.sfgi-live {
	position: relative;
	color: var(--sfgi-on-bright);
	background: var(--sfgi-accent);
	box-shadow: 0 4px 16px color-mix(in srgb, var(--sfgi-accent) 45%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}
.sfgi-live__dot,
.sfgi-chip.is-live .sfgi-dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--sfgi-on-bright);
	flex: 0 0 auto;
}

/* ---- pills (filter controls) ---- */
/* `flex: 0 0 auto` because .sfgi-filters__pills carries `min-width: 0` so the
 * bar can hand its width to the search field: left shrinkable, a pill can be
 * squeezed narrower than its own `white-space: nowrap` label and the text
 * spills out of its background. Fixed at content width they wrap instead,
 * which is what the wrapping row is for. Defensive at narrow widths — it is
 * NOT what made these pills look unstyled; see the button reset above. */
.sfgi-pill {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	gap: 6px;
	padding: 7px 13px;
	border-radius: var(--sfgi-pill);
	font-family: var(--sfgi-f-ui);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	white-space: nowrap;
	color: var(--sfgi-muted);
	background: color-mix(in srgb, var(--sfgi-panel-2) 70%, transparent);
	box-shadow: var(--sfgi-ring);
	cursor: pointer;
	transition: color var(--sfgi-t-fast) var(--sfgi-ease), background-color var(--sfgi-t-fast) var(--sfgi-ease), box-shadow var(--sfgi-t-fast) var(--sfgi-ease);
}
.sfgi-pill:hover { color: var(--sfgi-ink); background: var(--sfgi-panel-2); }
.sfgi-pill.is-active {
	color: var(--sfgi-on-bright);
	background: var(--sfgi-g-brand);
	box-shadow: 0 6px 20px color-mix(in srgb, var(--sfgi-accent) 34%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.28);
}

/* ---- buttons ---- */
.sfgi-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
	padding: 12px 20px;
	border-radius: var(--sfgi-pill);
	font-family: var(--sfgi-f-ui);
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	color: var(--sfgi-on-bright);
	background: var(--sfgi-g-brand);
	box-shadow: 0 10px 26px color-mix(in srgb, var(--sfgi-accent) 34%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.28);
	transition: box-shadow var(--sfgi-t) var(--sfgi-ease), filter var(--sfgi-t-fast) var(--sfgi-ease);
}
.sfgi-btn:hover {
	filter: brightness(1.06);
	box-shadow: 0 16px 38px color-mix(in srgb, var(--sfgi-accent) 44%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.34);
}
.sfgi-btn[disabled],
.sfgi-btn.is-disabled { opacity: 0.5; cursor: default; box-shadow: var(--sfgi-ring); }

/* ---- horizontal scroller: wide content scrolls here, never the page ---- */
.sfgi-scroll {
	overflow-x: auto;
	overflow-y: hidden;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
	scrollbar-color: color-mix(in srgb, var(--sfgi-ink) 22%, transparent) transparent;
	overscroll-behavior-x: contain;
	scroll-behavior: smooth;
}
.sfgi-scroll::-webkit-scrollbar { height: 8px; }
.sfgi-scroll::-webkit-scrollbar-track { background: transparent; }
.sfgi-scroll::-webkit-scrollbar-thumb {
	border-radius: var(--sfgi-pill);
	background: color-mix(in srgb, var(--sfgi-ink) 18%, transparent);
}
.sfgi-scroll::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--sfgi-ink) 30%, transparent); }
.sfgi-scroll > table { min-width: 620px; }

/* ==========================================================================
   FILTER BAR  (team-grid / player-grid / standings-full)
   ========================================================================== */

.sfgi-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sfgi-gap-sm);
	padding: 12px;
	margin-bottom: var(--sfgi-gap);
	border-radius: var(--sfgi-r);
	background-color: color-mix(in srgb, var(--sfgi-panel) 82%, transparent);
	background-image: var(--sfgi-sheen);
	box-shadow: var(--sfgi-d1), var(--sfgi-ring);
	position: relative;
	z-index: 3;
}
.sfgi-filters__search {
	flex: 1 1 190px;
	min-width: 0;
	padding: 10px 14px;
	border: 0;
	border-radius: var(--sfgi-pill);
	font-family: var(--sfgi-f-body);
	font-size: 13px;
	color: var(--sfgi-ink);
	background: color-mix(in srgb, var(--sfgi-base) 60%, transparent);
	box-shadow: var(--sfgi-ring);
	appearance: none;
	-webkit-appearance: none;
}
.sfgi-filters__search::placeholder { color: var(--sfgi-muted); opacity: 1; }
.sfgi-filters__select {
	padding: 10px 32px 10px 14px;
	border: 0;
	border-radius: var(--sfgi-pill);
	font-family: var(--sfgi-f-ui);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--sfgi-ink);
	background-color: color-mix(in srgb, var(--sfgi-base) 60%, transparent);
	background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
	background-position: right 16px center, right 11px center;
	background-size: 5px 5px, 5px 5px;
	background-repeat: no-repeat;
	box-shadow: var(--sfgi-ring);
	appearance: none;
	-webkit-appearance: none;
	cursor: pointer;
	max-width: 100%;
}
.sfgi-filters__select option { background: var(--sfgi-panel); color: var(--sfgi-ink); }
.sfgi-filters__pills {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	min-width: 0;
}
.sfgi-filter-count {
	margin-left: auto;
	font-family: var(--sfgi-f-num);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--sfgi-muted);
	white-space: nowrap;
}
.sfgi-noresults {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	padding: 48px 20px;
	border-radius: var(--sfgi-r);
	text-align: center;
	color: var(--sfgi-muted);
	background: color-mix(in srgb, var(--sfgi-panel) 60%, transparent);
	box-shadow: var(--sfgi-ring);
}
.sfgi-noresults b {
	font-family: var(--sfgi-f-display);
	font-size: 18px;
	text-transform: uppercase;
	color: var(--sfgi-ink);
}
[hidden] { display: none !important; }

/* ==========================================================================
   FOCUS — every interactive element gets a visible neon ring
   ========================================================================== */

.sfgi-btn:focus-visible,
.sfgi-pill:focus-visible,
.sfgi-chip:focus-visible,
.sfgi-more:focus-visible,
.sfgi-tcell:focus-visible,
.sfgi-card:focus-visible,
.sfgi-scroll:focus-visible,
.sfgi-filters__search:focus-visible,
.sfgi-filters__select:focus-visible,
.sfgi-scheme-toggle:focus-visible,
.sfgi-pick-opt:focus-visible,
.sfgi-bk-team:focus-visible,
.sfgi-tick:focus-visible,
.sfgi-strip__item:focus-visible,
th.sfgi-sortable:focus-visible,
[class^="sfgi-"] a:focus-visible,
[class*=" sfgi-"] a:focus-visible,
[class^="sfgi-"] button:focus-visible,
[class*=" sfgi-"] button:focus-visible,
[class^="sfgi-"] input:focus-visible,
[class*=" sfgi-"] input:focus-visible,
[class^="sfgi-"] select:focus-visible,
[class*=" sfgi-"] select:focus-visible {
	outline: 2px solid var(--sfgi-neon);
	outline-offset: 2px;
	border-radius: var(--sfgi-r-sm);
}
.sfgi-filters__search:focus-visible,
.sfgi-filters__select:focus-visible { border-radius: var(--sfgi-pill); }

.sfgi-gcard__top .sfgi-chip { margin-left: auto; }
.sfgi-box .sfgi-scroll > table { min-width: 460px; }

/* ---- 6. countdown ------------------------------------------------------- */
.sfgi-countdown {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: var(--sfgi-pad);
	border-radius: var(--sfgi-r);
	background-color: var(--sfgi-panel);
	background-image: var(--sfgi-sheen);
	box-shadow: var(--sfgi-d2), var(--sfgi-ring);
	position: relative;
	overflow: hidden;
}
.sfgi-countdown::before {
	content: "";
	position: absolute;
	inset: auto 0 0 0;
	height: 2px;
	background: var(--sfgi-g-brand);
	opacity: 0.85;
}
.sfgi-countdown.is-done .sfgi-cd-units { opacity: 0.5; }
.sfgi-roster .sfgi-scroll > table { min-width: 640px; }

/* ---- 10. team-grid / 18. player-grid — the filterable grids -------------
   Contract (SPEC 6, assets/filters.js):
     .sfgi-grid              block root
       .sfgi-filters         controls, [data-filter] / [data-value]
       [data-grid]           card wrapper, optional [data-visible-max]
         .sfgi-card          one item, data-* facets
       .sfgi-noresults       empty state
   ------------------------------------------------------------------------ */
.sfgi-grid { position: relative; }
.sfgi-grid [data-grid] {
	display: grid;
	gap: var(--sfgi-gap);
	grid-template-columns: repeat(2, minmax(0, 1fr));
}
.sfgi-grid[data-cols="1"] [data-grid] { grid-template-columns: minmax(0, 1fr); }

/* Hundreds of cards can exist on /players/ — keep the ones off-screen out of
   layout and paint. The intrinsic size stops the scrollbar jumping. */
.sfgi-grid [data-grid] > .sfgi-card {
	content-visibility: auto;
	contain-intrinsic-size: auto 260px;
}

/* ---- 13. team-strip — the marquee -------------------------------------- */
.sfgi-strip {
	position: relative;
	overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 1) 8%, rgba(0, 0, 0, 1) 92%, rgba(0, 0, 0, 0) 100%);
	mask-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 1) 8%, rgba(0, 0, 0, 1) 92%, rgba(0, 0, 0, 0) 100%);
}
.sfgi-strip__item img,
.sfgi-strip__item .sfgi-crest { filter: grayscale(1); opacity: 0.7; transition: filter var(--sfgi-t-fast) var(--sfgi-ease), opacity var(--sfgi-t-fast) var(--sfgi-ease); }
.sfgi-strip__item:hover img,
.sfgi-strip__item:hover .sfgi-crest { filter: none; opacity: 1; }
.sfgi-sfull .sfgi-scroll > table { min-width: 760px; }
.sfgi-bracket.is-compact .sfgi-bk-team .sfgi-crest { display: none; }

/* ==================================================== shared base (audit fix)
   These generic classes are emitted by the component renderers but had no
   rule anywhere — the block theme composed its pages from field blocks, so
   the gap never surfaced there. Sized against the block demo's equivalents. */

.sfgi-title {
	font-family: var(--sfgi-f-display);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.01em;
	line-height: 1.02;
	color: var(--sfgi-ink);
	margin: 0;
}

.sfgi-sub {
	font-family: var(--sfgi-f-body);
	font-size: 15px;
	line-height: 1.6;
	color: var(--sfgi-muted);
	margin: 0;
}

.sfgi-meta {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 12px;
	font-family: var(--sfgi-f-ui);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.04em;
	color: var(--sfgi-muted);
	margin: 0;
}

.sfgi-kv {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 14px;
	padding: 8px 0;
	border-bottom: 1px solid var(--sfgi-line);
	font-family: var(--sfgi-f-ui);
	font-size: 13.5px;
	letter-spacing: 0.04em;
}

.sfgi-kv:last-child {
	border-bottom: 0;
}

.sfgi-kv > :first-child {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--sfgi-muted);
}

.sfgi-kv > :last-child {
	font-weight: 600;
	color: var(--sfgi-ink);
	text-align: right;
}

/* A hero-grade rounded surface. Components that go full-bleed (the front
   field hero) reset the radius themselves or via the page CSS. */
.sfgi-stage {
	position: relative;
	overflow: hidden;
	border-radius: var(--sfgi-r-lg);
	background: var(--sfgi-panel);
	box-shadow: var(--sfgi-d2), var(--sfgi-ring);
}

/* Crest + headshot size ladder. */
.sfgi-crest--xs {
	width: 18px;
	height: 18px;
}

.sfgi-crest--sm {
	width: 28px;
	height: 28px;
}

.sfgi-crest--lg {
	width: 64px;
	height: 64px;
}

.sfgi-crest--xl {
	width: 92px;
	height: 92px;
}

.sfgi-crest--xxl {
	width: 128px;
	height: 128px;
}

.sfgi-face--xs {
	width: 28px;
	height: 28px;
}

.sfgi-face--sm {
	width: 36px;
	height: 36px;
}

.sfgi-face--lg {
	width: 72px;
	height: 72px;
}

/* Inline icon modifiers. */
.sfgi-i--sm {
	width: 14px;
	height: 14px;
}

.sfgi-i--muted {
	color: var(--sfgi-muted);
}

.sfgi-icon--hot {
	color: var(--sfgi-accent);
}

.sfgi-eyebrow--gold {
	color: var(--sfgi-gold-ink);
}

.sfgi-btn--ghost {
	background: transparent;
	color: var(--sfgi-ink);
	box-shadow: var(--sfgi-ring);
}

.sfgi-btn--ghost:hover {
	background: var(--sfgi-panel-2);
	box-shadow: var(--sfgi-ring-hot);
}

/* Small furniture. */
.sfgi-sep {
	display: inline-block;
	width: 3px;
	height: 3px;
	border-radius: 999px;
	background: var(--sfgi-muted);
	opacity: 0.55;
	flex: 0 0 auto;
}

.sfgi-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.sfgi-empty-cell,
.sfgi-bye-mark {
	color: var(--sfgi-muted);
	opacity: 0.6;
}

.sfgi-chip-label {
	font-size: 10px;
	letter-spacing: 0.16em;
	opacity: 0.8;
}

.sfgi-stat {
	font-family: var(--sfgi-f-num);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	color: var(--sfgi-ink);
}

.sfgi-stat--hot {
	color: var(--sfgi-accent-ink);
}

.sfgi-tile-label {
	font-family: var(--sfgi-f-ui);
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sfgi-muted);
}

.sfgi-tile-sub {
	font-size: 12px;
	line-height: 1.45;
	color: var(--sfgi-muted);
}

/* ==========================================================================
   THE LIGHT SCHEME — the ":root.sfgi-light block at the very bottom" that the
   header of this file has promised since line 17, and which did not exist:
   the toggle added the class, flipped its own icon (games.css), and nothing
   else on the page changed, on the block theme and the Elementor build alike.

   Only TOKENS are (re)defined here — definitions, not applications (rule 1b).
   No element is styled, so every block keeps rendering from its own
   attributes and simply resolves them against a light palette.

   Values mirror the theme's styles/light.json ("Daylight"), so the visitor
   toggle and the Site Editor variation are the same palette by construction.

   THREE CONSUMERS, ONE BLOCK — why each group below exists:
     1. WP presets. The block theme's emitted #block_ rules reference
        var(--wp--preset--color--…) ~540 times, and the Elementor theme's
        theme.css mirrors the same presets in :root (its --gx-* shorthands
        alias them), so this one group flips both themes' markup.
     2. Baked-dark sfgi tokens. The ink variants alias BRAND presets (which
        stay put), and the depth/ring/glow values have night literals baked
        in — none of them follow group 1, so each is re-pointed by hand.
     3. Elementor kit globals. Site 71's kit defines --e-global-color-gx* on
        .elementor-kit-<id> with dark literals; widgets consume those. The
        selector must out-rank the kit rule, hence the descendant form; the
        attribute match keeps it kit-id-agnostic.

   NOT remapped, deliberately:
     · --sfgi-scrim and the photo veils: --sfgi-on-photo is #ffffff in BOTH
       schemes (rule 1c), so the scrim under it must stay dark or captions
       wash out. Apex flips its scrim; Apex puts dark text on photos. We
       do not.
     · brand colours as SURFACES (accent, neon, turf, gold, violet): same
       fills in both schemes, same as light.json. Only their *-ink text
       variants darken.
     · --sfgi-sheen: a white top-light wash is invisible on white — harmless,
       and still correct on the brand-coloured cards.
   ========================================================================== */

:root.sfgi-light {
	/* ---- 1. the presets both themes read ---------------------------------- */
	--wp--preset--color--base:    #f4f6fa;
	--wp--preset--color--panel:   #ffffff;
	--wp--preset--color--panel-2: #eef1f7;
	--wp--preset--color--line:    rgba(6, 12, 24, 0.10);
	--wp--preset--color--edge:    rgba(6, 12, 24, 0.10);
	--wp--preset--color--ink:     #0b1220;
	--wp--preset--color--muted:   #5a6779;
	--wp--preset--color--glass:   rgba(255, 255, 255, 0.82);
	--wp--preset--color--glass-2: rgba(238, 241, 247, 0.72);

	/* The one gradient with a night surface baked in (theme.json). The brand,
	   holo and turf-fade gradients read on either ground and stay. */
	--wp--preset--gradient--night: linear-gradient(180deg, #ffffff 0%, #f4f6fa 100%);

	/* ---- 2. tokens whose dark value does not follow the presets ----------- */
	/* Brand-as-TEXT (rule 2): the fills stay, the text darkens to clear 4.5:1
	   on the day ground. */
	--sfgi-accent-ink: #b8400e;
	--sfgi-turf-ink:   #067a4d;
	--sfgi-gold-ink:   #8a6f1c;
	--sfgi-neon-ink:   #067a8a;
	--sfgi-violet-ink: #4c38b8;

	/* Text on a bright brand fill: dark in both schemes; here it is the day
	   ink rather than the night base. */
	--sfgi-on-bright: #0b1220;

	/* The depth ladder re-lit for a bright room: the same geometry, a fraction
	   of the weight — a night-strength shadow reads as a hole in daylight. The
	   white inset top edge stays; on white it costs nothing, on the brand
	   cards it still sells the lit slab. */
	--sfgi-d1: 0 2px 10px rgba(9, 14, 24, 0.10), inset 0 1px 0 rgba(255, 255, 255, 0.85);
	--sfgi-d2: 0 12px 30px rgba(9, 14, 24, 0.13), inset 0 1px 0 rgba(255, 255, 255, 0.90);
	--sfgi-d3: 0 26px 60px rgba(9, 14, 24, 0.16), inset 0 1px 0 rgba(255, 255, 255, 0.92);
	--sfgi-d4: 0 44px 96px rgba(9, 14, 24, 0.20), inset 0 1px 0 rgba(255, 255, 255, 0.94);
	--sfgi-d2-hi: 0 26px 60px rgba(9, 14, 24, 0.16), 0 0 0 1px color-mix(in srgb, var(--sfgi-accent) 42%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.92);
	--sfgi-d3-hi: 0 44px 96px rgba(9, 14, 24, 0.20), 0 0 0 1px color-mix(in srgb, var(--sfgi-neon) 40%, transparent), inset 0 1px 0 rgba(255, 255, 255, 0.94);

	/* Hairlines flip from white-on-night to ink-on-day. */
	--sfgi-ring: inset 0 0 0 1px rgba(6, 12, 24, 0.12);

	color-scheme: light;
}

/* ---- 3. the Elementor kit's own globals (site 71) -------------------------
   Declared by Elementor on .elementor-kit-<id> with the night literals baked
   in; every widget consumes them as var(--e-global-color-gx…). Matched by
   attribute so a re-imported kit with a new id keeps working. */
:root.sfgi-light [class*="elementor-kit-"] {
	--e-global-color-primary:   #0b1220;
	--e-global-color-secondary: #5a6779;
	--e-global-color-text:      #2a3546;
	--e-global-color-gxbase:    #f4f6fa;
	--e-global-color-gxpanel:   #ffffff;
	--e-global-color-gxpanel2:  #eef1f7;
}

/* The kit's BODY paint is a literal, not a var — Elementor writes
   `body_background_color: #05070C` / `body_color: #C7D0DF` straight into
   .elementor-kit-<id>, so no token remap can reach it and the page ground
   stayed night while every widget went day. Re-painted from the presets at
   higher specificity; the element selector keeps it off the block theme,
   the attribute match keeps it kit-id-agnostic. The other kit literals — the
   nav dropdown's dark panel, dark text baked onto amber buttons — read
   correctly on either ground and are left alone. */
:root.sfgi-light body[class*="elementor-kit-"] {
	background-color: var(--wp--preset--color--base, #f4f6fa);
	color: var(--wp--preset--color--ink, #0b1220);
}

/* ------------------------------------------------------------------ paging --
   The server-paged player archive. paginate_links() emits a <ul
   class="page-numbers"> of <a class="page-numbers"> and one <span
   class="current">; with no rule of our own that lands as a bare vertical
   stack of underlined blue links. Restated in .sfgi-pill's language so a page
   number reads as one more control on the same toolbar. The (0,2,0) anchor
   selector is deliberate: the Elementor kit writes
   `.elementor-kit-<id> a { color }` at (0,1,1) and loads after this sheet. */
.sfgi-pagination { margin-top: 22px; }
.sfgi-pagination .page-numbers { display:flex; flex-wrap:wrap; gap:6px; justify-content:center; margin:0; padding:0; list-style:none; }
.sfgi-pagination li { display:flex; }
.sfgi-pagination a.page-numbers,
.sfgi-pagination span.page-numbers { display:inline-flex; align-items:center; justify-content:center; min-width:40px; min-height:40px; padding:7px 13px; border-radius:var(--sfgi-pill); font-family:var(--sfgi-f-ui); font-size:12px; font-weight:600; letter-spacing:.1em; text-decoration:none; text-transform:uppercase; color:var(--sfgi-muted); background:color-mix(in srgb,var(--sfgi-panel-2) 70%,transparent); box-shadow:var(--sfgi-ring); transition:color var(--sfgi-t-fast) var(--sfgi-ease),background-color var(--sfgi-t-fast) var(--sfgi-ease); }
.sfgi-pagination a.page-numbers:hover { color:var(--sfgi-ink); background:var(--sfgi-panel-2); }
.sfgi-pagination .page-numbers.current { color:var(--sfgi-on-bright); background:var(--sfgi-g-brand); box-shadow:0 6px 20px color-mix(in srgb,var(--sfgi-accent) 34%,transparent),inset 0 1px 0 rgba(255,255,255,.28); }
.sfgi-pagination .page-numbers.dots { min-width:24px; background:transparent; box-shadow:none; }

/*
 * Centre the overlay-menu toggle's icon.
 *
 * Core renders `.wp-block-navigation__responsive-container-open` as
 * `display:flex` with `align-items:normal`, and the 24px icon inside it is a
 * replaced element that cannot stretch — so it lands flush at the TOP of the
 * 44px tap target. Measured at 440px: 0px above the icon, 20px below it, which
 * put the hamburger 10px higher than the theme toggle sitting next to it.
 *
 * The toggle is a core block internal, so no Stepfox Looks attribute can reach
 * it (attributes style the block's own element, `#block_hd-nav`). That is why
 * this lives here rather than in a block attribute.
 */
.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
	align-items: center;
	justify-content: center;
}

/* ---------------------------------------------------------------------------
   Header tuck — the score ticker scrolls away, the nav bar stays pinned.

   Both editions stack a ticker strip on top of the nav bar inside one sticky
   <header>. A negative `top` equal to the ticker's height lets the header
   travel up with the page until only the bar is left, then pin: the browser
   does the scrolling, so there is no threshold to flicker at and no motion
   for rule 5 (prefers-reduced-motion) to switch off.

   `--sfgi-hdr-tuck` and the class are both written by assets/fx.js, which
   measures the strip because its height is content-driven on both editions.
   No JS means no class, so a no-JS visitor keeps today's fully pinned header
   (rule 6), and the var fallback keeps `top: 0` even if the class is present
   without a measurement.

   !important is load-bearing, not lazy: the block edition sets the header's
   `top` from a stepfox attribute on the template-part call, which renders as
   `#block_part-hd-<route>{top:0px}` — an ID at (1,0,0), and the id differs on
   every one of the 24 routes, so it cannot be out-specified by name.
   --------------------------------------------------------------------------- */
body.sfgi-fx header.sfgi-hdr-tuck {
	top: calc(0px - var(--sfgi-hdr-tuck, 0px)) !important;
}
