/**
 * Pattern: Sponsors Hero  (patterns/sponsors-hero.php)
 *
 * Sponsors page hero, lavender band. Figma desktop `2085:11` (inside
 * composition `2085:2`), mobile `2082:2`. Decision log D26; build-tracker
 * SP1. Two-column split (copy left, cycling tier card right) above 900px;
 * stacked (copy, then buttons, then the card full-width, then a 2×2 stat
 * grid) below it — no tablet frame exists, 900 is this pattern's own
 * derived stacking point (flag for designer review per project convention).
 *
 * ── Mobile-first (gate round 1, item 1) ───────────────────────────────────
 * Every rule below is written base-first (the ≤899.98px state, no media
 * query) with breakpoints ascending after it (`@media (min-width:900px)`,
 * then `@media (min-width:81.25rem)`). This replaced a "desktop-first, mobile
 * override" structure after a real bug: `.sponsors-hero__heading`'s
 * unconditional base rule (64px) was declared LATER in the file than the
 * `@media (min-width:900px)` fluid rule that was supposed to size it
 * 44px→64px across that band — same specificity, later wins, so the fluid
 * rule was dead code and the heading rendered at a flat 64px at every
 * width ≥900px (verified live: 64px at both 1024 and 1240, should have
 * been ~52px / ~64px). Base-first removes the possibility of that
 * particular trap: nothing unconditional can out-order a `min-width` rule
 * when the unconditional declaration only ever runs FIRST.
 *
 * ── Two-slot layout — copy column + card column ───────────────────────────
 * Mirrors hero-campaign.css's own "generic derived band, then an
 * exact-pixel lock once the full composition fits" technique rather than
 * inventing a new one: a generic `1fr auto` grid from 900px up (H1/subtitle
 * fluid, card width a `clamp()` — all three shrink together, see the
 * 900px block), tightened to the literal Figma column widths only once the
 * container is wide enough to hold them at their exact size.
 *
 * ⚠️ That lock is `@media (min-width:81.25rem)` (1300px), NOT 76rem/1216px
 * (gate round 1, item 2 finding): `--kd-content-max` (1216px) is a CAP on
 * the content box, not its value at every viewport ≥1216px — `--kd-edge-pad`
 * is `max(gutter, (100%-1216px)/2)`, and the gutter term (7.64vw) is still
 * the larger of the two all the way up to ~1435.7px (solve
 * 0.0764vw = (vw-1216)/2). Below that crossover the content box is only
 * `vw − 2×0.0764vw = 0.8472vw`, e.g. 1030px at a 1216px viewport — not
 * 1216px. `37rem + 30rem` (1072px, no gap) doesn't fit inside that until
 * the content box itself reaches 1072px, which solves to ≈1265.5px;
 * 81.25rem (1300px) is that boundary plus a small safety margin. Below the
 * lock, the fluid clamp/calc formulas already reach their ceiling (64px /
 * 34px / 480px) within a few px of 81.25rem, so there is no visible jump at
 * the handoff, just a switch from "computed" to "asserted".
 *
 * One pattern = one CSS partial (auto-enqueued by inc/enqueue.php's glob).
 * The cycling behaviour is assets/js/sponsors-hero.js, enqueued centrally
 * in inc/enqueue.php (gate round 1, item 3 — a pre-approved shared-file
 * edit; see that file's own comment for why it moved there and how it
 * detects this pattern is present without a stable block name to key off).
 */

.sponsors-hero {
	background-color: var(
		--kd-color-surface
	); /* lavender band, D26/D28 page rhythm */
	/* ⚠️ Gate round 1, item 7b — hit the ACHIEVABLE floor (58px), not the
	   comp's 40px/32px, and flagged rather than forced: `templates/page.html`
	   (`.kd-main--no-hero`, shared by every interior page including
	   Sponsors) already carries a header→first-section gap of its own —
	   global.css overrides `--kd-no-hero-top` to 58px specifically for this
	   template, and that file's own comment on the rule says so explicitly:
	   "`templates/page.html` is shared by every interior page
	   (Sponsors/Gallery/FAQs too)... 58px becomes the system value for this
	   template — intended, not a [PG2-only] leak." That 58px is a fixed px
	   value, not responsive, and it is MORE than either of Figma's targets
	   (40px @1440, 32px @375) — so this pattern's own top padding cannot
	   close the gap to 40/32px without going negative (impossible) or
	   editing global.css's `kd-main--no-hero` rule, which is a shared file
	   NOT pre-approved this round (only inc/enqueue.php and tokens.css
	   were). Setting this pattern's own contribution to 0 gets as close as
	   this item CAN get within scope: a 58px header→kicker gap at every
	   width (verify), not 40/32px. Flagged for the next round or for
	   Alain's call: keep 58px consistent with Gallery/FAQs (same template),
	   or special-case Sponsors' own top padding in global.css. The bottom
	   side keeps the shared --dfd-section-pad token (spacing before
	   whatever section follows, same as every sibling pattern). */
	padding-block: 0 var(--dfd-section-pad);
}

