/*
Theme Name: Fennec Health
Theme URI: /
Description: Holding page for fennechealth.com. Creosote theme (brand book A): Daybreak on light systems, Twilight on dark. Fonts are self-hosted; the page makes no external requests.
Author: Fennec Health
Version: 1.6.4
Requires at least: 6.7
Tested up to: 6.9
Requires PHP: 8.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: fennec-health
*/

/*
 * Creosote Twilight. theme.json defines Daybreak on core's :root preset variables; these blocks
 * redefine the same variables. html:root (0,1,1) outranks core's :root (0,1,0), so the result does
 * not depend on which stylesheet prints first. :root:has(.fh-dark) (0,2,0) forces Twilight on a
 * page whose content carries .fh-dark, whatever the system setting.
 */
/*
 * --fh-line: rust where a line or mark carries meaning (non-text, 3:1 needed). Rust is 4.6:1 on
 * Daybreak but 2.5:1 on Twilight, so Twilight uses the sand-orange (6.3:1).
 */
:root { --fh-line: #C2410C; }

@media (prefers-color-scheme: dark) {
	html:root {
		color-scheme: dark;
		--fh-line: #F5A064;
		--wp--preset--color--ground: #2C3327;
		--wp--preset--color--surface: #37402F;
		--wp--preset--color--ink: #F6F0E2;
		--wp--preset--color--muted: #C3C8B5;
		--wp--preset--color--link: #F5A064;
		--wp--preset--color--rule: #4A5541;
	}
}

:root:has(.fh-dark) {
	color-scheme: dark;
	--fh-line: #F5A064;
	--wp--preset--color--ground: #2C3327;
	--wp--preset--color--surface: #37402F;
	--wp--preset--color--ink: #F6F0E2;
	--wp--preset--color--muted: #C3C8B5;
	--wp--preset--color--link: #F5A064;
	--wp--preset--color--rule: #4A5541;
}

body { margin: 0; }

.fh-page {
	box-sizing: border-box;
	max-width: 70rem;
	margin-inline: auto;
	padding: clamp(2.5rem, 7vw, 5.5rem) clamp(1.25rem, 5vw, 3rem) clamp(2rem, 5vw, 3.5rem);
}

/* Hero */
.fh-mark img {
	display: block;
	width: clamp(96px, 10vw, 120px); /* brand book §6: the grid reads cleanly from 96 px */
	height: auto;
}

.fh-eyebrow {
	margin-block-start: 2rem;
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--link); /* text-grade rust: #C2410C on the ground is only 4.6:1 */
}

.fh-hero h1 {
	max-width: 14ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.6rem, 1.4rem + 5vw, 5.25rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.fh-lede {
	max-width: 36rem;
	font-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}

/*
 * Wide screens: the grid mark stands to the right of the words, larger, instead of sitting over the
 * eyebrow and leaving the right half of the hero empty (Jerry, 2026-09-14). V14 keeps its own
 * two-column hero (words beside the form).
 */
@media (min-width: 60rem) {
	.fh-hero:has(> .fh-mark):not(.v14-hero > .fh-hero) {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		column-gap: clamp(2rem, 6vw, 6rem);
		align-items: center;
	}
	.fh-hero:has(> .fh-mark):not(.v14-hero > .fh-hero) > * { grid-column: 1; }
	.fh-hero:has(> .fh-mark):not(.v14-hero > .fh-hero) > .fh-mark {
		grid-column: 2;
		grid-row: 1 / span 3;
		margin: 0;
	}
	.fh-hero:has(> .fh-mark):not(.v14-hero > .fh-hero) > .fh-mark img { width: clamp(176px, 17vw, 232px); }
	.fh-hero:has(> .fh-mark):not(.v14-hero > .fh-hero) > .fh-eyebrow { margin-block-start: 0; }
}

/* The desert house */
.fh-scene { margin: clamp(2.5rem, 6vw, 4rem) 0 0; }

.fh-scene img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 20px;
}

/*
 * Layered card: overlaps the foot of the scene (period cue, brand book §5). It sits right so the
 * fennec, bottom-left at ~28% of the width, stays visible.
 */
.fh-story {
	position: relative;
	max-width: 40rem;
	margin-block-start: -5rem;
	margin-inline: auto clamp(0rem, 4vw - 1rem, 3rem);
	padding: clamp(1.5rem, 4vw, 2.75rem);
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 20px;
}

.fh-story h2,
.fh-faq h2 {
	font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
	font-weight: 600;
}

.fh-pull {
	padding-inline-start: 1rem;
	border-inline-start: 3px solid var(--wp--preset--color--rust);
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	font-weight: 600;
	line-height: 1.35;
}

/* Questions */
.fh-faq { margin-block-start: clamp(3.5rem, 8vw, 6rem); }

.fh-cards { gap: 1.25rem; margin-block-start: 1.5rem; }

.fh-card {
	padding: 1.5rem;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-top: 3px solid var(--wp--preset--color--rust);
	border-radius: 16px;
}

.fh-card h3 {
	font-size: 1.125rem;
	font-weight: 600;
	line-height: 1.35;
}

.fh-card p { font-size: 1rem; }

/* Footer */
.fh-foot {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 0.25rem 1rem;
	align-items: center;
	margin-block-start: clamp(3.5rem, 8vw, 6rem);
	padding-block-start: 2rem;
	border-top: 1px solid var(--wp--preset--color--rule);
}

.fh-foot p { margin: 0; }

.fh-head {
	grid-row: span 2;
	display: block;
	width: 48px;
	height: 48px;
}

.fh-note {
	font-size: 0.9375rem;
	color: var(--wp--preset--color--muted);
}

:where(a):focus-visible {
	outline: 2px solid var(--wp--preset--color--link);
	outline-offset: 2px;
}

/* The logo's line symbols as icons: one SVG each, painted in the text colour through a mask. */
.fh-sym {
	display: block;
	width: 52px;
	height: 52px;
	background: currentColor;
	-webkit-mask: var(--sym) center / contain no-repeat;
	mask: var(--sym) center / contain no-repeat;
}
.fh-sym--heart-pulse { --sym: url(assets/img/sym/heart-pulse.svg); }
.fh-sym--check { --sym: url(assets/img/sym/check.svg); }
.fh-sym--target { --sym: url(assets/img/sym/target.svg); }
.fh-sym--fennec { --sym: url(assets/img/sym/fennec.svg); }
.fh-sym--lightbulb { --sym: url(assets/img/sym/lightbulb.svg); }
.fh-sym--binary { --sym: url(assets/img/sym/binary.svg); }
.fh-sym--rocket { --sym: url(assets/img/sym/rocket.svg); }
.fh-sym--chart { --sym: url(assets/img/sym/chart.svg); }
.fh-sym--cactus { --sym: url(assets/img/sym/cactus.svg); }

/* Shared by the cover-block variants (V2, V6): cover text follows the theme, not core's white. */
.fh-cover .wp-block-cover__inner-container { color: var(--wp--preset--color--ink); }

.fh-cover::after {
	content: "";
	position: absolute;
	inset: auto 0 0;
	height: 35%;
	background: linear-gradient(to bottom, transparent, var(--wp--preset--color--ground));
	pointer-events: none;
}

/* Scrim behind cover text: the scene's pale mountains and lit house sit where the lede falls. */
.fh-cover .wp-block-cover__inner-container { position: relative; z-index: 2; }

.fh-cover::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
}

/*
 * These covers play the day-cycle loop, which passes noon: the scrim is sized for the brightest
 * frame, not the still. Ink (#F6F0E2) over a near-white sky needs ~75% ground beneath it to hold
 * 5.5:1; measured per text box by the contrast probe at t=24 s (noon) and 37.2 s (sunset).
 */
/* V2's scrim stops short of the house (Jerry: "I don't quite see enough of the picture"; it used to
 * reach 88%): the words are held to the left half and the scrim fades out by 68%. Ink over the noon
 * sky needs >= ~75% ground under every glyph, so it stays at 82% to 52%. */
.v2-hero::before {
	background: linear-gradient(100deg,
		color-mix(in srgb, var(--wp--preset--color--ground) 90%, transparent) 0%,
		color-mix(in srgb, var(--wp--preset--color--ground) 82%, transparent) 52%,
		transparent 68%);
}

/* Muted on the video would need ~87% ground; the lede takes ink instead, as on V6 and V15. */
.v2-hero .fh-lede { color: var(--wp--preset--color--ink); }

