/**
 * Fruit Warrior design system.
 *
 * 01 Fonts            self-hosted Figtree (body) + Bricolage Grotesque (display)
 * 02 Tokens           brand palette, spacing, radius, shadows
 * 03 Base             typography, layout primitives, Astra unboxing
 * 04 Buttons & forms
 * 05 Header           nav, actions, mobile nav, search overlay
 * 06 Mini cart drawer
 * 07 Footer
 * 08 Sections         page hero, section heading, CTA banner
 * 09 Components       cards, process loop, enzyme cards,
 *                     accordion, stats, split sections, product stage
 * 10 Landing page content islands
 * 11 Utilities & motion
 */

/* == 01 Fonts ========================================================== */

@font-face {
	font-family: 'Figtree';
	font-style: normal;
	font-weight: 300 900;
	font-display: swap;
	src: url('../fonts/figtree-latin.woff2') format('woff2');
}

@font-face {
	font-family: 'Figtree';
	font-style: italic;
	font-weight: 300 900;
	font-display: swap;
	src: url('../fonts/figtree-italic-latin.woff2') format('woff2');
}

@font-face {
	font-family: 'Bricolage Grotesque';
	font-style: normal;
	font-weight: 200 800;
	font-display: swap;
	src: url('../fonts/bricolage-grotesque-latin.woff2') format('woff2');
}

/* == 02 Tokens ========================================================= */

/* One palette only: opts out of the automatic dark mode of phone browsers,
   which otherwise recolours the cream islands and the consent banner. The
   same value is set as <meta name="color-scheme"> in header.php. */
:root {
	color-scheme: only light;
}

:root {
	/* Canonical corporate palette (see CLAUDE.md). */
	--fw-cream: #fcedc5;
	--fw-yellow-300: #fbe282;
	--fw-yellow-500: #f9ca12;
	--fw-orange-400: #f3ae4a;
	--fw-baby-blue: #00b8e8; /* Text/accent only since the 2026 refresh. */
	--fw-green-200: #b5c994;
	--fw-green-500: #6b9845;
	--fw-green-600: #4b7832;
	--fw-green-700: #3e5928;
	--fw-green-800: #3e5928;
	--fw-green-900: #3e5928;
	--fw-grey: #645a5a;
	--fw-brown-violet: #5f4647;
	--fw-red-700: #5a2d2d;
	--fw-dark-brown: #42230a;

	/* 2026 refresh: one dark ground carrying one container surface.
	   --fw-surface is a FILL and --fw-on-dark an INK; they were briefly the
	   same value, but the container moved to the warmer cream while text on
	   dark stayed off-white, so keep the two roles apart. */
	--fw-ground: #3e5928;
	--fw-surface: #faedc8;
	--fw-on-dark: #efede4;
	--fw-ink: #5f4647;
	--fw-ink-soft: var(--fw-grey);
	--fw-paper: var(--fw-surface);

	/* Product line surfaces. The bright baby blue is no longer a fill. */
	--fw-home-wash: #fcedc5;
	--fw-baby-wash: #a9edff;
	--fw-set-wash: #fdf1c9; /* Launch sets: the warm light of the set photographs. */

	/* The six product label pairs are NOT tokens here on purpose. They are
	   keyed by SKU in template-parts/sections/product-showcase.php, which
	   also has to ship them as JSON for the stage animation — one source of
	   truth beats a CSS copy that can silently drift out of step. The stage
	   feeds them in as --fw-stage-label / --fw-tab-label. */

	/* Hairlines drawn in the ink, for the many ruled lists that used to sit
	   on dark panels and now sit on the container surface. */
	--fw-rule: rgba(95, 70, 71, 0.34);
	--fw-rule-soft: rgba(95, 70, 71, 0.18);

	/* Semantic */
	--fw-bg: var(--fw-ground);
	--fw-text: var(--fw-ink);
	--fw-text-soft: var(--fw-ink-soft);
	/* Headings carry the corporate deep green again; body copy stays the
	   brown-violet ink. Dark bands override this to --fw-on-dark, otherwise
	   the heading green and the page ground are the same colour. */
	--fw-heading: var(--fw-green-700);
	--fw-accent: var(--fw-yellow-500);
	--fw-link: var(--fw-green-700);
	/* Selected text: one mid green that stands out from the cream surfaces
	   (2.8:1) and from the deep green ground (2.3:1), with white type on it
	   (3.4:1). See the ::selection rule in Base. */
	--fw-selection-bg: var(--fw-green-500);
	--fw-selection-ink: #fff;

	/* Type */
	--fw-font-body: 'Figtree', ui-sans-serif, system-ui, sans-serif;
	--fw-font-display: 'Bricolage Grotesque', 'Figtree', ui-sans-serif, system-ui, sans-serif;

	/* Layout */
	--fw-container: 74rem;
	--fw-gutter: clamp(1.25rem, 4vw, 2.5rem);
	/* Science page: one measure for the hero and every island, one inset from
	   the viewport edge, and the island's inner text measure for whatever sits
	   directly on the ground (ferment stage, game card). Two flush lines. */
	--fw-science-measure: 112rem;
	--fw-science-inset: clamp(1.5rem, 4vw, 4rem);
	--fw-science-island-pad: clamp(2.5rem, 5vw, 6rem);
	--fw-science-content: calc(min(var(--fw-science-measure), 100vw - var(--fw-science-inset)) - 2 * var(--fw-science-island-pad));
	--fw-section-pad: clamp(4rem, 9vw, 7.5rem);
	--fw-header-h: 4.5rem;
	/* What a hero must keep clear at the top: the fixed header, plus the
	   notice bar where it lies over the hero (05a). */
	--fw-header-clear: var(--fw-header-h);

	/* Shape */
	--fw-radius-s: 10px;
	--fw-radius-m: 18px;
	--fw-radius-l: 28px;
	--fw-shadow-s: 0 2px 10px rgba(66, 35, 10, 0.07);
	--fw-shadow-m: 0 14px 40px -12px rgba(66, 35, 10, 0.18);

	--fw-ease: cubic-bezier(0.33, 1, 0.68, 1);
}

/* == 03 Base =========================================================== */

/* Selected text must always show (owner, 2026-10-05: on many texts, the legal
   pages included, marking with the mouse showed nothing). Astra paints
   ::selection in its theme colour, which matched the cream surfaces. One mid
   green works on cream and on the deep green ground alike, so no section has
   to opt in; :root raises the rule above Astra's bare ::selection.
   audit-selection.mjs checks every text element on every page. */
:root ::selection {
	background-color: var(--fw-selection-bg);
	color: var(--fw-selection-ink);
}

/* Two kinds of fill the mid green disappears on. The product label colours
   (stage chip and active selector row, purple to pale yellow) all stand
   clear of a very deep ink; the names on the That's Us portraits sit on a
   dark scrim over the photograph, where the yellow accent shows. */
.fw-stage__label-chip,
.fw-stage__tab.is-active {
	--fw-selection-bg: #2b2021;
	--fw-selection-ink: #fff;
}

.fw-us-orbit__photo {
	--fw-selection-bg: var(--fw-accent);
	--fw-selection-ink: var(--fw-ground);
}

/* No tap flash anywhere (owner, 2026-09-25): mobile Chrome paints every tapped
   link or button with a translucent blue box (rgba(51, 181, 229, .4)), and a
   whole-card link like a newsroom card lit up entirely. The property is
   inherited, so this one declaration covers every element. Keyboard focus
   keeps its visible ring (:focus-visible below). */
html {
	-webkit-tap-highlight-color: transparent;
}

body {
	background: var(--fw-bg);
	color: var(--fw-text);
	font-family: var(--fw-font-body);
	font-size: 1.0625rem;
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
}

/* Astra paints the page background through a body-CLASS rule
   (.ast-plain-container et al., specificity 0-1-0), which outranks a bare
   `body` selector no matter how late our stylesheet loads. Match its
   container classes so the ground stays ours on every Astra layout. */
body.ast-plain-container,
body.ast-separate-container,
body.ast-narrow-container,
body.ast-page-builder-template {
	background: var(--fw-bg);
}

/* Same story one level down: Astra's article wrapper is its own white card. */
.ast-separate-container .ast-article-inner,
.ast-separate-container .ast-article-post,
.ast-separate-container .ast-comment-list li.depth-1 {
	background: transparent;
}

h1, h2, h3, h4, h5, h6 {
	font-family: var(--fw-font-display);
	color: var(--fw-heading);
	font-weight: 640;
	line-height: 1.12;
	letter-spacing: -0.015em;
	text-wrap: balance;
}

/* Astra colours headings through `.entry-content :where(h1…h6)`. The :where()
   contributes nothing but `.entry-content` does, so that rule is 0-1-0 and
   outranks the bare h1–h6 above on every boxed page — which is why cart,
   checkout and the product detail kept Astra's slate instead of our green.
   One extra element wins it back without outranking component rules. */
.entry-content :is(h1, h2, h3, h4, h5, h6) {
	color: var(--fw-heading);
}

a {
	color: var(--fw-link);
}

a:hover {
	color: var(--fw-green-700);
}

::selection {
	background: var(--fw-surface);
	color: var(--fw-ink);
}

:where(a, button, input, [tabindex]):focus-visible {
	outline: 3px solid var(--fw-green-500);
	outline-offset: 2px;
	border-radius: 4px;
}

.fw-container {
	max-width: var(--fw-container);
	margin-inline: auto;
	padding-inline: var(--fw-gutter);
}

/* Our overlays/drawers set display values that would beat the UA's
   [hidden] rule – restore expected semantics. */
[hidden] {
	display: none !important;
}

/* Unbox Astra's container on full-bleed templates (Astra uses a flex
   container, which would lay our stacked sections out as columns). */
.fw-fullbleed .site-content .ast-container {
	display: block;
	max-width: none;
	padding: 0;
}

.fw-fullbleed #content {
	padding: 0;
}

/* Boxed pages (legal, account, cart, checkout, single product …) get a
   comfortable width. Since the page ground is dark, the content area is
   itself the container surface — without this the default ink would sit
   on dark green. */
body:not(.fw-fullbleed) #content .ast-container {
	max-width: var(--fw-container);
	padding: clamp(2rem, 4vw, 3.5rem) var(--fw-gutter);
	margin-block: clamp(1.25rem, 2.5vw, 2.5rem);
	background: var(--fw-surface);
	border-radius: clamp(1.4rem, 2.5vw, 2.5rem);
}

img {
	max-width: 100%;
	height: auto;
}

/* == 04 Buttons & forms =============================================== */

.fw-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	padding: 0.85rem 1.75rem;
	border-radius: 999px;
	font-family: var(--fw-font-body);
	font-weight: 700;
	font-size: 1rem;
	line-height: 1.2;
	text-decoration: none;
	border: 2px solid transparent;
	cursor: pointer;
	transition: transform 0.25s var(--fw-ease), box-shadow 0.25s var(--fw-ease), background-color 0.25s, color 0.25s, border-color 0.25s;
}

.fw-btn:hover {
	transform: translateY(-2px);
	box-shadow: var(--fw-shadow-m);
}

.fw-btn:active {
	transform: translateY(0);
}

/* Each variant restates its resting colours for :focus: Astra's inlined
   `button:focus, button:hover` (0-1-1) fills any <button> blue with white
   text, and a tap leaves a button focused (see design-system.md). Hover
   rules follow, so a real hover still wins. */
.fw-btn--primary,
.fw-btn--primary:focus {
	background: var(--fw-yellow-500);
	color: var(--fw-ink);
}

.fw-btn--primary:hover {
	background: var(--fw-orange-400);
	color: var(--fw-ink);
}

.fw-btn--secondary,
.fw-btn--secondary:focus {
	background: var(--fw-green-700);
	color: var(--fw-on-dark);
}

.fw-btn--secondary:hover {
	background: var(--fw-green-800);
	color: #fff;
}

/* Ghost has no hover colour of its own, so hover is restated too. */
.fw-btn--ghost,
.fw-btn--ghost:is(:hover, :focus) {
	border-color: currentColor;
	color: var(--fw-green-700);
	background: transparent;
}

.fw-btn--light,
.fw-btn--light:focus {
	background: var(--fw-surface);
	color: var(--fw-text);
}

.fw-btn--light:hover {
	background: var(--fw-surface);
	color: var(--fw-green-900);
}

/* Cream outline for dark surfaces — the counterpart to --ghost, which is
   green and therefore invisible on the ground. Used for the hero's three
   subordinate destinations beside the yellow primary.

   The faint fill and the blur are not decoration: this button sits on moving
   video, where a bright frame can pass behind it and swallow a plain outline.
   The fill keeps a floor under the text no matter what the video does. */
.fw-btn--outline-light,
.fw-btn--outline-light:focus {
	border-color: var(--fw-on-dark);
	color: var(--fw-on-dark);
	background: rgba(239, 237, 228, 0.12);
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
}

.fw-btn--outline-light:hover,
.fw-btn--outline-light:focus-visible {
	background: var(--fw-on-dark);
	color: var(--fw-green-900);
	border-color: var(--fw-on-dark);
}

.fw-btn--small {
	padding: 0.55rem 1.15rem;
	font-size: 0.9rem;
}

input[type='text'],
input[type='email'],
input[type='search'],
input[type='tel'],
input[type='number'],
input[type='password'],
select,
textarea {
	border: 1.5px solid var(--fw-green-200);
	border-radius: var(--fw-radius-s);
	background: #fff;
	color: var(--fw-text);
	padding: 0.7rem 1rem;
	font-family: inherit;
	font-size: 1rem;
}

input:focus,
select:focus,
textarea:focus {
	border-color: var(--fw-green-500);
	outline: none;
	box-shadow: 0 0 0 3px rgba(107, 152, 69, 0.2);
}

/* == 05a Notice bar ===================================================== */

/* A slim yellow ticker above the header (inc/notice-bar.php, owner
   2026-10-16). It is a strip of its own, never laid over a hero: the heroes
   that fill the screen are shorter by its height (--fw-notice-space), so
   they still end at the bottom edge. It scrolls away with the page; on
   hero templates the fixed header starts below it (--fw-notice-offset, kept
   by main.js while scrolling). Not on the Circle film, and gone once
   closed until its messages change. */
:root {
	--fw-notice-space: 0px;
}

.fw-has-notice {
	--fw-notice-h: 1.75rem;
	--fw-notice-space: var(--fw-notice-h);
	--fw-notice-offset: var(--fw-notice-h);
}

.fw-notice {
	position: relative;
	z-index: 91;
	display: flex;
	align-items: center;
	height: var(--fw-notice-h);
	background: var(--fw-yellow-500);
	color: var(--fw-heading);
	font-size: 0.8rem;
	line-height: 1;
	font-weight: 600;
}

.fw-header-overlay.fw-has-notice .fw-header {
	top: var(--fw-notice-offset);
}

/* A small round close button at the right end. */
.fw-notice__close {
	display: grid;
	flex: 0 0 auto;
	place-items: center;
	width: 1.15rem;
	height: 1.15rem;
	margin: 0 0.6rem;
	padding: 0;
	border: 1.5px solid currentColor;
	border-radius: 50%;
	background: transparent;
	color: var(--fw-heading);
	cursor: pointer;
}

/* Restated: Astra paints a focused or hovered <button> blue. */
.fw-notice__close:is(:hover, :focus, :active) {
	background: var(--fw-heading);
	color: var(--fw-yellow-500);
	border-color: var(--fw-heading);
}

.fw-notice__close:focus-visible {
	outline: 2px solid var(--fw-heading);
	outline-offset: 2px;
}

.fw-notice__viewport {
	flex: 1;
	min-width: 0;
	overflow: hidden;
}

/* Two identical halves; moving the track by one half loops without a seam.
   Direction: left to right (owner). */
.fw-notice__track {
	display: flex;
	width: max-content;
	height: 100%;
	animation: fw-notice-run 70s linear infinite;
}

@keyframes fw-notice-run {
	from {
		transform: translateX(-50%);
	}

	to {
		transform: translateX(0);
	}
}

/* Hovering or tabbing into the bar holds it still so a link can be hit.
   Keyboard focus only: a clicked link keeps mouse focus after the back
   button (back/forward cache), and :focus-within would freeze the bar. */
.fw-notice:hover .fw-notice__track,
.fw-notice:has(.fw-notice__link:focus-visible) .fw-notice__track {
	animation-play-state: paused;
}

.fw-notice__list {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	margin: 0;
	padding: 0;
	list-style: none;
}

.fw-notice__item {
	display: flex;
	align-items: center;
	margin: 0;
	/* Wide, empty gaps keep about one message per screen third in view
	   (owner, 2026-10-16: not too many at once, no separators). main.js
	   sets the duration from the track width, so the speed stays the same
	   at every screen width. */
	padding-inline: clamp(6rem, 22vw, 26rem);
}

/* Every link state restated: Astra colours a focused or visited link blue,
   which stayed on the link after clicking it and coming back. */
.fw-notice__link,
.fw-notice__link:is(:focus, :active, :visited) {
	color: inherit;
	text-decoration: none;
	white-space: nowrap;
	outline: none;
}

.fw-notice__link:hover {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.fw-notice__link:focus-visible {
	outline: 2px solid var(--fw-heading);
	outline-offset: 2px;
}

/* Without motion the messages stand still, once, centred. */
@media (prefers-reduced-motion: reduce) {
	.fw-notice__track {
		width: 100%;
		justify-content: center;
		animation: none;
	}

	.fw-notice__list[aria-hidden='true'],
	.fw-notice__item[aria-hidden='true'] {
		display: none;
	}

	.fw-notice__item {
		padding-inline: clamp(1.5rem, 4vw, 4rem);
	}
}

/* == 05 Header ========================================================= */

.fw-header {
	position: sticky;
	top: 0;
	z-index: 90;
	transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Slides out when scrolling down, back in when scrolling up (main.js). */
.fw-header.is-hidden {
	transform: translateY(-100%);
}

/* The panel is measured when it opens. A header still sliding into view
   would give fitMobileNav() a transient top edge and too much height. */
.fw-header:has(.fw-mobile-nav:not([hidden])) {
	transform: none;
	transition: none;
}

/* Hero templates: header floats over the hero instead of pushing it down. */
.fw-header-overlay .fw-header {
	position: fixed;
	left: 0;
	right: 0;
}

.fw-header-overlay .fw-page-hero {
	padding-top: calc(clamp(4.5rem, 10vw, 8rem) + var(--fw-header-clear));
}

.fw-header__bar {
	/* Derived from the container token so it cannot drift out of step with it
	   again; the rgba above is the literal fallback for older engines. */
	background: rgba(250, 237, 200, 0.92);
	background: color-mix(in srgb, var(--fw-surface) 92%, transparent);
	-webkit-backdrop-filter: blur(12px);
	backdrop-filter: blur(12px);
	border-bottom: 1px solid var(--fw-rule-soft);
	transition: box-shadow 0.3s, background-color 0.65s var(--fw-ease), border-color 0.65s var(--fw-ease), -webkit-backdrop-filter 0.65s var(--fw-ease), backdrop-filter 0.65s var(--fw-ease);
}

.fw-header.is-scrolled .fw-header__bar {
	box-shadow: var(--fw-shadow-s);
}

/* Transparent at the very top of hero pages (declared after .is-scrolled so
   it wins in the 8–40 px overlap zone). */
.fw-header.is-transparent .fw-header__bar {
	background: transparent;
	-webkit-backdrop-filter: none;
	backdrop-filter: none;
	border-bottom-color: transparent;
	box-shadow: none;
}

/* Only top-level nav links go cream — dropdown panels stay white with
   dark links, so they remain readable over the transparent header. */
.fw-header.is-transparent .fw-nav__list > li > a,
.fw-header.is-transparent .fw-icon-btn,
.fw-header.is-transparent .fw-nav-toggle {
	color: var(--fw-on-dark);
}

.fw-header.is-transparent .fw-nav__list > li > a:hover {
	background: rgba(255, 255, 255, 0.16);
	color: var(--fw-on-dark);
}

.fw-header.is-transparent .fw-logo img {
	filter: brightness(0) invert(1);
}

.fw-logo img,
.fw-nav-toggle {
	transition: filter 0.65s var(--fw-ease), color 0.45s var(--fw-ease);
}

.fw-nav__list > li > a {
	transition: background-color 0.2s, color 0.45s var(--fw-ease);
}

@media (prefers-reduced-motion: reduce) {
	.fw-header,
	.fw-header__bar,
	.fw-logo img {
		transition: none;
	}
}

/* Three zones: logo hard left, nav centred, actions hard right.

   The bar deliberately opts out of the container's 74 rem cap (it still keeps
   its gutter), so on a wide screen the logo really does sit at the left edge
   instead of floating in a centred column. Everything else on the site stays
   inside the container — this is the one full-width row.

   The 1fr/auto/1fr grid is what actually centres the nav. As a flex row it was
   only centred *between* logo and actions, so it drifted right whenever those
   two differed in width — which they always do. The two 1fr tracks are equal
   by definition, so the middle track lands on the true centre; their automatic
   min-content floor still lets logo and actions claim the room they need. */
.fw-header__inner {
	max-width: none;
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 1.25rem;
	min-height: var(--fw-header-h);
}

.fw-header__inner > .fw-logo {
	justify-self: start;
}

.fw-header__inner > .fw-header__actions {
	justify-self: end;
}


.fw-logo img {
	display: block;
	width: auto;
	height: 3.4rem;
}

/* Header lockup: pineapple mark left, wordmark right (see fw_the_logo()).
   The two halves are sized independently and deliberately NOT in the 2:1
   proportion of the stacked original — at header scale the wordmark needs the
   extra height to stay readable, which is the whole reason for the split.

   The mark is the taller of the two by design (owner decision): its crown is
   roughly a quarter of its height and made of fine spikes, which smear into a
   vertical streak at small sizes and make the silhouette look stretched. The
   mark's aspect is not in fact wrong — it measures 0.58195 in the theme logo,
   0.58173 in content/logo/Logo_transparent.svg and 0.58346 in the original
   raster, i.e. identical within JPEG edge noise. Size is the only lever, so
   the mark takes the full header height it can get.

   Keep both on --fw-logo-h so the pair can shrink together at one place. */
.fw-logo--header {
	--fw-logo-h: 3.5rem;
	display: flex;
	align-items: center;
	gap: 0.65rem;
}

.fw-logo--header .fw-logo__mark {
	height: var(--fw-logo-h);
}

.fw-logo--header .fw-logo__wordmark {
	height: calc(var(--fw-logo-h) * 0.54);
}

.fw-logo--footer img {
	height: 4.5rem;
}

/* First-visit intro overlay (logo portal).
   The logo SVG doubles as an alpha mask layer that, composited with
   mask-composite: exclude against a solid layer, punches a logo-shaped
   hole into the overlay; animations.js grows that hole ("portal").
   mask-size 0 0 keeps the hole closed until the portal phase. */
.fw-intro {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: grid;
	place-items: center;
	background: var(--fw-surface);
}

/* An unmaskable beige layer directly behind the overlay, present for as
   long as the overlay is (template-parts/intro.php adds the class pre-paint
   and the portal removes it). A masked element renders see-through in two
   moments — while its mask image is still loading, and in the frame the
   browser first builds a compositing layer for it — and both flashed the
   hero: the first on every cold load (2026-09-22), the second on a phone at
   the instant the portal began (2026-09-23). This covers both, which is why
   the fix is structural rather than another attempt at better timing. */
.fw-intro-active::before {
	content: "";
	position: fixed;
	inset: 0;
	z-index: 99999;
	background: var(--fw-surface);
}

/* The consent banner waits for the intro (2026-10-05). It shares the
   overlay's z-index and its cream, so on a phone it showed through the
   transparent logo instead of the hero and flattened the fly-in. intro.php
   sets the class pre-paint, animations.js (finish) and the intro safety net
   lift it once the overlay is gone; the banner then rises in. visibility
   keeps it out of the tab order and the hit test while it waits. */
.fw-consent__banner {
	transition: opacity 0.5s ease, transform 0.5s ease;
}

.fw-consent-held .fw-consent__banner {
	visibility: hidden;
	opacity: 0;
	transform: translateY(1.5rem);
	transition: none;
}

@media (prefers-reduced-motion: reduce) {
	.fw-consent__banner {
		transition: none;
	}
}

/* A repeat visit skips the overlay, so nothing covers the hero while the
   deferred animations.js loads: its copy used to paint, vanish into GSAP's
   from-state and fade in again (2026-09-23). intro.php sets the class
   pre-paint, animations.js lifts it once GSAP holds the start state. */
/* Every page: what animations.js fades in stays hidden from the first paint
   until GSAP holds its start state (owner, 2026-10-05: the copy painted,
   vanished and came back on Science, That's Us, FAQ, Contact, the shop and
   more). inc/enqueue.php sets the class pre-paint, animations.js lifts it.
   Keep the list in step with the targets animations.js hides on load. */
.fw-motion-pending :is(.fw-reveal, .fw-grid > .fw-card, .fw-process__step, ul.products > li.product, [data-fw-us-letter-line], [data-fw-us-manifest-line], [data-fw-us-manifest-call], [data-fw-us-manifest-item]),
.fw-motion-pending:not(.fw-resumed):not(.fw-hero-css) .fw-hero-stagger {
	visibility: hidden;
}

/* Hero entrance in CSS on every page without the intro (2026-10-13). The
   GSAP entrance could only start once the deferred scripts had run, so the
   hero copy and the Science picture waited for them, 2 to 3 s on a slow
   phone. This is the same motion (GSAP's values: autoAlpha 0 → 1, y 34px,
   0.9s, power3.out = easeOutQuart, 0.15s delay, 0.12s stagger in document
   order via --fw-i from fw_hero_stagger_style()), but it starts with the
   first paint. html.fw-hero-css comes from the pre-paint script
   (fw_motion_pending(), never under Reduced Motion, never on the landing
   page, whose hero waits for the intro and keeps GSAP); a calm consent
   reload (fw-resumed) shows the copy without an entrance, as before.
   Fill mode backwards only: the start state holds through the delay, and
   nothing stays applied once the entrance is over. */
@keyframes fw-hero-in {
	from {
		visibility: hidden;
		opacity: 0;
		transform: translateY(34px);
	}
}

.fw-hero-css:not(.fw-resumed) .fw-hero-stagger {
	animation: fw-hero-in 0.9s cubic-bezier(0.165, 0.84, 0.44, 1) calc(0.15s + var(--fw-i, 0) * 0.12s) backwards;
	/* power3.out exactly (1 - (1 - t)^4, 25 points); browsers without
	   linear() keep the cubic-bezier approximation above. */
	animation-timing-function: linear(0 0%, 0.1565 4.17%, 0.2939 8.33%, 0.4138 12.5%, 0.5177 16.67%, 0.6072 20.83%, 0.6836 25%, 0.7483 29.17%, 0.8025 33.33%, 0.8474 37.5%, 0.8842 41.67%, 0.9139 45.83%, 0.9375 50%, 0.9559 54.17%, 0.9699 58.33%, 0.9802 62.5%, 0.9877 66.67%, 0.9928 70.83%, 0.9961 75%, 0.9981 79.17%, 0.9992 83.33%, 0.9998 87.5%, 1 91.67%, 1 100%);
}

.fw-hero-pending .fw-hero-stagger {
	visibility: hidden;
}

/* The mask goes on as soon as its file is decoded, which is well before the
   portal and well after first paint — never at either. Applied here the hole
   is zero-sized, so the overlay looks exactly the same; what it buys is that
   the layer is built and painted while the backdrop is still covering, so
   opening the hole later creates nothing new. */
.fw-intro.is-maskable {
	-webkit-mask-image: url(../img/fruit-warrior-logo.svg), linear-gradient(#fff, #fff);
	-webkit-mask-repeat: no-repeat;
	-webkit-mask-position: center;
	-webkit-mask-size: 0 0, 100% 100%;
	-webkit-mask-composite: destination-out;
	mask-image: url(../img/fruit-warrior-logo.svg), linear-gradient(#fff, #fff);
	mask-repeat: no-repeat;
	mask-position: center;
	mask-size: 0 0, 100% 100%;
	mask-composite: exclude;
}

/* The logo is painted with the overlay itself, not revealed by JavaScript.
   It used to start hidden so GSAP could fly its paths together, but the
   scripts are deferred: that left almost a second of empty beige before the
   logo appeared (measured 942 ms on a throttled load, 2026-09-22) and the
   assembly then fought the loading state the owner asked for. The still
   frame is now the first thing painted, and the intro animation is the
   charge-up plus the portal. */
.fw-intro svg {
	height: min(30vmin, 20rem);
	width: auto;
}

/* Loading bar under the logo. Positioned from the centre rather than placed
   in the grid, so the logo stays on the element's centre where the mask hole
   is (see the comment in template-parts/intro.php). The offset is half the
   logo height plus a gap, which keeps it a fixed distance below the mark at
   every viewport because it repeats the svg's own clamp. */
.fw-intro__progress {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, calc(min(15vmin, 10rem) + 3.25rem));
	width: min(48vw, 12rem);
	height: 3px;
	border-radius: 999px;
	background: rgba(62, 89, 40, 0.16);
	overflow: hidden;
	/* Painted with the overlay, like the logo. The overlay only exists on the
	   first view of a session, which is exactly the view that has something
	   to load, so there is no case where an empty bar would sit there for
	   nothing. */
	transition: opacity 0.2s var(--fw-ease);
}

/* The percentage under the bar, on the same centre line. Absolutely
   positioned for the same reason as the bar: the logo has to stay on the
   element's centre, where the portal's mask hole is. */
.fw-intro__progress-value {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, calc(min(15vmin, 10rem) + 4.6rem));
	margin: 0;
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	color: rgba(62, 89, 40, 0.6);
	/* Fixed-width digits, so counting up cannot make the label twitch. */
	font-variant-numeric: tabular-nums;
	transition: opacity 0.2s var(--fw-ease);
}

/* Both faded out as the portal starts, so they are gone before the mask
   opens and the hole starts eating the overlay. */
.fw-intro.is-portal .fw-intro__progress,
.fw-intro.is-portal .fw-intro__progress-value {
	opacity: 0;
}

.fw-intro__progress-fill {
	display: block;
	height: 100%;
	width: 100%;
	border-radius: inherit;
	background: var(--fw-ground);
	transform: scaleX(0);
	transform-origin: left center;
	/* Transform only — the bar must not lay out or paint the page while the
	   first clip is downloading. There is deliberately no transition here:
	   main.js eases one shared value and renders the bar and the percentage
	   from it, so a CSS transition would ease the same motion a second time
	   and make the two readouts disagree. Reduced Motion is handled there
	   too, by snapping instead of walking. */
}

/* Primary nav */
.fw-nav {
	margin-inline: auto;
}

.fw-nav__list {
	display: flex;
	gap: 0.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.fw-nav__list a {
	display: block;
	padding: 0.6rem 0.9rem;
	color: var(--fw-ink);
	font-weight: 650;
	font-size: 0.98rem;
	text-decoration: none;
	border-radius: 999px;
	transition: background-color 0.2s, color 0.2s;
}

.fw-nav__list > li.current-menu-item > a,
.fw-nav__list > li.current-menu-ancestor > a {
	color: var(--fw-green-700);
}

.fw-nav__list a:hover {
	background: var(--fw-surface);
	color: var(--fw-text);
}

.fw-nav__list li {
	position: relative;
}

.fw-nav__list .sub-menu {
	position: absolute;
	top: calc(100% + 0.4rem);
	left: 0;
	min-width: 15rem;
	background: var(--fw-surface);
	border-radius: var(--fw-radius-m);
	box-shadow: var(--fw-shadow-m);
	padding: 0.5rem;
	list-style: none;
	margin: 0;
	opacity: 0;
	visibility: hidden;
	transform: translateY(8px);
	transition: opacity 0.22s var(--fw-ease), transform 0.22s var(--fw-ease), visibility 0.22s;
}

.fw-nav__list li:hover > .sub-menu,
.fw-nav__list li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

.fw-nav__list .sub-menu a {
	border-radius: var(--fw-radius-s);
	padding: 0.55rem 0.8rem;
}

/* Header actions */
.fw-header__actions {
	display: flex;
	align-items: center;
	gap: 0.35rem;
}

.fw-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.6rem;
	height: 2.6rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--fw-ink);
	cursor: pointer;
	position: relative;
	transition: background-color 0.2s;
}

/* Astra fills a focused <button> blue. A tap leaves the search and cart
   toggles focused (the drawer and overlay also return focus to them), so
   the states are restated and the cream fill is kept for real hover. */
.fw-icon-btn:is(:hover, :focus, :active) {
	border-color: transparent;
	background: transparent;
	color: var(--fw-ink);
	outline: 0;
}

.fw-header.is-transparent .fw-icon-btn:is(:hover, :focus, :active) {
	color: var(--fw-on-dark);
}

.fw-icon-btn:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

@media (hover: hover) {
	.fw-icon-btn:hover,
	.fw-header.is-transparent .fw-icon-btn:hover {
		background: var(--fw-surface);
		color: var(--fw-text);
	}
}

/* Language switcher (2026-10-06): two text codes, the current one bold and
   underlined. It takes the header icons' colours in both header states;
   on phones it moves into the burger menu (see the 860 px block). */
.fw-lang {
	display: inline-flex;
	align-items: center;
	gap: 0.1rem;
	margin-right: 0.35rem;
}

.fw-lang__link,
.fw-lang__link:is(:hover, :focus, :active, :visited) {
	display: inline-flex;
	align-items: center;
	min-height: 2.6rem;
	padding: 0 0.45rem;
	font-size: 0.82rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	color: var(--fw-ink);
	text-decoration: none;
	background: transparent;
	outline: 0;
	-webkit-tap-highlight-color: transparent;
}

.fw-lang__link[aria-current="true"] {
	font-weight: 800;
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.35em;
}

@media (hover: hover) {
	.fw-lang__link:not([aria-current="true"]):hover {
		text-decoration: underline;
		text-decoration-thickness: 1px;
		text-underline-offset: 0.35em;
	}
}

.fw-lang__link:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

.fw-header.is-transparent .fw-lang--header .fw-lang__link {
	color: var(--fw-on-dark);
}

.fw-lang--mobile {
	display: flex;
	margin: 0 0 0.25rem;
	padding: 0.25rem 0.25rem 0.75rem;
	border-bottom: 1px solid rgba(95, 70, 71, 0.07);
}

.fw-lang--mobile .fw-lang__link {
	font-size: 1rem;
	padding: 0 0.75rem 0 0;
}

/* Parent styles zero out attribute-sized SVGs; size them explicitly. */
.fw-icon-btn svg,
.fw-stage__arrow svg {
	width: 20px;
	height: 20px;
	flex: 0 0 auto;
}

.fw-footer__social svg {
	width: 18px;
	height: 18px;
}

.fw-cart-count {
	position: absolute;
	top: 0.1rem;
	right: 0.05rem;
	min-width: 1.15rem;
	height: 1.15rem;
	padding-inline: 0.25rem;
	border-radius: 999px;
	background: var(--fw-yellow-500);
	color: var(--fw-ink);
	font-size: 0.7rem;
	font-weight: 800;
	line-height: 1.15rem;
	text-align: center;
}

.fw-cart-count.is-empty {
	display: none;
}

/* Burger (mobile only). Restated for every state: Astra fills a hovered or
   focused <button> blue with a white icon, and a tap leaves the burger both
   :hover and :focus, so it stayed blue after opening and closing the menu
   (owner, 2026-09-25). The transparent header's cream (0-3-0) still wins. */
.fw-nav-toggle,
.fw-nav-toggle:is(:hover, :focus, :active) {
	border: 0;
	background: transparent;
	cursor: pointer;
	padding: 0.5rem;
	color: var(--fw-ink);
}

.fw-nav-toggle {
	display: none;
}

.fw-nav-toggle__box {
	display: flex;
	flex-direction: column;
	gap: 5px;
	width: 24px;
}

.fw-nav-toggle__box span {
	height: 2.5px;
	border-radius: 2px;
	background: currentColor;
	transition: transform 0.3s var(--fw-ease), opacity 0.2s;
}

/* Open: the bars stay bars on a light tint (owner, 2026-10-12: the cross
   read as a plus sign). Restated for the tap states for the reason above. */
.fw-nav-toggle {
	border-radius: var(--fw-radius-s);
	transition: background-color 0.2s var(--fw-ease), filter 0.65s var(--fw-ease), color 0.45s var(--fw-ease);
}

.fw-nav-toggle[aria-expanded='true'],
.fw-nav-toggle[aria-expanded='true']:is(:hover, :focus, :active) {
	background: rgba(62, 89, 40, 0.12);
}

.fw-header.is-transparent .fw-nav-toggle[aria-expanded='true'] {
	background: rgba(255, 255, 255, 0.16);
}

/* Overlay below the bar: opening must not change the page height or its
   scroll anchor. main.js fits the panel to the remaining screen height and
   lowers --fw-nav-pad (row padding) where the list would not fit. */
.fw-mobile-nav {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	box-sizing: border-box;
	overflow-y: auto;
	overscroll-behavior: contain;
	background: var(--fw-surface);
	border-bottom: 1px solid rgba(95, 70, 71, 0.08);
	padding: 1rem var(--fw-gutter) 1.5rem;
}

.fw-mobile-nav__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.fw-mobile-nav__list a {
	display: block;
	padding: var(--fw-nav-pad, 0.8rem) 0.25rem;
	font-size: 1.15rem;
	font-weight: 700;
	color: var(--fw-ink);
	text-decoration: none;
	border-bottom: 1px solid rgba(95, 70, 71, 0.07);
	/* Astra's transition: all animates the padding reset during measurement.
	   Reopening then measures the old compact rows, which expand afterwards. */
	transition: color 0.2s;
}

.fw-mobile-nav__list .sub-menu {
	list-style: none;
	margin: 0;
	padding-left: 1rem;
}

.fw-mobile-nav__list .sub-menu a {
	font-size: 1rem;
	font-weight: 600;
	color: var(--fw-text-soft);
}

.fw-mobile-nav__cta {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	margin-top: 1.25rem;
}

/* Search overlay */
.fw-search-overlay {
	position: fixed;
	inset: 0;
	z-index: 95;
	background: rgba(45, 65, 32, 0.65);
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
	display: grid;
	align-content: start;
	padding-top: clamp(6rem, 18vh, 12rem);
}

.fw-search-form {
	display: flex;
	gap: 0.75rem;
	background: #fff;
	border-radius: 999px;
	padding: 0.5rem;
	box-shadow: var(--fw-shadow-m);
}

.fw-search-form input[type='search'] {
	flex: 1;
	border: 0;
	box-shadow: none;
	font-size: 1.15rem;
	background: transparent;
}

.fw-search-overlay__hint {
	color: var(--fw-on-dark);
	text-align: center;
	margin-top: 1rem;
	font-size: 0.95rem;
}

/* == 06 Mini cart drawer ============================================== */

.fw-drawer-backdrop {
	position: fixed;
	inset: 0;
	z-index: 96;
	background: rgba(43, 33, 24, 0.58);
	-webkit-backdrop-filter: blur(3px);
	backdrop-filter: blur(3px);
}

.fw-mini-cart {
	position: fixed;
	top: 0;
	right: 0;
	z-index: 97;
	width: min(29rem, 100vw);
	height: 100dvh;
	display: flex;
	flex-direction: column;
	background: var(--fw-paper);
	box-shadow: -24px 0 60px rgba(43, 33, 24, 0.24);
}

/* Head: "Dein Warenkorb", item count, close (owner, 2026-10-09). */
.fw-mini-cart__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.25rem clamp(1.25rem, 4vw, 1.75rem);
	border-bottom: 1px solid var(--fw-rule);
	background: var(--fw-paper);
	color: var(--fw-text);
}