.sponsors-hero__inner {
	display: flex;
	flex-direction: column;
	gap: 1.25rem; /* 20px — matches the copy column's own internal rhythm, see below */
}

/* Neutralise WP's default block-gap margin on this pattern's own nested
   groups (gate round 1, item 12 — same footgun hero-campaign.css's own
   file header documents for its sibling __inner/__copy rule): every gap
   here is this file's own explicit `gap`, not WP's blockGap. */
.sponsors-hero__inner > *,
.sponsors-hero__copy > * {
	margin-top: 0;
}

/* ── Copy column ──────────────────────────────────────────────────────────── */
.sponsors-hero__copy {
	display: flex;
	flex-direction: column;
	gap: 1.25rem; /* 20px — Figma's intro-copy flex gap (2085:13) */
	max-width: 37rem; /* 592px — caps the column at its Figma width once the grid gives it more room than that */
	/* Deliberately NO `min-width:0` here: this is a grid item once
	   `.sponsors-hero__inner` becomes a grid (≥900px), and the grid's
	   default `min-width:auto` is what protects it from shrinking narrower
	   than its content's min-content width — the widest UNBREAKABLE word
	   ("Duck'chella"). Overriding that to 0 (the usual flex/grid
	   "let it shrink/truncate" idiom) is exactly what let the card column
	   hold its full width no matter how little room was left, pushing the
	   h1's second line to render on top of the card instead of wrapping or
	   shrinking the split — a second, independent safety net alongside the
	   H1/card fluid sizing below (which is the PRIMARY fix — see the
	   900px block). */
}

.sponsors-hero__kicker {
	font-family: var(--kd-font-body);
	font-weight: 700;
	font-size: 0.75rem; /* 12px */
	letter-spacing: 0.1em; /* 1.2/12 */
	text-transform: uppercase;
	/* Gate round 2, item 1: was --kd-color-secondary (#746db0) at 3.94:1 on
	   the lavender page background — round 1 left this alone as a
	   "known token-level failure," round 2 withdrew that call.
	   --dfd-color-purple-ink (tokens.css) is darker (#5f58a3, the same
	   value the tier-card gradient fix already introduced) — 5.26:1 here,
	   still reads as purple, not navy. */
	color: var(--dfd-color-purple-ink);
	margin: 0;
}

/* H1 — 64px at the desktop lock is bigger than the sitewide
   --dfd-size-h2-section clamp (32→50px used by every other page's h1/h2),
   because THIS comp draws it at 64px (2085:15) — a deliberate scoped
   override, not a re-declare of the shared spec. White contour + navy fill
   via -webkit-text-stroke/paint-order — the same technique
   hero-campaign.css documents at length (Figma's Dev Mode API doesn't
   expose a stroke-WIDTH value for text strokes; 4px here mirrors the 4px
   given for the tier card's own (very similarly sized, 76px) name).
   Base (mobile) values below are the Figma mobile-frame exact numbers
   (`2082:4`); the 900px block makes both font-size and stroke-width fluid
   up to the desktop numbers instead of jumping — see this file's own
   header for why that fluidity exists at all. */
.sponsors-hero__heading {
	font-family: var(--kd-font-heading);
	font-weight: 700;
	font-size: 2.75rem; /* 44px */
	line-height: 3.125rem; /* 50px */
	letter-spacing: 0.02em; /* 0.88/44 */
	color: var(--kd-color-contrast);
	-webkit-text-stroke: 0.1875rem var(--kd-color-base); /* 3px white contour */
	paint-order: stroke fill;
	margin: 0;
	overflow-wrap: anywhere; /* defensive only — the grid's min-content protection (see .sponsors-hero__copy) plus the fluid sizing below are what actually keep this word unbroken/non-overlapping; this is the fallback if a future context ever leaves less room than both of those assume */
}

