/**
 * Pattern: Sponsor Packages  (patterns/sponsor-packages.php)
 *
 * Sponsors page "packages" section, lavender band. Figma desktop `2086:162`
 * (composition `2085:2`), mobile `2082:94` (M4). Decision log D26/D28,
 * build-tracker SP5. See the PHP file's own header for the full copy
 * sourcing / discrepancy notes and the P8-fix wrapper rationale.
 *
 * ── Mobile-first ───────────────────────────────────────────────────────────
 * Every rule below is written base-first (the ≤39.99rem/640px stacked
 * state) with ascending breakpoints after it — same discipline
 * sponsors-hero.css's own header documents the reason for (a base rule
 * declared AFTER a min-width rule silently wins on source order at the
 * same specificity, which is how that pattern's H1 shipped a dead fluid
 * rule in gate round 1).
 *
 * ── Breakpoints ────────────────────────────────────────────────────────────
 * No tablet/desktop Figma frame exists between the mobile M4 frame (390px)
 * and the desktop composition (1440px) — the build brief supplies the
 * tablet target directly ("641–1024: side-by-side, stub narrowing to
 * ~280px") rather than leaving it fully derived, so the two breakpoints
 * below are asserted from that brief, not interpolated from a missing
 * frame:
 *   - 40rem (640px): body+stub go side-by-side; stub narrows to a fixed
 *     17.5rem (280px) — the brief's own tablet number.
 *   - 64rem (1024px): stub reaches its Figma-exact 21.25rem (340px) and
 *     holds there through every wider viewport, including ≥1920 (verify).
 *
 * ── Ticket geometry (get_metadata on 2086:162 / 2082:94) ──────────────────
 * Closed ticket 233px tall desktop / 382px mobile (196 body + 185 stub +
 * 1px seam) at their own respective font scales — NOT a scaled copy of one
 * box, each breakpoint's numbers are independently Figma-exact. Opening a
 * ticket adds exactly the perks list's own height; the stub and seam
 * stretch to match via `align-items: stretch` on the ticket's own flex
 * row/column — no JS height sync needed.
 *
 * Price/passes/button are CENTERED in the 340px (desktop) / full-width
 * (mobile) stub — verified against every ticket's differently-wide price
 * string, all independently centered at `(340 − text-width) / 2` — so this
 * file centers that column instead of left-padding it like the body.
 *
 * ── Seam + notches ─────────────────────────────────────────────────────────
 * The seam is a single dashed border edge between the body and stub flex
 * items; the two notches are 28px circles positioned to straddle the
 * ticket's OWN top/bottom border (desktop) or left/right border (mobile) at
 * the seam position, coloured to match the page background
 * (--kd-color-surface). `.sponsor-packages__ticket`'s own
 * `overflow: hidden` + border-radius clips the half of each circle that
 * falls outside the ticket, which is what produces the "torn ticket"
 * cutout with no extra masking/clip-path.
 *
 * Dashed colour: `--kd-color-secondary` at 45% opacity (build brief) — the
 * comp's own navy read too dark once built; `color-mix()` keeps this a
 * one-line, token-driven override rather than a new hard-coded rgba.
 *
 * ── Stub gradient ──────────────────────────────────────────────────────────
 * Every ticket's stub uses the SAME flat pink→purple gradient, LEFT→RIGHT —
 * the Rising Star tier tokens SP1 already shipped in tokens.css
 * (--dfd-tier-grad-rising-star-top/-bottom), not a five-way rotation like
 * `.dfd-tier-card`. See the PHP file's own header for why (a Figma layer
 * named "sky raster" that renders as the same flat gradient in every
 * screenshot taken of it).
 *
 * ── Accordion classes (code-review round 1 correction) ────────────────────
 * `.sponsor-packages__perks` (the `<ul>` itself — no wrapper div) renders
 * VISIBLE by default; the PHP file's own header explains why (real
 * progressive enhancement: a no-JS visitor reads every perk with no
 * interactive control at all). assets/js/sponsor-packages.js collapses
 * every ticket back to the true accordion default on init(), then toggles
 * the `hidden` attribute + the button's `aria-expanded`/label/`aria-label`
 * from there.
 *
 * ── Notch colour lever (code-review round 2, item 3 — fixed placement) ────
 * `--sponsor-packages-notch-bg` is declared on `.sponsor-packages` itself
 * (the section root), NOT on `.sponsor-packages__notch` — custom
 * properties inherit down through descendants, so a value set on an
 * ancestor is what `.sponsor-packages__notch` picks up. Declaring it a
 * SECOND time on the notch selector itself (round 1's version) would
 * always win over that ancestor regardless of what the ancestor says,
 * making the "lever" a dead one — the whole point of a re-banding lever is
 * that something ELSE can override it. Repoint THIS declaration if the
 * section is ever re-banded onto a different page background — the notch
 * must always match whatever sits BEHIND the ticket, not the ticket's own
 * white/gradient fill.
 */