.fw-mini-cart__head-copy {
	display: flex;
	align-items: baseline;
	gap: 0.75rem;
	min-width: 0;
}

.fw-mini-cart__head h2 {
	margin: 0;
	color: var(--fw-heading);
	font-size: clamp(1.5rem, 4vw, 1.85rem);
	line-height: 1.1;
}

.fw-mini-cart__count {
	color: var(--fw-text-soft);
	font-size: 0.9rem;
	white-space: nowrap;
}

.fw-mini-cart__head .fw-icon-btn {
	flex: 0 0 auto;
	border: 1px solid var(--fw-rule);
	background: transparent;
	color: var(--fw-text);
}

.fw-mini-cart__head .fw-icon-btn:hover {
	border-color: var(--fw-yellow-500);
	background: var(--fw-yellow-500);
	color: var(--fw-text);
}

.fw-mini-cart__body {
	flex: 1;
	min-height: 0;
	overflow: hidden;
}

.fw-mini-cart.is-busy .fw-mini-cart__body {
	opacity: 0.6;
	pointer-events: none;
	transition: opacity 0.15s ease;
}

.fw-mini-cart__empty {
	display: grid;
	gap: 1rem;
	justify-items: center;
	text-align: center;
	padding: 4rem 2rem;
	color: var(--fw-text-soft);
}

.fw-mini-cart .widget_shopping_cart_content {
	display: flex;
	flex-direction: column;
	height: 100%;
}

/* Lines: image, name + remove, quantity stepper + line price. */
.fw-mini-cart .woocommerce-mini-cart {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	list-style: none;
	margin: 0;
	padding: 0 clamp(1.25rem, 4vw, 1.75rem) !important;
}

.fw-mini-cart .woocommerce-mini-cart-item {
	--fw-mini-stage: var(--fw-home-wash);
	display: grid;
	grid-template-columns: 5.5rem minmax(0, 1fr);
	gap: 1rem;
	align-items: start;
	margin: 0;
	padding: 1.1rem 0 !important;
	border-bottom: 1px solid var(--fw-rule);
}

/* WooCommerce's clearfix pseudo-elements would count as grid cells and push
   the image into the second column. */
.fw-mini-cart .woocommerce-mini-cart-item::before,
.fw-mini-cart .woocommerce-mini-cart-item::after {
	content: none !important;
	display: none !important;
}

.fw-mini-cart .woocommerce-mini-cart-item.fw-mini-cart-item--baby {
	--fw-mini-stage: var(--fw-baby-wash);
}

.fw-mini-cart .woocommerce-mini-cart-item.fw-mini-cart-item--set {
	--fw-mini-stage: var(--fw-set-wash);
}

.fw-mini-cart__media {
	display: block;
}

.fw-mini-cart .woocommerce-mini-cart-item img {
	position: static !important;
	float: none !important;
	display: block;
	width: 5.5rem !important;
	height: 6rem !important;
	margin: 0 !important;
	padding: 0.5rem;
	object-fit: contain !important;
	background: var(--fw-mini-stage);
	border-radius: 0.85rem;
	transform: none !important;
}

.fw-mini-cart__details {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	min-width: 0;
}

.fw-mini-cart__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 0.75rem;
}

.fw-mini-cart__product-name {
	color: var(--fw-ink);
	font-weight: 700;
	font-size: 1rem;
	line-height: 1.3;
	text-decoration: none;
}

a.fw-mini-cart__product-name:hover {
	text-decoration: underline;
}

/* Astra draws a ring on a.remove through ::before; it would span the whole
   line (and catch the stepper's clicks) once .remove sits in the flow. */
.fw-mini-cart .woocommerce-mini-cart-item .remove::before,
.fw-mini-cart .woocommerce-mini-cart-item .remove::after {
	content: none !important;
	display: none !important;
}

.fw-mini-cart .woocommerce-mini-cart-item .remove {
	position: relative;
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	border: 1px solid var(--fw-rule);
	background: transparent;
	color: var(--fw-text) !important;
	text-decoration: none;
}

.fw-mini-cart .woocommerce-mini-cart-item .remove:hover {
	border-color: var(--fw-red-700);
	background: var(--fw-red-700);
	color: var(--fw-on-dark) !important;
}

.fw-mini-cart .woocommerce-mini-cart-item .variation {
	margin: 0;
	color: var(--fw-text-soft);
	font-size: 0.84rem;
}

.fw-mini-cart__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
}

.fw-qty {
	display: inline-flex;
	align-items: center;
	border: 1px solid var(--fw-rule);
	border-radius: 999px;
	background: var(--fw-paper);
}

.fw-qty__btn {
	display: grid;
	place-items: center;
	width: 2.25rem;
	height: 2.25rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: var(--fw-text);
	cursor: pointer;
}

.fw-qty__btn:focus,
.fw-qty__btn:active {
	background: transparent;
	color: var(--fw-text);
	outline: none;
}

.fw-qty__btn:hover:not(:disabled),
.fw-qty__btn:focus-visible {
	background: var(--fw-yellow-500);
	color: var(--fw-ink);
}

.fw-qty__btn:disabled {
	opacity: 0.35;
	cursor: default;
}

.fw-qty__value {
	min-width: 2rem;
	text-align: center;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.fw-mini-cart__line-total {
	color: var(--fw-ink);
	font-weight: 700;
	white-space: nowrap;
}

/* Summary: coupon, totals, actions. */
.fw-mini-cart__summary {
	padding: 1rem clamp(1.25rem, 4vw, 1.75rem) clamp(1.25rem, 4vw, 1.75rem);
	border-top: 1px solid var(--fw-rule);
	background: var(--fw-paper);
}

.fw-coupon {
	display: flex;
	gap: 0.5rem;
}

.fw-coupon__input {
	flex: 1;
	min-width: 0;
	height: 2.75rem;
	padding: 0 0.9rem;
	border: 1px solid var(--fw-rule);
	border-radius: 0.6rem;
	background: #fff;
	color: var(--fw-ink);
	font-size: 0.95rem;
}

.fw-coupon__input:focus {
	outline: 2px solid var(--fw-green-700);
	outline-offset: 1px;
}

.fw-coupon__btn {
	height: 2.75rem;
	padding: 0 1.1rem;
	border: 1px solid var(--fw-green-800);
	border-radius: 0.6rem;
	background: transparent;
	color: var(--fw-text);
	font-weight: 700;
	cursor: pointer;
}

.fw-coupon__btn:hover,
.fw-coupon__btn:focus,
.fw-coupon__btn:focus-visible,
.fw-coupon__btn:active {
	border-color: var(--fw-green-800);
	background: var(--fw-green-800);
	color: var(--fw-on-dark);
}

.fw-coupon__message {
	margin: 0.5rem 0 0;
	color: var(--fw-green-700);
	font-size: 0.85rem;
}

.fw-coupon__message.is-error {
	color: var(--fw-red-700);
}

.fw-mini-cart__totals {
	margin: 1rem 0 0;
}

.fw-mini-cart__totals > div {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	padding: 0.2rem 0;
	color: var(--fw-text);
	font-size: 0.95rem;
}

.fw-mini-cart__totals dt,
.fw-mini-cart__totals dd {
	margin: 0;
}

.fw-mini-cart__coupon-remove {
	margin-left: 0.4rem;
	padding: 0;
	border: 0;
	background: none;
	color: var(--fw-text-soft);
	font-size: 0.8rem;
	text-decoration: underline;
	cursor: pointer;
}

.fw-mini-cart__totals .fw-mini-cart__grand-total {
	margin-top: 0.45rem;
	padding-top: 0.65rem;
	border-top: 1px solid var(--fw-rule);
	color: var(--fw-ink);
	font-weight: 700;
	font-size: 1.15rem;
}

.fw-mini-cart__vat {
	margin: 0;
	color: var(--fw-text-soft);
	font-size: 0.8rem;
	text-align: right;
}

.fw-mini-cart .woocommerce-mini-cart__buttons {
	display: grid;
	gap: 0.6rem;
	margin: 1rem 0 0;
	padding: 0;
	text-align: center;
}

.fw-mini-cart__checkout {
	width: 100%;
	justify-content: center;
}

.fw-mini-cart__view-cart {
	color: var(--fw-text);
	font-size: 0.9rem;
	text-decoration: underline;
}

/* == 07 Footer ========================================================= */

.fw-footer {
	background: var(--fw-green-900);
	color: var(--fw-on-dark);
	margin-top: 0;
	border-top: 1px solid rgba(252, 237, 197, 0.32);
}

.fw-footer a {
	color: var(--fw-on-dark);
	text-decoration: none;
}

.fw-footer a:hover {
	color: var(--fw-accent);
}

.fw-footer h2,
.fw-footer h3 {
	color: var(--fw-on-dark);
}

.fw-footer__newsletter {
	display: grid;
	grid-template-columns: 1.2fr 1fr;
	gap: 2rem;
	align-items: center;
	padding: clamp(2.5rem, 6vw, 4rem) 0;
	border-bottom: 1px solid rgba(252, 237, 197, 0.15);
}

.fw-footer__newsletter h2 {
	font-size: clamp(1.5rem, 3vw, 2.1rem);
	margin: 0 0 0.4rem;
}

.fw-footer__newsletter p {
	margin: 0;
	color: var(--fw-on-dark);
}

.fw-newsletter-form {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}

.fw-newsletter-form input[type='email'] {
	flex: 1;
	min-width: 14rem;
	border-radius: 999px;
	border-color: transparent;
}

.fw-newsletter-form__note {
	flex-basis: 100%;
	font-size: 0.85rem;
	color: var(--fw-on-dark);
	margin: 0;
}

.fw-footer__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: clamp(1.5rem, 4vw, 4rem);
	width: min(100%, 68rem);
	margin-inline: auto;
	padding: clamp(1.75rem, 4vw, 2.75rem) 0;
}

.fw-footer__service p {
	max-width: 23ch;
	margin: 0;
	color: var(--fw-on-dark);
}

.fw-footer__service p + p {
	margin-top: 0.45rem;
}

.fw-footer__service a {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

.fw-footer__service-email {
	font-weight: 800;
	overflow-wrap: anywhere;
}

.fw-footer__social {
	display: flex;
	gap: 0.4rem;
}

.fw-footer__social a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	border-radius: 50%;
	background: rgba(252, 237, 197, 0.12);
	transition: background-color 0.2s, transform 0.2s;
}

.fw-footer__social a:hover {
	background: rgba(252, 237, 197, 0.25);
	transform: translateY(-2px);
}

.fw-footer__col :is(h2, h3) {
	font-size: 0.85rem;
	font-family: var(--fw-font-body);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--fw-accent);
	margin: 0 0 0.75rem;
}

.fw-footer__col {
	min-width: 0;
}

.fw-footer__menu {
	grid-template-columns: minmax(0, 1fr);
	overflow-wrap: anywhere;
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.45rem;
}

.fw-footer__bottom {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	gap: 0.75rem clamp(1rem, 3vw, 2rem);
	align-items: center;
	padding: 1rem 0 1.25rem;
	border-top: 1px solid rgba(252, 237, 197, 0.15);
	font-size: 0.88rem;
	color: var(--fw-on-dark);
}

.fw-footer__bottom p {
	margin: 0;
}

.fw-footer__identity {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	justify-self: start;
}

.fw-footer__claim {
	font-weight: 700;
	justify-self: center;
	text-align: center;
}

.fw-footer__payments {
	justify-self: end;
}

.fw-footer__payments span,
.fw-trust__payments span {
	display: inline-block;
	padding: 0.2rem 0.6rem;
	margin-right: 0.35rem;
	border: 1px solid currentColor;
	border-radius: 6px;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.03em;
	opacity: 0.85;
}

.fw-footer__payments span:last-child {
	margin-right: 0;
}

/* == 08 Sections ======================================================= */

.fw-section {
	padding-block: var(--fw-section-pad);
}

.fw-section--cream {
	background: var(--fw-surface);
}

/* Full-bleed dark bands now merge into the page ground instead of drawing
   a second green rectangle on top of it. */
.fw-section--green {
	background: transparent;
	color: var(--fw-on-dark);
}

/* All six levels, not just h2–h4: the heading green now equals the page
   ground, so a missed level is invisible rather than merely off-palette.
   `.fw-section--green` is excluded on landing panels — those sections still
   carry the class in markup but are light containers, and inheriting the
   dark-band ink from here is what made their headings unreadable. */
.fw-section--green:not(.fw-landing-panel) :is(h1, h2, h3, h4, h5, h6),
.fw-page-hero--green :is(h1, h2, h3, h4, h5, h6),
.fw-us-hero :is(h1, h2, h3, h4, h5, h6),
.fw-science-hero :is(h1, h2, h3, h4, h5, h6),
.fw-us-orbit :is(h1, h2, h3, h4, h5, h6),
.fw-us-timeline :is(h1, h2, h3, h4, h5, h6),
.fw-us-manifest :is(h1, h2, h3, h4, h5, h6),
.fw-footer :is(h1, h2, h3, h4, h5, h6) {
	color: var(--fw-on-dark);
}

.fw-section--white {
	background: var(--fw-surface);
}

/* Heading colour rule for the whole site: the large heading of a section or
   chapter is the corporate green (--fw-heading, applied by the base h1–h6
   rule), while the small uppercase label above it — and any small in-card
   sub-heading — stays the brown ink. Role decides, not tag: `Ananasanbau` is
   an h3 and reads as a chapter heading, `Das Sortiment` on the shop hero is a
   span above the h1 and reads as a label. The landing stage heading (`Unsere Produkte`) went
   the other way in 2026-09: it now carries two sub-headings and therefore
   follows the base rule as a green section heading. */
.fw-kicker,
.fw-story-cycle__label,
.fw-shop-hero__eyebrow {
	color: var(--fw-ink);
}

.fw-kicker {
	font-size: 0.85rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	margin: 0 0 0.75rem;
}

/* On the dark ground the brown ink drops to 1.1:1, so the dark bands take the
   highlight yellow instead. Landing panels are excluded for the same reason
   as the heading rule above: they are light containers. */
.fw-section--green:not(.fw-landing-panel) .fw-kicker,
.fw-page-hero--green .fw-kicker,
.fw-science-hero .fw-kicker,
.fw-us-hero .fw-kicker,
.fw-us-timeline .fw-kicker,
.fw-us-manifest .fw-kicker {
	color: var(--fw-accent);
}
/* NOT .fw-us-orbit: its only label sits inside a cream card, where yellow
   drops to ~1.6:1. That card uses .fw-us-orbit__place in the deep green
   instead — no yellow anywhere on the beige. */

.fw-section-heading {
	max-width: 46rem;
	margin-bottom: clamp(2.25rem, 5vw, 3.75rem);
}

.fw-section-heading--center {
	margin-inline: auto;
	text-align: center;
}

.fw-section-title {
	font-size: clamp(1.9rem, 4vw, 2.9rem);
	margin: 0 0 1rem;
}

.fw-section-intro {
	font-size: 1.15rem;
	color: var(--fw-text-soft);
	margin: 0;
}

.fw-section--green .fw-section-intro {
	color: var(--fw-on-dark);
}

/* Page hero */
.fw-page-hero {
	padding: clamp(4.5rem, 10vw, 8rem) 0 clamp(3.5rem, 8vw, 6rem);
}

.fw-page-hero--green {
	background: transparent;
	color: var(--fw-on-dark);
}

.fw-page-hero--green .fw-page-hero__title {
	color: var(--fw-on-dark);
}

.fw-page-hero--cream {
	background: var(--fw-surface);
}

.fw-page-hero__title {
	font-size: clamp(2.4rem, 6vw, 4rem);
	max-width: 18ch;
	margin: 0 0 1.25rem;
}

.fw-page-hero__intro {
	font-size: clamp(1.1rem, 2vw, 1.3rem);
	max-width: 56ch;
	margin: 0;
}

.fw-page-hero--green .fw-page-hero__intro {
	color: var(--fw-on-dark);
}

.fw-page-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem;
	margin-top: 2rem;
}

/* CTA banner */
/* The band itself stays on the page ground; the island inside it is the
   container. Filling both would make the island's edge disappear. */
.fw-cta-banner {
	padding-block: clamp(3.5rem, 8vw, 6rem);
	background: transparent;
}

.fw-cta-banner__inner {
	display: grid;
	grid-template-columns: 1.4fr 1fr;
	gap: 2rem;
	align-items: center;
	background: var(--fw-surface);
	color: var(--fw-text);
	border-radius: var(--fw-radius-l);
	padding: clamp(2.25rem, 5vw, 4rem);
}

.fw-cta-banner__copy h2 {
	color: var(--fw-heading);
	font-size: clamp(1.7rem, 3.4vw, 2.5rem);
	margin: 0 0 0.6rem;
}

.fw-cta-banner__copy p {
	margin: 0;
	color: var(--fw-text-soft);
}

/* On the cream island the yellow primary and the near-white light button would
   each all but disappear, so the pair is restated in green: solid for the
   primary action, outline for the secondary. */
.fw-cta-banner .fw-btn--primary {
	background: var(--fw-green-700);
	color: var(--fw-on-dark);
	border-color: var(--fw-green-700);
}

.fw-cta-banner .fw-btn--primary:hover {
	background: var(--fw-green-800);
	color: var(--fw-on-dark);
}

.fw-cta-banner .fw-btn--light {
	background: transparent;
	color: var(--fw-green-700);
	border-color: var(--fw-green-700);
}

.fw-cta-banner .fw-btn--light:hover {
	background: var(--fw-green-700);
	color: var(--fw-on-dark);
}

.fw-cta-banner__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem;
	justify-content: flex-end;
}

/* Video hero (landing page) */
.fw-hero {
	position: relative;
	/* Down to the bottom edge, below the notice bar when it shows (05a). */
	min-height: calc(100svh - var(--fw-notice-space));
	display: grid;
	align-items: center;
	overflow: hidden;
	background: var(--fw-green-900);
}

/* The clip stage owns a stacking context of its own (z-index on a positioned
   box), so the layer that fades in can be raised above its predecessor
   without ever escaping above .fw-hero__overlay or the copy. */
.fw-hero__stage {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
}

.fw-hero__media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Until main.js takes over, the first layer is a plain looping video and the
   second one is an empty element — no opacity rules, no transition. */
.fw-hero__stage.is-sequenced .fw-hero__media {
	opacity: 0;
	transition: opacity var(--fw-hero-fade, 1.1s) linear;
}

.fw-hero__stage.is-sequenced .fw-hero__media.is-active {
	opacity: 1;
}

/* Only the incoming layer animates: it fades 0 → 1 on top while the outgoing
   one stays fully opaque underneath. Fading both at once would let the dark
   page background show through in the middle of the dissolve and dip the
   whole hero. */
.fw-hero__stage.is-sequenced .fw-hero__media.is-top {
	z-index: 1;
}

/* Clip 2's first frame is already loaded when the intro needs its fallback.
   The outgoing picture stays opaque underneath throughout the dissolve. */
.fw-hero__fallback {
	position: absolute;
	inset: 0;
	z-index: 2;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.6s linear;
}

.fw-hero__fallback img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.fw-hero__fallback.is-visible {
	opacity: 1;
}

/* Consent revocation resumes a still before the first paint, too. */
html.fw-resumed-still .fw-hero__fallback {
	opacity: 1;
	transition: none;
}

html.fw-resumed-still [data-fw-hero-playback] {
	display: none !important;
}

@media (prefers-reduced-motion: reduce) {
	.fw-hero__fallback { transition: none; }
}

.fw-hero__overlay {
	position: absolute;
	inset: 0;
	/* Uniform filter: same darkening at every point of the video. */
	background: rgba(34, 49, 26, 0.55);
}

.fw-hero__content {
	position: relative;
	z-index: 2;
	width: 100%;
	padding-block: clamp(6rem, 14vh, 9rem) clamp(5rem, 12vh, 8rem);
	color: var(--fw-on-dark);
}

.fw-hero__kicker {
	font-size: 0.95rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.2em;
	color: var(--fw-accent);
	margin: 0 0 1rem;
}

.fw-hero__title {
	color: #fff;
	font-size: clamp(2.6rem, 7vw, 4.8rem);
	margin: 0 0 1.25rem;
	max-width: 16ch;
}

.fw-hero__title em {
	font-style: normal;
	color: var(--fw-yellow-500);
}

/* Uppercased here, not in the markup — see the comment in hero-video.php. */
.fw-hero__brand {
	text-transform: uppercase;
}

.fw-hero__sub {
	font-size: clamp(1.05rem, 2vw, 1.3rem);
	max-width: 52ch;
	margin: 0 0 2rem;
	color: var(--fw-on-dark);
}

/* The hero is exactly one screen high and everything in it must be visible,
   including the pause button in its corner (owner, 2026-09-28). The sizes
   above only follow the width, so on a wide but short laptop window
   (1440 × 733 on a 14" screen) the copy made the hero ~60 px taller than the
   screen. From 768 px up, type and spacing also shrink with the height:
   unchanged from about 900 px of height, and everything fits down to
   800 × 600. Phones have their own layout below. Measured per viewport
   by audit-hero-actions.mjs („fits the screen“). */
@media (min-width: 768px) {
	/* With the notice bar (05a) the hero is shorter by its height; the
	   bottom gives that amount back, so the copy still fits. */
	.fw-hero__content {
		padding-block: clamp(5.5rem, 13svh, 9rem) calc(clamp(4.75rem, 11svh, 8rem) - var(--fw-notice-space));
	}

	.fw-hero__kicker {
		margin-bottom: clamp(0.5rem, 1.6svh, 1rem);
	}

	.fw-hero__title {
		font-size: clamp(2.4rem, min(7vw, 8.4svh), 4.8rem);
		margin-bottom: clamp(0.75rem, 2.2svh, 1.25rem);
	}

	.fw-hero__sub {
		font-size: clamp(0.95rem, min(2vw, 2.5svh), 1.3rem);
		margin-bottom: clamp(1rem, 3.5svh, 2rem);
	}

	.fw-hero__buttons .fw-btn {
		padding-block: clamp(0.6rem, 1.6svh, 0.85rem);
	}
}
/* The three destinations form a band, and the primary action closes the hero
   on its own line beneath them. Keeping them in two containers is deliberate:
   as one wrapping row of four the break landed 3 + 1 and left the last label
   stranded, and where a row of four breaks depends on the label lengths — so
   a longer word in another language would silently regroup the whole block. */
.fw-hero__explore {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	max-width: 46rem;
	margin-bottom: 0.85rem;
}

.fw-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
}

.fw-hero__explore .fw-btn {
	font-size: 0.95rem;
	padding-inline: 1.4rem;
}

/* Phones cannot hold the band in one row, so it becomes a fixed grid rather
   than a wrap that depends on label lengths: Wissenschaft and Das sind wir
   share the first row in equal halves, Die Kreislaufwirtschaft spans the
   second, and the shop button the full width beneath (owner, 2026-09-24).

   The buttons sit at the foot of the video and the copy stays around the
   middle: the content fills the hero as a grid whose two 1fr rows centre the
   copy in the space above the buttons. Unlike centring the copy in the
   whole hero, that can never let copy and buttons overlap on a short phone. */
@media (max-width: 767px) {
	.fw-hero__content {
		display: grid;
		grid-template-rows: 1fr auto 1fr auto;
		min-height: calc(100svh - var(--fw-notice-space));
		padding-bottom: 1.5rem;
	}

	/* Copy and buttons must fit one screen on short phones too (owner,
	   2026-10-19: on an Android at 360 × 641 the shop button ran 25 px
	   below the screen). The minimum height alone let the hero grow with
	   its content, so top space, title and lead also shrink with the
	   height here, as they do from 768 px up; from about 800 px of height
	   they are unchanged. audit-hero-actions.mjs measures 360 × 640 up. */
	.fw-hero__content {
		padding-top: clamp(5.25rem, 11svh, 9rem);
	}

	.fw-hero__title {
		font-size: clamp(2.1rem, min(10.5vw, 5.2svh), 2.6rem);
	}

	.fw-hero__sub {
		font-size: clamp(0.9rem, 2.3svh, 1.05rem);
		line-height: 1.5;
		margin-bottom: clamp(1rem, 3svh, 2rem);
	}

	.fw-hero__copy {
		grid-row: 2;
	}

	.fw-hero__buttons {
		grid-row: 4;
	}

	.fw-hero__explore {
		display: grid;
		grid-template-columns: 1fr 1fr;
	}

	.fw-hero__explore .fw-btn {
		padding-inline: 0.9rem;
	}

	.fw-hero__explore [data-fw-hero-circle-button] {
		grid-column: 1 / -1;
		grid-row: 2;
	}

	.fw-hero__actions .fw-btn {
		flex: 1 1 100%;
	}
}

.fw-hero__scroll {
	position: absolute;
	left: 50%;
	bottom: 1.5rem;
	transform: translateX(-50%);
	z-index: 2;
	width: 2rem;
	height: 3rem;
	border: 2px solid rgba(254, 250, 240, 0.6);
	border-radius: 999px;
	display: grid;
	justify-items: center;
	padding-top: 0.55rem;
}

.fw-hero__scroll span {
	width: 4px;
	height: 8px;
	border-radius: 2px;
	background: var(--fw-surface);
	animation: fw-scroll-cue 1.8s infinite var(--fw-ease);
}

@keyframes fw-scroll-cue {
	0% { transform: translateY(0); opacity: 1; }
	70% { transform: translateY(14px); opacity: 0; }
	100% { transform: translateY(0); opacity: 0; }
}

/* Pause / play for the clip reel, in the hero's bottom-right corner (owner,
   2026-09-28). The same material as the scroll cue and the outline buttons:
   a cream hairline and a faint frosted fill, so it stays legible on a bright
   frame without competing with the copy. Centred on the scroll cue's
   height. The resting rule lists every state because Astra paints hovered
   and focused buttons blue (design-system.md) — here the border as well,
   which stayed blue after a click. */
.fw-hero__playback,
.fw-hero__playback:is(:hover, :focus, :active) {
	background: rgba(239, 237, 228, 0.14);
	color: var(--fw-on-dark);
	border-color: rgba(254, 250, 240, 0.6);
	box-shadow: none;
}

.fw-hero__playback {
	position: absolute;
	right: var(--fw-gutter);
	bottom: calc(1.5rem + 0.125rem);
	z-index: 2;
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border-width: 2px;
	border-style: solid;
	border-radius: 50%;
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
	cursor: pointer;
	transition: border-color 0.2s var(--fw-ease), background-color 0.2s var(--fw-ease);
}

.fw-hero__playback[hidden] {
	display: none;
}

@media (hover: hover) {
	.fw-hero__playback:hover {
		background: rgba(239, 237, 228, 0.26);
		border-color: var(--fw-on-dark);
	}
}

.fw-hero__playback:focus-visible {
	outline: 2px solid var(--fw-accent);
	outline-offset: 3px;
}

.fw-hero__playback-icon {
	grid-area: 1 / 1;
	width: 1.15rem;
	height: 1.15rem;
	fill: currentColor;
}

.fw-hero__playback-icon--play,
.fw-hero__playback.is-paused .fw-hero__playback-icon--pause {
	display: none;
}

.fw-hero__playback.is-paused .fw-hero__playback-icon--play {
	display: block;
}

/* Phones need the room for the buttons at the foot of the video (owner,
   2026-09-23); scrolling is obvious there anyway.

   The pause button stands right of Jetzt shoppen, in the same row (owner,
   2026-09-28), so the buttons stay at the very foot of the video. It stays
   in the section rather than moving into the row, and takes the shop
   button's height (.fw-btn: 0.85rem padding twice + 1.2 × 1rem line + 2 px
   border twice) and its baseline (the content's 1.5rem bottom padding);
   the row gives up its width plus the 0.75rem gap of the button rows. */
@media (max-width: 767px) {
	.fw-hero__scroll {
		display: none;
	}

	.fw-hero {
		--fw-playback-size: calc(2.9rem + 4px);
	}

	.fw-hero__playback {
		bottom: 1.5rem;
		width: var(--fw-playback-size);
		height: var(--fw-playback-size);
	}

	/* Only while the button is shown: without JS it stays hidden and the
	   shop button keeps the full width. */
	.fw-hero:has([data-fw-hero-playback]:not([hidden])) .fw-hero__actions {
		padding-right: calc(var(--fw-playback-size) + 0.75rem);
	}
}

/* == 09 Components ===================================================== */

/* Generic card grid */
.fw-grid {
	display: grid;
	gap: clamp(1.25rem, 3vw, 2rem);
}

.fw-grid--2 {
	grid-template-columns: repeat(2, 1fr);
}

.fw-grid--3 {
	grid-template-columns: repeat(3, 1fr);
}

.fw-grid--4 {
	grid-template-columns: repeat(4, 1fr);
}

.fw-card {
	background: var(--fw-surface);
	border-radius: var(--fw-radius-m);
	padding: clamp(1.5rem, 3vw, 2.25rem);
	box-shadow: var(--fw-shadow-s);
	transition: transform 0.3s var(--fw-ease), box-shadow 0.3s var(--fw-ease);
}

.fw-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--fw-shadow-m);
}

.fw-card h3 {
	font-size: 1.3rem;
	margin: 0 0 0.6rem;
}

.fw-card p {
	margin: 0;
	color: var(--fw-text-soft);
}

.fw-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3.25rem;
	height: 3.25rem;
	border-radius: 14px;
	background: var(--fw-surface);
	font-size: 1.5rem;
	margin-bottom: 1.1rem;
}























/* Value cards are links */


/* Split section (image + copy) */
.fw-split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: center;
}

.fw-split__media img,
.fw-split__media video {
	width: 100%;
	border-radius: var(--fw-radius-l);
	box-shadow: var(--fw-shadow-m);
	display: block;
}



.fw-split__copy h2 {
	font-size: clamp(1.8rem, 3.6vw, 2.6rem);
	margin: 0 0 1rem;
}

/* The kicker is a p too, and this rule outranks it by specificity — without
   the :not() the eyebrow above a split heading turns soft grey. */
.fw-split__copy p:not(.fw-kicker) {
	color: var(--fw-text-soft);
}

/* Scoped away from the landing Science island, which still carries the
   .fw-section--green class in markup but is a light container now. Without
   the :not() this rule outranks the island's own ink by specificity. */
.fw-section--green:not(.fw-landing-panel) .fw-split__copy p {
	color: var(--fw-on-dark);
}

.fw-split__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem;
	margin-top: 1.6rem;
}

/* Checked benefit list */
/* Checked lists.
   One definition for every ticked list on the site. There used to be two --
   this masked SVG here and a text "✓" in woocommerce.css -- which put two
   different marks at two different indents on the same product page.
   Metrics are in em so a list can be set smaller without the tick drifting
   out of proportion; that is what makes one rule serve both sizes. */
.fw-benefit-list {
	list-style: none;
	margin: 0 0 1.25rem;
	padding: 0;
	display: grid;
	gap: 0.55rem;
}