/* Subtitle — "Be a Very Important Duck." Pink fill, navy contour (client
   edit, Janel/Userback 8521747, 2026-10-12; was purple fill + white
   contour per D26). Pink on the lavender hero is only 1.43:1, so the navy
   contour is what carries legibility — don't drop it. Not its own heading level (the hero already
   has `.sponsors-hero__heading` above it — an h2 since the SP8 gate, see
   patterns/sponsors-hero.php's own comment — and this is supporting copy,
   not a THIRD heading level) — DynaPuff still needs its `wdth` axis set by
   hand since the sitewide h1–h6 rule that supplies it (global.css) only
   targets heading ELEMENTS. */
.sponsors-hero__subtitle {
	font-family: var(--kd-font-heading);
	font-weight: 700;
	font-variation-settings: "wdth" 100;
	font-size: 1.5rem; /* 24px */
	line-height: var(--kd-lh-tight);
	letter-spacing: 0.02em; /* 0.48/24 */
	color: var(--kd-color-pink);
	-webkit-text-stroke: 0.125rem var(--kd-color-contrast); /* 2px navy contour */
	paint-order: stroke fill;
	margin: 0;
}

.sponsors-hero__lead {
	font-family: var(--kd-font-body);
	font-size: 1rem; /* 16px */
	line-height: 1.5rem; /* 24px */
	color: var(--kd-color-body);
	max-width: 35rem; /* 560px — Figma's own narrower lead-paragraph width, desktop only but harmless as a ceiling on mobile too */
	margin: 0;
}

/* ── Buttons — primary yellow pill needs ZERO colour/shape overrides at any
   width: theme.json's default wp:button already renders --kd-btn-bg/fg,
   --kd-radius-pill. The SECOND button is a true transparent/navy-border
   outline (Figma 2085:21) — NOT the sitewide `.is-style-outline`, which
   tokens.css maps to a SOLID navy pill (the Home "Create a Team" pill,
   10:334/335). That solid-navy style is a different, already-named
   component; re-pointing it here would change it sitewide from a shared
   file this item may not touch. This is therefore a new, pattern-scoped
   button treatment — not a re-declare of the shared roles, since it
   doesn't touch --kd-btn-* or .is-style-outline, just adds one more option
   used only inside .sponsors-hero. Flagged in the SP1 handoff: SP7
   (closing CTA) calls for the same "navy outline" pill per the tracker —
   worth promoting to a named --kd-btn3-* pair in tokens.css if a second
   pattern needs it, rather than each pattern reinventing it.

   Base (mobile) sizing below is smaller than the sitewide --kd-btn-pad/
   --kd-size-btn (Figma's mobile buttons are shorter, `2082:8-11`) — the
   900px block restores the full sitewide size once the buttons are no
   longer full-width. ─────────────────────────────────────────────────── */
.sponsors-hero__buttons.wp-block-buttons {
	gap: 0.75rem; /* 12px */
	flex-direction: column;
	flex-wrap: wrap;
	width: 100%;
}

.sponsors-hero__buttons.wp-block-buttons .wp-block-button,
.sponsors-hero__buttons.wp-block-buttons .wp-block-button__link {
	width: 100%;
}

.sponsors-hero__buttons.wp-block-buttons .wp-block-button__link {
	justify-content: center;
	text-align: center;
	font-size: 1.25rem; /* 20px, down from the sitewide 22px */
	padding: 1.25rem 1.75rem; /* 20px/28px, down from --kd-btn-pad's 24px/36px */
	/* Gate round 2, item 4: dropped a `font-variation-settings:"wdth" 100`
	   rule that lived here in round 1 — measured live and confirmed it's a
	   genuine no-op (rendered button width identical with or without it;
	   the actual width/wrap cause was the `flex-shrink` fix in the lock
	   block below). The sitewide `.wp-block-button__link` rule still omits
	   the DynaPuff `wdth` axis every OTHER button in the theme also lacks
	   — a real, but separate and out-of-scope, gap in global.css. */
}