.v6-hero::before {
	background: linear-gradient(to bottom,
		color-mix(in srgb, var(--wp--preset--color--ground) 70%, transparent) 0%,
		color-mix(in srgb, var(--wp--preset--color--ground) 68%, transparent) 58%,
		color-mix(in srgb, var(--wp--preset--color--ground) 20%, transparent) 75%,
		transparent 85%);
}

/*
 * The CTA band's 70% overlay flattens the night scene; core's dim rule is (0,3,0), this is (0,4,0).
 * The words get their own scrim instead: an ellipse behind them (the horizon glow sits right there),
 * flat on phones where the words run edge to edge. Measured, not guessed: contrast2.js probe.
 */
.wp-block-cover.v6-cta .wp-block-cover__background.has-background-dim { opacity: 0.4; }

.v6-cta::before {
	background: radial-gradient(ellipse 55% 70% at 50% 50%,
		color-mix(in srgb, var(--wp--preset--color--ground) 82%, transparent) 0%,
		color-mix(in srgb, var(--wp--preset--color--ground) 74%, transparent) 55%,
		transparent 85%);
}

@media (max-width: 48rem) {
	.v6-cta::before { background: color-mix(in srgb, var(--wp--preset--color--ground) 74%, transparent); }
}

/* ---- V2 · Twilight cinematic ---- */
.v2-hero .wp-block-cover__inner-container {
	box-sizing: border-box;
	max-width: 70rem;
	margin-inline: auto;
	padding: clamp(2rem, 6vw, 5rem) clamp(1.25rem, 5vw, 3rem);
}

.v2-hero .fh-lede { max-width: 30rem; }

.v2-hero h1 {
	max-width: 11ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.8rem, 1.2rem + 4vw, 5rem);
	line-height: 1;
	letter-spacing: -0.03em;
}

.v2-body { padding-block-start: clamp(2rem, 5vw, 3rem); }

.v2-body .wp-block-columns { gap: clamp(1.5rem, 4vw, 4rem); }

.v2-body h2 {
	padding-block-start: 1rem;
	border-top: 3px solid var(--wp--preset--color--rust);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.v2-body .v2-big {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
	font-weight: 600;
	line-height: 1.2;
}

/* ---- V3 · Minimal centered ---- */
.v3 {
	box-sizing: border-box;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1.25rem;
	padding: 3rem clamp(1.25rem, 5vw, 3rem);
	text-align: center;
}

.v3 > * { margin-block: 0; }

.v3 .fh-mark img { width: clamp(128px, 14vw, 168px); }

.v3 h1 {
	max-width: 16ch;
	margin-block-start: 1rem;
	font-size: clamp(2.2rem, 1.4rem + 3.2vw, 3.75rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

.v3 .fh-lede { max-width: 32rem; }

.v3 .fh-note { margin-block-start: 2rem; }

/* ---- V4 · Values grid: the logo's 3×3 tile, drawn at page scale ---- */
.v4-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2px; /* the rule colour showing through: the logo's grid lines */
	margin-block-start: clamp(2.5rem, 6vw, 4rem);
	background: var(--wp--preset--color--rule);
	border: 2px solid var(--wp--preset--color--rule);
	border-radius: 20px;
	overflow: hidden;
}

.v4-grid > * { margin: 0; }

.v4-cell {
	padding: clamp(1.25rem, 3vw, 2rem);
	background: var(--wp--preset--color--surface);
}

.v4-cell > * { margin-block: 0; }

.v4-cell h3 {
	margin-block-start: 1.25rem;
	font-size: 1.1875rem;
	font-weight: 600;
	line-height: 1.3;
}

.v4-cell p {
	margin-block-start: 0.5rem;
	font-size: 0.9875rem;
	color: var(--wp--preset--color--muted);
}

.v4-cell .fh-sym { color: var(--wp--preset--color--ink); }

/* ---- V5 · Audience cards ---- */
.v5-who { margin-block-start: clamp(3rem, 7vw, 5rem); }

.v5-who > h2 {
	font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
	font-weight: 600;
}

.v5-cards { gap: 1.25rem; margin-block-start: 1.5rem; }

.v5-card {
	display: flex;
	flex-direction: column;
	padding: clamp(1.5rem, 3vw, 2rem);
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 20px;
}

.v5-card > * { margin-block: 0; }

.v5-card .fh-eyebrow { margin-block-start: 0; }

.v5-card h3 {
	margin-block-start: 0.75rem;
	font-size: 1.3125rem;
	font-weight: 600;
	line-height: 1.3;
}

.v5-card p { margin-block-start: 0.875rem; font-size: 1rem; }

.v5-card .v5-close {
	margin-block-start: auto;
	padding-block-start: 1.25rem;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600;
}

/* ---- V6 · Cinematic ---- */
.v6-wrap {
	box-sizing: border-box;
	max-width: 76rem;
	margin-inline: auto;
	padding-inline: clamp(1.25rem, 5vw, 3rem);
}

.v6-hero .wp-block-cover__inner-container {
	display: flex;
	flex-direction: column;
	min-height: inherit;
}

.v6-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding-block: 1.5rem;
}

.v6-brand {
	margin: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.375rem;
	font-weight: 700;
	letter-spacing: -0.01em;
}

.v6-headline { text-align: center; padding-block: clamp(2rem, 6vw, 4rem) 0; }

.v6-headline h1 {
	max-width: 15ch;
	margin-inline: auto;
	font-size: clamp(2.75rem, 1rem + 6.5vw, 7rem);
	font-weight: 600;
	line-height: 0.98;
	letter-spacing: -0.035em;
}

.v6-headline .fh-lede {
	max-width: 40rem;
	margin-inline: auto;
	color: var(--wp--preset--color--ink);
}

.v6 .wp-block-buttons { gap: 0.75rem; }

.v6 .v6-headline .wp-block-buttons { justify-content: center; margin-block-start: 2rem; }

.v6 .wp-block-button.is-style-outline .wp-block-button__link {
	padding: 0.8rem 1.9rem;
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--ink) 35%, transparent);
	border-radius: 999px;
	background: color-mix(in srgb, var(--wp--preset--color--ground) 20%, transparent);
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
	color: var(--wp--preset--color--ink);
	font-size: 0.9375rem;
	font-weight: 500;
}

.v6-bar .wp-block-button.is-style-outline .wp-block-button__link { padding: 0.55rem 1.4rem; }

.v6-statement {
	padding-block: clamp(5rem, 14vw, 10rem);
	text-align: center;
}

.v6-statement h2 {
	max-width: 20ch;
	margin-inline: auto;
	font-size: clamp(2rem, 1.2rem + 3vw, 3.75rem);
	font-weight: 600;
	line-height: 1.08;
	letter-spacing: -0.02em;
}

.v6-feature { gap: 1rem; }

.v6-card {
	padding: clamp(1.75rem, 4vw, 3rem);
	background: var(--wp--preset--color--surface);
	border-radius: 20px;
}

.v6-card > * { margin-block: 0; }

.v6-card .fh-sym { width: 40px; height: 40px; color: var(--wp--preset--color--ink); }

.v6-card h3 {
	margin-block-start: 1.75rem;
	font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
	font-weight: 600;
	line-height: 1.15;
}

.v6-card p { margin-block-start: 1rem; color: var(--wp--preset--color--muted); }

.v6-tags {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-block-start: 1.75rem;
	padding: 0;
	list-style: none;
}

.v6-tags li {
	padding: 0.35rem 0.9rem;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 999px;
	font-size: 0.875rem;
}

/* Dark green on sand: brand book's badge pairing, 9.3:1. */
.v6-tags li:first-child {
	border-color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ground);
}

.v6-photo { height: 100%; margin: 0; }

.v6-photo img {
	display: block;
	width: 100%;
	height: 100%;
	min-height: 18rem;
	object-fit: cover;
	object-position: 30% 60%;
	border-radius: 20px;
}

.v6-pdsa {
	padding-block: clamp(5rem, 12vw, 9rem);
	text-align: center;
}

.v6-kicker {
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.v6-pdsa h2,
.v6-cta h2 {
	margin-block-start: 1rem;
	font-size: clamp(2.25rem, 1.3rem + 3.2vw, 4rem);
	font-weight: 600;
	line-height: 1.05;
	letter-spacing: -0.025em;
}

.v6-pdsa .v6-steps { gap: 1.5rem; margin-block-start: clamp(2.5rem, 5vw, 3.5rem); }

.v6-steps h3 {
	font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.5rem);
	font-weight: 600;
	letter-spacing: -0.02em;
}

.v6-steps p {
	margin-block-start: 0.5rem;
	font-size: 0.9375rem;
	color: var(--wp--preset--color--muted);
}