.fw-benefit-list li {
	padding-left: 1.9em;
	position: relative;
}

.fw-benefit-list li::before {
	content: '';
	position: absolute;
	left: 0;
	top: 0.28em;
	width: 1.15em;
	height: 1.15em;
	border-radius: 50%;
	background: var(--fw-green-500);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' d='M4 12.5 9.5 18 20 6.5'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' d='M4 12.5 9.5 18 20 6.5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Timeline */












/* Process loop / fermentation steps */
.fw-process {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 1.25rem;
	counter-reset: fw-step;
}

.fw-process__step {
	counter-increment: fw-step;
	background: var(--fw-surface);
	border-radius: var(--fw-radius-m);
	padding: 1.75rem 1.5rem;
	box-shadow: var(--fw-shadow-s);
	position: relative;
}

.fw-process__step::before {
	content: '0' counter(fw-step);
	font-family: var(--fw-font-display);
	font-weight: 800;
	font-size: 0.95rem;
	color: var(--fw-green-500);
	letter-spacing: 0.08em;
}

.fw-process__step h3 {
	font-size: 1.15rem;
	margin: 0.5rem 0;
}

.fw-process__step p {
	margin: 0;
	font-size: 0.95rem;
	color: var(--fw-text-soft);
}

/* Stats band */






/* Accordion */
/* A ruled list, not a stack of cards. The accordion only ever sits on a cream
   surface (the FAQ island, the Contact page's cream section), where a cream
   card is invisible and only its shadow shows. States live in the question's
   colour and the icon; the surface never inverts. */
.fw-accordion {
	max-width: 48rem;
	margin-inline: auto;
	border-top: 1px solid var(--fw-rule);
}

.fw-accordion__item {
	border-bottom: 1px solid var(--fw-rule);
}

.fw-accordion__heading {
	margin: 0;
	font-size: inherit;
}

.fw-accordion__trigger {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1.25rem;
	width: 100%;
	padding: 1.1rem 0;
	background: transparent;
	border: 0;
	border-radius: 0;
	cursor: pointer;
	font-family: var(--fw-font-body);
	font-size: 1.05rem;
	font-weight: 700;
	line-height: 1.35;
	color: var(--fw-ink);
	text-align: left;
	transition: color 0.2s var(--fw-ease);
}

/* Astra paints every focused or hovered <button> with its global blue
   (`button:focus`, 0-1-1, inlined). That is what turned an opened question
   blue. The extra class outranks it, so the question keeps its own colours
   in every state: ink at rest, heading green on hover, focus and while open. */
.fw-accordion__item .fw-accordion__trigger:hover,
.fw-accordion__item .fw-accordion__trigger:focus,
.fw-accordion__item .fw-accordion__trigger:active,
.fw-accordion__item .fw-accordion__trigger[aria-expanded='true'] {
	background: transparent;
	border-color: transparent;
	color: var(--fw-green-700);
}

.fw-accordion__icon {
	flex: 0 0 auto;
	width: 1.6rem;
	height: 1.6rem;
	margin-top: 0.05rem;
	border-radius: 50%;
	background: var(--fw-green-700);
	position: relative;
	transition: transform 0.3s var(--fw-ease);
}

.fw-accordion__icon::before,
.fw-accordion__icon::after {
	content: '';
	position: absolute;
	inset: 0;
	margin: auto;
	width: 0.7rem;
	height: 2px;
	border-radius: 2px;
	background: var(--fw-surface);
	transition: transform 0.3s var(--fw-ease);
}

.fw-accordion__icon::after {
	transform: rotate(90deg);
}

.fw-accordion__trigger[aria-expanded='true'] .fw-accordion__icon {
	transform: rotate(180deg);
}

.fw-accordion__trigger[aria-expanded='true'] .fw-accordion__icon::after {
	transform: rotate(0deg);
}

.fw-accordion__content {
	padding: 0 3.6rem 1.4rem 0;
	max-width: 64ch;
	color: var(--fw-text-soft);
}

.fw-accordion__content > :last-child {
	margin-bottom: 0;
}

/* Product stage: one broad editorial surface, without an inner card. */
/* The panel is a container like any other. Product colour lives in two
   places only: the wash behind the bottle (per line) and the label chip
   plus the selector fill (per product). */
.fw-stage {
	position: relative;
	overflow: hidden;
	min-height: min(44rem, calc(100svh - 3rem));
	background: var(--fw-surface);
	color: var(--fw-text);
}

.fw-stage__layout {
	display: grid;
	grid-template-columns: minmax(12rem, 0.72fr) minmax(20rem, 1.2fr) minmax(21rem, 1.08fr);
	gap: clamp(1.5rem, 3vw, 4.5rem);
	align-items: center;
	min-height: 34rem;
}

/* The heading column. Heading and selector share the left track so the panel
   keeps its three columns of roughly equal height; a full-width masthead
   above the grid stacked its height on top of all three. */
.fw-stage__aside {
	display: flex;
	flex-direction: column;
	min-width: 0;
	align-self: center;
}

.fw-stage__header {
	margin: 0 0 clamp(1.5rem, 2.5vw, 2.25rem);
}

/* The enzyme family belongs to the product list, not to the heading: it sits
   between the selector and the shop link and names what every row above it
   has in common. No rules around it — the spacing carries it. */
.fw-stage__basis {
	margin-top: 1.5rem;
	padding-top: 0.25rem;
}

/* Astra prints `h2 { margin-bottom: 0.7em }` into its dynamic inline CSS,
   which is why the heading needs the extra class here: with a single class
   the shorthand loses and a 26 px gap opens under the heading. */
.fw-stage__header .fw-stage__heading {
	margin: 0;
	font-size: clamp(1.75rem, 2.6vw, 2.4rem);
	line-height: 1;
}

.fw-stage__basis-lead {
	margin: 0;
	color: var(--fw-ink);
	font-size: 0.7rem;
	font-weight: 850;
	letter-spacing: 0.13em;
	line-height: 1.2;
	text-transform: uppercase;
}

.fw-stage__basis-main {
	margin: 0.15rem 0 0;
	color: var(--fw-heading);
	font-family: var(--fw-font-display);
	font-size: clamp(1.05rem, 1.45vw, 1.3rem);
	font-weight: 700;
	line-height: 1.15;
}

.fw-stage__selector {
	display: flex;
	min-width: 0;
	height: auto;
	flex-direction: column;
	justify-content: flex-start;
}

.fw-stage__tabs {
	display: grid;
	position: relative;
	z-index: 2;
}

.fw-stage__tab {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 0.55rem;
	align-items: center;
	width: 100%;
	border: 0;
	border-bottom: 1px solid currentColor;
	border-radius: 0;
	background: transparent;
	padding: 0.72rem 0.25rem;
	font-family: var(--fw-font-body);
	font-weight: 750;
	font-size: clamp(0.78rem, 0.85vw, 0.94rem);
	line-height: 1.15;
	text-align: left;
	color: inherit;
	cursor: pointer;
	transition: padding 0.25s var(--fw-ease), background-color 0.25s, color 0.25s;
}

/* A tap leaves the tab focused; without this Astra filled it blue. */
.fw-stage__tab:focus {
	background: transparent;
	color: inherit;
	outline: 0;
}

/* The filled row is the product's own label: its colour, its ink. */
.fw-stage__tab:is(:hover, :focus-visible) {
	padding-inline: 0.75rem;
	background: var(--fw-tab-label);
	color: var(--fw-tab-label-ink);
	outline: 0;
}

.fw-stage__tab.is-active {
	padding-inline: 0.75rem;
	background: var(--fw-tab-label);
	color: var(--fw-tab-label-ink);
}

.fw-stage__shop-link {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	margin-top: 1.25rem;
	padding-top: 1.5rem;
	color: inherit;
	font-size: 0.86rem;
	font-weight: 800;
	text-decoration: none;
	text-transform: uppercase;
	letter-spacing: 0.06em;
}

.fw-stage__shop-link:hover {
	color: inherit;
}

.fw-stage__visual {
	position: relative;
	display: grid;
	place-items: center;
	align-self: stretch;
	min-width: 0;
	min-height: 33rem;
	overflow: visible;
	/* The stage no longer fills a coloured field behind the bottle. Product
	   identity moved into the drop shadow, so the surface stays the container
	   cream for every line including Baby Care. */
	background: var(--fw-surface);
	border-radius: clamp(1rem, 2vw, 1.75rem);
	/* Clip the horizontal fly-in/out, but give the product shadow room to
	   feather out above and below the visual column. */
	clip-path: inset(-3.5rem 0 -3.5rem 0);
	touch-action: pan-y;
}

.fw-stage__visual:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 0.35rem;
}

/* The bottle is a link to the product page (owner, 2026-10-05), without any
   hover effect. The link fills the image's grid cell so the image keeps its
   sizing; animations.js marks it .is-hit-tested and only the bottle's own
   pixels then show the pointer (.is-on-product) and take the click. */
.fw-stage__product-link {
	display: grid;
	place-items: center;
	align-self: stretch;
	justify-self: stretch;
	min-width: 0;
	color: inherit;
	cursor: pointer;
	transition: none;
	-webkit-tap-highlight-color: transparent;
}

.fw-stage__product-link.is-hit-tested:not(.is-on-product) {
	cursor: default;
}

.fw-stage__product-link:focus {
	outline: none;
}

.fw-stage__product-link:focus-visible .fw-stage__img {
	outline: 2px solid currentColor;
	outline-offset: 0.35rem;
	border-radius: 0.75rem;
}

.fw-stage__img {
	width: min(100%, 26.25rem);
	height: min(33rem, 64vh);
	object-fit: contain;
}

/* `--fw-stage-copy-min-height` is measured in animations.js across all
   products and keeps the panel from growing and shrinking while the visitor
   switches products. Without it the tallest claim plus a benefit that wraps
   decide the section height, and the page jumps under the thumb. */
.fw-stage__copy {
	display: flex;
	flex-direction: column;
	align-self: stretch;
	min-width: 0;
	min-block-size: var(--fw-stage-copy-min-height, 0);
	touch-action: pan-y;
}

.fw-stage__facts {
	display: flex;
	flex-wrap: wrap;
	gap: 0.55rem;
	margin: 0 0 1.25rem;
	font-size: 0.82rem;
	font-weight: 850;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.fw-stage__copy h3 {
	max-width: 13ch;
	margin: 0 0 1rem;
	color: inherit;
	font-size: clamp(2.2rem, 3.4vw, 4rem);
	line-height: 0.96;
}

/* The product name reproduces its physical label rather than borrowing the
   label colour as ink — four of the six labels are far too light to read as
   text on the container surface. */
.fw-stage__label-chip {
	display: inline-block;
	padding: 0.12em 0.42em 0.2em;
	border-radius: 0.18em;
	background: var(--fw-stage-label);
	color: var(--fw-stage-label-ink);
	box-decoration-break: clone;
	-webkit-box-decoration-break: clone;
}

/* One claim per product instead of the WooCommerce short description, which
   repeated the volume/scent line directly above it. A claim is a sentence,
   not body copy, so it gets the display face and full ink. */
.fw-stage__claim {
	max-width: 32ch;
	margin: 0;
	color: inherit;
	font-family: var(--fw-font-display);
	font-size: clamp(1.05rem, 1.35vw, 1.3rem);
	font-weight: 600;
	line-height: 1.35;
}

.fw-stage__benefits {
	display: grid;
	margin: clamp(1.4rem, 2.5vw, 2.15rem) 0 0;
	padding: 0;
	list-style: none;
}

.fw-stage__benefits li {
	position: relative;
	padding: 0.65rem 0 0.65rem 1.45rem;
	border-top: 1px solid currentColor;
	font-size: clamp(0.88rem, 1vw, 1rem);
	font-weight: 700;
	line-height: 1.3;
}

.fw-stage__benefits li::before {
	content: '→';
	position: absolute;
	left: 0;
}

.fw-stage__price {
	font-family: var(--fw-font-display);
	font-size: 1.5rem;
	font-weight: 800;
	color: inherit;
}

.fw-stage__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.9rem;
	margin-top: auto;
	padding-top: clamp(1.5rem, 3vw, 2.5rem);
}

.fw-stage__actions .fw-btn,
.fw-stage__actions .fw-btn:is(:hover, :focus, :active) {
	border-color: var(--fw-green-800);
	background: var(--fw-green-800);
	color: var(--fw-on-dark);
}

.fw-stage__detail-link {
	display: inline-flex;
	gap: 0.45rem;
	align-items: center;
	padding-block: 0.45rem;
	border-bottom: 1px solid currentColor;
	color: inherit;
	font-weight: 800;
	text-decoration: none;
}

.fw-stage__detail-link:hover {
	color: inherit;
}

.fw-stage__arrow {
	position: absolute;
	top: 50%;
	z-index: 3;
	width: 2.8rem;
	height: 2.8rem;
	border-radius: 50%;
	border: 1px solid currentColor;
	background: transparent;
	color: inherit;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	box-shadow: none;
	transform: translateY(-50%);
	transition: background-color 0.2s, color 0.2s, transform 0.2s;
}

.fw-stage__arrow:is(:focus, :focus-visible, :active) {
	border-color: currentColor;
	background: transparent;
	color: inherit;
	outline: 0;
	box-shadow: none;
}

.fw-stage__arrow:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

@media (hover: hover) {
	.fw-stage__arrow:hover {
		border-color: var(--fw-green-800);
		background: var(--fw-green-800);
		color: var(--fw-on-dark);
		outline: 0;
		transform: translateY(-50%) scale(1.07);
	}
}

.fw-stage__arrow--prev {
	left: clamp(0.1rem, 0.8vw, 0.8rem);
}

.fw-stage__arrow--next {
	right: clamp(0.1rem, 0.8vw, 0.8rem);
}

.fw-stage__swipe-hint {
	display: none;
}

/* Fermentation formula band */
.fw-formula {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 0.75rem;
	font-family: var(--fw-font-display);
	font-size: clamp(1rem, 2vw, 1.25rem);
	font-weight: 700;
}

.fw-formula__item {
	background: var(--fw-surface);
	border-radius: 999px;
	padding: 0.7rem 1.4rem;
	box-shadow: var(--fw-shadow-s);
	color: var(--fw-text);
}

.fw-formula__item--result {
	background: var(--fw-green-700);
	color: var(--fw-on-dark);
}

.fw-formula__op {
	color: var(--fw-orange-400);
	font-size: 1.5em;
}

/* ======================================================================
   That's Us — the human counterpart to the process-led Story page.

   The page is one continuous experience with a deliberate rhythm:
   hero (photograph) → letter (cream island) → orbit (dark, full bleed) →
   places (cream island) → timeline (dark, full bleed) → Vietnam (cream
   island) → manifest (dark, full bleed) → CTA. Colour therefore marks the
   change of register, exactly as it does on the Science page.

   Two structural rules hold the whole page together:
   1. Both dark chapters run FULL BLEED with border-radius: 0 and carry
      --fw-ground. A rounded dark island on a dark ground reads as a hole.
   2. Both dark chapters use position: sticky rather than a GSAP pin. Two
      pins on one page means two pin spacers, and the Science page already
      proved how easily a trigger below a spacer measures the wrong
      geometry. Sticky has no spacer and no refresh order to get wrong.
   ====================================================================== */

/* ---- Shared island geometry ---------------------------------------- */
/* The page is full bleed, so every light chapter has to bring its own
   surface — otherwise the brown ink lands on the dark green ground. */
.fw-us-vietnam > .fw-container {
	box-sizing: border-box;
	width: calc(100% - clamp(1.25rem, 4vw, 4rem));
	max-width: 92rem;
	margin-inline: auto;
	padding: clamp(2.25rem, 5vw, 4.5rem) clamp(1.25rem, 4vw, 4rem);
	background: var(--fw-surface);
	border-radius: clamp(1.4rem, 2.5vw, 2.5rem);
	overflow: hidden;
}

.fw-us-letter-section,
.fw-us-vietnam {
	padding-block: clamp(2.5rem, 6vw, 5rem);
}

/* Grid children must be allowed to shrink below their intrinsic content
   width or long German compounds create horizontal page overflow. */
.fw-us-vietnam__inner > *,
.fw-us-orbit__card > *,
.fw-us-manifest__list li > * {
	min-width: 0;
}

/* ======================================================================
   1. Hero — the team in front of the factory
   ====================================================================== */
/* THE constraint on this hero: the three of us must never sit behind text
   or a button, at any viewport. That is guaranteed by geometry, not by eye.
   The photograph fills the viewport; `object-position: 50% 100%` pins the
   frame's BOTTOM edge to the hero's bottom edge, so the product row is
   always visible and the people always occupy the same lower band of the
   frame. The headline is centred in the sky above the roof; the three
   actions lie on the strip of blue floor UNDER the product row — the
   bottles end at 91.5% of the frame height (measured), the remaining 8.5%
   is floor. scripts/audit-thats-us.mjs maps the people-and-products
   rectangle through the exact object-fit: cover transform and fails if the
   headline or a button intersects it. */
.fw-us-hero {
	position: relative;
	display: flex;
	flex-direction: column;
	height: calc(100svh - var(--fw-notice-space));
	min-height: 34rem;
	overflow: hidden;
	background: var(--fw-ground);
}

.fw-us-hero__media {
	position: relative;
	flex: 1 1 auto;
	min-height: 0;
	overflow: hidden;
}

.fw-us-hero__img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Bottom-anchored: the eight products stand on the very bottom edge of
	   the source frame, so anything less than 100% starts cropping them. */
	object-position: 50% 100%;
}

/* One uniform darkening pass over the whole frame, the same treatment the
   landing hero video uses (.fw-hero__overlay). The previous top/bottom
   green gradients tinted the photograph unevenly and read as a haze. */
.fw-us-hero__scrim {
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: rgba(34, 49, 26, 0.55);
}

/* The headline lives in the sky above the roof, centred. There is no intro
   any more: the band above the people on a 16:9 laptop is only ~150px and
   the two lines of the headline are all that fits there. */
.fw-us-hero__copy {
	position: absolute;
	inset: calc(var(--fw-header-clear) + clamp(0.75rem, 2.5vw, 2rem)) 0 auto 0;
	z-index: 2;
	display: grid;
	justify-items: center;
	text-align: center;
}

.fw-us-hero__title {
	display: grid;
	justify-items: center;
	gap: clamp(0.35rem, 0.8vw, 0.7rem);
	margin: 0;
}

/* Small uppercase label above the display line. */
.fw-us-hero__eyebrow {
	font-family: var(--fw-font-body);
	font-size: clamp(0.8rem, 1.4vw, 1.15rem);
	font-weight: 800;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--fw-accent);
}

/* "Fruit" off-white, "Warrior" in the brand yellow. Both stay on one line
   on desktop so the block keeps a predictable height above the people. The
   size uses the sky: at 1920x1080 the people start ~363px down and the
   headline ends ~270px down; the short-viewport rule below trims it. */
.fw-us-hero__word {
	display: block;
	font-family: var(--fw-font-display);
	font-size: clamp(2.1rem, 7.5vw, 9rem);
	font-weight: 700;
	line-height: 0.94;
	letter-spacing: -0.025em;
}

.fw-us-hero__word-a {
	color: var(--fw-on-dark);
}

.fw-us-hero__word-b {
	color: var(--fw-accent);
}

/* The actions lie on the floor strip under the products, vertically
   centred in it. The strip is the bottom 8.5% of the rendered frame, and
   with object-fit: cover the rendered height is max(0.667vw, 100svh), so
   half the strip is max(2.83vw, 4.25svh); subtracting half the button's
   height puts the button's centre on the strip's centre. ~100px at
   1920x1080 but only ~68px at 1280x720, so short viewports get the small
   button size (see the max-height rules below). */
.fw-us-hero__actions {
	--fw-us-btn-half: 25px;
	position: absolute;
	inset: auto 0 calc(max(2.83vw, 4.25svh) - var(--fw-us-btn-half)) 0;
	z-index: 2;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.75rem;
}

/* ======================================================================
   2. The letter
   ====================================================================== */
/* The section IS the sheet of paper. Previously a 92rem island held a 62rem
   text column, so the copy floated in the middle of a very wide cream slab
   with a lot of air on both sides — nothing like a letter. Now the sheet is
   sized like a sheet, the text runs close to its edges, and the paper cues
   are quiet: a fine edge, a small radius (paper is not round), a lifted
   shadow and a ruled left margin. */
.fw-us-letter-section > .fw-container {
	box-sizing: border-box;
	width: calc(100% - clamp(1.25rem, 4vw, 3rem));
	max-width: 58rem;
	margin-inline: auto;
	padding: clamp(1.75rem, 4vw, 3.25rem) clamp(1.5rem, 3.5vw, 3rem);
	background: var(--fw-surface);
	border: 1px solid var(--fw-rule-soft);
	border-radius: 6px;
	box-shadow: 0 26px 60px -30px rgba(0, 0, 0, 0.55);
}

/* Deliberately NOT a grid. The margin rule was a grid item spanning
   `grid-row: 1 / -1`, but -1 resolves against the EXPLICIT grid, and with no
   grid-template-rows the explicit grid has none — so the span collapsed to a
   single row and the reading rule only ran beside the salutation. Absolute
   positioning inside the relative article spans the real height by
   definition and needs no row bookkeeping. */
.fw-us-letter {
	position: relative;
	padding-left: clamp(1rem, 2.5vw, 2rem);
}

.fw-us-letter__margin {
	position: absolute;
	left: 0;
	top: 0;
	bottom: 0;
	width: 2px;
	border-radius: 2px;
	background: var(--fw-rule-soft);
}

/* Green, not the brand yellow: on letter paper a bright yellow bar reads as
   exactly the kind of highlight this letter was asked to drop. */
.fw-us-letter__progress {
	position: absolute;
	inset: 0 0 auto 0;
	height: 0;
	border-radius: 2px;
	background: var(--fw-green-600);
}

/* Tight: "Liebes Europa," and "wir freuen uns…" are one sentence. */
.fw-us-letter__head {
	margin-bottom: clamp(0.75rem, 1.5vw, 1.25rem);
}

/* The date line of a letter sits at the top right of the sheet. */
.fw-us-letter__place {
	margin: 0 0 1.5rem;
	text-align: right;
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--fw-ink-soft);
}

.fw-us-letter__salutation {
	margin: 0;
	font-size: clamp(1.6rem, 3.4vw, 2.6rem);
	line-height: 1.1;
}

.fw-us-letter__body {
	max-width: 100%;
}

.fw-us-letter__body p {
	margin: 0 0 1.15em;
	font-size: clamp(1rem, 1.25vw, 1.1rem);
	line-height: 1.72;
	max-width: 62ch;
}

.fw-us-letter__lead {
	font-size: clamp(1.1rem, 1.7vw, 1.35rem) !important;
	font-weight: 600;
}

/* The names are stylistically offset, not semantically emphasised — hence
   <b>. No underline and no highlight: this is a letter, and a drawn-on
   marker rule made it read as a marketing page. Weight alone is enough. */
.fw-us-letter__body b {
	font-weight: 700;
}

/* Body → tagline → valediction → signature, the order of the owner's letter. */
.fw-us-letter__signoff {
	margin-top: clamp(1.75rem, 4vw, 2.75rem);
}

.fw-us-letter__valediction {
	margin: 0 0 0.15rem;
	font-size: 1rem;
	color: var(--fw-ink);
}

/* The signature is the only handwritten element on the sheet — Caveat is
   already vendored for the Story photo wall. */
.fw-us-letter__signature {
	margin: 0;
	font-family: 'Caveat', var(--fw-font-body);
	font-size: clamp(1.85rem, 3.6vw, 2.6rem);
	font-weight: 700;
	line-height: 1.1;
	color: var(--fw-heading);
}

/* The slogan closes the body as a quiet printed line, not a heading: at
   display size it once read as a section heading interrupting the letter. */
.fw-us-letter__body .fw-us-letter__tagline {
	margin: clamp(1.25rem, 3vw, 2rem) 0 0;
	font-size: 0.78rem !important;
	font-weight: 800;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--fw-ink);
}

/* ======================================================================
   3. Orbit — the page signature
   ====================================================================== */
/* A bearing sits at the left edge, vertically centred. Two arms hinge on it
   and swing clockwise through the viewport, each carrying one portrait and
   its text. The choreography is driven by three separate scrubbed triggers
   (see animations.js::initUsOrbit) so each phase has trivially correct
   geometry:
     entry     the section scrolls in, arm 1 rises from -100° to horizontal
               and arrives exactly as the bearing reaches the viewport centre
     handover  the stage is stuck; arm 1 swings out downwards while arm 2
               comes down from above and reaches horizontal
     exit      the stage rides up with the page again while arm 2 leaves
               through the bottom-left corner
   The stage clips its own overflow. Without that, an arm rotated to ±100°
   would extend the page's scroll width on every viewport. */
.fw-us-orbit {
	position: relative;
	background: var(--fw-ground);
	color: var(--fw-on-dark);
	border-radius: 0;

	/* Geometry, all in one place.

	   Two of these numbers are load bearing and were both wrong first time:
	   --fw-orbit-rod has to be clearly LONGER than half of --fw-orbit-hub,
	   or the bearing's own disc covers the whole rod and the linkage never
	   reads — the card just appears to float. And the card needs a hard max
	   width: stretched to the right edge it was ~1430px, and a slab that
	   size sweeps the entire viewport as it rotates, which looks like a
	   layout fault rather than an arm carrying something. */
	/* The slice is the wheel the cards hang on, so it has to hold its own
	   against a card over 1000px wide (2026-09-29: at 10vw it read as a
	   sticker beside a floating box). */
	--fw-orbit-x: clamp(5rem, 9vw, 10rem);
	/* The pivot sits in the middle of what is visible BELOW the fixed
	   header, not of the whole viewport (owner, 2026-09-30: on a small
	   laptop the card sat low, with the spare room above it). */
	--fw-orbit-y: calc(50% + var(--fw-header-h) / 2);
	--fw-orbit-hub: clamp(150px, 15vw, 250px);
	/* Long enough that the painted spoke is thick: its height follows its
	   length through the image's aspect ratio. */
	--fw-orbit-rod: clamp(11rem, 17vw, 19rem);
	--fw-orbit-gutter: clamp(1.25rem, 3vw, 3rem);
	--fw-orbit-card: 78rem;
	/* The card's thickness, seen from below. */
	--fw-orbit-edge: #d6bf82;
}

.fw-us-orbit__track {
	height: 320svh;
}

.fw-us-orbit__stage {
	position: sticky;
	top: 0;
	height: 100svh;
	overflow: hidden;
}

/* The pivot: a painted pineapple slice, turned by JS as the arms swing (it
   replaced a drawn rolling-element bearing on 2026-09-18). The ground
   around it is plain green — the earlier glow, dashed tracks and doodle
   mural were removed by the owner. */
.fw-us-orbit__bearing {
	position: absolute;
	left: var(--fw-orbit-x);
	top: var(--fw-orbit-y);
	z-index: 3;
	width: var(--fw-orbit-hub);
	height: var(--fw-orbit-hub);
	transform: translate(-50%, -50%);
	filter: drop-shadow(0 6px 6px rgba(0, 0, 0, 0.3)) drop-shadow(0 22px 34px rgba(0, 0, 0, 0.42));
}

.fw-us-orbit__slice {
	display: block;
	width: 100%;
	height: 100%;
	will-change: transform;
}

.fw-us-orbit__arms {
	position: absolute;
	inset: 0;
	z-index: 2;
}

/* A zero-height bar hinged on the bearing. Its children hang off the axis,
   so rotating the bar rotates rod and card together as one linkage. */
.fw-us-orbit__arm {
	position: absolute;
	left: var(--fw-orbit-x);
	top: var(--fw-orbit-y);
	height: 0;
	width: calc(100vw - var(--fw-orbit-x) - var(--fw-orbit-gutter));
	transform-origin: 0 0;
	transform: rotate(-100deg);
	will-change: transform;
}

/* Light comes from above. main.js writes --fw-orbit-sx / --fw-orbit-sy on
   each arm (sin and cos of its angle): a shadow offset of (sx, sy) × d in
   the arm's own, rotated coordinates always lands straight below it on
   screen. A shadow fixed to the card turned with it and fell upwards or
   sideways mid-swing, which flattened everything (2026-09-29). Without
   JS the defaults are the unrotated case. */
.fw-us-orbit__arm {
	--fw-orbit-sx: 0;
	--fw-orbit-sy: 1;
}

/* The spoke is painted in the slice's own gouache (owner, 2026-09-30: the
   CSS bar with a rivet still looked like a part, not like the fruit). It
   is the pineapple core — the very piece punched out of the slice's
   centre — keyed out by scripts/thats-us-media.php. Both of its ends are
   hidden: it starts under the flesh, a quarter of the slice out from the
   centre (so the core hole shows the green ground), and runs on under the
   card's edge, as if the card were pushed onto it. Its thickness follows
   its length through the image's aspect ratio (1024 × 142). */
.fw-us-orbit__rod {
	--fw-orbit-spoke-in: 2.25rem;
	position: absolute;
	z-index: 0;
	left: calc(var(--fw-orbit-hub) * 0.25);
	top: 0;
	width: calc(var(--fw-orbit-rod) - var(--fw-orbit-hub) * 0.25 + var(--fw-orbit-spoke-in));
	aspect-ratio: 1024 / 142;
	transform: translateY(-50%);
	background: url('../img/thats-us/1024/spoke-core.webp') center / 100% 100% no-repeat;
	filter: drop-shadow(calc(var(--fw-orbit-sx) * 9px) calc(var(--fw-orbit-sy) * 9px) 7px rgba(10, 18, 6, 0.5));
}

/* --fw-orbit-depth (1 at horizontal, smaller as the arm swings away) is
   also written by main.js: the card recedes towards the hinge. */
.fw-us-orbit__card {
	position: absolute;
	z-index: 1;
	left: var(--fw-orbit-rod);
	top: 0;
	width: min(calc(100vw - var(--fw-orbit-x) - var(--fw-orbit-rod) - var(--fw-orbit-gutter)), var(--fw-orbit-card));
	transform: translateY(-50%) scale(var(--fw-orbit-depth, 1));
	transform-origin: 0 50%;
	display: grid;
	grid-template-columns: clamp(12rem, 21vw, 24rem) minmax(0, 1fr);
	align-items: center;
	overflow: hidden;
	border-radius: clamp(1rem, 1.6vw, 1.5rem);
	background: linear-gradient(165deg, #fff5da 0%, var(--fw-surface) 42%);
	color: var(--fw-ink);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.7),
		calc(var(--fw-orbit-sx) * 7px) calc(var(--fw-orbit-sy) * 7px) 0 var(--fw-orbit-edge),
		calc(var(--fw-orbit-sx) * 18px) calc(var(--fw-orbit-sy) * 18px) 24px -6px rgba(10, 18, 6, 0.5),
		calc(var(--fw-orbit-sx) * 64px) calc(var(--fw-orbit-sy) * 64px) 90px -22px rgba(8, 14, 4, 0.62);
}

/* The portrait is the card's stage: flush with the hinge side, full
   height, with place and name set on it over a dark scrim. */
.fw-us-orbit__photo {
	position: relative;
	margin: 0;
	align-self: stretch;
	overflow: hidden;
	background: var(--fw-green-600);
}

.fw-us-orbit__photo img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: 50% 22%;
}

.fw-us-orbit__photo::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(to top, rgba(20, 31, 12, 0.9) 0%, rgba(20, 31, 12, 0.55) 30%, rgba(20, 31, 12, 0) 58%);
	pointer-events: none;
}

.fw-us-orbit__caption {
	position: absolute;
	z-index: 1;
	left: 0;
	right: 0;
	bottom: 0;
	padding: clamp(1rem, 1.8vw, 1.75rem);
}

.fw-us-orbit__copy {
	position: relative;
	padding: clamp(1.25rem, 2.4vw, 2.5rem);
}

.fw-us-orbit__copy > * {
	margin: 0 0 0.6em;
}

.fw-us-orbit__copy > *:last-child {
	margin-bottom: 0;
}

/* Place and name sit on the photograph's dark scrim, so the yellow is
   allowed here — and only here: yellow on the cream of the card itself
   drops to about 1.6:1 (the audit checks both). */
.fw-us-orbit__place {
	margin: 0 0 0.35rem;
	font-size: 0.74rem;
	font-weight: 800;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--fw-accent);
}

.fw-us-orbit__card .fw-us-orbit__caption .fw-us-orbit__name {
	margin: 0;
	color: var(--fw-on-dark);
	font-size: clamp(1.9rem, 3.1vw, 3.4rem);
	line-height: 0.95;
	letter-spacing: -0.035em;
	text-shadow: 0 2px 18px rgba(10, 18, 6, 0.45);
	overflow-wrap: break-word;
}

/* The biographies are long (three to four paragraphs each), so they run
   in two columns: a single column of that length is taller than a laptop
   viewport, and the card has to fit the viewport at the dwell. */
.fw-us-orbit__text {
	columns: 2;
	column-gap: clamp(1.25rem, 2.2vw, 2rem);
}

/* Justified, as the owner asked for the long biographies (2026-09-29).
   German justification without hyphenation opens wide gaps between long
   compounds, so hyphens: auto is part of the rule, not an option. */
.fw-us-orbit__text p {
	margin: 0 0 0.7em;
	font-size: clamp(0.9rem, 1vw, 1.05rem);
	line-height: 1.55;
	text-align: justify;
	hyphens: auto;
	-webkit-hyphens: auto;
	hyphenate-limit-chars: 6 3 3;
}

/* On desktop the portrait is a full-height plate beside the two text
   columns: the figure stretches to the row and the image covers it, so
   the text alone decides the card height and the photo never looks like a
   thumbnail next to three paragraphs. Phones keep the 4:3 crop. */
@media (min-width: 861px) {
	/* The card uses the height below the header, less a margin top and
	   bottom, so the portrait grows and the copy breathes instead of
	   leaving empty green above and below (owner, 2026-09-30). */
	.fw-us-orbit__card {
		align-items: stretch;
		min-height: min(calc(100svh - var(--fw-header-h) - 7rem), 46rem);
	}

	.fw-us-orbit__photo {
		min-height: 0;
	}

	.fw-us-orbit__photo img {
		position: absolute;
		inset: 0;
		height: 100%;
		aspect-ratio: auto;
		object-position: 50% 30%;
	}

	.fw-us-orbit__copy {
		align-self: center;
	}
}

/* Large screens (owner, 2026-09-29: the page looked empty at 2500 px).
   The text keeps its size and a capped measure; the photograph takes the
   rest of a wider card, and the card grows taller, so the extra space goes
   to the portrait instead of to longer lines or bigger type. */
@media (min-width: 1700px) and (min-height: 901px) {
	.fw-us-orbit {
		--fw-orbit-card: 124rem;
	}

	/* The measure is widened with the photo: justified columns narrower
	   than ~45 characters open visible gaps between words. */
	.fw-us-orbit__card {
		grid-template-columns: minmax(24rem, 1fr) minmax(0, 64rem);
		min-height: min(54svh, 44rem);
	}

	.fw-us-orbit__text p {
		font-size: 1.1rem;
	}

	/* The name scales with the photograph it stands on. */
	.fw-us-orbit__card .fw-us-orbit__caption .fw-us-orbit__name {
		font-size: clamp(3.4rem, 3.4vw, 5rem);
	}
}