/* Pending packet-download state (`dfd_links('packet')` empty pre-Phase 6) —
   same visual convention as patterns/sponsor-tiers.css's `.is-pending`
   rule, duplicated here rather than shared (each pattern is its own CSS
   partial; see this pattern's file header). Only the visual state — the
   markup itself (aria-disabled, tabindex="-1", no target/rel) is in the PHP. */
.sponsors-hero .is-pending .wp-block-button__link {
	opacity: 0.55;
	pointer-events: none;
	cursor: not-allowed;
}

/* Specificity note: global.css's default-button rule is
   `.wp-block-button:not(.is-style-outline):not(.is-style-text-link)
   .wp-block-button__link` — each `:not(.class)` counts as a class for
   specificity, so that selector is 4 classes deep (0,4,0). A plain
   `.sponsors-hero__btn-outline .wp-block-button__link` (0,2,0) loses to it
   outright, no matter the source order. Matching the real ancestor chain
   this button actually has (.sponsors-hero .wp-block-buttons.sponsors-hero__buttons
   .sponsors-hero__btn-outline .wp-block-button__link — 5 classes, 0,5,0)
   beats it on specificity alone, no `!important` needed. */
.sponsors-hero
	.wp-block-buttons.sponsors-hero__buttons
	.sponsors-hero__btn-outline
	.wp-block-button__link {
	background-color: transparent;
	color: var(--kd-color-primary);
	border: 2px solid var(--kd-color-primary);
	transition:
		background-color var(--kd-transition-fast),
		color var(--kd-transition-fast);
}

/* Derived hover (no interaction state exists in the static Figma comp) —
   fills solid on hover/focus, consistent with how the rest of the site's
   buttons darken on hover rather than doing nothing. */
.sponsors-hero
	.wp-block-buttons.sponsors-hero__buttons
	.sponsors-hero__btn-outline
	.wp-block-button__link:hover,
.sponsors-hero
	.wp-block-buttons.sponsors-hero__buttons
	.sponsors-hero__btn-outline
	.wp-block-button__link:focus-visible {
	background-color: var(--kd-color-primary);
	color: var(--kd-color-base);
}

/* ── Card column ──────────────────────────────────────────────────────────── */
.sponsors-hero__card-col {
	min-width: 0;
}

/* ── Stats row — separate from the two-column grid above it (Figma: a
   sibling row spanning the full composition, not nested in either column).
   Base (mobile) is the Figma mobile 2×2 grid (`2082:23`); the 900px block
   switches to the desktop 4-across flex row. ─────────────────────────── */
.sponsors-hero__stats {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	row-gap: 1rem;
	column-gap: 1rem;
	margin-top: 1.75rem; /* 20px outer rhythm + Figma's own 8px pt on the mobile stats block */
	/* Client edit (Janel/Userback 8521755, 2026-10-12): "put this in a
	   purple box and make the text white". White on secondary purple =
	   4.61:1 (AA for the 13px labels too). Figma: page "Client edits 10-12
	   (Janel) — KD proposal", node 2100:543. */
	background-color: var(--kd-color-secondary);
	border-radius: 1.5rem; /* 24px */
	padding: 1.25rem; /* 20px mobile */
}

.sponsors-hero__stat {
	display: flex;
	flex-direction: column;
	gap: 0.125rem; /* 2px */
	margin: 0;
}

.sponsors-hero__stat-number {
	font-family: var(--kd-font-heading);
	font-weight: 700;
	font-variation-settings: "wdth" 100;
	/* Gate round 2, item 3: a fixed 32px + `nowrap` still overflowed the
	   2-up grid cell at 320px (round 1's fix kept the NUMBER from
	   wrapping internally, but didn't stop the whole nowrap'd box from
	   overflowing its cell when the cell itself is narrower than the
	   32px-rendered text — e.g. "20,000+"). Fluid instead: shrinks
	   continuously with the viewport down to 320, floor 24px; the 900px
	   block re-asserts the fixed desktop 44px once the row is no longer a
	   narrow 2-up grid. */
	font-size: clamp(1.5rem, 8.5vw, 2rem); /* 24px → 32px */
	line-height: 1.1;
	letter-spacing: 0.02em; /* 0.64/32 */
	color: var(--kd-color-base);
	-webkit-text-stroke: 0.125rem var(--kd-color-contrast); /* navy contour, same as the subtitle */
	paint-order: stroke fill;
	margin: 0;
	/* Gate round 1: the widest label ("children & families served") wraps
	   fine as prose, but the NUMBER itself ("20,000+") must never
	   wrap/clip inside its narrow 2-up cell — `nowrap` keeps it one line;
	   the grid cell is `1fr`, so it still only takes the width the column
	   allows, just without an internal line-break splitting the digits.
	   Works WITH the fluid size above, not instead of it — see round 2's
	   comment. */
	white-space: nowrap;
}