.sponsor-packages {
	--sponsor-packages-notch-bg: var(--kd-color-surface);
	background-color: var(
		--kd-color-surface
	); /* lavender band, D26/D28 page rhythm */
	padding-block: var(--dfd-section-pad);
}

/* P8-fix: the outer alignfull "constrained" group has exactly one direct
   child (this one) so heading/lead/list share ONE centered box instead of
   three independently max-width'd ones (see patterns/adopt-grid.php's own
   header for the underlying bug this avoids). */
.sponsor-packages__inner > * {
	margin-top: 0;
}

.sponsor-packages__heading {
	font-size: var(--dfd-size-h2-section); /* 32px → 50px */
	letter-spacing: var(--dfd-track-heading);
	line-height: var(--kd-lh-tight);
	color: var(--kd-color-contrast);
	-webkit-text-stroke: 0.125rem var(--kd-color-base); /* 2px white contour */
	paint-order: stroke fill;
	margin-bottom: 1.25rem; /* 20px, Figma-verified at both breakpoints */
}

.sponsor-packages__lead {
	font-family: var(--kd-font-body);
	font-size: 1.125rem; /* 18px */
	line-height: var(--kd-lh-body);
	color: var(--kd-color-body);
	margin-bottom: 1.25rem; /* 20px mobile gap to the first ticket — the
		64px desktop gap is added below instead of here, since only the
		900px+ block knows the wider number applies */
}

.sponsor-packages__list {
	display: flex;
	flex-direction: column;
	gap: 1.25rem; /* 20px between tickets, mobile (2082:94: 616 − 596) */
}

/* ── Ticket shell ───────────────────────────────────────────────────────── */
.sponsor-packages__ticket {
	position: relative;
	display: flex;
	flex-direction: column; /* stacked: body, seam, stub */
	overflow: hidden; /* clips the gradient + notch circles to the radius */
	border-radius: var(--kd-radius-card); /* 12px, Figma-exact */
	scroll-margin-top: 2rem; /* breathing room when a #package-<slug> deep link scrolls here */
}

/* ── Body (white) ─────────────────────────────────────────────────────────
   Padding/gap below are the mobile numbers (2082:94/2082:97: 24px pad,
   ~10px vertical rhythm between title/summary/perks/toggle). */
.sponsor-packages__body {
	background-color: var(--kd-color-base);
	display: flex;
	flex-direction: column;
	gap: 0.625rem; /* 10px */
	padding: 1.5rem; /* 24px */
}

.sponsor-packages__body > * {
	margin: 0;
}

.sponsor-packages__title {
	font-size: 1.75rem; /* 28px mobile */
	line-height: var(--kd-lh-mid);
	letter-spacing: var(--dfd-track-heading);
	color: var(--kd-color-contrast);
}

.sponsor-packages__summary {
	font-family: var(--kd-font-body);
	font-size: 1rem; /* 16px */
	line-height: var(--kd-lh-body);
	color: var(--kd-color-body);
}