/* ======================================================================
   4. Timeline — a horizontal rail, scrubbed sideways
   ====================================================================== */
/* Vertical timelines are the default and read as a list. This one moves
   sideways under a stuck stage, which is what makes a span of ten years
   feel like a distance travelled. Two lanes: the Vietnamese company above
   the axis, Europe below it. The Europe lane is deliberately empty before
   2026 — that emptiness is the honest statement, not a gap to fill. */
.fw-us-timeline {
	position: relative;
	background: var(--fw-ground);
	color: var(--fw-on-dark);
	border-radius: 0;
}

.fw-us-timeline__track {
	height: 300svh;
}

.fw-us-timeline__stage {
	position: sticky;
	top: 0;
	height: 100svh;
	display: grid;
	grid-template-rows: auto minmax(0, 1fr) auto;
	align-content: center;
	gap: clamp(1rem, 3vw, 2.5rem);
	padding-block: calc(var(--fw-header-h) + clamp(1rem, 3vw, 2.5rem)) clamp(1.5rem, 4vw, 3rem);
	overflow: hidden;
}

.fw-us-timeline__head {
	padding-inline: var(--fw-gutter);
	max-width: 46rem;
	margin-inline: auto;
	text-align: center;
}

.fw-us-timeline__head h2 {
	margin: 0;
	font-size: clamp(1.6rem, 3.4vw, 2.75rem);
	line-height: 1.1;
}

.fw-us-timeline__viewport {
	overflow: hidden;
	display: flex;
	align-items: stretch;
}

/* The rail takes the full height of the stage's middle row and the items
   take the full height of the rail, so the two card lanes always get half
   of whatever is actually left over. A fixed item height was a guess about
   viewport height, and at 900px it cut the bottom line off every card
   below the axis. */
.fw-us-timeline__rail {
	position: relative;
	width: max-content;
	height: 100%;
	padding-inline: var(--fw-gutter);
	will-change: transform;
}

.fw-us-timeline__axis {
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 2px;
	transform: translateY(-50%);
	background: rgba(239, 237, 228, 0.22);
}

.fw-us-timeline__axis-fill {
	position: absolute;
	inset: 0 auto 0 0;
	width: 0;
	background: var(--fw-accent);
}

.fw-us-timeline__items {
	position: relative;
	display: flex;
	align-items: stretch;
	height: 100%;
	gap: clamp(1.25rem, 3vw, 2.75rem);
	list-style: none;
	margin: 0;
	padding: 0;
}

/* 34vw, not 24vw: the cap does the work on wide screens, while narrow
   desktops and tablets get a card wide enough for the year and three lines
   of German to stay legible instead of being squeezed to 15rem. */
.fw-us-timeline__item {
	flex: 0 0 auto;
	width: clamp(16.5rem, 34vw, 22rem);
	height: 100%;
	display: grid;
	grid-template-rows: minmax(0, 1fr) auto minmax(0, 1fr);
	align-items: center;
}

.fw-us-timeline__dot {
	grid-row: 2;
	justify-self: start;
	width: 1.05rem;
	height: 1.05rem;
	border-radius: 50%;
	background: var(--fw-ground);
	border: 2px solid rgba(239, 237, 228, 0.4);
	box-shadow: 0 0 0 5px var(--fw-ground);
	z-index: 2;
	transition: background-color 0.25s var(--fw-ease), border-color 0.25s var(--fw-ease);
}

/* Set by the scrub once the axis fill has passed the milestone. Without JS
   the dots stay as hollow outlines, which is still a legible timeline. */
.fw-us-timeline__item.is-reached .fw-us-timeline__dot {
	background: var(--fw-accent);
	border-color: var(--fw-accent);
}

/* Dimming the not-yet-reached cards is an ENHANCEMENT, so it is gated on a
   class the scrub adds. Written the other way round — dim by default, lifted
   by .is-reached — a visitor without JavaScript would read the entire
   timeline at 55% opacity, because nothing would ever add the class. */
/* 0.72, not 0.55: the not-yet-reached state is a de-emphasis, not a
   readability trade — at 0.55 the off-white on the deep green fell below
   comfortable reading contrast on the cards still ahead of the fill. */
.fw-us-timeline.is-scrubbed .fw-us-timeline__card {
	opacity: 0.72;
	transition: opacity 0.3s var(--fw-ease);
}

.fw-us-timeline.is-scrubbed .fw-us-timeline__item.is-reached .fw-us-timeline__card {
	opacity: 1;
}

.fw-us-timeline__card {
	padding-block: clamp(0.75rem, 2vw, 1.25rem);
}

/* Cards alternate above and below the axis. An earlier version put the
   Vietnamese milestones above and the single European one below, which is
   the more literal reading of "two companies" — but with six entries in one
   lane and one in the other it left the whole lower half of the screen
   empty for the entire scrub, and that read as a broken layout rather than
   as a young European lane. Company is carried by the lane label and the
   dot colour instead, which says the same thing without the dead space. */
.fw-us-timeline__item:nth-child(odd) .fw-us-timeline__card {
	grid-row: 1;
	align-self: end;
}

.fw-us-timeline__item:nth-child(even) .fw-us-timeline__card {
	grid-row: 3;
	align-self: start;
}

.fw-us-timeline__card > * {
	margin: 0 0 0.4em;
}

.fw-us-timeline__lane {
	font-size: 0.68rem;
	font-weight: 800;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	/* --fw-green-200 (#b5c994) lifted 3 % towards white: 4.50 : 1 on the
	   ground instead of 4.41 for this small text (owner, 2026-10-13). */
	color: #b7cb97;
}

/* Yellow marks Fruit Warrior itself. The 2023 card sits in the Europe
   lane but is still FUWA3E, so it keeps the plain label (owner, 2026-10-06). */
.fw-us-timeline__item--eu .fw-us-timeline__lane:not(.fw-us-timeline__lane--fuwa3e) {
	color: var(--fw-accent);
}

.fw-us-timeline__year {
	font-family: var(--fw-font-display);
	font-size: clamp(2.9rem, 5vw, 4rem);
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: -0.02em;
	color: var(--fw-on-dark);
}

.fw-us-timeline__card h3 {
	font-size: clamp(1.05rem, 1.7vw, 1.35rem);
	line-height: 1.2;
}

.fw-us-timeline__text {
	font-size: clamp(0.94rem, 1.05vw, 1rem);
	line-height: 1.6;
	color: rgba(239, 237, 228, 0.86);
}

.fw-us-timeline__hint {
	margin: 0;
	text-align: center;
	font-size: 0.75rem;
	font-weight: 800;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: rgba(239, 237, 228, 0.55);
}

/* ======================================================================
   5. Vietnam — FUWA3E, the Vietnamese origin
   ====================================================================== */
/* A wide band plus a two-column copy row. An earlier version floated the
   copy over the photograph's bottom-right corner, which looked good in
   isolation but left a large empty cream L at bottom-left with nothing in
   it — and pushing the overlap far enough to close that gap started
   covering the faces the section exists to show. */
.fw-us-vietnam__inner {
	display: grid;
	gap: clamp(1.5rem, 3.5vw, 3rem);
}

.fw-us-vietnam__figure {
	margin: 0;
	border-radius: clamp(0.9rem, 1.6vw, 1.4rem);
	overflow: hidden;
	background: var(--fw-home-wash);
}

/* A 3:2 crop at island width is nearly 900px tall on a laptop and fills the
   whole viewport on its own. The band keeps all nineteen people readable at
   a height the section can afford. */
.fw-us-vietnam__figure img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 21 / 9;
	object-fit: cover;
	object-position: 50% 42%;
}

.fw-us-vietnam__copy {
	display: grid;
	grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
	gap: clamp(1.5rem, 4vw, 4rem);
	align-items: start;
}

.fw-us-vietnam__head > *,
.fw-us-vietnam__text > * {
	margin: 0 0 1em;
}

.fw-us-vietnam__head > *:last-child {
	margin-bottom: 0;
}

.fw-us-vietnam__text > *:last-child {
	margin-bottom: 0;
	margin-top: 0.5em;
}

.fw-us-vietnam__copy h2 {
	font-size: clamp(1.8rem, 3.4vw, 2.9rem);
	line-height: 1.08;
	letter-spacing: -0.015em;
}

.fw-us-vietnam__text p {
	font-size: clamp(1rem, 1.2vw, 1.15rem);
	line-height: 1.65;
}

/* ======================================================================
   6. Manifest — the typographic close
   ====================================================================== */
.fw-us-manifest {
	background: var(--fw-ground);
	color: var(--fw-on-dark);
	border-radius: 0;
	padding-block: clamp(4rem, 10vw, 8.5rem);
}

.fw-us-manifest__inner {
	max-width: 72rem;
}

.fw-us-manifest__statement {
	display: grid;
	gap: clamp(0.15rem, 0.6vw, 0.5rem);
	margin: 0 0 clamp(2.5rem, 6vw, 4.5rem);
	font-size: clamp(1.9rem, 5.4vw, 4.6rem);
	line-height: 1.02;
	letter-spacing: -0.025em;
}

.fw-us-manifest__line {
	display: block;
	/* Held for the wipe reveal; without JS the clip stays open. */
	color: var(--fw-on-dark);
}

/* The rejected alternative is dimmed rather than coloured: yellow on a
   negative statement would read as an endorsement. 0.66 keeps it above AA
   against the ground. */
.fw-us-manifest__line--counter {
	color: rgba(239, 237, 228, 0.66);
}

.fw-us-manifest__list {
	list-style: none;
	margin: 0 0 clamp(3rem, 7vw, 5rem);
	padding: 0;
	border-top: 1px solid rgba(239, 237, 228, 0.22);
}

.fw-us-manifest__list li {
	display: grid;
	grid-template-columns: auto minmax(0, 22ch) minmax(0, 1fr);
	gap: clamp(1rem, 3vw, 2.5rem);
	align-items: start;
	padding: clamp(1.1rem, 2.6vw, 1.9rem) 0;
	border-bottom: 1px solid rgba(239, 237, 228, 0.22);
}

.fw-us-manifest__num {
	font-family: var(--fw-font-display);
	font-size: clamp(1rem, 1.6vw, 1.3rem);
	font-weight: 700;
	color: var(--fw-accent);
}

.fw-us-manifest__list h3 {
	margin: 0;
	font-size: clamp(1.1rem, 2vw, 1.6rem);
	line-height: 1.15;
}

.fw-us-manifest__list p {
	margin: 0;
	font-size: clamp(0.92rem, 1.15vw, 1.05rem);
	line-height: 1.65;
	color: rgba(239, 237, 228, 0.82);
}

.fw-us-manifest__call {
	margin: 0;
	font-family: var(--fw-font-display);
	font-size: clamp(2rem, 6.4vw, 5.4rem);
	font-weight: 700;
	line-height: 0.98;
	letter-spacing: -0.03em;
	color: var(--fw-accent);
}

/* Two lines: the invitation in off-white, the promise in the brand yellow
   (owner, 2026-09-18). */
.fw-us-manifest__call span {
	display: block;
}

.fw-us-manifest__call-a {
	color: var(--fw-on-dark);
}

/* ======================================================================
   Responsive
   ====================================================================== */

/* Laptops: the orbit card has to stop competing with the viewport height. */
@media (max-width: 1250px) {
	.fw-us-orbit__card {
		grid-template-columns: clamp(8rem, 22vw, 12rem) minmax(0, 1fr);
	}

	.fw-us-vietnam__copy {
		gap: clamp(1.25rem, 3vw, 2rem);
	}
}

/* Tablets and phones: the orbit cannot work — a horizontal arm swinging a
   photo-plus-text card needs width that does not exist. The chapter becomes
   an ordinary stacked pair, the bearing becomes a small mark above it, and
   the timeline turns vertical. Both stages stop being sticky, so nothing
   is left pinned around content that no longer moves. */
@media (max-width: 860px) {
	/* -- Hero: the photograph does not fill the phone screen. A viewport-
	      high portrait crop would cut Lars and Louis off at the shoulders,
	      so the frame is cropped to 12:13 instead: with the bottom anchor
	      that shows 61% of the frame's width, x 0.19–0.81, and the people
	      span 0.20–0.76. The headline stays in the sky; the actions are
	      dropped entirely (owner decision 2026-09-18: the floor strip is
	      ~35px there, and a band of three buttons under the photograph
	      pushed the letter off the first screen). -- */
	.fw-us-hero {
		height: auto;
		min-height: 0;
	}

	.fw-us-hero__media {
		flex: none;
		aspect-ratio: 12 / 13;
	}

	.fw-us-hero__actions {
		display: none;
	}

	/* -- Letter: the reading rule needs width the phone does not have. -- */
	.fw-us-letter {
		padding-left: 0;
	}

	.fw-us-letter__margin {
		display: none;
	}

	/* -- Orbit -- */
	.fw-us-orbit {
		padding-block: clamp(2.5rem, 8vw, 4rem);
	}

	.fw-us-orbit__track {
		height: auto;
	}

	/* Phones: no pivot. The cards are as wide as the other cream islands
	   (same side margin as .fw-us-vietnam > .fw-container, rounded corners
	   kept); before, the desktop width calc still applied and left them
	   visibly narrower than the letter above (owner, 2026-09-18). */
	.fw-us-orbit__stage {
		position: static;
		height: auto;
		overflow: visible;
		display: grid;
		gap: clamp(1.5rem, 5vw, 2.5rem);
		padding-inline: calc(clamp(1.25rem, 4vw, 4rem) / 2);
	}

	.fw-us-orbit__bearing {
		display: none;
	}

	.fw-us-orbit__rod {
		display: none;
	}

	.fw-us-orbit__text {
		columns: 1;
	}

	.fw-us-orbit__arms {
		position: static;
		display: grid;
		gap: clamp(1.5rem, 5vw, 2.5rem);
	}

	.fw-us-orbit__arm {
		position: static;
		width: auto;
		height: auto;
		transform: none;
	}

	.fw-us-orbit__card {
		position: static;
		transform: none;
		width: auto;
		grid-template-columns: minmax(0, 1fr);
	}

	.fw-us-orbit__photo img {
		aspect-ratio: 4 / 3;
		object-position: 50% 30%;
	}

	/* -- Timeline: vertical, no stage, no horizontal scrub -- */
	.fw-us-timeline__track {
		height: auto;
	}

	.fw-us-timeline__stage {
		position: static;
		height: auto;
		overflow: visible;
		padding-block: clamp(2.5rem, 8vw, 4rem);
	}

	.fw-us-timeline__viewport {
		overflow: visible;
		display: block;
	}

	.fw-us-timeline__rail {
		width: auto;
		transform: none !important;
	}

	.fw-us-timeline__axis {
		left: 0.5rem;
		right: auto;
		top: 0;
		bottom: 0;
		width: 2px;
		height: auto;
		transform: none;
	}

	.fw-us-timeline__axis-fill {
		inset: 0 0 auto 0;
		width: 100%;
		height: 0;
	}

	.fw-us-timeline__items {
		flex-direction: column;
		gap: clamp(1.5rem, 5vw, 2.25rem);
		padding-left: 2rem;
	}

	.fw-us-timeline__item {
		width: auto;
		height: auto;
		display: grid;
		grid-template-rows: none;
		grid-template-columns: minmax(0, 1fr);
		position: relative;
	}

	/* grid-row MUST be reset here. An absolutely positioned grid child takes
	   its GRID AREA as containing block, so the inherited `grid-row: 2` from
	   the desktop rule anchored every dot to the implicit row after its
	   card — the dots rendered one milestone too low down the whole rail. */
	.fw-us-timeline__dot {
		position: absolute;
		grid-row: 1;
		left: -1.98rem;
		top: 0.55rem;
	}

	.fw-us-timeline__item--vn .fw-us-timeline__card,
	.fw-us-timeline__item--eu .fw-us-timeline__card {
		grid-row: auto;
		align-self: auto;
	}

	.fw-us-timeline__hint {
		display: none;
	}

	/* -- Vietnam -- */
	.fw-us-vietnam__copy {
		grid-template-columns: minmax(0, 1fr);
	}

	.fw-us-vietnam__figure img {
		aspect-ratio: 3 / 2;
	}

	/* -- Manifest -- */
	.fw-us-manifest__list li {
		grid-template-columns: auto minmax(0, 1fr);
		gap: 0.5rem 1rem;
	}

	.fw-us-manifest__list h3 {
		grid-column: 2;
	}

	.fw-us-manifest__list p {
		grid-column: 2;
	}
}

/* Short desktop viewports: the orbit card carries ~300 words and has to fit
   the viewport at the dwell — a narrower photo column and tighter type buy
   the height (verified by the card-fits-viewport check in the audit). */
@media (min-width: 861px) and (max-height: 900px) {
	.fw-us-orbit__card {
		grid-template-columns: clamp(10rem, 17vw, 14rem) minmax(0, 1fr);
	}

	.fw-us-orbit__copy {
		padding: 1rem 1.4rem;
	}

	.fw-us-orbit__card .fw-us-orbit__caption .fw-us-orbit__name {
		font-size: clamp(1.6rem, 2.5vw, 2.4rem);
	}

	.fw-us-orbit__text p {
		font-size: 0.88rem;
		line-height: 1.48;
		margin-bottom: 0.55em;
	}
}

/* Very short laptops (1280x720): Huong's rewritten biography (owner,
   2026-10-16) ran ~20px past the viewport at the dwell; slightly tighter
   leading brings it back without touching the type size. */
@media (min-width: 861px) and (max-height: 740px) {
	.fw-us-orbit__text p {
		line-height: 1.42;
	}
}

/* Narrow and short at once (1024x768 landscape tablets): Huong's six-
   paragraph biography (2026-10-06) ran ~100px taller than the viewport.
   A narrower photo plate and slightly smaller type bring it back inside. */
@media (min-width: 861px) and (max-width: 1100px) and (max-height: 900px) {
	.fw-us-orbit__card {
		grid-template-columns: clamp(8rem, 14vw, 10rem) minmax(0, 1fr);
	}

	.fw-us-orbit__text p {
		font-size: 0.84rem;
		line-height: 1.42;
	}
}

/* Short desktop viewports: the floor strip under the products is ~61px at
   1024x768 and ~68px at 1280x720, so the actions take the small button
   size and sit close to the bottom edge there. */
@media (min-width: 861px) and (max-height: 900px) {
	.fw-us-hero__actions {
		--fw-us-btn-half: 19.5px;
	}

	.fw-us-hero__actions .fw-btn {
		padding: 0.55rem 1.15rem;
		font-size: 0.9rem;
	}
}

/* Wide but short — the 16:9 laptop sizes. A 3:2 photograph bottom-anchored
   in a 16:9 viewport leaves only ~150px of clear band above the people at
   1366x768. The headline sits directly under the fixed header and drops a
   step so both of its lines stay in the sky. 1024x768 is deliberately
   excluded: its crop is height-driven, so it has the room to spare. */
@media (min-width: 1200px) and (max-height: 900px) {
	.fw-us-hero__copy {
		inset: calc(var(--fw-header-clear) + 0.25rem) 0 auto 0;
	}

	.fw-us-hero__title {
		gap: 0.25rem;
	}

	.fw-us-hero__word {
		font-size: clamp(2rem, 6vw, 5rem);
	}
}

/* ---------------------------------------------------------------------
   Timeline on short desktop viewports (14" laptops and anything below a
   1000px tall window).

   The two card lanes have to fit into HALF the space left over after the
   heading and the padding, and at the generous metrics they do not: at
   1366x768 a card needed ~239px against ~196px of lane, so the year was cut
   off every card above the axis and the body text off every card below it.
   The clipper is .fw-us-timeline__viewport, and it clips silently.

   Everything below is height budget, not taste: a smaller heading, tighter
   gaps and padding, a smaller year, and the scroll hint dropped. Verified by
   the clipping check in scripts/audit-thats-us.mjs at 1512x945, 1440x790,
   1366x768, 1280x720 and 1024x768.
   ------------------------------------------------------------------- */
@media (min-width: 861px) and (max-height: 1000px) {
	.fw-us-timeline__stage {
		gap: 0.9rem;
		padding-block: calc(var(--fw-header-h) + 0.75rem) 1rem;
	}

	.fw-us-timeline__head h2 {
		font-size: clamp(1.4rem, 2.2vw, 1.9rem);
	}

	.fw-us-timeline__hint {
		display: none;
	}

	.fw-us-timeline__year {
		font-size: clamp(2.2rem, 3.6vw, 3rem);
	}

	.fw-us-timeline__card {
		padding-block: 0.5rem;
	}

	.fw-us-timeline__text {
		line-height: 1.5;
	}
}

/* Very small phones. */
@media (max-width: 480px) {
	.fw-us-hero__word {
		font-size: clamp(1.9rem, 10vw, 2.6rem);
	}
}

/* Reduced motion: everything that JS would animate has to be complete and
   readable at rest. The letter's reading rule fills, the seam is drawn, the
   timeline axis is filled and the manifest lines are unclipped. */
@media (prefers-reduced-motion: reduce) {
	.fw-us-letter__progress {
		height: 100%;
	}

	.fw-us-timeline__axis-fill {
		width: 100%;
	}
}

/* Contact page */
/* The form card and the three sidebar cards stand directly on the ground
   as separate islands (owner, 2026-09-18: one shared island with a ruled
   sidebar was tried and rejected). The section drops its bottom padding so
   the FAQ banner follows closely. */
.fw-contact {
	padding-top: 0;
	padding-bottom: 0;
}

.fw-contact + .fw-cta-banner {
	padding-top: clamp(1.5rem, 3vw, 2.5rem);
}

.fw-contact-grid {
	display: grid;
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: start;
}

.fw-contact-form {
	background: var(--fw-surface);
	border-radius: var(--fw-radius-l);
	padding: clamp(1.5rem, 4vw, 2.75rem);
}

.fw-contact-form h2 {
	margin: 0 0 1.25rem;
	font-size: clamp(1.5rem, 2.4vw, 1.9rem);
}

.fw-contact-aside {
	display: grid;
	gap: 1.25rem;
}

.fw-contact-aside__mail {
	display: inline-block;
	margin-top: 0.6rem;
	font-family: var(--fw-font-display);
	font-weight: 700;
	font-size: clamp(1.1rem, 1.6vw, 1.3rem);
	line-height: 1.2;
	color: var(--fw-green-700);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.fw-contact-aside__mail:hover,
.fw-contact-aside__mail:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.fw-contact-aside .fw-benefit-list {
	margin: 0;
}

/* Form fields: a quiet white field with the ink hairline;
   the green border on focus replaces Astra's blue. */
.wpcf7 input:not([type='submit']):not([type='checkbox']),
.wpcf7 select,
.wpcf7 textarea {
	padding: 0.75rem 0.95rem;
	border: 1.5px solid var(--fw-rule);
	border-radius: var(--fw-radius-s);
	background: #fff;
	color: var(--fw-ink);
	font-family: var(--fw-font-body);
	font-size: 1rem;
	transition: border-color 0.2s var(--fw-ease);
}

.wpcf7 input:not([type='submit']):not([type='checkbox']):focus,
.wpcf7 select:focus,
.wpcf7 textarea:focus {
	border-color: var(--fw-green-600);
	outline: none;
	box-shadow: 0 0 0 3px rgba(75, 120, 50, 0.18);
}

.wpcf7 textarea {
	min-height: 11rem;
	resize: vertical;
}

.wpcf7 .fw-form-privacy {
	font-size: 0.92rem;
	color: var(--fw-text-soft);
}

/* A link in running text needs more than colour (1.18 : 1 against the
   sentence): underlined like the footer's and the consent banner's links
   (owner, 2026-10-13). */
.wpcf7 .fw-form-privacy a {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Contact Form 7 integration */
.wpcf7 .fw-form-row {
	display: grid;
	gap: 0.35rem;
	margin-bottom: 1.1rem;
}

.wpcf7 label {
	font-weight: 700;
	font-size: 0.95rem;
}

.wpcf7 input:not([type='submit']):not([type='checkbox']),
.wpcf7 select,
.wpcf7 textarea {
	width: 100%;
}

.wpcf7 input[type='submit'] {
	background: var(--fw-yellow-500);
	color: var(--fw-ink);
	border: 0;
	border-radius: 999px;
	padding: 0.85rem 2rem;
	font-weight: 700;
	font-size: 1rem;
	cursor: pointer;
	transition: background-color 0.25s, transform 0.25s var(--fw-ease);
}

.wpcf7 input[type='submit']:hover {
	background: var(--fw-orange-400);
	transform: translateY(-2px);
}

.wpcf7 .wpcf7-acceptance .wpcf7-list-item {
	margin-left: 0;
}

.wpcf7 .wpcf7-acceptance label {
	font-weight: 500;
	display: flex;
	gap: 0.6rem;
	align-items: flex-start;
}

.wpcf7 .wpcf7-not-valid-tip {
	color: var(--fw-red-700);
	font-size: 0.85rem;
	margin-top: 0.25rem;
}

.wpcf7 .wpcf7-response-output {
	border: 2px solid var(--fw-green-500) !important;
	border-radius: var(--fw-radius-s);
	padding: 0.8rem 1rem !important;
	margin: 1rem 0 0 !important;
}

/* FAQ page */
/* Chapter navigation under the hero. Still on the ground, so the pills take
   cream outlines and the chapter number the highlight yellow. */
.fw-faq-nav {
	margin-top: calc(-1 * clamp(1.5rem, 4vw, 3rem));
	padding-bottom: clamp(2.5rem, 6vw, 4rem);
}

.fw-faq-nav__label {
	color: var(--fw-accent);
}

.fw-faq-nav__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
}

.fw-faq-nav__link {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	padding: 0.55rem 1.1rem 0.55rem 0.85rem;
	border: 1.5px solid rgba(239, 237, 228, 0.42);
	border-radius: 999px;
	color: var(--fw-on-dark);
	font-weight: 600;
	font-size: 0.95rem;
	line-height: 1.2;
	text-decoration: none;
	transition: background-color 0.2s var(--fw-ease), color 0.2s var(--fw-ease), border-color 0.2s var(--fw-ease);
}

.fw-faq-nav__num {
	font-family: var(--fw-font-display);
	font-weight: 700;
	font-size: 0.8rem;
	color: var(--fw-accent);
	transition: color 0.2s var(--fw-ease);
}

.fw-faq-nav__link:hover,
.fw-faq-nav__link:focus-visible {
	background: var(--fw-surface);
	border-color: var(--fw-surface);
	color: var(--fw-green-700);
}

.fw-faq-nav__link:hover .fw-faq-nav__num,
.fw-faq-nav__link:focus-visible .fw-faq-nav__num {
	color: var(--fw-green-700);
}

/* One cream island for all chapters, like the CTA banner: the container
   itself is the island, so its edge lines up with the other pages. */
.fw-faq {
	padding-top: 0;
}

.fw-faq__island {
	background: var(--fw-surface);
	border-radius: var(--fw-radius-l);
	padding: clamp(1.75rem, 4vw, 4rem) clamp(1.25rem, 4vw, 4rem);
}

/* A chapter is one ruled row: number, title and count on the left, stuck
   below the header while its questions scroll by on the right. */
.fw-faq-group {
	display: grid;
	grid-template-columns: minmax(0, 17rem) minmax(0, 1fr);
	gap: clamp(1.5rem, 4vw, 4rem);
	padding-block: clamp(2rem, 4vw, 3.25rem);
	border-top: 1px solid var(--fw-rule);
	scroll-margin-top: calc(var(--fw-header-h) + 1rem);
}

.fw-faq-group:first-child {
	border-top: 0;
	padding-top: 0;
}

.fw-faq-group:last-child {
	padding-bottom: 0;
}

.fw-faq-group__head {
	position: sticky;
	top: calc(var(--fw-header-h) + 1.5rem);
	align-self: start;
}

.fw-faq-group__num {
	margin: 0 0 0.5rem;
	font-family: var(--fw-font-display);
	font-weight: 700;
	font-size: clamp(2rem, 4vw, 3rem);
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--fw-green-600);
}

.fw-faq-group__title {
	margin: 0 0 0.6rem;
	font-size: clamp(1.4rem, 2.4vw, 1.85rem);
	line-height: 1.15;
}

.fw-faq .fw-accordion {
	max-width: none;
}

@media (max-width: 860px) {
	.fw-faq-group {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.25rem;
	}

	.fw-faq-group__head {
		position: static;
	}

	.fw-faq-nav__link {
		font-size: 0.9rem;
		padding: 0.5rem 0.95rem 0.5rem 0.75rem;
	}

	.fw-accordion__content {
		padding-right: 0;
	}
}

/* Search results cards */
.fw-search-card {
	display: grid;
	gap: 0.6rem;
	justify-items: start;
	text-decoration: none;
}

.fw-search-card img {
	max-height: 14rem;
	width: auto;
	justify-self: center;
}

.fw-search-card__price {
	font-weight: 800;
	color: var(--fw-green-700);
}

.fw-search-form--inline {
	max-width: 34rem;
	margin-top: 1.75rem;
	border: 1px solid rgba(95, 70, 71, 0.12);
}

/* 404 — full-bleed like search, so it carries its own container island. */
.fw-404 > .fw-container {
	width: calc(100% - clamp(1.25rem, 2.5vw, 2.25rem));
	max-width: none;
	padding: clamp(2.5rem, 5vw, 4.5rem) var(--fw-gutter);
	background: var(--fw-surface);
	border-radius: clamp(1.4rem, 2.5vw, 2.5rem);
}

.fw-404__code {
	font-family: var(--fw-font-display);
	font-size: clamp(5rem, 16vw, 10rem);
	font-weight: 800;
	line-height: 1;
	color: var(--fw-green-600);
	margin: 0;
}

.fw-404__title {
	font-size: clamp(1.8rem, 4vw, 2.6rem);
	margin: 0.5rem 0 1rem;
}

.fw-404__text {
	max-width: 46ch;
	margin-inline: auto;
	color: var(--fw-text-soft);
}

.fw-404__search {
	max-width: 32rem;
	margin: 2rem auto 0;
	border: 1px solid rgba(95, 70, 71, 0.12);
}

/* Utility pages reached from a mail: /unsubscribe/ and /review/
   (inc/marketing-consent.php, inc/reviews.php). Same island as the 404
   page, the content in a centred column. */
.fw-utility > .fw-utility__island {
	width: calc(100% - clamp(1.25rem, 2.5vw, 2.25rem));
	max-width: none;
	padding: clamp(2.5rem, 6vw, 5rem) var(--fw-gutter);
	background: var(--fw-surface);
	border-radius: clamp(1.4rem, 2.5vw, 2.5rem);
}

.fw-utility__card {
	max-width: 46rem;
	margin-inline: auto;
}

.fw-utility__card--narrow {
	max-width: 34rem;
	text-align: center;
}

/* Public withdrawal form and the unmodified statutory guarantee artwork. */
.fw-footer__service .fw-footer__withdraw {
	margin-top: 1rem;
	padding: 0.75rem 1rem;
	font-size: 0.9rem;
	text-decoration: none;
	text-align: center;
}

.fw-footer .fw-footer__withdraw:is(:hover, :focus-visible) {
	background: var(--fw-on-dark);
	color: var(--fw-ground);
}

.fw-withdrawal__form {
	display: grid;
	gap: 0.6rem;
	margin-block: 2rem;
}

.fw-withdrawal__form label {
	margin-top: 0.75rem;
	font-weight: 700;
}

.fw-withdrawal__form :is(input:not([type="hidden"]), select, textarea) {
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
	min-height: 3rem;
	padding: 0.8rem 1rem;
	border: 1px solid var(--fw-rule);
	border-radius: 0.7rem;
	background: #fff;
	color: var(--fw-ink);
	font: inherit;
	scroll-margin-top: calc(var(--fw-header-h) + 3rem);
}

.fw-withdrawal__form :is(input, select, textarea):focus-visible {
	outline: 2px solid var(--fw-ground);
	outline-offset: 2px;
}

.fw-withdrawal__form button {
	justify-self: start;
	max-width: 100%;
}

.fw-withdrawal__help {
	font-size: 0.9rem;
}

.fw-withdrawal__errors {
	padding: 1rem;
	border: 2px solid var(--fw-ink);
	border-radius: 0.7rem;
	scroll-margin-top: calc(var(--fw-header-h) + 1rem);
}

.fw-guarantee {
	clear: both;
	margin: 1.5rem 0;
	padding: 1rem 1.2rem;
	border: 1px solid var(--fw-rule);
	border-radius: 0.7rem;
	color: var(--fw-ink);
	background: var(--fw-surface);
}

.fw-guarantee > summary {
	cursor: pointer;
	font-weight: 700;
}

.fw-guarantee__content {
	padding-top: 1rem;
}

.fw-guarantee__image {
	display: block;
	width: 100%;
	max-width: 44rem;
	height: auto;
	margin-inline: auto;
}

.fw-utility__title {
	font-size: clamp(1.8rem, 4vw, 2.6rem);
	line-height: 1.1;
	margin: 0.5rem 0 1rem;
}

.fw-utility__text {
	color: var(--fw-text-soft);
	margin: 0 auto;
	max-width: 46ch;
}

.fw-utility__text strong {
	color: var(--fw-ink);
	overflow-wrap: anywhere;
}

.fw-utility__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	justify-content: center;
	margin-top: 2rem;
}

/* /review/: one card per product, star radios, optional text. */
.fw-rate-intro {
	color: var(--fw-text-soft);
	margin: 0 0 1.75rem;
	max-width: 60ch;
}

.fw-rate-error {
	margin: 0 0 1.25rem;
	padding: 0.85rem 1.1rem;
	border-radius: var(--fw-radius-m);
	background: rgba(90, 45, 45, 0.08);
	color: var(--fw-red-700);
	font-weight: 700;
}

.fw-rate-form {
	display: grid;
	gap: 1rem;
}

.fw-rate-item {
	display: grid;
	grid-template-columns: clamp(4.5rem, 14vw, 6.5rem) minmax(0, 1fr);
	gap: clamp(1rem, 3vw, 1.75rem);
	align-items: start;
	margin: 0;
	padding: clamp(1rem, 3vw, 1.5rem);
	border: 1px solid var(--fw-rule-soft);
	border-radius: var(--fw-radius-l);
	background: rgba(255, 255, 255, 0.55);
	min-width: 0;
}

.fw-rate-item__media img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 4;
	object-fit: contain;
	border-radius: var(--fw-radius-m);
	background: var(--fw-home-wash);
}

.fw-rate-item__body {
	display: grid;
	gap: 0.5rem;
	min-width: 0;
}

.fw-rate-item__name {
	float: left;
	width: 100%;
	margin: 0;
	padding: 0;
	font-family: var(--fw-font-display);
	font-size: clamp(1.15rem, 2.4vw, 1.35rem);
	font-weight: 700;
	line-height: 1.2;
	color: var(--fw-heading);
}

.fw-rate-item__name + * {
	clear: both;
}

.fw-rate-item__label {
	margin-top: 0.35rem;
	font-size: 0.9rem;
	font-weight: 700;
	color: var(--fw-text);
}

.fw-rate-item textarea {
	width: 100%;
	min-height: 5.5rem;
	padding: 0.8rem 1rem;
	border: 1px solid var(--fw-rule);
	border-radius: var(--fw-radius-m);
	background: #fffdf6;
	color: var(--fw-text);
	font: inherit;
	font-size: 1rem;
	resize: vertical;
}