.sponsors-hero__stat-label {
	font-family: var(--kd-font-body);
	font-weight: 500;
	font-size: 0.8125rem; /* 13px */
	/* white on the purple box (was --kd-color-body) */
	color: var(--kd-color-base);
	margin: 0;
}

/* ── Card cycler — all five tier cards stacked in the same box, sliding via
   sponsors-hero.js. No-JS fallback: the PHP marks the first (Headliner)
   `is-active` and the other four `hidden` (a real HTML attribute — zero
   paint/layout cost, and out of the accessibility tree without any ARIA),
   so with no script the page shows exactly one static card. JS removes
   `hidden` from all five on init and switches them to `inert` instead (or
   a `hidden` toggle, feature-detected, on browsers without `inert`).
   `.dfd-tier-card-frame` (tier-card.css) supplies `container-type:inline-size`
   + `aspect-ratio:480/620` + the position:absolute base for its
   `.dfd-tier-card` children — this rule only sets the WIDTH, which differs
   by layout mode (fills the column here / a `clamp()` in the 900–1300 band
   / fixed 480px past that, see the media queries below) since only this
   pattern knows which mode is active.

   `--sponsors-hero-cycle-ms` (gate round 1, item 15): the ONE source of
   truth for the slide/fade transition duration — sponsors-hero.js reads it
   via getComputedStyle instead of hard-coding a matching number, so the
   two can't drift out of sync with each other again. ────────────────── */
.sponsors-hero__card-cycler {
	--sponsors-hero-cycle-ms: 550ms;
	width: min(
		30rem,
		100%
	); /* fills the stacked column, capped at 480px so a wide tablet-width single column doesn't blow the card up past its designed max — the 100% term is what shrinks it further on a true small phone */
}

/* ── Slide + fade "deck shuffle" transition (Alain, live review: a straight
   crossfade read as flat — wanted a card that physically leaves, like the
   top card of a deck). Three states, driven by sponsors-hero.js's class
   toggles:
     - default (waiting its turn): translateY(+1.5rem), opacity 0 — sits
       just below its resting spot, ready to slide up into place.
     - .is-active (on screen): translateY(0), opacity 1.
     - .is-leaving (transient, ~550ms): translateY(-1.5rem), opacity 0 —
       the outgoing card continues UPWARD past its resting spot rather
       than sliding back down to the "waiting" position, so the motion
       reads as one continuous exit, not a reverse of the entrance. JS
       removes this class after the transition completes, returning the
       card to the plain "waiting below" default for its next turn. ───── */
.sponsors-hero__card-cycler .dfd-tier-card {
	/* position:absolute/inset/width/height already come from tier-card.css's
	   `.dfd-tier-card-frame .dfd-tier-card` rule (`.sponsors-hero__card-cycler`
	   IS a `.dfd-tier-card-frame`, see the markup in patterns/sponsors-hero.php)
	   — only the animated state lives here. */
	opacity: 0;
	pointer-events: none;
	transform: translateY(1.5rem);
	transition:
		transform var(--sponsors-hero-cycle-ms) ease-out,
		opacity var(--sponsors-hero-cycle-ms) ease-out;
}

.sponsors-hero__card-cycler .dfd-tier-card.is-active {
	opacity: 1;
	pointer-events: auto;
	transform: translateY(0);
}

.sponsors-hero__card-cycler .dfd-tier-card.is-leaving {
	opacity: 0;
	transform: translateY(-1.5rem);
}

@media (prefers-reduced-motion: reduce) {
	/* Belt-and-suspenders only: sponsors-hero.js never starts the cycler
	   under reduced motion (checked before it even reveals the hidden
	   cards), so `.is-active` never moves off the PHP-default Headliner
	   card and `.is-leaving` is never applied — this rule has nothing to
	   neutralise in practice, kept in case a future change ever drives the
	   class toggles some other way. */
	.sponsors-hero__card-cycler .dfd-tier-card {
		transition: none;
	}
}