.v6-cta .wp-block-cover__inner-container {
	max-width: 44rem;
	margin-inline: auto;
	padding-block: clamp(5rem, 12vw, 9rem);
	text-align: center;
}

.v6-cta p:not(.v6-kicker) { margin-inline: auto; max-width: 36rem; color: var(--wp--preset--color--ink); }

.v6-foot { padding-block: 3rem; }

.v6-foot .fh-foot { margin-block-start: 0; }

/*
 * Day-cycle loop (V1, V2, V5, V6). fh-motion.js plays it only when motion is allowed and it is on
 * screen; the poster (and, in covers, the cover image beneath) is the still for reduced motion.
 */
.fh-scene,
.v6-photo { position: relative; }

.fh-scene video {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 20px;
	background: var(--wp--preset--color--surface);
}

.v6-photo video {
	display: block;
	width: 100%;
	height: 100%;
	min-height: 18rem;
	object-fit: cover;
	object-position: 50% 60%;
	border-radius: 20px;
}

.fh-bgvideo { position: absolute; inset: 0; z-index: 0; }

.fh-bgvideo video { display: block; width: 100%; height: 100%; object-fit: cover; }

/*
 * A video cover's inner container must not be a stacking context, or the video inside it paints
 * over the z-index:1 scrim. The cover is display:flex, so core's z-index:1 on the inner container
 * makes it one even at position:static (flex items honour z-index). Measured 2026-09-14: V2/V6/V15
 * scrims were under the video until this was auto. !important because the z-index:1 comes from core's
 * inline cover rule "body:not(.editor-styles-wrapper) .wp-block-cover:not(.wp-block-cover:has(
 * .wp-block-cover__background + .wp-block-cover__inner-container)) .wp-block-cover__inner-container",
 * specificity (0,6,1), which applies because our background span is followed by the <img>.
 */
.fh-cover.fh-has-video .wp-block-cover__inner-container { position: static; z-index: auto !important; }

.fh-cover.fh-has-video .wp-block-cover__inner-container > :not(.fh-bgvideo):not(.fh-pause) {
	position: relative;
	z-index: 2;
}

/*
 * WCAG 2.2.2: anything that moves for more than 5 s can be paused. It sits over video in both
 * themes, so it carries Twilight values directly: sand on 80% ground is 6.0:1 even over noon sky.
 */
.fh-pause {
	position: absolute;
	right: 0.75rem;
	bottom: 0.75rem;
	z-index: 3;
	padding: 0.45rem 0.95rem;
	border: 1px solid rgba(246, 240, 226, 0.45);
	border-radius: 999px;
	background: rgba(44, 51, 39, 0.8);
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
	color: #F6F0E2;
	font: 500 0.8125rem/1 var(--wp--preset--font-family--body);
	cursor: pointer;
}