.fw-rate-item textarea:focus-visible {
	outline: 2px solid var(--fw-green-600);
	outline-offset: 2px;
	border-color: transparent;
}

.fw-rate-item.is-done {
	background: transparent;
}

.fw-rate-item__done {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	justify-self: start;
	margin: 0;
	padding: 0.3rem 0.75rem;
	border-radius: 999px;
	background: rgba(62, 89, 40, 0.1);
	color: var(--fw-green-700);
	font-size: 0.88rem;
	font-weight: 700;
}

/* Star radios: native inputs (arrow keys, form posting) under drawn stars.
   Everything up to the checked star is filled. Yellow with a dark-gold
   outline, as on the product page (3:1 for graphics on cream). */
.fw-star-input {
	display: flex;
	gap: 0.2rem;
	margin-left: -0.2rem;
}

.fw-star-input input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
}

.fw-star-input label {
	padding: 0.2rem;
	border-radius: var(--fw-radius-s);
	line-height: 0;
	cursor: pointer;
}

.fw-star-input svg {
	width: clamp(2.2rem, 8vw, 2.6rem);
	height: clamp(2.2rem, 8vw, 2.6rem);
	fill: rgba(95, 70, 71, 0.1);
	stroke: rgba(95, 70, 71, 0.42);
	stroke-width: 1.5;
	stroke-linejoin: round;
	transition: transform 0.15s var(--fw-ease), fill 0.15s;
}

.fw-star-input:has(input:checked) svg {
	fill: var(--fw-yellow-500);
	stroke: #8f6f00;
}

.fw-star-input input:checked + label ~ label svg {
	fill: rgba(95, 70, 71, 0.1);
	stroke: rgba(95, 70, 71, 0.42);
}

.fw-star-input input:focus-visible + label {
	outline: 2px solid var(--fw-green-600);
	outline-offset: 1px;
}

@media (hover: hover) {
	.fw-star-input label:hover svg {
		transform: scale(1.12);
	}
}

.fw-rate-publish {
	display: grid;
	gap: 0.75rem;
	margin-top: 0.5rem;
	color: var(--fw-text-soft);
	font-size: 0.95rem;
}

.fw-rate-publish p {
	margin: 0;
	max-width: 62ch;
}

.fw-rate-anonymous {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	justify-self: start;
	color: var(--fw-text);
	font-weight: 700;
	cursor: pointer;
}

.fw-rate-anonymous input {
	width: 1.2rem;
	height: 1.2rem;
	margin: 0;
	accent-color: var(--fw-green-600);
}

.fw-rate-submit {
	display: flex;
	justify-content: flex-start;
	margin-top: 0.5rem;
}

.fw-rate-all-done {
	margin: 0.5rem 0 0;
	font-weight: 700;
	color: var(--fw-green-700);
}

.fw-rate-notice {
	margin-top: 2rem;
}

.fw-utility__icon {
	display: inline-grid;
	place-items: center;
	width: 3.5rem;
	height: 3.5rem;
	margin-bottom: 0.5rem;
	border-radius: 50%;
	background: var(--fw-ground);
	color: var(--fw-accent);
}






/* == 10 Landing page content islands ================================= */

/* The video remains full-bleed. Everything below it sits on the dark page
   ground, with the content grouped into islands that all share one surface;
   colour now identifies a product line rather than a section. */
.fw-landing-stack {
	--fw-landing-inset: clamp(1.25rem, 2.5vw, 2.25rem);
	display: grid;
	gap: clamp(1rem, 2vw, 2rem);
	padding-block: clamp(1.25rem, 2.5vw, 2.5rem);
	background: transparent;
}
/* Target of the hero scroll cue (tabindex -1): focus lands here without a ring. */
.fw-landing-stack:focus {
	outline: none;
}

.fw-landing-stack > :is(.fw-section, .fw-cta-banner) {
	padding-block: 0;
	background: transparent;
}

.fw-landing-panel > .fw-container,
.fw-landing-stack .fw-cta-banner__inner {
	width: calc(100% - var(--fw-landing-inset));
	max-width: none;
	margin-inline: auto;
	border-radius: clamp(1.4rem, 2.5vw, 2.5rem);
}

.fw-landing-panel > .fw-container {
	position: relative;
	overflow: hidden;
	padding: clamp(2.25rem, 4.5vw, 5rem);
}

.fw-landing-panel--products > .fw-stage {
	padding: clamp(2rem, 3.5vw, 4rem);
}

.fw-landing-panel--categories > .fw-container {
	background: var(--fw-surface);
	padding: 0;
}

.fw-landing-panel--story > .fw-container {
	background: var(--fw-surface);
}

.fw-landing-panel--science > .fw-container {
	background: var(--fw-surface);
}



.fw-landing-panel .fw-section-heading {
	margin-bottom: clamp(2rem, 4vw, 3.5rem);
}

/* No CSS shadow under the products (owner, 2026-10-16): the product
   photographs carry their own subtle shadow since then. Stage, line bottles
   and shop cards used to add a drop-shadow on top. */

/* == The two product lines ============================================== */

/* Two quiet stages; the product family itself is the interaction. */
.fw-landing-panel--categories .fw-lines__heading {
	margin: 0;
	padding: clamp(1.4rem, 2.8vw, 2.5rem) clamp(1.5rem, 4vw, 3.5rem) 0;
	font-size: clamp(1.9rem, 2.8vw, 2.8rem);
	letter-spacing: -0.035em;
	line-height: 1.1;
}
.fw-lines {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
}
.fw-line {
	min-width: 0;
	padding: clamp(1.5rem, 3vw, 3rem) clamp(1.5rem, 4vw, 3.5rem) 2.5rem;
}
.fw-line + .fw-line {
	border-left: 1px solid var(--fw-rule-soft);
}
/* The line names stay smaller than the section heading above them. */
.fw-line__header .fw-line__title {
	margin: 0;
	font-size: clamp(1.5rem, 2vw, 2.1rem);
	letter-spacing: -0.04em;
	line-height: 1.1;
}
/* The name links to the category; the former arrow button is gone. */
.fw-line__category,
.fw-line__category:is(:hover, :focus, :active) {
	color: inherit;
	text-decoration: none;
}
.fw-line__category:hover {
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.18em;
}
/* The copy uses the full column instead of wrapping at 35ch. */
.fw-line__text {
	min-height: 3em;
	margin: 0.6rem 0 0;
	text-wrap: pretty;
	font-size: clamp(0.95rem, 1.15vw, 1.1rem);
	line-height: 1.5;
}
.fw-line__gallery {
	position: relative;
	height: clamp(16rem, 25vw, 25rem);
	margin: 1rem -1rem 0;
}
.fw-line__bottle {
	position: absolute;
	bottom: 1rem;
	left: var(--fw-bottle-position);
	display: flex;
	align-items: end;
	justify-content: center;
	width: min(38%, calc(140% / var(--fw-line-count)));
	height: 88%;
	transform: translateX(-50%) rotate(var(--fw-bottle-tilt));
	transform-origin: center 85%;
	z-index: 1;
}
.fw-line__bottle img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}
.fw-line__bottle.is-selected {
	z-index: 3;
	transform: translateX(-50%) translateY(-0.7rem) rotate(0deg) scale(1.1);
}
.fw-line__selection {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	/* Reserve two name lines so short/long products never move the list. */
	min-height: calc(2.9em + 1.4rem + 2px);
	margin: 0;
	padding-block: 0.7rem;
	border-bottom: 1px solid var(--fw-rule);
	color: var(--fw-heading);
	font-weight: 750;
	font-size: clamp(1rem, 1.2vw, 1.2rem);
	line-height: 1.45;
}
.fw-line__selection span {
	max-width: 30ch;
}
.fw-line a:focus-visible {
	outline: 2px solid var(--fw-heading);
	outline-offset: 4px;
}
@media (min-width: 1001px) and (hover: hover) and (pointer: fine) {
	.fw-line.is-enhanced:not(.is-open) .fw-line__bottle {
		left: 50%;
		opacity: 0;
		visibility: hidden;
		transform: translateX(-50%) scale(0.65);
	}
	.fw-line.is-enhanced:not(.is-open) .fw-line__bottle.is-featured {
		width: 57%;
		opacity: 1;
		visibility: visible;
		transform: translateX(-50%);
	}
}
@media (prefers-reduced-motion: no-preference) {
	.fw-line__bottle {
		transition: left 0.6s var(--fw-ease), width 0.6s var(--fw-ease), transform 0.45s var(--fw-ease), opacity 0.35s, visibility 0.35s;
	}
}
@media (max-width: 1000px) {
	.fw-lines {
		grid-template-columns: 1fr;
	}
	.fw-line + .fw-line {
		border-left: 0;
		border-top: 1px solid var(--fw-rule-soft);
	}
	.fw-line__text {
		min-height: 0;
	}
	.fw-line__gallery {
		height: clamp(17rem, 43vw, 23rem);
	}
}
@media (max-width: 600px) {
	.fw-line {
		padding: 1.75rem 1.5rem 2rem;
	}
	.fw-landing-panel--categories .fw-lines__heading {
		font-size: clamp(1.75rem, 8vw, 2.2rem);
	}
	.fw-line__header .fw-line__title {
		font-size: clamp(1.3rem, 6vw, 1.7rem);
	}
	/* A centred, endless carousel (owner, 2026-09-25 and 2026-09-29): the
	   first product starts in the middle, whichever product stands in the
	   middle is the selected one, and main.js clones the family to both sides
	   so it can be swiped on in either direction.
	   The inline padding lets the first and the last product reach the
	   centre: the gallery is 3rem wider than its parent (the negative margins),
	   while the percentage resolves against the parent, so half the gallery
	   minus half a bottle is 50% + 1.5rem − 4.25rem. */
	.fw-line__gallery {
		display: flex;
		gap: 0.15rem;
		height: 16rem;
		margin-inline: -1.5rem;
		padding: 1.25rem calc(50% - 2.75rem) 1rem;
		overflow-x: auto;
		overflow-y: hidden;
		scroll-snap-type: x mandatory;
		overscroll-behavior-x: contain;
		scrollbar-width: none;
	}
	.fw-line__gallery::-webkit-scrollbar {
		display: none;
	}
	/* With JS the carousel moves one product per swipe itself (main.js);
	   the browser keeps vertical page scrolling. Snapping pauses while the
	   gallery follows the finger. Without JS it scrolls natively. */
	.fw-line.is-enhanced .fw-line__gallery {
		touch-action: pan-y;
	}
	.fw-line__gallery.is-dragging {
		scroll-snap-type: none;
	}
	/* --fw-near (1 = in the middle, 0 = a bottle or more away) is written per
	   frame by main.js while the gallery scrolls, so the bottles grow and come
	   forward as they approach the middle. It follows the finger directly, so
	   nothing may transition it; without JS every bottle keeps full size. */
	.fw-line__bottle,
	.fw-line__bottle.is-selected {
		position: relative;
		left: auto;
		bottom: auto;
		flex: 0 0 8.5rem;
		width: 8.5rem;
		height: 100%;
		scroll-snap-align: center;
		scroll-snap-stop: always;
		transform-origin: center bottom;
		transform: translateY(calc(var(--fw-near, 1) * -0.6rem)) scale(calc(0.74 + var(--fw-near, 1) * 0.36));
		opacity: calc(0.5 + var(--fw-near, 1) * 0.5);
		transition: none;
	}
	.fw-line__selection {
		border-bottom: 0;
		font-size: 1rem;
	}
}















/* A large section-level title,
	so it takes the heading green. It used to
   inherit purely so it could flip with the card on hover — that still works {
	color: var(--fw-heading);
	font-size: clamp(2.25rem, 4vw, 3.6rem);
}







/* Story and science use the whole island edge to edge. */
.fw-landing-panel--story > .fw-container,
.fw-landing-panel--science > .fw-container {
	padding: 0;
}

/* The landing story is an explorable process map, not a generic card
   timeline. Percentage-based hit areas sit directly on the cycle artwork.
   Their clipped washes render over the artwork without escaping a segment. */
.fw-story-cycle {
	position: relative;
	color: var(--fw-text);
}

.fw-story-cycle__copy-ghost {
	position: absolute;
	z-index: 6;
	box-sizing: border-box;
	margin: 0;
	pointer-events: none;
	will-change: transform, opacity;
}

.fw-story-cycle__copy-probe {
	position: absolute !important;
	z-index: -1;
	height: auto !important;
	min-height: 0 !important;
	visibility: hidden !important;
	pointer-events: none;
}

.fw-story-cycle.is-swiping .fw-story-cycle__text {
	will-change: transform, opacity;
}

.fw-story-cycle__experience {
	display: grid;
	grid-template-columns: minmax(30rem, 0.96fr) minmax(0, 1.04fr);
	min-height: 50rem;
	border-block: 1px solid currentColor;
}

.fw-story-cycle__map {
	position: relative;
	display: grid;
	grid-template-rows: auto 1fr;
	min-width: 0;
	padding: clamp(2rem, 3.5vw, 4rem);
	border-right: 1px solid currentColor;
	background: var(--fw-surface);
}

.fw-story-cycle__heading {
	position: relative;
	z-index: 3;
	margin: 0 0 clamp(1rem, 2vw, 2rem);
	color: var(--fw-heading);
	font-size: clamp(2.75rem, 4.7vw, 5rem);
	line-height: 0.92;
}

.fw-story-cycle__orbit {
	--fw-story-orbit-bleed: clamp(1.25rem, calc(5.45vw - 2.02rem), 2.75rem);
	--fw-story-visual-extra: clamp(0rem, calc(9.375vw - 9.375rem), 2.625rem);
	position: relative;
	align-self: center;
	width: min(calc(100% + var(--fw-story-orbit-bleed)), 44rem);
	aspect-ratio: 626 / 654;
	margin-inline: auto;
	isolation: isolate;
}

.fw-story-cycle__visual {
	position: absolute;
	top: 50%;
	left: 50%;
	width: calc(100% + var(--fw-story-visual-extra));
	aspect-ratio: 626 / 654;
	transform: translate(-50%, -50%);
	isolation: isolate;
}

.fw-story-cycle__illustration {
	position: relative;
	z-index: 1;
	display: block;
	width: 100%;
	height: auto;
	object-fit: contain;
	filter: none;
}

.fw-story-cycle__effects,
.fw-story-cycle__hotspots {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
}

.fw-story-cycle__effects {
	z-index: 2;
	pointer-events: none;
}

.fw-story-cycle__effect-core {
	fill: var(--fw-green-500);
	stroke: transparent;
	opacity: 0;
	filter: blur(12px);
	mix-blend-mode: multiply;
	pointer-events: none;
	transform: scale(0.94);
	transform-box: fill-box;
	transform-origin: center;
	will-change: opacity;
}

.fw-story-cycle__effect-core.is-active {
	fill: var(--fw-green-500);
	opacity: 0.32;
}

.fw-story-cycle__effect-core.is-preview:not(.is-active) {
	fill: var(--fw-green-200);
	opacity: 0.24;
}

@media (min-width: 961px) {
	.fw-story-cycle__effect-core {
		filter: blur(14px);
		transform: scale(0.96);
	}
}

.fw-story-cycle__hotspots {
	z-index: 3;
}

.fw-story-cycle__hotspot {
	fill: rgba(0, 0, 0, 0.001);
	stroke: none;
	cursor: pointer;
	pointer-events: fill;
}

.fw-story-cycle__hotspot:focus,
.fw-story-cycle__hotspot:focus-visible {
	outline: none;
}

.fw-story-cycle__chapter {
	--fw-story-object-position: center center;
	display: grid;
	grid-template-rows: minmax(26rem, 1.15fr) auto;
	min-width: 0;
	background: var(--fw-surface);
}

.fw-story-cycle__photo {
	position: relative;
	min-width: 0;
	overflow: hidden;
	background: var(--fw-surface);
}

.fw-story-cycle__photo img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	border-radius: 0;
	box-shadow: none;
	object-fit: cover;
	object-position: var(--fw-story-object-position);
}

.fw-story-cycle__copy {
	display: grid;
	grid-template-columns: auto minmax(0, 58ch) auto;
	gap: clamp(0.8rem, 1.6vw, 1.35rem);
	align-items: center;
	justify-content: center;
	min-height: 28rem;
	padding: clamp(2rem, 3.5vw, 3.5rem);
	touch-action: pan-y;
}

.fw-story-cycle__copy-body {
	display: flex;
	flex-direction: column;
	min-width: 0;
	min-block-size: var(--fw-story-copy-min-height, 0);
}

.fw-story-cycle__swipe-hint {
	display: none;
}