.sponsor-packages__perks {
	margin: 0;
	padding-left: 1.125rem; /* room for the bullet marker */
	display: flex;
	flex-direction: column;
	gap: 0.5rem; /* 8px between perk lines */
	list-style: disc;
}

.sponsor-packages__perks li {
	font-family: var(--kd-font-body);
	font-size: 1rem; /* 16px */
	line-height: var(--kd-lh-body);
	color: var(--kd-color-body);
}

/* Self-caught in live verification (not a reviewer finding): the class rule
   above sets `display: flex`, which — being AUTHOR css — beats the
   browser's own `[hidden] { display: none }` UA-stylesheet rule regardless
   of specificity (origin/importance is resolved before specificity in the
   cascade), so `sponsor-packages.js`'s `panel.hidden = true` silently had
   no visual effect. This selector's extra attribute bumps specificity
   (0,2,0 vs 0,1,0) so it wins outright, no `!important` needed. */
.sponsor-packages__perks[hidden] {
	display: none;
}

/* Toggle — plain button, no icon glyph (DynaPuff has none, per the brief);
   the "+"/"–" text glyph is swapped by sponsor-packages.js alongside the
   label. Plain text, NOT underlined (design-diff round 1 finding — the
   comp's toggle is plain purple DynaPuff with no underline at either
   breakpoint; only the colour shifts on hover/focus). Focus ring is the
   sitewide `*:focus-visible` default (global.css, 3px navy + 2px offset) —
   this toggle sits on white with no halo-contrast problem, so it does not
   need its own override. */
.sponsor-packages__toggle {
	appearance: none;
	background: none;
	border: none;
	padding: 0;
	margin: 0;
	display: inline-flex;
	align-items: baseline;
	gap: 0.375rem; /* 6px */
	font-family: var(--kd-font-heading);
	font-weight: var(--kd-fw-heading);
	font-variation-settings: "wdth" 100;
	font-size: 1.125rem; /* 18px mobile */
	color: var(--kd-color-secondary);
	text-decoration: none;
	cursor: pointer;
	align-self: flex-start;
}

.sponsor-packages__toggle:hover,
.sponsor-packages__toggle:focus-visible {
	color: var(--dfd-color-purple-ink);
}

.sponsor-packages__toggle-glyph {
	font-family: var(--kd-font-heading);
}

/* ── Seam — mobile: horizontal, notches on the side edges (2082:97's own
   `seam` sub-frame: dash spans the ticket width, notches sit at x=-14/328,
   i.e. straddling the ticket's own left/right border at this seam's own
   vertical position). ───────────────────────────────────────────────── */
.sponsor-packages__seam {
	position: relative;
	width: 100%;
	height: 0;
	border-top: 2px dashed
		color-mix(in srgb, var(--kd-color-secondary) 45%, transparent);
	flex-shrink: 0;
}

.sponsor-packages__notch {
	position: absolute;
	top: 0;
	width: 1.75rem; /* 28px */
	height: 1.75rem;
	border-radius: 50%;
	/* Consumes the ancestor's --sponsor-packages-notch-bg (declared on
	   .sponsor-packages, see this file's header) — the var()'s own second
	   argument is a fallback for the (today, hypothetical) case this
	   markup ever renders outside that ancestor entirely, not the normal
	   path. */
	background-color: var(--sponsor-packages-notch-bg, var(--kd-color-surface));
	/* The seam's `border-top` (mobile) sits OUTSIDE its own padding box, so
	   an absolutely positioned child's `top: 0` lands 1px short of the
	   actual dashed line (the containing block is the padding box, not the
	   border's outer edge) — nudge up 1px to recentre on it. The 40rem
	   block below re-nudges this to the `margin-left` axis once the seam
	   turns vertical (`border-left`). */
	margin-top: -1px;
}

.sponsor-packages__notch--a {
	left: 0;
	transform: translate(-50%, -50%);
}