.fh-pause:focus-visible { outline: 2px solid #F5A064; outline-offset: 2px; }

/* The layered story card overlaps the scene's lower right; the control moves clear of it. */
.fh-scene .fh-pause { top: 0.75rem; bottom: auto; }

@media (max-width: 48rem) {
	.fh-scene video {
		aspect-ratio: 16 / 10;
		object-fit: cover;
		object-position: 40% 50%;
	}
}

/* Shared by the centred single-screen variants (V7, V9). */
.v7,
.v9 {
	box-sizing: border-box;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	padding: 3rem clamp(1.25rem, 5vw, 3rem);
	text-align: center;
	overflow-x: clip; /* V9's ripples reach past the screen edge on phones */
}

.v7 > *,
.v9 > * { margin-block: 0; }

.v7 h1,
.v9 h1 {
	max-width: 16ch;
	font-size: clamp(2.2rem, 1.4rem + 3.2vw, 3.75rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

.v7 .fh-lede,
.v9 .fh-lede { max-width: 32rem; }

/* ---- V7 · Startup shell: the logo tile assembles like the app shell ---- */
.v7-shell {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2px;
	width: clamp(216px, 40vw, 312px);
	aspect-ratio: 1;
	margin-block-end: 1.5rem;
	background: var(--wp--preset--color--rule);
	border: 2px solid var(--wp--preset--color--rule);
	border-radius: 20px;
	overflow: hidden;
}

.v7-cell {
	display: grid;
	place-items: center;
	background: var(--wp--preset--color--surface);
}

.v7-cell .fh-sym {
	width: 64%;
	height: 64%;
	color: var(--wp--preset--color--ink);
}

/* ---- V8 · Shooting star: the arc drawn in the daybreak sky, travelled ---- */
.v8-fig { position: relative; margin: clamp(2.5rem, 6vw, 4rem) 0 0; }

.v8-fig img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 20px;
}

/* Same 1584×672 space as the image and never cropped, so the arc lines up at every width. */
.v8-sky {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	overflow: visible;
	pointer-events: none;
}

.v8-trace,
.v8-tail {
	fill: none;
	stroke: #FBFAF4;
	stroke-width: 3;
	stroke-linecap: round;
}

.v8-trace { stroke-dasharray: 1; opacity: 0; }

.v8-tail { stroke-dasharray: 0.07 1; stroke-dashoffset: 0.07; opacity: 0.85; }

.v8-star { fill: #FFFFFF; }

.v8-glow { transition: filter 220ms ease; }

.v8-fox { fill: transparent; pointer-events: auto; }

.v8-fig:has(.v8-fox:hover) .v8-glow { filter: brightness(1.6) drop-shadow(0 0 6px #FFFFFF); }

.v8-fig .fh-pause { top: 0.75rem; bottom: auto; }

/* ---- V9 · Listening fennec ---- */
.v9-stage {
	position: relative;
	display: grid;
	place-items: center;
	width: clamp(200px, 36vw, 280px);
	aspect-ratio: 1;
}

.v9-head {
	position: relative;
	z-index: 1;
	width: 72%;
	height: auto;
	overflow: visible;
	color: var(--wp--preset--color--ink);
}

.v9-ear {
	transform-box: view-box;
	transform-origin: 35px 46px; /* the base of the ear, in the symbol's 100×100 space */
	transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.v9-ear--l { transform: rotate(var(--ear-l, 0deg)); }

.v9-ear--r { transform: rotate(var(--ear-r, 0deg)); }

.v9-ring {
	position: absolute;
	inset: 14%;
	border: 2px solid var(--fh-line);
	border-radius: 50%;
	opacity: 0;
	pointer-events: none;
}

.v9-syms {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: clamp(0.9rem, 2.5vw, 1.75rem);
	max-width: 36rem;
	margin-block-end: 1.5rem;
}

.v9-syms .fh-sym { width: 40px; height: 40px; color: var(--wp--preset--color--ink); }

/* V9's footer carries the grid mark at its 96 px minimum instead of the 48 px head. */
.fh-foot .fh-mark.fh-head { width: auto; height: auto; }

.fh-foot .fh-mark.fh-head img { width: 96px; }

.v9 .fh-foot { align-self: stretch; max-width: 40rem; margin-inline: auto; text-align: start; }

.v9-pull {
	max-width: 30rem;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	font-weight: 600;
}

/* ---- V10 · Depth diorama ---- */
.v10-dio {
	position: relative;
	aspect-ratio: 1584 / 672;
	margin: clamp(2.5rem, 6vw, 4rem) 0 0;
	overflow: hidden;
	border-radius: 20px;
	background: var(--wp--preset--color--surface);
}

/* 3% overscan each side: a plate shifted 15 source px never shows its edge (plates end at the frame). */
.v10-layer {
	position: absolute;
	top: -3%;
	left: -3%;
	width: 106%;
	height: 106%;
	object-fit: cover;
	object-position: 50% 50%;
	will-change: transform;
}

/* ---- V16 · Signal line ---- */
.v16-fig { position: relative; margin: clamp(2rem, 5vw, 3rem) 0 0; }

.v16-fig img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 20px;
}

/* The art's own 1584×672 space; the image is never cropped, so the points hold at every width. */
.v16-signal {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
}

.v16-signal path {
	fill: none;
	stroke: #FBFAF4;
	stroke-width: 2.5;
	stroke-linecap: round;
	vector-effect: non-scaling-stroke;
	filter: drop-shadow(0 1px 1.5px rgba(44, 51, 39, 0.55));
}

.v16-ln { stroke-dasharray: 1; stroke-dashoffset: 1; }

.v16-wave { opacity: 0; transform-box: view-box; transform-origin: 1088.6px 288.9px; }

.v16-stage.is-on .v16-ln { stroke-dashoffset: 0; }

.v16-stage.is-on .v16-wave { opacity: 1; }

/* The heading's underline arrives last, as if the dish had delivered it. */
.v16 h1 {
	text-decoration: underline 0.06em transparent;
	text-underline-offset: 0.16em;
	text-decoration-skip-ink: none; /* one unbroken line, not dashes between the descenders */
}

.v16-stage.is-on h1 { text-decoration-color: var(--fh-line); }

.v16 .v16-lede { margin-block-start: clamp(2rem, 5vw, 3rem); }

/* ---- V11 · Scroll through a day ---- */
/*
 * The frames are 1584 px wide at source. A full-height stage at 1440×900 enlarged them 1.34× (soft,
 * Jerry 2026-09-14); capped at 44vw / 46rem tall it stays within ~1.1× up to 1920 wide, centred on
 * screen while pinned. Phones keep the full-height stage (the art is cropped, not enlarged, there).
 */
.fh-dayscroll {
	--stage-h: min(100svh, 44vw, 46rem);
	position: relative;
	margin-block-start: clamp(1rem, 3vw, 2rem);
}

.fh-dayscroll-stage {
	position: sticky;
	top: calc((100svh - var(--stage-h)) / 2);
	height: var(--stage-h);
	max-width: 110rem;
	margin-inline: auto;
	overflow: hidden;
}

@media (min-width: 110rem) { .fh-dayscroll-stage { border-radius: 20px; } }

@media (max-width: 48rem) { .fh-dayscroll { --stage-h: 100svh; } }

.fh-dayscroll-frames img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 45% 60%;
	opacity: 0;
}

.fh-dayscroll-frames img:first-child { opacity: 1; }

.fh-dayscroll-steps {
	position: relative;
	z-index: 1;
	margin-block-start: calc(-1 * var(--stage-h));
}

/* One card per ~60% of a screen of scroll (was 95%): the next card is in view as the last one leaves. */
.fh-dayscroll-step {
	box-sizing: border-box;
	display: flex;
	align-items: flex-end;
	min-height: max(55vh, calc(var(--stage-h) * 0.8));
	padding: 0 clamp(1.25rem, 5vw, 3rem) calc((100svh - var(--stage-h)) / 2 + clamp(1.25rem, 4vw, 2.5rem));
}

.fh-dayscroll-step:last-child { min-height: 100svh; }

/*
 * Pinned (fh-motion.js moves the steps into the stage and adds the class): the cards no longer
 * scroll past the letterbox bands; they take turns in one spot inside the picture, one per ~55% of a
 * screen of scroll. Without the script the steps above scroll over the stage instead.
 */
.fh-dayscroll--pinned { height: calc(var(--stage-h) + var(--steps, 5) * 55svh); }

.fh-dayscroll--pinned .fh-dayscroll-steps {
	position: absolute;
	inset: 0;
	margin: 0;
	pointer-events: none;
}

.fh-dayscroll--pinned .fh-dayscroll-step {
	position: absolute;
	left: clamp(1.25rem, 4vw, 3rem);
	right: clamp(1.25rem, 4vw, 3rem);
	bottom: clamp(1rem, 3vw, 2rem);
	display: block;
	pointer-events: auto;
	min-height: 0;
	padding: 0;
	opacity: 0;
	visibility: hidden;
	transition: opacity 400ms ease, visibility 0s 400ms;
}

.fh-dayscroll--pinned .fh-dayscroll-step.is-on {
	opacity: 1;
	visibility: visible;
	transition: opacity 400ms ease;
}

.fh-dayscroll-card {
	max-width: 26rem;
	padding: clamp(1.25rem, 3vw, 1.75rem);
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 20px;
}

.fh-dayscroll-card > * { margin-block: 0; }

.fh-dayscroll-card .fh-eyebrow { margin-block-start: 0; }

.fh-dayscroll-card h3 {
	margin-block-start: 0.5rem;
	font-size: clamp(1.4rem, 1.1rem + 1vw, 1.875rem);
	font-weight: 600;
	line-height: 1.15;
}

.fh-dayscroll-card p:not(.fh-eyebrow) { margin-block-start: 0.75rem; color: var(--wp--preset--color--muted); }

/* ---- V12 · Your hour ---- */
/*
 * isolation: the script lifts the incoming frame to z-index 2 for its fade. Without a stacking
 * context here that z-index competed with the page, and the frame painted over the story card that
 * overlaps the figure's foot (Jerry: "the text block is behind the picture", measured 2026-09-14).
 */
.fh-hour {
	isolation: isolate;
	position: relative;
	aspect-ratio: 1584 / 672;
	margin: clamp(2.5rem, 6vw, 4rem) 0 0;
	overflow: hidden;
	border-radius: 20px;
	background: var(--wp--preset--color--surface);
}

.fh-hour img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
}

.fh-hour img.is-on { opacity: 1; }

.fh-hour-time {
	position: absolute;
	top: 0.75rem;
	left: 0.75rem;
	z-index: 3;
	padding: 0.45rem 0.95rem;
	border-radius: 999px;
	background: rgba(44, 51, 39, 0.8);
	color: #F6F0E2;
	font: 600 0.8125rem/1 var(--wp--preset--font-family--body);
	letter-spacing: 0.04em;
}

.fh-hour .fh-pause { top: 0.75rem; bottom: auto; }

/* ---- V13 · Run chart ---- */
.v13-chart {
	margin: clamp(2.5rem, 6vw, 4rem) 0 0;
	padding: clamp(1rem, 3vw, 2rem);
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 20px;
}

.v13-chart svg { display: block; width: 100%; height: auto; overflow: visible; }

.v13-chart figcaption {
	margin-block-start: 0.75rem;
	font-size: 0.875rem;
	color: var(--wp--preset--color--muted);
}

.fh-run-axis { stroke: var(--wp--preset--color--rule); stroke-width: 2; }

.fh-run-series {
	fill: none;
	stroke: var(--wp--preset--color--muted);
	stroke-width: 2;
	stroke-linejoin: round;
	stroke-dasharray: 1;
}

.fh-run-median { stroke: var(--wp--preset--color--ink); stroke-width: 2; stroke-dasharray: 1; }

.fh-run-extend { stroke: var(--wp--preset--color--ink); stroke-width: 2; stroke-dasharray: 8 7; }

.fh-run-note { stroke: var(--wp--preset--color--muted); stroke-width: 1.5; stroke-dasharray: 5 6; }

.fh-run-pt { fill: var(--wp--preset--color--ink); }

.fh-run-pt.is-run { fill: var(--fh-line); }

.fh-run-ring { fill: none; stroke: var(--fh-line); stroke-width: 3; }

.fh-run-label {
	fill: var(--wp--preset--color--muted);
	font: 500 20px var(--wp--preset--font-family--body);
}

.fh-run-pill { fill: var(--wp--preset--color--ground); stroke: var(--fh-line); stroke-width: 2; }

.fh-run-pilltext {
	fill: var(--wp--preset--color--link);
	font: 600 20px var(--wp--preset--font-family--body);
}

.v13-notes { gap: 1.25rem; margin-block-start: clamp(2.5rem, 6vw, 3.5rem); }

.v13-notes h3 { font-size: 1.1875rem; font-weight: 600; line-height: 1.3; }

.v13-notes p { font-size: 1rem; color: var(--wp--preset--color--muted); }

/* ---- V14 · Form cascade ---- */
.v14-hero {
	display: grid;
	grid-template-columns: 1.15fr 1fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

.v14-form {
	padding: clamp(1.25rem, 3vw, 1.75rem);
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 20px;
}

.v14-form-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.25rem 1rem;
	padding-block-end: 1rem;
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

.v14-form-title {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	font-weight: 600;
}

.v14-tag {
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--link);
}

.v14-row {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	padding-block: 0.85rem;
	border-bottom: 1px solid var(--wp--preset--color--rule);
}

.v14-box {
	flex: none;
	display: grid;
	place-items: center;
	width: 22px;
	height: 22px;
	border: 2px solid var(--wp--preset--color--ink);
	border-radius: 6px;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ground);
}

.v14-box svg { width: 14px; height: 14px; }

.v14-box path {
	fill: none;
	stroke: currentColor;
	stroke-width: 3;
	stroke-linecap: round;
	stroke-linejoin: round;
	stroke-dasharray: 1;
}

/* Dark green on sand: brand book's badge pairing, 9.3:1. */
.v14-req {
	margin-inline-start: auto;
	padding: 0.2rem 0.6rem;
	border-radius: 999px;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ground);
	font-size: 0.75rem;
	font-weight: 600;
}

.v14-chip {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	margin-block-start: 1.25rem;
	padding: 0.8rem 1rem;
	border: 1px solid var(--fh-line);
	border-radius: 14px;
	background: var(--wp--preset--color--ground);
}

.v14-chip .fh-sym { flex: none; width: 26px; height: 26px; color: var(--fh-line); }

.v14-chip p { margin: 0; font-size: 0.9375rem; }

.v14-loop { margin-block-start: clamp(3.5rem, 8vw, 6rem); max-width: 44rem; }

.v14-loop h2 { font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); font-weight: 600; }