.fw-story-cycle__label {
	margin: 0;
	font-size: 0.72rem;
	font-weight: 850;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.fw-story-cycle__copy-body h3,
.fw-story-cycle__copy-ghost h3 {
	margin: 0.55rem 0 0.9rem;
	color: var(--fw-heading);
	font-size: clamp(2.1rem, 3.8vw, 3.6rem);
	overflow-wrap: anywhere;
	hyphens: auto;
}

.fw-story-cycle__text > p:not(.fw-story-cycle__label) {
	max-width: 58ch;
	margin: 0;
	color: var(--fw-grey);
	line-height: 1.6;
}

.fw-story-cycle__actions {
	gap: 0.7rem;
	margin-top: auto;
	padding-top: 1.5rem;
}

/* Restated for hover, focus and active: Astra fills a <button> blue in those
   states, and on touch screens (where the real hover below does not apply)
   a tap left the arrow blue. */
.fw-story-cycle__arrow,
.fw-story-cycle__arrow:is(:hover, :focus, :active) {
	border-color: currentColor;
	background: transparent;
	color: inherit;
	outline: 0;
	box-shadow: none;
}

.fw-story-cycle__arrow:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

.fw-story-cycle__arrow {
	display: grid;
	place-items: center;
	width: 3rem;
	aspect-ratio: 1;
	padding: 0;
	border: 1px solid currentColor;
	border-radius: 50%;
	font: inherit;
	cursor: pointer;
	transition: background-color 0.25s var(--fw-ease), color 0.25s var(--fw-ease), transform 0.25s var(--fw-ease);
}

.fw-story-cycle__arrow span {
	font-size: 1.25rem;
	line-height: 1;
}

.fw-story-cycle__chapter.is-entering .fw-story-cycle__photo img,
.fw-story-cycle__chapter.is-entering .fw-story-cycle__text > * {
	animation: fw-story-chapter-in 0.5s var(--fw-ease) both;
}

.fw-story-cycle__chapter.is-entering .fw-story-cycle__text > *:nth-child(2) {
	animation-delay: 0.04s;
}

.fw-story-cycle__chapter.is-entering .fw-story-cycle__text > *:nth-child(3) {
	animation-delay: 0.08s;
}

@keyframes fw-story-chapter-in {
	from {
		opacity: 0;
		transform: translateY(0.6rem);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* A chapter whose photo has not arrived yet (main.js preloads all eight)
   shows a loading ring instead of the previous chapter's photo. The ring
   waits a moment, so a photo that is only decoding never flashes it. */
.fw-story-cycle__photo.is-loading img {
	visibility: hidden;
}

.fw-story-cycle__photo.is-loading::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 2.75rem;
	height: 2.75rem;
	margin: -1.375rem 0 0 -1.375rem;
	border: 3px solid color-mix(in srgb, var(--fw-ground) 16%, transparent);
	border-top-color: var(--fw-ground);
	border-radius: 50%;
	animation:
		fw-story-photo-wait 0.2s linear 0.15s both,
		fw-story-photo-spin 0.9s linear infinite;
}

.fw-story-cycle__photo.is-arriving img {
	animation: fw-story-photo-arrive 0.4s var(--fw-ease) both;
}

@keyframes fw-story-photo-wait {
	from {
		opacity: 0;
	}
}

@keyframes fw-story-photo-spin {
	to {
		transform: rotate(1turn);
	}
}

@keyframes fw-story-photo-arrive {
	from {
		opacity: 0;
	}
}

/* Landing Science is one compact thesis, not a second long-form explainer.
   Wide screens use a deliberate copy / artwork / interactive process split.
   The process rows share the right field until hover or keyboard focus lets
   one explanation expand while the other three remain reachable. */
.fw-landing-panel--science {
	color: var(--fw-text);
}

.fw-science-teaser__layout {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	min-height: clamp(48rem, 40vw, 49rem);
}

.fw-science-teaser__layout > * {
	min-width: 0;
}

.fw-science-teaser__copy {
	grid-column: 1;
	grid-row: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: clamp(3rem, 3vw, 4.25rem);
}

.fw-science-teaser__copy .fw-science-teaser__heading {
	max-width: none;
	margin: 0;
	color: var(--fw-heading);
	font-size: clamp(2.65rem, 3vw, 4.25rem);
	line-height: 0.96;
	letter-spacing: -0.045em;
}

.fw-science-teaser__copy-body > p {
	max-width: none;
	margin: clamp(1.25rem, 2vw, 1.75rem) 0 0;
	padding-top: 1.2rem;
	border-top: 1px solid var(--fw-rule);
	color: var(--fw-text);
	font-size: clamp(0.98rem, 1.08vw, 1.1rem);
	line-height: 1.65;
	opacity: 0.84;
}

.fw-science-teaser__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
	margin-top: 2rem;
}

.fw-science-teaser__visual {
	grid-column: 2;
	grid-row: 1;
	position: relative;
	display: grid;
	place-items: center;
	min-width: 0;
	min-height: 0;
	margin: 0;
	padding: clamp(2.75rem, 3.5vw, 4rem) clamp(1.5rem, 2.5vw, 3rem);
	overflow: hidden;
	border-inline: 1px solid var(--fw-rule);
	background: var(--fw-surface);
	color: var(--fw-text);
	isolation: isolate;
}

.fw-science-teaser__illustration {
	align-self: center;
	justify-self: center;
	display: block;
	width: auto;
	height: min(88%, 39rem);
	max-width: 110%;
	object-fit: contain;
	transition: transform 0.7s var(--fw-ease);
}

.fw-science-teaser__steps {
	grid-column: 3;
	grid-row: 1;
	display: flex;
	flex-direction: column;
	min-width: 0;
	min-height: 0;
	padding-top: clamp(2rem, 2.7vw, 3rem);
}

.fw-science-teaser__steps-label {
	margin: 0;
	padding: 0 clamp(1.5rem, 2.2vw, 2.5rem) 1.15rem;
	color: var(--fw-ink);
	font-size: 0.68rem;
	font-weight: 850;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.fw-science-teaser__steps ol {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	min-height: 0;
	margin: 0;
	padding: 0;
	border-block: 1px solid var(--fw-rule);
	list-style: none;
}

.fw-science-teaser__steps li {
	position: relative;
	display: grid;
	grid-template-columns: 1.8rem minmax(0, 1fr);
	gap: clamp(0.55rem, 0.8vw, 0.85rem);
	align-content: center;
	flex: 1 1 0;
	min-height: 0;
	padding: clamp(1rem, 1.5vw, 1.55rem) clamp(1.4rem, 2vw, 2.25rem);
	overflow: hidden;
	outline: 0;
	transition: flex-grow 0.48s var(--fw-ease), background-color 0.32s var(--fw-ease), color 0.32s var(--fw-ease);
}

.fw-science-teaser__steps li + li {
	border-top: 1px solid var(--fw-rule);
}

.fw-science-teaser__steps li > span {
	padding-top: 0.18rem;
	color: var(--fw-green-700);
	font-size: 0.62rem;
	font-weight: 850;
	letter-spacing: 0.1em;
}

.fw-science-teaser__steps h3 {
	margin: 0 0 0.18rem;
	color: var(--fw-heading);
	font-size: clamp(1.2rem, 1.5vw, 1.55rem);
	line-height: 1.08;
	transition: color 0.32s var(--fw-ease), font-size 0.48s var(--fw-ease);
}

.fw-science-teaser__steps li p {
	margin: 0;
	color: var(--fw-text);
	font-size: clamp(0.78rem, 0.84vw, 0.9rem);
	line-height: 1.45;
	opacity: 0.82;
	transition: max-height 0.38s var(--fw-ease), margin 0.38s var(--fw-ease), opacity 0.25s var(--fw-ease), color 0.32s var(--fw-ease);
}

.fw-science-teaser__step-content {
	min-width: 0;
}

.fw-science-teaser__step-summary {
	max-height: 7rem;
	font-weight: 650;
}

.fw-science-teaser__step-detail {
	max-height: 0;
	margin-top: 0;
	overflow: hidden;
	opacity: 0;
	visibility: hidden;
	transition: max-height 0.45s var(--fw-ease), margin 0.38s var(--fw-ease), opacity 0.28s var(--fw-ease), visibility 0s linear 0.45s;
}

.fw-science-teaser__step-detail > p {
	font-size: clamp(0.76rem, 0.75vw, 0.84rem);
	line-height: 1.5;
}

.fw-science-teaser__step-detail dl {
	margin: 1rem 0 0;
	font-size: clamp(0.88rem, 0.9vw, 1rem);
	line-height: 1.45;
}

.fw-science-teaser__step-detail dl > div + div {
	margin-top: 0.35rem;
}

.fw-science-teaser__step-detail dt,
.fw-science-teaser__step-detail dd {
	display: inline;
}

.fw-science-teaser__step-detail dt {
	font-weight: 850;
}

.fw-science-teaser__step-detail dt::after {
	content: ":";
}

.fw-science-teaser__step-detail dd {
	margin: 0 0 0 0.22rem;
}

@media (min-width: 1251px) and (hover: hover) {
	.fw-science-teaser__steps ol:has(li:hover) > li:not(:hover) {
		flex-grow: 0.48;
	}

	.fw-science-teaser__steps li:hover {
		flex-grow: 4;
		align-content: start;
		padding-top: clamp(1.5rem, 2vw, 2.15rem);
		background: var(--fw-green-800);
		color: var(--fw-on-dark);
	}

	.fw-science-teaser__steps li:hover > span {
		color: var(--fw-accent);
	}

	.fw-science-teaser__steps li:hover h3 {
		color: inherit;
		font-size: calc(clamp(1.65rem, 1.85vw, 2.05rem) * var(--fw-step-fit, 1));
	}

	.fw-science-teaser__steps li:hover p {
		max-height: 18rem;
		color: inherit;
		font-size: calc(clamp(0.98rem, 1.08vw, 1.1rem) * var(--fw-step-fit, 1));
		line-height: 1.65;
		opacity: 0.88;
	}

	.fw-science-teaser__steps li:hover .fw-science-teaser__step-detail dl {
		font-size: calc(clamp(0.88rem, 0.9vw, 1rem) * var(--fw-step-fit, 1));
	}

	.fw-science-teaser__steps ol:has(li:hover) > li:not(:hover) p {
		max-height: 0;
		opacity: 0;
	}

	.fw-science-teaser__steps li:hover .fw-science-teaser__step-detail {
		max-height: 24rem;
		margin-top: 1rem;
		opacity: 1;
		visibility: visible;
		transition-delay: 0s;
	}
}

/* .is-measuring is the same opened state, set for one synchronous layout by
   main.js to find the font scale (--fw-step-fit) at which each opened step
   fits its row; .is-fitting switches every transition off meanwhile, so no
   frame of it is ever painted (owner, 2026-09-30: on smaller desktops the
   opened text ran out at the bottom). */
@media (min-width: 1251px) {
	.fw-science-teaser__steps ol.is-fitting,
	.fw-science-teaser__steps ol.is-fitting * {
		transition: none !important;
	}

	.fw-science-teaser__steps ol:has(li:is(:focus-visible, .is-measuring)) > li:not(:focus-visible, .is-measuring) {
		flex-grow: 0.48;
	}

	.fw-science-teaser__steps li:is(:focus-visible, .is-measuring) {
		flex-grow: 4;
		align-content: start;
		padding-top: clamp(1.5rem, 2vw, 2.15rem);
		background: var(--fw-green-800);
		color: var(--fw-on-dark);
	}

	.fw-science-teaser__steps li:focus-visible {
		box-shadow: inset 0 0 0 3px var(--fw-accent);
	}

	.fw-science-teaser__steps li:is(:focus-visible, .is-measuring) > span {
		color: var(--fw-accent);
	}

	.fw-science-teaser__steps li:is(:focus-visible, .is-measuring) h3 {
		color: inherit;
		font-size: calc(clamp(1.65rem, 1.85vw, 2.05rem) * var(--fw-step-fit, 1));
	}

	.fw-science-teaser__steps li:is(:focus-visible, .is-measuring) p {
		max-height: 18rem;
		color: inherit;
		font-size: calc(clamp(0.98rem, 1.08vw, 1.1rem) * var(--fw-step-fit, 1));
		line-height: 1.65;
		opacity: 0.88;
	}

	.fw-science-teaser__steps li:is(:focus-visible, .is-measuring) .fw-science-teaser__step-detail dl {
		font-size: calc(clamp(0.88rem, 0.9vw, 1rem) * var(--fw-step-fit, 1));
	}

	.fw-science-teaser__steps ol:has(li:is(:focus-visible, .is-measuring)) > li:not(:focus-visible, .is-measuring) p {
		max-height: 0;
		opacity: 0;
	}

	.fw-science-teaser__steps li:is(:focus-visible, .is-measuring) .fw-science-teaser__step-detail {
		max-height: 24rem;
		margin-top: 1rem;
		opacity: 1;
		visibility: visible;
		transition-delay: 0s;
	}
}

/* Values repeat the product-stage list language: one field, four ruled links. */












/* Colour comes from the base .fw-cta-banner rules; only the width differs
   here, because the landing islands run wider than the default container. */
.fw-landing-stack .fw-cta-banner__inner {
	max-width: none;
}

@media (hover: hover) {
	.fw-story-cycle__arrow:hover {
		background: var(--fw-green-800);
		color: var(--fw-on-dark);
	}
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {

	

	

	

	

	

	.fw-science-teaser__visual:hover .fw-science-teaser__illustration {
		transform: scale(1.025);
	}

	

	.fw-story-cycle__arrow:hover {
		transform: translateY(-2px);
	}

	

	
}

@media (prefers-reduced-motion: reduce) {
	.fw-science-teaser__steps li,
	.fw-science-teaser__steps h3,
	.fw-science-teaser__steps li p,
	.fw-science-teaser__step-detail {
		transition: none;
	}

	.fw-science-teaser__visual:hover .fw-science-teaser__illustration,
.fw-story-cycle__arrow:hover {
		transform: none;
	}

	.fw-story-cycle__chapter.is-entering .fw-story-cycle__photo img,
	.fw-story-cycle__chapter.is-entering .fw-story-cycle__text > * {
		animation: none;
	}

	.fw-story-cycle__photo.is-arriving img {
		animation: none;
	}

	.fw-story-cycle__photo.is-loading::after {
		animation: fw-story-photo-wait 0.2s linear 0.15s both, fw-story-photo-spin 2.4s linear infinite;
	}
}

@media (max-width: 1250px) {
	.fw-science-teaser__layout {
		grid-template-columns: minmax(0, 0.92fr) minmax(22rem, 1.08fr);
		min-height: 0;
	}

	.fw-science-teaser__copy {
		padding: 3rem;
	}

	.fw-science-teaser__visual {
		grid-column: 2;
		grid-row: 1;
		min-height: 31rem;
		padding: 2.5rem;
		border-right: 0;
		border-left: 1px solid var(--fw-rule);
	}

	.fw-science-teaser__illustration {
		width: min(92%, 30rem);
		height: auto;
		max-width: 100%;
		max-height: 27rem;
	}

	.fw-science-teaser__steps {
		grid-column: 1 / -1;
		grid-row: 2;
		display: block;
		padding: 1.5rem 2.5rem 2rem;
		border-top: 1px solid var(--fw-rule);
	}

	.fw-science-teaser__steps-label {
		margin: 0 0 1rem;
		padding: 0;
	}

	.fw-science-teaser__steps ol {
		display: grid;
		grid-template-columns: repeat(4, minmax(0, 1fr));
		width: auto;
	}

	.fw-science-teaser__steps li:nth-child(n) {
		align-self: stretch;
		min-height: 0;
		padding: 1rem;
		overflow: visible;
		border-top: 0;
	}

	.fw-science-teaser__steps li + li {
		border-left: 1px solid var(--fw-rule);
	}
}

@media (max-width: 1100px) {
	.fw-stage {
		min-height: 0;
	}

	.fw-stage__layout {
		grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
		/* Keep the visual/copy row taller than the longest wrapped product
		   content throughout the laptop/tablet breakpoint. */
		min-height: 36rem;
	}

	/* Below the three-column layout the heading column becomes the row above
	   the bottle: heading, sub-headings, then the selector as a strip. */
	.fw-stage__aside {
		grid-column: 1 / -1;
	}

	.fw-stage__selector {
		height: auto;
	}

	.fw-stage__tabs {
		display: flex;
		gap: 0.5rem;
		overflow-x: auto;
		scrollbar-width: none;
		scroll-snap-type: x proximity;
	}

	.fw-stage__tabs::-webkit-scrollbar {
		display: none;
	}

	.fw-stage__tab {
		flex: 0 0 auto;
		grid-template-columns: auto;
		width: auto;
		max-width: 15rem;
		border: 1px solid currentColor;
		border-radius: 999px;
		padding: 0.62rem 0.9rem;
		scroll-snap-align: center;
	}

	.fw-stage__tab:is(:hover, :focus-visible),
	.fw-stage__tab.is-active {
		padding-inline: 0.9rem;
	}

	.fw-stage__shop-link,
	.fw-stage__basis {
		display: none;
	}

	.fw-stage__visual {
		min-height: 30rem;
	}

}



@media (max-width: 860px) {

	.fw-science-teaser__layout {
		grid-template-columns: 1fr;
		min-height: 0;
	}

	.fw-science-teaser__copy {
		display: contents;
	}

	.fw-science-teaser__copy > .fw-kicker {
		grid-column: 1;
		grid-row: 1;
		margin: 0;
		padding: 2.5rem 2.5rem 1rem;
	}

	.fw-science-teaser__visual {
		grid-column: 1;
		grid-row: 2;
		min-height: clamp(23rem, 62vw, 32rem);
		border: 0;
		border-bottom: 1px solid var(--fw-rule);
	}

	.fw-science-teaser__illustration {
		max-height: clamp(19rem, 50vw, 27rem);
	}

	.fw-science-teaser__copy .fw-science-teaser__heading {
		grid-column: 1;
		grid-row: 3;
		padding: 2.5rem 2.5rem 0;
	}

	.fw-science-teaser__copy-body {
		grid-column: 1;
		grid-row: 4;
		padding: 0 2.5rem 2.5rem;
	}

	.fw-science-teaser__copy-body > p {
		max-width: 65ch;
	}

	.fw-science-teaser__actions {
		justify-content: flex-start;
		margin-top: 2rem;
	}

	.fw-science-teaser__steps {
		grid-column: 1;
		grid-row: 5;
		display: block;
		padding: 2rem 2.5rem 2.5rem;
		border-top: 1px solid var(--fw-rule);
	}

	.fw-science-teaser__steps ol {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.fw-science-teaser__steps li + li {
		border-left: 0;
	}

	.fw-science-teaser__steps li:nth-child(2n) {
		border-left: 1px solid var(--fw-rule);
	}

	.fw-science-teaser__steps li:nth-child(n + 3) {
		border-top: 1px solid var(--fw-rule);
	}

	.fw-story-cycle__experience {
		grid-template-columns: 1fr;
		min-height: 0;
	}

	.fw-story-cycle__map {
		min-height: 46rem;
		border-right: 0;
		border-bottom: 1px solid currentColor;
	}

	.fw-story-cycle__orbit {
		width: min(100%, 38rem);
	}

	.fw-story-cycle__chapter {
		grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
		grid-template-rows: minmax(27rem, auto);
	}

	.fw-story-cycle__copy {
		min-height: 0;
	}

}

@media (max-width: 960px) {
	.fw-story-cycle__chapter {
		display: contents;
	}

	.fw-story-cycle__experience {
		grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
		grid-template-rows: auto clamp(20rem, 44vw, 26rem) auto;
		grid-template-areas:
			"story-heading story-heading"
			"story-orbit story-photo"
			"story-copy story-copy";
		background: var(--fw-surface);
	}

	.fw-story-cycle__map {
		display: contents;
	}

	.fw-story-cycle__heading {
		grid-area: story-heading;
		margin: 0;
		padding: 1.5rem 1.5rem 0.9rem;
		background: var(--fw-surface);
	}

	.fw-story-cycle__photo {
		grid-area: story-photo;
		align-self: stretch;
		height: auto;
		min-height: 0;
		border-left: 1px solid currentColor;
	}

	.fw-story-cycle__orbit {
		grid-area: story-orbit;
		align-self: center;
		justify-self: center;
		width: min(calc(100% - 1.5rem), 25rem);
		margin: 0;
	}

	.fw-story-cycle__copy {
		grid-area: story-copy;
		min-height: clamp(19rem, 32vw, 23rem);
		border-top: 1px solid currentColor;
		background: var(--fw-surface);
	}
}

@media (max-width: 640px) {
	.fw-story-cycle__experience {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: auto auto auto auto;
		grid-template-areas:
			"story-heading"
			"story-orbit"
			"story-controls"
			"story-copy";
	}

	.fw-story-cycle__photo {
		display: none;
	}

	.fw-story-cycle__heading {
		padding-bottom: 0.25rem;
	}

	.fw-story-cycle__orbit {
		grid-area: story-orbit;
		align-self: center;
		justify-self: center;
		width: min(calc(100% - 0.5rem), 25rem);
		margin: -0.35rem 0 0.75rem;
	}

	.fw-story-cycle__copy {
		display: contents;
	}

	.fw-story-cycle__copy-body {
		grid-area: story-copy;
		padding: 2.15rem 1.5rem 1.75rem;
		background: var(--fw-surface);
		touch-action: pan-y;
	}

	.fw-story-cycle__actions {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		flex-wrap: nowrap;
		width: 100%;
		gap: 0.7rem;
	}

	.fw-story-cycle__actions .fw-btn {
		width: 100%;
		min-width: 0;
		padding-inline: 1rem;
		font-size: 0.9rem;
		white-space: nowrap;
	}

	/* Keep the navigation below the artwork, with the swipe instruction
	   between the arrows rather than over the wheel's lower segments. */
	.fw-story-cycle__arrow {
		position: relative;
		z-index: 4;
		grid-area: story-controls;
		align-self: center;
		width: 2.5rem;
		margin: 0 1.5rem;
	}

	.fw-story-cycle__swipe-hint {
		grid-area: story-controls;
		align-self: center;
		justify-self: center;
		display: block;
		max-width: calc(100% - 9rem);
		margin: 0;
		font-size: 0.74rem;
		font-weight: 800;
		line-height: 1.4;
		letter-spacing: 0.08em;
		text-align: center;
		text-transform: uppercase;
		text-wrap: balance;
		opacity: 0.72;
		touch-action: pan-y;
	}

	.fw-story-cycle__arrow--previous {
		justify-self: start;
	}

	.fw-story-cycle__arrow--next {
		justify-self: end;
	}

	.fw-story-cycle__arrow span {
		font-size: 1.1rem;
	}

	.fw-landing-panel--products > .fw-stage {
		padding: clamp(1.35rem, 4vw, 2rem);
	}

	.fw-stage__layout {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.25rem;
		min-height: 0;
	}

	/* No selector on a phone, and the enzyme family goes with it: the heading
	   is alone above the bottle, so it is centred like the swipe hint and the
	   product below it rather than hanging in the left corner. */
	.fw-stage__selector {
		display: none;
	}

	.fw-stage__header {
		margin-bottom: 0;
		text-align: center;
	}

	.fw-stage__aside,
	.fw-stage__visual,
	.fw-stage__copy {
		grid-column: 1;
	}

	.fw-stage__visual {
		min-height: clamp(21.5rem, 60vw, 24rem);
	}

	.fw-stage__img {
		width: min(100%, 22rem);
		height: clamp(20rem, 55vw, 22rem);
	}

	.fw-stage__arrow--prev {
		left: 0;
	}

	.fw-stage__arrow--next {
		right: 0;
	}

	.fw-stage__swipe-hint {
		position: absolute;
		bottom: 0;
		display: block;
		margin: 0;
		font-size: 0.74rem;
		font-weight: 800;
		letter-spacing: 0.08em;
		text-transform: uppercase;
		opacity: 0.72;
	}

	.fw-stage__copy {
		min-block-size: var(--fw-stage-copy-min-height, 27rem);
	}

	/* The label chip is the heaviest element on a phone: at 9vw the longer
	   product names filled three full-width purple lines and pushed the claim
	   off the first screen. */
	.fw-stage__copy h3 {
		max-width: none;
		margin-bottom: 0.75rem;
		font-size: clamp(1.7rem, 7.2vw, 2.25rem);
	}

}

@media (max-width: 600px) {
	.fw-landing-stack {
		--fw-landing-inset: 1rem;
		gap: 1rem;
		padding-block: 0.75rem 1.5rem;
	}

	.fw-landing-panel > .fw-container {
		padding: 1.5rem;
	}

	.fw-landing-panel > .fw-container,
	.fw-landing-stack .fw-cta-banner__inner {
		border-radius: 1.35rem;
	}

	.fw-landing-panel--products > .fw-stage {
		padding: 1.35rem 1.1rem 1.6rem;
	}

	.fw-stage__header {
		margin-bottom: 0;
	}

	.fw-stage__claim {
		max-width: none;
	}

	.fw-stage__benefits li {
		font-size: 0.86rem;
	}

	/* The claim is a single line where the short description was a paragraph,
	   so the phone shows one bullet more than before. The last bullet stays
	   too: on every product without a hazard statement it is the „Ohne
	   Gefahrenhinweis" line, which must not be cut on the phone (2026-10-06). */
	.fw-stage__benefits li:nth-child(n + 4):not(:last-child) {
		display: none;
	}

	.fw-stage__actions {
		gap: 0.75rem;
	}

	.fw-stage__price {
		flex-basis: 100%;
	}

	.fw-landing-panel--categories > .fw-container {
		padding: 0;
	}

	

	

	

	

	

	.fw-landing-panel--story > .fw-container,
	.fw-landing-panel--science > .fw-container {
		padding: 0;
	}

	.fw-science-teaser__copy > .fw-kicker {
		padding: 2rem 1.5rem 0.8rem;
	}

	/* Phones read the heading first, then the illustration and the copy,
	   without any rule inside the island. */
	.fw-science-teaser__copy .fw-science-teaser__heading {
		grid-row: 2;
		margin: 0 1.5rem;
		padding: 0.4rem 0 0.25rem;
		font-size: clamp(1.35rem, 7vw, 2.4rem);
		line-height: 1.02;
	}

	.fw-science-teaser__visual {
		grid-row: 3;
		min-height: 0;
		padding: 1.25rem 1.25rem 0.75rem;
		border-bottom: 0;
	}

	.fw-science-teaser__copy-body {
		grid-row: 4;
		padding: 0 1.5rem 0.5rem;
	}

	.fw-science-teaser__copy-body > p {
		margin-top: 0;
		padding-top: 0;
		border-top: 0;
	}

	.fw-science-teaser__steps {
		grid-row: 5;
	}

	.fw-science-teaser__steps {
		border-top: 0;
	}

	.fw-science-teaser__illustration {
		width: min(88%, 20rem);
		max-height: 18rem;
	}

	.fw-science-teaser__copy-body > p {
		font-size: 0.98rem;
		line-height: 1.65;
	}

	.fw-science-teaser__actions {
		display: grid;
		grid-template-columns: 1fr;
		width: 100%;
		gap: 0.7rem;
	}

	.fw-science-teaser__actions .fw-btn {
		width: 100%;
	}

	.fw-science-teaser__steps {
		padding: 1.5rem 1.25rem 1.75rem;
	}

	.fw-science-teaser__steps-label {
		margin-bottom: 0.8rem;
	}

	.fw-science-teaser__steps li {
		grid-template-columns: 1.45rem minmax(0, 1fr);
		gap: 0.45rem;
		padding: 0.9rem 0.35rem;
	}

	.fw-science-teaser__steps h3 {
		font-size: 1rem;
	}

	.fw-science-teaser__steps li p {
		font-size: 0.72rem;
	}

	.fw-story-cycle__heading {
		font-size: clamp(2rem, 10vw, 2.75rem);
	}

	.fw-story-cycle__copy {
		grid-template-columns: 2.7rem minmax(0, 1fr) 2.7rem;
		gap: 0.65rem;
		padding: 3.1rem 0.85rem 1.75rem;
	}

	.fw-story-cycle__copy-body {
		padding: 2rem 1.5rem 1.75rem;
	}

	.fw-story-cycle__copy-body h3,
	.fw-story-cycle__copy-ghost h3 {
		font-size: clamp(2rem, 10vw, 2.7rem);
	}

	

	

	

/* The smaller offset block for this breakpoint is gone with the yellow one. */
}

/* == 11 Science page ================================================= */

/* The Science page extends the landing-page island system into a long-form
   explainer. Its target map is the visual signature: terminology and function
   replace decorative icons, while supplied imagery carries each chapter. */
.fw-science-hero {
	min-height: min(58rem, calc(100svh - var(--fw-notice-space)));
	background: transparent;
	color: var(--fw-on-dark);
}

.fw-header-overlay .fw-science-hero {
	padding-top: var(--fw-header-clear);
}

.fw-science-hero__inner {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(24rem, 0.72fr);
	gap: clamp(2rem, 5vw, 6rem);
	align-items: center;
	min-height: min(58rem, calc(100svh - var(--fw-notice-space)));
	padding-block: clamp(4rem, 8vw, 7rem);
}

.fw-science-hero__copy {
	position: relative;
	z-index: 1;
}

.fw-science-hero__title {
	max-width: 13ch;
	margin: 0;
	color: var(--fw-on-dark);
	font-size: clamp(3.35rem, 6.4vw, 7rem);
	line-height: 0.9;
	letter-spacing: -0.055em;
}

.fw-science-hero__title em {
	color: var(--fw-yellow-500);
	font-style: normal;
}

.fw-science-hero__intro {
	max-width: 55ch;
	margin: clamp(1.75rem, 3vw, 2.75rem) 0 0;
	color: var(--fw-on-dark);
	font-size: clamp(1.05rem, 1.6vw, 1.3rem);
}

.fw-science-hero__visual {
	align-self: center;
	display: grid;
	grid-template-rows: minmax(0, 1fr) auto;
	min-height: 0;
	margin: 0;
	overflow: hidden;
	border-radius: clamp(1.5rem, 2.5vw, 2.5rem);
	background: var(--fw-surface);
	color: var(--fw-text);
}

.fw-science-hero__visual img {
	display: block;
	width: 100%;
	height: auto;
	min-height: 0;
	object-fit: contain;
}

.fw-science-hero__visual figcaption {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	border-top: 1px solid var(--fw-text);
	font-size: 0.67rem;
	font-weight: 850;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.fw-science-hero__visual figcaption span {
	padding: 1rem 0.8rem;
}

.fw-science-hero__visual figcaption span + span {
	border-left: 1px solid var(--fw-text);
}

.fw-science-stack {
	display: grid;
	gap: clamp(1rem, 2vw, 2rem);
	padding-block: clamp(1.25rem, 2.5vw, 2.5rem);
	background: transparent;
}

.fw-science-stack > :is(.fw-section, .fw-cta-banner) {
	min-width: 0;
	padding-block: 0;
	background: transparent;
}

/* Every island (and the CTA) shares the hero's measure, so the page reads as
   one column from the hero down. The dark full-bleed chapters (game,
   fermentation, mechanism) lift this cap again. */
.fw-science-panel > .fw-container,
.fw-science-stack .fw-cta-banner__inner {
	box-sizing: border-box;
	min-width: 0;
	width: calc(100% - var(--fw-science-inset));
	max-width: var(--fw-science-measure);
	margin-inline: auto;
	overflow: hidden;
	border-radius: clamp(1.4rem, 2.5vw, 2.5rem);
}
/* ------------------------------------------------------------------
   Fermentation — "Das Reifefenster"
   The one dark section of the page. It breaks the otherwise unbroken run
   of cream islands so the ferment photograph gets a stage of its own.
   ------------------------------------------------------------------ */
/* This section carries the ground colour, so it also carries the ground's
   geometry: full bleed, no island inset, no radius. Keeping the rounded
   island here would draw an edge nobody can see and make the section read
   as a hole rather than as the deliberate opening it is. */
.fw-science-panel--fermentation > .fw-container {
	width: 100%;
	max-width: none;
	padding: clamp(2.5rem, 5vw, 5.5rem) clamp(1.25rem, 4vw, 4.5rem);
	border-radius: 0;
	background: var(--fw-ground);
	color: var(--fw-on-dark);
	/* The radius is 0 here, so nothing needs clipping — and clipping would
	   cut the pinned stage off. Every other panel keeps overflow:hidden. */
	overflow: visible;
}

/* The stage is the desktop/tablet pin target. Its natural height is centred
   in the viewport while the 90 days run; on phones the copy becomes the pin
   target instead. The resting layout is always free to be as tall as needed. */
.fw-ferment__stage {
	display: grid;
	align-items: center;
}

.fw-ferment__stage.is-pinned {
	box-sizing: border-box;
	height: auto;
	padding-top: var(--fw-header-h);
	padding-bottom: clamp(1rem, 2vh, 2rem);
}

/* The hold is CSS sticky inside a runway, not a JS pin (2026-09-30). A JS
   pin switches the stage to position:fixed from a scroll event, one frame
   after the browser has already scrolled, and the stage visibly jumped at
   the moment it caught, most of all when scrolling back up into it. Sticky
   is resolved by the browser itself, so there is no switch to catch.
   animations.js sets the runway height (stage + scroll distance), the
   sticky top and the ease length. */
.fw-ferment__runway.is-sticky {
	height: var(--fw-runway-h);
	margin-bottom: calc(-1 * var(--fw-ease-h, 0px));
}

.fw-ferment__runway.is-sticky > .fw-ferment__stage {
	position: sticky;
	top: var(--fw-sticky-top, 0px);
}

/* The stage does not stop dead: over the first --fw-ease-h of the hold it
   keeps gliding up and slows to a standstill (quadratic ease-out, which
   starts at exactly the scroll speed), and over the last --fw-ease-h it
   picks the scroll speed back up (quadratic ease-in). Driven by the scroll
   position on the compositor, so it cannot lag behind the scroll; the
   ranges are scroll offsets set by animations.js. Browsers without scroll
   timelines get the same curve from GSAP. The two halves animate separate
   properties (translate / transform) so they add up. */
@supports (animation-timeline: scroll()) {
	.fw-ferment__runway.is-sticky.is-css-ease > .fw-ferment__stage {
		animation: fw-ferment-settle linear both, fw-ferment-release linear both;
		animation-timeline: scroll(root), scroll(root);
		animation-range:
			var(--fw-settle-start) var(--fw-settle-end),
			var(--fw-release-start) var(--fw-release-end);
	}
}

@keyframes fw-ferment-settle {
	from {
		translate: 0 0;
		animation-timing-function: cubic-bezier(0.3333, 0.6667, 0.6667, 1);
	}
	to {
		translate: 0 calc(var(--fw-ease-h) / -2);
	}
}

@keyframes fw-ferment-release {
	from {
		transform: translateY(0);
		animation-timing-function: cubic-bezier(0.3333, 0, 0.6667, 0.3333);
	}
	to {
		transform: translateY(calc(var(--fw-ease-h) / -2));
	}
}

/* The stage takes the islands' inner text measure, so its photo and copy
   edges line up with the text inside the cream islands above and below. */
.fw-science-panel--fermentation .fw-ferment,
.fw-science-panel--fermentation .fw-ferment__faq {
	max-width: var(--fw-science-content);
	margin-inline: auto;
}

/* The stage is a grid item of `.fw-ferment__stage`; with auto margins alone a
   grid item shrinks to its content (the two-column composition rendered
   1211px wide inside a 1346px measure). Explicit width plus justify-self
   makes it fill the measure and centre. Kept to the two-column layout: the
   single-column tablet stage is approved as a compact centred block. */
@media (min-width: 1101px) {
	.fw-science-panel--fermentation .fw-ferment {
		width: 100%;
		justify-self: center;
	}
}

/* The stage itself owns the fixed-header clearance. A second width-driven
   block of container padding created 70-90px of extra air on laptop
   screens and made the transition vary with monitor size. Keep the mobile
   spacing untouched; the wide two-column composition gets one stable,
   height-aware inset. */
@media (min-width: 1101px) {
	.fw-science-panel--fermentation > .fw-container {
		padding-block: clamp(1rem, 1.5vh, 2rem);
	}

	.fw-science-panel--fermentation .fw-ferment__faq {
		margin-top: clamp(1rem, 1.6vh, 1.75rem);
	}
}

/* --fw-heading is the same value as --fw-ground, so an un-overridden
   heading is invisible here, not merely off-palette. All six levels on
   purpose — see the dark-context rules further up. */
.fw-science-panel--fermentation :is(h1, h2, h3, h4, h5, h6) {
	color: var(--fw-on-dark);
}

.fw-science-panel--fermentation .fw-kicker {
	color: var(--fw-accent);
}

.fw-ferment {
	display: grid;
	/* The copy carries the explanation and gets the wider track; the photo
	   used to dominate it and left the text column looking undersized. */
	grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
	gap: clamp(1.75rem, 3.5vw, 3.5rem);
	/* Stretch, not center: the photograph is the subject of this section
	   and fills the full height of the row. */
	align-items: stretch;
}

.fw-ferment > * {
	min-width: 0;
}

.fw-ferment__media {
	position: relative;
	min-height: clamp(26rem, 46vw, 40rem);
	margin: 0;
	overflow: hidden;
	border-radius: clamp(1rem, 2vw, 1.75rem);
	background: var(--fw-green-700);
}

.fw-ferment__media img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.fw-ferment__copy {
	align-self: center;
}

/* Inside the pin the whole composition has at most one viewport to live
   in, so type scales against the viewport HEIGHT as well as its width.
   Without the vh term the headline and counter push the phases off the
   bottom of short laptop screens. */
.fw-ferment__stage.is-pinned .fw-ferment {
	height: auto;
	align-items: stretch;
}

/* The copy determines the row height and the photograph follows that same
   edge-to-edge geometry. Independently centring a 68svh image against a
   dynamically measured reel made their top edges cross over as viewport
   height changed: too low on laptops, too high on large monitors. */
.fw-ferment__stage.is-pinned .fw-ferment__media {
	align-self: stretch;
	min-height: 0;
	height: auto;
}

.fw-ferment__stage.is-pinned .fw-ferment__copy {
	align-self: start;
}

.fw-ferment__stage.is-pinned .fw-ferment__copy h2 {
	font-size: clamp(1.75rem, min(3.1vw, 4.6vh), 3.5rem);
}

/* The phone copy pin had no heading reduction of its own: the desktop
   2.35rem+ heading took three lines and, measured with the real fonts, the
   copy no longer fit a 360×640 viewport (the pin silently fell back).
   Two lines at this size keep the whole copy inside the viewport. */
.fw-ferment__stage.is-copy-pinned .fw-ferment__copy h2 {
	font-size: clamp(1.6rem, 7vw, 2.35rem);
}

.fw-ferment__stage.is-pinned .fw-ferment__count {
	font-size: clamp(2.25rem, min(4.4vw, 6.4vh), 4.5rem);
}

.fw-ferment__stage.is-pinned .fw-ferment__clock {
	margin-top: clamp(1rem, 2.2vh, 2rem);
}


.fw-ferment__copy h2 {
	margin: 0;
	font-size: clamp(2.35rem, 4vw, 4.25rem);
	line-height: 0.98;
	letter-spacing: -0.04em;
}

/* The 90-day clock. The counter carries the time information; the photo
   above carries atmosphere only and makes no claim about any given day. */
.fw-ferment__clock {
	margin-top: clamp(1.75rem, 3vw, 2.5rem);
}

.fw-ferment__count {
	margin: 0;
	color: var(--fw-accent);
	font-family: var(--fw-font-display);
	font-size: clamp(3rem, 5.5vw, 5rem);
	font-variant-numeric: tabular-nums;
	line-height: 1;
	letter-spacing: -0.045em;
}

.fw-ferment__count em {
	font-size: 0.42em;
	font-style: normal;
	letter-spacing: -0.01em;
}

/* One bar, two readings: elapsed days fill it continuously, and the three
   phases are marked as segments of the same line. */
.fw-ferment__timeline {
	margin-top: clamp(1rem, 2vh, 1.5rem);
}

.fw-ferment__timeline-ends {
	display: flex;
	justify-content: space-between;
	margin-bottom: 0.5rem;
	color: var(--fw-on-dark);
	font-size: 0.62rem;
	font-weight: 850;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	/* 0.74, not 0.7: the lowest opacity that reaches 4.5 : 1 on the
	   ground (4.54; was 4.25), owner 2026-10-13. */
	opacity: 0.74;
}

.fw-ferment__timeline-bar {
	position: relative;
	height: 3px;
	border-radius: 2px;
	background: rgba(239, 237, 228, 0.22);
}

.fw-ferment__timeline-fill {
	display: block;
	height: 100%;
	border-radius: inherit;
	background: var(--fw-accent);
	transform: scaleX(1);
	transform-origin: left center;
}

.fw-ferment__timeline-tick {
	position: absolute;
	top: 50%;
	width: 2px;
	height: 11px;
	margin-left: -1px;
	background: var(--fw-ground);
	transform: translateY(-50%);
}

.fw-ferment__timeline-tick::after {
	content: '';
	position: absolute;
	inset: 0;
	background: rgba(239, 237, 228, 0.45);
}

.fw-ferment__timeline-labels {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: clamp(0.4rem, 1vw, 0.9rem);
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
}

.fw-ferment__timeline-labels li {
	min-width: 0;
	color: var(--fw-on-dark);
	font-size: clamp(0.68rem, 0.8vw, 0.78rem);
	font-weight: 850;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.fw-ferment__timeline-labels li > span {
	margin-right: 0.4rem;
	font-size: 0.62rem;
	letter-spacing: 0.14em;
	opacity: 0.6;
}

/* The reel. Resting state (no JS, reduced motion) is a plain stacked
   list; .is-reel turns it into a drum the phases ride on. */
.fw-ferment__reel {
	margin-top: clamp(1.4rem, 2.6vh, 2.25rem);
}

/* Each phase is a slat on the drum. Giving it a surface is what makes the
   rotation legible — bare text tilting in empty space reads as distortion,
   a tilting panel reads as an object turning. */
.fw-ferment__reel article {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	gap: clamp(0.9rem, 1.8vw, 1.5rem);
	align-items: start;
	padding: clamp(1.25rem, 2.1vw, 1.85rem) clamp(1.5rem, 2.6vw, 2.35rem);
	border: 1px solid rgba(239, 237, 228, 0.16);
	border-radius: clamp(0.85rem, 1.4vw, 1.2rem);
	background: rgba(239, 237, 228, 0.07);
}

.fw-ferment__reel article + article {
	margin-top: clamp(0.75rem, 1.4vh, 1.1rem);
}

.fw-ferment__reel-step {
	margin: 0;
	color: var(--fw-accent);
	font-family: var(--fw-font-display);
	font-size: clamp(1.9rem, 2.9vw, 2.7rem);
	font-variant-numeric: tabular-nums;
	line-height: 0.9;
	letter-spacing: -0.04em;
}

.fw-ferment__reel-body {
	min-width: 0;
}

.fw-ferment__reel-label {
	display: block;
	margin-bottom: 0.35rem;
	color: var(--fw-accent);
	font-size: 0.66rem;
	font-weight: 850;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.fw-ferment__reel-body h3 {
	margin: 0 0 0.45rem;
	font-size: clamp(1.2rem, 1.7vw, 1.55rem);
	line-height: 1.15;
}

/* Scoped to the body on purpose: a bare `.fw-ferment__reel p` (0-1-1)
   outranks the step number's own class (0-1-0) and shrank it to body size. */
.fw-ferment__reel-body p {
	margin: 0;
	color: var(--fw-on-dark);
	font-size: clamp(0.9rem, 1vw, 1rem);
	line-height: 1.5;
}

/* Drum mode: the phases sit on the surface of a horizontal cylinder.
   JS positions each one on that cylinder from a continuous scroll
   position, so the current phase faces the reader while the previous one
   tilts away above and the next rises from below. */
.fw-ferment__reel.is-reel {
	position: relative;
	height: var(--fw-reel-h, 20rem);
	overflow: hidden;
	perspective: var(--fw-reel-perspective, 900px);
	perspective-origin: 50% 50%;
	/* Fade the drum out at both ends so phases leave and enter the window
	   instead of being cut off by a hard edge. */
	/* A generous fade at both ends. The drum is a straight sequence, not a
	   loop, so nothing sits above the first phase or below the last; a soft
	   edge lets that read as the drum running out rather than as a hole. */
	mask-image: linear-gradient(
		to bottom,
		transparent 0,
		#000 24%,
		#000 76%,
		transparent 100%
	);
}

/* In drum mode the timeline above already names the current phase, so the
   label inside the slat would repeat it. The stacked fallback has no
   indicator and still needs it. */
.fw-ferment__reel.is-reel .fw-ferment__reel-label {
	display: none;
}

/* Only position and margin change in drum mode. The slat keeps its own
   padding and border — zeroing them here (a leftover from the earlier
   borderless list) both flattened the card and, because the height is
   measured with padding but rendered without it, inflated the drum radius
   and blew the gaps between slats wide open. */
.fw-ferment__reel.is-reel article {
	position: absolute;
	top: 50%;
	right: 0;
	left: 0;
	margin: 0;
	transform-origin: 50% 50%;
	backface-visibility: hidden;
	will-change: transform, opacity;
}

/* The alcohol question is the same collapsible as the scent question in the
   mechanism chapter; both dark chapters share the styling further down. */
.fw-science-panel--fermentation .fw-ferment__faq {
	margin-top: clamp(1.75rem, 3vw, 2.75rem);
}

@media (max-width: 1100px) {
	.fw-science-hero__inner {
		grid-template-columns: minmax(0, 1fr) minmax(21rem, 0.65fr);
	}

	.fw-science-hero__visual {
		min-height: 34rem;
	}
}

@media (max-width: 860px) {
	.fw-science-hero {
		min-height: 0;
	}

	.fw-science-hero__inner {
		grid-template-columns: 1fr;
		min-height: 0;
		padding-bottom: 2rem;
	}

	.fw-science-hero__title {
		max-width: 12ch;
	}

	.fw-science-hero__visual {
		min-height: 0;
		max-height: none;
	}

	.fw-science-hero__visual img {
		max-height: none;
		object-fit: contain;
	}
}

@media (max-width: 600px) {
	.fw-science-hero__inner {
		padding-top: 3rem;
	}

	.fw-science-hero__title {
		font-size: clamp(3rem, 14vw, 4.6rem);
	}

	.fw-science-hero__visual img {
		height: auto;
	}

	.fw-science-hero__visual figcaption {
		grid-template-columns: 1fr;
	}

	.fw-science-hero__visual figcaption span {
		padding: 0.7rem 1rem;
	}

	.fw-science-hero__visual figcaption span + span {
		border-top: 1px solid var(--fw-text);
		border-left: 0;
	}

	.fw-science-stack {
		gap: 1rem;
		padding-block: 0.75rem 1.5rem;
	}

	/* Phones: no inner measure. The islands' padding is a tiny inset here,
	   and subtracting it twice left a 270px game card and a narrow ferment
	   stage inside a 360px viewport. Both may use the full container width. */
	:root {
		--fw-science-inset: 1rem;
		--fw-science-content: none;
	}

	.fw-science-panel > .fw-container,
	.fw-science-stack .fw-cta-banner__inner {
		border-radius: 1.35rem;
	}

}

.fw-science-hero__visual figcaption {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

.fw-science-panel--compare > .fw-container {
	padding: clamp(2.5rem, 5vw, 5.5rem);
}

.fw-science-panel--compare > .fw-container {
	background: var(--fw-surface);
	color: var(--fw-text);
}

.fw-science-scent {
	margin-top: 1.5rem;
	border: 1px solid currentColor;
	border-radius: 1rem;
}

.fw-science-scent summary {
	position: relative;
	padding: 1rem 3.25rem 1rem 1.15rem;
	font-family: var(--fw-font-display);
	font-size: 1.08rem;
	font-weight: 750;
	cursor: pointer;
	list-style: none;
}

.fw-science-scent summary::-webkit-details-marker {
	display: none;
}

.fw-science-scent summary::after {
	content: '+';
	position: absolute;
	top: 50%;
	right: 1.15rem;
	font-family: var(--fw-font-body);
	font-size: 1.4rem;
	transform: translateY(-50%);
}

.fw-science-scent[open] summary::after {
	content: '−';
}

.fw-science-scent p {
	margin: 0;
	padding: 0 1.15rem 1.15rem;
	color: inherit;
	font-size: 0.9rem;
	opacity: 0.78;
}



























































































@media (max-width: 600px) {

	.fw-science-hero__visual figcaption {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.fw-science-hero__visual figcaption span + span {
		border-top: 0;
		border-left: 1px solid var(--fw-dark-brown);
	}

	.fw-science-hero__visual figcaption span:nth-child(n + 3) {
		border-top: 1px solid var(--fw-dark-brown);
	}

	.fw-science-hero__visual figcaption span:nth-child(3) {
		border-left: 0;
	}

	.fw-science-panel--compare > .fw-container {
		padding: 2rem 1.5rem;
	}

	

	

	

	

	

	

	

	

	

	

	

	

	

	

	

	
}

@media (prefers-reduced-motion: reduce) {
	.fw-science-teaser__illustration {
		transition: none;
	}
}

/* Science page: one evidence-led narrative instead of stacked data tables.
   The comparison is a continuous split field; the mechanism below reads as
   one reaction path from ferment to rinsing water. */
.fw-science-hero {
	min-height: 0;
}

/* Same width formula as the islands below: the hero copy's left edge and the
   first island's left edge are one line at every viewport. */
.fw-science-hero__inner {
	width: calc(100% - var(--fw-science-inset));
	max-width: var(--fw-science-measure);
	grid-template-columns: minmax(30rem, 0.98fr) minmax(30rem, 1.02fr);
	gap: clamp(2rem, 4.5vw, 7rem);
	align-items: start;
	min-height: 0;
	padding: clamp(1.5rem, 2.5vw, 3rem) 0 clamp(1rem, 1.75vw, 2rem);
}

.fw-science-hero__title {
	max-width: 12.5ch;
	font-size: clamp(3.8rem, 6.2vw, 7.6rem);
}

.fw-science-hero__title span,
.fw-science-hero__title em {
	display: block;
}

.fw-science-hero__intro {
	max-width: 62ch;
	font-size: clamp(1.05rem, 1.35vw, 1.28rem);
	line-height: 1.65;
}

.fw-science-hero__visual {
	display: grid;
	place-items: center;
	min-height: clamp(34rem, 48vw, 52rem);
	overflow: visible;
	border-radius: 0;
	background: transparent;
}

.fw-science-hero__visual img {
	width: min(100%, 48rem);
	height: auto;
	max-height: min(78svh, 52rem);
	object-fit: contain;
}

@media (min-width: 861px) {
	.fw-science-hero__inner {
		padding-bottom: 0.75rem;
	}

	.fw-science-hero__visual {
		position: relative;
		top: clamp(-3.5rem, -3.2vw, -2.625rem);
		margin-bottom: clamp(-3.5rem, -3.2vw, -2.625rem);
	}

	.fw-science-stack {
		padding-top: clamp(0.75rem, 1.25vw, 1.25rem);
	}
}

.fw-science-panel--enzyme-intro > .fw-container,
.fw-science-panel--compare > .fw-container,
.fw-science-panel--mechanism > .fw-container,
.fw-science-panel--scoby > .fw-container {
	padding: clamp(2.5rem, 5vw, 6rem);
}

.fw-science-panel--enzyme-intro > .fw-container,
.fw-science-panel--compare > .fw-container,
.fw-science-panel--scoby > .fw-container {
	background: var(--fw-surface);
	color: var(--fw-text);
}

/* No container padding: the columns carry it (landing "Enzymkraft" pattern),
   so the middle column's rules run from the island's top edge to its bottom
   edge instead of stopping short inside a padded frame. */
.fw-science-panel--enzyme-intro > .fw-container {
	--fw-enzyme-pad: clamp(3rem, 3vw, 4.25rem);
	--fw-enzyme-row-pad: clamp(1.5rem, 2.8vw, 3rem);
	padding: 0;
}

/* The generic mobile island radius is declared after the fermentation base
   styles. Reassert the full-bleed geometry here so phones do not silently
   turn the dark chapter back into a rounded panel. */
.fw-science-panel--fermentation > .fw-container {
	border-radius: 0;
}

/* ------------------------------------------------------------------
   Enzymes as one three-column chapter (2026-09-18), the grid of the landing
   page's "Die Enzymkraft" section: plain-language primer left, the
   specialist text ruled on both sides in the middle (where the landing
   page keeps its illustration), the four enzyme classes as the hover list
   on the right. The island ends with the list; the game follows as its
   own section on the ground.
   ------------------------------------------------------------------ */
/* Three equal columns, exactly the landing grid. The chapter is the query
   container for both headings: the island is capped at the page measure, so
   a viewport-scaled heading keeps growing on wide monitors while its column
   does not ("Unterschiedlicher" ran into the list at 2560px), and sizing
   both headings from the same chapter width keeps them identical. */
.fw-enzyme-chapter {
	container-type: inline-size;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	align-items: stretch;
	min-height: clamp(40rem, 40vw, 48rem);
}

.fw-enzyme-chapter > * {
	min-width: 0;
}

/* Left column: the primer. Centred against the list's height like the
   landing copy column, with the same padding as the middle column so the
   two text columns share one content width. */
.fw-enzyme-intro__lead {
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: var(--fw-enzyme-pad);
}

.fw-enzyme-intro__lead h2,
.fw-enzyme-specialists__intro h2 {
	max-width: 14ch;
	margin: 0;
	color: var(--fw-heading);
	font-size: clamp(2rem, 3.1cqi, 3.4rem);
	line-height: 0.98;
	letter-spacing: -0.045em;
}

.fw-enzyme-intro__copy {
	margin-top: clamp(1.25rem, 2vw, 1.75rem);
	padding-top: 1.2rem;
	border-top: 1px solid var(--fw-rule);
}

.fw-enzyme-intro__copy p {
	max-width: 46ch;
	margin: 0;
	font-size: clamp(0.98rem, 1.08vw, 1.1rem);
	line-height: 1.65;
}

.fw-enzyme-intro__copy p:first-child {
	font-weight: 720;
}

.fw-enzyme-intro__copy p + p {
	margin-top: 0.85rem;
}

/* "Spiel" in the primer jumps to the game section below. */
.fw-enzyme-intro__game-link {
	color: var(--fw-heading);
	font-weight: 700;
	text-decoration: none;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.18em;
}

.fw-enzyme-intro__game-link:hover,
.fw-enzyme-intro__game-link:focus-visible {
	color: var(--fw-heading);
	text-decoration: underline;
}

/* The fixed header must not cover the game heading after the jump. */
.fw-science-panel--game {
	scroll-margin-top: var(--fw-header-h);
}

/* The game card. It sits on the ground now, so the hairline is what makes
   it read as an object rather than as a hole in the section. */
.fw-enzyme-game {
	width: 100%;
	max-width: var(--fw-science-content);
	margin: 0 auto;
	overflow: hidden;
	border: 1px solid rgba(239, 237, 228, 0.16);
	border-radius: clamp(1.25rem, 2.2vw, 2rem);
	background: var(--fw-ground);
	color: var(--fw-on-dark);
	isolation: isolate;
}

/*
 * The whole arcade island sits on the dark ground colour, so every heading
 * inside it needs an explicit colour: --fw-heading is wertgleich mit
 * --fw-ground and would render invisible. That applies to the legend headings
 * below as much as to anything else.
 */
.fw-enzyme-game :is(h1, h2, h3, h4, h5, h6) {
	color: var(--fw-on-dark);
}

.fw-enzyme-game__bar {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	gap: clamp(1rem, 2.5vw, 2.25rem);
	align-items: center;
	padding: clamp(1rem, 2vw, 1.4rem) clamp(1.1rem, 2.5vw, 2rem);
	border-bottom: 1px solid color-mix(in srgb, var(--fw-on-dark) 20%, transparent);
}

.fw-enzyme-game__bar p {
	margin: 0;
}

.fw-enzyme-game__eyebrow {
	font-size: 0.72rem;
	font-weight: 900;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--fw-accent);
	/* One long word: without this it overflows its auto column onto the rail. */
	white-space: nowrap;
}

/* Three stations, three fills. The rail replaces the old "Station: Küche" text. */
.fw-enzyme-game__rail {
	display: flex;
	gap: clamp(0.5rem, 1.5vw, 1.15rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.fw-enzyme-game__station {
	--fw-station-fill: 0;
	position: relative;
	flex: 1 1 0;
	min-width: 0;
	padding-bottom: 0.6rem;
	line-height: 1.15;
}

.fw-enzyme-game__station::after,
.fw-enzyme-game__station::before {
	content: '';
	position: absolute;
	bottom: 0;
	height: 3px;
	border-radius: 999px;
}

.fw-enzyme-game__station::after {
	inset-inline: 0;
	background: color-mix(in srgb, var(--fw-on-dark) 22%, transparent);
}

.fw-enzyme-game__station::before {
	z-index: 1;
	inset-inline-start: 0;
	width: calc(var(--fw-station-fill) * 100%);
	background: var(--fw-accent);
	transition: width 240ms ease;
}

.fw-enzyme-game__station span {
	display: block;
	font-size: 0.6rem;
	font-weight: 900;
	letter-spacing: 0.14em;
	color: color-mix(in srgb, var(--fw-on-dark) 62%, transparent);
}

.fw-enzyme-game__station strong {
	display: block;
	overflow: hidden;
	font-family: var(--fw-font-display);
	font-size: clamp(0.95rem, 1.3vw, 1.15rem);
	color: color-mix(in srgb, var(--fw-on-dark) 70%, transparent);
	text-overflow: ellipsis;
	white-space: nowrap;
}

.fw-enzyme-game__station.is-active strong {
	color: var(--fw-accent);
}

.fw-enzyme-game__station.is-done strong {
	color: var(--fw-on-dark);
}

.fw-enzyme-game__meters {
	display: flex;
	flex: 0 0 auto;
	gap: clamp(0.7rem, 1.4vw, 1.25rem);
	align-items: center;
}

.fw-enzyme-game__score span {
	font-size: 0.63rem;
	font-weight: 850;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--fw-on-dark) 72%, transparent);
}

.fw-enzyme-game__jumps {
	display: flex;
	gap: 0.3rem;
	align-items: center;
	padding: 0.46rem 0.58rem;
	border: 1px solid color-mix(in srgb, var(--fw-on-dark) 24%, transparent);
	border-radius: 999px;
}

.fw-enzyme-game__jumps span {
	display: block;
	width: 0.58rem;
	aspect-ratio: 1;
	border: 1px solid var(--fw-accent);
	border-radius: 50%;
	background: var(--fw-accent);
	transition: opacity 120ms ease, background-color 120ms ease;
}

.fw-enzyme-game__jumps span.is-used {
	background: transparent;
	opacity: 0.4;
}

.fw-enzyme-game__score {
	display: flex;
	gap: 0.65rem;
	align-items: baseline;
}

.fw-enzyme-game__score strong {
	font-family: var(--fw-font-display);
	font-size: clamp(1.8rem, 3vw, 3rem);
	font-weight: 750;
	line-height: 0.8;
	color: var(--fw-accent);
}

/*
 * The playfield must not become a thin letterbox on wide screens: the jump
 * height and the scene scale both derive from this height, so a short strip on
 * a 2560 px monitor leaves the character tiny and the world slow.
 */
.fw-enzyme-game__viewport {
	position: relative;
	height: clamp(18rem, 29vw, 26rem);
	overflow: hidden;
	background: var(--fw-ground);
}

@media (min-width: 1500px) {
	.fw-enzyme-game__viewport {
		height: clamp(24rem, 22vw, 31rem);
	}
}

.fw-enzyme-game canvas {
	display: block;
	width: 100%;
	height: 100%;
	background: var(--fw-ground);
	image-rendering: pixelated;
	touch-action: pan-y;
	user-select: none;
	visibility: hidden;
}

.fw-enzyme-game.is-enhanced canvas {
	visibility: visible;
}

.fw-enzyme-game__fallback {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	margin: 0;
	padding: 2rem;
	text-align: center;
	color: var(--fw-on-dark);
}

.fw-enzyme-game.is-enhanced .fw-enzyme-game__fallback {
	display: none;
}

.fw-enzyme-game.is-running canvas {
	cursor: pointer;
	touch-action: none;
}

.fw-enzyme-game canvas:focus-visible,
.fw-enzyme-game__start:focus-visible {
	outline: 3px solid var(--fw-accent);
	outline-offset: -6px;
}

/*
 * Without JavaScript no start control is exposed at all — offering a button
 * that cannot start anything is worse than the honest static fallback.
 */
.fw-enzyme-game .fw-enzyme-game__overlay {
	display: none;
}

.fw-enzyme-game.is-enhanced .fw-enzyme-game__overlay {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
	align-items: center;
	justify-content: center;
	padding: clamp(1rem, 3vw, 2rem);
	background: linear-gradient(180deg, color-mix(in srgb, var(--fw-ground) 62%, transparent), color-mix(in srgb, var(--fw-ground) 84%, transparent));
	text-align: center;
	-webkit-backdrop-filter: blur(2px);
	backdrop-filter: blur(2px);
}

.fw-enzyme-game__overlay-kicker {
	font-size: 0.7rem;
	font-weight: 900;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--fw-accent);
}

.fw-enzyme-game__overlay-title {
	font-family: var(--fw-font-display);
	font-size: clamp(1.5rem, 3.2vw, 2.5rem);
	line-height: 1;
	color: var(--fw-on-dark);
}

.fw-enzyme-game__overlay-text {
	max-width: 46ch;
	font-size: clamp(0.86rem, 1.1vw, 1rem);
	line-height: 1.5;
	color: color-mix(in srgb, var(--fw-on-dark) 84%, transparent);
}

.fw-enzyme-game__overlay small {
	font-size: 0.8rem;
	color: color-mix(in srgb, var(--fw-on-dark) 72%, transparent);
}

.fw-enzyme-game .fw-enzyme-game__start,
.fw-enzyme-game .fw-enzyme-game__start:is(:hover, :focus, :active) {
	margin: 0.35rem 0 0.1rem;
	padding: 0.78rem 1.6rem;
	border: 0;
	border-radius: 999px;
	background: var(--fw-accent);
	box-shadow: none;
	font-family: var(--fw-font-display);
	font-size: clamp(1.05rem, 1.8vw, 1.4rem);
	line-height: 1;
	color: var(--fw-green-700);
	cursor: pointer;
	transition: transform 180ms ease;
}

.fw-enzyme-game .fw-enzyme-game__start:hover {
	transform: scale(1.04);
}

/* The station beat plays while the game keeps running, so it never takes input. */
.fw-enzyme-game__banner {
	position: absolute;
	inset-inline: 0;
	top: clamp(0.9rem, 6%, 2.2rem);
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	align-items: center;
	margin: 0;
	padding-inline: 1rem;
	text-align: center;
	pointer-events: none;
}

.fw-enzyme-game__banner strong {
	padding: 0.45rem 1.15rem;
	border-radius: 999px;
	background: var(--fw-accent);
	font-family: var(--fw-font-display);
	font-size: clamp(1.05rem, 2.2vw, 1.6rem);
	line-height: 1;
	color: var(--fw-green-700);
}

.fw-enzyme-game__banner span {
	padding: 0.2rem 0.7rem;
	border-radius: 999px;
	background: color-mix(in srgb, var(--fw-ground) 72%, transparent);
	font-size: 0.82rem;
	color: var(--fw-on-dark);
}

body.fw-enzyme-game-active #ast-scroll-top {
	opacity: 0 !important;
	visibility: hidden !important;
	pointer-events: none !important;
}

.fw-enzyme-game:not(.is-enhanced) .fw-enzyme-game__footer p:first-child {
	display: none;
}

/*
 * The legend does the job the floating canvas labels used to do badly: it names
 * what is collected AND which enzyme specialist fits it, so the section carries
 * the message even for a visitor who never presses start. Collectibles show the
 * same yellow aura the playfield gives them; obstacles deliberately show none.
 */
.fw-enzyme-game__legend {
	display: grid;
	grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
	gap: clamp(1.1rem, 3vw, 2.75rem);
	padding: clamp(1.05rem, 2.2vw, 1.6rem) clamp(1.1rem, 2.5vw, 2rem);
	border-top: 1px solid color-mix(in srgb, var(--fw-on-dark) 20%, transparent);
	background: rgba(0, 0, 0, 0.12);
}

.fw-enzyme-game__legend h3 {
	margin: 0 0 0.8rem;
	font-family: var(--fw-font-body);
	font-size: 0.68rem;
	font-weight: 900;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--fw-on-dark) 72%, transparent);
}

.fw-enzyme-game__legend-group--collect h3 {
	color: var(--fw-accent);
}

.fw-enzyme-game__legend ul {
	display: flex;
	flex-wrap: wrap;
	gap: 0.7rem clamp(0.9rem, 2vw, 1.6rem);
	margin: 0;
	padding: 0;
	list-style: none;
}

.fw-enzyme-game__legend li {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	align-items: center;
	column-gap: 0.55rem;
}

.fw-enzyme-game__legend img {
	grid-row: 1 / -1;
	width: clamp(2.1rem, 3vw, 2.6rem);
	height: auto;
	aspect-ratio: 1;
	object-fit: contain;
	image-rendering: pixelated;
}

.fw-enzyme-game__legend-group--collect img {
	border-radius: 50%;
	background: radial-gradient(circle, rgba(249, 202, 18, 0.4) 34%, rgba(249, 202, 18, 0) 70%);
}

.fw-enzyme-game__legend span {
	font-size: clamp(0.82rem, 1vw, 0.94rem);
	font-weight: 800;
	color: var(--fw-on-dark);
}

.fw-enzyme-game__legend small {
	font-size: 0.72rem;
	color: color-mix(in srgb, var(--fw-on-dark) 70%, transparent);
}

.fw-enzyme-game__footer {
	display: flex;
	gap: 1rem 2rem;
	align-items: center;
	justify-content: space-between;
	min-height: 3.6rem;
	padding: 0.8rem clamp(1.1rem, 2.5vw, 2rem);
	border-top: 1px solid color-mix(in srgb, var(--fw-on-dark) 20%, transparent);
}

.fw-enzyme-game__footer p {
	margin: 0;
	font-size: 0.78rem;
	line-height: 1.45;
	color: color-mix(in srgb, var(--fw-on-dark) 78%, transparent);
}

.fw-enzyme-game__footer p:last-child {
	text-align: right;
}

.fw-enzyme-game__footer kbd {
	padding: 0.17rem 0.38rem;
	border: 1px solid color-mix(in srgb, var(--fw-on-dark) 36%, transparent);
	border-radius: 0.3rem;
	background: color-mix(in srgb, var(--fw-on-dark) 8%, transparent);
	font: inherit;
	font-weight: 800;
	color: var(--fw-on-dark);
}

/* ------------------------------------------------------------------
   The game section: full bleed on the ground like the fermentation, with
   one centred single-line heading above the card. --fw-heading equals
   --fw-ground, so the heading colour must be restated here.
   ------------------------------------------------------------------ */
.fw-science-panel--game > .fw-container {
	width: 100%;
	max-width: none;
	padding: clamp(1.5rem, 3vw, 3rem) clamp(1.25rem, 4vw, 4.5rem);
	overflow: visible;
	border-radius: 0;
	background: var(--fw-ground);
	color: var(--fw-on-dark);
}

.fw-science-panel--game :is(h1, h2, h3, h4, h5, h6) {
	color: var(--fw-on-dark);
}

.fw-science-panel--game .fw-kicker {
	color: var(--fw-accent);
}

.fw-enzyme-game-intro {
	max-width: var(--fw-science-content);
	margin: 0 auto clamp(1.5rem, 2.5vw, 2.5rem);
	text-align: center;
}

.fw-enzyme-game-intro h2 {
	max-width: none;
	margin: 0;
	font-size: clamp(2.2rem, 4.2vw, 4.6rem);
	line-height: 0.95;
	letter-spacing: -0.05em;
	text-wrap: balance;
}

@media (max-width: 860px) {
	.fw-enzyme-game__viewport {
		height: clamp(17rem, 62vw, 21rem);
	}

	/* The eyebrow moves above the rail so all three stations keep their width. */
	.fw-enzyme-game__bar {
		grid-template-columns: minmax(0, 1fr) auto;
		gap: 0.7rem 1rem;
	}

	.fw-enzyme-game__eyebrow {
		grid-column: 1 / -1;
	}

	.fw-enzyme-game__legend {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.1rem;
	}

	.fw-enzyme-game__legend-group--avoid {
		padding-top: 1.1rem;
		border-top: 1px solid color-mix(in srgb, var(--fw-on-dark) 18%, transparent);
	}
}

@media (max-width: 560px) {
	.fw-science-panel--enzyme-intro > .fw-container {
		--fw-enzyme-pad: clamp(1.1rem, 5vw, 1.5rem);
		--fw-enzyme-row-pad: clamp(1.1rem, 5vw, 1.5rem);
		padding: 0;
	}

	.fw-science-panel--game > .fw-container {
		padding-inline: 0.75rem;
	}

	.fw-enzyme-game {
		border-radius: 1.15rem;
	}

	.fw-enzyme-game__bar {
		align-items: center;
		padding: 0.85rem 1rem;
	}

	.fw-enzyme-game__rail {
		gap: 0.4rem;
	}

	.fw-enzyme-game__station {
		padding-bottom: 0.5rem;
	}

	.fw-enzyme-game__station span {
		font-size: 0.52rem;
	}

	.fw-enzyme-game__station strong {
		font-size: 0.82rem;
	}

	.fw-enzyme-game__score span {
		font-size: 0.55rem;
	}

	.fw-enzyme-game__legend {
		padding: 0.95rem 1rem;
	}

	.fw-enzyme-game__legend ul {
		gap: 0.6rem 1rem;
	}

	.fw-enzyme-game__jumps {
		gap: 0.22rem;
		padding: 0.36rem 0.42rem;
	}

	.fw-enzyme-game__jumps span {
		width: 0.48rem;
	}

	.fw-enzyme-game__score {
		gap: 0.28rem;
		align-items: flex-end;
		flex-direction: column;
	}

	.fw-enzyme-game__score strong {
		font-size: 2rem;
	}

	.fw-enzyme-game__viewport {
		height: clamp(17rem, 78vw, 19.5rem);
	}

	.fw-enzyme-game__overlay small {
		max-width: 26ch;
		font-size: 0.76rem;
	}

	.fw-enzyme-game__footer {
		display: grid;
		gap: 0.6rem;
		min-height: 4.4rem;
		padding: 0.75rem 1rem;
	}

	.fw-enzyme-game__footer p:last-child {
		text-align: left;
	}
}

@media (prefers-reduced-motion: reduce) {
	.fw-enzyme-game__jumps span,
	.fw-enzyme-game__station::before,
	.fw-enzyme-game .fw-enzyme-game__start {
		transition: none;
	}

	.fw-enzyme-game .fw-enzyme-game__start:hover {
		transform: none;
	}
}

/* ------------------------------------------------------------------
   Enzyme specialists: the middle text column and the hover list on the
   right of the three-column chapter. The middle column is ruled on both
   sides; one specialist grows on hover/focus while all stay readable.
   ------------------------------------------------------------------ */
.fw-enzyme-specialists__intro {
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: var(--fw-enzyme-pad);
	border-inline: 1px solid var(--fw-rule);
}

.fw-enzyme-specialists__intro > p:last-child {
	max-width: 46ch;
	margin: clamp(1.25rem, 2vw, 1.75rem) 0 0;
	padding-top: 1.2rem;
	border-top: 1px solid var(--fw-rule);
	color: var(--fw-ink);
	font-size: clamp(0.98rem, 1.08vw, 1.1rem);
	line-height: 1.65;
}

/* The list has no inline inset of its own: the rows carry it, so a hovered
   row's dark field runs right up to the middle column's rule and the rows
   run down to the island's bottom edge. It is a query container so the
   grown heading of an open row is measured against the list, not the
   viewport: at 4.2vw "Pektinasen" ran over its substrate label. */
.fw-enzyme-specialists__list {
	container-type: inline-size;
	position: relative;
	display: flex;
	flex-direction: column;
	min-width: 0;
	padding-top: clamp(2rem, 2.7vw, 3rem);
}

.fw-enzyme-specialists__list-label {
	margin: 0;
	padding: 0 var(--fw-enzyme-row-pad) 1.15rem;
	color: var(--fw-ink);
	font-size: 0.68rem;
	font-weight: 850;
	letter-spacing: 0.13em;
	text-transform: uppercase;
}

.fw-enzyme-specialists__list ul {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	min-height: 0;
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--fw-rule);
	list-style: none;
}

.fw-enzyme-specialists__list li {
	display: flex;
	flex: 1 1 0;
	flex-direction: column;
	justify-content: center;
	min-width: 0;
	min-height: 0;
	padding: clamp(1.25rem, 2vw, 2rem) var(--fw-enzyme-row-pad);
	overflow: hidden;
	color: var(--fw-ink);
	outline: 0;
	transition:
		flex-grow 0.48s var(--fw-ease),
		padding 0.48s var(--fw-ease),
		background-color 0.32s var(--fw-ease),
		color 0.32s var(--fw-ease);
}

.fw-enzyme-specialists__list li + li {
	border-top: 1px solid var(--fw-rule);
}

.fw-enzyme-specialists__item-heading {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: 1rem;
	align-items: baseline;
}

.fw-enzyme-specialists__item-heading h3 {
	margin: 0;
	color: var(--fw-heading);
	font-size: clamp(1.75rem, 2.7vw, 3rem);
	line-height: 0.98;
	letter-spacing: -0.04em;
	transition: color 0.32s var(--fw-ease), font-size 0.48s var(--fw-ease);
}

.fw-enzyme-specialists__item-heading span {
	color: var(--fw-green-700);
	font-size: 0.66rem;
	font-weight: 850;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	transition: color 0.32s var(--fw-ease);
}

.fw-enzyme-specialists__target,
.fw-enzyme-specialists__detail {
	margin: 0;
	color: inherit;
	transition:
		max-height 0.42s var(--fw-ease),
		margin 0.38s var(--fw-ease),
		opacity 0.26s var(--fw-ease),
		color 0.32s var(--fw-ease),
		visibility 0s linear 0.42s;
}

.fw-enzyme-specialists__target {
	max-height: 5rem;
	margin-top: 0.35rem;
	font-size: clamp(0.88rem, 1vw, 1rem);
	font-weight: 650;
	line-height: 1.4;
	opacity: 0.84;
}

.fw-enzyme-specialists__detail {
	max-width: 64ch;
	max-height: 0;
	overflow: hidden;
	font-size: clamp(0.96rem, 1.08vw, 1.08rem);
	line-height: 1.62;
	opacity: 0;
	visibility: hidden;
}

@media (min-width: 861px) {
	/* Continue the shared centre rule through the deliberately small breathing
	   space between chapters. The horizontal rules now meet one uninterrupted
	   vertical axis instead of leaving two floating line ends. */
	.fw-enzyme-specialists__list ul:has(li:hover) > li:not(:hover),
	.fw-enzyme-specialists__list ul:not(:has(li:hover)):has(li:focus) > li:not(:focus),
	.fw-enzyme-specialists__list ul:has(li.is-measuring) > li:not(.is-measuring) {
		flex-grow: 0.55;
	}

	/* .is-measuring is the same opened state, set for one synchronous layout
	   by main.js (fitOpenRows) to find the font scale (--fw-enzyme-fit) at
	   which each opened row fits; .is-fitting switches every transition off
	   meanwhile, so no frame of it is painted (owner, 2026-10-05: on smaller
	   screens the opened explanation ran out at the bottom). */
	.fw-enzyme-specialists__list ul.is-fitting,
	.fw-enzyme-specialists__list ul.is-fitting * {
		transition: none !important;
	}

	.fw-enzyme-specialists__list li:hover,
	.fw-enzyme-specialists__list ul:not(:has(li:hover)) li:focus,
	.fw-enzyme-specialists__list li.is-measuring {
		flex-grow: 4;
		justify-content: flex-start;
		padding-top: clamp(1.75rem, 2.8vw, 2.75rem);
		background: var(--fw-green-800);
		color: var(--fw-on-dark);
	}

	.fw-enzyme-specialists__list li:hover .fw-enzyme-specialists__item-heading h3,
	.fw-enzyme-specialists__list ul:not(:has(li:hover)) li:focus .fw-enzyme-specialists__item-heading h3,
	.fw-enzyme-specialists__list li.is-measuring .fw-enzyme-specialists__item-heading h3 {
		color: inherit;
		/* Measured against the list width (query container), so the grown
		   name always leaves room for the substrate label beside it. */
		font-size: calc(clamp(2.2rem, 12cqi, 3.8rem) * var(--fw-enzyme-fit, 1));
	}

	.fw-enzyme-specialists__list li:hover .fw-enzyme-specialists__item-heading span,
	.fw-enzyme-specialists__list ul:not(:has(li:hover)) li:focus .fw-enzyme-specialists__item-heading span,
	.fw-enzyme-specialists__list li.is-measuring .fw-enzyme-specialists__item-heading span {
		color: var(--fw-accent);
	}

	.fw-enzyme-specialists__list li:hover .fw-enzyme-specialists__target,
	.fw-enzyme-specialists__list ul:not(:has(li:hover)) li:focus .fw-enzyme-specialists__target,
	.fw-enzyme-specialists__list li.is-measuring .fw-enzyme-specialists__target {
		max-height: 6rem;
		color: inherit;
		font-size: calc(clamp(1rem, 1.18vw, 1.14rem) * var(--fw-enzyme-fit, 1));
		opacity: 0.9;
	}

	.fw-enzyme-specialists__list li:hover .fw-enzyme-specialists__detail,
	.fw-enzyme-specialists__list ul:not(:has(li:hover)) li:focus .fw-enzyme-specialists__detail,
	.fw-enzyme-specialists__list li.is-measuring .fw-enzyme-specialists__detail {
		max-height: 16rem;
		margin-top: clamp(1rem, 1.8vw, 1.5rem);
		color: inherit;
		font-size: calc(clamp(0.96rem, 1.08vw, 1.08rem) * var(--fw-enzyme-fit, 1));
		opacity: 0.9;
		visibility: visible;
		transition-delay: 0s;
	}

	.fw-enzyme-specialists__list ul:not(:has(li:hover)) li:focus-visible {
		box-shadow: inset 0 0 0 3px var(--fw-accent);
	}
}

/* Tablets: primer and specialist text keep their two columns, the list
   drops below them at full width (the landing page folds the same way). */
@media (max-width: 1100px) {
	.fw-enzyme-chapter {
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		min-height: 0;
	}

	.fw-enzyme-intro__lead h2,
	.fw-enzyme-specialists__intro h2 {
		font-size: clamp(2rem, 4.6cqi, 3.4rem);
	}

	.fw-enzyme-specialists__intro {
		border-right: 0;
	}

	.fw-enzyme-specialists__list {
		grid-column: 1 / -1;
		min-height: 30rem;
		padding-top: clamp(1.5rem, 2.5vw, 2rem);
		border-top: 1px solid var(--fw-rule);
	}
}

/* Phones: one column in reading order, every column divider becomes a
   horizontal rule that runs edge to edge, and all four explanations stay open. */
@media (max-width: 860px) {
	.fw-science-panel--enzyme-intro > .fw-container {
		--fw-enzyme-pad: clamp(1.5rem, 6vw, 2.5rem);
		--fw-enzyme-row-pad: clamp(1.5rem, 6vw, 2.5rem);
	}

	.fw-enzyme-chapter {
		grid-template-columns: minmax(0, 1fr);
	}

	.fw-enzyme-intro__lead {
		padding-top: clamp(2rem, 7vw, 3rem);
	}

	.fw-enzyme-intro__lead h2,
	.fw-enzyme-specialists__intro h2 {
		max-width: 15ch;
		font-size: clamp(2.2rem, 10cqi, 4rem);
	}

	.fw-enzyme-specialists__intro {
		border-inline: 0;
		border-top: 1px solid var(--fw-rule);
	}

	.fw-enzyme-specialists__list {
		min-height: 0;
		padding-top: clamp(1.5rem, 5vw, 2rem);
		border-top: 1px solid var(--fw-rule);
	}

	.fw-enzyme-specialists__list li {
		display: block;
		flex: none;
		padding-block: clamp(1.5rem, 4.5vw, 2.25rem);
		overflow: visible;
	}

	.fw-enzyme-specialists__detail {
		max-height: none;
		margin-top: 0.85rem;
		overflow: visible;
		opacity: 0.86;
		visibility: visible;
		transition-delay: 0s;
	}

}

@media (max-width: 600px) {
	.fw-enzyme-intro__lead h2,
	.fw-enzyme-specialists__intro h2 {
		font-size: clamp(2rem, 10cqi, 3rem);
	}

	.fw-enzyme-specialists__item-heading h3 {
		font-size: clamp(2rem, 9vw, 2.65rem);
	}

}

@media (prefers-reduced-motion: reduce) {
	.fw-enzyme-specialists__list li,
	.fw-enzyme-specialists__item-heading h3,
	.fw-enzyme-specialists__item-heading span,
	.fw-enzyme-specialists__target,
	.fw-enzyme-specialists__detail {
		transition: none;
	}
}

.fw-science-compare__heading,
.fw-science-mechanism__heading {
	margin-bottom: clamp(2.5rem, 5vw, 5rem);
}

.fw-science-compare__heading h2,
.fw-science-mechanism__heading h2 {
	max-width: 16ch;
	margin: 0;
	color: var(--fw-heading);
	font-size: clamp(2.75rem, 5.2vw, 5.75rem);
	line-height: 0.95;
	letter-spacing: -0.045em;
}

.fw-science-compare__heading > p:last-child,
.fw-science-mechanism__heading > p:last-child {
	max-width: 70ch;
	margin: clamp(1.5rem, 2.5vw, 2.25rem) 0 0;
	font-size: clamp(1.02rem, 1.3vw, 1.2rem);
}

/* The comparison header uses the mechanism's grid: kicker and heading on
   the left, the intro paragraph bottom-aligned on the right, so the island
   opens with the same composition as the dark chapter below it. */
.fw-science-compare__heading {
	display: grid;
	grid-template-columns: minmax(0, 0.9fr) minmax(24rem, 1.1fr);
	gap: 0.5rem clamp(2rem, 5vw, 6rem);
	align-items: end;
	margin-bottom: clamp(2rem, 3.5vw, 3.5rem);
}

.fw-science-compare__heading .fw-kicker,
.fw-science-compare__heading h2 {
	grid-column: 1;
}

.fw-science-compare__heading h2 {
	max-width: 12ch;
	font-size: clamp(2.6rem, 4.2vw, 4.6rem);
}

.fw-science-compare__heading > p:last-child {
	grid-column: 2;
	grid-row: 1 / span 2;
	align-self: end;
	max-width: 58ch;
	margin: 0;
	color: var(--fw-ink);
}

/* The comparison is deliberately asymmetric: Fruit Warrior is the
   protagonist and gets the wide, large-set column, while the conventional
   formulations sit in a narrow, quieter side column behind a hairline.
   Hierarchy comes from size and placement, never from lowered opacity —
   the side column must stay above the AA contrast threshold. */
.fw-science-compare {
	margin: 0;
	padding: 0;
	border-top: 1px solid var(--fw-rule);
	list-style: none;
}

.fw-science-compare__row {
	display: grid;
	grid-template-columns: minmax(0, 0.62fr) minmax(0, 1.55fr) minmax(0, 0.88fr);
	gap: clamp(1.5rem, 3vw, 3.25rem);
	align-items: start;
	padding-block: clamp(1.85rem, 3vw, 2.85rem);
	border-bottom: 1px solid var(--fw-rule);
}

.fw-science-compare__row > * {
	min-width: 0;
}

.fw-science-compare__criterion {
	margin: 0;
	color: var(--fw-ink);
	font-family: var(--fw-font-display);
	font-size: clamp(1.45rem, 2.1vw, 2rem);
	line-height: 1.05;
	letter-spacing: -0.03em;
}

.fw-science-compare__criterion span {
	display: block;
	margin-bottom: 0.6rem;
	color: var(--fw-green-600);
	font-family: var(--fw-font-body);
	font-size: 0.68rem;
	font-weight: 850;
	letter-spacing: 0.14em;
}

.fw-science-compare__ours h3,
.fw-science-compare__theirs h3 {
	margin: 0 0 0.6rem;
	font-family: var(--fw-font-body);
	font-size: 0.68rem;
	font-weight: 850;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.fw-science-compare__ours h3 {
	color: var(--fw-green-700);
}

.fw-science-compare__theirs h3 {
	color: var(--fw-grey);
}

.fw-science-compare__ours p {
	margin: 0;
	color: var(--fw-ink);
	font-size: clamp(1.05rem, 1.45vw, 1.32rem);
	line-height: 1.5;
}

.fw-science-compare__theirs {
	padding-left: clamp(1.25rem, 2.5vw, 2.15rem);
	border-left: 1px solid var(--fw-rule-soft);
}

.fw-science-compare__theirs p {
	margin: 0;
	color: var(--fw-grey);
	font-size: clamp(0.86rem, 1vw, 0.96rem);
	line-height: 1.55;
}

.fw-science-panel--mechanism > .fw-container {
	width: 100%;
	max-width: none;
	padding: clamp(2.5rem, 4.5vw, 4.5rem) clamp(1.25rem, 4vw, 4.5rem);
	border-radius: 0;
	background: var(--fw-ground);
	color: var(--fw-on-dark);
}

.fw-science-mechanism__inner {
	width: min(100%, 78rem);
	margin-inline: auto;
}

.fw-science-panel--mechanism .fw-science-mechanism__heading {
	display: grid;
	grid-template-columns: minmax(0, 0.9fr) minmax(24rem, 1.1fr);
	gap: 0.5rem clamp(2rem, 5vw, 6rem);
	align-items: end;
	margin-bottom: clamp(1.75rem, 3vw, 2.75rem);
}

.fw-science-panel--mechanism .fw-science-mechanism__heading .fw-kicker,
.fw-science-panel--mechanism .fw-science-mechanism__heading h2 {
	grid-column: 1;
}

.fw-science-panel--mechanism .fw-science-mechanism__heading .fw-kicker {
	color: var(--fw-accent);
}

.fw-science-panel--mechanism .fw-science-mechanism__heading h2 {
	max-width: 11ch;
	color: var(--fw-on-dark);
	font-size: clamp(2.8rem, 4.6vw, 5rem);
}

.fw-science-panel--mechanism .fw-science-mechanism__heading > p:last-child {
	grid-column: 2;
	grid-row: 1 / span 2;
	align-self: end;
	max-width: 58ch;
	margin: 0;
	color: var(--fw-on-dark);
}

/* ------------------------------------------------------------------
   Mechanism — the chain from ferment to rinsing water.
   The verb is the hero: what each agent does carries the explanation,
   so it is set at display size while the agent itself becomes a label.
   The rail on the left is a real progress line that grows with the
   scroll, replacing the horizontal bar nobody read as progress.
   ------------------------------------------------------------------ */
.fw-science-mechanism {
	position: relative;
	padding-left: clamp(1.5rem, 3vw, 2.75rem);
}

.fw-science-mechanism ol {
	margin: 0;
	padding: 0;
	list-style: none;
}

.fw-science-mechanism__rail {
	position: absolute;
	top: 0.35rem;
	bottom: 0.35rem;
	left: 0;
	width: 2px;
	background: color-mix(in srgb, var(--fw-on-dark) 22%, transparent);
}

.fw-science-mechanism__rail i {
	display: block;
	width: 100%;
	height: 100%;
	background: var(--fw-accent);
	transform-origin: top center;
}

/* Origin groups the chain: two steps come out of the barrel, one from
   the formulation, one only at the sink. */
.fw-science-mechanism__origin {
	position: relative;
	padding-block: clamp(1.15rem, 1.8vw, 1.75rem) 0.3rem;
}

.fw-science-mechanism__origin span {
	color: var(--fw-accent);
	font-size: 0.68rem;
	font-weight: 850;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.fw-science-mechanism__origin::before {
	content: '';
	position: absolute;
	top: calc(clamp(1.15rem, 1.8vw, 1.75rem) + 0.42rem);
	left: calc(clamp(1.5rem, 3vw, 2.75rem) * -1 - 3px);
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--fw-accent);
}

.fw-science-mechanism__step {
	display: grid;
	grid-template-columns: 3rem minmax(0, 1.65fr) minmax(0, 0.75fr);
	gap: clamp(1rem, 2.5vw, 2.5rem);
	align-items: start;
	padding-block: clamp(1rem, 1.4vw, 1.35rem);
	border-bottom: 1px solid color-mix(in srgb, var(--fw-on-dark) 20%, transparent);
}

.fw-science-mechanism__step > * {
	min-width: 0;
}

.fw-science-mechanism__index {
	margin: 0;
	padding-top: 0.5rem;
	color: color-mix(in srgb, var(--fw-on-dark) 62%, transparent);
	font-size: 0.7rem;
	font-weight: 850;
	letter-spacing: 0.12em;
}

.fw-science-mechanism__body h3 {
	margin: 0;
	color: var(--fw-on-dark);
	font-size: clamp(2rem, 3vw, 3.1rem);
	line-height: 0.98;
	letter-spacing: -0.035em;
}

.fw-science-mechanism__agent {
	margin: 0.5rem 0 0;
	color: var(--fw-accent);
	font-size: 0.72rem;
	font-weight: 850;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.fw-science-mechanism__detail {
	max-width: 58ch;
	margin: 0.85rem 0 0;
	color: color-mix(in srgb, var(--fw-on-dark) 84%, transparent);
	font-size: clamp(0.96rem, 1.15vw, 1.08rem);
	line-height: 1.55;
}

.fw-science-mechanism__outcome {
	justify-self: end;
	margin: 0;
	padding-top: 0.6rem;
	text-align: right;
}

/* A chip that wraps used to keep the full column width while its two lines
   sat right-aligned inside it, so the pill looked far wider than its text.
   Capping the width just above the longest single word and balancing the
   lines lets the pill hug what it says; centred text hides the remaining
   slack as even padding. */
.fw-science-mechanism__outcome span {
	display: inline-block;
	max-width: min(100%, 30ch);
	padding: 0.5rem 0.85rem;
	border: 1px solid rgba(239, 237, 228, 0.16);
	border-radius: 999px;
	background: rgba(239, 237, 228, 0.07);
	color: var(--fw-on-dark);
	font-size: 0.72rem;
	font-weight: 850;
	line-height: 1.35;
	letter-spacing: 0.04em;
	text-align: center;
	text-wrap: balance;
}

/* Collapsible questions on the two dark chapters (scent in the mechanism,
   alcohol under the ferment) share one appearance. */
.fw-science-panel--mechanism .fw-science-scent,
.fw-science-panel--fermentation .fw-science-scent {
	margin-top: clamp(1.5rem, 3vw, 2.5rem);
	border: 1px solid color-mix(in srgb, var(--fw-on-dark) 30%, transparent);
	border-radius: 1.25rem;
	background: color-mix(in srgb, var(--fw-on-dark) 7%, transparent);
	color: var(--fw-on-dark);
}

.fw-science-panel--mechanism .fw-science-scent summary,
.fw-science-panel--fermentation .fw-science-scent summary {
	padding: clamp(1.3rem, 2.5vw, 2rem) clamp(3.5rem, 5vw, 5rem) clamp(1.3rem, 2.5vw, 2rem) clamp(1.5rem, 3vw, 2.5rem);
	color: inherit;
	font-size: clamp(1.15rem, 1.9vw, 1.6rem);
}

.fw-science-panel--mechanism .fw-science-scent summary::after,
.fw-science-panel--fermentation .fw-science-scent summary::after {
	right: clamp(1.5rem, 3vw, 2.5rem);
	color: var(--fw-yellow-500);
}

.fw-science-panel--mechanism .fw-science-scent p,
.fw-science-panel--fermentation .fw-science-scent p {
	max-width: 76ch;
	padding: 0 clamp(1.5rem, 3vw, 2.5rem) clamp(1.5rem, 3vw, 2.5rem);
	font-size: 1rem;
	line-height: 1.6;
	color: color-mix(in srgb, var(--fw-on-dark) 84%, transparent);
}

/* ------------------------------------------------------------------
   SCOBY — one material, two states.
   The first chapter balances one concise premise against the process photo;
   its three facts then use the complete width. The cropped portrait below
   keeps the bag and the reuse copy close enough to read as one transformation.
   ------------------------------------------------------------------ */
.fw-science-panel--scoby > .fw-container {
	padding: clamp(2.25rem, 4vw, 4.5rem);
}

.fw-scoby__chapter {
	display: grid;
	width: 100%;
	max-width: 96rem;
	margin-inline: auto;
	grid-template-columns: minmax(0, 0.88fr) minmax(20rem, 1.12fr);
	column-gap: clamp(2rem, 4vw, 5rem);
	row-gap: clamp(1.5rem, 2.5vw, 2.5rem);
	align-items: center;
}

/* No rule of its own: the facts row above already closes with a hairline,
   and a second one directly beneath it read as a double underline. */
.fw-scoby__chapter--material {
	grid-template-columns: minmax(20rem, 0.82fr) minmax(0, 1.18fr);
	margin-top: clamp(2.5rem, 4vw, 4.5rem);
}

.fw-scoby__chapter > * {
	min-width: 0;
}

.fw-scoby__copy h2,
.fw-scoby__copy h3 {
	max-width: 12ch;
	margin: 0;
	color: var(--fw-heading);
	font-size: clamp(2.8rem, 4.3vw, 4.8rem);
	line-height: 0.98;
	letter-spacing: -0.055em;
}

.fw-scoby__copy h3 {
	max-width: 13ch;
	font-size: clamp(2.6rem, 4vw, 4.35rem);
}

.fw-scoby__copy > p:not(.fw-kicker) {
	max-width: 56ch;
	margin: 1rem 0 0;
	color: var(--fw-ink);
	line-height: 1.65;
}

.fw-scoby__copy .fw-scoby__lead {
	margin-top: clamp(1.25rem, 2.2vw, 2rem);
	font-size: clamp(1.06rem, 1.3vw, 1.2rem);
}

/* The material chapter has two paragraphs at lead size (owner, 2026-10-05:
   the second one read smaller); only the first takes the lead's gap. */
.fw-scoby__copy .fw-scoby__lead + .fw-scoby__lead {
	margin-top: 1rem;
}

.fw-scoby__facts {
	display: grid;
	grid-column: 1 / -1;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	margin: clamp(0.25rem, 1vw, 0.75rem) 0 0;
	border-block: 1px solid var(--fw-rule-soft);
}

.fw-scoby__facts > div {
	padding: clamp(1.15rem, 2vw, 1.65rem) clamp(1rem, 2.5vw, 2.25rem);
}

.fw-scoby__facts > div:first-child {
	padding-left: 0;
}

.fw-scoby__facts > div + div {
	border-left: 1px solid var(--fw-rule-soft);
}

.fw-scoby__facts dt {
	color: var(--fw-green-700);
	font-size: 0.68rem;
	font-weight: 850;
	letter-spacing: 0.13em;
	text-transform: uppercase;
}

.fw-scoby__facts dd {
	margin: 0.55rem 0 0;
	color: var(--fw-ink);
	font-size: 0.96rem;
	line-height: 1.55;
}

.fw-scoby__media {
	margin: 0;
}

.fw-scoby__media img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: clamp(0.9rem, 1.5vw, 1.4rem);
}

.fw-scoby__media--pellicle img {
	aspect-ratio: 3 / 2;
	object-fit: cover;
}

.fw-scoby__media--bag img {
	width: min(100%, 32rem);
	aspect-ratio: 4 / 5;
	margin-inline: auto;
	object-fit: cover;
	object-position: center top;
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	/* The comparison stays deliberately still — no hover, no motion. */
	.fw-science-mechanism__step {
		transition: background-color 0.35s var(--fw-ease);
	}

	.fw-science-mechanism__step:hover {
		background: color-mix(in srgb, var(--fw-on-dark) 6%, transparent);
	}
}

@media (max-width: 1100px) {
	.fw-science-hero__inner {
		grid-template-columns: minmax(25rem, 0.92fr) minmax(24rem, 1.08fr);
		gap: clamp(2rem, 3.5vw, 4rem);
	}

	.fw-science-mechanism__step {
		grid-template-columns: 2.75rem minmax(0, 1.5fr) minmax(0, 0.8fr);
		gap: 1.25rem;
	}

	.fw-ferment {
		grid-template-columns: minmax(0, 1fr);
		gap: clamp(1.5rem, 3vw, 2.25rem);
	}

	.fw-ferment__media {
		min-height: 24rem;
	}

	/* Single column inside the pin: the photo takes a fixed share of the
	   viewport and the copy follows directly beneath it, with the whole
	   block centred. Stretching the grid to full height here would push
	   the counter away from the photo and break the connection. */
	.fw-ferment__stage.is-pinned .fw-ferment {
		height: auto;
		gap: clamp(1rem, 2.5vh, 1.75rem);
	}

	.fw-ferment__stage.is-pinned .fw-ferment__media {
		height: auto;
		min-height: 0;
		max-height: 19svh;
		aspect-ratio: 16 / 10;
	}

	/* Compact slats on narrow screens. The card padding that gives the
	   desktop drum its air makes the slats too tall to pin here, and
	   losing the pin costs far more than a few pixels of inset. */
	.fw-ferment__reel article {
		gap: 0.8rem;
		padding: 1rem 1.15rem;
	}

	.fw-ferment__reel-step {
		font-size: 1.65rem;
	}

	.fw-ferment__reel-body h3 {
		margin-bottom: 0.3rem;
		font-size: 1.08rem;
	}

	.fw-ferment__reel-body p {
		font-size: 0.87rem;
		line-height: 1.45;
	}

	.fw-ferment__stage.is-pinned .fw-ferment__copy {
		align-self: start;
	}

	/* Two columns: the criterion spans the row, our claim and the
	   conventional one sit side by side beneath it. */
	.fw-science-compare__row {
		grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.9fr);
		gap: clamp(1rem, 2.5vw, 1.85rem);
	}

	.fw-science-compare__criterion {
		grid-column: 1 / -1;
	}
}

@media (max-width: 860px) {
	.fw-science-hero__inner {
		width: min(calc(100% - 2.5rem), 46rem);
		grid-template-columns: 1fr;
		gap: 1.5rem;
		padding-bottom: 2.5rem;
	}

	.fw-science-hero__title {
		max-width: 11.5ch;
	}

	.fw-science-hero__visual {
		min-height: 31rem;
	}

	.fw-science-hero__visual img {
		width: min(90%, 35rem);
		max-height: 38rem;
	}

	.fw-ferment__media {
		min-height: 17rem;
	}


	.fw-science-panel--mechanism .fw-science-mechanism__heading,
	.fw-science-compare__heading {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.25rem;
	}

	.fw-science-panel--mechanism .fw-science-mechanism__heading > p:last-child,
	.fw-science-compare__heading > p:last-child {
		grid-column: 1;
		grid-row: auto;
	}

	/* One column: criterion, then our claim, then the conventional one as an
	   indented footnote rather than an equally weighted block. */
	.fw-science-compare__row {
		grid-template-columns: minmax(0, 1fr);
		gap: 1.1rem;
		padding-block: 1.6rem;
	}

	.fw-science-compare__criterion {
		grid-column: auto;
	}

	.fw-science-compare__theirs {
		padding-left: 1.1rem;
		border-left: 2px solid var(--fw-rule-soft);
	}

	/* The outcome chip drops below the copy rather than competing with it
	   for width. */
	.fw-science-mechanism__step {
		grid-template-columns: 2.5rem minmax(0, 1fr);
		gap: 0.85rem 1.25rem;
	}

	.fw-science-mechanism__outcome {
		grid-column: 2;
		justify-self: start;
		padding-top: 0;
		text-align: left;
	}

	.fw-scoby__chapter,
	.fw-scoby__chapter--material {
		grid-template-columns: minmax(0, 1fr);
		gap: 2rem;
	}

	.fw-scoby__chapter--material {
		margin-top: 2.75rem;
	}

	.fw-scoby__media--pellicle {
		margin-top: 0.25rem;
	}

	.fw-scoby__facts {
		grid-template-columns: minmax(0, 1fr);
		margin-top: 0.5rem;
	}

	.fw-scoby__facts > div {
		padding: 0.95rem 0;
	}

	.fw-scoby__facts > div + div {
		border-top: 1px solid var(--fw-rule-soft);
		border-left: 0;
	}

	.fw-scoby__media--bag img {
		width: min(92%, 31rem);
	}
}

/* Small phones: the copy pin only fits with a slightly tighter drum. Measured
   with the real fonts, a 360×640 viewport has about 560px for the copy. */
@media (max-width: 400px) {
	.fw-ferment__reel article {
		padding: 0.85rem 1rem;
	}

	.fw-ferment__reel-body p {
		font-size: 0.82rem;
		line-height: 1.4;
	}

	.fw-ferment__stage.is-copy-pinned .fw-ferment__clock {
		margin-top: 1rem;
	}
}

@media (max-width: 600px) {
	.fw-science-hero__inner {
		width: calc(100% - 2rem);
		padding-top: 2.5rem;
	}

	.fw-science-hero__title {
		max-width: none;
		font-size: clamp(2.8rem, 13vw, 4.3rem);
		line-height: 0.94;
	}

	.fw-science-hero__intro {
		font-size: 1rem;
	}

	.fw-science-hero__visual {
		min-height: 24rem;
	}

	.fw-science-hero__visual img {
		width: min(100%, 27rem);
	}

	.fw-science-panel--compare > .fw-container,
	.fw-science-panel--mechanism > .fw-container,
	.fw-science-panel--scoby > .fw-container {
		padding: 2rem 1.5rem;
	}

	.fw-science-compare__heading h2,
	.fw-science-mechanism__heading h2,
	.fw-scoby__copy h2,
	.fw-scoby__copy h3 {
		font-size: clamp(2.4rem, 11vw, 3.45rem);
	}

	.fw-science-panel--mechanism .fw-science-mechanism__heading h2 {
		font-size: clamp(2.4rem, 11vw, 3.45rem);
	}

	.fw-science-mechanism {
		padding-left: 1.15rem;
	}

	.fw-science-mechanism__step {
		grid-template-columns: 2.1rem minmax(0, 1fr);
		gap: 0.55rem 0.85rem;
		padding-block: 1.5rem;
	}

	.fw-science-mechanism__index {
		padding-top: 0.35rem;
	}

	.fw-science-mechanism__origin::before {
		left: calc(1.15rem * -1 - 3px);
	}

	.fw-science-panel--mechanism .fw-science-scent summary,
	.fw-science-panel--fermentation .fw-science-scent summary {
		font-size: 1.1rem;
	}
}

/* == 12 Utilities & motion ============================================ */

.fw-center {
	text-align: center;
}



.fw-actions-center {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem;
	justify-content: center;
	margin-top: clamp(2rem, 5vw, 3rem);
}

/* Elements revealed on scroll keep full opacity without JS;
   animations.js sets the initial states. */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* Astra's scroll-to-top button, re-branded */
#ast-scroll-top {
	background-color: var(--fw-green-700) !important;
	color: var(--fw-on-dark) !important;
	border-radius: 50% !important;
}

/* Keep Astra's floating arrow out of the open menu, including keyboard focus. */
body:has(.fw-mobile-nav:not([hidden])) #ast-scroll-top {
	opacity: 0 !important;
	visibility: hidden !important;
	pointer-events: none !important;
}

/* == Responsive ======================================================== */

@media (max-width: 1024px) {
	.fw-grid--4 {
		grid-template-columns: repeat(2, 1fr);
	}

	.fw-process {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 860px) {
	.fw-nav {
		display: none;
	}

	/* The bar keeps logo, icons and burger; the switcher sits in the menu. */
	.fw-lang--header {
		display: none;
	}

	.fw-nav-toggle {
		display: block;
	}

	/* The centre track carried the nav, which is gone here. Three items
	   remain — logo, actions, burger — and the burger sits hard right, after
	   the icons (owner, 2026-09-24). It is last in the DOM as well, so the
	   tab order matches what is on screen; on desktop it is hidden and takes
	   no grid track. The negative margin lines its bars up with the gutter. */
	.fw-header__inner {
		grid-template-columns: 1fr auto auto;
	}

	.fw-header__inner > .fw-nav-toggle {
		margin-right: -0.5rem;
	}

	/* The lockup keeps the desktop proportion to the bar (owner, 2026-09-25):
	   3.5 of 4.5 rem, i.e. 78 % of the header height, where it used to step
	   down to 56–62 % and left visible room above and below. Only the gap
	   inside the lockup tightens a little. */
	.fw-logo--header {
		--fw-logo-h: 3.5rem;
		gap: 0.55rem;
	}

	.fw-grid--3 {
		grid-template-columns: repeat(2, 1fr);
	}

	.fw-grid--2 {
		grid-template-columns: 1fr;
	}

	.fw-split {
		grid-template-columns: 1fr;
	}

	

	.fw-cta-banner__inner {
		grid-template-columns: 1fr;
	}

	.fw-cta-banner__actions {
		justify-content: flex-start;
	}

	.fw-contact-grid {
		grid-template-columns: minmax(0, 1fr);
	}

	.fw-footer__newsletter {
		grid-template-columns: 1fr;
	}

	.fw-footer__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.fw-footer__bottom {
		grid-template-columns: minmax(0, 1fr) auto;
	}

	.fw-footer__claim {
		grid-column: 1 / -1;
		grid-row: 1;
	}

	.fw-footer__identity {
		grid-column: 1;
		grid-row: 2;
	}

	.fw-footer__payments {
		grid-column: 2;
		grid-row: 2;
	}
}

@media (max-width: 600px) {
	.fw-grid--3,
.fw-grid--4,
.fw-process {
		grid-template-columns: 1fr;
	}

	/* Lockup + three icon buttons + burger have to survive a 360 px viewport:
	   at 3.5rem there are still ~48 px to spare there. */
	.fw-logo--header {
		gap: 0.5rem;
	}

	/* Below that the spare room would drop under 10 px, so one small step. */
	@media (max-width: 359px) {
		.fw-logo--header {
			--fw-logo-h: 3.1rem;
			gap: 0.4rem;
		}
	}

	.fw-header__inner {
		gap: 0.75rem;
	}

	.fw-footer__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1.5rem 1rem;
	}

	.fw-footer__bottom {
		grid-template-columns: 1fr;
		justify-items: center;
		text-align: center;
	}

	.fw-footer__claim,
	.fw-footer__identity,
	.fw-footer__payments {
		grid-column: 1;
		justify-self: center;
	}

	.fw-footer__claim {
		grid-row: 1;
	}

	.fw-footer__identity {
		grid-row: 2;
	}

	.fw-footer__payments {
		grid-row: 3;
	}

	.fw-stage__arrow {
		width: 2.5rem;
		height: 2.5rem;
	}

	
}

/* Newsroom: a lit stage on the green ground. Large 3:2 photographs swing
   through a shared 3D camera; newsroom.js owns every per-frame transform. */
.fw-newsroom {
	--fw-news-inset: clamp(1.25rem, 4vw, 4.5rem);
	--fw-news-gap: clamp(3rem, 6vw, 6.5rem);
	--fw-news-photo-w: min(54vw, 60rem);
	--fw-news-text-w: clamp(20rem, 28vw, 28rem);
	--fw-news-col-gap: clamp(2rem, 3.6vw, 4rem);
	--fw-news-pad: clamp(2.5rem, 5vw, 4.5rem);
	position: relative;
	isolation: isolate;
	min-width: 0;
	overflow-x: clip;
	padding-block: clamp(1.5rem, 3vw, 3rem) clamp(1rem, 2vw, 2rem);
	background: transparent;
	color: var(--fw-on-dark);
}
.fw-newsroom__header {
	display: flex;
	align-items: center;
	gap: 1.5rem;
	margin: 0 var(--fw-news-inset) clamp(-1.5rem, -1vw, -.5rem);
}
.fw-newsroom__header::after {
	content: '';
	height: 1px;
	flex: 1;
	background: color-mix(in srgb, var(--fw-on-dark) 22%, transparent);
}
.fw-newsroom .fw-newsroom__header h2 {
	margin: 0;
	color: var(--fw-accent);
	font-size: clamp(1.75rem, 2.5vw, 2.5rem);
	font-weight: 800;
	letter-spacing: -.045em;
	line-height: 1;
}
.fw-newsroom__stage { position: relative; }
/* The stage light: a soft pool of brighter green behind the reading position.
   It fades out well inside the stage so no edge ever shows against the ground. */
.fw-newsroom__stage::before {
	content: '';
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background: radial-gradient(42% 52% at 34% 48%, color-mix(in srgb, var(--fw-green-500) 42%, transparent), transparent 70%);
}
.fw-newsroom__rail {
	overflow-x: auto;
	overflow-y: hidden;
	padding-block: var(--fw-news-pad);
	overscroll-behavior-x: contain;
	scrollbar-color: var(--fw-accent) transparent;
}
.fw-newsroom.is-enhanced .fw-newsroom__rail {
	/* Clip sideways only: shadows and glows must fade out below the photos, not end at a cut. */
	overflow-x: clip;
	overflow-y: visible;
	touch-action: pan-y pinch-zoom;
	overflow-anchor: none;
}
/* Flat strip (owner, 2026-10-16): the cards used to recede and turn in a
   shared 3D scene (perspective on the rail, preserve-3d below it), and on
   real GPUs dark stripes flashed on the photos of cards coming in from the
   right. A per-card perspective did not cure it; flat cards did. */
.fw-newsroom__track,
.fw-newsroom__group {
	display: flex;
	align-items: stretch;
	width: max-content;
}
/* One stable GPU layer per card: nothing is promoted or demoted while the
   strip moves, which would re-raster and hitch. */
.fw-newsroom.is-enhanced .fw-news-card { will-change: transform; }
/* Only the content takes pointer events; events still bubble to the rail
   for dragging. Introduced for the former 3D scene, where a receding card
   sat behind the transparent planes of card, group and track and they took
   its clicks; kept as a guard. */
.fw-newsroom.is-enhanced :is(.fw-newsroom__track, .fw-newsroom__group, .fw-news-card) { pointer-events: none; }
.fw-newsroom.is-enhanced .fw-news-card__layout { pointer-events: auto; }
.fw-newsroom__group {
	position: relative;
	gap: var(--fw-news-gap);
	padding-right: var(--fw-news-gap);
}
.fw-newsroom:not(.is-enhanced) .fw-newsroom__track { padding-left: var(--fw-news-inset); }
.fw-news-card {
	position: relative;
	flex: 0 0 auto;
	width: calc(var(--fw-news-photo-w) + var(--fw-news-col-gap) + var(--fw-news-text-w));
	background: transparent;
	color: var(--fw-on-dark);
}
.fw-news-card__layout {
	display: grid;
	grid-template-columns: var(--fw-news-photo-w) var(--fw-news-text-w);
	align-items: start;
	gap: var(--fw-news-col-gap);
	height: 100%;
	color: inherit;
	text-decoration: none;
}
.fw-news-card__media {
	position: relative;
	display: block;
	aspect-ratio: 3 / 2;
	min-width: 0;
}
/* Ambient light: a small, blurred copy scaled up by the compositor. Blurring
   at a quarter of the size keeps the filter cheap while the strip moves. */
.fw-news-card__glow {
	position: absolute;
	left: 37.5%;
	top: 52%;
	width: 25%;
	height: 25%;
	opacity: .42;
	filter: blur(9px) saturate(1.6);
	transform: scale(3.9);
	pointer-events: none;
}
.fw-news-card__glow img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
.fw-news-card__frame {
	position: absolute;
	inset: 0;
	display: block;
	overflow: hidden;
	border-radius: 6px;
	background: color-mix(in srgb, var(--fw-ground) 70%, #000);
	box-shadow:
		0 1px 2px rgba(14, 22, 6, .28),
		0 18px 36px -14px rgba(14, 22, 6, .5),
		0 50px 90px -40px rgba(14, 22, 6, .55);
}
/* Shade that deepens as a card leaves the reading position (set by JS). */
.fw-news-card__frame::after {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--fw-ground);
	opacity: var(--fw-news-shade, 0);
	pointer-events: none;
}
.fw-news-card__photo {
	position: absolute;
	top: 0;
	left: -7%;
	display: block;
	width: 114%;
	max-width: none;
	height: 100%;
	object-fit: cover;
}
.fw-news-card--illustration .fw-news-card__frame {
	background: transparent;
	box-shadow: none;
}
.fw-news-card--illustration .fw-news-card__photo { left: 0; width: 100%; object-fit: contain; }
.fw-news-card__body {
	align-self: center;
	min-width: 0;
	padding-block: .5rem;
}
.fw-news-card .fw-news-card__body h3 {
	margin: 0 0 1.1rem;
	color: var(--fw-on-dark);
	font-size: clamp(1.9rem, 3vw, 3.1rem);
	font-weight: 800;
	line-height: .98;
	letter-spacing: -.04em;
	text-transform: uppercase;
	overflow-wrap: break-word;
	hyphens: auto;
	text-wrap: balance;
}
.fw-news-card__body p {
	max-width: 40ch;
	margin: 0;
	color: color-mix(in srgb, var(--fw-on-dark) 88%, transparent);
	font-size: clamp(1rem, 1.25vw, 1.25rem);
	line-height: 1.55;
}
.fw-news-card__cta {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	margin-top: 1.5rem;
	color: var(--fw-accent);
	font-weight: 700;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .35em;
	transition: gap .3s var(--fw-ease);
}
.fw-news-card__cta svg { flex: 0 0 auto; }
/* Every news CTA is its own link; the cards themselves are not links
   (owner, 2026-09-30). It keeps its colour, since Astra's link hover turned
   it green on the green ground, and only the arrow moves. */
a.fw-news-card__cta:is(:hover, :focus, :active) { color: var(--fw-accent); }
a.fw-news-card__cta:hover { gap: .9rem; }
.fw-newsroom :focus-visible {
	outline: 2px solid var(--fw-accent);
	outline-offset: 4px;
}
/* After a click or tap (newsroom.js): no ring until the next key press. */
.fw-newsroom.is-pointer :focus-visible {
	outline: none;
}
.fw-newsroom.is-dragging,
.fw-newsroom.is-dragging a { user-select: none; cursor: grabbing; }

/* Arrows: only while the pointer is over the newsroom or focus is inside it.
   They sit on the photo's vertical centre and straddle the strip's edges. */
.fw-newsroom .fw-newsroom__arrow {
	position: absolute;
	top: calc(var(--fw-news-pad) + var(--fw-news-photo-w) / 3);
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 3.5rem;
	height: 3.5rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: var(--fw-on-dark);
	color: var(--fw-ground);
	box-shadow: 0 12px 30px -10px rgba(14, 22, 6, .6);
	cursor: pointer;
	opacity: 0;
	pointer-events: none;
	transform: translate(var(--fw-arrow-shift, 0), -50%) scale(.82);
	transition: opacity .3s var(--fw-ease), transform .45s var(--fw-ease), background-color .2s, color .2s;
}
.fw-newsroom .fw-newsroom__arrow[hidden] { display: none; }
.fw-newsroom .fw-newsroom__arrow--prev { left: max(.5rem, var(--fw-news-inset) - 1.75rem); --fw-arrow-shift: -.75rem; }
.fw-newsroom .fw-newsroom__arrow--next { right: max(.5rem, var(--fw-news-inset) - 1.75rem); --fw-arrow-shift: .75rem; }
.fw-newsroom:is(:hover, :has(:focus-visible)) .fw-newsroom__arrow {
	opacity: 1;
	pointer-events: auto;
	transform: translate(0, -50%) scale(1);
}
.fw-newsroom .fw-newsroom__arrow:is(:hover, :focus-visible) {
	background: var(--fw-accent);
	color: var(--fw-ground);
	outline-offset: 3px;
}
.fw-newsroom .fw-newsroom__arrow:active { transform: translate(0, -50%) scale(.94); }

/* Scrollbar: a hairline that surfaces with the arrows. */
.fw-newsroom__scrubber {
	margin: clamp(-2rem, -2vw, -1rem) var(--fw-news-inset) 0;
	opacity: 0;
	transition: opacity .35s var(--fw-ease);
}
.fw-newsroom:is(:hover, :has(:focus-visible)) .fw-newsroom__scrubber { opacity: 1; }
.fw-newsroom .fw-newsroom__scrollbar {
	--fw-news-track: 2px;
	appearance: none;
	-webkit-appearance: none;
	display: block;
	width: 100%;
	height: 24px;
	padding: 0;
	margin: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
	cursor: ew-resize;
	box-shadow: none;
	touch-action: pan-y;
}
.fw-newsroom .fw-newsroom__scrollbar:is(:hover, :active, :focus-visible) { --fw-news-track: 4px; }
.fw-newsroom .fw-newsroom__scrollbar:focus-visible { outline-offset: 0; }
.fw-newsroom .fw-newsroom__scrollbar::-webkit-slider-runnable-track {
	height: var(--fw-news-track);
	border-radius: 2px;
	box-shadow: none;
	background: color-mix(in srgb, var(--fw-on-dark) 16%, transparent);
	transition: height .2s;
}
.fw-newsroom .fw-newsroom__scrollbar::-webkit-slider-thumb {
	appearance: none;
	-webkit-appearance: none;
	width: var(--fw-news-thumb, 18%);
	height: var(--fw-news-track);
	margin-top: 0;
	border: 0;
	border-radius: 2px;
	background: var(--fw-accent);
	box-shadow: none;
}
.fw-newsroom .fw-newsroom__scrollbar::-moz-range-track {
	height: var(--fw-news-track);
	border-radius: 2px;
	background: color-mix(in srgb, var(--fw-on-dark) 16%, transparent);
}
.fw-newsroom .fw-newsroom__scrollbar::-moz-range-thumb {
	width: var(--fw-news-thumb, 18%);
	height: var(--fw-news-track);
	border: 0;
	border-radius: 2px;
	background: var(--fw-accent);
}
/* Touch screens cannot hover: arrows give way to swiping, the bar stays faint. */
@media (hover: none) {
	.fw-newsroom .fw-newsroom__arrow { display: none; }
	.fw-newsroom__scrubber { opacity: .55; }
}

/* Below laptop width the text moves under the photograph. */
@media (max-width: 1023px) {
	.fw-newsroom {
		--fw-news-photo-w: min(84vw, 44rem);
		--fw-news-gap: clamp(1.5rem, 5vw, 3rem);
		--fw-news-pad: clamp(1.75rem, 5vw, 3rem);
	}
	.fw-news-card { width: var(--fw-news-photo-w); }
	.fw-news-card__layout { grid-template-columns: 1fr; gap: clamp(1.25rem, 3vw, 2rem); }
	.fw-news-card__body { align-self: start; padding-block: 0; }
	.fw-news-card .fw-news-card__body h3 { font-size: clamp(1.6rem, 5.4vw, 2.6rem); margin-bottom: .85rem; }
	.fw-news-card__body p { font-size: clamp(.95rem, 2.4vw, 1.1rem); }
	.fw-news-card__cta { margin-top: 1.1rem; }
}
/* Phones: the next news peeks in clearly at the right edge, so it is obvious
   there is more to swipe to (owner, 2026-09-25: the former 1.5rem showed only
   a sliver once the drum pushed the neighbour outwards). */
@media (max-width: 700px) {
	.fw-newsroom {
		--fw-news-photo-w: calc(100vw - 2 * var(--fw-news-inset) - 3.75rem);
		--fw-news-gap: 1rem;
	}
	.fw-news-card__glow { opacity: .5; }
}

/* Newsroom set picker (inc/sets.php): the four set photographs share one
   frame and cross-fade; the choices and the offer sit in the text column. */
.fw-news-sets__photos .fw-news-sets__photo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity .55s var(--fw-ease);
}
.fw-news-sets__photos .fw-news-sets__photo.is-active { opacity: 1; }
.fw-news-card--sets .fw-news-card__photo { display: block; }
.fw-news-sets {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: .5rem;
	margin: 1.25rem 0 1.1rem;
}
.fw-newsroom .fw-news-sets__choice,
.fw-newsroom .fw-news-sets__choice:is(:hover, :focus, :active) {
	padding: .6rem .85rem;
	border: 1px solid color-mix(in srgb, var(--fw-on-dark) 38%, transparent);
	border-radius: 999px;
	background: transparent;
	box-shadow: none;
	color: var(--fw-on-dark);
	font: 700 .95rem/1.2 var(--fw-font-body);
	text-align: center;
	cursor: pointer;
	transition: background-color .25s, border-color .25s, color .25s;
}
.fw-newsroom .fw-news-sets__choice:hover { border-color: var(--fw-on-dark); }
.fw-newsroom .fw-news-sets__choice[aria-pressed="true"] {
	border-color: var(--fw-accent);
	background: var(--fw-accent);
	color: var(--fw-ground);
}
.fw-news-sets__panel p { margin: 0; }
.fw-news-card .fw-news-sets__name {
	color: var(--fw-on-dark);
	font: 800 clamp(1.1rem, 1.4vw, 1.3rem)/1.2 var(--fw-font-display);
	letter-spacing: -.02em;
}
.fw-news-card .fw-news-sets__deal {
	margin-top: .25rem;
	font-size: clamp(.95rem, 1.1vw, 1.05rem);
}
.fw-news-card .fw-news-sets__price { margin-top: .55rem; }
.fw-news-sets__price strong {
	color: var(--fw-on-dark);
	font: 800 clamp(1.4rem, 1.9vw, 1.8rem)/1 var(--fw-font-display);
}
.fw-news-sets__price span {
	margin-left: .35rem;
	color: color-mix(in srgb, var(--fw-on-dark) 75%, transparent);
	font-size: .85rem;
}
.fw-news-sets__panel .fw-news-card__cta { margin-top: 1rem; }
/* „statt einzeln ~~29,96 €~~“ after the set price (inc/sets.php fw_set_was_html()). */
.fw-news-sets__price .fw-set-was,
.fw-news-sets__price .fw-set-was span {
	margin-left: 0;
	font-size: 1rem;
}
.fw-news-sets__price .fw-set-was { margin-left: .4rem; }
.fw-news-sets__price .fw-set-was .fw-set-was__label { font-size: .85rem; }
/* With the comparison beside the price, the tax note gets a line of its own. */
.fw-news-sets__price > span:last-child { display: block; margin: .35rem 0 0; }
/* Without JavaScript the choices cannot switch: show the first offer and a link to all sets. */
.fw-news-sets__all {
	display: inline-block;
	margin-top: .75rem;
	color: var(--fw-on-dark);
}
.fw-newsroom.is-enhanced .fw-news-sets__all,
.fw-newsroom:not(.is-enhanced) .fw-news-sets { display: none; }