/* ══════════════════════════════════════════════════════════════════════
   900px — generic two-column band (no comp exists between 900 and the
   1300px lock below; H1/subtitle/card all shrink continuously with the
   viewport instead of holding their desktop size until they collide —
   gate round 1, item 3 in Alain's live review). ═══════════════════════ */
@media (min-width: 900px) {
	.sponsors-hero__inner {
		display: grid;
		/* The card column is `auto` — sized to `.sponsors-hero__card-cycler`'s
		   OWN specified width (a `clamp()`, see that rule below), not
		   negotiated by the grid. */
		grid-template-columns: 1fr auto;
		column-gap: clamp(1.5rem, 4vw, 9rem);
		align-items: start;
	}

	.sponsors-hero__kicker {
		font-size: 0.875rem; /* 14px */
		letter-spacing: 0.12em; /* 1.68/14 */
	}

	/* ── Fluid H1/subtitle, 900px → 81.25rem (round-1 fix) ──────────────────
	   Exact linear interpolation between the two known-good endpoints (the
	   base/mobile values above, and the lock block's Figma-exact values
	   below) — NOT a plain `Nvw` clamp (this codebase's usual shorthand,
	   e.g. --dfd-size-h2-section) because that form only guarantees ONE
	   endpoint; here both ends have to be exact, so
	   `clamp(floor, calc(base + (100vw - 900px) * slope), ceiling)` is used
	   to hit both precisely AND stay correctly bounded even though this
	   band now runs to 81.25rem/1300px rather than 76rem/1216px (gate round
	   1, item 2) — the explicit `clamp()` wrapper (missing before) means
	   the formula can't overshoot past the ceiling in that extended range.
	   slope = (ceiling − floor) / (900 → 1300 in px) = /400. Re-derive all
	   three numbers together if either endpoint value or the lock
	   breakpoint ever changes. */
	.sponsors-hero__heading {
		font-size: clamp(
			44px,
			calc(44px + (100vw - 900px) * 0.05),
			64px
		); /* 44px@900 → 64px@1300, slope 20/400 */
		letter-spacing: 0.03em; /* 1.92/64 — desktop tracking takes over from the mobile value once the fluid band starts */
		-webkit-text-stroke-width: clamp(
			3px,
			calc(3px + (100vw - 900px) * 0.0025),
			4px
		); /* 3px@900 → 4px@1300, slope 1/400 */
	}

	.sponsors-hero__subtitle {
		font-size: clamp(
			24px,
			calc(24px + (100vw - 900px) * 0.025),
			34px
		); /* 24px@900 → 34px@1300, slope 10/400 */
		letter-spacing: 0.03em; /* 1.02/34 */
		-webkit-text-stroke-width: clamp(
			2px,
			calc(2px + (100vw - 900px) * 0.0025),
			3px
		); /* 2px@900 → 3px@1300, slope 1/400 */
	}

	.sponsors-hero__lead {
		font-size: 1.125rem; /* 18px */
		line-height: 1.4444; /* 26/18 */
	}

	.sponsors-hero__buttons.wp-block-buttons {
		flex-direction: row;
		gap: 1rem; /* 16px */
		width: auto;
	}

	.sponsors-hero__buttons.wp-block-buttons .wp-block-button,
	.sponsors-hero__buttons.wp-block-buttons .wp-block-button__link {
		width: auto;
	}

	.sponsors-hero__buttons.wp-block-buttons .wp-block-button__link {
		font-size: var(--kd-size-btn); /* 22px, sitewide default */
		/* Gate round 3: --kd-btn-pad's 36px side padding (sitewide default)
		   put the two buttons' combined natural width at 592.5px — 0.5px
		   OVER the fixed 592px column at the >=1300 lock, forcing a wrap
		   with today's copy despite both fitting the comp visually.
		   Checked both other suspects first (letter-spacing is already
		   -0.02em/-0.44px from global.css's shared button rule; DynaPuff's
		   `wdth` axis is confirmed a no-op — toggling it live changes
		   nothing, 0px, in this font/browser) — the actual gap is DynaPuff
		   itself simply rendering ~2px wider per side than Figma's own
		   number implies. 32px side padding (4px per side off both
		   buttons, 16px off the combined pair) clears the 592px column
		   with margin. Scoped to .sponsors-hero__buttons only — does not
		   touch --kd-btn-pad or any other button sitewide. */
		padding: 1.5rem 2rem; /* 24px/32px */
	}

	/* Card width — clamp(360px, 40vw, 480px): 40vw is exactly 360px at the
	   900px floor and reaches 480px by 1200px (a little before the 81.25rem
	   lock takes over, so there's no visible jump at that handoff — it's
	   already sitting at 480 for the last stretch of this band). Height
	   follows from tier-card.css's `.dfd-tier-card-frame { aspect-ratio:
	   480 / 620; }`, and the card's OWN internal type/padding is cqi-driven
	   off this same width (see that file) — narrower card, smaller type,
	   never overflowing its fixed-aspect box. */
	.sponsors-hero__card-cycler {
		width: clamp(22.5rem, 40vw, 30rem);
	}

	.sponsors-hero__stats {
		display: flex;
		justify-content: space-between;
		gap: 1rem;
		margin-top: 4rem; /* 64px — Figma stats-row top (724) minus the card's bottom edge (40+620=660) */
		padding: 1.75rem 2.5rem; /* 28px/40px — client-edit purple box, Figma 2100:543 */
	}

	.sponsors-hero__stat-number {
		font-size: 2.75rem; /* 44px */
		letter-spacing: 0.03em; /* 1.32/44 */
	}

	.sponsors-hero__stat-label {
		font-size: 1rem; /* 16px */
	}
}