.sponsor-packages__notch--b {
	right: 0;
	transform: translate(50%, -50%);
}

/* ── Stub (gradient) — content always centered + top-anchored (NOT
   vertically centered: Figma's open Main Stage example keeps the price at
   the same y-offset as every closed ticket, the extra open height just
   adds blank gradient below the button). ─────────────────────────────── */
.sponsor-packages__stub {
	background-image: linear-gradient(
		to right,
		var(--dfd-tier-grad-rising-star-top),
		var(--dfd-tier-grad-rising-star-bottom)
	);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.5rem; /* 8px, mobile (2082:106: 75−67, 102−94) */
	padding: 1.5rem; /* 24px */
	text-align: center;
}

.sponsor-packages__stub > * {
	margin: 0;
}

.sponsor-packages__price {
	/* Not a heading ELEMENT (it's a <p>) so it gets none of theme.json's
	   automatic h1-h6 font-family — declared explicitly here exactly like
	   `.dfd-tier-card__amount`/`__name` (tier-card.css) do for the same
	   reason. Design-diff round 1 finding: without this it fell through to
	   the BODY stack (Helvetica Neue/Arial/sans-serif), not DynaPuff. */
	font-family: var(--kd-font-heading);
	font-weight: var(--kd-fw-heading);
	font-variation-settings: "wdth" 100;
	font-size: 2.25rem; /* 36px mobile */
	line-height: 1.1;
	letter-spacing: var(--dfd-track-heading);
	color: var(--kd-color-contrast);
	-webkit-text-stroke: 0.1875rem var(--kd-color-base); /* 3px white contour */
	paint-order: stroke fill;
}

.sponsor-packages__passes {
	font-family: var(--kd-font-body);
	font-weight: 500;
	font-size: 1rem; /* 16px */
	color: var(--kd-color-body); /* black */
}

.sponsor-packages__cta.wp-block-button {
	width: 100%;
}

.sponsor-packages__cta .wp-block-button__link {
	width: 100%;
	text-align: center;
	justify-content: center;
}

/* ══════════════════════════════════════════════════════════════════════
   40rem (640px) — body + stub go side-by-side; seam turns vertical with
   notches on the top/bottom edges; stub narrows to the brief's own tablet
   target (~280px) rather than jumping straight to the 340px desktop
   value. ═══════════════════════════════════════════════════════════════ */
@media (min-width: 40rem) {
	.sponsor-packages__lead {
		margin-bottom: 4rem; /* 64px — desktop gap to the first ticket (2086:162: 250 − 186) */
	}

	.sponsor-packages__list {
		gap: 2.875rem; /* 46px between tickets, desktop (2086:162: 529 − 483) */
	}

	.sponsor-packages__ticket {
		flex-direction: row;
		align-items: stretch;
	}

	.sponsor-packages__body {
		flex: 1 1 auto;
		min-width: 0;
		gap: 0.75rem; /* 12px, desktop rhythm */
		padding: 2rem 2.25rem; /* 32px / 36px */
	}

	.sponsor-packages__title {
		font-size: 2.25rem; /* 36px */
	}

	.sponsor-packages__summary {
		font-size: 1.125rem; /* 18px */
	}

	.sponsor-packages__toggle {
		font-size: 1.25rem; /* 20px */
	}

	.sponsor-packages__seam {
		width: 0;
		height: auto;
		border-top: none;
		border-left: 2px dashed
			color-mix(in srgb, var(--kd-color-secondary) 45%, transparent);
		align-self: stretch;
	}

	.sponsor-packages__notch {
		top: auto;
		left: 0;
		margin-top: 0;
		margin-left: -1px; /* seam border is now `border-left` — recentre on THAT axis instead (see the base rule's own comment) */
	}

	.sponsor-packages__notch--a {
		top: 0;
		transform: translate(-50%, -50%);
	}

	.sponsor-packages__notch--b {
		bottom: 0;
		right: auto;
		transform: translate(-50%, 50%);
	}

	.sponsor-packages__stub {
		flex-shrink: 0;
		width: 17.5rem; /* 280px — brief's tablet target */
		justify-content: flex-start;
		gap: 0.625rem; /* 10px, desktop rhythm */
		padding: 2rem 1.5rem;
	}

	.sponsor-packages__price {
		font-size: 2.75rem; /* 44px */
	}

	.sponsor-packages__passes {
		font-size: 1.125rem; /* 18px */
	}

	/* Code-review round 1, item 3: keep `width: 100%` (the base/mobile rule,
	   still in effect here) rather than a fixed `width`, and only CAP it —
	   a fixed 16.875rem forced the pill past the 232px content box the
	   280px tablet stub actually has (340 padding included), and the
	   ticket's own `overflow: hidden` silently clipped the overflow. `100%`
	   under a `max-width` shrinks safely to whatever room a given stub
	   width leaves; the smaller tablet-only type/padding scale just below
	   is what keeps the LABEL itself on one line inside that narrower box. */
	.sponsor-packages__cta.wp-block-button,
	.sponsor-packages__cta .wp-block-button__link {
		max-width: 16.875rem; /* 270px, Figma-exact desktop button width — a ceiling, not an assertion */
	}
}