/* Keep the established bottle size while the source canvas gives shadows room.
   The 1920x1728 master contains the same 1472px bottle as the old 1200x1600 frame. */
.fw-stage__image-frame {
  position: relative;
  display: block;
  width: min(100%, 26.25rem, calc(min(33rem, 64vh) * .75));
  aspect-ratio: 3 / 4;
}
.fw-stage__image-frame .fw-stage__img {
  position: absolute;
  left: -30%;
  top: -7%;
  width: 160%;
  height: 108%;
  max-width: none;
  object-fit: contain;
}
.fw-line__bottle img {
  position: absolute;
  left: -30%;
  top: -4%;
  width: 160%;
  height: 108%;
  max-width: none;
}
@media (max-width: 767px) {
  .fw-stage__image-frame {
    width: min(100%, 22rem, calc(clamp(20rem, 55vw, 22rem) * .75));
  }
}

/* Hit targets exclude transparent margins and supplied shadows. */
.fw-line__bottle.has-product-hit,
.fw-line__bottle.has-product-hit img { pointer-events: none; }
.fw-line__hit {
  position: absolute;
  left: -30%;
  top: -4%;
  width: 160%;
  height: 108%;
  overflow: visible;
  pointer-events: none;
}
.fw-line__hit rect { fill: transparent; pointer-events: all; cursor: pointer; }