.v14-loop li { margin-block-end: 0.75rem; }

/* ---- V15 · Day-cycle hero ---- */
.v15-hero .wp-block-cover__inner-container {
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: inherit;
}

.v15-wrap {
	box-sizing: border-box;
	width: 100%;
	max-width: 76rem;
	margin-inline: auto;
	padding: clamp(2rem, 6vw, 5rem) clamp(1.25rem, 5vw, 3rem);
}

.v15-wrap > * { margin-block: 0; }

/* The loop passes noon and sunset: the words need ground under them at the brightest frame. */
.v15-hero::before {
	background:
		linear-gradient(to top,
			color-mix(in srgb, var(--wp--preset--color--ground) 94%, transparent) 0%,
			color-mix(in srgb, var(--wp--preset--color--ground) 78%, transparent) 34%,
			color-mix(in srgb, var(--wp--preset--color--ground) 35%, transparent) 60%,
			transparent 80%),
		linear-gradient(100deg,
			color-mix(in srgb, var(--wp--preset--color--ground) 55%, transparent) 0%,
			transparent 55%);
}

.v15-hero h1 {
	max-width: 13ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.8rem, 1.2rem + 6vw, 6.5rem);
	line-height: 1;
	letter-spacing: -0.03em;
}

.v15-hero .fh-lede { margin-block-start: 1rem; color: var(--wp--preset--color--ink); }

.v15-q { counter-reset: q; margin-block-start: 1.5rem; padding: 0; list-style: none; }

.v15-q li {
	counter-increment: q;
	display: grid;
	grid-template-columns: 3rem 1fr;
	padding-block: 1.25rem;
	border-top: 1px solid var(--wp--preset--color--rule);
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(1.35rem, 1.05rem + 1.2vw, 2rem);
	font-weight: 600;
	line-height: 1.2;
}

.v15-q li::before { content: counter(q); color: var(--fh-line); }

/* ---- V17 · Bloom ---- */
.v17-hero {
	position: relative;
	display: grid;
	min-height: min(92svh, 60rem);
	overflow: hidden;
	background: #1F3350; /* the picture's own top-left sky, while it loads */
}

.v17-art {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 30% 62%;
}

/*
 * The picture's own night blue, deepened under the words only: from the left (to 56%, gone by 72%)
 * and from the top (gone by 86%, above the fox). The lower headline line and the lede fall on pale
 * mountains and poppies otherwise (measured 1.8:1 without it, 2026-09-14).
 */
.v17-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(100deg, rgba(24, 38, 62, 0.8) 0%, rgba(24, 38, 62, 0.76) 56%, transparent 72%);
	-webkit-mask-image: linear-gradient(to bottom, #000 0 68%, transparent 86%);
	mask-image: linear-gradient(to bottom, #000 0 68%, transparent 86%);
	pointer-events: none;
}

@media (max-width: 48rem) { .v17-hero::before { background: rgba(24, 38, 62, 0.74); } }

.v17-words {
	position: relative;
	z-index: 2;
	box-sizing: border-box;
	width: 100%;
	max-width: 76rem;
	margin-inline: auto;
	padding: clamp(2rem, 6vw, 5rem) clamp(1.25rem, 5vw, 3rem);
	color: #F6F0E2;
}

.v17-words > * { margin-block: 0; }

.v17-words .fh-eyebrow { margin-block-start: 1.75rem; color: #F5A064; }

.v17-words h1 {
	max-width: 11ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.8rem, 1.2rem + 4.4vw, 5.25rem);
	line-height: 1;
	letter-spacing: -0.03em;
	color: #F6F0E2;
}

.v17-words h1 span { display: inline-block; }

.v17-words .fh-lede { max-width: 30rem; margin-block-start: 1.25rem; color: #F6F0E2; }

.v17-values { padding-block-end: 0; }

.v17-values > h2 { font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); font-weight: 600; }

/* Stacked cards: each value pins a little lower than the last and the next slides over it. */
.v17-stack { margin: 1.5rem 0 0; padding: 0; list-style: none; }

.v17-card {
	position: sticky;
	top: calc(8vh + var(--i) * 1.25rem);
	box-sizing: border-box;
	min-height: 14rem;
	margin-block-end: 26vh;
	padding: clamp(1.5rem, 4vw, 2.5rem);
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--rule);
	border-top: 3px solid var(--wp--preset--color--rust);
	border-radius: 20px;
	box-shadow: 0 -8px 28px rgba(44, 51, 39, 0.1);
}

.v17-card:last-child { margin-block-end: 0; }

.v17-card > * { margin-block: 0; }

.v17-card .fh-sym { width: 44px; height: 44px; color: var(--wp--preset--color--ink); }

.v17-card h3 {
	margin-block-start: 1.25rem;
	font-size: clamp(1.4rem, 1.1rem + 1vw, 1.875rem);
	font-weight: 600;
	line-height: 1.2;
}

.v17-card p { max-width: 36rem; margin-block-start: 0.75rem; color: var(--wp--preset--color--muted); }

.v17-close { padding-block-start: clamp(2.5rem, 6vw, 4rem); }

/* ---- V18 · Listening portrait ---- */
.v18-stage { width: clamp(220px, 44vw, 320px); perspective: 800px; }

.v18-tile {
	position: relative;
	z-index: 1;
	width: 100%;
	aspect-ratio: 1;
	overflow: hidden;
	border-radius: 28px;
	background: #F5EFDF; /* the portrait's own background */
	transform: rotateY(var(--ry, 0deg)) rotateX(var(--rx, 0deg));
	transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}