/* ══════════════════════════════════════════════════════════════════════
   81.25rem (1300px) — the exact pixel lock (gate round 1, item 2: moved
   from 76rem/1216px — see this file's own header for the full derivation
   of why 1216px alone isn't enough room for 37rem+30rem). H1/subtitle/card
   width all switch from the fluid formulas above to fixed Figma values
   here; the fluid formulas already reach these same numbers within a few
   px of this boundary, so there is no visible jump, just a switch from
   "computed" to "asserted". Verify ≥1920 stays pixel-identical to 1440 —
   same caution as every sibling pattern. ══════════════════════════════ */
@media (min-width: 81.25rem) {
	.sponsors-hero__inner {
		grid-template-columns: 37rem 30rem; /* 592px / 480px */
		column-gap: 0;
		justify-content: space-between;
	}

	.sponsors-hero__heading {
		font-size: 4rem; /* 64px */
		-webkit-text-stroke-width: 0.25rem; /* 4px */
	}

	.sponsors-hero__subtitle {
		font-size: 2.125rem; /* 34px */
		-webkit-text-stroke-width: 0.1875rem; /* 3px */
	}

	/* Gate round 1, item 7a / gate round 2, item 2: the two buttons read
	   naturally on ONE row here (Figma 2085:18–22) as long as neither
	   SHRINKS below its own label's width — the combined natural
	   (unshrunk) content width is 589px inside a 592px-wide column, only
	   3px of slack, and the default `flex-shrink:1` on a flex item still
	   proportionally compresses BOTH by a fraction of a px to close even
	   that tiny gap, which was just enough to force "Become a sponsor"'s
	   own label onto a second line (confirmed live, gate round 1: its
	   unshrunk one-line width measures 269px, but it rendered at 271.8px
	   total box width — wider than the text needed — while STILL
	   wrapping). `flex-shrink:0` stops that.
	   `flex-wrap:nowrap` was ALSO set here in round 1 to force one row —
	   withdrawn in round 2: with `flex-shrink:0` alone, the row already
	   reads as one line whenever it fits (589px < 592px today) and
	   gracefully drops to a clean two-ROW wrap (not a two-LINE label)
	   the moment label growth in Phase 6 (real client copy, unknown
	   length) ever pushes the combined width past the column — `nowrap`
	   would instead force a horizontal overflow in that case, which is
   	   worse. Scoped to this lock band ONLY — below it, the copy column is
	   narrower than 589px combined, so shrink-BUT-wrap is already the
	   default (base rule sets `flex-wrap:wrap`). */
	.sponsors-hero__buttons.wp-block-buttons .wp-block-button {
		flex-shrink: 0;
	}

	.sponsors-hero__card-cycler {
		width: 30rem; /* 480px, Figma-exact */
	}
}