/* ══════════════════════════════════════════════════════════════════════
   40rem–63.99rem (640–1023px) ONLY — tablet-scale pill. The 280px stub's
   232px content box (280 − 2×24px padding) is narrower than "Become a
   Sponsor" renders at the sitewide default 22px/1.5rem–2.25rem padding,
   which would wrap the label to two lines even after the max-width fix
   above stops it overflowing. Code-review round 1, item 3's own suggested
   numbers. ═══════════════════════════════════════════════════════════ */
@media (min-width: 40rem) and (max-width: 63.99rem) {
	.sponsor-packages__cta .wp-block-button__link {
		font-size: 1.125rem; /* 18px */
		padding: 1rem 1.5rem; /* 16px / 24px */
	}
}

/* ══════════════════════════════════════════════════════════════════════
   64rem (1024px) — stub reaches its Figma-exact desktop width; the pill's
   340px stub / 292px content box comfortably fits the 270px cap from here.
   ⚠️ The pill's FONT-SIZE/PADDING don't return to the sitewide 22px/74px
   default until 1025px, not 1024 — global.css carries its own pre-existing
   `@media (max-width: 1024px)` "buttons slightly smaller on tablet" rule
   (unrelated to this pattern, not touched here) that still wins at exactly
   1024px since this file's own tablet-only override above stops at
   63.99rem. Harmless (nothing overflows or clips at 1024, verified), just
   don't expect a byte-identical 74px pill until 1025px+. Holds through
   ≥1920 (verify — the container system caps the ticket's OWN width at
   --kd-content-max well before that, so nothing here needs its own upper
   lock). ════════════════════════════════════════════════════════════ */
@media (min-width: 64rem) {
	.sponsor-packages__stub {
		width: 21.25rem; /* 340px, Figma-exact */
	}
}

/* ── Section gap: adjacent full-bleed bands touch ───────────────────────────
 * The sitewide owl (`.entry-content > * + *`, --kd-section-gap) applies a
 * 120px margin between every pair of sections "regardless of whether the
 * adjacent section is plain or banded" (global.css). On /sponsors/ every
 * section IS a full-bleed band, so that margin renders as a strip of the
 * lavender page background between two coloured bands — Alain, 2026-09-16:
 * "on top of the Our sponsor section, there's a left over pale purple
 * section". The compositions (2085:2 / 2086:2) show the bands touching.
 * Each band already carries its own --dfd-section-pad top and bottom, so
 * that padding is the rhythm; the external margin only adds the strip.
 * Selector shape + mechanism copied from info-band.css's own gap override
 * (3 classes beats the owl's 1 — no !important). */
.entry-content > .kd-section.sponsor-packages {
	margin-block-start: 0;
}