.v18-face {
	display: block;
	width: 100%;
	height: 100%;
	transform: translate(var(--fx, 0px), var(--fy, 0px)) scale(1.05);
	transition: transform 320ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* ---- V19 · Hear the data ---- */
.v19-scene {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
	width: min(100%, 62rem);
	margin-block-end: 2rem;
	text-align: start;
}

.v19-head { width: clamp(150px, 20vw, 220px); }

.v19-chart { margin: 0; }

/* The rings wait for the chart's flag (fh-motion.js adds .v19-heard), rather than leaving on load. */
.v19 .v9-ring { animation-name: none; }

.v19-note { max-width: 34rem; font-size: 1rem; color: var(--wp--preset--color--muted); }

/* Narrow screens */
@media (max-width: 48rem) {
	.v19-scene { grid-template-columns: 1fr; justify-items: center; }
	.v17-art { object-position: 18% 62%; }
	.fh-scene img {
		aspect-ratio: 16 / 10;
		object-fit: cover;
		object-position: 30% 50%;
	}
	.fh-story {
		max-width: none;
		margin: 1.25rem 0 0;
	}
	.v4-grid { grid-template-columns: 1fr; }
	.v14-hero { grid-template-columns: 1fr; }
	.fh-hour { aspect-ratio: 16 / 10; }
	.fh-hour img { object-position: 40% 50%; }
	.v10-dio { aspect-ratio: 16 / 10; }
	.v10-layer { object-position: 30% 50%; }
	.fh-cover { min-height: 80vh !important; }
	/* Text spans the full width here, so the scrim runs top-down instead of from the left. */
	.v2-hero::before,
	.v6-hero::before {
		background: linear-gradient(to bottom,
			color-mix(in srgb, var(--wp--preset--color--ground) 90%, transparent) 0%,
			color-mix(in srgb, var(--wp--preset--color--ground) 80%, transparent) 60%,
			transparent 85%);
	}
}

/* Enter once, on the in-app enter token (380 ms, ease-out). Nothing moves under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
	.fh-hero,
	.fh-scene,
	.fh-story,
	.v3,
	.v6-headline {
		animation: fh-rise 380ms cubic-bezier(0.22, 1, 0.36, 1) both;
	}
	.fh-scene { animation-delay: 80ms; }
	.fh-story { animation-delay: 160ms; }

	/* V7: empty cells, then each symbol wipes in, 80 ms apart, the fennec last; then the words. */
	.v7-cell .fh-sym {
		animation: v7-wipe 380ms cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-delay: calc(420ms + var(--o) * 80ms);
	}
	.v7-cell:nth-child(4) .fh-sym { animation-delay: calc(420ms + 8 * 80ms + 160ms); }
	.v7 > :not(.v7-shell) { animation: fh-rise 380ms cubic-bezier(0.22, 1, 0.36, 1) 1.45s both; }
	.v7 > .fh-note { animation-delay: 1.6s; }

	/* V8: the arc draws once over the illustration's dashed one, then fades back to it. */
	.v8-trace {
		animation:
			v8-draw 1.4s cubic-bezier(0.22, 1, 0.36, 1) 500ms both,
			v8-fade 1.2s ease 2.2s forwards;
	}

	/* V9: three rings leave the head once; each symbol lights as the sound reaches it. */
	.v9-ring { animation: v9-ping 1.8s cubic-bezier(0.22, 1, 0.36, 1) both; }
	.v9-ring:nth-child(2) { animation-delay: 350ms; }
	.v9-ring:nth-child(3) { animation-delay: 700ms; }
	.v9-syms .fh-sym {
		animation: v9-hear 380ms cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-delay: calc(800ms + var(--d) * 130ms);
	}

	/* V16: ears to dish, the dish answers in three arcs toward the words, then the underline. Once. */
	.v16-stage.is-on .v16-ln { animation: v13-draw 1.8s cubic-bezier(0.45, 0, 0.2, 1) 300ms both; }
	.v16-stage.is-on .v16-wave { animation: v16-wave 700ms cubic-bezier(0.22, 1, 0.36, 1) both; animation-delay: calc(2s + var(--w) * 220ms); }
	.v16 h1 { transition: text-decoration-color 700ms ease 2.8s; }

	/* V17: the picture settles in once (4.5 s); the headline rises a word at a time. */
	.v17-art { animation: v17-settle 4.5s cubic-bezier(0.22, 1, 0.36, 1) both; }
	.v17-words h1 span {
		animation: fh-rise 600ms cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-delay: calc(200ms + var(--i) * 90ms);
	}
	.v17-words .fh-lede { animation: fh-rise 600ms cubic-bezier(0.22, 1, 0.36, 1) 850ms both; }

	/* V19: the rings go out when the fennec hears the flag. */
	.v19.v19-heard .v9-ring { animation-name: v9-ping; }

	/* V12: slow cross-fade between hours. */
	.fh-hour img { transition: opacity 2.4s ease; }

	/* V13: points plot in order, the centre line draws, then one point is flagged. */
	.fh-run-pt {
		transform-box: fill-box;
		transform-origin: center;
		animation: v13-pt 220ms cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-delay: calc(300ms + var(--i) * 55ms);
	}
	.fh-run-pt.is-run {
		animation:
			v13-pt 220ms cubic-bezier(0.22, 1, 0.36, 1) calc(300ms + var(--i) * 55ms) both,
			v13-run 380ms ease 2.6s both;
	}
	.fh-run-series {
		animation: v13-draw calc(var(--n) * 55ms) linear both;
		animation-delay: calc(300ms + var(--i) * 55ms);
	}
	.fh-run-median { animation: v13-draw 600ms cubic-bezier(0.22, 1, 0.36, 1) 1.75s both; }
	.fh-run-extend,
	.fh-run-note,
	.fh-run-notelabel { animation: v13-fade 380ms ease 2.2s both; }
	.fh-run-flag { animation: v13-fade 380ms ease 2.6s both; }

	/* V14: each row ticks on the 220 ms checkmark, then the rule's follow-up appears. */
	.v14-row {
		animation: fh-rise 380ms cubic-bezier(0.22, 1, 0.36, 1) both;
		animation-delay: calc(300ms + var(--r) * 550ms);
	}
	.v14-box,
	.v14-box path {
		animation: v14-box 220ms ease both;
		animation-delay: calc(620ms + var(--r) * 550ms);
	}
	.v14-box path { animation-name: v13-draw; }
	.v14-req { animation: v13-fade 220ms ease 1.95s both; }
	.v14-chip { animation: fh-rise 380ms cubic-bezier(0.22, 1, 0.36, 1) 2.35s both; }
}

@keyframes v7-wipe {
	from { clip-path: inset(0 100% 0 0); }
	to { clip-path: inset(0 0 0 0); }
}

@keyframes v8-draw {
	from { stroke-dashoffset: 1; opacity: 0.95; }
	to { stroke-dashoffset: 0; opacity: 0.95; }
}

@keyframes v8-fade { to { opacity: 0; } }

@keyframes v9-ping {
	from { transform: scale(0.6); opacity: 0.8; }
	to { transform: scale(2.6); opacity: 0; }
}

@keyframes v9-hear { from { opacity: 0.2; transform: translateY(4px); } }

@keyframes v13-pt { from { opacity: 0; transform: scale(0.3); } }

@keyframes v13-run { from { fill: var(--wp--preset--color--ink); } }

@keyframes v13-draw {
	from { stroke-dashoffset: 1; }
	to { stroke-dashoffset: 0; }
}

@keyframes v13-fade { from { opacity: 0; } }

@keyframes v16-wave { from { opacity: 0; transform: scale(0.6); } }

@keyframes v17-settle { from { transform: scale(1.08); } }

/* ==== Round three: V20–V25, no house (fh-gen.js) ==== */

/* Full-width stages whose content lines up with the 70rem page column. */
.v20-stage,
.v22-words {
	--gutter: max(clamp(1.25rem, 5vw, 3rem), calc((100% - 70rem) / 2));
}

/* ---- V20 · Scatter to structure ---- */
.v20-stage {
	position: relative;
	box-sizing: border-box;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: clamp(2rem, 6vw, 6rem);
	align-items: center;
	min-height: 100svh;
	padding: clamp(2rem, 6vw, 5rem) var(--gutter);
	overflow: hidden;
}

.v20-canvas,
.v23-canvas,
.v22-canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
}

/* The words sit above the particles; loose particles pass behind them. */
.v20-words { position: relative; z-index: 1; }

.v20-words > * { margin-block: 0; }

.v20-words h1,
.v25-words h1 {
	max-width: 12ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.6rem, 1.4rem + 4.6vw, 5rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.v20-words .fh-eyebrow,
.v25-words .fh-eyebrow { margin-block-start: 0; }

.v20-words .fh-lede,
.v25-words .fh-lede { margin-block-start: 1.25rem; }

.v20-target { position: relative; margin: 0; width: clamp(220px, 30vw, 380px); aspect-ratio: 1; }

.v20-target .fh-mark img { width: 100%; height: 100%; }

/* The logo stays in place (no script, screen readers) and goes transparent while particles draw it. */
.v20-stage.is-live .v20-target img { opacity: 0; }

.v20-close { padding-block-start: 0; }

/* ---- V21 · Listening waveforms ---- */
.v21-stage {
	position: relative;
	width: min(100% - 2.5rem, 64rem);
	height: min(62vw, 72svh);
	margin: clamp(1.5rem, 5vw, 3.5rem) auto 0;
}

.v21-canvas { display: block; width: 100%; height: 100%; }

.v21-words { padding-block-start: clamp(1rem, 3vw, 2rem); text-align: center; }

.v21-words > .fh-eyebrow,
.v21-words > h1,
.v21-words > .fh-lede { margin-inline: auto; }

.v21-words h1 {
	max-width: 16ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.2rem, 1.4rem + 3.2vw, 3.75rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
}

.v21 .fh-foot { text-align: start; }

/* ---- V22 · Dusk sky ---- */
/* Without WebGL (or before it draws) the section shows a still version of the same sky. */
.v22-stage {
	position: relative;
	display: grid;
	align-items: center;
	min-height: 100svh;
	overflow: hidden;
	background:
		radial-gradient(120% 70% at 18% 105%, #6A2A0E 0%, transparent 60%),
		radial-gradient(90% 70% at 85% 15%, #3E3F86 0%, transparent 60%),
		linear-gradient(160deg, #1F3350, #4A2E4F 55%, #1B2019);
}

.v22-words {
	position: relative;
	z-index: 1;
	box-sizing: border-box;
	width: 100%;
	padding: clamp(2rem, 6vw, 5rem) var(--gutter);
	color: #F6F0E2;
}

.v22-words > * { margin-block: 0; }

.v22-words h1 {
	max-width: 11ch;
	margin-block-start: 0.75rem;
	font-size: clamp(3rem, 1.2rem + 7vw, 8rem);
	line-height: 0.95;
	letter-spacing: -0.04em;
	color: #F6F0E2;
}

.v22-words .fh-lede { max-width: 32rem; margin-block-start: 1.5rem; color: #F6F0E2; }

/* Sand-orange over the sky's rust passages measured 4.2:1; the eyebrow takes the same cream. */
.v22-words .fh-eyebrow { color: #F6F0E2; }

.v22-body .wp-block-columns { gap: clamp(1.5rem, 4vw, 4rem); }

.v22-body h2 {
	padding-block-start: 1rem;
	border-top: 3px solid var(--fh-line);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.v22-big {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
	font-weight: 600;
	line-height: 1.2;
}

/* ---- V23 · Wind over sand ---- */
.v23-stage {
	position: relative;
	display: grid;
	place-items: center;
	min-height: 100svh;
	overflow: hidden;
	background: var(--wp--preset--color--ground);
}

.v23-words {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	max-width: 40rem;
	padding: 2rem clamp(1.25rem, 5vw, 3rem);
	text-align: center;
}

.v23-words > * { margin-block: 0; }

.v23-words h1 {
	max-width: 13ch;
	margin-block-start: 1.75rem;
	font-size: clamp(2.4rem, 1.4rem + 4vw, 4.5rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.v23-words .fh-lede { margin-block-start: 1.25rem; color: var(--wp--preset--color--ink); } /* muted: 5.47:1 over stray trails */

.v23-close { padding-block-start: clamp(2rem, 5vw, 3rem); }

/* ---- V24 · Constellations ---- */
.v24 { position: relative; }

.v24-sky {
	position: sticky;
	top: 0;
	height: 100svh;
	background:
		radial-gradient(ellipse 60% 70% at 72% 40%, #1F3350 0%, transparent 70%),
		var(--wp--preset--color--ground);
}

.v24-sky canvas { display: block; width: 100%; height: 100%; }

/* The steps pass over the pinned sky; only their words take clicks, so the pause stays reachable. */
.v24-steps { position: relative; z-index: 1; margin-block-start: -100svh; pointer-events: none; }

.v24-step {
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: 100svh;
	max-width: 76rem;
	margin-inline: auto;
	padding: 4rem clamp(1.25rem, 5vw, 3rem);
}

.v24-step > * { max-width: min(32rem, 46%); margin-block: 0; pointer-events: auto; }

.v24-step h1 {
	margin-block-start: 0.5rem;
	font-size: clamp(2.4rem, 1.4rem + 4vw, 4.5rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.v24-step h2 {
	margin-block-start: 0.5rem;
	font-size: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
	font-weight: 600;
	line-height: 1.1;
	letter-spacing: -0.015em;
}

.v24-step p:not(.fh-eyebrow) { margin-block-start: 1rem; font-size: 1.125rem; color: var(--wp--preset--color--muted); }

.v24-step .fh-lede { color: var(--wp--preset--color--ink); }

.v24-sky .fh-pause { bottom: 1rem; right: 1rem; }

/* ---- V25 · 3D logo tile ---- */
.v25-hero {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: clamp(2rem, 6vw, 6rem);
	align-items: center;
}

.v25-words > * { margin-block: 0; }

.v25-scene {
	position: relative;
	display: grid;
	justify-items: center;
	gap: 1.75rem;
	perspective: 1200px;
}

.v25-tile {
	position: relative;
	width: clamp(260px, 34vw, 400px);
	aspect-ratio: 1;
	transform-style: preserve-3d;
	transform: rotateX(var(--rx, 8deg)) rotateY(var(--ry, -14deg));
}

/* The edge: four plates stepping back and darkening, like the logo's tile cut from layered card. */
.v25-plate {
	position: absolute;
	inset: 0;
	border-radius: 26px;
	background: color-mix(in srgb, var(--wp--preset--color--muted) calc(var(--z) * 18%), var(--wp--preset--color--rule));
	transform: translateZ(calc(var(--z) * -7px));
}

.v25-grid {
	position: absolute;
	inset: 0;
	box-sizing: border-box;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 2px;
	overflow: hidden;
	border: 2px solid var(--wp--preset--color--rule);
	border-radius: 26px;
	background: var(--wp--preset--color--rule);
	perspective: 700px;
}

.v25-cell {
	position: relative;
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	font: inherit;
	cursor: pointer;
	transform-style: preserve-3d;
}

.v25-cell:focus-visible { z-index: 1; outline: 3px solid var(--wp--preset--color--link); outline-offset: -3px; }

.v25-cell.is-flipped { transform: rotateY(180deg); }

.v25-face {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	padding: 8%;
	-webkit-backface-visibility: hidden;
	backface-visibility: hidden;
	background: var(--wp--preset--color--surface);
}

.v25-front .fh-sym { width: 56%; height: 56%; color: var(--wp--preset--color--ink); }

/* Dark green on sand: the brand book's badge pairing, 9.3:1. */
.v25-back {
	transform: rotateY(180deg);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ground);
	font: 600 clamp(0.72rem, 0.55rem + 0.45vw, 0.95rem) / 1.2 var(--wp--preset--font-family--display);
	text-align: center;
}

.v25-caption { max-width: 26rem; min-height: 8rem; text-align: center; }

.v25-caption h2 { margin: 0; font-size: 1.375rem; font-weight: 600; line-height: 1.25; }

.v25-caption p { margin: 0.5rem 0 0; color: var(--wp--preset--color--muted); }

.v25-scene .fh-pause { position: static; }

@media (max-width: 48rem) {
	.v20-stage { grid-template-columns: 1fr; align-content: center; }
	.v20-target { order: -1; width: min(60vw, 240px); }
	.v21-stage { height: min(110vw, 64svh); }
	.v24-step { justify-content: flex-end; padding-block-end: 12svh; }
	.v24-step > * { max-width: none; }
	.v25-hero { grid-template-columns: 1fr; }
	.v25-tile { width: min(76vw, 340px); }
}

@media (prefers-reduced-motion: no-preference) {
	.v20-target img { transition: opacity 600ms ease; }
	.v25-tile { transition: transform 500ms cubic-bezier(0.22, 1, 0.36, 1); }
	.v25-cell { transition: transform 700ms cubic-bezier(0.22, 1, 0.36, 1); }
	.v25-caption.is-in { animation: fh-rise 380ms cubic-bezier(0.22, 1, 0.36, 1) both; }
}

@keyframes v14-box { from { background: transparent; } }

@keyframes fh-rise {
	from { opacity: 0; transform: translateY(12px); }
}

/*
 * Variations index (/variations/, patterns/variations.php + fh-variations.js). One card per version:
 * screenshot, code, name, theme tag, idea; under it a row of five squares (1–5 rating) and a clear
 * control; above the grid a sort bar. Squares are --fh-line (3:1+ on both themes), never text.
 */
.fh-page.fh-vx { max-width: 84rem; }
.fh-vx-head { max-width: 46rem; margin-block-end: 2rem; }
.fh-vx-head .fh-mark img { width: 96px; }
.fh-vx-head h1 { margin-block: 0.4rem 0; font-size: clamp(2.2rem, 1.5rem + 3vw, 3.5rem); line-height: 1.05; }

.fh-vx-list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
	gap: 1.75rem 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}
.fh-vx-list > li { display: flex; flex-direction: column; gap: 0.625rem; margin: 0; }
.fh-vx-list > li[hidden] { display: none; }
.fh-vx-card {
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 10px;
	background: var(--wp--preset--color--surface);
	color: inherit;
	text-decoration: none;
	transition: border-color 150ms;
}
.fh-vx-card:hover { border-color: var(--fh-line); }
.fh-vx-card:focus-visible { outline: 2px solid var(--wp--preset--color--link); outline-offset: 3px; }
.fh-vx-shot { margin: 0; aspect-ratio: 16 / 10; border-bottom: 1px solid var(--wp--preset--color--rule); background: var(--wp--preset--color--ground); }
.fh-vx-shot img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top left; }
.fh-vx-body { display: grid; gap: 0.35rem; padding: 1rem 1.15rem 1.25rem; }
.fh-vx-code {
	font: 600 0.8125rem/1 var(--wp--preset--font-family--display);
	letter-spacing: 0.14em;
	color: var(--wp--preset--color--link);
}
.fh-vx-name { font: 700 1.25rem/1.2 var(--wp--preset--font-family--display); }
.fh-vx-tag {
	justify-self: start;
	padding: 0.25rem 0.6rem;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 999px;
	font-size: 0.8125rem;
	color: var(--wp--preset--color--muted);
}
.fh-vx-idea { margin: 0.2rem 0 0; font-size: 0.9375rem; line-height: 1.55; color: var(--wp--preset--color--muted); }

/* Rating row: 44 px targets around 20 px squares. */
.fh-vx-rate {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	padding: 2px 8px 2px 4px;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 10px;
	background: var(--wp--preset--color--surface);
}
.fh-vx-rate[hidden] { display: none; }
.fh-vx-rate [data-n] { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; background: none; cursor: pointer; }
.fh-vx-rate [data-n] span { width: 20px; height: 20px; box-sizing: border-box; border: 2px solid var(--wp--preset--color--muted); }
.fh-vx-rate [data-n].is-on span { background: var(--fh-line); border-color: var(--fh-line); }
.fh-vx-rate [data-n].is-pre span { background: color-mix(in oklab, var(--fh-line) 45%, transparent); border-color: var(--fh-line); }
.fh-vx-rate [data-n]:focus-visible { outline: 2px solid var(--wp--preset--color--link); outline-offset: -5px; border-radius: 8px; }
.fh-vx-rate.is-ro { padding-left: 12px; }
.fh-vx-rate.is-ro [data-n] { width: 26px; cursor: default; }
.fh-vx-rate.is-ro [data-n] span { width: 16px; height: 16px; }
.fh-vx-val { margin-left: 6px; white-space: nowrap; font-size: 0.8125rem; font-weight: 500; color: var(--wp--preset--color--muted); }
.fh-vx-list > li.is-rated .fh-vx-val { color: var(--wp--preset--color--ink); }
.fh-vx-clear {
	margin-left: auto;
	min-height: 44px;
	padding: 0 8px;
	border: 0;
	background: none;
	font: 500 0.8125rem/1 var(--wp--preset--font-family--body);
	color: var(--wp--preset--color--muted);
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}
.fh-vx-clear:hover { color: var(--wp--preset--color--ink); }
.fh-vx-clear[hidden] { display: none; }

/* Sort bar + mode line */
.fh-vx-sort { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 0 0 0.75rem; }
.fh-vx-sort[hidden] { display: none; }
.fh-vx-sort-l {
	margin-right: 4px;
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}
.fh-vx-sort-b {
	min-height: 44px;
	padding: 0 18px;
	border: 1px solid var(--wp--preset--color--rule);
	border-radius: 999px;
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	font: 600 0.875rem/1 var(--wp--preset--font-family--body);
	cursor: pointer;
}
.fh-vx-sort-b:hover { border-color: var(--fh-line); }
.fh-vx-sort-b:focus-visible { outline: 2px solid var(--wp--preset--color--link); outline-offset: 2px; }
.fh-vx-sort-b[aria-pressed="true"] { background: var(--wp--preset--color--ink); border-color: var(--wp--preset--color--ink); color: var(--wp--preset--color--ground); }
.fh-vx-count { margin-left: 6px; font-size: 0.8125rem; color: var(--wp--preset--color--muted); }
.fh-vx-mode { margin: 0 0 1.5rem; font-size: 0.875rem; color: var(--wp--preset--color--muted); }
.fh-vx-mode[hidden] { display: none; }
.fh-vx .fh-note { margin-block-start: 3rem; }

.fh-vx-toast {
	position: fixed;
	left: 50%;
	bottom: 20px;
	z-index: 60;
	max-width: calc(100vw - 32px);
	translate: -50% 12px;
	padding: 12px 18px;
	border-radius: 10px;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--ground);
	font: 600 0.875rem/1.3 var(--wp--preset--font-family--body);
	box-shadow: 0 12px 30px color-mix(in oklab, #000 25%, transparent);
	opacity: 0;
}
.fh-vx-toast.is-on { opacity: 1; translate: -50% 0; }
.fh-vx-toast.is-bad { background: var(--wp--preset--color--link); color: var(--wp--preset--color--ground); }

@media (prefers-reduced-motion: no-preference) {
	.fh-vx-card { transition: border-color 150ms, transform 150ms; }
	.fh-vx-card:hover { transform: translateY(-2px); }
	.fh-vx-rate [data-n] span { transition: background 180ms, border-color 180ms, transform 250ms cubic-bezier(0.2, 0.9, 0.25, 1); }
	.fh-vx-rate [data-n].is-pre span { transform: scale(1.1); }
	.fh-vx-rate:not(.is-ro) [data-n]:active span { transform: scale(0.88); }
	.fh-vx-rate.is-pop [data-n].is-on span { animation: fh-vx-pop 450ms cubic-bezier(0.2, 0.9, 0.25, 1); }
	.fh-vx-sort-b { transition: background 200ms, border-color 200ms, color 200ms; }
	.fh-vx-toast { transition: opacity 250ms, translate 300ms cubic-bezier(0.2, 0.9, 0.25, 1); }
}

@keyframes fh-vx-pop { 45% { transform: scale(1.28); } }

/*
 * ---- V26 · Settle to solid / V27 · Ink sets ----
 * V20's layout, one module in fh-gen.js, two endings from data-finish (Jerry, 2026-09-15). The layout
 * rules repeat V20's rather than sharing a selector with it: V20 is the page he picked, and nothing here
 * may change how it renders. --v26-set (0→1, written by the script) hands the mark from the canvas to
 * the real logo: opacity for "fade", a left-to-right clip wipe for "wipe". Without the script the logo
 * is simply solid (no .is-live), which is also the no-script and reduced-motion state.
 */
.v26-stage { --gutter: max(clamp(1.25rem, 5vw, 3rem), calc((100% - 70rem) / 2)); }

.v26-stage {
	position: relative;
	box-sizing: border-box;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: clamp(2rem, 6vw, 6rem);
	align-items: center;
	min-height: 100svh;
	padding: clamp(2rem, 6vw, 5rem) var(--gutter);
	overflow: hidden;
}

.v26-canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
}

.v26-words { position: relative; z-index: 1; }

.v26-words > * { margin-block: 0; }

.v26-words h1 {
	max-width: 12ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.6rem, 1.4rem + 4.6vw, 5rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.v26-words .fh-eyebrow { margin-block-start: 0; }

.v26-words .fh-lede { margin-block-start: 1.25rem; }

.v26-target { position: relative; margin: 0; width: clamp(220px, 30vw, 380px); aspect-ratio: 1; }

.v26-target .fh-mark img { width: 100%; height: 100%; }

/* V26: the logo fades up as the dust dissolves. */
.v26-stage.is-live .v26-target img { opacity: var(--v26-set, 0); }

/* V27: the logo is opaque from the start but clipped; the wipe uncovers it left to right. */
.v26-stage[data-finish="wipe"].is-live .v26-target img {
	opacity: 1;
	clip-path: inset(0 calc(100% - (var(--v26-set, 0) * 100%)) 0 0);
}

.v26-close { padding-block-start: 0; }

@media (max-width: 48rem) {
	.v26-stage { grid-template-columns: 1fr; align-content: center; }
	.v26-target { order: -1; width: min(60vw, 240px); }
}

/*
 * ---- V28 · Waveform to mark ----
 * V20's stage on V21's plot (Jerry, 2026-09-15): the canvas carries both the signal lines and the dust
 * they shed, and --v28-set hands the finished mark to the page's real logo. Always Twilight (.fh-dark on
 * the group). Without the script the logo is simply solid, which is also the reduced-motion state.
 */
.v28-stage {
	--gutter: max(clamp(1.25rem, 5vw, 3rem), calc((100% - 70rem) / 2));
	position: relative;
	box-sizing: border-box;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: clamp(2rem, 6vw, 6rem);
	align-items: center;
	min-height: 100svh;
	padding: clamp(2rem, 6vw, 5rem) var(--gutter);
	overflow: hidden;
}

.v28-canvas {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	pointer-events: none;
}

.v28-words { position: relative; z-index: 1; }

.v28-words > * { margin-block: 0; }

.v28-words h1 {
	max-width: 12ch;
	margin-block-start: 0.5rem;
	font-size: clamp(2.6rem, 1.4rem + 4.6vw, 5rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.v28-words .fh-eyebrow { margin-block-start: 0; }

.v28-words .fh-lede { margin-block-start: 1.25rem; }

.v28-target { position: relative; margin: 0; width: clamp(220px, 30vw, 380px); aspect-ratio: 1; }

.v28-target .fh-mark img { width: 100%; height: 100%; }

.v28-stage.is-live .v28-target img { opacity: var(--v28-set, 0); }

.v28-close { padding-block-start: 0; }

@media (max-width: 48rem) {
	.v28-stage { grid-template-columns: 1fr; align-content: center; }
	.v28-target { order: -1; width: min(60vw, 240px); }
}
