/*
Theme Name: Chumuk
Theme URI: https://chumuk.com/
Author: Chumuk
Description: Block theme for Chumuk. Token layer plus the C33/C02/C37/C16 skeleton, the C04 hero, the C01 marquee, the C05 bento grid and the C06/C34 ingredients carousel.
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.0
Version: 0.4.0
  !! BUMPING THE FIELD ABOVE DOES NOT BUST ANY CACHE !!
  It is theme metadata only, and WordPress requires it. The cache-buster for this
  stylesheet and for every theme script is the file's own mtime, via
  chumuk_asset_version() in functions.php [checklist section 10.78 r4]. Editing
  this file changes what a browser fetches without touching the field above; the
  field was retired as the cache-buster because it has to be remembered, and in
  audit 06 it was not.
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: chumuk
Tags: block-theme, full-site-editing
*/

/* ==========================================================================
   TOKEN LAYER — build step 1 (build-specs/f-foundation.md)

   Every colour value referenced below is SAMPLED from the comp per checklist
   §3.11 and defined once, in theme.json settings.color.palette. Nothing here
   restates a hex.

   🔴 THE COMP MOVED 2026-08-27 [§10.157]. design/ no longer exists — it mixed
   the client's confidential archive with our own artefacts under one name.
     ~~wp-content/design/pink-new-3.png~~
       -> wp-content/design-source/comp/pink-new-3.png
   EVERY `design/…` PATH IN THE PROVENANCE COMMENTS BELOW MAPS THE SAME WAY:
   the comp to design-source/comp/, the source images (BG-1.jpg, expert-scene.png,
   glass-hydration.png, ice-band-bg.jpg, doodles-white.png, footer-card-tile.png,
   footer-doodles-ref.png, ingredient-images/, expert-guidance-icons/) to
   design-source/assets/. Those comments were left in their original wording on
   purpose — they are contemporaneous measurement records, and rewriting a path
   inside each one would add noise to the evidence. Full table:
   docs/claude-code-agent-instructions.md item 3.

   NOTE (spec defect F-D1, see build report): design-tokens.md §2 requires a
   per-value `SAMPLED from wp-content/design/pink-new-3.png` comment in
   theme.json AND style.css. JSON has no comment syntax, so the provenance
   note lives here for the whole palette.

   Component CSS starts in the build-step-2 layer below.
   ========================================================================== */

:root {
	/* --- Semantic aliases — design-tokens.md §2.1.2 ------------------------ */
	--chumuk-bg: var(--wp--preset--color--white);
	--chumuk-surface: var(--wp--preset--color--ice);
	--chumuk-surface-alt: var(--wp--preset--color--pink-soft);
	--chumuk-surface-warm: var(--wp--preset--color--sand);
	--chumuk-text: var(--wp--preset--color--ink);

	/* §10.30 SITE-WIDE RULE — on ANY light-or-mid brand ground (cyan, pink,
	   pink-deep, pink-soft, pink-ghost, ice, sand, mint, lime, lime-pale, all
	   three veils) text is `ink`, NEVER white. `--chumuk-text-invert` is ONLY
	   for genuinely dark grounds: `ink` itself and the §15.4 flavour DEEP
	   tones. Do not add a darkened `cyan-deep` — REJECTED, it collides with
	   Natural Bliss deep #0A7C96. See design-tokens.md §2.1.2. */
	--chumuk-text-on-brand: var(--wp--preset--color--ink);
	--chumuk-text-invert: var(--wp--preset--color--white);
	--chumuk-primary: var(--wp--preset--color--ink);        /* buttons */
	--chumuk-secondary: var(--wp--preset--color--cyan);
	--chumuk-accent: var(--wp--preset--color--pink);
	--chumuk-success: var(--wp--preset--color--green);
	--chumuk-error: var(--wp--preset--color--red);
	--chumuk-warning: var(--wp--preset--color--gold);

	/* --- Bare-channel companions of two palette slugs — §10.192 ------------- */
	/* 🔴 THESE ARE NOT NEW COLOURS. They are `forest` and `blue-deep` — both
	   already registered in theme.json (slugs 18 and 11) and both already emitted
	   as `--wp--preset--color--*` — restated as bare `R G B` channels.

	   WHY THEY HAVE TO EXIST: C05's brand-tinted wash needs a TRANSLUCENT palette
	   colour, and `rgb( <hex> / <alpha> )` is not legal CSS. The alpha must be
	   applied to channels, so the channels must be available separately.

	   WHY THEY ARE HERE AND NOT IN theme.json: `--wp--preset--color--*` names are
	   GENERATED by WordPress from palette slugs, and `17 58 0` is not a colour
	   value, so no palette entry can produce them. The name is the design's own
	   [chumuk-homepage.dc.html :root] and is kept verbatim so the design file and
	   the theme spell the token identically.

	   ⚠️ THE TWO HALVES MUST MOVE TOGETHER. Changing #113A00 in theme.json without
	   changing `17 58 0` here silently desynchronises C05's tint from C10's ink,
	   and nothing computes to `unset` to warn you — the wash simply becomes a
	   different colour from the one it was contrast-solved against. */
	--wp--preset--color--forest-rgb: 17 58 0;        /* #113A00 — theme.json slug `forest` */
	--wp--preset--color--blue-deep-rgb: 2 63 130;    /* #023F82 — theme.json slug `blue-deep` */
	/* ➕ §10.193, when the wash became a registered block style and `ink` joined
	   the offered set. Same rule as the two above: the value is theme.json's,
	   restated as channels because CSS has no `rgb( <hex> / <alpha> )` form. */
	--wp--preset--color--ink-rgb: 52 52 52;          /* #343434 — theme.json slug `ink` */

	/* --- Derived surfaces — design-tokens.md §2.1 -------------------------- */
	/* Translucency over a parent. A flat hex would be wrong.
	   ⚠️ ~~these are the only colour values in this file, and none of them is a
	   palette entry~~ AMENDED at §10.192: the two `*-rgb` companions above are
	   also colour values, and they ARE palette entries — restated as channels
	   because CSS has no `rgb( <hex> / <alpha> )` form. Everything in THIS block
	   remains non-palette. */
	/* ⚠️ THE OLD COMMENT WAS WRONG AND IS CORRECTED HERE [§10.98 / D]: this token
	   has TWO consumers, not one. Besides `.chumuk-hero__card` it also fills the
	   SELECTED flavour thumbnail's plate — `.chumuk-hero__variants
	   input:checked + .screen-reader-text + .chumuk-hero__variant-jar`. Any
	   future change to this value moves the selected-state plate too. Same class
	   of defect as §10.82 r8's veil-light: a token's scope comment trusted
	   instead of grepped. */
	--chumuk-veil-card: rgb(255 255 255 / 0.50);    /* the selected switcher plate. NO LONGER the hero card — see below */

	/* 🔴 THE C04 HERO CARD'S OWN VEIL — MEASURED OFF THE COMP, APPLIED 2026-08-24
	   BY OWNER RULING 1 [checklist §10.126].

	   SPLIT FROM `--chumuk-veil-card` RATHER THAN CHANGING IT, because that token
	   has TWO consumers (see the note above) and the switcher plate is not part of
	   this ruling. Same split as `veil-card` / `veil-light` and `verdict-yes`.

	   HOW 0.20 WAS OBTAINED, and why it is not a guess: the comp's hero ground
	   just above the card reads rgb(234,138,184) — which is the palette's own
	   `pink` #EA8AB8, EXACTLY — and the veil just inside reads rgb(238,162,198).
	   Solving v = a*255 + (1-a)*g per channel gives a = 0.190 / 0.205 / 0.197.
	   🔴 THE THREE CHANNELS AGREEING TO WITHIN 1.5 % IS WHAT PROVES THE OVERLAY IS
	   WHITE AND NOT A PINK TINT — a tinted overlay solves to three different
	   alphas. Round-trip check: white@0.20 over rgb(234,138,184) computes
	   rgb(238,161,198) against the comp's measured rgb(238,162,198) — one channel
	   out by 1/255. */
	/* 🔴 DARKENED AT §10.192 so the card's white copy is legible — and SPLIT IN
	   TWO, because one token was doing two unrelated jobs. It painted the hero
	   CARD and the switcher's jar PLATES, which the comp specifies as "both 20%
	   white": darkening a single token would have dragged the plates dark with
	   the card. The plate keeps the measured design value under its own name;
	   only the card's ground changes.
	   ⚠️ 0.68 IS SOLVED, NOT CHOSEN BY EYE: white text needs the ground under it
	   at <= 118.6 per channel for 4.5:1, and `ink` #343434 at alpha a over a
	   worst-case PURE WHITE region of the photograph gives 255 - 203a <= 118.6,
	   so a >= 0.672. 0.68 is the first hundredth clear of it, which is why it
	   holds on all four variant photographs rather than on the one that was
	   checked.
	   ⚠️ ~~--chumuk-hero-card-veil: rgb(255 255 255 / 0.20)~~ SUPERSEDED. The old
	   value is not deleted; it moves to `--chumuk-hero-plate-veil` below. */
	--chumuk-hero-card-veil: rgb(52 52 52 / 0.68);
	--chumuk-hero-plate-veil: rgb(255 255 255 / 0.20);

	/* 🔴 THE C10 VERDICT ICONS' OWN ROLE TOKENS [F19, checklist §10.101].
	   The tick used the `green` preset directly and MEASURED **2.43:1** against
	   the composited comparison card `rgb(251,255,255)` — under WCAG 1.4.11's
	   3:1 floor for a graphical object.

	   🔴 THE SHARED `green` TOKEN IS DELIBERATELY NOT DARKENED. `green` backs
	   `--chumuk-success`, whose real consumers — the newsletter confirmation and
	   form states — are still UNBUILT. Changing it would pre-empt those surfaces
	   with no measurement behind the choice. So the ROLE gets its own property
	   and the shared token is left alone: the same split as `--chumuk-veil-card`
	   / `--chumuk-veil-light`.

	   ➕ AND IT COINS NO NEW COLOUR. `mint-ink` is already in the palette and is
	   already this build's icon-glyph green (C35's discs). Measured against the
	   same composited card it gives **5.51:1** — not a marginal pass. A
	   hue-preserving darkening of `green` was the alternative and reached only
	   3.11:1, i.e. it would have invented a colour to scrape the floor.

	   ⚠️ The cross is UNCHANGED. `red` measures **3.97:1** on the same card and
	   already clears the floor; it takes a role property here for symmetry, with
	   the same value it always had. */
	--chumuk-verdict-yes: var(--wp--preset--color--mint-ink);
	--chumuk-verdict-no: var(--wp--preset--color--red);
	/* [MEASURED] the comp's hero jar leans 12deg counter-clockwise — axis-of-
	   symmetry fit over three y-bands, rms 1.26-1.37 px [§10.98 / B]. */
	--chumuk-hero-jar-tilt: -12deg;
	/* [MEASURED] all four jar attachments are 1707 x 2560 = 2/3 [§10.98 / A1]. */
	--chumuk-hero-jar-aspect: 2 / 3;

	/* 🔴 AN ALPHA IS MEANINGLESS WITHOUT ITS GROUND [checklist §10.82 r8,
	   design-tokens.md §2.4]. VALUE CORRECTED 2026-08-19: 0.18 → 0.42.
	   GROUND IT IS DERIVED AGAINST: the step card is nested INSIDE
	   `--chumuk-veil-strong`'s 0.85 white inner card, not laid on the section
	   photograph. Over 0.85 white the largest delta 0.18 can produce is ~7/255
	   and the rendered delta measured 0/255 — a structurally invisible card.
	   0.42 is the comp's own value, sampled at 11 x positions just inside and
	   outside the step card's top edge in pink-new-3.png (range 0.379–0.490,
	   flat — a plain veil over a gradient ground, not a gradient veil).
	   So: 0.18 was a reasonable veil OVER A PHOTOGRAPH and useless over an 0.85
	   veil. Do not reuse this token on a different ground without re-deriving
	   the alpha for that ground — C13 and C15 both have veils ahead of them. */
	--chumuk-veil-light: rgb(255 255 255 / 0.42);   /* nested step-card veil, over --chumuk-veil-strong */

	/* ROLE, NOT SECTION [checklist §10.82 r8]: this reads "near-opaque card veil
	   over a photographic ground" — that is the contract. It was coined for
	   C10's card over BG-2.jpg (not built yet); today its ONLY rendered
	   consumer is C08's inner `.chumuk-howto` card at line ~2809, which is why
	   the old "C10 card over photo" comment had become false. A comment that
	   names a consumer instead of a role goes stale the moment a second
	   consumer arrives. */
	--chumuk-veil-strong: rgb(255 255 255 / 0.85);
	/* 🔴 12 % -> 20 % 2026-08-22 [F4, checklist §10.101]. ~~`rgb(52 52 52 / 0.12)`~~
	   composited over white to **#E7E7E7**; the comp's C09 rules measure
	   **(214,214,214) = #D6D6D6** at all five rows. Anti-aliasing can only LIGHTEN
	   a 1 px line, never darken it, so the gap was real rather than a sampling
	   artefact. 20 % is solved, not guessed: 255 - 0.20 x 203 = 214.4 -> #D6.
	   F4 was deferred at step 6 because this token is SHARED with the bento, the
	   carousel and the FAQ — and step 12 is the pass that owns exactly that. Every
	   consumer was re-measured on its own ground; see the step-12 report. */
	--chumuk-border-hairline: rgb(52 52 52 / 0.20); /* C09 rules, FAQ dividers, C10 table, trust bar, footer base, carousel ring */
	--chumuk-border: var(--chumuk-border-hairline);

	/* --- The two-tone focus ring's LIGHT COMPANION [checklist §10.82 r4] ----
	   Both tones are existing tokens and NO value is coined: the dark tone stays
	   theme.json's `--wp--custom--focus-ring` (#1A1A1A, §15.4) and the companion
	   is the `white` PALETTE entry. Its width is aliased to the ring's own width
	   rather than restated, so the two can never drift (§3.11 define-once).
	   The rule that consumes these — and the reason a single dark ring is
	   unsatisfiable over a photograph — is the standing block below the button
	   focus rules. */
	--chumuk-focus-ring-companion: var(--wp--preset--color--white);
	--chumuk-focus-ring-companion-width: var(--wp--custom--focus-ring-width);

	/* --- Spacing — design-tokens.md §2.3 ---------------------------------- */
	--chumuk-section-pad: clamp(48px, 6vw, 80px);

	/* C37 banner height — [DERIVED at build step 2]. c37-page-banner.md:
	   "Height and spacing are [DERIVED] — no comp exists for any non-front
	   page. Shorter than the C04 hero; define once as a token so all templates
	   match." The C04 hero band is 1030 px (design-tokens.md §2.5); this ceiling
	   is 320 px, well under it, and the floor keeps the banner usable at 375. */
	--chumuk-banner-min-height: clamp(200px, 18vw, 320px);

	/* C02 header action-icon box — [MEASURED] from pink-new-3.png: the icon row
	   runs y 87–112, x 1615–1780. Declared once here because the icons are now
	   supplied by WooCommerce blocks whose own stylesheet does not size them
	   (measured 0 × 0 on the rendered page). */
	--chumuk-header-icon: 26px;

	/* 🔴 THE TWO HEADER CONTROL BOXES — §10.192, from the finalised homepage.
	   The GLYPH stays 26 (above); these are the BOXES around it. WCAG 2.5.5 wants
	   44 × 44 and the account link, the cart button and the hamburger were all
	   rendering at the glyph's own size. The cart is 45 and not 44 because the
	   design measures it at 45 — the mini-cart button's own box in the comp — and
	   a 1px difference between two adjacent boxes is not worth normalising away
	   against a measured value. */
	--chumuk-header-action-box: 44px;
	--chumuk-header-cart-box: 45px;

	/* THE C05 BENTO CARD CORNER RADIUS — the C05 bento cards are now the only thing
	   it actually paints, plus the SHARED `.chumuk-carousel__media` base rule that
	   C06 overrides and C13 inherits at step 8. [MEASURED] from pink-new-3.png by
	   tracing the corner arc: bento card B top-left runs y 1411 x716 → y 1425 x702,
	   an arc of 14 px.
	   🔴 THIS TOKEN NO LONGER SERVES THE C06 INGREDIENT CARD MEDIA, AND ITS 16 px
	   CAME FROM THAT NOW-SUPERSEDED READING [checklist §10.69 r2]. The 16 was a
	   consolidation of TWO single-corner traces that disagreed by 2 px — the bento's
	   14 px above and the first ingredient card's media at y 2531 x156 → y 2546 x140
	   (arc 16 px) — resolved by taking the larger. §10.69 r2 retired the C06 media
	   reading: that card is one continuous card and takes the canonical
	   --chumuk-card-radius-lg (20 px) top and bottom, measured far more rigorously
	   (twice per card across four cards, with an arc-centre cross-check).
	   ⚠️ THE VALUE DELIBERATELY STAYS 16 px. §10.69 r2 retired one reading on one
	   element; it did NOT re-measure the bento. The bento's own trace is 14 px, so
	   14-vs-16 goes to §3.10 — a narrower question than before, because only one
	   section now depends on the answer.
	   ⚠️ Still deliberately NOT merged into --chumuk-card-radius-lg below: checklist
	   §10.68 r2 refuses to merge 12 px and 16 px into 20 px "by assumption", because
	   they may be genuinely distinct, and §10.69 r2 states that refusal still stands. */
	--chumuk-card-radius: 16px;

	/* THE CANONICAL CARD RADIUS — [MEASURED], and the consolidation of two
	   measurements of one design radius [checklist §10.68 r2]. It was
	   --chumuk-hero-card-radius (20 px, step 3, measured on the hero card box at
	   x 140–660 / y 700–915) and --chumuk-card-panel-radius (19 px, build fix 05,
	   measured twice per card on all four C06 description panels — see the padding
	   token below for the method). The two land 1 px apart on different comp
	   surfaces, and tracing a curve in a raster carries ±1 px of anti-aliasing
	   error, so §10.68 r2 rules them ONE radius measured twice: the rounder value
	   is canonical, which also avoids re-pointing the hero.
	   Named for CARDS, not for the hero, because its consumers are the hero card,
	   the hero switcher jar plate and the C06 ingredient card panel. */
	--chumuk-card-radius-lg: 20px;

	/* C05 body-scrim panel corner — [DERIVED at build step 4]. The comp draws a
	   chip behind the card TITLE only (fully rounded, y 1458–1522) and no panel
	   behind the body copy, so there is nothing to measure: the body scrim is an
	   accessibility addition (c05-bento.md's "scrim or overlay where it fails"),
	   and a pill radius on a three-line block reads wrong. Sized against the
	   card radius above rather than invented independently. */
	--chumuk-bento-panel-radius: 12px;
	/* ~~[MEASURED] the comp's bento title chip, by differencing rows inside it
	   against rows above and below: least-squares white alpha 0.116.
	   --chumuk-bento-chip-veil: rgb(255 255 255 / 0.12)~~ SUPERSEDED at §10.192.
	   🔴 THE CHIP IS NO LONGER OPAQUE `ink` AND NO LONGER A WHITE WASH. C06's 23
	   carousel labels drop `has-ink-background-color` and take this veil instead,
	   so the photograph reads through the chip. The alpha is the same 0.68 the
	   hero card is solved at, and for the same reason: white copy needs its
	   ground at <= 118.6 per channel, and `ink` #343434 at alpha a over a
	   worst-case pure-white region gives 255 - 203a <= 118.6, i.e. a >= 0.672.
	   ⚠️ THIS IS THE ONE PLACE ON THE PAGE WHERE A PHOTOGRAPH CAN NOW REACH A
	   TEXT GROUND. It was 12.45:1 by construction before, on an opaque fill; it
	   is now a measured value per card. Pixel-sampled on all 23 — see report 73. */
	--chumuk-bento-chip-veil: rgb(52 52 52 / 0.68);
	--chumuk-bento-pad-top: 71px;
	--chumuk-carousel-gap: 19px;
	--chumuk-ingredient-media-h: 407px;
	--chumuk-ingredient-panel-h: 187px;
	--chumuk-ingredient-panels-gap: 44px;
	--chumuk-ingredient-pad-bottom: 42px;
	--chumuk-ingredient-tabs-gap: 67px;
	/* ⚠️ ~~--chumuk-tabs-pad-block: 5px~~ · ~~--chumuk-tab-w: 166px~~ — BOTH
	   RETIRED at §10.192. The 166 was a real measurement (four label inks solving
	   for one equal tab width twice over, 4 × 166 = 664 against the comp's 665
	   strip) and the tabs are no longer equal-width, so it describes nothing that
	   renders. Removed rather than left declared and unused — a token no rule
	   reads is a maintenance trap. */

	/* ======================================================================
	   SHARED TAB TOKENS — C07's store tabs and C34's ingredient tabs are ONE
	   style [§10.192].
	   🔴 PROMOTED TO SITE SCOPE, NOT DUPLICATED. These are the store handoff's
	   tab values verbatim; they previously lived only in `--cs-*`, which is
	   declared under `.chumuk-store` and is therefore INVISIBLE to C06 — the
	   same scoping trap already on record for `--cs-cyan`. Copying the hexes
	   into C06 would have put one colour in two places with nothing keeping
	   them equal. Both bands read these now, so the two strips cannot drift.
	   ⚠️ The two whites are written as the palette slug rather than as the
	   design file's `#FFFFFF`: a registered slug exists, so a literal is not
	   justified. Same computed value; the only place this file departs from the
	   design's literal bytes, and it is declared in report 73 §2.4.
	   ⚠️ The other three literals have NO palette slug — they are the store's
	   own `--cs-dark` / `--cs-grey` / `--cs-tab-hover`, verified identical here
	   and re-pointed AT these tokens in the C07 commit so the value exists once.
	   ====================================================================== */
	--chumuk-tab-gap: 4px;
	--chumuk-tab-strip-pad: 6px;
	--chumuk-tab-strip-bg: var(--wp--preset--color--white);
	--chumuk-tab-strip-shadow: 0 2px 14px rgba(158, 27, 60, 0.08);
	--chumuk-tab-ink: #6B6068;
	--chumuk-tab-hover-bg: #F6EEF2;
	--chumuk-tab-active-bg: #232323;
	--chumuk-tab-active-ink: var(--wp--preset--color--white);
	--chumuk-tab-font-size: 13px;
	--chumuk-tab-tracking: 0.12em;
	--chumuk-tab-pad-block: 14px;
	--chumuk-tab-pad-inline: 44px;
	/* [MEASURED] from the comp's card shadow — 17/255 of darkening at the edge
	   over a 20 px falloff is 0.07 of `ink` at the peak of a 20 px blur. */
	--chumuk-card-shadow: rgb(52 52 52 / 0.14);
	/* 🔴 C07's nine comp-measured geometry tokens are SUPERSEDED and removed —
	   ~~--chumuk-store-pad-top: 65px~~ ~~--chumuk-store-pill-h: 40px~~
	   ~~--chumuk-store-rail-card-h: 78px~~ ~~--chumuk-store-rail-card-pad: 22px~~
	   ~~--chumuk-store-row-gap: 64px~~ ~~--chumuk-store-rail-card-pad-x: 32px~~
	   ~~--chumuk-store-pad-bottom: 45px~~ ~~--chumuk-store-title-gap: 30px~~
	   ~~--chumuk-store-desc-gap: 45px~~
	   Each was measured from pink-new-3.png for the rail-and-segmented-control
	   layout the 2026-08-26 handoff replaces. Every one was verified to have
	   ZERO remaining `var()` consumers before deletion, not assumed unused.
	   The handoff's own geometry lives with its rules in the C07 block below.
	   Struck rather than silently dropped — build-reports/47, §3. */
	--chumuk-howto-pad: 91px;
	--chumuk-howto-veil: rgb(255 255 255 / 0.75);
	--chumuk-howto-col-gap: 67px;

	/* Card DESCRIPTION-PANEL padding — [MEASURED] from pink-new-3.png
	   by tracing the ingredients band (checklist §10.67 r1, build audit 04 MINOR
	   1). The comp draws each ingredient item as one rounded panel with the media
	   flush at its top and the description below on the panel's own ground, which
	   is what makes it read as a card — joined into one continuous card per
	   checklist §10.68 r3.

	   🔴 THE RADIUS THIS BLOCK USED TO DECLARE IS RETIRED. --chumuk-card-panel-radius
	   (19 px) was consolidated into --chumuk-card-radius-lg (20 px) by checklist
	   §10.68 r2 — see that token above for the reasoning. The 19 px derivation is
	   kept here because it is the [MEASURED] evidence behind the canonical value.

	   METHOD, and it is two independent derivations of the same arc per card: the
	   panel ground is #E9FBFF against the band's `ice` #E5FBFB, so the panel is
	   separable by exact colour match. On each card the straight left edge, the
	   bottom row's leftmost panel pixel, and the left column's lowest panel pixel
	   give r twice — bottom-row inset and left-column rise. Card 1 left x 140,
	   bottom y 3110, bottom row starts x 159, left column ends y 3091 → 19 and 19.
	   Cards 3, 4 and 5 (left x 803 / 1134 / 1465) repeat it: 19 / 19 / 19, and
	   19 / 19 / 19 on the right corners. All four panels measure 315 px wide.

	   Padding is the same trace: the description ink starts exactly 20 px inside
	   the left edge on ALL FOUR cards, and card 3's longest line ends 20 px inside
	   the right edge, so 20 px is the box and not a ragged-edge artefact. The
	   glyph-top inset reads 24 px on all four, which is 20 px of padding plus the
	   cap gap of a 16 px / 24 px line box — consistent, not a second value.

	   Named for CARDS, not for C06: the next card panel reuses this rather than
	   coining another literal. ⚠️ design-tokens.md §2.4 records only the 999 px
	   button radius and has no card entry; these are reported in build-fix-05 and
	   build-fix-06 for §2.4 to record — the theme does not own that document.
	   🔴 DO NOT shave this 20 px to make band arithmetic work [checklist §10.68 r3]:
	   trimming a [MEASURED] value to satisfy a target is how a token stops meaning
	   anything. If the band overflows, the number gets reported, not absorbed. */
	--chumuk-card-panel-pad: 20px;

	/* --- Motion — design-tokens.md §2.6 (all [DERIVED]) -------------------- */
	--chumuk-dur-fast: 150ms;
	--chumuk-dur-base: 300ms;
	--chumuk-dur-slow: 600ms;
	--chumuk-ease: cubic-bezier(.2, .7, .3, 1);
	--chumuk-marquee-dur: 40s;
	--chumuk-counter-dur: 1600ms;
	--chumuk-lift: translateY(-4px) scale(1.02);

	/* --- C07 store rail states — SUPERSEDED 2026-08-26 --------------------- */
	/* 🔴 ~~--chumuk-store-rail-hover: #FDF3F7~~  ~~--chumuk-store-rail-darken: 88%~~
	   Both encoded checklist §15.4's rail-card behaviour: an inactive card that
	   tints to #FDF3F7 on hover, and an ACTIVE card that darkens one step because
	   it was FILLED with the flavour's deep tone.

	   The handoff retires the filled card entirely. Its Option C card stays white
	   with #111 ink in BOTH states and identifies by rail + rimmed dot, so there
	   is no fill left to darken, and the inactive hover is now #e2c9d4 on the
	   BORDER rather than a tint on the ground. §15.4's two values therefore
	   describe a control that no longer exists.

	   ⚠️ The `--chumuk-store-rail-darken` note claimed a derivation calibrated
	   against §15.4's `#87082E` example. That claim was true and is not being
	   overturned — it is simply moot, because the surface it tinted is gone.
	   Struck, not deleted, so the next pass does not re-derive it. Both were
	   verified to have zero `var()` consumers before removal. */
}

/* --------------------------------------------------------------------------
   Line height per SIZE preset — design-tokens.md §2.2

   Keyed to the size preset, never to the heading LEVEL: level and size are
   independent (§2.2.1, "level ≠ size"), so an <h3> carrying the `h6` token
   must take the h6 line height. theme.json fontSizes entries cannot carry a
   line height, which is why these live here.

   ⚠️ The `h2`–`h6` slugs are emitted KEBAB-CASED by WordPress: the theme.json
   slug `h2` becomes the class `.has-h-2-font-size` and the property
   `--wp--preset--font-size--h-2` (_wp_to_kebab_case splits letter→digit).
   Block markup still uses the documented slug — {"fontSize":"h2"} — but any
   hand-written CSS or var() reference must use the emitted `h-2` form.
   Measured on WP 7.0.4, build step 1. See build report finding F-D3.
   -------------------------------------------------------------------------- */
.has-display-1-font-size { line-height: 1; }
.has-display-2-font-size { line-height: 0.91; }
.has-display-3-font-size { line-height: 1; }
.has-h-2-font-size { line-height: 1.07; }
.has-h-3-font-size { line-height: 1.1; }
.has-h-4-font-size { line-height: 1.15; }
.has-h-5-font-size { line-height: 1.2; }
.has-h-6-font-size { line-height: 1.2; }
.has-question-font-size { line-height: 1.4; }
.has-body-lg-font-size { line-height: 1.56; }
.has-body-font-size { line-height: 1.5; }
.has-body-sm-font-size { line-height: 1.6; }
.has-label-xs-font-size,
.has-label-sm-font-size,
.has-label-md-font-size,
.has-label-lg-font-size { line-height: 1.4; }

/* --------------------------------------------------------------------------
   The `label` ROLE — design-tokens.md §2.2, checklist §10.40 / §10.51 r1

   `label` is a STYLE ROLE, not a size: uppercase + 0.08em tracking + the body face,
   applied on top of whichever of the four label-* size presets the element
   takes. It is deliberately NOT a fontSizes entry.

   The emitted selector is `.is-style-label` (the block style variation
   registered in functions.php). `.chumuk-label` is the rule's name in prose
   only and is never emitted.
   -------------------------------------------------------------------------- */
.is-style-label {
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	line-height: 1.4;
}

/* --------------------------------------------------------------------------
   THE `sans` HEADING STYLE — checklist §10.97, build-fix-22 F6

   Registered on core/heading in functions.php; this is the rule it emits.

   WHY IT EXISTS. §2.2's `h5` row says serif, and for C35's expert card titles
   that is correct. It is wrong for C08's step titles: the comp draws "Mix",
   "Shake" and "Drink" in the sans. Both elements carry the `h5` SIZE token, so
   the token cannot fix it — a type token carries SIZE ONLY and the family
   comes from `styles.elements.heading` (§2.2.1). This is the family half of
   that split, made a reusable role rather than a private fact about C08.

   WEIGHT 600, MEASURED, NOT ASSUMED. Comp step titles ink: "Mix" 41 x 20,
   "Shake" 73 x 20, "Drink" 64 x 20 (threshold 128, crop-edge assertion clean
   on all four sides). Geist 600 reproduces all three within 4.1-8.2 % on
   width and EXACTLY on height at 27 px; Geist 700 runs 6.2-9.6 % wide on the
   same strings. 600 it is.

   ⚠️ THIS RULE DOES NOT CLOSE THE C08 GAP ON ITS OWN — see F10 in
   build-fix-22. At the `h5` token's 30 px these three strings render 15-19 %
   WIDER than the comp on all three; the comp's own size is ~26-27 px. The
   SIZE is a separate, unauthorised question and is REPORTED, not fixed here.

   ⚠️ It carries NO `letter-spacing`. The `h5` tracking of -0.015em is solved
   against PLAYFAIR ink on C35's serif titles (§10.95 r3) and must not follow
   the family across — which is why `.is-style-sans` is excluded from that
   rule below, exactly as `.is-style-label` is [§10.91 r3: the fit is not
   uniform across faces OR sizes, so nothing transfers by assumption].
   -------------------------------------------------------------------------- */
.is-style-sans {
	font-family: var(--wp--custom--font-body);
	font-weight: 600;
}

/* --------------------------------------------------------------------------
   THE DISPLAY SERIF'S WEIGHT, TRACKING AND FIGURES — Playfair Display
   [checklist §10.87, family unlocked by the owner 2026-08-20]

   The family changed from Instrument Serif because the comp's headings are a
   high-contrast Didone and Instrument Serif is a condensed, low-contrast
   transitional: at a matched 41 px cap the comp's string is 25 % WIDER and its
   stems twice as thick. Three properties ride with the face, and all three were
   MEASURED off `pink-new-3.png` rather than chosen:

   • WEIGHT 500. The comp's `D` at a 41 px cap has an 8 px stem and a 1 px
     hairline — stroke contrast 8.0. Playfair 500 measures 7 / 1 = 7.0, the
     closest of every weight tested. 600 matches the stem exactly (8 px) but its
     hairline thickens to 2 px, halving the contrast match to 4.0. Per-glyph shape
     overlap against the comp also peaks at 500 (0.713 mean over D,e,p,H,a,o,n,
     against Instrument Serif's 0.382).
   • TRACKING -0.048em, h2 ONLY. Playfair's natural advances run ~9 % wider than
     the comp's at matched cap height. Solved independently over FIVE comp
     headings — -0.0465, -0.0532, -0.0427, -0.0418, -0.0563 em — mean -0.0481,
     SD 0.37 px. ⚠️ It is applied to `h2` alone. ⚠️ CORRECTED 2026-08-21 by
     §10.91 r3, which made the old wording FALSE — it read ~~"h2 is the only role
     whose tracking was measured; h3–h6 and display-1/2/3 are NOT tracked here"~~.
     `h3` IS now measured, and its answer is `normal`: at 52 px Playfair's advances
     run 1.2 % NARROW of the comp — the OPPOSITE sign to h2's 9 % wide — so closing
     it would need +0.006 em and no declaration is warranted. 🔴 DO NOT "fix" the
     inconsistency by copying h2's -0.048em down to h3; the fit is not uniform
     across the size range, which is why each role needs its own measurement.
     ⚠️ SUPERSEDED 2026-08-21 by §10.95, which made this census FALSE too — it
     read ~~"Still genuinely UNMEASURED: h4–h6 and display-1/2/3"~~. Measured
     since: `h4` 38 px / `normal` — DELIBERATELY untracked, its three comp
     instances disagree by 16 % so there is nothing to match (§10.95 r1);
     `h5` -0.015em and `h6` -0.011em, both declared BELOW this block, keyed to
     the SIZE CLASS not the heading level (read the note there before touching
     them); `display-2` `normal`, 104 → 102 px in theme.json (r2); `display-3`
     128 px / `normal` (r6). STILL genuinely unmeasured: `display-1` — the hero
     ghost word, whose mask no attempt has yet defeated — and `question`.
   • LINING FIGURES. Playfair's default `0` is 0.5425 em against a 0.7075 em cap
     — roughly x-height. The comp's "100%" measures 41–43 px against its own
     41 px cap, so the comp sets lining figures. Without this the C06 heading's
     digits render two-thirds height.

   🔴 SCOPED `:not( .is-style-label )` ON PURPOSE. `styles.elements.heading` gives
   every heading the serif; `.is-style-label` swaps it to the body face for the label role
   (footer column heads, eyebrows, the C04 `h1`). Those keep weight 400 and the
   label role's own +0.08em tracking, so this treatment must not reach them.

   ⚠️ At the family change the cap-derived SIZE tokens did not move: display-1,
   display-2, h2, h4 and h6 all back-solve from the comp's measured ink at a cap
   ratio of 0.702–0.711, and Playfair's is 0.7075 where Instrument Serif's is
   0.7200. The scale was Playfair's all along; only the family name was wrong.
   ⚠️ CORRECTED 2026-08-21 by §10.95 — the old wording read ~~"The cap-derived SIZE
   tokens did not change and did not need to"~~, which is no longer true of two of
   them. §10.94 r2 derived the instrument's own constant: Chromium RASTERISES this
   face at a 0.724 cap ratio, not the 0.7075 design figure the sizes were divided
   by, and that 2.3 % gap made three tokens read 2–4 % large. Re-solved on comp INK
   WIDTH, which does not depend on the ratio: `display-2` 104 → 102 px (§10.95 r2,
   two strings agreeing to 0.3 %) and `h6` 26 → 25 px (§10.95 r4). ✅ `h2` 58 px,
   `h3` 52 px, `h4` 38 px and `display-3` 128 px are UNCHANGED and were re-measured
   to confirm it — `h4` in particular was proposed for 37 px and REVERSED (§10.95
   r1): its three comp instances disagree by 16 %, so there is no value to match.
   🔴 Do not read the 0.7075 ratio above as a way to derive a NEW size; it is
   kept because it is what identified the family. Sizes are solved on ink width.
   -------------------------------------------------------------------------- */
/* ➕ `.is-style-sans` joins `.is-style-label` in the exclusion [§10.97 / F6].
   It is not decoration: this rule is `h5:not(...)` = (0,1,1) and `.is-style-sans`
   is (0,1,0), so WITHOUT the exclusion the serif weight 500 would beat the sans
   style's own weight and the C08 step titles would render the body face at the display
   weight. Same mechanism, same fix, as the label role. */
/* ➕ 2026-08-26 — C07's two headings are excluded, using this rule's OWN escape hatch.
   The store handoff sets no weight on either heading, so both render at the UA's bold 700.
   This rule overrides that to the display weight 500 site-wide, and at (0,2,1) it outranks a
   single class — so the section could not simply state its own weight without strengthening a
   selector, which §9 forbids. Adding the two classes to the exclusion list is the mechanism
   already here for `.is-style-label` and `.is-style-sans`, and it changes no other heading.
   ⚠️ Measured before and after: every other h1–h6 on the page still computes 500. */
h1:not( .is-style-label ):not( .is-style-sans ),
h2:not( .is-style-label ):not( .is-style-sans ):not( .cs-head__title ):not( .cs-buy__title ),
h3:not( .is-style-label ):not( .is-style-sans ),
h4:not( .is-style-label ):not( .is-style-sans ),
h5:not( .is-style-label ):not( .is-style-sans ),
h6:not( .is-style-label ):not( .is-style-sans ) {
	font-weight: 500;
	font-variant-numeric: lining-nums;
}

/* 🔴 RE-KEYED FROM THE LEVEL TO THE SIZE CLASS 2026-08-22 [F21, checklist
   §10.101]. This read `h2:not( .is-style-label )`, which is the exact
   anti-pattern §10.95 r2 corrected for `h5` and `h6`: **the value was derived
   from the comp's 58 px h2 STRINGS, so it belongs to the SIZE, not to the
   element level.**

   Keying it to the level meant every `<h2>` on the site took 58 px-derived
   tracking regardless of what size it actually rendered at. MEASURED before the
   change, at 1920:

     `Ready To Feel The Difference?`   display-2, 102 px  ->  -4.896px
     `Electrolyte`                     h3 size,   52 px   ->  -2.496px
     WooCommerce mini-cart `Your cart` no size class, 32  ->  -1.536px
     WooCommerce `Products in cart`    no size class, 24  ->  -1.152px

   None of those four is a 58 px heading and none of them was ever measured.
   The Woo pair is third-party cart chrome inheriting this build's display
   tracking purely because it happens to use `<h2>`.

   ⚠️ THE PROMOTION IS WHAT EXPOSED IT. F21 promoted the store title from `h3`
   to `h2` to close the page's only skipped heading level; its SIZE token was
   deliberately unchanged, and the size did hold at 48.67 px — but its tracking
   silently went `normal` -> `-2.336px` because of this rule. Level and size are
   independent (§10.35 r2), and so is tracking: it follows the size it was
   solved against.

   ➕ `display-2`'s own tracking is now UNSET, and that is the honest state
   rather than a regression — the -0.048em it was inheriting was never derived
   for 102 px. Recorded as F22; deriving it needs the comp, and the comp draws
   the CTA with Version B's headline, which this build does not use. */
.has-h-2-font-size:not( .is-style-label ) {
	letter-spacing: -0.048em;
}

/* --------------------------------------------------------------------------
   TRACKING for the `h5` and `h6` SIZE tokens — checklist §10.95 r3 and r4

   🔴 KEYED TO THE EMITTED SIZE CLASS, NOT TO THE HEADING LEVEL, and the `h2`
   rule above is NOT the shape to copy here. Level and size are independent
   (§2.2.1, and see the line-height block near the top of this file): BOTH of
   these tokens render on `<h3>` elements — C08's three step titles carry `h5`,
   C06's 23 chip labels carry `h6`, and there is not one `<h5>` or `<h6>` element
   on the page. An `h5:not(...)` / `h6:not(...)` rule in the `h2` rule's shape
   would match NOTHING. The `h2` rule can be level-keyed only because the `h2`
   token happens to land on `h2` elements there. Measured, not assumed.

   • `h5` → -0.015em. Derived over THREE comp strings at 30 px, to §10.87's
     multi-string standard: `Clinical Nutrition & Dietetics` solves -0.0179,
     `Digestive & Gut Health` -0.0175, `General Medicine & Wellness` -0.0090.
     -0.015em MINIMISES THE SPREAD instead of fitting one string — residuals
     +0.8 % / +0.5 % / -1.3 %, mean absolute 0.9 %. ⚠️ §10.94 r3 proposed
     -0.018em from the FIRST STRING ALONE, at which the third lands -2.1 % out.
     THE SIZE IS NOT CHANGED: 30 px is confirmed exact (§10.94 r3).
   • `h6` → -0.011em, with the size corrected 26 → 25 px in theme.json
     (§10.95 r4). The clean instance is `BEETROOT`, the ONLY chip label with no
     word space, comp ink 129 × 18: at 26 px live is +6.2 % wide, at 25 px
     +1.6 %, at 25 px / -0.011em +0.8 %. Cap height agrees independently — comp
     18, live 18 at 25 px and 19 at 26 px. ⚠️ ONE-STRING derivation, and §10.95
     r4 labels it as such: below this project's five-string standard. The other
     two chip labels are UNUSABLE, not ignored — their inter-word gap measures
     no wider than their inter-letter gaps and §10.95 r5 could not separate a
     narrow comp word space from a mask bridging it, so NO `word-spacing` is
     declared anywhere.

   🔴 THE `h6` TRACKING IS SCOPED TO SERIF HEADINGS ON PURPOSE, AND
   `.chumuk-stat__value` IS THE REASON. C09's four stat values are PARAGRAPHS
   carrying the `h6` token, and a paragraph does not take
   `styles.elements.heading` — they render in GEIST 600, not Playfair (the
   `.chumuk-stat__value` block further down says so explicitly). Both values
   above are solved against PLAYFAIR ink, and pushing a serif-derived tracking
   onto a sans face is the transfer §10.91 r3 forbids. The SIZE change does
   reach those paragraphs — unavoidable, it is the token's own value — but the
   tracking must not. `:not( .is-style-label )` excludes the body-face label role
   for the same reason it does on the weight rule above.
   ⚠️ REPORTED, not decided here: §10.95 anticipated `h6` reaching C06 only.
   C09's four stat values are a SECOND consumer of the token.

   ⚠️ `display-2` takes NO tracking declaration — §10.95 r2 solves it at
   `normal` on both comp lines. Its 104 → 102 px lives in theme.json alone.
   -------------------------------------------------------------------------- */
:is( h1, h2, h3, h4, h5, h6 ):not( .is-style-label ):not( .is-style-sans ).has-h-5-font-size {
	letter-spacing: -0.015em;
}

:is( h1, h2, h3, h4, h5, h6 ):not( .is-style-label ).has-h-6-font-size {
	letter-spacing: -0.011em;
}

/* --------------------------------------------------------------------------
   LINK STATES — checklist §10.57 r1

   theme.json carries the two settled values: colour `ink` and
   `text-decoration: underline`, in styles.elements.link (plus :hover, :focus,
   :active and :visited, all pinned to `ink` so no UA state colour — #0000EE
   unvisited, #551A8B visited — can win by matching the element).

   🔴 The underline is NOT optional. Because the link colour is IDENTICAL to
   body text (`ink` on both), colour conveys nothing, so the underline is the
   only affordance — WCAG 1.4.1. Do not drop it for aesthetics.

   Hover and focus change the UNDERLINE, never the colour. Thickness and
   offset are not expressible in theme.json's typography schema, so they live
   here. Nav is exempt from the underline (theme.json
   styles.blocks.core/navigation) — the rules below only touch decoration
   geometry, so they are inert where the line is `none`.

   Focus ring: 3 px #1A1A1A at 3 px offset (checklist §15.4). The hex is a
   fixed a11y value and deliberately NOT a palette entry (§10.30 rejected a
   muted-text token; `ink` is the muted text colour). It is declared once, in
   theme.json settings.custom, so no hex literal lives in this file.
   `:focus-visible`, not `:focus`, per §15.4's wording.
   -------------------------------------------------------------------------- */
a:where( :not( .wp-element-button ) ):hover,
a:where( :not( .wp-element-button ) ):focus-visible {
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}

/* 🔴 REMOVED 2026-08-22 [§10.97 / D2 + F8] — folded into the global two-tone
   rule below. Was:
     ~~a:where( :not( .wp-element-button ) ):focus-visible {
         outline: ...; outline-offset: ...; }~~
   Its `:where()` already gave it zero specificity, so it and the global rule
   were the same weight and the LATER one won — meaning links already took the
   two-tone ring in practice. Deleting it removes a second definition that
   agreed with the first only by source order. The hover/underline rule above
   is NOT part of this and stays. */

/* 🔴 THREE BUTTON CONTROLS FROM EARLIER STEPS, WRITTEN AGAINST THE ELEMENTS AND NOT
   AGAINST `.wp-element-button` [checklist §10.66 r3, build audit 04 MAJOR 3].
   §10.65 r4 scoped the focus-ring gap to `.wp-element-button` and recorded step 4 as
   shipping the build's first buttons. §10.66 r3 CORRECTS that: these three are
   `<button>` elements that never carry that class, so r4's remedy could not reach
   them — including the primary mobile-navigation affordance.

     button.wp-block-navigation__responsive-container-open   (parts/header.html, C02)
     button.wp-block-navigation__responsive-container-close  (the 375 nav overlay)
     button.wc-block-mini-cart__button                       (Phase 2a mini-cart)

   Measured before this rule: all three resolved to Chrome's UA ring
   `1px auto rgb(0, 95, 204) offset 0` while every link-shaped control on the page
   resolved to `3px solid rgb(26, 26, 26) offset 3px`. Focus WAS visible, so this is
   a token-integrity failure, not a WCAG 2.4.7 failure — the values below are the
   SAME `--wp--custom--focus-ring*` tokens the `a:focus-visible` rule above already
   uses (§15.4, declared once in theme.json settings.custom). Nothing new is coined.

   ⚠️ SCOPED TO THESE THREE ON PURPOSE. The GLOBAL `button, [role="button"],
   .wp-element-button` rule belongs to build step 11 per §10.65 r4 and must not be
   pre-empted here; step 11 also owns the separate defect r4 named, where the two
   mini-cart DRAWER controls that DO carry `.wp-element-button` resolve to a fully
   transparent `outline: 3px solid rgba(0, 0, 0, 0)`. Those are not touched here. */
/* 🔴 REMOVED 2026-08-22 [§10.97 / D2 + F8] — all three are `<button>`, so the
   global two-tone rule reaches them and this scoped single-tone copy is now
   redundant. Was:
     ~~.wp-block-navigation__responsive-container-open:focus-visible,
       .wp-block-navigation__responsive-container-close:focus-visible,
       .wc-block-mini-cart__button:focus-visible { outline: ...; }~~
   The reasoning above is kept because it is still the record of WHY these three
   needed naming at all (they never carry `.wp-element-button`), and because the
   mini-cart DRAWER defect it points at is still open for step 11. */

/* --------------------------------------------------------------------------
   🔴 THE TWO-TONE FOCUS RING — A STANDING RULE, NOT A C08 ONE-OFF
   [checklist §10.82 r4 + §15.4 as amended, 00-conventions.md §8]

   ANY CONTROL THIS BUILD PLACES OVER A PHOTOGRAPH OR A GRADIENT GETS THIS
   RING. C08's play button is the first; C13's carousel controls and C15's CTA
   are the next candidates, and they inherit it by adding ONE selector to the
   list below (or by putting `chumuk-ring-duo` on the block's outermost
   wrapper, which agent-instructions §2 rule 8 allows). Do not re-declare these
   four lines in a section block — that is how a two-tone ring becomes a
   one-tone ring on the third control that needs it.

   WHY: §15.4's single `#1A1A1A` ring at 3 px offset is correct on flat brand
   grounds and provably insufficient on a variable one. [MEASURED] on C08's
   video poster it failed 5 of its 8 sides, worst 1.30:1 against `#053154`,
   against WCAG 1.4.11's 3:1 floor.

   🔴 §15.4 IS NOT REVERSED. Nothing is subtracted: the dark ring keeps its
   exact width and its +3 px offset. A LIGHT COMPANION is ADDED via
   `box-shadow` — WCAG's own technique for an indicator over an unknown ground,
   because one of two opposite tones always reads. Both tones are existing
   tokens: `--wp--custom--focus-ring` (#1A1A1A, theme.json settings.custom,
   §15.4) and the `white` palette entry. NO COLOUR VALUE IS COINED HERE.

   GEOMETRY. An outer `box-shadow` spread paints from the border box outwards
   and the outline paints on top of it, so ONE shadow gives the companion on
   BOTH sides of the dark ring:
     0 → 3 px   companion (the offset gap, which would otherwise be poster)
     3 → 6 px   the §15.4 dark ring, untouched
     6 → 9 px   companion
   spread = offset + width + companion width.

   REJECTED, and do not substitute [§10.82 r4]: a negative `outline-offset`
   putting the ring on the control's own fill (it contradicts §15.4's +3 px and
   passes only against that fill), and a scrim behind the control (a design
   change to the comp's most prominent frame).

   VERIFICATION IS PER SIDE, FROM SCREENSHOT PIXELS — every side must clear
   3:1 on at least ONE of the two tones. Measured results are in the fix
   report; a CSS parser that cannot read `color(srgb …)` produced two false
   findings in this project already (§10.75 r5).
   -------------------------------------------------------------------------- */
/* ➕ MADE GLOBAL 2026-08-22 [§10.97 / D2 + F8]. It was an OPT-IN LIST — every
   control that needed it added a selector, and three components had instead
   shipped their own scoped single-tone copy, which is the duplication this
   closes. The list is gone; the rule now applies to every focusable control.

   🔴 `:where()` IS LOAD-BEARING, NOT STYLE. It gives this rule ZERO
   specificity, so a component rule never has to fight it and no `!important`
   is needed anywhere — which is why the three scoped copies could simply be
   DELETED rather than re-pointed. It also means a component CAN still override
   it deliberately with a plain class, and that is the intended escape hatch.

   ⚠️ THIS PRE-EMPTS §10.65 r4, WHICH RESERVED THE GLOBAL BUTTON FOCUS RULE FOR
   BUILD STEP 11, and it does so on the client lead's explicit authorisation for
   this pass. Recorded rather than quietly done. Step 11 still owns the separate
   defect r4 named: the two mini-cart DRAWER controls that carry
   `.wp-element-button` and resolve to `outline: 3px solid rgba(0, 0, 0, 0)`.
   That is a transparent-colour bug, not a missing rule, and this does not fix
   it — a zero-specificity rule cannot beat their existing declaration.

   `.chumuk-ring-duo` is retired with it: grep finds it in NO markup — not in
   `patterns/`, `parts/`, `plugins/` or post 45 — so it was a hook nothing ever
   used. A global rule needs no opt-in hook. */
:where( a, button, summary, input, select, textarea, [tabindex]:not( [tabindex^="-"] ) ):focus-visible {
	outline: var(--wp--custom--focus-ring-width) solid var(--wp--custom--focus-ring);
	outline-offset: var(--wp--custom--focus-ring-offset);
	box-shadow: 0 0 0
		calc(
			var(--wp--custom--focus-ring-offset) + var(--wp--custom--focus-ring-width) +
				var(--chumuk-focus-ring-companion-width)
		)
		var(--chumuk-focus-ring-companion);
}

/* ==========================================================================
   COMPONENT LAYER — build step 2 (template parts and templates)

   c33-promo-bar.md · c02-header.md · c16-footer.md (skeleton) · c37-page-banner.md

   No hex, no raw px and no font stack below: every value is a theme.json token
   read by its EMITTED name (design-tokens.md §2.2's kebab-case callout —
   --wp--preset--font-size--h-2, never --h2).
   ========================================================================== */

/* --------------------------------------------------------------------------
   C02 — sticky header

   🔴 SOLID BY DEFAULT, on every template [checklist §10.34 d.1, 00-build-order
   step 2]. The cyan ground comes from the block's own backgroundColor
   attribute, so it is painted by the global stylesheet — there is no frame in
   which this header is transparent, and no JS decides it. The
   transparent-over-hero state is a FRONT-PAGE-ONLY enhancement layered on in
   build step 3 with C04, scoped to body.home; it is deliberately absent here.

   Sticky sits on the template-part wrapper, not on .chumuk-header: a sticky
   element can only travel inside its own parent's box, and .chumuk-header's
   parent is exactly its own height. The wrapper is a child of .wp-site-blocks,
   which spans the page.
   -------------------------------------------------------------------------- */
.wp-site-blocks > header.wp-block-template-part:has( > .chumuk-header ) {
	position: sticky;
	top: 0;
	z-index: 20;
}

/* The promo bar, the header, <main> and the footer are consecutive TOP-LEVEL
   blocks, and core's `:where(.wp-site-blocks) > *` rule gives each a 24 px
   top margin — measured on the rendered page as a white strip between the
   promo bar and the header, i.e. exactly the "header offset" c33-promo-bar.md
   warns about. Section rhythm inside <main> is unaffected: those blocks are
   children of post-content, not of .wp-site-blocks. */
.wp-site-blocks > * {
	margin-block-start: 0;
}

/* Nav gap. Measured 50 px at the comp's native 1920 (item edges 231→281,
   317→367, 434→485), which is design-tokens.md §2.3's `70` (48 px). Held as a
   fluid step between two spacing tokens because a fixed 48 px wraps the four
   items onto a second line once the viewport is narrow enough to shrink the
   third of the content box this column occupies — measured wrapping at 1040.
   Both endpoints are tokens; only the interpolation rate is [DERIVED], the
   same construction as --chumuk-section-pad. */
.chumuk-header .chumuk-header__nav {
	gap: clamp( var(--wp--preset--spacing--50), 2.6vw, var(--wp--preset--spacing--70) );
}

/* c02-header.md Responsive: "Add a subtle bottom border or shadow on the solid
   state to separate it from content." Never animate height, padding or logo
   size on scroll — that is layout shift. */
.chumuk-header {
	border-bottom: 1px solid var(--chumuk-border-hairline);
}

.chumuk-header__actions a {
	display: inline-flex;
	align-items: center;
}

/* WooCommerce ships these icons as viewBox-only SVGs and relies on its own
   stylesheet to size them; measured 0 × 0 rendered here, so the theme sizes
   them. `currentColor` inside the icons means they follow the header ink —
   which is what makes the per-variant flip in build step 3 possible without
   touching this rule. */
.chumuk-header__actions svg {
	width: var(--chumuk-header-icon);
	height: var(--chumuk-header-icon);
}

/* 🔴 THE CLOSED MINI-CART DRAWER IS TAKEN OUT OF THE TAB ORDER [checklist §10.67
   r4, build audit 04 MINOR 3]. WooCommerce hides the closed drawer with
   `.wc-block-components-drawer__screen-overlay--is-hidden { opacity: 0;
   pointer-events: none }` (mini-cart.css) and flips `aria-hidden` on the drawer
   itself — but neither opacity nor pointer-events removes a control from the tab
   order. Measured before this rule: with the drawer closed, `Tab` reached
   `.wc-block-components-drawer__close` and `.wc-block-mini-cart__shopping-button`
   (stops 28 and 29 on the homepage) inside an `aria-hidden="true"` subtree — a
   focusable element a screen reader will not announce.

   ⚠️ THIS IS WOOCOMMERCE'S OWN MARKUP AND IT IS NOT EDITED. The fix is
   declarative and keyed to the ONE state WooCommerce actually toggles: the
   `aria-hidden` attribute the Interactivity API binds via
   `data-wp-bind--aria-hidden="!state.isOpen"`. `visibility: hidden` is the only
   CSS mechanism that removes descendants from the tab order while leaving layout
   intact (the drawer's width is measured by its own script), and because the
   selector reads the ARIA state rather than a class name, the two can never
   disagree again — which is precisely the defect. `inert` would be correct too
   but is an attribute, so it would need JS; declarative beats JS here.

   Specificity: class + attribute = (0,2,0), above every WooCommerce rule that
   touches the drawer, and scoped to one component so it cannot reach anything
   else. Nothing global is strengthened [§3.4].

   OBSERVATION for C20 in Phase C (§10.2 — the cart drawer is undesigned): the
   hide is immediate, so the 0.3 s slide-out no longer plays to completion. Adding
   `transition: visibility 0s linear .3s` here would restore it but would have to
   restate WooCommerce's own `transition: transform .3s` in the same shorthand to
   avoid dropping it — a stale twin of a third-party value. The drawer's motion
   design belongs to C20; a11y does not wait for it. */
.wc-block-mini-cart__drawer[aria-hidden="true"] {
	visibility: hidden;
}

/* ==========================================================================
   🔴 TAP TARGETS — 44 × 44 VIA AN OVERLAY, SO NOTHING MOVES  [§10.192]

   Every control below is icon-only or a thin text control and measured under
   44px in at least one axis: hero social 26×26, footer social 24×24, carousel
   arrows 38×38, C07 quantity steppers 12×20, C07 tabs 117×43, SEE FULL PRODUCT
   206×15, FAQ summary 760×38. WCAG 2.5.5 wants 44×44; 2.5.8 wants 24×24 and
   exempts inline text links, which is why the nav and footer CONTACT links are
   deliberately NOT touched here — they are text in a sentence-like list, not
   icon controls.

   ⚠️ THE TECHNIQUE IS AN `::after` OVERLAY, NOT PADDING, and the reason is this
   project's own discipline: every box in these bands is a value measured against
   the comp and reconciled in a report. Padding would grow the control and shift
   its neighbours, invalidating those measurements; an absolutely-positioned
   overlay centred on the control changes NO layout box at all. The visual is
   untouched — only the hit area grows.

   ⚠️ VERIFIED NON-OVERLAPPING BEFORE APPLYING, because two 44px targets 30px
   apart would steal each other's clicks. Measured pitch: hero social 50 · footer
   social 48 · steppers 64 · C13 arrows far apart. All >= 44, so no two overlays
   meet. The steppers' overlays span 6–50 and 70.5–114.5 inside a 121-wide row
   whose readout sits at 52–68, so they clear the readout too — and that readout
   is an `<output>`, not an input, so nothing interactive is covered.
   ========================================================================== */
:is(
	.chumuk-hero__social a,
	.chumuk-footer .wp-block-social-link-anchor,
	.chumuk-ingredients .wp-block-buttons button,
	.chumuk-testimonials .wp-block-buttons button,
	.cs-qty button,
	.cs-tab,
	.cs-details
) {
	position: relative;
}

:is(
	.chumuk-hero__social a,
	.chumuk-footer .wp-block-social-link-anchor,
	.chumuk-ingredients .wp-block-buttons button,
	.chumuk-testimonials .wp-block-buttons button,
	.cs-qty button,
	.cs-tab,
	.cs-details
)::after {
	content: '';
	position: absolute;
	left: 50%;
	top: 50%;
	translate: -50% -50%;
	/* `min-`, so a control already wider or taller than 44 keeps its own size and
	   only the deficient axis grows. */
	min-inline-size: 44px;
	min-block-size: 44px;
	inline-size: 100%;
	block-size: 100%;
}

/* 🔴 THE FAQ SUMMARY GETS `::before`, NOT `::after` — AND THAT IS A BUG THE
   DESIGN SHIPPED AND THEN CAUGHT, WORTH KEEPING.
   `.chumuk-faq summary::after` ALREADY EXISTS: it is the accordion's +/− disc, a
   32px pill drawn with two background bars. Adding `summary` to the overlay list
   above re-declared that same pseudo-element, and being later in the file it won
   on the geometry properties while the disc's `background-color` and
   `background-image` survived — turning the marker into a 760 × 44 BLUE PILL
   across the whole question row. [MEASURED] `::after` computed 760 × 44,
   absolute, rgb(2, 63, 130), radius 999px.
   ⚠️ A PSEUDO-ELEMENT IS A SINGLE SLOT PER ELEMENT. A shared `::after` utility
   silently collides with any component that already uses one — and the hit test
   still PASSED, because a broken overlay is exactly as clickable as a correct
   one. Only looking at it caught this.
   `::before` is unused on this summary (content computed `none`), so the hit
   area goes there and the disc is left alone. */
.chumuk-faq summary {
	position: relative;
}

.chumuk-faq summary::before {
	content: '';
	position: absolute;
	left: 50%;
	top: 50%;
	translate: -50% -50%;
	inline-size: 100%;
	block-size: 100%;
	min-block-size: 44px;
}

/* --------------------------------------------------------------------------
   C02 — THE CONTROL BOXES AND THE MOBILE MENU  [§10.192]

   Everything below comes from the finalised homepage design
   (.tmp/design-verify/chumuk-homepage.dc.html). It adds NO structure: the
   header already carries core's complete responsive-navigation markup, and
   parts/header.html already carries the mini-cart block. These rules do the
   things core leaves undone.
   -------------------------------------------------------------------------- */

/* The two Woo controls are BOXES with a centred glyph, not glyphs. `flex: none`
   so the nowrap actions row cannot shrink them below the measured size.

   ⚠️ `padding: 0` IS LOAD-BEARING AND THE DESIGN FILE CANNOT SHOW YOU WHY.
   WooCommerce's own sheet gives this link `padding: .5em` inside a `:where()`,
   i.e. specificity (0,0,0). The design source does not carry WooCommerce's
   stylesheets at all, so there the link has no padding and the 44px sizes
   resolve to a 44 × 44 box directly. Here they do not: `inline-size` sets the
   CONTENT box (the element computes `content-box`), so 44 + 8.5 + 8.5 rendered
   61.03 × 61.03 — [MEASURED] before this line. Zeroing the padding reproduces
   the design's box exactly, and the 26px glyph still sits centred with ~9px of
   space each side, which is what the design's own note describes. */
.chumuk-header__actions .wc-block-customer-account__link {
	flex: none;
	padding: 0;
	inline-size: var(--chumuk-header-action-box);
	block-size: var(--chumuk-header-action-box);
	justify-content: center;
}

/* ⚠️ WOOCOMMERCE'S OWN MARKUP, sized and coloured only — never edited. The
   button reset is needed because Woo ships this as a bare <button> and the
   theme's own button styling would otherwise reach it. */
.chumuk-header__actions .wc-block-mini-cart__button {
	background: none;
	border: 0;
	padding: 0;
	color: inherit;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	flex: none;
	justify-content: center;
	inline-size: var(--chumuk-header-cart-box);
	block-size: var(--chumuk-header-cart-box);
}

.chumuk-header__actions .wc-block-mini-cart__quantity-badge {
	display: inline-flex;
	align-items: center;
}

/* 🔴 THE BREAKPOINT MOVES 600 → 640.
   core's overlay breakpoint is 600. [MEASURED] that is too low for this header:
   the nav row wraps to TWO rows between 600 and ~639 and only fits on one line
   from 640 up, so the burger has to take over below 640.

   ⚠️ NO `!important` AND NO SELECTOR STRENGTHENING IS NEEDED, and the arithmetic
   is the reason: core's container rule is (0,3,0) and its open-button rule
   (0,2,0); scoping with `.chumuk-header` makes these (0,4,0) and (0,3,0), and
   style.css is enqueued after core's navigation sheet, so they win inside this
   range on specificity alone.

   ⚠️ There is deliberately NO `min-width: 640` companion. Above 639 core's own
   `min-width: 600` rules resume unchanged, so there is nothing to maintain in
   two places. */
@media ( max-width: 639px ) {
	.chumuk-header .wp-block-navigation__responsive-container:not(.is-menu-open) {
		display: none;
	}

	.chumuk-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}
}

/* THE HAMBURGER AND THE CLOSE X ARE 44px TARGETS. core renders both at the
   glyph's own 24 × 24 — the last controls on the page under the minimum. The
   GLYPH stays 24 (core's two bars, untouched); the BOX becomes 44, matching the
   account link at the other end of the row. */
.chumuk-header .wp-block-navigation__responsive-container-open,
.chumuk-header .wp-block-navigation__responsive-container-close {
	inline-size: var(--chumuk-header-action-box);
	block-size: var(--chumuk-header-action-box);
	align-items: center;
	justify-content: center;
}

/* THE OVERLAY GROUND — option 1a, the header's own cyan. core's
   `:not(.has-background)` default paints the open menu #fff with #000 ink: a
   full-screen off-brand white arriving over a cyan header. Cyan makes the menu
   read as the header EXPANDING rather than as a new surface.

   🔴 THE DESIGN SUGGESTS SETTING THE BLOCK ATTRIBUTE INSTEAD, AND THAT IS WRONG
   HERE — CHECKED, NOT ASSUMED. Giving the navigation block `backgroundColor`
   would emit `has-background` on the <nav> itself, and core paints the nav
   element with it at every width. On the front page the header is TRANSPARENT
   over the hero (`body.home.chumuk-hero-behind-header`), so a cyan nav element
   would draw a cyan strip across the hero artwork at all four variants. The
   attribute route is right for the actions' blockGap (which is a layout value
   core owns) and wrong for this one (which is a state core only applies inside
   the overlay). The override is scoped to the open overlay and reaches nothing
   else.

   🔴 CONTRAST, STATED PLAINLY BECAUSE IT IS THE COST OF THIS OPTION: white on
   cyan is 2.23:1. The LINKS are fine — at 32px they are large-scale text and
   clear the 3:1 bar. The BURGER AND CLOSE X DO NOT: icons need 3:1 as non-text
   contrast with no large-size exemption, and sizing cannot fix it. They stay
   white because that is the header's EXISTING white-on-cyan condition, shared
   with the account and cart icons beside them — not a new failure introduced
   here. The owner chose 1a knowing this. DO NOT "fix" it. */
.chumuk-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	background-color: var(--wp--preset--color--cyan);
}

.chumuk-header .wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	color: var(--wp--preset--color--white);
}

/* 🔴 THE OVERLAY'S GUTTER — core's own padding rule computes 0 here, so without
   this every menu item sits flush against the viewport edge. core writes it as a
   four-side shorthand:
     padding: clamp(1rem, var(--wp--style--root--padding-top), 20rem) … × 4
   theme.json defines `--wp--style--root--padding-left` and `--right` but NOT
   `--padding-top` / `--padding-bottom`. An empty `var()` makes `clamp(1rem, ,
   20rem)` invalid, and an invalid value in a SHORTHAND discards the WHOLE
   declaration — so one missing token zeroes all four sides, not just the top.

   ⚠️ Fixed by overriding the padding, NOT by defining the two missing root
   tokens: those are global and other core rules read them. The inline padding is
   the site gutter, which is what the closed header's nav already sits on, so the
   open menu's items align to the same content edge as the header above them.
   core's close button is positioned against the dialog, which now inherits that
   inset, so it lands on the gutter beside the cart icon with no extra rule. */
.chumuk-header .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	padding-inline: var(--wp--custom--gutter);
	padding-block: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
}

/* The open menu's own type: the heading face at 32px on 56px rows,
   hairline-divided. The row height is the tap target, and it is 56 rather than
   the 44 minimum because a full-width menu row should feel like a row, not a
   button. */
.chumuk-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	inline-size: 100%;
}

.chumuk-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
	inline-size: 100%;
	border-block-end: 1px solid rgb( 255 255 255 / 0.24 );
}

.chumuk-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:last-child {
	border-block-end: 0;
}

.chumuk-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	display: flex;
	align-items: center;
	min-block-size: 56px;
	inline-size: 100%;
	font-family: var(--wp--custom--font-heading);
	font-weight: 500;
	font-size: 32px;
	letter-spacing: -0.02em;
	color: var(--wp--preset--color--white);
}

/* --------------------------------------------------------------------------
   C37 — page banner

   The height token is declared once in :root above so all three templates
   match (c37: "define once as a token").

   🔴 The banner is a FLAT `pink-soft` band on all three surfaces — checklist
   §10.61 r2, narrowed to this one file by §10.62 r3. `useFeaturedImage` is
   DROPPED: c37 cannot guarantee AA behind an author-chosen image (measured
   worst composited pixel #80747E → 2.80:1 at the spec's 50 % overlay). The
   AA floor for an arbitrary image is dimRatio ≥ 66 %, at which the image is
   all but invisible — and the comp draws this band flat anyway. All three
   covers now ship dimRatio: 100, so the old no-image fallback rule
   (.chumuk-banner:not(:has(.wp-block-cover__image-background))) is dead code
   and has been removed with it. If image banners are ever wanted, 66 % is the
   recorded floor and it is a NEW decision — do not re-litigate below it.
   -------------------------------------------------------------------------- */
.chumuk-banner {
	min-height: var(--chumuk-banner-min-height);
}

/* Full-bleed, only in the template-part case. On `page` the banner arrives via
   parts/page-banner.html, and core's template-part wrapper <div> sits between
   the root-padded <main> and the alignfull cover — so core's own
   `.has-global-padding > .alignfull` negative-margin rule cannot reach it and
   the banner rendered 936 px inside a 1040 px viewport (measured). On `404`
   and `search` the cover is a direct child of <main> and core already handles
   it, which is why this selector names the wrapper instead of the class alone:
   applied to both, it would double the offset. */
.has-global-padding > .wp-block-template-part > .chumuk-banner {
	margin-left: calc( var(--wp--style--root--padding-left) * -1 );
	margin-right: calc( var(--wp--style--root--padding-right) * -1 );
}

/* --------------------------------------------------------------------------
   chumuk/breadcrumbs — the C37 core-block gap

   The separator is CSS generated content, so no punctuation string enters the
   markup. The anchors take the global in-content underline (theme.json
   styles.elements.link); nothing here touches text-decoration, because raising
   a link rule in style.css is exactly the trap in 00-conventions.md §3.4.
   -------------------------------------------------------------------------- */
.wp-block-chumuk-breadcrumbs ol {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	padding: 0;
	list-style: none;
}

.wp-block-chumuk-breadcrumbs li + li::before {
	content: "/";
	margin-right: var(--wp--preset--spacing--20);
}

/* --------------------------------------------------------------------------
   C16 — footer SKELETON (structure + ground only; content is build step 10)

   🔴 All footer text is `ink`, never white [§10.30] — the footer is the site's
   largest cyan surface. That is carried by the block's textColor attribute and
   by theme.json's heading/link element colours, not by a rule here.

   Rule R5 [§14.0]: no footer column gets a fixed width — Bengali strings run
   longer — so the columns keep core's equal-width default and no width is
   declared below.
   -------------------------------------------------------------------------- */
.chumuk-footer__base {
	border-top: 1px solid var(--chumuk-border-hairline);
	padding-top: var(--wp--preset--spacing--50);
}

/* ==========================================================================
   COMPONENT LAYER — build step 3 (C04 hero, C01 marquee)

   c04-hero.md · c01-marquee.md · d-flavour-meta.md

   Same invariant as the step-2 layer above: no hex, no font stack, and every
   size read by its EMITTED token name. The per-flavour ground and ghost tint
   are the one exception in kind, not in discipline — they are term-meta DATA,
   emitted as custom properties by chumuk-core's inc/hero-data.php, never
   written here.
   ========================================================================== */

/* --------------------------------------------------------------------------
   C02 header — the TRANSPARENT-OVER-HERO state [checklist §10.34 d.1]

   🔴 SCOPED TO body.home, AND LAYERED OVER step 2's solid base — step 2's rule
   above is untouched, so every non-front template still paints cyan from the
   first frame. This state also requires `.chumuk-hero-behind-header`, which
   only view.js adds.

   WHY THE STATE IS JS-GATED. A CSS-only transparent header would stay
   transparent after the hero scrolls away whenever JS is unavailable,
   stranding header text over the C08 photographic band whose contrast cannot
   be measured. Solid-without-JS loses an effect; transparent-without-JS loses
   legibility. See the build report's 🔴 D2.

   THE OVERLAP IS A GRID, NOT A NEGATIVE MARGIN. Putting the header and <main>
   in the same grid row makes them overlap with no magic number for the
   header's height — and `position: sticky` keeps working, because a grid
   item's containing block is its grid area, which here spans all of <main>.
   -------------------------------------------------------------------------- */
body.home .wp-site-blocks {
	display: grid;
	grid-template-columns: 100%;
}

/* ⚠️ BOTH row AND column must be explicit. `grid-row: 2` alone does not stack
   them: auto-placement refuses to overlap two auto-column items, so it invents
   an implicit SECOND COLUMN and the hero lands beside the header at a fraction
   of the page width. Measured at build step 3 — `grid-template-columns`
   resolved to `1040px 344.859px`. Naming the column is the fix. */
body.home .wp-site-blocks > header.wp-block-template-part,
body.home .wp-site-blocks > main {
	grid-row: 2;
	grid-column: 1;
}

body.home .wp-site-blocks > main {
	min-width: 0;
}

/* 🔴 The header wrapper STRETCHES over the whole grid area — which is all of
   <main> — because that tall box is exactly what step 2's `position: sticky`
   needs to travel inside. Overlapping it onto the hero therefore lays an
   invisible, full-height click shield across the page: measured at build step
   3, every click on the variant switcher was intercepted by
   `<header class="wp-block-template-part">`, and NO screenshot shows it.

   So the wrapper passes pointer events through and the header itself takes
   them back. Only the visible bar stays interactive; the hero underneath is
   reachable again. */
body.home .wp-site-blocks > header.wp-block-template-part {
	pointer-events: none;
}

body.home .wp-site-blocks > header.wp-block-template-part > .chumuk-header {
	pointer-events: auto;
}

/* d-flavour-meta.md field 13 — the per-variant header ink, delivered as a body
   class by chumuk-core (server-rendered for the default variant, swapped by
   view.js on a switch). Only the two MEASURED keywords exist, and each maps to
   a palette token here, so no colour value travels through PHP or JS.

   🔴 This is the ONE measured exception to 00-conventions.md §3.1's ink rule
   (§3.2): Beetroot Blast's `#C72153` ground gives ink 2.24:1 ❌ and white
   5.57:1 ✅, so THAT variant alone takes white. Do not "correct" it. */
/* [MEASURED] the comp's promo strip is rows 0-49 — 50 px — with its label ink
   centred at y 18-31 (cap 14, the same cap the build draws, so the type size is
   already right). The build wrapped a 28 px line box in `--wp--preset--spacing--30`
   = 12 px and measured 52. 11 px is not a step on the spacing scale, so the value
   is held here as a measured component value rather than invented as a preset, and
   the block's inline padding was removed so this can own it.
   ⚠️ THIS IS THE PAGE'S VERTICAL DATUM. Everything below the strip carried the
   same 2 px offset, which is why comp-to-live y mapping needed a +2 correction. */
.chumuk-promo {
	padding-block: 11px;
}

body.chumuk-header-ink--ink {
	--chumuk-header-ink: var(--wp--preset--color--ink);
}

body.chumuk-header-ink--white {
	--chumuk-header-ink: var(--wp--preset--color--white);
}

/* THE WORDMARK IS INLINE SVG, NOT AN <img>, FOR ONE REASON: `currentColor`. The
   header sits on cyan today and on the hero's own ground on the home page, so the
   mark has to take the header's ink the way the action icons already do — an
   <img> cannot, and would need a second white PNG per ground.
   The 132 × 80 box is the PNG's measured box, kept so nothing reflows.
   ⚠️ TRANSCRIBED from header-and-promo-bar.dc.html, both rules unchanged [TASK D].
   ⚠️ THE FALLBACK IS WHY THE INK-FLIP BLOCK BELOW NEEDS NO NEW SELECTOR.
   `--chumuk-header-ink` is declared only by `body.chumuk-header-ink--ink|--white`,
   which the homepage sets and the inner pages do not; off the homepage the `white`
   fallback resolves against the header's cyan. Adding `.chumuk-header__logo a` to
   the flip's selector list would have been a second way to say the same thing. */
.chumuk-header__logo a {
	color: var( --chumuk-header-ink, var( --wp--preset--color--white ) );
	display: inline-block;
}

.chumuk-header__mark {
	display: block;
	inline-size: 132px;
	block-size: auto;
}

/* The preset background class WordPress emits carries `!important`
   (`.has-cyan-background-color{background-color:…!important}`), so nothing but
   `!important` can lift it — a specificity bump alone cannot. Declared here
   rather than by removing the block's backgroundColor attribute, because that
   attribute is what guarantees the solid default on every other template. */
body.home.chumuk-hero-behind-header .chumuk-header {
	background-color: transparent !important;
	border-bottom-color: transparent;
}

/* The ink flip. Nav links and the WooCommerce action icons both resolve through
   `currentColor`, which is why step 2's icon rule needs no change. The nav
   anchor needs the explicit hop because theme.json's own navigation colour is
   emitted at (0,1,0) — 00-conventions.md §3.4's specificity trap, in colour
   form. */
body.home.chumuk-hero-behind-header .chumuk-header,
body.home.chumuk-hero-behind-header .chumuk-header .wp-block-navigation-item__content,
body.home.chumuk-hero-behind-header .chumuk-header .chumuk-header__actions a {
	color: var(--chumuk-header-ink);
}

/* --------------------------------------------------------------------------
   C04 — hero

   ONE STRUCTURE, FOUR DATA SETS. There is exactly one set of rules below and
   no per-flavour branch: everything that differs is a custom property the
   block emits from term meta.

   🔴 NO FIXED HEIGHTS. The band reserves space with `min-height` and grows
   with its content. Because all four variants share the same `min-height` and
   the same background aspect box, and the card is far shorter than the band,
   switching cannot change the hero's height — which is what makes CLS zero
   without any variant contributing height while `hidden`.
   -------------------------------------------------------------------------- */
.chumuk-hero {
	/* The hero band is y 50–1080 = 1030 px at the comp's native 1920
	   (design-tokens.md §2.5), i.e. 53.65vw. The ceiling is that measurement;
	   the floor is [DERIVED] — at 375 px, 53.65vw is 201 px, far too short for
	   the card, the jar and the switcher to coexist. */
	--chumuk-hero-min-height: clamp( 560px, 53.65vw, 1030px );
	/* [MEASURED] the comp's hero card sits with its BOTTOM 154 px above the hero's
	   bottom edge — card box y 704-925 inside a hero band y 50-1079, so
	   154 / 1030 = 0.1495 of hero height [§10.98 / C].
	   🔴 DECLARED HERE, NOT ON `:root`, AND THAT IS LOAD-BEARING. It was first
	   put on `:root`, where `--chumuk-hero-min-height` does not exist — the
	   `calc()` was then invalid at computed-value time and `margin-block-end`
	   silently fell back to its initial 0, which MEASURED as a card flush to the
	   hero's bottom edge. A var() that resolves nowhere fails quietly; it does
	   not warn. */
	--chumuk-hero-card-bottom: calc( var(--chumuk-hero-min-height) * 0.1495 );

	/* 🔴 THE HERO JAR'S PLACEMENT — [MEASURED] 2026-08-24 [checklist §10.128].
	   The build centred the jar in the band and sat it on the band's bottom
	   edge; the comp does neither.

	   HOW THESE WERE OBTAINED. The comp and the build draw the SAME artwork at
	   the SAME -12deg tilt, so the tilted silhouettes differ by a similarity
	   transform only. Per-row horizontal chords of the jar were extracted from
	   both (segmenting magenta body + neutral metal/glass against the flat
	   rgb(234,138,184) ground) and a (scale, offset) fit was run over the LID
	   RAMP AND UPPER BODY ONLY — comp y 215-445 — which is the region the
	   mountain does not occlude in either image.
	     scale  0.9825   rms width residual 2.59 px over 230 rows
	     dx     +69.78 px at 1920  ->  69.78 / 1920 = 0.036344 = 3.6344vw
	     dy     -184.13 px at 1920 ->  184.13 / 1030 = 0.178767 of hero height

	   🔴 NO UNTILTING WAS NEEDED FOR THE SCALE, AND THAT IS THE POINT OF FITTING
	   TWO IMAGES RATHER THAN ONE. A horizontal chord across a rectangle rotated
	   by theta measures w / cos(theta); both images carry the SAME theta, so the
	   1/cos factor is identical in both and CANCELS in the ratio. Deriving a
	   layout box from the comp's tilted ink alone — which is what the earlier
	   attempt did, and what build-fix-23 recorded as NOT VERIFIED — has to undo
	   that expansion against an occluded base, and returned 510 px for a jar
	   that is plainly narrower.

	   🔴 AND NO UNTILTING IS NEEDED FOR THE POSITION EITHER, BECAUSE THE ROTATION
	   ORIGIN IS `bottom center`: that point is invariant under the transform, so
	   the untilted box's bottom-centre IS the rendered jar's bottom-centre and
	   the offsets above apply to it directly.

	   ✅ CHECKED AGAINST A FEATURE 600 px OUTSIDE THE FITTING WINDOW. The jar's
	   tan base rim, predicted from the fit at comp band-relative (1016.0, 808.0),
	   MEASURES (1016.5, 812.0) — 0.5 px in x, 4.0 px in y. Its width ratio
	   292/297 = 0.983 reproduces the 0.9825 scale independently.

	   ⚠️ THE 1.75 % SCALE CHANGE IS NEAR THE MEASUREMENT FLOOR and is applied
	   because two independent features agree on it, not because it is large. The
	   POSITION change is not marginal: 3.6 % of band width and 17.9 % of band
	   height.

	   ⚠️ MEASURED AT 1920 ONLY. The comp is a single 1920 export, so the way this
	   offset should behave at other widths is NOT VERIFIED — see the jar/mountain
	   note on `.chumuk-hero__jar`. Both offsets are expressed proportionally so
	   the jar and its displacement scale together rather than drifting apart. */
	--chumuk-hero-jar-scale: 0.9825;
	--chumuk-hero-jar-shift-x: 3.6344vw;
	--chumuk-hero-jar-lift: calc( var(--chumuk-hero-min-height) * 0.178767 );

	/* Card box, [MEASURED] from pink-new-3.png: fill x 140–660 (520 px), y
	   700–915, corner radius ~20 px. The width is held as a vw range so the
	   card keeps its proportion of the 1640 content box rather than pinning to
	   one viewport.
	   🔴 THE RADIUS IS NO LONGER DECLARED HERE. --chumuk-hero-card-radius was
	   retired by checklist §10.68 r2 and renamed --chumuk-card-radius-lg at :root,
	   because the same 20 px is now the C06 ingredient card panel's radius too and
	   a hero-scoped custom property cannot be read outside the hero. The VALUE is
	   unchanged; only the name and the scope moved. */
	--chumuk-hero-card-max: clamp( 260px, 34vw, 540px );

	/* 🔴 THE HERO'S OWN GUTTER WAS 44 px WIDE OF THE CONTENT COLUMN, AND THE
	   TOKEN IT USED CAN NEVER REACH IT. [MEASURED] 2026-08-25.

	   `settings.layout.contentSize` is 1640px, so core's constrained layout puts
	   every ordinary band's content at (1920 - 1640) / 2 = 140 px at the comp's
	   width. The comp agrees on four independent features: nav "Why Chumuk"
	   ink x 141, hero card fill x 140, hero social ink x 140, and the switcher
	   row's right edge at 1779 — a 141 px right gutter.

	   `--wp--custom--gutter` is `clamp(20px, 5vw, 140px)`. The 140px ceiling is
	   the right number and is never reached: 5vw is 96px at 1920 and would need
	   a 2800px viewport to hit it. The three hero elements that pad by the
	   gutter — card, social row, switcher — therefore sat at 96 while the nav
	   above them sat at 140.

	   ⚠️ THE GUTTER TOKEN ITSELF IS NOT CHANGED. It is the root padding for the
	   whole document (theme.json `styles.spacing.padding`), so widening it would
	   move every band at every width, and only 1920 is measurable. This resolves
	   to the content-column edge WHEN the column is capped and to the gutter
	   otherwise, so nothing below ~1822px moves at all.

	   `100%` resolves against the hero's own grid area — `grid-template-columns:
	   100%` on a full-bleed band, i.e. exactly the width core divides. Using the
	   grid area rather than `100vw` also keeps a classic scrollbar out of the
	   arithmetic. */
	--chumuk-hero-inset: max( var(--wp--custom--gutter), calc( ( 100% - 1640px ) / 2 ) );

	/* Card padding, [MEASURED] from pink-new-3.png by two independent features:
	   the CTA pill's bottom edge at y 905 against the card's bottom edge at 925,
	   and the body copy's ink left at x 161 against the card's fill left at 140
	   less the "T" left side bearing. Both give 20. The build shipped
	   `--wp--preset--spacing--50` = 24. No spacing preset sits within 2 % of 20
	   (16 and 24 are both 20 % away), so it is held here as a component value at
	   the comp's width rather than registered as a scale step. */
	--chumuk-hero-card-pad: 20px;

	/* 🔴 THE SWITCHER, [MEASURED] 2026-08-25 — the earlier figures were estimates
	   and both were wrong.

	   Slot pitch is read off the ONE unambiguous feature in the row: the selected
	   slot's 20 %-white plate is a clean 120 px run at x 1520-1639 with 20 px of
	   bare ground on each side, so pitch = 140, slot = 120, gap = 20. Four slots
	   from x 1240 put the row's right edge at 1779 — the content column's right
	   edge, which is how the row is anchored.

	   The jar is 70 px wide and 141 px tall: 70 / 141 = 0.496 against the source
	   asset's 576 / 1163 = 0.495, i.e. THE COMP DRAWS THE WHOLE JAR AT ITS NATURAL
	   ASPECT. The build was requesting the `thumbnail` size — 150x150 HARD CROP —
	   so it drew a square slice of a jar three times taller than it is wide.

	   Plates: every slot carries one, not just the selected one. Unselected is
	   120 x 50 and selected is 120 x 160, both bottom-aligned at comp y 1029, and
	   both are 20 % white — the same veil as the hero card, NOT the 50 % the
	   build used. */
	--chumuk-hero-jar-size: clamp( 52px, 3.6458vw, 70px );
	--chumuk-hero-slot-gap: 20px;
	--chumuk-hero-slot-pad: 25px;
	--chumuk-hero-plate-h: 50px;
	--chumuk-hero-plate-h-selected: 160px;
	--chumuk-hero-jar-foot: 9px;

	/* [MEASURED] the social row and the switcher row both bottom out at comp
	   y 1030 in a hero band that ends at 1080 — 50 px, not the 80 px
	   `--chumuk-section-pad` resolves to at this width. */
	--chumuk-hero-row-bottom: 50px;

	/* ⚠️ ~~[MEASURED] the CTA pill's fill is comp y 866-905. --chumuk-hero-cta-h:
	   40px~~ RETIRED at §10.192 — the height now falls out of core's padding, so
	   the token has no reader left. Removed rather than left declared. */

	position: relative;
	display: grid;
	grid-template-columns: 100%;

	/* display-1 is 260 px at 1920 and the ghost word must bleed past the 1640
	   content box (it spans nearly the full comp width). `clip` contains that
	   bleed without creating a scroll container — `hidden` would let a focused
	   child scroll the box. */
	overflow-x: clip;
}

/* Explicit placement, for the same reason the header/main pair needs it: the
   social row and the switcher below are explicitly in row 1, and an auto-placed
   stage would be pushed to row 2 — which rendered the switcher and the social
   icons ABOVE the artwork, inside the header band. Measured at build step 3. */
.chumuk-hero__stage {
	grid-row: 1;
	grid-column: 1;
	display: grid;
	grid-template-columns: 100%;
}

.chumuk-hero__variant {
	/* Fallbacks are the DEFAULT variant's documented palette tokens, so a
	   missing meta value degrades to Himalayan Revive rather than to nothing.
	   The live values arrive per variant from term meta. */
	--chumuk-hero-ground: var(--wp--preset--color--pink);
	--chumuk-hero-ghost: var(--wp--preset--color--pink-ghost);

	grid-row: 1;
	grid-column: 1;
	position: relative;
	display: grid;
	grid-template-columns: 100%;
	min-height: var(--chumuk-hero-min-height);

	/* Painted before the artwork decodes, so there is no white flash on the LCP
	   image and no colour shift when a lazy variant is first shown. */
	background-color: var(--chumuk-hero-ground);
}

/* 🔴 `display: grid` above OVERRIDES the UA's `[hidden] { display: none }`, which
   is a bare type-less rule — so without this line all four variants paint on top
   of one another and four `<h1>` elements are exposed. Measured at build step 3:
   the rendered hero showed Jira's card over Himalayan's and Natural's ghost
   words simultaneously.

   This restores the `hidden` attribute's own semantics; it does NOT replace them
   with a CSS-only hiding mechanism. `hidden` remains the single source of truth
   for which variant is exposed (§10.33 c.4). */
.chumuk-hero__variant[hidden] {
	display: none;
}

/* Every layer occupies the same single grid cell; only alignment and z-index
   separate them. This is what puts the ghost word BEHIND the jar without
   taking either out of flow. */
.chumuk-hero__bg,
.chumuk-hero__ghost,
.chumuk-hero__jar,
.chumuk-hero__card {
	grid-row: 1;
	grid-column: 1;
}

.chumuk-hero__bg {
	z-index: 0;
	align-self: stretch;
	justify-self: stretch;
	overflow: hidden;
}

.chumuk-hero__bg img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

/* 🔴 DECORATIVE, not a heading, and aria-hidden in the markup [§10.32]. Its low
   tonal contrast against the ground is therefore correct and carries no WCAG
   requirement. DO NOT DARKEN IT — the tint is a measured ΔE2000 separation
   from its own ground (d-flavour-meta.md field 12), and darkening it breaks
   both the effect and the acceptance criterion. */
.chumuk-hero__ghost {
	z-index: 1;
	align-self: center;
	justify-self: center;
	color: var(--chumuk-hero-ghost);
	font-family: var(--wp--custom--font-heading);
	font-size: var(--wp--preset--font-size--display-1);
	line-height: 1;
	white-space: nowrap;
	pointer-events: none;
	/* 🔴 THE COMP CENTRES THE CAPS, NOT THE LINE BOX. [MEASURED]: the comp's
	   ghost caps ink y 474-656, centre 565.0, in a hero band y 50-1079 whose
	   centre is 565.0 — exact. `align-self: center` centres the LINE BOX, and
	   because the face's ascent and descent are not symmetric about the cap
	   band the caps then sit 15.5 px low (live ink y 491-674 against a band
	   centre of 567). 15.5 / 260 = 0.0596em, so it is expressed against the
	   font size and survives display-1 being fluid.
	   ⚠️ The ink WIDTH is not matched and deliberately so: comp 1423 px against
	   1394 at an identical 183/184 px cap height. Same size, different face —
	   §10.113 records that the comp's export substituted the serif, so its
	   advance widths are not Playfair's and tracking derived from them would be
	   wrong. The cap height, which is what a size measurement is, agrees. */
	translate: 0 -0.0596em;
	/* The word's LENGTH varies per flavour — "BEETROOT" vs "JIRA" — so neither
	   its size nor its tracking may be tuned to one word (design-tokens.md §2.2
	   display-1, checklist §10.33). display-1 is fluid; tracking is held as a
	   ratio of the font size rather than a px value. */
	letter-spacing: -0.02em;
}

.chumuk-hero__jar {
	z-index: 2;
	align-self: end;
	justify-self: center;
	display: flex;
	align-items: flex-end;
	pointer-events: none;
	/* 🔴 THE COMP DOES NOT CENTRE THE JAR AND DOES NOT SIT IT ON THE BAND'S
	   BOTTOM EDGE [§10.128]. `justify-self: center` + `align-self: end` put its
	   centre at exactly 0.50000 of band width and its base at 1.00000 of band
	   height; the comp measures 0.53634 and 0.82124.

	   `translate` RATHER THAN MARGINS, DELIBERATELY. This layer is a decorative,
	   `pointer-events: none` overlay sharing one grid cell with the ghost, the
	   card and the background, so a visual offset cannot reflow anything — and
	   MEASURED, every band height on the page is unchanged by it. Margins would
	   have to fight `justify-self: center`, which resolves a start margin as
	   HALF the shift and reads as an arithmetic error to the next person.

	   ⚠️ THE MOUNTAIN CANNOT FOLLOW, AND IT DOES NOT NEED TO. The mountain is
	   painted INTO the per-flavour background photograph (verified by hiding
	   `.chumuk-hero__bg`: the mountain goes with it), so it is not a movable
	   layer. It does not need to be: MEASURED, the mountain's base row spans
	   x 476-1479 mid 977.5 in the comp and x 475-1480 mid 977.5 in the build —
	   the same to within 1 px. The background is already placed correctly and
	   the jar was the only thing out of position, so moving the jar alone
	   REPRODUCES the comp's composition rather than breaking it. */
	translate: var( --chumuk-hero-jar-shift-x ) calc( -1 * var( --chumuk-hero-jar-lift ) );
}

/* --------------------------------------------------------------------------
   THE HERO JAR'S BOX AND TILT — checklist §10.98 [A2 + B]

   THE BOX. `width/height: auto` + `max-*` already gave all four flavours an
   identical box, because the four attachments share intrinsics (1707 x 2560)
   and are width-bound at every width 320-1920 — MEASURED live at 1920:
   460 x 690 for the active variant, ratio 0.6667 = the canvas ratio. The
   explicit `inline-size` + `aspect-ratio` below states that invariant instead
   of leaving it to emerge, so an asset with a different intrinsic ratio can
   never re-introduce the jitter. `object-fit: contain` + `bottom center` pin
   how the pixels sit inside it.
   ⚠️ THE BOX IS *NOT* DERIVED FROM THE COMP, AND THAT IS A LIMITATION, NOT A
   CHOICE. The comp's hero jar has its base occluded by the mountain, so its
   full length is not visible; a colour mask cannot separate jar from mountain
   (both are dark against the pink), and the oriented fit returned a 510 px
   "width" for a jar that is plainly narrower. The existing clamp is retained
   because Task A's requirement is INVARIANCE ACROSS FLAVOURS, which it already
   satisfies and which is measurable; the absolute size is recorded NOT VERIFIED
   in build-fix-23 §6.

   THE TILT: -12deg. MEASURED on the comp, not eyeballed. The jar's AXIS OF
   SYMMETRY (per-row midpoint between the silhouette edges, which cancels the
   perspective convergence of a photographed cylinder) was fitted over three
   independent y-bands: 360-520 -> 12.090deg, 370-560 -> 12.095deg,
   350-570 -> 11.986deg, with rms residuals of 1.37 / 1.26 / 1.28 px.
   ⚠️ Fitting the SILHOUETTE EDGES instead gives 11.50deg (left) and 12.68deg
   (right) — they disagree by 1.2deg because a cylinder's edges converge. The
   axis is the right feature; the edges are not.
   SIGN: the midline moves RIGHT as y increases (x 916.5 at y=360 -> 950.0 at
   y=519), so the jar's top sits LEFT of its base = COUNTER-CLOCKWISE = a
   NEGATIVE CSS angle.
   🔴 THE TILT IS A TRANSFORM, NEVER BAKED INTO THE PNG. A transform does not
   affect layout, so the box above is untouched; re-exporting tilted artwork
   would change every file's alpha bounding box and destroy the invariance
   Task A exists to protect.
   ⚠️ ONE SHARED ANGLE, and the comp CANNOT confirm that is right: it draws
   only ONE flavour in the hero (Himalayan Revive). A single angle is the
   deliberate default per the brief — a per-flavour angle would be one more
   invariant that can drift. Recorded as NOT VERIFIED.
   ⚠️ The tilt is the FEATURED jar's only. The comp's four switcher thumbnails
   are upright: thumb 2's axis measures -3.17deg (rms 2.55 px on a 73-row
   sample) against the featured jar's +12.09deg. The rule below is scoped to
   `.chumuk-hero__jar img` and does not reach `.chumuk-hero__variant-jar`.
   -------------------------------------------------------------------------- */
.chumuk-hero__jar img {
	display: block;
	/* ⚠️ THE CLAMP'S SHAPE IS PRESERVED AND ONLY SCALED [§10.128]. The comp is a
	   single 1920 export and establishes ONE point on this curve; re-deriving the
	   whole clamp from it would replace a measured invariance with a guess at
	   every other width. Multiplying keeps the existing behaviour and reproduces
	   the comp where the comp actually says something: 460 * 0.9825 = 451.95. */
	inline-size: calc( clamp( 180px, 26vw, 460px ) * var( --chumuk-hero-jar-scale ) );
	block-size: auto;
	aspect-ratio: var( --chumuk-hero-jar-aspect );
	max-block-size: calc( var(--chumuk-hero-min-height) * 0.82 );
	object-fit: contain;
	object-position: bottom center;
	transform: rotate( var( --chumuk-hero-jar-tilt ) );
	transform-origin: bottom center;
}

/* ⚠️ THIS COMMENT WAS FALSE AND IS CORRECTED, NOT DELETED. It described the
   card as it shipped before §10.126, and §10.126 reversed exactly that decision
   — so a reader following it would have "restored" the state the owner ruled
   against. Verified against the rule below before rewriting.

   ~~🔴 The card's fill is --chumuk-veil-card, 50 % white [checklist §10.37]. The
   veil is what makes `ink` pass on all four grounds — Beetroot is the worst
   case at 5.23:1 and 45 % was tested and rejected at 4.76:1. Do not thin it.
   All card text is plain `ink`; the card carries NO per-variant ink field.~~

   ~~🔴 CURRENT [§10.126]: the fill is --chumuk-hero-card-veil, 20 % white, and
   all card text is `white`. That is the DESIGN's treatment, applied by owner
   ruling 1, and it FAILS AA on all four grounds — worst 1.80 / 4.02 / 1.19 /
   1.10, flagged for decision before launch.~~ SUPERSEDED at §10.192 — the
   decision it was flagged for has been taken, in the finalised homepage.

   🔴 CURRENT [§10.192]: the fill is still --chumuk-hero-card-veil, but that
   token is now `ink` at 0.68, not white at 0.20. The alpha is SOLVED for the
   white copy: white needs its ground <= 118.6 per channel for 4.5:1, and
   #343434 at alpha a over a worst-case PURE WHITE region of the photograph
   gives 255 - 203a <= 118.6, i.e. a >= 0.672. So this holds on all four
   photographs by construction rather than on the one that was sampled — see
   the measured ratios in build report 73. The card still carries no
   per-variant ink field, which is the one clause above that survives. */
.chumuk-hero__card {
	z-index: 3;
	/* 🔴 WAS `align-self: center`, which nothing in this file defended — it read
	   as an unexamined default, and MEASURED live it put the card at exactly
	   50.00 % of hero height. The comp puts it far lower: card box y 704-925 in
	   a hero band y 50-1079, centre at 74.22 % — 249 px lower at this hero
	   height. Anchored from the BOTTOM rather than by centre or percentage,
	   because the comp's composition is bottom-referenced (the card sits beside
	   the mountain, which is itself anchored to the hero's base) and because a
	   bottom offset is insensitive to the card's own height, which differs
	   between comp and build (222 px vs 238 px) purely from copy and font.
	   Live hero height measures 1030 px against the comp's 1030 px, so the
	   fraction maps 1:1. ⚠️ The narrow-width override further down keeps
	   `align-self: start` and is deliberately NOT touched. */
	align-self: end;
	margin-block-end: var( --chumuk-hero-card-bottom );
	justify-self: start;
	max-width: var(--chumuk-hero-card-max);
	margin-inline-start: var(--chumuk-hero-inset);
	padding: var(--chumuk-hero-card-pad);
	border-radius: var(--chumuk-card-radius-lg);
	/* 🔴 THE DESIGN'S TREATMENT, AND IT FAILS AA ON EVERY GROUND — APPLIED
	   DELIBERATELY AND RECORDED, NOT SILENTLY SUBSTITUTED [§10.126].
	   ~~background-color: var(--chumuk-veil-card); color: ink~~ — the build shipped
	   50 % white with `ink` text because a thinner veil measured 4.76:1 on Beetroot
	   at §10.37. 🔴 THAT FIGURE WAS FOR INK ON A WHITE VEIL AND DOES NOT DESCRIBE
	   THIS TREATMENT — a different colour on a different ground — so it was not
	   reused.

	   MEASURED, white text on white@0.20, pixel-sampled over the four real hero
	   photographs (a colour-walk cannot see a photograph):
	     natural-bliss     worst 1.80  mean 1.96  100.0 % of ground pixels fail
	     beetroot-blast    worst 4.02  mean 4.37   80.6 % fail
	     himalayan-revive  worst 1.19  mean 2.22   97.2 % fail
	     jira-twist        worst 1.10  mean 2.02   99.5 % fail

	   ⚠️ AND IT IS NOT THE PHOTOGRAPHS' FAULT. On the COMP'S OWN flat pink ground
	   the same treatment measures 1.98:1 computed and 1.79:1 sampled under the
	   heading. The design's hero card fails AA on the design's own artefact, by a
	   factor of about 2.4. FLAGGED FOR DECISION BEFORE LAUNCH. */
	background-color: var(--chumuk-hero-card-veil);
	/* 🔴 ~~backdrop-filter: blur( 12px )~~ — THE COMP DOES NOT BLUR BEHIND THIS
	   CARD. Sampled at 1:1 over the mountain artwork the card overlaps (comp
	   x 490-660, y 760-925), the crystal edges behind the comp's card are as
	   sharp as the same crystals outside it; the build's were smeared across
	   12 px. The blur was never a measured property of the design.
	   ⚠️ It was also doing contrast work by accident — it flattened the ground
	   the white text sits on. The AA figures above were taken THROUGH it and are
	   re-measured without it below. */
	color: var(--wp--preset--color--white);
	display: grid;
	/* [MEASURED] the comp's card is 222 px tall against the build's 238. With the
	   20 px padding and the pill's measured 40 px height that leaves 142 px for
	   title + body + two gaps; the title box is 33.6 and the three body lines
	   84.24, so the gap is (142 - 117.84) / 2 = 12.08. ~~spacing--40~~ = 16. */
	gap: var(--wp--preset--spacing--30);
	justify-items: start;
}

.chumuk-hero__title,
.chumuk-hero__body {
	margin: 0;
	/* ~~ink~~ — the design draws light text on the veil [§10.126]. See the
	   contrast table on `.chumuk-hero__card`: this is a recorded AA failure. */
	color: var(--wp--preset--color--white);
}

/* ✅ An OUTLINED PILL, not a solid ink one [§10.38 r3]. Traced at y 880/886/892
   the comp's button has NO dark fill — it is a light pill with a pale rounded
   outline sitting directly on the card surface. Building it solid would drop a
   heavy dark CTA where the design draws a ghost one.

   It therefore adds NO further composited layer: `background-color:
   transparent` means the label sits on the card's own 50 % veil and inherits
   the card's measured ratio rather than needing its own (c04-hero.md's warning
   about a pill with a fill of its own). */
.chumuk-hero__cta {
	/* ~~inline-flex + align-items + gap: 0~~ SUPERSEDED at §10.192: the arrow is
	   gone from the markup, so there is nothing left to align against the label. */
	display: inline-block;
	/* The height is a BORDER-box measurement and `min-block-size` sizes the
	   content box unless this is said. It is kept even though the height is no
	   longer pinned, because the padding below is border-box arithmetic. */
	box-sizing: border-box;
	/* ~~[MEASURED] the comp's pill is x 160-309 (150 wide) and y 866-905 (40
	   tall) … padding: 0 var(--chumuk-hero-card-pad); min-block-size:
	   var(--chumuk-hero-cta-h);~~ SUPERSEDED at §10.192. THE COMP IS NO LONGER
	   THE AUTHORITY FOR THIS BUTTON'S SIZE — C35's is. Matching the experts
	   button means taking ITS padding, which is core's own button padding.
	   ⚠️ core's `+2px` terms become `+1px` HERE, and that is what makes the two
	   buttons the same size rather than merely similar. The experts button has
	   no border, so its outer box is content + 2 × (0.667em + 2). This one
	   carries a 1px border top and bottom, which under `box-sizing: border-box`
	   with no declared height still ADDS to the box — measured 52 against the
	   experts button's 50. Giving the border its 1px back out of the padding
	   makes both outer boxes content + 2 × 0.667em + 4, i.e. identical, instead
	   of this one running 2px taller in both axes. */
	padding: calc( 0.667em + 1px ) calc( 1.333em + 1px );
	/* ~~ink~~ — light, to match the design's light-on-veil card [§10.126]. */
	border: 1px solid var(--wp--preset--color--white);
	/* Fully rounded — design-tokens.md §2.4 records the store button's traced
	   radius as r = 23 px (half its height) and states that `999px` renders
	   identically, so the pill is held once as a token rather than as a literal
	   here, the same construction as the focus ring. */
	border-radius: var(--wp--custom--pill-radius);
	background-color: transparent;
	color: var(--wp--preset--color--white);
	font-family: var(--wp--custom--font-body);
	/* ~~label-xs~~ = 14px. [MEASURED] two ways and they agree on 16:
	     cap height — the comp's "S" inks 12 px against the build's 10 at 14 px,
	       so 14 x 12 / 10 = 16.8 with a +/-1 antialiasing band;
	     pill width — the comp's 150 px pill less 2 x 20 padding and 2 x 1 border
	       leaves 108 for a 34 px arrow and the label, i.e. a 74 px "Shop Now",
	       which the build draws at 66 px at 14 px -> 16.0.
	   `body` is 16px and is used unchanged; nothing new is registered. */
	font-size: var(--wp--preset--font-size--body);
	text-decoration: none;
	cursor: default;
	transition: border-color var(--chumuk-dur-fast) var(--chumuk-ease);
}

/* ⚠️ ~~.chumuk-hero__cta-arrow { flex: none }~~ REMOVED at §10.192 with the arrow
   it sized. A rule matching nothing is the same trap as a token nobody reads. */

.chumuk-hero__cta:focus-visible {
	outline: var(--wp--custom--focus-ring-width) solid var(--wp--custom--focus-ring);
	outline-offset: var(--wp--custom--focus-ring-offset);
}

/* Social row — BELOW the card in the comp, at the content box's left edge.
   Only the icons that have destinations ship: TikTok and X are MISSING (G18),
   so the comp's four become two. */
.chumuk-hero__social {
	position: relative;
	z-index: 4;
	grid-row: 1;
	grid-column: 1;
	align-self: end;
	justify-self: start;
	display: flex;
	/* The `li`s are baseline-aligned by default, which leaves the row's descender
	   space BELOW the glyphs — the icons then sit 8 px high of the comp inside a
	   correctly placed row box. Bottom-aligning them removes the gap without
	   moving the row. */
	align-items: flex-end;
	gap: var(--wp--preset--spacing--50);
	margin: 0 0 var(--chumuk-hero-row-bottom) 0;
	padding: 0 0 0 var(--chumuk-hero-inset);
	list-style: none;
	color: var(--wp--preset--color--ink);
}

.chumuk-hero__social li {
	display: flex;
}

.chumuk-hero__social a {
	display: inline-flex;
	text-decoration: none;
	color: currentColor;
}

.chumuk-hero__social-icon {
	width: var(--chumuk-header-icon);
	height: var(--chumuk-header-icon);
}

/* --------------------------------------------------------------------------
   The switcher — four native radios in a fieldset [checklist §10.42]

   Native gives arrow-key traversal, `checked` and selected-state exposure for
   free, so there is no ARIA here to half-apply.
   -------------------------------------------------------------------------- */
.chumuk-hero__variants {
	position: relative;
	z-index: 4;
	grid-row: 1;
	grid-column: 1;
	align-self: end;
	justify-self: end;
	display: flex;
	align-items: flex-end;
	gap: var(--chumuk-hero-slot-gap);
	/* 🔴 WRAPS RATHER THAN OVERFLOWS — AND WITH NO BREAKPOINT [§10.192].
	   [MEASURED] at a 320 viewport the four slots compute 4 × 90 + 3 × 20 = 420,
	   plus 40 of gutter padding = 460, inside a 265px column: the document
	   overflowed and the switcher was clipped by the hero's own `overflow-x:
	   clip`. `nowrap` made that unavoidable — the min-content width of a nowrap
	   flex row is the SUM of its items, so the box could never be smaller than
	   420 however narrow the column got.
	   ⚠️ NO MEDIA QUERY, DELIBERATELY. `wrap` reflows the row to 2 × 2 exactly
	   when it stops fitting and leaves it 4-up when it fits, so the behaviour is
	   derived from the real available width instead of a threshold someone has
	   to keep correct. The break computes at ~575px; a hardcoded 600 or 480
	   would have been another number measured once and then trusted forever.
	   ⚠️ `box-sizing: border-box` IS LOAD-BEARING HERE, not tidiness: this theme
	   ships no global reset, so under the inherited content-box the gutter
	   padding is ADDED to the 100% cap and the row overflows by exactly that
	   padding.
	   🔴 THIS REMOVES 30 OF THE 32px THE PAGE SCROLLS AT 320 — measured
	   scrollWidth 352 before, 322 after. See build report 73 §2.2. */
	flex-wrap: wrap;
	box-sizing: border-box;
	max-inline-size: 100%;
	min-inline-size: 0;
	/* 🔴 THE INSET IS A MARGIN HERE, NOT PADDING, AND THAT IS NOT COSMETIC.
	   The fieldset is a shrink-to-fit grid item, and a PERCENTAGE padding on a
	   shrink-to-fit box resolves to zero while its intrinsic width is being
	   computed and to the real value afterwards. Measured live with the padding
	   route: the box sized itself 636 px wide (540 of slots + the 96 px the
	   `max()` falls back to when `100%` is treated as zero) and then laid out
	   with 140 px of padding, so the four slots overflowed 44 px past the
	   content edge to x 1824. A margin does not enter the element's own width,
	   so the box sizes to its 540 px of slots and the inset only places it. */
	margin: 0 var(--chumuk-hero-inset) var(--chumuk-hero-row-bottom) 0;
	padding: 0;
	border: 0;
}

.chumuk-hero__variant-choice {
	position: relative;
	display: block;
	cursor: pointer;
}

/* The input stays in the accessibility tree and stays focusable — it is only
   visually replaced by the jar. `appearance: none` plus zero size would remove
   the focus target, so it is clipped instead. */
.chumuk-hero__variants input[type="radio"] {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: 0;
	opacity: 0;
	pointer-events: none;
}

.chumuk-hero__variant-jar {
	position: relative;
	display: flex;
	justify-content: center;
	align-items: flex-end;
	inline-size: calc( var(--chumuk-hero-jar-size) + 2 * var(--chumuk-hero-slot-pad) );
	padding: 0;
	background-color: transparent;
}

/* The plate is a pseudo-element rather than the slot's own background because
   the comp's jar OVERFLOWS it: the unselected plate is 50 px tall behind a
   141 px jar, and the selected one is 160 px tall, 8 px proud of the jar's top.
   A background on the box could be neither. */
.chumuk-hero__variant-jar::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	block-size: var(--chumuk-hero-plate-h);
	border-radius: var(--chumuk-card-radius-lg);
	/* ~~--chumuk-veil-card~~ (50 % white), then ~~--chumuk-hero-card-veil~~ until
	   §10.192 darkened that one for the card. Sampled in the comp both plates read
	   rgb(238 162 198) over the flat rgb(234 138 184) ground, which is 20 % white;
	   50 % would have measured rgb(245 197 220). The measured value is unchanged —
	   only the token holding it is. */
	background-color: var(--chumuk-hero-plate-veil);
	transition: block-size var(--chumuk-dur-fast) var(--chumuk-ease);
}

.chumuk-hero__variant-jar img {
	position: relative;
	display: block;
	width: var(--chumuk-hero-jar-size);
	height: auto;
	margin-block-end: var(--chumuk-hero-jar-foot);
}

/* 🔴 THE SELECTED INDICATOR IS NOT COLOUR ALONE (WCAG 1.4.1), and it is stated
   distinctly from the focus ring.

   The comp marks the active jar with a pale plate ALONE — colour plus shape,
   and visually confusable with focus. So selection carries THREE cues:
     1. the comp's pale plate (retained),
     2. a check-mark badge — a glyph, present or absent, not a colour, and
     3. a size change.
   Focus is an OUTLINE offset outside the plate, so the two never read as the
   same thing.

   ⚠️ ALL THREE CUES SURVIVE, BUT THE SIZE CUE MOVED. It used to be
   `transform: scale(1.08)` on the jar; the comp draws every jar at the same
   70 px and distinguishes the selected slot by a plate 160 px tall against 50.
   Scaling the jar as well would have put the selected one 8 % off the measured
   width, so the size change is now carried by the plate — 110 px of movement
   rather than 5. */
.chumuk-hero__variants input[type="radio"]:checked + .screen-reader-text + .chumuk-hero__variant-jar::before {
	block-size: var(--chumuk-hero-plate-h-selected);
}

.chumuk-hero__variants input[type="radio"]:checked + .screen-reader-text + .chumuk-hero__variant-jar::after {
	content: "\2713";
	position: absolute;
	inset-block-start: 0;
	inset-inline-end: 0;
	display: grid;
	place-items: center;
	width: var(--wp--preset--spacing--50);
	height: var(--wp--preset--spacing--50);
	border-radius: var(--wp--custom--pill-radius);
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--body-sm);
	line-height: 1;
}

.chumuk-hero__variants input[type="radio"]:focus-visible + .screen-reader-text + .chumuk-hero__variant-jar {
	outline: var(--wp--custom--focus-ring-width) solid var(--wp--custom--focus-ring);
	outline-offset: var(--wp--custom--focus-ring-offset);
}

.chumuk-hero__variant-choice:hover .chumuk-hero__variant-jar {
	transform: var(--chumuk-lift);
}

/* --------------------------------------------------------------------------
   Hero, narrow viewports — `[DERIVED]`

   No mobile board exists in the comp (design-tokens.md §2.2 "Fluid/responsive":
   the comp contains only a 1920 desktop view), so this is a derived layout, not
   a measured one. It keeps the desktop STRUCTURE — one grid cell, everything
   stacked by alignment — and only re-aligns within it, so there is still one
   hero and no second set of rules to drift.

   At 375 the desktop alignment collided: the card grew to five lines and
   overlapped the switcher, which sits on the same bottom line as the social
   row. Measured at build step 3. The band gets more height and the three
   elements take separate rows of it.
   -------------------------------------------------------------------------- */
@media ( max-width: 781px ) {
	.chumuk-hero {
		--chumuk-hero-min-height: clamp( 620px, 150vw, 900px );
		--chumuk-hero-jar-size: clamp( 40px, 12vw, 60px );

		/* 🔴 THE COMP-DERIVED JAR OFFSET IS SCOPED OUT HERE, AND THIS BLOCK'S OWN
		   HEADING IS THE REASON: there is no mobile board in the comp, so a
		   measurement taken from the 1920 export cannot speak about this layout.
		   MEASURED both ways before scoping: carrying the shift down to 375/768
		   moved the jar's box off the switcher row (an overlap that WAS there)
		   and onto the card (one that was NOT), because this layout re-aligns
		   the card to `start` and the two then meet. Trading a real overlap for
		   a new one, on the authority of a board that does not exist, is not a
		   fix. The desktop values are in the `.chumuk-hero` block above. */
		--chumuk-hero-jar-scale: 1;
		--chumuk-hero-jar-shift-x: 0px;
		--chumuk-hero-jar-lift: 0px;
	}

	.chumuk-hero__card {
		align-self: start;
		justify-self: stretch;
		margin-inline: var(--wp--custom--gutter);
		/* Clears the overlaid header, which is taller here because the promo bar
		   wraps. A proportion of the band, never a fixed offset. */
		margin-block-start: 22%;
	}

	.chumuk-hero__jar img {
		max-width: 46vw;
		max-height: calc( var(--chumuk-hero-min-height) * 0.46 );
	}

	/* Social sits above the switcher instead of beside it — at this width the two
	   cannot share a line without one of them leaving the content box. */
	.chumuk-hero__social {
		margin-block-end: calc(
			var(--chumuk-section-pad) + var(--chumuk-hero-jar-size) + var(--wp--preset--spacing--80)
		);
	}

	.chumuk-hero__variants {
		justify-self: center;
		padding-inline: var(--wp--custom--gutter);
		/* §10.192 — centres the WRAPPED rows too, so a 2 × 2 reads as a block
		   rather than as a full row with a short one hanging off one edge. */
		justify-content: center;
	}
}

/* --------------------------------------------------------------------------
   C01 — badge marquee

   MARQUEE, NOT CAROUSEL [checklist §10.18]: no arrows, no swipe affordance,
   and no shared code path with c13-testimonials.md — this file contains the
   whole mechanism.

   Band: y 1080–1160, 80 px, fill `cyan` (design-tokens.md §2.5). The ground and
   the text colour are both block attributes, not rules here.
   🔴 ~~text and dots are `ink`, 5.59:1 on cyan; white would be 2.23:1 and fails
   even the 3:1 floor [§10.30]~~ — STRUCK: the arithmetic was right and the
   conclusion was reversed by owner ruling at §10.135. The band ships WHITE, the
   design's colour, and the failure is recorded rather than substituted away.
   -------------------------------------------------------------------------- */
.chumuk-marquee {
	--chumuk-marquee-gap: 42px;
	--chumuk-marquee-dot: 10px;
	/* 80 px at 1920 = 4.17vw. Held as min-height so a wrapped badge grows the
	   strip rather than being clipped. */
	min-height: clamp( 56px, 4.17vw, 80px );
	display: flex;
	align-items: center;
	overflow: hidden;
	padding: 0;
}

.chumuk-marquee__track {
	display: flex;
	align-items: center;
	/* [MEASURED] a full cycle of the comp's strip runs x 53 -> 1105 = 1052 px.
	   Its four badges ink 191 + 192 + 188 + 109 and its four dots 4 x 10, so the
	   eight gaps share 1052 - 720 = 332 -> 41.5 each. ~~spacing--60~~ = 36. */
	gap: var(--chumuk-marquee-gap);
	flex: none;
	padding-inline: calc( var(--chumuk-marquee-gap) / 2 );
	/* 🔴 THE SECOND TRACK WAS SITTING 12 px LOWER THAN THE FIRST, AND THE SEAM
	   SHOWED. marquee.js appends the clone as a sibling, so core's flow layout
	   gave it `margin-block-start` — measured live at 24 px on the clone and 0
	   on the original, which put their baselines at y 1122.2 and 1110.2. The
	   band is a flex row and wants no block margin on either. */
	margin: 0;

	/* 🔴 label-serif — a FAMILY OVERRIDE, not a fontSizes entry [§10.51 r2].
	   It is `label-xs` (carried by the paragraph's own size preset) + the
	   instrument-serif family + the `label` role's uppercase and 0.08em
	   tracking, applied here and nowhere else. It is deliberately absent from
	   settings.typography.fontSizes because it is a FAMILY override, not a size.
	   ~~adding it would break the 16-preset count~~
	   🔴 **STRUCK 2026-08-22 [§10.102] — AND THIS ONE WAS ACTIVELY MISLEADING.**
	   It warned against an addition that has since happened TWICE (`display-4`,
	   `h7`), so a reader following it would have blocked two correct changes.
	   The preset count is not a constraint on this build and never was: the
	   reason `label-serif` is not a `fontSizes` entry is that **it changes the
	   FAMILY, and families are not sizes** — that reason stands on its own and
	   needs no arithmetic behind it. Count lives in the checklist, not here. */
	font-family: var(--wp--custom--font-heading);
	text-transform: uppercase;
	white-space: nowrap;

	/* The size is declared HERE as well as on each badge paragraph, because
	   `letter-spacing` in `em` resolves against the element that DECLARES it and
	   then inherits as a computed px value. Without this the track's inherited
	   body-lg (17.86 px) set the tracking to 1.43 px instead of label-xs's
	   1.12 px, and every badge inherited the wrong figure — measured at build
	   step 3. */
	/* ~~label-xs~~ = 14px. [MEASURED] two ways, agreeing to 1 %:
	     cap height — the comp's badge caps ink 17 px against the build's 10 at
	       14 px, so 14 x 17 / 10 = 23.8;
	     advance width — "NO ADDED SUGAR" inks 192 px in the comp against 114 in
	       the build; both are Playfair, and with tracking held in `em` the ratio
	       is the size ratio, giving 23.6.
	   `label-lg` is 24px and is used unchanged; nothing new is registered. */
	font-size: var(--wp--preset--font-size--label-lg);
	letter-spacing: 0.08em;
}

.chumuk-marquee__track > p {
	margin: 0;
}

.chumuk-marquee__dot {
	flex: none;
	/* [MEASURED] the comp's dots ink 10 px across (x 285-294, 571-580, 851-860,
	   1053-1062 — four independent runs, all 10). ~~spacing--20~~ = 8. */
	width: var(--chumuk-marquee-dot);
	height: var(--chumuk-marquee-dot);
}

/* The animation only starts once marquee.js has appended the clone — otherwise
   a single track would translate off-screen and leave the strip empty. So the
   un-enhanced state is a static, fully readable row of badges. */
.chumuk-marquee--looping .chumuk-marquee__track {
	animation: chumuk-marquee-scroll var(--chumuk-marquee-dur) linear infinite;
}

.chumuk-marquee--looping:hover .chumuk-marquee__track,
.chumuk-marquee--looping:focus-within .chumuk-marquee__track {
	animation-play-state: paused;
}

@keyframes chumuk-marquee-scroll {
	from {
		transform: translateX( 0 );
	}

	to {
		transform: translateX( -100% );
	}
}

/* --------------------------------------------------------------------------
   C05 — feature bento grid  [build-specs/c05-bento.md]

   Band: the bento and the ingredients section SHARE one `ice` band,
   y 1160–3260 (design-tokens.md §2.5). Both sections paint `ice` as a block
   attribute, so the seam is invisible and the band reads as one surface.

   Geometry is design-tokens.md §2.4, applied here and nowhere else:
   col A 526 × 780 · col B 1078 × 372 · cols C/D 521 × 372 · gap 36 px.
   Widths come from the fr ratios; HEIGHTS come from aspect-ratio on B, C and D,
   which is what makes the reserved box PROPORTIONAL — it survives every
   breakpoint and holds before the image loads, so the swap costs zero CLS
   (00-conventions.md §1.1 rule 1). Card A carries no ratio of its own: it spans
   both rows, so 372 + 36 + 372 = 780 falls out of the grid rather than being
   asserted twice.
   -------------------------------------------------------------------------- */

/* 🔴 A FIFTH instance of the §3.4 class, and the only one that was VISIBLE. Both
   of these sections are top-level children of core/post-content, whose constrained
   layout emits

     :where(.is-layout-constrained) > *:not(:first-child) { margin-block-start: 24px }

   so a 24 px strip of the PAGE background — `white`, not `ice` — was showing
   between the marquee and the bento, and again between the bento and the
   ingredients. design-tokens.md §2.5 has y 1160–3260 as ONE continuous `ice` band,
   so a white seam through the middle of it is wrong, not merely tight.

   ➕ EXTENDED to the C04 hero and the C01 marquee [checklist §10.66 r2, build
   audit 04 MAJOR 2]. Step 4 zeroed this on its own two wrappers only, which was
   correct scoping at the time, and raised the hero→marquee instance backward to
   steps 2–3 (§10.65 r8). Audit 04 confirmed it exactly — hero ends y 612, marquee
   starts y 636, the marquee carrying `margin-top: 24px` — so the SAME rule now
   covers all four post-content children. §10.66 r2: extend the existing mechanism,
   do not invent a new one.
   ⚠️ This is NOT the same rule as `.wp-site-blocks > *` above (line ~228): that one
   zeroes the gap between the promo bar, header, <main> and footer, which are
   children of `.wp-site-blocks`. These four are children of `core/post-content`.
   Two different stacking contexts, two separate rules — deliberately not merged
   into one global reset. */
/* 🔴 EVERY BAND, NOT THE FIRST FIVE. The comp's bands touch — measured at all
   nine boundaries below the store, the last row of one ground is immediately
   followed by the first row of the next (store/C08 at comp y 4261/4262,
   C08/C09 at 5289/5290, C09/C10 at 6092/6093, C10/C11 at 7169/7170,
   C11/C13 at 7819/7820, C13/C35 at 8519/8520, C35/C14 at 9419/9420,
   C14/C15 at 10416/10417, C15/C16 at 11274/11275). The build listed only the
   first five sections here, so core's root block gap put 24 px of white BODY
   BACKGROUND between every remaining pair — six visible seams the design does
   not draw, and 144 px of page height. */
.chumuk-hero,
.chumuk-marquee,
.chumuk-bento-section,
.chumuk-ingredients,
.chumuk-store,
.chumuk-howto-section,
.chumuk-stats,
.chumuk-compare-band,
.chumuk-counters,
.chumuk-testimonials,
.chumuk-experts,
.chumuk-faq-section,
.chumuk-cta {
	margin-block-start: 0;
}

.chumuk-bento-section {
	/* ~~--chumuk-section-pad~~ = 80px at 1920. [MEASURED] 71, by two features
	   that cannot both be a font artefact: card A's top edge is comp y 1411
	   against a live 1420.1, and the h2's cap ink starts at comp 1240 against
	   1249. Both give 9. The card top is a BOX, not ink, so the face
	   substitution recorded at §10.113 cannot account for it. Everything below
	   the heading already agreed — the h2's two-line pitch is 62 in both, and
	   its last ink to the card top is 53 in both.
	   ⚠️ SCOPED TO C05. --chumuk-section-pad is shared, and C06's head does NOT
	   show the same 9 px, so the token is not moved. */
	padding-block-start: var(--chumuk-bento-pad-top);
	/* No block-end padding: chumuk-ingredients continues the same band and owns
	   the spacing between the two. */
	padding-block-end: 0;
}

/* Heading left / intro right, bottom-aligned as the comp draws them (the h2 is
   two lines and the intro sits on its last baseline).
   🔴 ~~The 48 px gutter is the `70` token — design-tokens.md §2.4 records that
   this sits ~15 px right of the comp's measured 33 px and accepts it under
   §3.11.~~ STRUCK 2026-08-25: 33 was not the gap either, and the 15 px was
   real and visible in three bands at once.

   SOLVED, NOT ESTIMATED. The intro's first glyph inks at comp x 969 in C05, C06
   AND C07 — the same number in all three — against a live 985. Core's columns
   are equal, so with a content box of 1640: 2w + g = 1640 and 140 + w + g = 968
   (the ink less a 1 px left side bearing) give w = 812 and g = 16 — which is the
   `40` token exactly, an existing step. At `70` the columns were 796 and the
   intro started 16 px right of the design in every head on the page. */
.chumuk-bento-section__head,
.chumuk-ingredients__head {
	column-gap: var(--wp--preset--spacing--40);
	/* ~~margin-block-end: var(--wp--preset--spacing--80);~~
	   🔴 STRUCK 2026-08-22 [F15 / checklist §10.100]. THIS DECLARATION WAS DEAD
	   ON BOTH HEADS and had been since it was written — it never produced the
	   64 px it names. `.chumuk-bento-section > *` and `.chumuk-ingredients > *`
	   (line ~1863) set `margin-block: 0` at the SAME (0,1,0) specificity and
	   LATER in the file, so order decided it and this lost. C05 computed 0;
	   C06 computed 80 only because a third rule re-set it further down still.
	   It is not moved up or strengthened — the zeroing rule is deliberate
	   architecture ("every vertical gap below comes from an explicit margin
	   that can be checked against the comp"), so the live declaration belongs
	   AFTER it, and now sits with C06's near the end of this section. */
}

.chumuk-bento-section__head :where( h2, p ),
.chumuk-ingredients__head :where( h2, p ),
.chumuk-store__head :where( h2, p ) {
	margin-block: 0;
}

/* The section heading has its own measure, narrower than the 796 px column it
   sits in: the comp sets both of these over TWO lines, and without a measure they
   set on one at 1920, which changes the section's vertical rhythm.

   🔴 THE MEASURE IS IN `em` BECAUSE IT IS DERIVED FROM A `clamp()` TOKEN, AND A
   MEASURE DERIVED FROM A CLAMP MUST BE DERIVED FROM THE TOKEN'S OUTPUT AT EACH
   VIEWPORT, NEVER FROM ITS MAXIMUM [checklist §10.66 r1, build audit 04 MAJOR 1].
   Build step 4 tuned a 600 px measure against `h-2`'s clamp CEILING, 58 px — a size
   that only occurs at ≥ 1920. The emitted preset is

     --wp--preset--font-size--h-2: clamp(32px, 2rem + ((1vw - 3.2px) * 1.97), 58px)

   which OUTPUTS 33.08 px @375 · 40.83 @768 · 45.87 @1024 · 54.06 @1440 · 58 @1920.
   A fixed 600 px is therefore a DIFFERENT measure at every width — 14.70 em @768,
   11.10 em @1440, 10.34 em @1920 — and the C06 h2 flipped line count on webfont swap
   at 768 (1→2), 1024 (2→3) and 1440 (1→2), C05 at 768, for a measured CLS of
   0.0399 @768 and 0.017 @1440. `em` resolves against the token's own output, so one
   declaration is the same measure relative to the type at every viewport.

   Intrinsic one-line widths, measured on the rendered page. In px they change at
   every width; in `em` they are INVARIANT — and that invariance is now VERIFIED
   rather than argued: across every integer width 320–1920 the computed
   `max-width / font-size` ratio held at exactly 10.350 em in both font states
   while `font-size` itself ranged 32 → 58 px.

   🔴 RE-DERIVED 2026-08-20 FOR PLAYFAIR DISPLAY [checklist §10.87 r6]. The band
   below was computed for Instrument Serif, and its whole reason for existing was
   a 32 % width gap to the Georgia fallback. Playfair's gap to Georgia is ≤ 2.5 %,
   so the band is WIDER than it was, not narrower — the value survives, but the
   arithmetic that justified it does not.

   SUPERSEDED (kept as the audit trail, not a live derivation):
     ~~"The Refreshment Bangladesh Trusts"  Instrument Serif 12.15 em · Georgia 16.05 em~~
     ~~"100% Real Ingredients Zero Junk"    Instrument Serif 10.88 em · Georgia 14.77 em~~
     ~~band [9.85 em, 10.85 em], midpoint 10.35 em~~

   LIVE, measured at 58 px with this file's -0.048em tracking, Playfair Display 500
   vs the Georgia fallback (webfont state proven by an aborted-request count of 1
   AND an explicit Georgia probe agreeing to 0.00 px AND `document.fonts.check()`
   returning false — three independent signals, because a computed `font-family`
   reports the declared stack whether or not the file loaded):

                                  line 1    line 2   line 1 + next word   full
     C05 "The Refreshment…"  PF    7.101     7.551         12.014        14.834
                             Ga    6.923     7.358         11.756        14.474
     C06 "100% Real Ingred…" PF    9.016     3.974         11.103        13.185
                             Ga    9.026     4.062         11.061        13.281

   A measure holds the comp's two-line break when it is >= both line widths and
   <  "line 1 + the next word". Per-heading that is C05 [7.551, 12.014) webfont /
   [7.358, 11.756) fallback, and C06 [9.016, 11.103) / [9.026, 11.061). ONE
   declaration serves both, so the governing band is the intersection of all four:

     🔴 [9.026 em, 11.061 em)  — 2.035 em wide, where Instrument's was 1.00 em.

   Its midpoint is 10.043 em. **10.35 em is INSIDE the band and is therefore NOT
   CHANGED** — it sits 1.32 em above the floor and 0.71 em below the ceiling, and
   at 1920 it is still 600 px, so the comp's own width is untouched. Re-deriving a
   value that already passes would churn the comp's measured geometry for nothing.

   Band edges CONFIRMED by real sweep, not only by arithmetic: at 8.98 em C06
   breaks wrong in BOTH states (measure-bound, not column-bound); at 9.05, 10.35
   and 11.03 em both headings hold the comp's break in both states; at 11.10 em
   the fallback breaks wrong. That brackets [9.026, 11.061) from both sides.
   [DERIVED at build step 4 fix pass for Instrument Serif; RE-DERIVED at the
   §10.87 multi-width sweep for Playfair Display, every integer width 320–1920 in
   both font states.] */
.chumuk-bento-section__head h2,
.chumuk-ingredients__head h2 {
	max-width: 10.35em;
}

/* --------------------------------------------------------------------------
   C08 AND C09'S HEADING MEASURE — added with the Playfair swap [§10.87]

   Neither heading carried a `max-width` at all, so both set on ONE line at 1920
   where the comp sets TWO. That was invisible before the family change because
   Instrument Serif was 25 % narrower: the strings were short enough that the
   comp's own break looked like a wrap that never happened.

   The comp's breaks are "Real Prashanti in / 3 Simple Steps" and "Formulated
   For / Deep Hydration". MEASURED at 1920 in BOTH font states, at 58 px with
   this file's -0.048em tracking:

                            webfont          Georgia fallback
     longest kept line      400.8 px         394.2 px    <- measure must be >= this
     first word too many    440.7 px         434.6 px    <- measure must be <  this

   The two-state intersection is [400.8, 434.6) px = [6.91 em, 7.49 em).
   **7.2 em is its midpoint** — 417.6 px at 1920, ~17 px of margin on each side,
   and `em` keeps that margin proportional as the fluid h2 scales down.

   ✅ SWEEP COMPLETED 2026-08-20 — every integer width 320–1920 in both font
   states, and the value HOLDS [checklist §10.87, sequencing item 1]. Independent
   re-derivation at 0.001 em resolution reproduced the band as
   C08 [6.910, 7.493) and C09 [6.519, 8.602); the intersection the single
   declaration must satisfy is [6.910 em, 7.493 em) whose midpoint is 7.201 em, so
   the shipped 7.2 em is the midpoint to three decimals. Edges bracketed by real
   sweep, not arithmetic alone: 6.88 em breaks wrong in the webfont state, 6.92 /
   7.20 / 7.48 em hold in both, 7.52 em breaks wrong in the fallback state.
   `max-width / font-size` measured exactly 7.200 em at all 1601 widths in both
   states while `font-size` ranged 32 → 58 px, so the `em` proportionality this
   rule depends on is verified rather than assumed. C09 is clean at every one of
   the 1601 widths in both states.

   🔴 THE OFF-COMP BAND IS GONE, AND IT WAS NEVER A TYPOGRAPHIC PROBLEM —
   SUPERSEDED 2026-08-20 BY THE C08 STACKING RULE in the responsive block far
   below [owner decision, checklist §10.88 sequencing]. Kept as the audit trail,
   not a live derivation:
     ~~ONE BAND IS OFF-COMP AND NO `max-width` CAN REACH IT — THE COLUMN BINDS,
     NOT THE MEASURE. From 782 px the C08 head un-stacks and the column offers
     only 6.399–6.913 em of measure, against the 6.910 em the webfont's "Real
     Prashanti in" needs. So C08 sets THREE lines over 782–847 (webfont) and
     782–831 (fallback); at 848 the column reaches 6.910 em exactly and the
     comp's break returns.~~
     ~~AND IT LEFT AN UNGUARDED CLS BAND AT 832–847 px: the webfont sets three
     lines there while Georgia sets two, so the heading's height moved
     135.1 px → 90.1 px on webfont swap — a 45.0–45.3 px shift over 16 px of
     viewport. ✅ DECIDED 2026-08-20 BY THE OWNER: ADD A RESERVED BOX.~~

   WHY IT IS STRUCK: the narrow column was itself the defect. core/columns
   un-stacked this head 418 px before the column could carry the step rows next to
   it — step 1's paragraph measured **22.1 px wide over 27 lines at 782 px** — and
   the same narrowing is what took the heading to three lines. With the head kept
   STACKED to 1199 px the column offers 590–694 px (14.4–12.0 em) instead of
   263–441 px, and C08's heading sets the comp's TWO lines at **all 1601 widths
   320–1920 in BOTH font states**, with the two states differing in neither line
   count nor height at ANY width. The reserved box that guarded 832–847 is
   therefore retired — its tombstone is immediately below — and 7.2 em is now
   inside the band at every width rather than being over-ruled by the column.
   ⚠️ 7.2 em ITSELF IS UNCHANGED by any of this: `max-width / font-size` still
   measures exactly 7.200 em at all 1601 widths in both states.
   -------------------------------------------------------------------------- */
.chumuk-howto h2,
.chumuk-stats h2 {
	max-width: 7.2em;
}

/* --------------------------------------------------------------------------
   C10 · C11 · C13 · C35 — FOUR MORE HEADINGS GET THE COMP'S OWN BREAK
   [owner instruction §10.131, design-first §10.121; derived by the method §10.87 and
   the `.chumuk-bento-section__head h2` block above established]

   🔴 NO COPY CHANGED. Every one of the four strings below is byte-identical to
   what shipped before this rule existed; only the line break moved. Quoted
   verbatim from post 45 so the record shows what was preserved:

     C10  "Ditch The Soda Choose Nature"     28 chars
     C11  "Our Story in Numbers"             20 chars
     C13  "Real People Refreshing Stories"   30 chars
     C35  "Expert Guidance in Every Sip"     28 chars

   ⚠️ C11 SHIPS "Numbers", PLURAL, AND IT STAYS. The comp draws "Our Story in
   Number", singular. The owner has confirmed their own phrasing was shorthand
   for the break point and NOT a correction, so the build's string is kept
   exactly and only the break after "Our Story" is applied. A break is not a
   licence to normalise a string.

   🔴 `max-inline-size`, NOT `<br>`, AND THE REASON IS 320 px. A `<br>` forces
   the break at every width, including the ones where these headings should wrap
   naturally to the column; it also puts presentation in the content, where post
   45 would carry it. A measure in `em` resolves against the h2 token's own fluid
   output, so one declaration is the same measure relative to the type at every
   viewport — the property the 10.35 em and 7.2 em blocks above already depend on.

   MEASURED at 1920, 58 px, with this file's -0.048em tracking, Playfair Display
   500 against the Georgia fallback. Webfont state proven by
   `document.fonts.check('58px "Playfair Display"')` returning true with the
   file served and false with the request aborted at the network layer.

                                     line 1   line 2   line 1 + next word
     C10  webfont                     6.199    6.050         9.451
          Georgia fallback            6.096    5.920         9.219
     C11  webfont                     4.012    4.824         4.988
          Georgia fallback            3.886    4.754         4.867
     C13  webfont                     4.710    7.474         9.349
          Georgia fallback            4.662    7.251         9.185
     C35  webfont                     6.840    4.794         7.843
          Georgia fallback            6.689    4.751         7.670

   A measure holds the required break when it is >= BOTH line widths and
   < "line 1 + the next word", in BOTH states. Those bands, taken as the worst
   case over every swept width and both states rather than from 1920 alone:

     C10  [6.1995 em, 9.2163 em)   3.017 em wide   midpoint 7.708 em
     C11  [4.8242 em, 4.8649 em)   0.041 em wide   midpoint 4.845 em
     C13  [7.4738 em, 9.1824 em)   1.709 em wide   midpoint 8.328 em
     C35  [6.8402 em, 7.6673 em)   0.827 em wide   midpoint 7.254 em

   Every floor is set by the WEBFONT (Playfair is the wider face on the kept
   line) and every ceiling by the FALLBACK (Georgia admits the next word soonest)
   — so each band is a genuine two-state intersection, not one state's band
   with the other assumed to follow.

   ⚠️ C11's BAND IS 0.041 em WIDE AND THAT IS THE STRING, NOT A MISTAKE. The word
   that would be pulled up is "in", two letters, so "Our Story in" is barely
   wider than "in Numbers" — floor and ceiling nearly meet. 4.845 em leaves
   0.021 em of clearance each side, which is 0.66 px at the 32 px clamp floor and
   1.18 px at 58 px. It is verified rather than argued (below), but it is the
   one value here that a future change to this string or its tracking will break
   first. Re-derive it, do not nudge it.

   ✅ VERIFIED BY REAL SWEEP, NOT ARITHMETIC. All four shipped values render the
   required break at EVERY INTEGER WIDTH 320–1920 in BOTH font states — 1601
   widths x 2 states x 4 headings, zero failures, with the single documented
   exception below. And `max-inline-size / font-size` computes exactly the
   declared value at every one of those widths while `font-size` ranges 32 → 58 px,
   so the `em` proportionality this rule depends on is measured, not assumed.

   Band edges bracketed from BOTH sides by real sweep, the same way the blocks
   above bracket theirs — the low probe fails in the webfont state, the high
   probe fails in the fallback state, and everything between holds in both:

     C10   6.15 ✗wf   6.21 ✓✓   7.708 ✓✓   9.19 ✓✓   9.26 ✗fb
     C11   4.80 ✗wf   4.83 ✓✓   4.845 ✓✓   4.86 ✓✓   4.89 ✗fb
     C13   7.42 ✗wf   7.48 ✓✓   8.328 ✓✓   9.16 ✓✓   9.24 ✗fb
     C35   6.79 ✗wf   6.85 ✓✓   7.254 ✓✓   7.64 ✓✓   7.72 ✗fb

   🔴 THE ONE EXCEPTION IS C35 OVER 782–860 px, AND THE COLUMN BINDS THERE, NOT
   THE MEASURE — exactly the failure `.chumuk-howto h2` documented above. At
   782 px `core/columns` un-stacks `.chumuk-experts__grid` and the 42 % intro
   column offers only 6.3745 em, against the 6.8402 em "Expert Guidance" needs in
   the webfont state and 6.6888 em in the fallback. The heading therefore sets
   THREE lines from 782, recovering at 835 in the fallback state and 861 in the
   webfont state.
   ⚠️ MEASURED BEFORE AND AFTER: that band is IDENTICAL with and without this
   declaration — same three lines, same 131.91 px height, same recovery widths.
   This rule neither causes it nor can reach it. It is recorded as **F68**, with
   its font-state height difference over 835–860 (90.16 px fallback against
   131.91 px webfont), and left for a scoped pass. Do not add a reserved box here
   on this comment's authority alone; §10.87 r6's box was an owner decision and
   was later retired by fixing the column instead. */
.chumuk-compare-band h2 {
	max-inline-size: 7.708em;
}

.chumuk-counters h2 {
	max-inline-size: 4.845em;
}

.chumuk-testimonials h2 {
	max-inline-size: 8.328em;
}

.chumuk-experts h2 {
	max-inline-size: 7.254em;
}

/* ⚠️ SUPERSEDED 2026-08-20 — THE RULE THIS COMMENT DESCRIBES NO LONGER EXISTS.
   It is kept because its measurements are the basis on which the box was retired;
   the tombstone that replaced the rule is immediately after it. Read the two
   together: this block says why the box was added, that one says why the stacking
   fix removed its cause. Nothing between here and the tombstone is live CSS.

   ~~C08's RESERVED BOX — ADDED 2026-08-20 [owner decision, §10.87 r6], modelled
   exactly on `.chumuk-ingredients__head h2` above, and it is scoped to
   `.chumuk-howto h2` ALONE: the `max-width` rule above is shared with
   `.chumuk-stats h2`, but C09 has NO column-bound band and NO font-state height
   difference at any of the 1601 widths, so it must not inherit this reserve.

   THE BAND IT GUARDS. From 782 px core's `core/columns` un-stacks the C08 head and
   the column offers only 6.399–6.913 em of measure against the 6.910 em the
   webfont's "Real Prashanti in" needs, so C08 takes a third line that NO
   `max-width` can prevent — the column binds, not the measure. Line counts,
   measured every integer width in both states: three lines over 782–847 in the
   webfont state and 782–831 in the fallback, which leaves the two states
   DISAGREEING over 832–847 — a measured 45.0–45.3 px height shift on webfont swap.

   WHY THE COST IS SMALL. Over 782–831 both states already set three lines, so the
   reserve changes nothing there; it only reserves a third line for the FALLBACK
   state over 832–847. `min-height: 3lh` = 3 × 45.2011 px = 135.60 px at 840 px,
   which is exactly the three-line height already measured there.

   Band 778–852 px — the measured edges 782–847 rounded OUTWARD, per the same
   convention the C06 box states: over-reserving costs a line of whitespace,
   under-reserving costs CLS. `align-content: end` keeps the reserve ABOVE the text
   so the heading's last line still sits directly on its intro paragraph, which is
   the relationship the comp draws; the h2's next sibling is that `<p>`.~~ */
/* 🔴 C08's RESERVED BOX WAS REMOVED HERE 2026-08-20 — RETIRED BY THE STACKING FIX
   THAT REMOVED ITS CAUSE, NOT OVERLOOKED [owner decision 2026-08-20; checklist
   §10.88 sequencing]. What stood here, and what the comment above it describes:

     @media ( min-width: 778px ) and ( max-width: 852px ) {
         .chumuk-howto h2 { display: grid; align-content: end; min-height: 3lh; }
     }

   ⚠️ THE FIVE LINES ABOVE ARE INERT — THEY ARE INSIDE THIS COMMENT, exactly as
   C05's tombstone below warns. A comment-blind `grep` WILL report C08's box as
   still live. The authoritative check is the RENDERED value: at 800 px
   `.chumuk-howto h2` computes `display: block` / `min-height: 0px`. Live reserved
   boxes in this file now number ONE — `.chumuk-ingredients__head h2`, C06's, which
   is still load-bearing — and nothing else.

   WHY IT EXISTED: it absorbed a measured 45.0–45.3 px webfont-swap shift over
   832–847 px, where the webfont set three lines and Georgia set two. That flip
   existed ONLY BECAUSE core/columns un-stacked this head at 782 px and squeezed
   the heading into a 590–654 px column offering just 6.399–6.913 em of measure
   against the 6.910 em "Real Prashanti in" needs in the webfont state.

   WHY IT IS RETIRED: the stacking rule in the C08 responsive block below keeps
   this head STACKED to 1199 px, so the column no longer narrows at 782 and the
   third line never happens. RE-MEASURED after that rule, every integer width
   770–860 in both font states, with this box LIVE and NEUTRALISED (the neutraliser
   asserted to bite: at 800 px `grid / 133.031px` before it, `block / 0px` after
   it — fix 17 found its own neutraliser silently permanently live, so the toggle
   is now proven rather than assumed):

                              webfont state        Georgia fallback state
     line count 770–860       2 at all 91          2 at all 91
     same, box neutralised    2 at all 91          2 at all 91
     box height @800          133.03 px            133.03 px
     released height @800      88.69 px             88.69 px
     cost of the reserve      +43.88 px @778 rising to +45.41 px @850

   So the two font states differ by 0.00 px at every width in the band, and the box
   held 43.9–45.4 px of whitespace above a heading that sets two lines either way.
   Confirmed against the whole sweep, not just the band: with the stacking rule in
   force C08's heading sets TWO lines at all 1601 widths 320–1920 in BOTH font
   states, and the two states differ in neither line count nor height at ANY width.

   ⚠️ THIS IS THE SECOND TIME A RESERVED BOX HERE TURNED OUT TO BE GUARDING A
   LAYOUT BUG RATHER THAN A FONT SWAP. A reserved box makes a CLS symptom
   disappear, which is exactly what let a 27-line step row survive next to it. If a
   future pass re-introduces a two-column C08 below 1200 px, THE COLUMN WIDTH is
   the quantity that decides whether this box has to come back — not the string,
   which has not changed, and not the font, whose gap to Georgia is <= 2.5 %. */

/* 🔴 RESERVED BOX — the bands where the COLUMN, not the measure, is the binding
   constraint, so no `max-width` can reach them. ⚠️ NOTE THE DISTINCTION THE 2026-08-20
   NARROWING INTRODUCED: the COLUMN is short over the two wide bands described next,
   but the QUERY below now covers only the far narrower sub-bands where the two FONT
   STATES actually DISAGREE on line count — being column-bound is what makes the third
   line unavoidable, whereas a font-state DISAGREEMENT is what makes it a CLS risk
   worth reserving. Below 368 px the stacked column
   offers only 8.75–9.93 em of measure; from 782 px core's `core/columns` un-stacks
   the head and the two-column split offers 7.98–9.87 em until 1088 px. Both are
   below the ~9.03 em C06's first line needs, so C06 takes a third line that no
   measure can prevent. The third line is RESERVED instead: `min-height: 3lh` makes
   the box height identical in both font states, and `align-content: end` keeps the
   reserve ABOVE the text so the heading's last baseline still meets the intro's,
   which is the bottom-alignment the comp draws and the `column-gap` rule above
   depends on. Bands are rounded OUTWARD from the measured edges — over-reserving
   costs a line of whitespace, under-reserving costs CLS.

   SUPERSEDED — measured against Instrument Serif, whose 32 % gap to Georgia is what
   made these bands wide (kept as the audit trail, not a live derivation):
     ~~C06 h2:  320–363  and  782–1080   ·   C05 h2:  782–809~~
     ~~"both are BELOW the 9.85 em Georgia needs", a 15 px shortfall at 1024~~

   🔴 RE-MEASURED 2026-08-20 FOR PLAYFAIR DISPLAY, every integer width 320–1920 in
   both font states, comparing the two states width-by-width [checklist §10.87 r6].
   Playfair's gap to Georgia is ≤ 2.5 %, so the FONT-STATE flip these boxes exist to
   absorb now occurs at far fewer widths:

     C06 `.chumuk-ingredients__head h2`  line count differs between font states at
       323–324 and 909–913 ONLY (7 widths of 1601). The box is WORKING: with it in
       force the height differs by ≤ 0.1 px across the flip; with it neutralised the
       same widths jump 34.3 px (at 323–324) and 46.7 px (at 909–913). **STILL
       LOAD-BEARING — do not remove.** ✅ Its cover WAS ≤ 367 and 782–1087, much
       wider than the 7 widths that need it, so 782–896 and 926–1087 paid a reserved
       third line for a heading that sets two in both states. **NARROWED 2026-08-20
       to ≤ 336 and 897–925** — see the rule below.

     C05 `.chumuk-bento-section__head h2`  line count is TWO in both font states at
       ALL 1601 widths, and stays two with the box neutralised. ⚠️ **Its reserved
       box protected nothing measurable**, while costing a visible third line:
       over 782–815 the head measured 131.9 px reserved against 89.4 px at 816 px
       where the query released. ✅ **REMOVED 2026-08-20** — the tombstone with the
       full derivation is below, where the rule used to be.

   🔴 BOTH BOXES DISPOSITIONED 2026-08-20 BY THE OWNER, on the measurements above
   plus an independent owner re-measurement — C06's is NARROWED, C05's is REMOVED,
   and C08 GAINS one (its rule sits with the 7.2 em measure above). A reserved box
   is a CLS device, so narrowing or retiring one was referred as a decision rather
   than taken by the pass that measured it; these are the decided outcomes. */

/* C06 — NARROWED 2026-08-20 to the measured need [owner decision, §10.87 r6].
   The font-state line-count flip occurs at 323-324 and 909-913 ONLY (7 widths of
   1601), yet this query used to cover `<= 367` and `782-1087`, so 782-896 and
   926-1087 paid for a reserved third line at widths where BOTH font states agree
   on two. Cost of the old over-cover, measured: up to +50.4 px of whitespace over
   325-367 and 914-1087.

   THE BOX IS STILL LOAD-BEARING AND IS NOT RETIRED. At the 7 flip widths, with the
   box in force the height differs between font states by <= 0.1 px; with it
   neutralised the same widths jump 34.3 px (323-324) and 46.7 px (909-913).

   Edges rounded OUTWARD from the measured flip, per the convention below:
   `<= 336` covers 323-324, and `897-925` covers 909-913. Line count is INDEPENDENT
   of the box (a `grid` h2 resolves the same measure as a `block` one — verified:
   shipped and neutralised line counts are identical at all 1601 widths in both
   states), so narrowing the query cannot move the flip it guards. */
@media ( max-width: 336px ), ( min-width: 897px ) and ( max-width: 925px ) {
	.chumuk-ingredients__head h2 {
		display: grid;
		align-content: end;
		min-height: 3lh;
	}
}

/* 🔴 C05's RESERVED BOX WAS REMOVED HERE 2026-08-20 — DELETED ON MEASUREMENT, NOT
   OVERLOOKED [owner decision, §10.87 r6]. What stood here:

     @media ( min-width: 782px ) and ( max-width: 815px ) {
         .chumuk-bento-section__head h2 { display: grid; align-content: end; min-height: 3lh; }
     }

   ⚠️ THE FIVE LINES ABOVE ARE INERT — THEY ARE INSIDE THIS COMMENT. A comment-blind
   `grep`/regex inventory WILL report C05's box as still live; the fix pass that wrote
   this tombstone made exactly that mistake against its own file and caught it only by
   re-running the inventory with comments stripped. The authoritative check is the
   RENDERED value: at 800 px `.chumuk-bento-section__head h2` computes
   `display: block` / `min-height: 0px`. 🔴 CENSUS CORRECTED 2026-08-20 (later the
   same day): live reserved boxes in this file number **ONE** —
   `.chumuk-ingredients__head h2`, C06's — and nothing else.
     ~~Live reserved boxes in this file number TWO — `.chumuk-ingredients__head h2`
     and `.chumuk-howto h2`.~~
   C08's was retired the same day by the stacking fix that removed its cause; its
   own tombstone is above, with the rule it replaced. Verified as rendered, not
   grepped: at 800 px `.chumuk-howto h2` computes `display: block` /
   `min-height: 0px`, and `.chumuk-ingredients__head h2` computes `display: grid` /
   a 3lh `min-height` only inside `<= 336` and `897–925`.

   WHY IT EXISTED: it was a §10.87-era CLS device from the Instrument Serif build,
   where the display face and the Georgia fallback differed in width by 32 %, so
   "The Refreshment Bangladesh Trusts" flipped between two and three lines on
   webfont swap and the third line had to be reserved.

   WHY IT IS RETIRED: Playfair Display's gap to Georgia is <= 2.5 % where Instrument
   Serif's was 32 %, so the flip no longer happens anywhere. MEASURED over every
   integer width 320-1920 in both font states: C05's heading sets TWO lines in both
   states at ALL 1601 widths, and stays two with the box NEUTRALISED — it protected
   nothing measurable. Meanwhile it cost a visible third line of whitespace over
   782-815, up to +44.7 px (at 800 px: 133.0 px reserved vs 88.7 px released =
   44.3 px of pure whitespace).

   This is a deletion justified by a full two-state sweep. If a future pass changes
   the display family, the WIDTH GAP TO THE FALLBACK is the quantity that decides
   whether this box has to come back — not the string, which has not changed. */

/* 🔴 THE SERVED PAGE HAS NO GLOBAL `box-sizing` RESET, AND THAT IS THE FINDING
   [§10.192]. C01's and C05's band files both transcribed `* { box-sizing:
   border-box }` under "verbatim from the render dump"; it is in neither the
   inline CSS nor any linked sheet. C10's note — "NO GLOBAL box-sizing RESET, the
   theme sets it per element where needed" — is the correct reading.
   ⚠️ NOT SIMPLY DROPPED. Both bands were measured and verified WITH it, and the
   review recorded box-sizing over/under-application as PIXEL-NEUTRAL, so the
   declaration is SCOPED to exactly the two bands that carry it rather than
   hoisted to the page (which would change the other thirteen) or dropped (which
   would change those two). Core's own `.wp-block-group { box-sizing: border-box }`
   is what actually does the work in both. */
.chumuk-marquee,
.chumuk-marquee *,
.chumuk-bento-section,
.chumuk-bento-section * {
	box-sizing: border-box;
}

.chumuk-bento {
	display: grid;
	grid-template-columns: 526fr 521fr 521fr;
	grid-template-areas:
		"a b b"
		"a c d";
	gap: var(--wp--preset--spacing--60);
}

/* ⚠️ A FOURTH instance of 00-conventions.md §3.4's class, and the one that
   actually broke the measured geometry. core/group's flow layout emits

     :where(.wp-block-group.is-layout-flow) > * { margin-block-start: <block-gap> }

   and the block gap here is 24 px. Every grid item therefore carried a 24 px top
   margin, which is part of its contribution to the auto row: the rows resolved to
   372 + 24 = 396 px and the grid came out 828 px against §2.4's 780 px. The cards
   themselves measured correctly the whole time, which is exactly why this survived
   a first pass — the error was in the TRACKS, not the boxes. Zeroed at (0,1,0)
   against core's (0,0,0), scoped to the four containers this step owns, so every
   vertical gap below comes from an explicit margin that can be checked against the
   comp instead of an inherited 24 px nobody chose. */
.chumuk-bento > *,
.chumuk-bento-section > *,
.chumuk-ingredients > *,
.chumuk-ingredients__panels > *,
.chumuk-carousel > *,
/* ➕ step 7. The counter GRID and the counter CARD both needed adding, and the
   symptom was not a gap — it was a MISALIGNMENT. core's flow/constrained layout
   emits `> * + * { margin-block-start: 24px }`, and inside a grid container that
   margin pushes each item down WITHIN its own grid area: measured, the first
   card sat at y 7398.6 and the other three at y 7422.6, a 24 px step across a
   row that is supposed to be flush. The same 24 px also inflated every card
   from the measured 320 px to 344. Zeroed here so the only vertical gaps in
   this component are the grid `gap` and the card's own `row-gap`. */
.chumuk-counters__grid > *,
.chumuk-counter > * {
	margin-block: 0;
}

.chumuk-bento__a {
	grid-area: a;
	/* Card A gets its OWN ratio even though it spans both rows. Without it, A's
	   content is what sizes the two auto rows, and the measured 372 px rows drift
	   (observed: 396 px at 1920, so A came out 828 instead of 780). With it, all
	   four cards contribute the same 372-per-row figure and the grid resolves to
	   §2.4 exactly. */
	aspect-ratio: 526 / 780;
	/* 🔴 AND `height: 100%` IS WHAT CLOSES THE GAP UNDER A [§10.192]. A's ratio
	   526/780 has the 36px ROW GAP BAKED INTO IT: 780 = 372 + 36 + 372. The three
	   card ratios all scale with the columns, but the gap is a fixed 36px that
	   does not — so `row1 + 36 + row2` shrinks SLOWER than A's ratio-derived
	   height, and A comes up short everywhere except the one width where
	   1fr = 1px. [MEASURED] the shortfall is 0.00 at 1920 · 10.62 at 1440 · 18.16
	   at 1169 · 24.98 at 924 · 28.91 at 782 — it grows monotonically as the
	   viewport narrows, which is the signature of a fixed length inside an
	   otherwise proportional system.
	   `height: 100%` resolves against the grid AREA (both rows plus the gap),
	   which is definite, so it overrides the ratio for SIZE while the ratio still
	   does its job of keeping A's content out of row sizing.
	   ⚠️ ~~`aspect-ratio: auto`~~ also closes the gap and was REJECTED: it lets A's
	   shape drift with width (0.618 at 782 climbing to 0.674 at 1920), i.e. it
	   fixes the symptom by abandoning the measured card shape. */
	height: 100%;
}

.chumuk-bento__b {
	grid-area: b;
	aspect-ratio: 1078 / 372;
}

.chumuk-bento__c {
	grid-area: c;
}

.chumuk-bento__d {
	grid-area: d;
}

.chumuk-bento__c,
.chumuk-bento__d {
	aspect-ratio: 521 / 372;
}

/* ==========================================================================
   THE BRAND-TINTED WASH — CARDS C AND D ONLY  [§10.192]

   🔴 WHY IT EXISTS: both bodies are bare white on PALE photography and measured
   1.06:1 with 85.3% of the pixels under the copy below 4.5.
   ⚠️ A AND B ARE NOT TREATED, DELIBERATELY. They keep bare white copy on their
   photographs and measure 1.39:1 and 1.01:1. Two of the four cards still fail
   AA. Recorded, not fixed — the design's scope was C and D. DO NOT "fix" it.

   🔴 WHY A COLOUR RATHER THAN INK: a neutral dim at the strength this needs
   retains only ~13% of each photograph's tonal variation, and it greys C and D
   while A and B stay saturated beside them — the section visibly splits. A deep
   PALETTE colour keeps each card in its own subject's family (digestion green,
   hydration blue), so the treated row still relates to the untreated one by hue.

   ⚠️ THE COLOURS ARE NOT FREE CHOICES — they are contrast-constrained. Every one
   of the 23 palette slugs was solved at §10.193 for the alpha at which white body
   copy reaches 4.5:1 over each card's own MEASURED worst-case ground (A
   rgb(254,253,219) · B rgb(253,255,234) · C rgb(253,253,240) · D rgb(251,255,255)
   — all four are near-white where the copy sits). NINETEEN SOLVE AT NO ALPHA:
   `pink` tops out at 2.38:1 fully opaque, `cyan` 2.23, `sand` 1.24. Four solve,
   and the worst-card floor of each is:
     forest    #113A00  >= 0.6530   set to 0.78
     ink       #343434  >= 0.6703   set to 0.68
     blue-deep #023F82  >= 0.6938   set to 0.74
     mint-ink  #0A7845  >= 0.8915   NOT OFFERED

   🔴 ~~mint-ink … needs white at alpha >= 1.013. NO ALPHA EXISTS.~~ CORRECTED at
   §10.193, AND THE CONCLUSION SURVIVES THE CORRECTION. 1.013 came from applying
   the GREY per-channel threshold (255 - Δα <= 118.6) to mint-ink's green channel
   alone. That proxy is exact for a neutral tint and conservative for a coloured
   one, because it ignores the other two channels: by WCAG relative luminance the
   real floor is 0.8915, not "no alpha". mint-ink is still not offered, for the
   reason the arithmetic actually supports — at 0.89 the photograph is 89 %
   obliterated, which is no longer a wash but a fill, and every other candidate
   solves roughly 0.24 lower.

   ⚠️ PER-CARD ALPHAS, NOT ONE SHARED VALUE: a single alpha cannot serve two
   different grounds, and card B proved the point in testing — its photograph
   READS dark but its copy sits over a bright spark trail, and ink at 0.55 there
   measured 3.25:1. An average impression of a photograph says nothing about the
   strip under the text.

   🔴 ~~THE MODIFIER CLASS IS THE POINT … `.chumuk-bento__card--tinted`, one class
   per card~~ SUPERSEDED at §10.193 — AND BY THE THING IT ASKED FOR. That note
   said a single class toggle "is exactly what a block attribute emits"; the wash
   is now three REGISTERED BLOCK STYLES on `core/cover`, so the class is emitted
   by the editor's own Styles panel and the modifier class has no author left.
   ⚠️ THE MECHANISM IS UNCHANGED — same `::after`, same z-index pair, same
   `rgb( <channels> / <alpha> )`. Only the selector that carries it moved, from a
   hand-written class to `is-style-tint-*`.

   🔴 THIS IS STILL NOT core/cover's OVERLAY, AND IT STILL CANNOT BE. core's
   `dimRatio` is a 0–100 slider in steps of 10, emitted as
   `has-background-dim-{10,20,…}`. The alphas here are 0.68 / 0.74 / 0.78 and they
   are the contrast SOLUTIONS above, not preferences — rounding any of them to
   core's grid moves it off its own derivation.
   ⚠️ NO FREE COLOUR PICKER AND NO FREE ALPHA. The panel offers exactly the three
   checked pairs; the other twenty palette slugs are deliberately not registered,
   because an editor who picks a light tint would silently ship 1.06:1 body copy.
   Registration and the reasoning live in functions.php.
   ========================================================================== */

/* The colour comes from the palette token, never retyped here. Only the ALPHA is
   a local value, because the alpha is not a palette fact — it is what these
   grounds needed to clear 4.5:1, derived per tint. */
.is-style-tint-ink {
	--chumuk-tint: var(--wp--preset--color--ink-rgb);
	--chumuk-tint-alpha: 0.68;
}

.is-style-tint-forest {
	--chumuk-tint: var(--wp--preset--color--forest-rgb);
	--chumuk-tint-alpha: 0.78;
}

.is-style-tint-blue-deep {
	--chumuk-tint: var(--wp--preset--color--blue-deep-rgb);
	--chumuk-tint-alpha: 0.74;
}

:is( .is-style-tint-ink, .is-style-tint-forest, .is-style-tint-blue-deep )::after {
	content: "";
	position: absolute;
	inset: 0;
	/* above the cover image, below the inner container. Both z-indexes are stated
	   together because neither works alone: core gives the inner container
	   `position: relative` with `z-index: auto`, so a positioned `::after` later
	   in DOM order would otherwise paint OVER the copy it exists to make
	   readable.
	   ⚠️ The `::after` anchors on core's own `.wp-block-cover { position: relative }`;
	   nothing here positions the cover, which is why the styles are registered for
	   `core/cover` ONLY and would need their own `position` anywhere else. */
	z-index: 1;
	pointer-events: none;
	background-color: rgb( var(--chumuk-tint) / var(--chumuk-tint-alpha) );
}

:is( .is-style-tint-ink, .is-style-tint-forest, .is-style-tint-blue-deep ) > .wp-block-cover__inner-container {
	z-index: 2;
}

/* core/cover ships `min-height: 430px`; the grid owns these heights, so it has
   to go or the aspect ratios above never bind. Same specificity as core's
   `.wp-block-cover`, later in source order. */
.chumuk-bento > .wp-block-cover {
	/* Kills core cover's 430 px default, which would otherwise fight the ratios.
	   ⚠️ NOT `min-content`: that was tried and is a trap here. `width: fit-content`
	   on the two scrims resolves to MIN-content under an intrinsic sizing pass, so
	   the paragraph is measured at its longest word and the card's min-content
	   height came out 828 px against a 780 px box. Measured, then reverted. */
	min-height: 0;
	border-radius: var(--chumuk-card-radius);
	overflow: hidden;
	/* Card padding scales with the viewport. The comp's 48 px is the `70` token at
	   1920, but `body-sm` is fixed at 13 px (design-tokens.md §2.2: fluid min ==
	   max), so as the card narrows the copy needs proportionally MORE of the box
	   than a fixed padding leaves it. [DERIVED at build step 4] — the 48 px
	   ceiling is the measured value, the ramp below it is not. */
	padding: clamp( 20px, 2.5vw, 48px );
	align-items: stretch;
	transition:
		transform var(--chumuk-dur-fast) var(--chumuk-ease),
		box-shadow var(--chumuk-dur-fast) var(--chumuk-ease);
}

/* §2 C05 caps card hover scale at 1.03; --chumuk-lift is 1.02 (design-tokens.md
   §2.6) and the reduced-motion block above resolves it to `none`. */
.chumuk-bento > .wp-block-cover:hover,
.chumuk-bento > .wp-block-cover:focus-within {
	transform: var(--chumuk-lift);
}

.chumuk-bento .wp-block-cover__inner-container {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--50);
	height: 100%;
}

/* 🔴 ~~THE BOUNDED SCRIM~~ — STRUCK 2026-08-25, AND THE ARITHMETIC UNDER IT IS
   NOT DISPUTED. The struck text read:

     "These four grounds are PHOTOGRAPHS, so 00-conventions.md §3.1's brand-ground
      rule does not decide them and §3.3's composited-surface rule does. Measured
      on the real images, white text on the bare photography is 1.04–1.34:1 in the
      bands where the text sits — on ALL FOUR cards, the dark one included, because
      its gold neon ring crosses the title band. c05-bento.md's remedy is 'a scrim
      or overlay where it fails'; this is that scrim, bounded to the text and
      OPAQUE, so the contrast surface is `ink` and not the pixel behind it. The
      chip shape is the comp's own device at y 1458–1522 (313 × 64, fully rounded)
      — only its tone is inverted, because the comp's translucent WHITE chip made
      the failure worse rather than better. The fill itself is the `ink` palette
      slug, set as a block attribute in patterns/bento.php."

   Every figure there measures correctly. What changed is the ruling, not the
   numbers: "only its tone is inverted" IS the silent substitution of a passing
   variant, and the same call has now been reversed four times elsewhere on this
   page — hero card (1.10–4.02), marquee (2.16), footer (2.24 across 25 surfaces)
   and C11 (2.23). The design's colours are applied and the cost is recorded.

   [MEASURED] on the comp, differencing rows 1462-1474 inside the chip against
   1436-1448 and 1532-1544 outside it: the chip is a light veil, least-squares
   white alpha 0.116 over the card's own gradient. It is NOT a pure alpha in the
   export — the residual is 16.3 rms, because whatever produced it also
   desaturates — so 0.12 is the closest single value, not an exact reproduction.
   ⚠️ AND THE CAPTIONS CARRY NO SCRIM AT ALL. The comp draws its body copy as
   bare white text on the photograph; the build wrapped it in the same opaque ink
   panel. That panel is removed rather than lightened.

   🔴 TO REVERSE: put `"backgroundColor":"ink"` back on the four
   `chumuk-bento__title` headings and the three `chumuk-bento__body` paragraphs
   in patterns/bento.php AND post 45, and delete the two rules below. */
/* ⚠️ THE ELEMENT QUALIFIER IS LOAD-BEARING — a THIRD instance of
   00-conventions.md §3.4's class, and the first where core outranks a class rule
   outright rather than tying it:

     wp-includes/blocks/heading/style.css:52
     h3:where(.wp-block-heading).has-background { padding: 1.25em 2.375em; }

   `:where()` contributes nothing, so that is `h3` + `.has-background` = (0,1,1) —
   HIGHER than a bare `.chumuk-bento__title` at (0,1,0), which is why the first
   build of this rule silently rendered 45 px / 85 px padding and wrapped
   "Natural Energy" onto four lines. §3.4's two preferred fixes do not reach it:
   there is no block attribute that disarms `.has-background` while keeping the
   background, and `styles.blocks."core/heading"` emits at (0,1,0) — still lower,
   and it would repad every heading on the site. So the specificity is matched
   deliberately at (0,1,1), and `:is()` carries the specificity of its most
   specific argument, so listing every level keeps the fix LEVEL-AGNOSTIC —
   design-tokens.md §2.2.1's "level from nesting, token from size" survives an
   editor changing the level.

   ⚠️ This is NOT §3.4's trap. The trap is strengthening a GLOBAL element rule,
   which then outranks the nav exclusion. This rule is scoped to one component
   className and cannot reach anything else.

   The paragraph's twin rule is `:root :where(p.has-background)` at (0,1,0) —
   a tie, which style.css wins on source order — but it is qualified here too so
   the two scrims cannot drift apart the next time core changes one of them. */
:is( h1, h2, h3, h4, h5, h6 ).chumuk-bento__title {
	width: fit-content;
	max-width: 100%;
	margin: 0;
	/* 12 / 24 reproduces the comp's measured chip: 38 px text ≈ 265 px + 48 px
	   gives 313 px, and the comp's chip at y 1458–1522 measures 313 × 64. */
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	border-radius: var(--wp--custom--pill-radius);
	background-color: var(--chumuk-bento-chip-veil);
	/* All-caps is RECORDED, not inferred: design-tokens.md §2.2's `h4` row reads
	   "Bento card titles \"NATURAL ENERGY\" (C05) … cap 27 px, y 1477–1503, all-caps"
	   [build audit 04 MINOR 2]. The DOM text stays title-case per content-source.md
	   §6 — this is presentation only, so the source string is untouched and a screen
	   reader still hears "Natural Energy". design-tokens.md outranks both the spec
	   and the comp in the authority order, so this is the recorded value, not a
	   consistency judgement against .chumuk-carousel__label. No tracking is added:
	   the §2.2 `h4` row records the case and NOT the 0.08em the `label` role carries,
	   and `h4` is a serif heading token, not the `label` role. */
	text-transform: uppercase;
}

/* ~~padding + border-radius~~ — the comp draws no panel here at all, so there is
   nothing to pad and nothing to round. `--chumuk-bento-panel-radius` is left
   declared because C06's ingredient panels still read it. */
p.chumuk-bento__body {
	/* ~~body-sm~~ = 13px, and every derivation puts the comp above it.
	   [MEASURED] three ways, on the caption of card A:
	     line width — with the measure removed the two sides set the SAME 61
	       characters on line 1; the comp inks 415 px, the build 375 -> 14.4;
	     x-height — "ov" inks 8 px against 7 -> 14.9;
	     cap height — "P" inks 11 px against 9 -> 15.9.
	   The spread is 14.4-15.9 and no preset sits within 2 % of its middle, so
	   NO NEW TOKEN IS REGISTERED. `label-xs` = 14 is the nearest existing step,
	   sits inside the measured range, and is closer than 13 on all three. The
	   residual is recorded as a finding rather than hidden in a rounded token.
	   Line pitch is a cleaner reading: comp 18 px baseline to baseline against
	   the build's 20.28, so the caption is set tight, not at the body 1.56. */
	/* 🔴 THE SIZE CANNOT BE SET FROM HERE AND THE FIRST ATTEMPT PROVED IT.
	   WordPress emits its font-size preset classes with `!important`
	   (`.has-body-sm-font-size { font-size: ... !important }`), so a declaration
	   here computed to nothing at all — the line-height below took effect and
	   the size did not, which is exactly the shape of every other silent failure
	   on this build. The size is therefore a BLOCK ATTRIBUTE, changed in
	   patterns/bento.php and post 45: `body-sm` -> `label-xs`. */
	line-height: calc( 18 / 14 );
	width: fit-content;
	/* ~~max-width: 44ch~~ — the comp sets no measure here. Its first caption line
	   carries 61 characters and inks 415 px inside a card whose content box is
	   430 (526 less 2 x 48 padding), i.e. the copy simply fills the card. The
	   44ch ceiling broke the line five words early and was never derived from
	   anything in the comp. */
	margin: 0;
}

/* 🔴 782–1079 IS A TWO-COLUMN LAYOUT, NOT THE ONE-COLUMN STACK [§10.192].
   Sending that range to one column was wrong for the same reason 781 was: A's
   ratio 526/780 is a measurement of a TWO-ROW COLUMN, and one column makes A a
   full-width card. [MEASURED] at 1079 that gave A 956 × 1418 and a band of
   3608px against the 3-column band's 461 — a 1px viewport change swinging the
   band by 3147px (0.13×), with 1024 (iPad landscape, 1024×768 laptops,
   Chromebooks) landing in the middle of it at 3427px.
   Two columns at 2 × 2 restores continuity: 693 at 1079 against 461 at 1080, a
   0.67× step — and every card is ~460 wide, close to the 3-column C/D width at
   1440 (413), so the type-to-card relationship is comfortable here.
   ⚠️ ALL FOUR cards take C/D's measured 521/372 in this range, A included: in a
   2 × 2 the row height is shared, so a portrait A or a 2.9:1 B would leave one
   card gapped or stretched. No coined value — 521/372 is C/D's own measured
   ratio, and B's 4/3 precedent below is the same move.
   ⚠️ ~~"a b" / "a c" / "a d"~~ (A kept as a 3-row hero) was measured and
   REJECTED: it stretches A to 887 tall at a 0.52 ratio — MORE portrait than
   designed — and its continuity at the 1080 boundary is 0.52×, worse than the
   2 × 2's 0.67×. */
@media ( min-width: 782px ) and ( max-width: 1079px ) {
	.chumuk-bento {
		grid-template-columns: 1fr 1fr;
		grid-template-areas:
			"a b"
			"c d";
	}

	.chumuk-bento__a,
	.chumuk-bento__b,
	.chumuk-bento__c,
	.chumuk-bento__d {
		aspect-ratio: 521 / 372;
	}
}

@media ( max-width: 781px ) {
	/* One column below md. The reserved ratios are unchanged through the
	   collapse, so nothing shifts (c05-bento.md acceptance 6). Card A takes the
	   ratio it inherited from spanning two rows, now that there is only one. */
	.chumuk-bento {
		grid-template-columns: 1fr;
		grid-template-areas:
			"a"
			"b"
			"c"
			"d";
	}

	/* ⚠️ ONE reserved ratio DOES change through the collapse, and it is stated
	   rather than absorbed. Card B is a 2.9:1 banner (1078 × 372); at 335 px wide
	   that is a 116 px box, and its title plus body measure 142 px — the copy would
	   be clipped. It is re-reserved at 4:3, the same family as C/D's measured 1.40
	   (c05-bento.md itself notes 1.40 ≈ 4:3). A, C and D keep their measured ratios
	   exactly. CLS is unaffected either way: the box is still fixed before the image
	   loads, which is what the reservation is for. */
	.chumuk-bento__b {
		aspect-ratio: 4 / 3;
	}
}

/* 🔴 B NEEDS ONE MORE STEP AT THE VERY NARROW END [§10.192], and it is the
   second half of the scrollbar finding rather than a new problem. The 4/3
   re-reserve was fitted at "335px wide"; with a 15px scrollbar a 320 viewport
   gives the grid only 265px, where 4/3 is a 199px box against a title + body
   measuring 205 — [MEASURED] B clipped by +6.03, and ONLY at 320 (clean from 324
   up). 265/205 = 1.29, so the ratio has to come in under that: 5/4 = 1.25 gives
   212 and −7.22 of slack. Scoped to <= 371 so the 4/3 reading is untouched
   everywhere it works. */
@media ( max-width: 371px ) {
	.chumuk-bento__b {
		aspect-ratio: 5 / 4;
	}
}

/* --------------------------------------------------------------------------
   C06 + C34 — ingredients carousel and flavour tabs
   [build-specs/c06-ingredients.md]

   Band: the lower half of the shared `ice` band, y 1160–3260
   (design-tokens.md §2.5).

   Geometry, all `[MEASURED]` from pink-new-3.png and recorded in
   design-tokens.md §2.4 unless noted:
     card width 320 px, pitch 331 px → gap ≈ 11 px, taken as the `30` token (12)
     card media 320 × 400 = 4:5, the reserved box for the MISSING photography
     tab strip 652 × 50 at y 2431–2481, active pill 138 × 40 inset 5 px
     arrows 38 px circles centred on the content edges (x 140 / 1780, y 2871)
     stagger: odd-card media tops at y 2531, even at y 2624 → 93 px, held on the
       4 px base unit (§2.3) as 92 px  [MEASURED]
   -------------------------------------------------------------------------- */

.chumuk-ingredients {
	/* NOT --chumuk-section-pad here: the two sections share one band, so this is
	   an INTERNAL boundary, not a band edge. [MEASURED] from the comp — the bento
	   cards end at y 2190 and this heading starts at 2240 (50 px), and the last
	   ingredient card ends at 3218 against the band edge at 3260 (42 px). The `70`
	   token (48) is the closest step to both.
	   ⚠️ ~~"the closest step to BOTH"~~ — it is close to the top and 6 px wide of
	   the bottom, and the band carried that 6 px. Re-measured 2026-08-25: the last
	   card's bottom edge is y 3218 on both sides and the comp's ice ground ends at
	   3259, so the bottom padding is 41-42, not 48. The top stays on the token —
	   the comp's heading box starts at 2240 against a live 2239.1. */
	padding-block: var(--wp--preset--spacing--70) var(--chumuk-ingredient-pad-bottom);
}

/* THE HEAD GAP FOR BOTH C05 AND C06 — 56 px, the `75` token [F15, checklist
   §10.100]. MEASURED on the comp: both heads sit 56 px above their content, and
   they sit at the SAME distance — the comp does not distinguish them. Live they
   were 0 (C05) and 80 (C06), so neither matched and they did not even match each
   other. C05 must GROW and C06 must SHRINK; 56 is not a midpoint, it is the
   measurement.

   🔴 PLACEMENT IS THE FIX. The declaration that used to carry this sat at line
   ~1498, BEFORE `.chumuk-bento-section > * { margin-block: 0 }`, at identical
   (0,1,0) specificity — so the zeroing rule won on order and the value was
   inert. It is struck in place there. This rule sits after the zeroing rule,
   which is why it computes. No `!important`, no added selector weight: the only
   thing changed is where the declaration lives.

   `75` (56 px) was registered in theme.json for this — it is a real step
   between `70` (48) and `80` (64), not a one-off value inlined here. */
.chumuk-bento-section__head,
.chumuk-ingredients__head {
	margin-block-end: var(--wp--preset--spacing--75);
}

/* [MEASURED] C06 alone needs more: the comp's tab strip tops out at y 2431 and
   its cards at 2524, and with the tab strip's own 50 px and the 44 px below it
   that puts 67 between the head and the strip, not `75`'s 56. C05's head is NOT
   changed — its heading-ink-to-card-top distance already measures 53 on both
   sides. */
.chumuk-ingredients__head {
	margin-block-end: var(--chumuk-ingredient-tabs-gap);
}

/* C34 — the tab strip. THE SELECTED STATE IS NOT COLOUR ALONE: aria-selected is
   what the accessibility tree reads, and the pill is its visual echo.

   🔴 RESTYLED TO C07's STORE TABS at §10.192 — one tab style on the page, read
   from the shared `--chumuk-tab-*` tokens rather than restated here.
   ⚠️ WHAT THIS SUPERSEDES, stated because both were measured: the comp's
   ~~equal-width 166px tabs~~ and its ~~5px block padding on a bare white pill~~
   (four label inks of 135 / 95 / 72 and ink-to-ink gaps of 51 and 82 solved for
   one equal width twice over, 4 × 166 = 664 against the comp's 665). Tabs are
   now CONTENT-WIDTH with 44px of inline padding, the strip carries 6px of
   padding and the store's soft shadow, and the resting ink is the store's grey
   rather than full `ink`. The comp's strip measurement is no longer the
   authority for this element; the store band is.
   ⚠️ `flex-wrap` is NOT part of the store's style — the store has two short tabs
   (JAR / COMBO) and never needs to wrap, while C34 has four long flavour names
   at 44px padding each. The two media queries below are the minimum addition
   that keeps the borrowed style responsive. */
.chumuk-tabs {
	width: fit-content;
	max-width: 100%;
	margin-inline: auto;
	display: flex;
	justify-content: center;
	gap: var(--chumuk-tab-gap);
	padding: var(--chumuk-tab-strip-pad);
	/* border-box so the 6px strip padding is inside the 100% cap — this theme
	   ships no global reset, so it has to be said here. */
	box-sizing: border-box;
	border-radius: var(--wp--custom--pill-radius);
	background-color: var(--chumuk-tab-strip-bg);
	box-shadow: var(--chumuk-tab-strip-shadow);
}

/* ==========================================================================
   🔴 THE PILL AND WRAPPING ARE MUTUALLY EXCLUSIVE — so below the width where
   four tabs hold ONE ROW, the strip stops being a pill and becomes a panel.
   `border-radius: 999px` is a single-row STADIUM treatment. ⚠️ ~~It is correct in
   the store because `.cs-tabs__group` is always one row of two short labels and
   can never wrap.~~ — **THAT PREMISE IS DEAD [§10.195 audit r8, MINOR 4].** A tab
   became a product category at §10.194 B, the strip carries three and wraps at
   320-414, and it no longer uses 999px at all — see the cap at `.cs-tabs__group`
   below. The sentence is struck rather than deleted because it is the RECORDED
   JUSTIFICATION for exempting that strip, and it is exactly why the lozenge
   shipped: leaving it standing lets the next reader re-learn the error.
   Borrowing the radius and then wrapping four long flavour names put
   a 999px radius on a 103–198px-tall box: every corner clamps to height / 2 and
   the strip renders as a giant lozenge.
   ⚠️ AND `justify-content: center` ORPHANS THE LAST TAB. Flex wrapping fills rows
   greedily and centres the remainder — 3 + 1 across 781–924 leaves JIRA TWIST
   alone under three tabs, and 1 + 1 + 2 at 480 is worse. An explicit 2-column
   GRID cannot produce a ragged row.
   The three states, each sized from the tabs themselves (13px is fixed, so tab
   widths are ~220 / 236 / 206 / 172 at every viewport):
     one row  — needs 858px of strip: 834 of tabs + 3 gaps + 12 padding
     two cols — needs 488px: 2 × 236 + 1 gap + 12 padding
     one col  — needs 248px: 236 + 12 padding

   🔴 SELECTORS ARE (0,2,0), AND THAT IS THE WHOLE REASON THIS WORKS. The strip is
   a core/buttons block carrying `is-layout-flex`, and core ships
   `body .is-layout-flex { display: flex }` at (0,1,1) — which outranks a bare
   `.chumuk-tabs` at (0,1,0). MEDIA QUERIES ADD NO SPECIFICITY. Qualifying with
   the section beats core on class count without `!important`.
   ⚠️ 1000, NOT ~951. The bound must be a VIEWPORT number while the constraint is
   a STRIP number: 858px of strip needs the viewport minus two ~5vw gutters minus
   the scrollbar. [MEASURED] the first true single row is 972 (client 957) — so
   951 would leave a 952–971 window rendering a 103px box at a 999px radius: the
   exact lozenge these rules exist to prevent. 1000 carries ~29px of slack and
   keeps the pill at 1024 and above.
   ========================================================================== */
@media ( max-width: 1000px ) {
	.chumuk-ingredients .chumuk-tabs {
		display: grid;
		grid-template-columns: repeat( 2, minmax(0, 1fr) );
		width: 100%;
		/* never wider than the two widest tabs need, so the panel stays compact
		   instead of stretching across the band */
		max-width: calc( 2 * 236px + var(--chumuk-tab-gap) + 2 * var(--chumuk-tab-strip-pad) );
		/* a multi-row box is a panel: the band's own card radius, not the pill */
		border-radius: var(--chumuk-card-radius-lg);
	}

	.chumuk-ingredients .chumuk-tabs__tab {
		display: block;
	}

	.chumuk-ingredients .chumuk-tabs__tab .wp-block-button__link {
		inline-size: 100%;
	}
}

/* One column once two no longer fit. Two columns need 488px of strip; with the
   same gutter-and-scrollbar arithmetic that puts the crossover near 560, and 579
   is taken so the boundary carries ~20px rather than sitting on it. */
@media ( max-width: 579px ) {
	.chumuk-ingredients .chumuk-tabs {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* theme.json's styles.elements.button makes every button a solid `ink` pill at
   (0,1,0). Tabs need the inverse at rest, so this is (0,2,0) and wins on
   specificity — a block-level override, not a strengthened global rule
   (00-conventions.md §3.4). */
.chumuk-tabs__tab .wp-block-button__link {
	/* ⚠️ THE SIZE MOVED OUT OF THE BLOCK ATTRIBUTE at §10.192, and that is a real
	   departure from this band's convention. Preset size classes carry
	   `!important`, so `has-label-sm-font-size` (17px) would have beaten the
	   store's 13px outright — the class is removed from the MARKUP and the size
	   is declared here instead. Noted because the rule is "sizes are block
	   attributes"; this element is now the exception, and it is one because 13px
	   is not a registered step.
	   ⚠️ `text-transform: uppercase` is a STYLE, not a content change: the store's
	   labels are literal uppercase strings, and 0.12em tracking at 13px is an
	   uppercase treatment. The flavour names stay Title Case in the DOM (they are
	   `pa_flavor` term names) and are cased by CSS, exactly as C06's own chip
	   labels already are. */
	border: 0;
	cursor: pointer;
	font-family: inherit;
	font-size: var(--chumuk-tab-font-size);
	font-weight: 600;
	letter-spacing: var(--chumuk-tab-tracking);
	/* ~~padding: var(--wp--preset--spacing--20) 0; inline-size:
	   var(--chumuk-tab-w)~~ SUPERSEDED — content-width now, see .chumuk-tabs. */
	padding: var(--chumuk-tab-pad-block) var(--chumuk-tab-pad-inline);
	border-radius: var(--wp--custom--pill-radius);
	background-color: transparent;
	color: var(--chumuk-tab-ink);
	inline-size: auto;
	/* matches the store's `line-height: normal`. Without it the tab inherits the
	   body's 1.56 (20.28px at 13px) and computes 48px tall against the store's
	   44 — the last 4px of the geometry, and it comes from INHERITANCE rather
	   than from any declaration, which is why it survives a property-by-property
	   comparison. */
	line-height: normal;
	text-align: center;
	text-transform: uppercase;
	white-space: nowrap;
	/* 🔴 ONE DELIBERATE DIFFERENCE FROM THE STORE, AND IT NEEDS A DECISION.
	   The store's tabs render in FIGTREE — `.cs-tab` takes `font-family: inherit`
	   and inherits `--cs-sans` from `.chumuk-store`. These tabs keep the band's
	   own `--wp--custom--font-body` (Bricolage Grotesque). Everything else — 13px,
	   600, 0.12em, 14/44 padding, pill, the strip, all three colour states — is
	   identical.
	   ⚠️ NOT matched on purpose: Figtree in the store band is already recorded as
	   an UNRESOLVED ANOMALY, so copying it here would spread a known open question
	   into a second band on the strength of "make it look the same". If the intent
	   is that the store's face is correct and should be shared, this is a one-line
	   change — but it should be a decision, not a side effect. */
	transition: background-color var(--chumuk-dur-fast) var(--chumuk-ease);
}

.chumuk-tabs__tab .wp-block-button__link:hover {
	background-color: var(--chumuk-tab-hover-bg);
}

.chumuk-tabs__tab .wp-block-button__link[aria-selected="true"] {
	background-color: var(--chumuk-tab-active-bg);
	color: var(--chumuk-tab-active-ink);
}

.chumuk-tabs__tab .wp-block-button__link[aria-selected="true"]:hover {
	background-color: var(--chumuk-tab-active-bg);
}

/* Pre-JS state: the first panel only. flavour-tabs.js adds `.is-enhanced` and
   from then on the `hidden` attribute governs, so CSS and ARIA never disagree
   about which panel is showing. */
.chumuk-ingredients__panels:not( .is-enhanced ) > .chumuk-carousel:not( :first-child ) {
	display: none;
}

/* [MEASURED] the comp puts 44 px between the tab row's bottom edge (y 2480) and
   the card tops (2524); ~~spacing--70~~ = 48. */
.chumuk-ingredients__panels {
	margin-block-start: var(--chumuk-ingredient-panels-gap);
}

/* The carousel. These five rules are the SHARED contract that
   assets/js/carousel.js and c13-testimonials.md both build on — they describe a
   scroll-snap track with edge controls, not an ingredient row. */
.chumuk-carousel {
	position: relative;
}

.chumuk-carousel__track {
	/* [MEASURED] 2026-08-25 against pink-new-3.png. Card 1's fill runs x 142-453
	   with a soft drop shadow outside it, so the card is 313 wide, and card 2
	   starts at 473 — a 19 px gap. Pitch 332 was already right; the split between
	   card and gap was not. ~~320 / spacing--30 (12)~~. */
	--chumuk-carousel-card: 313px;
	/* [MEASURED] the raised cards sit at comp y 2524 and the lowered ones at 2624
	   — 100, read four times across the five cards. ~~92~~. */
	--chumuk-carousel-stagger: 100px;

	display: flex;
	flex-wrap: nowrap;
	align-items: flex-start;
	gap: var(--chumuk-carousel-gap);
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
	/* Room for the staggered even cards, which are transformed and therefore
	   contribute nothing to layout height. */
	padding-block-end: var(--chumuk-carousel-stagger);
}

/* A scroll container is keyboard-focusable in current Chromium, which is how the
   track is reachable and arrow-scrollable even with assets/js/carousel.js absent.
   Verified with a real Tab keypress: without this rule it showed the 1 px UA ring,
   which is not §15.4's. */
.chumuk-carousel__track:focus-visible {
	outline: var(--wp--custom--focus-ring-width) solid var(--wp--custom--focus-ring);
	outline-offset: var(--wp--custom--focus-ring-offset);
}

.chumuk-carousel__track::-webkit-scrollbar {
	display: none;
}

.chumuk-carousel__card {
	flex: 0 0 var(--chumuk-carousel-card);
	scroll-snap-align: start;
}

/* The comp's alternating vertical offset is an nth-child translate, not separate
   blocks — one editable card list, one visual rhythm. */
.chumuk-carousel__card:nth-child( even ) {
	transform: translateY( var(--chumuk-carousel-stagger) );
}

/* ~~🔴 THE RESERVED BOX. The ingredient photography is MISSING (G14), so each
   media slot is a core/cover with no image and a solid `sand` overlay.~~
   ✅ SUPERSEDED 2026-08-29 — G14 IS CLOSED [§10.190]. All eight ingredients are
   photographed and all 23 cards carry one; no `sand` cover remains
   (`has-background-dim-100` went 13 → 0 in post 45). THE BOX EARNED ITS KEEP AND
   THAT IS MEASURED, NOT CLAIMED: filling all 23 moved the C06 band by 0.00 px and
   every band below it by 0.00 px, at 320 / 375 / 781 / 1180 / 1440 / 1920, with
   CLS unchanged and no C06 node in any layout-shift entry. The 4:5
   ratio and the explicit width above are what make the swap free: the box is
   already the right size before any image exists, so acceptance 6's
   placeholder→real swap causes no shift. Overriding core's 430 px min-height is
   what lets the ratio bind.
   ⚠️ "4:5" is the SHARED default and is not what C06 draws — the C06 override
   below replaces `aspect-ratio` with a fixed 407 px block-size, so the real slot
   is 313 × 407 = 0.769. The photographs are cut to 0.769 for that reason.
   ⚠️ The --chumuk-card-radius here is the SHARED carousel default (C13's contract at
   step 8). C06 overrides all four corners below with --chumuk-card-radius-lg per
   checklist §10.69 r2, so this 16 px paints nothing today. */
.chumuk-carousel__media {
	min-height: 0;
	aspect-ratio: 4 / 5;
	border-radius: var(--chumuk-card-radius);
	overflow: hidden;
	align-items: flex-start;
	justify-content: flex-start;
	padding: var(--wp--preset--spacing--50);
}

.chumuk-carousel__media .wp-block-cover__inner-container {
	width: auto;
}

/* THE TOP HALF OF THE JOINED CARD [checklist §10.68 r3]. With the 24 px gap below
   it removed, the media is no longer a free-standing tile — it is the card's top
   edge, so only its TOP corners are rounded and the bottom edge runs straight into
   the description panel. `overflow: hidden` is already on the shared rule above,
   which is what stops the ~~future G14~~ photograph from squaring off or spilling past
   those corners; it was there for the reserved box and it earns a second job here.
   ✅ 2026-08-29: no longer future — the photographs landed [§10.190] and the clip is
   doing that second job on all 23 cards.
   ⚠️ SCOPED TO C06, like the panel fill and the panel radius: the unscoped
   `.chumuk-carousel__media` rule above is the shared contract c13-testimonials.md
   builds on at step 8, and a C13 card that has no joined panel below it still wants
   all four corners.
   🔴 ONE CARD, ONE RADIUS: --chumuk-card-radius-lg (20 px) TOP AND BOTTOM
   [checklist §10.69 r2]. This rule previously used --chumuk-card-radius (16 px)
   against the panel's 20 px below, because build fix 06 obeyed an explicit
   instruction to leave the 16 alone. But the 16 (media) and the 19→20 (panel) were
   both traced on the SAME comp card, and a single continuous card cannot have two
   radii in the design — so one trace had to be wrong. §10.69 r2 weighs them on
   rigour, not on which came first: the 20 px was derived TWICE PER CARD across all
   four cards (19/19 every time) with an arc-centre cross-check predicting
   142.3/146.2/150.5/152.9 against 143/147/151/153 measured, while the 16 px is two
   single-corner traces that DISAGREED by 2 px (14 and 16) and were resolved upward.
   The media reading is therefore SUPERSEDED and the visibly asymmetric corner pair
   that no design draws is gone.
   ⚠️ This is NOT the 12/16→20 merge §10.68 r2 refuses. --chumuk-card-radius keeps
   its 16 px and keeps serving the C05 bento cards; only this one element moved. */
/* 🔴 THE C06 CARD IS A FIXED BOX IN THE COMP AND A CONTENT-SIZED ONE IN THE BUILD.
   [MEASURED]: every one of the comp's five cards is 594 tall and splits 407 media
   / 187 description, read on all five independently (media 407 on every card, to
   the pixel). The build's cards measured 560, 584 and 608 in one row because the
   description panel grew with its copy — three different card heights where the
   design draws one. ~~aspect-ratio: 4 / 5~~ gave 400 at a 320 card; the comp's
   313 x 407 is 0.769, not 0.8, so the ratio is not the thing being held — the
   HEIGHT is, and it is stated as one. */
.chumuk-ingredients .chumuk-carousel__media {
	aspect-ratio: auto;
	block-size: var(--chumuk-ingredient-media-h);
	flex: none;
	border-radius: var(--chumuk-card-radius-lg) var(--chumuk-card-radius-lg) 0 0;
}

/* [MEASURED] the comp's cards carry a soft drop shadow — sampled outward from
   card 1's left edge at y 3050 the ice ground darkens from rgb(229 251 251) to
   rgb(212 232 232) at the edge and recovers over ~20 px, and below the card it
   recovers over ~14. The build drew none, which is what made an `ice` panel on an
   `ice` band read as no card at all. */
.chumuk-ingredients .chumuk-carousel__card {
	display: flex;
	flex-direction: column;
	border-radius: var(--chumuk-card-radius-lg);
	box-shadow: 0 2px 20px var(--chumuk-card-shadow);
}

/* The chip label — an `h3` at the `h6` token [design-tokens.md §2.2.1]. Level
   from nesting, token from size; do not "correct" either to match the other.
   The comp draws a translucent LIGHT chip with white text, which fails on the
   pale ingredient photography; this is the same shape filled with the `ink`
   slug instead, so white on it is 12.45:1 whatever lands behind.
   🔴 12.45, not 12.63 — this comment asserted 12.63:1 and was wrong [checklist
   §10.68 r7, the §10.48 stale-twin class living in a comment]. `#FFFFFF` on `ink`
   `#343434` computes to 12.4496 by WCAG 2.x relative luminance. */
/* Element-qualified for the same reason as .chumuk-bento__title above — core's
   `h3:where(.wp-block-heading).has-background` is (0,1,1). 4 / 16 reproduces the
   comp's chip at x 163–317 / y 2551–2590 (154 × 40). */
:is( h1, h2, h3, h4, h5, h6 ).chumuk-carousel__label {
	width: fit-content;
	margin: 0;
	padding: var(--wp--preset--spacing--10) var(--wp--preset--spacing--40);
	border-radius: var(--wp--custom--pill-radius);
	text-transform: uppercase;
	/* §10.192 — the chip stops being an opaque `ink` fill and becomes the shared
	   veil. `has-ink-background-color` is removed from the markup, so this is the
	   only declaration painting the chip. Element-qualified for the same reason
	   as the rules above: core's `h3:where(.wp-block-heading).has-background` is
	   (0,1,1), and a bare class would lose to it. */
	background-color: var(--chumuk-bento-chip-veil);
}

/* ==========================================================================
   🔴 THE CARD SHADOW HAD NOWHERE TO FALL, and the fix is scoped for a reason I
   got wrong first [§10.192].
   The stagger alone put the lowered cards' bottom edge EXACTLY on the track's
   bottom edge ([MEASURED] card 594 tall, translated 100, track content box
   694 — 0px of slack), so the card's `0 2px 20px` shadow had nowhere to fall and
   `overflow-y: hidden` cut it off: the card read as sliced rather than shadowed.
   The raised cards had the same problem at the top, where the shadow reaches up
   by blur/2 − offset.
   ⚠️ THE CLIP BOX GROWS BUT NOTHING MOVES — the padding is cancelled by an equal
   negative margin, so the cards sit at exactly the same y and the band's
   measured 44px strip→cards gap is preserved. The shadow paints into space the
   section's own bottom padding already occupied.
   ⚠️ SCOPED TO `.chumuk-ingredients`, NOT PUT IN THE SHARED CONTRACT. Changing
   `.chumuk-carousel__track` itself was tried and reverted: C13 re-declares that
   rule later in this file, so C13 took the negative margin but not the padding,
   which shortened its track by 22px — a regression in a band that never had the
   problem, since C13's stagger is 0 and its cards never sit on the edge. One
   band's fix does not belong in a contract two bands read.
   Specificity is (0,2,0), which outranks both `.chumuk-carousel__track` and the
   `.chumuk-carousel > *` margin-zeroing rule without relying on source order.
   ========================================================================== */
.chumuk-ingredients .chumuk-carousel__track {
	--chumuk-carousel-shadow-bleed: 22px;
	padding-block: var(--chumuk-carousel-shadow-bleed)
		calc( var(--chumuk-carousel-stagger) + var(--chumuk-carousel-shadow-bleed) );
	margin-block: calc( -1 * var(--chumuk-carousel-shadow-bleed) )
		calc( -1 * var(--chumuk-carousel-shadow-bleed) );
}

/* Shared carousel-card paragraph spacing — the C13 contract. ⚠️ C06 OVERRIDES THE
   BLOCK-START TO 0 further down, because §10.68 r3 joins the ingredient media and
   its description into one continuous card. This 24 px still applies to any other
   carousel card; if step 8 wants a joined testimonial card too, that is C13's
   decision and belongs in a `.chumuk-testimonials`-scoped rule, not here. */
.chumuk-carousel__card > p {
	margin-block: var(--wp--preset--spacing--50) 0;
}

/* THE C06 DESCRIPTION PANEL [checklist §10.67 r1]. c06-ingredients.md describes
   the card only as "per-ingredient image + name + 30–60-word description"
   (line 46) and is SILENT on the description's ground; silence is not a mandate,
   so the precedence order reaches the comp, which draws a white rounded panel —
   which is what makes the item read as a card. The `white` ground arrives as the
   block's own backgroundColor attribute in patterns/ingredients.php so it stays a
   palette slug and shows in the editor; only the geometry is here. That is the
   same division of labour as p.chumuk-bento__body above.

   🔴 SCOPED TO C06 ON PURPOSE, and the selector above is why. The five
   `.chumuk-carousel*` rules at the head of this block are the SHARED contract
   c13-testimonials.md builds on at step 8, and `.chumuk-carousel__card > p` is
   generic enough to reach a testimonial paragraph. §10.67 r1 decides the
   INGREDIENT description and nothing else, so the panel is qualified by the
   section class and the shared rule above keeps only the margin it always had.
   A testimonial card's ground is C13's decision, not this pass's.

   🔴 ~~the comp draws a WHITE rounded panel~~ — STRUCK 2026-08-25, AND THE
   SHAPE WAS RIGHT WHILE THE TONE WAS NOT. Sampled flat inside all five of the
   comp's panels the fill is rgb(233 251 255), not rgb(255 255 255): the card is
   read by its DROP SHADOW, not by a bright fill. `ice` is rgb(229 251 251) —
   within 1.6 % on every channel, so no new colour is registered and the panel
   takes `ice`. The struck claim's contrast arithmetic (12.45:1 white vs 11.57:1
   ice) was correct and is simply no longer the deciding number; ink on the
   measured fill computes 11.84:1 and still passes comfortably.

   ⚠️ Core's twin is `:root :where(p.has-background)` at (0,1,0) carrying
   `padding: 1.25em 2.375em` (= 20 px / 38 px at this font size). This selector is
   two classes plus an element at (0,2,1) and outranks it, which is what lets the
   measured 20 px bind on all four sides [§3.4 — matched declaratively on the
   component; no global rule strengthened]. Contrast moves in the safe direction
   and is MEASURED on the rendered page, not asserted: `rgb(52, 52, 52)` on
   `rgb(255, 255, 255)` = 12.45:1 against 11.57:1 on `ice` — so this is fidelity,
   not accessibility, exactly as §10.67 r1 says.

   🔴 THE PANEL IS NOW THE BOTTOM HALF OF ONE CONTINUOUS CARD [checklist §10.68 r3].
   The comp draws the ingredient item as ONE panel — media flush at the top, the
   card's own radius, no gap — and the build carried a pre-existing 24 px
   `spacing--50` strip of `ice` between the two. `margin-block-start: 0` closes it,
   and the radius is split across the two halves: top corners on the media (the
   scoped rule above `.chumuk-carousel__media`), bottom corners here. Only the
   BOTTOM corners are rounded, so the seam where the panel meets the media is
   straight and the two read as one surface rather than two stacked tiles.
   ⚠️ Zeroing the margin is scoped to `.chumuk-ingredients` for the same reason the
   fill is: `.chumuk-carousel__card > p` above is the shared C13 contract, and
   §10.68 r3 decides the INGREDIENT card only. A testimonial card keeps its 24 px. */
.chumuk-ingredients .chumuk-carousel__card > p {
	margin-block-start: 0;
	/* [MEASURED] 187, the same on all five of the comp's cards. Held rather than
	   grown so the row has ONE card height, as the comp draws it.
	   ⚠️ BORDER-BOX, said explicitly: 187 is the comp's FILL, and without this the
	   20 px panel padding is added to it and the card measured 634 against 594. */
	box-sizing: border-box;
	block-size: var(--chumuk-ingredient-panel-h);
	/* ~~body (16) / 1.5~~. [MEASURED] on card 1's seven lines, which both sides set
	   as seven: the comp's first line inks 255 px against 278 (-> 14.7) and its
	   ink height is 14 against 15 (-> 14.9), with a baseline pitch of 20 against
	   24. `label-xs` = 14 is the nearest existing step; the ~0.8 px residual is
	   recorded rather than turned into a new preset. The size itself is a BLOCK
	   ATTRIBUTE (preset classes carry !important) — only the pitch is here. */
	line-height: calc( 20 / 14 );
	padding: var(--chumuk-card-panel-pad);
	border-radius: 0 0 var(--chumuk-card-radius-lg) var(--chumuk-card-radius-lg);
}

/* The two edge controls. ~~`display: contents`~~ SUPERSEDED at §10.192: the nav
   is `height: 0`, so it occupies no row, and the buttons — absolutely positioned,
   with the nav unpositioned — still resolve against .chumuk-carousel, without
   adding a className to anything core owns. `contents` removed the box entirely,
   which also removed it from the accessibility tree in older engines; a zero-height
   flex box keeps the element and takes no space. */
.chumuk-carousel__nav {
	display: flex;
	height: 0;
}

.chumuk-carousel__prev,
.chumuk-carousel__next {
	position: absolute;
	top: 50%;
	z-index: 2;
	transform: translateY( -50% );
}

.chumuk-carousel__prev {
	left: 0;
	transform: translate( -50%, -50% );
}

.chumuk-carousel__next {
	right: 0;
	transform: translate( 50%, -50% );
}

.chumuk-carousel__prev .wp-block-button__link,
.chumuk-carousel__next .wp-block-button__link {
	/* [MEASURED] comp: the arrows are 38 px circles centred on the content-box
	   edges (left x 121–159, right x 1761–1799, both at y 2871). */
	--chumuk-carousel-arrow: 38px;
	/* Chevron leg. The comp draws a thin chevron, not a filled glyph; two 2 px
	   borders on a 9 px box is that shape without an asset. [DERIVED] */
	--chumuk-carousel-chevron: 9px;

	display: block;
	position: relative;
	width: var(--chumuk-carousel-arrow);
	height: var(--chumuk-carousel-arrow);
	padding: 0;
	border-radius: var(--wp--custom--pill-radius);
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--ink);
	/* The label stays in the DOM and in the accessibility tree — it is the
	   button's accessible name — but the glyph is what is drawn. */
	font-size: 0;
	box-shadow: 0 0 0 1px var(--chumuk-border-hairline);
}

/* 🔴 THE COMPANION TONE, COMPOSED BACK IN — F11 [checklist §10.100].
   The global two-tone ring near the top of this file is `:where(…)`, i.e.
   ZERO specificity, and its own comment predicts exactly this: "a
   zero-specificity rule cannot beat their existing declaration." The rule
   above sets `box-shadow` for the arrow's hairline, so on focus the hairline
   WON and the white companion never painted. MEASURED before the fix: these
   two rendered `rgba(52,52,52,0.12) 0 0 0 1px` — one tone — while the C08
   play button, the C06 tabs and the footer links all rendered the companion
   at `rgb(255,255,255) 0 0 0 9px`.

   `box-shadow` does not cascade per-layer — a single declaration replaces the
   whole list — so the fix is to RESTATE both shadows together rather than to
   strengthen the global selector or reach for `!important`. The hairline is
   listed FIRST so it paints on top of the companion, preserving the arrow's
   1 px edge exactly as it is when unfocused.

   The companion geometry is not re-derived here: the `calc()` is the same
   expression the global rule uses, so the two cannot drift.

   ➕ WHY ONLY THESE TWO. `grep` of every `box-shadow` in this file finds four
   other declarations, and none is on a focusable control: two are the store
   dot (a `<span>`), one is the rail's drop shadow, one is a transition. The
   arrows were the only controls this defeated. */
.chumuk-carousel__prev .wp-block-button__link:focus-visible,
.chumuk-carousel__next .wp-block-button__link:focus-visible {
	box-shadow:
		0 0 0 1px var(--chumuk-border-hairline),
		0 0 0
			calc(
				var(--wp--custom--focus-ring-offset) + var(--wp--custom--focus-ring-width) +
					var(--chumuk-focus-ring-companion-width)
			)
			var(--chumuk-focus-ring-companion);
}

.chumuk-carousel__prev .wp-block-button__link::before,
.chumuk-carousel__next .wp-block-button__link::before {
	content: "";
	position: absolute;
	inset: 0;
	width: var(--chumuk-carousel-chevron);
	height: var(--chumuk-carousel-chevron);
	margin: auto;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
}

.chumuk-carousel__prev .wp-block-button__link::before {
	transform: translateX( 15% ) rotate( 135deg );
}

.chumuk-carousel__next .wp-block-button__link::before {
	transform: translateX( -15% ) rotate( -45deg );
}

/* Focus ring — 3 px #1A1A1A at 3 px offset, read from settings.custom so no hex
   literal lives outside theme.json (checklist §15.4, 00-conventions.md §8).
   ⚠️ SCOPED TO THIS STEP'S CONTROLS ON PURPOSE. §8 says all five button states
   live in style.css, but the token layer only ships a ring for `a:not(
   .wp-element-button)` — there is no `.wp-element-button:focus-visible` rule, so
   every core/button on the site currently falls back to the UA ring. These are the
   first core/button controls in the build. Fixing it globally would be editing an
   earlier step's output, so it is fixed here for C06/C34 and RAISED in the build
   report for the step-11 a11y pass. Both grounds are checked: white ring-on-ice
   for the tabs, white ring-on-ice for the arrows.
   ➕ UPDATED at the audit-04 fix pass [checklist §10.66 r3]: this comment's premise
   — that step 4 shipped the build's first buttons — was WRONG, and §10.65 r4
   inherited the error. Three `<button>` controls from steps 2 and 2a predate these
   and carry no `.wp-element-button`, so they are now covered by their own rule near
   line 214. The GLOBAL rule is still step 11's and still absent; the statement
   above about `.wp-element-button` having no `:focus-visible` rule remains true. */
/* 🔴 REMOVED 2026-08-22 [§10.97 / D2 + F8] — these three were a SCOPED
   SINGLE-TONE COPY of the focus ring, and the global two-tone rule near the top
   of this file now covers them. Kept as a tombstone so the deletion is not
   mistaken for an omission:
     ~~.chumuk-tabs__tab .wp-block-button__link:focus-visible,
       .chumuk-carousel__prev .wp-block-button__link:focus-visible,
       .chumuk-carousel__next .wp-block-button__link:focus-visible {
         outline: ...focus-ring-width... solid ...focus-ring...;
         outline-offset: ...focus-ring-offset...;
       }~~
   They had HIGHER specificity than the global rule, so leaving them would have
   silently downgraded exactly these three controls to one tone — the failure
   mode the two-tone comment warned about ("that is how a two-tone ring becomes
   a one-tone ring on the third control that needs it"). */

/* aria-disabled, not the `disabled` attribute: the control must keep its place
   in the tab order at the ends of the track (c06-ingredients.md Accessibility). */
.chumuk-carousel__prev .wp-block-button__link[aria-disabled="true"],
.chumuk-carousel__next .wp-block-button__link[aria-disabled="true"] {
	opacity: 0.35;
	cursor: default;
}

@media ( max-width: 781px ) {
	.chumuk-carousel__track {
		/* A narrower card so the next one peeks and the swipe affordance is
		   visible; the 4:5 ratio is untouched, so the reserved box still holds.
		   The stagger is dropped — at one-and-a-bit cards per screen it reads as
		   misalignment rather than rhythm. */
		--chumuk-carousel-card: min( 320px, 76vw );
		--chumuk-carousel-stagger: 0px;
	}

	.chumuk-carousel__card:nth-child( even ) {
		transform: none;
	}

	/* ⚠️ ~~.chumuk-tabs { gap: var(--wp--preset--spacing--10) }~~ REMOVED at
	   §10.192. The strip's gap is now --chumuk-tab-gap at every width, and the
	   narrow layouts are the two grid queries beside the strip's own rule — a
	   second, contradicting gap here would have been a silent override. */
}

/* ==========================================================================
   C07 — STORE SECTION  (rebuilt 2026-08-26 from the FINAL handoff)

   🔴 THE ONE AUTHORITY FOR EVERY VALUE BELOW:
     design-source/handoff/store-section.html
     md5 8a295ed4505b850b44579cb6fa489eeb

   🔴 THREE OTHER STORE SOURCES EXIST IN THIS REPO AND ALL ARE SUPERSEDED. Do not
   read them, do not reconcile against them, do not cite them. ⚠️ MOVED 2026-08-27
   [§10.156] — they are OUT OF THE WAY, NOT GONE, and the paths now read:
     ~~design/store-section/~~
       -> _superseded/design/store-section/                                earlier draft
     ~~design-source/design_handoff_store_colour_system/~~
       -> _superseded/design-source/design_handoff_store_colour_system/    earlier colour study
     ~~design-source/design_handoff_store_colour_system_v2/~~
       -> _superseded/design-source/design_handoff_store_colour_system_v2/ earlier colour study
   Reasons and replacements: _superseded/MANIFEST.md.

   ⚠️ THIS BLOCK REPLACES ONE BUILT FROM `_v2`, WHICH WAS THE WRONG SOURCE. What
   that pass produced and this one removes, so the difference is not mistaken for
   drift later:
     ~~a WHITE active card with #111 ink~~   -> the card FILLS with the flavour colour
     ~~a 10px/56px animated left rail~~      -> there is NO rail
     ~~a rimmed dot (deep companion border)~~-> a plain dot; it turns WHITE when active
     ~~four "deep companion" tones~~         -> there are no deep companions at all
     ~~a #1b7d9c save badge~~                -> the badge is `--cs-cyan` ~~#29abd4~~ #006c90
     ~~a deep tick glyph on each card~~      -> there is no tick on a variant card
     ~~five grid tracks with 0-width spacers~~-> THREE tracks and a 64px column-gap
     ~~breakpoints at 1240 / 760 / 560~~     -> ONE breakpoint, 1180
     ~~Bricolage Grotesque via a role token~~-> Figtree, scoped to this section
   Every one of those is struck in build-reports/48 with the reason.

   NO HEX BELOW except inside the token block that opens it. The tokens are the
   handoff's own `--cs-*` set, declared where it declares them — on `.chumuk-store`,
   so a block can expose them as supports/theme.json settings later.
   ========================================================================== */

/* The handoff sets `box-sizing: border-box` on `*` globally. This theme does not
   — it sets it per element where needed — so the reset is SCOPED to the section
   rather than made global. Same box model inside the section, nothing changed
   outside it. Without this the padded rows measure wider than the design. */
.chumuk-store,
.chumuk-store *,
.chumuk-store *::before,
.chumuk-store *::after {
	box-sizing: border-box;
}

.chumuk-store {
	/* --- The handoff's own token block, verbatim --------------------------
	   Registered in design-tokens.md §2.4. All DESIGN-GIVEN, none measured. */
	--cs-pink-bg: #fdeaf1;
	--cs-crimson: #9e1b3c;
	--cs-ink: #111;
	--cs-ink-soft: #4a4249;
	/* ⚠️ ~~#6b6068~~ / ~~#232323~~ — the VALUES are unchanged; these two now point
	   at the site-wide tab tokens promoted at §10.192, so the colour exists once
	   rather than in two places with nothing keeping them equal. Verified as
	   computed values on the served page before and after. */
	--cs-grey: var(--chumuk-tab-ink);
	--cs-white: #fff;
	--cs-dark: var(--chumuk-tab-active-bg);
	--cs-outline: #1c1c3c;
	/* ⬅ #006c90, 2026-08-26. ~~#29abd4~~ — SUPERSEDED by the handoff. White on the old value
	   measured **2.67** and failed 4.5:1 (report 48, F100); on this one it measures **5.92** and
	   passes. Consumed by ONE rule, `.cs-offer__save` — verified before the swap, not assumed. */
	--cs-cyan: #006c90;

	/* The three the handoff leaves raw in its own CSS, registered here at the
	   SAME values so no hex reaches a rule below. */
	--cs-lede: #4a4a4a;
	/* ~~#f6eef2~~ — same value, now the shared token [§10.192]. */
	--cs-tab-hover: var(--chumuk-tab-hover-bg);
	--cs-note-rule: #e4c8d4;

	/* Its four shadows, likewise. Each is the handoff's exact rgba(). */
	/* ~~0 2px 14px rgba(158, 27, 60, 0.08)~~ — same value, now the shared token
	   [§10.192]. The other three shadows have no C06 twin and stay literal. */
	--cs-shadow-tabs: var(--chumuk-tab-strip-shadow);
	--cs-shadow-variant: 0 8px 20px rgba(158, 27, 60, 0.1);
	--cs-shadow-variant-active: 0 10px 24px rgba(158, 27, 60, 0.22);
	--cs-shadow-card: 0 10px 26px rgba(158, 27, 60, 0.1);

	/* 🔴 FIGTREE, SELF-HOSTED, AND SCOPED EXACTLY AS THE HANDOFF SCOPES IT.
	   The handoff declares `--cs-sans: Figtree, …` on this element, so the face
	   reaches this section and nothing else. ⚠️ It CONFLICTS with the project's
	   standing type ruling (Playfair / Bricolage Grotesque / Hind Siliguri through
	   role tokens): the store now carries a different UI face from the rest of the
	   page and the payload gains a fourth family. **Reported, not decided** —
	   build-reports/48 §5. 🔴 NO GOOGLE FONTS LINK: the handoff's `<link>` to
	   fonts.googleapis.com is NOT ported; `figtree-variable.woff2` is served from
	   the theme. */
	--cs-serif: var(--wp--preset--font-family--playfair-display);
	--cs-sans: var(--wp--preset--font-family--figtree);

	--cs-gutter: clamp(40px, 7.14vw, 137px);
	--cs-col-gap: 64px;
	--cs-radius-card: 18px;
	--cs-radius-row: 16px;

	background: var(--cs-pink-bg);
	color: var(--cs-ink);
	font-family: var(--cs-sans);
	/* 🔴 THE HANDOFF'S OWN INHERITED TEXT CONTEXT, AND BOTH VALUES ARE MEASURED.
	   Its `body` sets neither, so the section inherits the browser's 16px and `normal`
	   (~1.2). This theme's body is 17.86px at a 1.56 line-height, and the section was
	   taking both — worth +5 px on the offer name, +6 on the quantity output and +5 on
	   the details link, because those are exactly the elements the handoff leaves to
	   inherit. The six places it DOES state a line-height set their own below. */
	font-size: 16px;
	line-height: normal;
	padding: 96px 0 110px;
	-webkit-font-smoothing: antialiased;
}

.chumuk-store__inner {
	max-width: 1920px;
	margin: 0 auto;
	padding-inline: var(--cs-gutter);
}

/* Core's flow-layout gap, zeroed inside the section. `.chumuk-store__inner` and
   `.cs-head` are core groups, and core emits `> * + * { margin-block-start }` for
   every flow layout. The handoff spaces this section with explicit margins, so
   core's gap would ADD to each of them rather than replace them. */
.chumuk-store__inner > *,
.cs-head > * {
	margin-block-start: 0;
	margin-block-end: 0;
}

/* --------------------------------------------------------------------------
   The two hidden surfaces the handoff has no equivalent for, because it has no
   cart. `.chumuk-store__woo-attrs` is WooCommerce's binding surface — the two
   `[data-attribute_name]` selects its own script reads to resolve `variation_id`.
   `.chumuk-store__inputs` carries the POST values for controls the handoff draws
   as `<button>` and `<output>`, neither of which can submit.

   ⚠️ BOTH ALSO CARRY `aria-hidden`/`hidden` IN THE MARKUP. Either alone would be
   wrong: without the CSS the selects would paint, and without the attribute a
   screen-reader user would meet the same choice twice.
   -------------------------------------------------------------------------- */
.chumuk-store__woo-attrs,
.chumuk-store__inputs {
	display: none;
}

/* --- section head ------------------------------------------------------- */
.cs-head {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 80px;
	align-items: start;
	margin-bottom: 52px;
}

.cs-head__title {
	font-family: var(--cs-serif);
	/* theme.json sets `elements.heading.color` to `ink` #343434, and ANY direct rule beats
	   inheritance — so the section's `color` never reached its own headings. The handoff
	   renders them at --cs-ink. Measured: rgb(52,52,52) before, rgb(17,17,17) after. */
	color: var(--cs-ink);
	/* The handoff states no weight; its `<h2>` therefore renders at the UA's bold.
	   Stated explicitly because this theme's Playfair preset is 500, which would
	   ship a visibly lighter heading than the design. Measured, not preferred. */
	font-weight: 700;
	font-size: 56px;
	line-height: 1.08;
	margin: 0;
}

.cs-head__lede {
	margin: 8px 0 0;
	font-size: 17px;
	line-height: 1.6;
	color: var(--cs-lede);
	max-width: 760px;
}

/* --- tabs --------------------------------------------------------------- */
.cs-tabs {
	display: flex;
	justify-content: center;
	margin-bottom: 46px;
}

/* ⚠️ VALUES UNCHANGED at §10.192 — every declaration below now reads the shared
   `--chumuk-tab-*` token that carries the same value, so C06's flavour strip and
   this one are one component and cannot drift apart. Verified as computed
   values, not as matching source: 4px, 6px, 13px, 0.12em, 14px 44px, the shadow,
   and all three colour states are identical before and after. */
.cs-tabs__group {
	display: flex;
	/* 🔴 THE STRIP MUST WRAP, BECAUSE THE TAB COUNT IS NO LONGER TWO
	   [§10.195 audit, MAJOR 1]. The rule above this one used to read "`.cs-tabs__
	   group` is always one row of two short labels (JAR / COMBO) and can never
	   wrap" — TRUE when a tab was a purchase option, FALSE since §10.194 B made
	   a tab a product category. A third tab took the strip to 430px inside a
	   320px viewport: [MEASURED] document scrollWidth 375 at 320, the first tab
	   clipped to "AR" at left -49, and the same clipping at 360/375/414. That
	   reopened — and widened — the 32px overflow §10.192 closed and 7505c74
	   measured at 352 -> 320.
	   ⚠️ Wrapping, not `overflow-x: auto`: a scrolling pill strip hides tabs
	   behind a gesture with no affordance, and the tab a visitor cannot see is
	   the packaging they do not know exists. Two tabs still fit one row at 320,
	   so nothing about the shipped design moves. */
	flex-wrap: wrap;
	justify-content: center;
	/* ⚠️ WITHOUT THIS THE CAP DOES NOTHING. `.cs-tabs` is itself a flex row, so
	   the group is a flex ITEM and shrinks to its container by default — which,
	   now that wrapping is allowed, it can do all the way down to 240px. That
	   reproduced the same two-row two-tab regression the `100%` cap caused.
	   Refusing to shrink leaves the viewport cap as the only constraint. */
	flex-shrink: 0;
	/* ⚠️ THE CAP IS THE VIEWPORT, NOT THE CONTAINER — ~~`max-inline-size: 100%`~~
	   wrapped the SHIPPED two-tab design as well. [MEASURED] at 320 the strip's
	   parent is only 240px wide while two tabs need 273, so the pill has always
	   bled past its column and centred: -16.5 to 256.5 — outside the container
	   and comfortably inside the viewport. Capping at the container turned that
	   into two rows at 320 and 360 and moved the first tab 74.28px; the
	   before/after geometry check caught it, looking at it did not. The strip
	   may bleed. It may not reach past the viewport edge, which is the only
	   thing that actually scrolls the document. */
	max-inline-size: 100vw;
	gap: var(--chumuk-tab-gap);
	background: var(--chumuk-tab-strip-bg);
	/* 🔴 THE PILL AND WRAPPING ARE MUTUALLY EXCLUSIVE [§10.195 audit r7, MINOR 4].
	   `style.css`'s C06 block already records this rule and forbids the shape:
	   "`border-radius: 999px` is a single-row STADIUM treatment … Borrowing the
	   radius and then wrapping … put a 999px radius on a 103–198px-tall box:
	   every corner clamps to height / 2 and the strip renders as a giant
	   lozenge." That comment excused THIS strip on the grounds that it "is
	   always one row of two short labels and can never wrap" — a premise the
	   third tab destroyed, and §10.192 had already recorded that the two strips
	   "are one component and cannot drift apart". [MEASURED] they had: 20px on
	   C06 against 51px here, in the same wrapped state, at 320/360/375/390/414.
	   Capping at half a SINGLE row is what keeps the pill exactly — one row
	   measures 55px, so 999px already clamps to 27.5 and nothing about the
	   shipped one-row design moves — while a wrapped box reads as a panel
	   instead of a lozenge.
	   ⚠️ **43px IS A LITERAL AND CANNOT BE TOKENISED HONESTLY** [§10.195 audit r8,
	   OBS 2]. ~~"the cap is written from the padding token so the two cannot
	   drift"~~ was half true — only the padding is a token, so a change to
	   `--chumuk-tab-pad-block` or `--chumuk-tab-font-size` stales the 43 in
	   silence. 🔴 I then tried to derive it, and
	   `--chumuk-tab-pad-block * 2 + --chumuk-tab-font-size * 1.5` [MEASURED]
	   **29.75px against the true 27.5** — the line box is not 1.5em, so the
	   "derivation" was a second guess wearing arithmetic. It is stated as a
	   measurement instead: **tab height 43.0px at every width; strip 55.0px on
	   ONE ROW and 102.0px wrapped at 320-414 (164.0px with a wrapped long
	   label); cap 27.5px throughout**. ⚠️ ~~"strip 55.0px … at every width"~~ —
	   **FALSE, AND FALSE IN THE COMMENT WRITTEN TO STOP FALSE NUMBERS**
	   [§10.195 audit r9, MINOR 2]. 55 is the UNWRAPPED height; with the three
	   shipped tabs the strip is 102 at every width this fix exists for. Saying
	   "55 at every width" tells the next reader the strip never wraps — which is
	   the exact dead premise the same commit struck out of the C06 block four
	   lines from here — and a change to the tab's type scale must re-measure it.
	   Over-estimating is the safe direction (a radius above h/2 still clamps to
	   h/2 on one row), but a wrong number in a comment is what this build keeps
	   getting caught by. */
	border-radius: min( var(--wp--custom--pill-radius), calc( ( 43px + var(--chumuk-tab-strip-pad) * 2 ) / 2 ) );
	padding: var(--chumuk-tab-strip-pad);
	box-shadow: var(--chumuk-tab-strip-shadow);
}

.cs-tab {
	border: 0;
	cursor: pointer;
	/* 🔴 A SINGLE UNBREAKABLE LABEL STILL SCROLLED THE DOCUMENT [§10.195 audit
	   r9, MINOR 1]. `flex-wrap` fixes overflow caused by SEVERAL tabs; it cannot
	   break ONE. The label is a `product_cat` name — owner-editable in Products →
	   Categories, with no length or whitespace constraint — so
	   "Chumukgifthamperselection" [MEASURED] took scrollWidth to 328 at a 320
	   viewport and clipped the tab at BOTH ends; 37 unbroken characters took it
	   to 381. The threshold is 23–25 characters, and a SPACED label of 36 is
	   fine. That is the same 320 overflow §10.192 closed and the wrap fix
	   reopened through a door it does not cover — the strip's own rule says it
	   "may not reach past the viewport edge, which is the only thing that
	   actually scrolls the document". ⚠️ `anywhere`, not `break-word`: only
	   `anywhere` lets the break shrink the flex item's min-content size, which is
	   what the overflow is actually made of. */
	overflow-wrap: anywhere;
	font-family: inherit;
	/* ⚠️ THE CAPITALS ARE A CASE TRANSFORM, NOT STORED COPY — the same rule
	   `.cs-variant__name` already applies to the flavour term. §10.194 B made the
	   label a `product_cat` NAME, and that name also titles the category archive
	   and the WooCommerce admin list; storing it as "JAR" to satisfy one tab
	   strip would shout everywhere else. The design's glyphs are unchanged. */
	text-transform: uppercase;
	font-size: var(--chumuk-tab-font-size);
	font-weight: 600;
	letter-spacing: var(--chumuk-tab-tracking);
	padding: var(--chumuk-tab-pad-block) var(--chumuk-tab-pad-inline);
	border-radius: var(--wp--custom--pill-radius);
	background: transparent;
	color: var(--chumuk-tab-ink);
}

.cs-tab:hover {
	background: var(--chumuk-tab-hover-bg);
}

.cs-tab.is-active {
	background: var(--chumuk-tab-active-bg);
	color: var(--chumuk-tab-active-ink);
}

.cs-tab.is-active:hover {
	background: var(--chumuk-tab-active-bg);
}

/* --- shared 3-column panel layout ---------------------------------------
   ⚠️ THREE tracks and a real `column-gap`, not five tracks with zero-width
   spacers. `minmax(0, 1fr)` on the middle track is load-bearing: without the 0
   floor the track takes its content's min-content width and the jar pushes the
   layout wider than the panel. */
.cs-panel {
	display: none;
	align-items: start;
	column-gap: var(--cs-col-gap);
}

.cs-panel.is-active {
	display: grid;
}

.cs-panel--jar {
	grid-template-columns: 21.57% minmax(0, 1fr) 32.8%;
}

.cs-panel--combo {
	grid-template-columns: 24.5% minmax(0, 1fr) 32.5%;
}

/* --- centre media column: image fills the column, no dead space ---------- */
.cs-media {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	padding-top: 8px;
}

.cs-media--jar {
	align-items: center;
	justify-content: flex-start;
}

/* 🔴 THE RESERVED MEDIA BOX — a product with no photograph [§10.194 B].
   C06's reserved `sand` cover, applied to an `<img>` slot. It takes the jars'
   own width rule and their MEASURED ratio (296 : 621, the tallest of the four
   at the capped width), so the panel is the same height before and after a
   photograph arrives and nothing jumps when one is added.
   ⚠️ It is a `sand` PRESET, not a hex — the same contract as every other
   colour in this build. */
.cs-media--jar .cs-media__reserved {
	width: min( 296px, 100% );
	aspect-ratio: 296 / 621;
	background: var(--wp--preset--color--sand);
	border-radius: 12px;
}

.cs-media--combo .cs-media__reserved {
	width: 100%;
	aspect-ratio: 1;
	background: var(--wp--preset--color--sand);
	border-radius: 12px;
}

.cs-media--jar img {
	/* ~~296px~~ AMENDED at §10.192: `min()` keeps the measured 296 wherever the
	   column can hold it and lets the image shrink where it cannot. At 320 the
	   fixed width made this image wider than its own track, which is where the
	   band's 32px of document overflow came from — [MEASURED] scrollWidth 352
	   with the fixed width, 320 without it. The 296 is not abandoned; it is
	   capped. */
	width: min( 296px, 100% );
	height: auto;
	display: block;
}

.cs-media--combo img {
	width: 100%;
	height: auto;
	display: block;
}

.cs-media__caption {
	margin-top: 14px;
	text-align: center;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.12em;
	color: var(--cs-crimson);
}

/* ==========================================================================
   JAR TAB — the variant picker.

   🔴 THE ACTIVE CARD IS FILLED WITH THE FLAVOUR COLOUR AND ITS TEXT GOES WHITE.
   This is the opposite of what the `_v2` study drew, and `_v2` is not the design.
   The dot turns WHITE on the filled card; the sub-line inherits white at 0.82
   opacity; a rotated square in the flavour colour points at the jar.

   ⚠️ `--dot` is NOT set here. It arrives per card from
   `chumuk_store_variant_styles()`, which emits
   `.chumuk-store [data-chumuk-flavor="<slug>"]{--dot:…}` from `pa_flavor` term
   meta — the emitter C04 already uses. The handoff writes it as an inline
   `style="--dot:#…"`; routing it through the existing emitter keeps hex out of
   the markup (§4.1) and adds no second copy of the behaviour.
   ========================================================================== */
.cs-variants {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.cs-variant {
	position: relative;
	display: flex;
	align-items: center;
	gap: 16px;
	width: 100%;
	text-align: left;
	border: 0;
	cursor: pointer;
	font-family: inherit;
	background: var(--cs-white);
	border-radius: var(--cs-radius-row);
	padding: 20px 24px;
}

.cs-variant:hover {
	box-shadow: var(--cs-shadow-variant);
}

.cs-variant__dot {
	width: 22px;
	height: 22px;
	border-radius: var(--wp--custom--pill-radius);
	flex: 0 0 auto;
	background: var(--dot);
}

/* ⚠️ THE CAPITALS ARE A CASE TRANSFORM, NOT STORED COPY. The handoff spells these
   "BEETROOT BLAST"; the `pa_flavor` term is "Beetroot Blast" and must stay that
   way, because the same term names the WooCommerce catalogue, the cart and the
   order line. The rendered result is the handoff's exactly. */
.cs-variant__name {
	display: block;
	font-size: 16px;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.cs-variant__sub {
	display: block;
	font-size: 14px;
	color: var(--cs-grey);
	margin-top: 3px;
}

.cs-variant__arrow {
	display: none;
}

/* 🔴 THE UNBUYABLE STATE [§10.195 audit r5, MAJOR 4/5]. The section had none:
   an out-of-stock jar drew a priced, enabled button and the visitor found out
   after clicking, and two flavourless products in one packaging drew two cards
   that silently did nothing. `aria-disabled` rather than `disabled` on the card
   so a screen reader can still land on it and be told why; the sub-line carries
   the reason, so this is not colour-only. */
.cs-variant.is-unavailable {
	opacity: 0.55;
	cursor: not-allowed;
}

.cs-add[disabled] {
	opacity: 0.55;
	cursor: not-allowed;
}

.cs-variant.is-active {
	background: var(--dot);
	color: var(--cs-white);
	box-shadow: var(--cs-shadow-variant-active);
}

.cs-variant.is-active .cs-variant__dot {
	background: var(--cs-white);
}

.cs-variant.is-active .cs-variant__sub {
	color: inherit;
	opacity: 0.82;
}

.cs-variant.is-active .cs-variant__arrow {
	display: block;
	position: absolute;
	right: -11px;
	top: 50%;
	width: 22px;
	height: 22px;
	background: var(--dot);
	transform: translateY(-50%) rotate(45deg);
	border-radius: 3px;
}

/* ==========================================================================
   COMBO TAB — the contents card. Read-only: it communicates the set, it is not
   a picker, so there is no radio semantics here.
   ========================================================================== */
.cs-combo-card {
	background: var(--cs-white);
	border-radius: var(--cs-radius-card);
	padding: 26px 26px 22px;
	box-shadow: var(--cs-shadow-card);
}

.cs-combo-card__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-bottom: 18px;
}

.cs-combo-card__label {
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.1em;
	color: var(--cs-crimson);
}

.cs-combo-card__pill {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	color: var(--cs-white);
	background: var(--cs-crimson);
	border-radius: var(--wp--custom--pill-radius);
	padding: 5px 11px;
}

.cs-combo-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.cs-combo-item {
	display: flex;
	align-items: center;
	gap: 14px;
	background: var(--cs-pink-bg);
	border-radius: 12px;
	padding: 14px 16px;
}

.cs-combo-item__dot {
	width: 20px;
	height: 20px;
	border-radius: var(--wp--custom--pill-radius);
	flex: 0 0 auto;
	background: var(--dot);
}

.cs-combo-item__text {
	flex: 1;
}

.cs-combo-item__name {
	display: block;
	font-size: 14px;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.cs-combo-item__sub {
	display: block;
	font-size: 13px;
	color: var(--cs-grey);
	margin-top: 2px;
}

.cs-combo-item__check {
	font-size: 15px;
	font-weight: 700;
	color: var(--cs-crimson);
}

.cs-combo-card__note {
	margin-top: 18px;
	padding-top: 16px;
	border-top: 1px dashed var(--cs-note-rule);
	font-size: 13px;
	color: var(--cs-grey);
	line-height: 1.5;
}

/* --- buy column ---------------------------------------------------------- */
.cs-buy__badge {
	display: inline-block;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.1em;
	color: var(--cs-white);
	background: var(--cs-dark);
	border-radius: var(--wp--custom--pill-radius);
	padding: 6px 14px;
	margin-bottom: 16px;
}

/* Level h2, size h3. The handoff writes `<h3>`; F21 / checklist §10.101 found an
   h3 here produced the page's only skipped heading level, sitting directly under
   the hero's h1. §10.35 r2: level comes from the outline, size from the token,
   and the two are independent. The rendered type is the handoff's exactly. */
.cs-buy__title {
	font-family: var(--cs-serif);
	/* theme.json sets `elements.heading.color` to `ink` #343434, and ANY direct rule beats
	   inheritance — so the section's `color` never reached its own headings. The handoff
	   renders them at --cs-ink. Measured: rgb(52,52,52) before, rgb(17,17,17) after. */
	color: var(--cs-ink);
	font-weight: 700;
	font-size: 48px;
	line-height: 1.05;
	margin: 0 0 18px;
}

.cs-buy__desc {
	margin: 0 0 34px;
	font-size: 16px;
	line-height: 1.55;
	color: var(--cs-ink-soft);
}

/* ⚠️ THE OFFER ROW IS ALWAYS SELECTED. There is one option per panel, so its
   border and its filled radio are unconditional — there is no unselected state
   in this design, and therefore no `#c9bcc3` resting ring. */
.cs-offer {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	background: var(--cs-white);
	border: 2px solid var(--cs-outline);
	border-radius: 14px;
	padding: 22px 24px;
	margin-bottom: 34px;
	cursor: pointer;
}

.cs-offer__left {
	display: flex;
	align-items: center;
	gap: 16px;
}

.cs-offer__radio {
	width: 20px;
	height: 20px;
	border-radius: var(--wp--custom--pill-radius);
	flex: 0 0 auto;
	border: 2px solid var(--cs-outline);
	background: var(--cs-white);
	box-shadow:
		inset 0 0 0 3px var(--cs-white),
		inset 0 0 0 9px var(--cs-outline);
}

/* 🔴 A "SAVE 0৳" PILL IS A DEFECT, NOT A ZERO [§10.195 audit, MINOR 5].
   `chumuk_store_price_pair()` has always said so; nothing ever read the flag,
   and the Sachet tab put "Regular price 600৳ · you save 0৳ … SAVE 0৳" on
   screen with a struck price identical to the live one. The nodes are hidden
   rather than omitted because the panel relabels — see store-markup.php. */
.cs-offer--flat .cs-offer__meta,
.cs-offer--flat .cs-offer__save {
	display: none;
}

.cs-offer__name {
	display: block;
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 0.04em;
	/* §10.194 B — the combo row's name is now the PRODUCT's title ("All Variant
	   Combo") rather than a second spelling of it in a PHP file. The jar row's
	   "SINGLE JAR" is a purchase-option label, not a product, and is unaffected:
	   it was already capitals. */
	text-transform: uppercase;
}

.cs-offer__meta {
	display: block;
	font-size: 13px;
	color: var(--cs-grey);
	margin-top: 6px;
}

.cs-offer__meta s {
	text-decoration: line-through;
}

.cs-offer__price {
	font-size: 26px;
	font-weight: 600;
	white-space: nowrap;
}

.cs-offer__save {
	position: absolute;
	top: -11px;
	right: 22px;
	background: var(--cs-cyan);
	color: var(--cs-white);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	padding: 4px 12px;
	border-radius: var(--wp--custom--pill-radius);
}

.cs-cart {
	display: flex;
	align-items: stretch;
	gap: 20px;
}

.cs-qty {
	display: flex;
	align-items: center;
	gap: 18px;
	background: var(--cs-white);
	border-radius: var(--wp--custom--pill-radius);
	padding: 14px 22px;
}

.cs-qty button {
	border: 0;
	background: none;
	font: inherit;
	font-size: 20px;
	color: var(--cs-grey);
	cursor: pointer;
	line-height: 1;
	padding: 0;
}

.cs-qty output {
	font-size: 16px;
	font-weight: 600;
	min-width: 16px;
	text-align: center;
}

.cs-add {
	flex: 1;
	border: 0;
	cursor: pointer;
	font-family: inherit;
	background: var(--cs-dark);
	color: var(--cs-white);
	border-radius: var(--wp--custom--pill-radius);
	padding: 18px 32px;
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 0.1em;
}

.cs-add:hover {
	background: var(--cs-crimson);
}

.cs-details {
	display: inline-block;
	margin-top: 30px;
	color: var(--cs-ink);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-decoration: underline;
	text-underline-offset: 4px;
}

.cs-details:hover {
	color: var(--cs-crimson);
}

/* --- responsive — ONE breakpoint, and it is 1180 -------------------------
   ⚠️ The handoff has no other query. There is no 1240, no 760 and no 560; those
   belonged to the superseded `_v2` study. Verified free of horizontal overflow at
   every integer width 320–1920 all the same. */
@media (max-width: 1180px) {
	.cs-head {
		grid-template-columns: 1fr;
		gap: 20px;
	}

	.cs-panel--jar,
	.cs-panel--combo {
		/* ~~1fr~~ AMENDED at §10.192. `minmax(0, …)` here is the SAME mechanism as
		   the three-track rule above and a DIFFERENT purpose from C11's: a bare
		   `1fr` is `minmax(auto, 1fr)`, whose auto floor is the widest item's
		   min-content — the 296px jar image plus its padding — so the single
		   track could not shrink below the viewport and the band overflowed. The
		   explicit 0 floor lets it. C11's counters use no minmax at all. */
		grid-template-columns: minmax(0, 1fr);
		row-gap: 40px;
	}

	/* THE CARET'S ONE-COLUMN STATE — it does not render. Transcribed from the
	   handoff, which carries it in all three files (c07-store, chumuk-homepage,
	   chumuk-shop) inside this same query.
	   The caret exists to point from the active variant card at the column BESIDE
	   it: at 1440/1920 the panel is three tracks (310.594 / 529.094 / 472.312) with
	   a 64px column gap, and that gap absorbs the overhang. THIS query is the line
	   where the neighbouring column stops existing, so it is also the line where
	   the caret stops meaning anything — declared here, inside the collapse itself,
	   so the caret and the columns can never disagree about where the grid ends.
	   ⚠️ Do NOT lift this into a query of its own: that is how C09's trust bar lost
	   `block-size: 98px` silently when its grid stacked at a different number.
	   It is a 22px square rotated 45°: 31.11px rendered, 4.56px of half-overhang
	   each side, and right:-11px puts 15.56px past the button. With no column to
	   its right that only pushed the document sideways — measured 1027-in-1012 on
	   the homepage (hidden in 84.252px of wrapper padding) and 1196-in-1180 on
	   Shop, where there is no padding to hide in. Nothing above 1180 changes. */
	.cs-variant.is-active .cs-variant__arrow {
		display: none;
	}

	.cs-media--combo img {
		max-width: 620px;
		margin: 0 auto;
	}

	.cs-head__title {
		font-size: 40px;
	}

	.cs-buy__title {
		font-size: 36px;
	}
}

/* --------------------------------------------------------------------------
   Global reduced-motion kill switch — 00-conventions.md §5

   Every motion value in this build is disabled under reduced motion. This is
   not per-component discretion; component specs add to it, never replace it.
   -------------------------------------------------------------------------- */
@media ( prefers-reduced-motion: reduce ) {
	:root {
		--chumuk-dur-fast: 0.01ms;
		--chumuk-dur-base: 0.01ms;
		--chumuk-dur-slow: 0.01ms;
		--chumuk-marquee-dur: 0.01ms;
		--chumuk-counter-dur: 0.01ms;
		--chumuk-lift: none;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ==========================================================================
   C08 / C12 — HOW-IT-WORKS + VIDEO LIGHTBOX (build step 6)
   build-specs/c08-how-it-works.md · design-tokens.md §2.1, §2.2.1, §2.5 §4.2

   No hex, no raw px and no font stack below except inside a documented custom
   property: every colour is a theme.json slug reached through a semantic alias,
   every type size a registered preset, every gap a spacing token.

   GEOMETRY, all [MEASURED] from pink-new-3.png at its native 1920, each edge
   confirmed at four independent positions before it was used:
     band                y 4260–5290 (1030)      design-tokens.md §2.5
     inner card          x   50–1869 · y 4310–5239  (1820 × 930), SQUARE corners
     video panel         x  140–  951 · y 4400–5149  (812 × 750)  r = 16
     column gutter       x  952–1015 (64) = spacing token `80`, exactly
     step row pitch      165 px, from the icon centres (4737.5 / 4902.5 / 5067.5)
     step card           x 1149–1779 · 100 tall · r = 8
     step icon box       x 1018–1118 (100)
     play button         60 × 60, centred on the panel at (545.5, 4774.5)

   ⚠️ THE COMP'S MIDDLE STEP CARD IS 15 PX OUT AND THE ROW PITCH IS NOT. Card
   tops measure 4703 / 4853 / 5033: rows 1→3 are 330 apart, exactly 2 × 165, and
   the icons are 165 apart with no error at all, but card 2 sits 15 px above
   where 165 puts it. One card out of three disagreeing with both its own
   neighbours and the icon it belongs to is a design-file inconsistency, not a
   rhythm. A uniform 165 is built. §4.1: a measured value is checked against the
   comp, and here the comp contradicts itself — the two-of-three that agree with
   an independent series (the icons) win.
   -------------------------------------------------------------------------- */

.chumuk-howto-section {
	/* The band is 1030 px and the card inside it 930, so the cover contributes
	   the 50 px inset measured on all four sides (x 50 → 1869 in a 1920 comp).

	   🔴 PADDING LIVES HERE, NOT IN A BLOCK ATTRIBUTE, AND THAT IS NOT A STYLE
	   PREFERENCE — IT IS THE FIX FOR A MEASURED 375 px FAILURE. Set as block
	   attributes (`70` on the cover, `90` on the card) the two nest, and at 375
	   they left 375 − 96 − 160 = 119 px of content: the video panel rendered
	   119 × 110 and the three step rows blew out to 1042 / 930 / 1002 px tall,
	   making the section 4035 px against its 1030 px band. Block-attribute
	   padding is an inline style, so a media query can only beat it with
	   `!important`. Declared here instead it is responsive by construction, and
	   it matches how every other section in this file already does it
	   (`.chumuk-bento-section`, `.chumuk-store` — both `--chumuk-section-pad`).
	   The cost is that the two paddings are no longer editor-editable; the
	   alternative was a section that does not work on a phone. */
	--chumuk-howto-inset: var( --wp--preset--spacing--70 );

	position: relative;
	padding: var( --chumuk-howto-inset );
}

/* [MEASURED] the comp's card runs y 4309-5239 and its video panel 4400-5150, so
   the padding is 91 above and 91 below a 750 px panel — 932, against the card's
   measured 931. ~~--chumuk-section-pad~~ resolves to 80 and gave 899. */
.chumuk-howto {
	padding: var( --chumuk-howto-pad );
}

/* 🔴 THE TWO COLUMNS ARE NOT EQUAL IN THE COMP, AND CORE MAKES THEM EQUAL.
   [MEASURED]: the video panel runs x 140-952 (812) and the step column's heading
   inks from 1020, i.e. a track starting at ~1019 and ending at the card's inner
   edge 1778 — 759. The build split the same 1642 px of content into 789 / 789.
   Core sizes an un-widthed column as `flex: 1 1 0`, so overriding ONLY
   `flex-grow` sets the ratio exactly and leaves the gap alone — no width
   arithmetic, no percentage that has to subtract half a gap. */
/* [MEASURED] the comp's video ends x 952 and its step column starts at ~1019. */
.chumuk-howto > .wp-block-columns {
	gap: var( --chumuk-howto-col-gap );
}

.chumuk-howto > .wp-block-columns > .wp-block-column:first-child {
	flex-grow: 812;
}

.chumuk-howto > .wp-block-columns > .wp-block-column:last-child {
	flex-grow: 759;
}

/* --------------------------------------------------------------------------
   The inner card — `--chumuk-veil-strong`, 85 % white (design-tokens.md §2.1).

   ⚠️ THE COMP'S CORNERS ARE SQUARE AND c08-how-it-works.md SAYS "rounded".
   Traced at the top-left corner (50, 4310) the fill is already present at
   dx = 0 on the card's very first row, and the enlarged crop shows a hard
   90° corner. So `border-radius` is 0 here, matching the comp; the spec's one
   word is REPORTED as a comp/spec conflict rather than resolved by rounding a
   corner the comp does not draw. §4.1 — the comp is the check, not the prose.
   -------------------------------------------------------------------------- */
/* 🔴 THE VEIL IS 0.75, NOT 0.85, AND THE MEASUREMENT THAT SETTLES IT IS TEXTURE
   AMPLITUDE — not tone, which the two artefacts do not share.
   ⚠️ The comp's ice photograph and the build's are the SAME image at different
   resolutions: the attachment is 950 x 505 stretched to cover 1920 x 995, a 2.02x
   upscale, so the build's copy is smoother and lighter than the comp's and no
   tone-based comparison between them means anything (an edge regression on the
   comp's own photo returned alphas of 0.31, 0.60 and 0.64 on three edges, and
   fills of 264, 190 and 216 — the photo is not continuous across the boundary).
   What IS comparable is how much of the photograph's TEXTURE survives the veil.
   High-pass filtered (detrended against a 25 px blur, so the tone gradient drops
   out) the comp's photo has a std of 14.6 above the card and 18.6 below it, and
   the comp's card interior 3.3 at the top and 5.1 at the bottom. A veil of alpha
   scales texture by (1 - alpha), so 1 - 3.3/14.6 = 0.773 and 1 - 5.1/18.6 = 0.728
   — two independent readings agreeing to 6 %.
   ⚠️ --chumuk-veil-strong (0.85) is NOT changed: it has other consumers and 0.75
   is 12 % away, so this is a component value, not a re-pointed token.

   ⚠️ THE COMP'S CORNERS ARE SQUARE AND c08-how-it-works.md SAYS "rounded".
   Traced at the top-left corner (50, 4310) the fill is already present at
   dx = 0 on the card's very first row, and the enlarged crop shows a hard
   90° corner. So `border-radius` is 0 here, matching the comp; the spec's one
   word is REPORTED as a comp/spec conflict rather than resolved by rounding a
   corner the comp does not draw. §4.1 — the comp is the check, not the prose. */
.chumuk-howto {
	background-color: var( --chumuk-howto-veil );
	border-radius: 0;
}

/* --------------------------------------------------------------------------
   The video panel.

   🔴 THE FRAME TREATMENT IS RECORDED HERE, WHICH IS ACCEPTANCE CRITERION 6.
   c08-how-it-works.md offers a binary — "either art-direct the panel to a 4:5
   frame or accept pillarboxing" — on the stated premise that "the comp's video
   panel is landscape". 🔴 THAT PREMISE IS MEASURABLY WRONG: the panel is
   812 × 750, aspect 1.083, very nearly square. Left/right edges read 140 and
   952 at y = 4500 / 4700 / 4900 / 5100 and top/bottom read 4400 and 5150 at
   x = 200 / 400 / 700 / 900 — twelve readings, no variance.

   That measurement also DECIDES the binary, because 4:5 is arithmetically
   impossible here (§4.2): at the measured 812 px column width a 4:5 frame is
   1015 px tall, and the inner card it has to sit inside is 930. It would
   overrun the card before it overran the band.

   SO: the frame is the comp's own 812 / 750 box, and the 4:5 video and the
   3:4 poster are `object-fit: cover`, centre-cropped to fill it. Not
   pillarboxed — the comp's panel is filled edge to edge, with the marble
   surface running the full width. Nothing is scaled non-uniformly.
   The spec assigns the final call to the §3.10 fidelity pass; this is the
   measured basis it should start from.
   -------------------------------------------------------------------------- */
.chumuk-howto__video {
	--chumuk-howto-video-aspect: 812 / 750;
	--chumuk-play-size: 60px;

	aspect-ratio: var( --chumuk-howto-video-aspect );
	border-radius: var( --chumuk-card-radius );
	overflow: hidden;
	padding: 0;
}

/* core/cover pins its own min-height; the aspect box above is the height here,
   so that has to be released or the panel can only ever grow. */
.chumuk-howto__video.wp-block-cover {
	min-height: 0;
}

.chumuk-howto__video .wp-block-cover__image-background {
	object-fit: cover;
}

.chumuk-howto__video .wp-block-cover__inner-container {
	display: grid;
	block-size: 100%;
	inline-size: 100%;
	place-items: center;

	/* 🔴 THE ROW HAS TO BE DEFINITE, AND THAT IS WHAT KEEPS THE UNENHANCED
	   <video controls> INSIDE THE PANEL [build-audit-08 MAJOR 2].
	   Without this the implicit row is content-sized, so the figure's and the
	   video's own `block-size: 100%` below has nothing definite to resolve
	   against and computes to `auto`. The media then takes its height from a
	   ratio of its own — core's injected `aspect-ratio: 864 / 1080` on the
	   front end, the 1624 × 2165 poster's 0.7501 in the editor canvas, where
	   core injects nothing — and overflows the 812/750 box, so `overflow:
	   hidden` on the panel clips the bottom, which is exactly where Chromium
	   paints the native control bar. Measured before this line, JS off:
	   375 panel 279 × 257.7 / video 348.8 (91.1 px clipped) · 768 672 × 620.7 /
	   840 (219.3) · 1440 560 × 517.2 / 700 (182.8) · 1920 800 × 738.9 / 1000
	   (261.1). With it, video height == panel height at all four and the
	   control bar is inside the panel — Chromium's own play button measures
	   48 × 48 fully inside the panel box at 375 / 768 / 1440 / 1920, and at 1440
	   a real mouse click on its centre starts playback (currentTime 2.16 s).
	   THE SAME TRACK SIZES THE ENHANCED STATE, so it was A/B'd rather than
	   assumed: with the figure `display: none` and `.wp-block-buttons` the only
	   grid item, the play button's centre sits at the identical offset from the
	   panel centre (dx 0, dy +12) with this line and with it reverted, at all
	   four widths. `100%` and not `1fr` so that row keeps a length rather than
	   a share of free space. */
	grid-auto-rows: 100%;
}

/* --------------------------------------------------------------------------
   The two states, and which one is the default.

   The UNENHANCED state is the default and it is the one that works with no
   JS: the <video controls> fills the panel and the play button is not
   rendered. video-modal.js adds `.is-enhanced` only once it has confirmed
   `HTMLDialogElement.prototype.showModal` exists and has wired the trigger up,
   and only then do they swap. Written this way round on purpose — the reverse
   leaves a JS failure showing a play button that does nothing over a hidden
   video, which is the worse of the two failures.
   -------------------------------------------------------------------------- */
/* 🔴 `core/video`, NOT `core/html` [checklist §10.82 r2]. The class can only land
   on core/video's FIGURE — its blockProps go there and the <video> element takes
   no className — so the figure is the layout box and the media fills it. Both are
   sized here because the figure is now the grid child the cover centres. */
.chumuk-howto__player {
	margin: 0;
}

.chumuk-howto__player,
.chumuk-howto__player video {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
}

/* 🔴 AND THE MEDIA CARRIES THE PANEL'S OWN RATIO, BECAUSE THE EDITOR CANVAS PUTS A
   WRAPPER BETWEEN THE FIGURE AND THE <video> [build-audit-08 MAJOR 2, second surface].
   Measured in the canvas with all writes aborted: the <video>'s parent there is
   `<div class="components-disabled">` — @wordpress/components' Disabled wrapper, which
   core/video's edit component renders and the front end has none of — and it is
   content-sized, so the `block-size: 100%` above has no definite containing block and
   computes to `auto`. The media then falls back to a ratio of its own (in the canvas the
   1624 × 2165 poster's 0.7501, since core injects no width/height/aspect-ratio there) and
   overflows the clipped panel: figure 462.6 but video 667.6, 205.1 px of control bar gone.
   812/750 of the same width the panel is 812/750 of IS the panel's height, by
   construction, so this pins the media to the panel on either surface without depending on
   any wrapper. It is the panel's registered `--chumuk-howto-video-aspect`, not a second
   copy of the number.
   NOT `!important`, deliberately: on the front end `render_block_core_video()` emits
   `style="aspect-ratio: 864 / 1080;"` inline and inline outranks every selector, so this
   declaration loses there — and it is meant to, because there the `block-size: 100%` above
   does resolve (517.2 px at 1440) and a resolved block-size governs over any ratio. This
   rule is the editor-canvas half of the same guarantee.
   Scoped to `.chumuk-howto__video` so it cannot reach the lightbox: video-modal.js MOVES
   the figure out of the panel and into `.chumuk-video-dialog__frame`, where the video is
   shown whole at its own ratio. */
.chumuk-howto__video .chumuk-howto__player video {
	aspect-ratio: var( --chumuk-howto-video-aspect );
}

.chumuk-howto__video .wp-block-buttons {
	display: none;
}

.chumuk-howto__video.is-enhanced .wp-block-buttons {
	display: flex;
}

/* The figure is what is hidden, so the media inside it goes with it. */
.chumuk-howto__video.is-enhanced .chumuk-howto__player {
	display: none;
}

/* --------------------------------------------------------------------------
   The play button — `red`, and DELIBERATELY THE EXISTING ONE [§10.44 r4].

   The comp draws this #FF0000 and `red` is #FF0007: Δ is 7/255 on the blue
   channel alone, inside design-tokens.md §2.1's own ≤ 8/255 consolidation
   rule, so they are the same colour. Sampled at the button's centre the comp
   reads exactly (255, 0, 0). NO SECOND RED IS DEFINED HERE — §3.11 define-once,
   and §2.1 records that `red` therefore has two uses, the error semantic and
   this glyph. The fill arrives as core's own `has-red-background-color` from
   the block attribute, so this file names no colour for it at all.

   THE GLYPH IS A CLIP-PATH TRIANGLE, NOT AN INLINE SVG, AND THAT IS A REPORTED
   DEVIATION. c08-how-it-works.md says the button "carr[ies] the inline-SVG play
   glyph". `core/button` cannot hold one: its content is a RichText field, so an
   <svg> inside it is not part of what `save()` produces and the editor would
   flag the block as having "unexpected or invalid content" — the exact failure
   00-conventions.md §6 gates against. A nested core/html is not available
   either, because core/button takes no inner blocks. So the label is real text
   (which is what gives the control its accessible name) clipped away visually,
   and the triangle is drawn geometrically — resolution-independent, one
   element, no second colour.
   -------------------------------------------------------------------------- */
.chumuk-howto__play .wp-block-button__link {
	position: relative;
	display: grid;
	place-items: center;
	inline-size: var( --chumuk-play-size );
	block-size: var( --chumuk-play-size );
	padding: 0;
	border-radius: var( --wp--custom--pill-radius );
	/* The label is the accessible name and must stay in the a11y tree, so it is
	   clipped rather than `display: none`-d or `visibility: hidden`. */
	overflow: hidden;
	text-indent: -100vw;
	white-space: nowrap;
}

.chumuk-howto__play .wp-block-button__link::after {
	content: "";
	position: absolute;
	inline-size: calc( var( --chumuk-play-size ) / 4 );
	block-size: calc( var( --chumuk-play-size ) / 3.4 );
	/* Optical centring: a triangle's visual centre sits left of its bounding
	   box centre. The comp's white glyph measures 19 × 22 inside the 60 px
	   disc and sits 1–2 px right of centre; this reproduces that. */
	margin-inline-start: calc( var( --chumuk-play-size ) / 22 );
	background-color: currentColor;
	clip-path: polygon( 0 0, 100% 50%, 0 100% );
}

.chumuk-howto__play .wp-block-button__link:hover {
	transform: scale( 1.06 );
	transition: transform var( --chumuk-dur-fast ) var( --chumuk-ease );
}

/* 🔴 THE PLAY BUTTON'S FOCUS RING IS NOT DECLARED HERE ANY MORE. It moved to the
   STANDING TWO-TONE RULE near the top of this file (search
   `chumuk-ring-duo`), because §10.82 r4 made it a rule rather than a C08
   detail: `.chumuk-howto__play .wp-block-button__link:focus-visible` is one of
   that rule's selectors, and C13/C15 join the same list.
   The history stays here because it is C08's: the token layer ships a ring for
   `a:not(.wp-element-button)` only and there is still no GLOBAL
   `.wp-element-button:focus-visible` rule (step 11 owns that per §10.65 r4), so
   MEASURED without any rule this button took the UA default,
   `rgb(0, 95, 204) auto 1px` at 0 offset. §15.4's 3 px offset is preserved
   exactly — a dark-on-red edge at offset 0 would be the weakest pairing
   available — and the light companion is what makes the ring read on the
   poster's dark-blue sides, where the dark tone alone measured 1.30–1.99:1. */

/* --------------------------------------------------------------------------
   The three step rows.

   🔴 THE VEIL IS PAINTED BY A PSEUDO-ELEMENT, AND THAT IS WHAT THE
   className-ONLY RULE FORCES. In the comp the `--chumuk-veil-light` card
   starts AFTER the icon — the icon sits on the inner card, not on the step
   card. c08-how-it-works.md's structure puts the icon, the text group and the
   numeral all inside `.chumuk-step`, and agent-instructions §2 rule 8 allows a
   custom class on the outermost wrapper only, so the text group cannot be given
   one to paint. A `::before` spanning grid columns 2–3 paints exactly the
   region the comp fills, from one class. 00-conventions.md §2's stated
   consequence — patterns end up more nested than hand-written HTML — applies
   in reverse here: the nesting exists, so the paint is what has to move.

   ⚠️ CONTRAST OVER A PHOTOGRAPH IS NOT ASSUMED FROM THE VEIL VALUE
   [00-conventions.md §3.3, checklist §10.37]. §10.30's brand-ground rule does
   not reach a photograph. The composited hex and ratio for these rows are
   MEASURED FROM RENDERED PIXELS and reported in the build report — and note
   that the photographic ground is currently a reserved `ice` slot, so that
   measurement has to be RE-RUN when the real background lands.
   -------------------------------------------------------------------------- */
.chumuk-step {
	--chumuk-step-icon: 100px;
	--chumuk-step-card-radius: 8px;
	/* Declared separately from --chumuk-step-icon even though both measure
	   100 px: they are two independent readings (the icon's ink box x 1018–1118,
	   and the card's height y 4853–4953) that happen to agree. Collapsing them
	   into one property would make a future correction to either silently move
	   the other — the "duplicated token value" failure in 00-conventions.md
	   §4.5, arrived at from the opposite direction. */
	--chumuk-step-card-h: 100px;

	/* ✅ DECIDED [checklist §10.82 r3, registered in design-tokens.md §2.4]:
	   the ghost ordinal's size is a --chumuk-* custom property at 76 px, NOT a
	   seventeenth `fontSizes` preset. [MEASURED] comp digits 57 px tall ÷ the
	   display serif's LINING digit height = 76.x → 76.
	   ⚠️ RE-DERIVED 2026-08-20 [§10.87] after the family changed to Playfair
	   Display. The original arithmetic cited Instrument Serif's 0.745 em; the
	   value survives because Playfair's LINING digit height MEASURES 0.7414 em
	   (43 px at 58 px, shared-baseline probe), giving 57 ÷ 0.7414 = 76.9 → 76.
	   **This is a coincidence of two faces agreeing to within 0.5 %, not a
	   derivation that transfers** — and it holds ONLY because the rule above
	   asks for `lining-nums`. Playfair's default figures would give 57 ÷ 0.5425
	   = 105 px. The 0.58 width-to-height ratio that the original used to
	   identify the serif no longer discriminates and is struck; the width
	   derivation (84.6) is deliberately NOT used,
	   because digit height is measured directly while advance width varies per
	   digit. A preset would appear in the editor's font-size picker, where an
	   author could apply "ghost numeral size" to a paragraph — ~~and it would
	   break §10.41's count of 16~~ ⚠️ **[figure struck 2026-08-22, §10.102: the
	   count is 18 now, and it is not a constraint. The picker argument above
	   stands on its own.]** The cost — the client cannot change it in the editor
	   — is correct for an ordinal the design owns. */
	--chumuk-step-ghost-size: var( --wp--preset--font-size--display-4 );  /* 76px — §10.97 */

	position: relative;
	display: grid;
	grid-template-columns: var( --chumuk-step-icon ) 1fr auto;
	align-items: center;
	column-gap: var( --wp--preset--spacing--60 );
	/* 100 px card + 64 px (`80`) gap = a 164 px pitch against the measured 165. */
	min-block-size: var( --chumuk-step-card-h );
	margin-block-start: var( --wp--preset--spacing--80 );
}

.chumuk-step::before {
	content: "";
	position: absolute;
	z-index: 0;
	inset-block: 0;
	inset-inline-end: 0;
	inset-inline-start: calc( var( --chumuk-step-icon ) + var( --wp--preset--spacing--60 ) );
	border-radius: var( --chumuk-step-card-radius );
	background-color: var( --chumuk-veil-light );
}

.chumuk-step > * {
	position: relative;
	z-index: 1;
	margin-block: 0;
}

.chumuk-step__icon {
	inline-size: var( --chumuk-step-icon );
	block-size: var( --chumuk-step-icon );
	color: var( --chumuk-text );
}

/* The text group is grid column 2. Padding goes on it rather than on the row,
   so the icon keeps its own full-height cell and the veil's inset arithmetic
   above stays a single expression. */
.chumuk-step > .wp-block-group {
	display: grid;
	gap: var( --wp--preset--spacing--10 );
	padding-inline: var( --chumuk-card-panel-pad );
	padding-block: var( --wp--preset--spacing--30 );
}

.chumuk-step > .wp-block-group > * {
	margin-block: 0;
}

/* --------------------------------------------------------------------------
   The ghost numeral.

   ⚠️ NOT A HEADING — c08-how-it-works.md is explicit, and it is `aria-hidden`
   as well: "01" carries no information a screen-reader user needs that the
   three rows' order does not already give them.

   ✅ ITS SIZE IS DECIDED: 76 px, via `--chumuk-step-ghost-size` on
   `.chumuk-step` above [checklist §10.82 r3, design-tokens.md §2.4]. Measured in
   the comp the digits are 57 px tall (ink 4896→4952) and the "0" is 33 px wide
   (strokes 1706–1716 and 1728–1738), a width-to-height ratio of 0.579.

   🔴 CORRECTED 2026-08-20 [checklist §10.87] — this paragraph still carried the
   Instrument Serif arithmetic after the family changed, and BOTH of its numbers
   were superseded by the swap. It is the stale twin of the corrected note on
   `--chumuk-step-ghost-size` above; the value is unchanged, the reasoning is not.
     ~~Geist's "0" measures 0.76–0.83 wide per unit tall at weights 400–800 and
     Instrument Serif's 0.52 — so at 0.58 the comp's numeral is the SERIF, and
     57 / 0.745 = 76.5 from the height gives the value.~~
   ⚠️ THE WIDTH-TO-HEIGHT RATIO NO LONGER IDENTIFIES THE FACE, AND SAYING SO IS THE
   HONEST READING. Re-measured in this browser on the real webfonts at 200 px with
   a shared-baseline "H 0 H" probe (ink bbox asserted clear of the crop edge on
   every probe, per §10.87 r7): Playfair Display 500 `lining-nums` zero = 0.696
   wide per unit tall, Geist = 0.779, Georgia = 0.920. The comp's 0.579 matches
   NONE of the three, so the ratio discriminates nothing and is struck rather than
   re-pointed at Playfair.
   The value survives on the HEIGHT derivation alone, which is measured directly:
   Playfair's LINING digit height is 0.740 em (148 px ink at 200 px, independently
   reproducing the 0.7414 em recorded for the token above to 0.2 %), and
   57 / 0.740 = 77.0 → the shipped 76 px, within the ±1 px of a pixel scan.
   🔴 It holds ONLY because `lining-nums` is asked for: Playfair's DEFAULT figures
   measure 0.545 em here, which would demand 105 px.
   REJECTED: `h2` 58 px (what shipped provisionally at step 6 — 24 % under the
   comp) and `display-2` — 104 px when this was written, 102 px since §10.95 r2,
   and it overflows the 100 px row either way, so the rejection is unaffected and
   only the figure is re-pointed [swept 2026-08-21]. The block therefore
   carries NO `fontSize` attribute: a decorative ordinal is component geometry,
   not a level in the typographic scale, so it takes no preset — ~~and the count
   of registered `fontSizes` stays 16 (§10.41)~~.
   ⚠️ **FIGURE STRUCK 2026-08-22 [§10.102].** The count was 16 when this was
   written and is **18** now (`display-4` at §10.100 r4, `h7` at §10.101 r6).
   **The reasoning is untouched** — a decorative ordinal still takes no preset —
   only the number was wrong, and it was wrong because it was RESTATED here
   instead of cited. The live figure lives in the checklist and in
   `WP_Theme_JSON_Resolver`; this comment no longer carries one.

   ~~The tint is `--chumuk-border-hairline`, ALIASED rather than copied. Its
   value is ink at 12 %, and the comp's numeral measures ink at 0.127 over the
   card — the same colour to within measurement error. Aliasing keeps one value
   in one place, where declaring `rgb(52 52 52 / 0.12)` a second time would be
   the duplication 00-conventions.md §4.5 makes a gate.~~

   🔴 **UN-ALIASED 2026-08-22 [F4 / F23, checklist §10.101]. THE ALIAS WAS
   CORRECT REASONING ABOUT A VALUE THAT THEN CHANGED UNDERNEATH IT.** F4 moved
   `--chumuk-border-hairline` from 12 % to **20 %**, its own comp-measured
   value. The alias faithfully followed — and in doing so would have painted
   these numerals at 0.20 against **their own measured 0.127**.

   The two values were never the same quantity; they were two independently
   measured things that happened to coincide at 12 %. An alias cannot express
   "these agree today", only "these are the same thing", and they are not: one
   is a RULE colour on white, the other a GHOST NUMERAL over the C08 card.

   ✅ So the token is SPLIT BY ROLE rather than the shared change being forced
   through — the remedy F4's own deferral note anticipated. The literal here is
   not a duplicate of the hairline any more; it is this role's own measurement,
   and §4.5's define-once gate is satisfied because there is now exactly one
   definition of each of the two distinct values.
   -------------------------------------------------------------------------- */
.chumuk-step__num {
	/* [MEASURED] the comp's ghost numeral is ink at 0.127 over the card —
	   (210,245,247) on (233,254,254). Kept at its own measurement. */
	--chumuk-step-num-tint: rgb( 52 52 52 / 0.127 );

	justify-self: end;
	padding-inline-end: var( --chumuk-card-panel-pad );
	color: var( --chumuk-step-num-tint );
	/* 76 px at line-height 1 inside a 100 px row: 24 px of clearance, so the
	   row is never clipped. Verified on the rendered page, not assumed. */
	/* ➕ Now the registered `display-4` preset [§10.97 / D1]. The custom property
	   is kept as the single source of the 76 px and simply reads the preset, so
	   §2.4's register and theme.json cannot drift to two values. */
	font-size: var( --chumuk-step-ghost-size );
	font-family: var( --wp--custom--font-heading );
	/* 🔴 `lining-nums` IS LOAD-BEARING HERE, NOT DECORATION [§10.87]. Playfair
	   Display's DEFAULT figures are short — a `0` measures 0.5425 em against a
	   0.7075 em cap. `tabular-nums` alone selects tabular OLD-STYLE figures, so
	   this ordinal would render at roughly two-thirds height. With `lining-nums`
	   the measured digit height is 43 px at 58 px = 0.7414 em, which is why the
	   76 px token below survived the family change at all. */
	font-variant-numeric: lining-nums tabular-nums;
	line-height: 1;
	pointer-events: none;
	user-select: none;
}

/* --------------------------------------------------------------------------
   The lightbox. <dialog> is MANDATED by c08-how-it-works.md, and the reason is
   that it brings the focus trap and the ESC close with it — neither is
   reimplemented in JS.

   The open animation is a keyframe animation on purpose: style.css's global
   `@media (prefers-reduced-motion: reduce)` block already forces
   `animation-duration: 0.01ms !important` on everything, so this needs no
   media query of its own and cannot drift out of step with the global switch
   (00-conventions.md §5).
   -------------------------------------------------------------------------- */
.chumuk-video-dialog {
	/* [DERIVED] — the comp draws no lightbox, so there is nothing to measure
	   here. 780 px is the 4:5 source's own 864 px width rounded down inside a
	   92vh ceiling, so the video is never upscaled past its encode. */
	--chumuk-video-dialog-max: min( 92vw, 780px );

	max-inline-size: var( --chumuk-video-dialog-max );
	max-block-size: 92vh;
	inline-size: auto;
	padding: 0;
	border: 0;
	border-radius: var( --chumuk-card-radius );
	background: transparent;
	overflow: visible;
}

.chumuk-video-dialog[open] {
	animation: chumuk-dialog-in var( --chumuk-dur-base ) var( --chumuk-ease ) both;
}

.chumuk-video-dialog::backdrop {
	background-color: rgb( 52 52 52 / 0.72 );
	animation: chumuk-dialog-fade var( --chumuk-dur-base ) var( --chumuk-ease ) both;
}

.chumuk-video-dialog__frame {
	/* `position: relative` is what the close control is positioned against. It
	   is set on the FRAME and not on the dialog on purpose: a modal <dialog> is
	   centred by the UA with `position: fixed; inset: 0; margin: auto`, and
	   overriding its `position` breaks that centring. */
	position: relative;
	display: grid;
	overflow: hidden;
	border-radius: var( --chumuk-card-radius );
	background-color: var( --chumuk-text );
}

/* --------------------------------------------------------------------------
   THE VISIBLE CLOSE CONTROL [checklist §10.82 r6 — D4 DECIDED].

   ESC and a backdrop click both worked before this and still do; what was
   missing is a DISCOVERABLE AFFORDANCE for pointer and touch users, who have
   no way to know either gesture exists. §10.82 r6 also settles the copy
   question the step-6 build correctly refused to answer on its own: `Close` is
   a BUILD-OWNED ACCESSIBILITY STRING, listed in content-source.md §8.2, on the
   same ground as `Packaging` — an accessible name for a UI control is not
   marketing copy. This closes checklist open question 9.

   IT IS TEXT, NOT A GLYPH, AND THAT IS DELIBERATE. §10.82 r6 forbids inventing
   an icon that is not already in this build's SVG vocabulary, and a grep of
   every pattern, part and template finds NO close/cross glyph anywhere in it —
   so the sanctioned fallback, text, is what ships. The label is therefore both
   the visible affordance and the accessible name; there is no second string
   and no `aria-label` to drift from it.

   COLOUR: `white` ground with `ink` text — 12.44:1, and it holds whatever the
   video's first frame happens to be behind it, because the pill carries its own
   background rather than relying on the frame. §10.30's rule (ink, never white,
   on any light ground) is satisfied by construction. Measured on the rendered
   composite in the fix report.

   SIZE is [DERIVED] — the comp draws no lightbox at all, exactly as
   `--chumuk-video-dialog-max` above is [DERIVED]. 44 px is WCAG 2.5.5's target
   size, not a comp reading, and it is recorded as such rather than presented as
   measured.

   FOCUS: the two-tone standing ring, because this control sits over video
   pixels whose colour is unknown — its selector is in that rule's list near the
   top of this file, NOT re-declared here.
   -------------------------------------------------------------------------- */
.chumuk-video-dialog__close {
	--chumuk-video-dialog-close-size: 44px;

	position: absolute;
	z-index: 1;
	inset-block-start: var( --wp--preset--spacing--30 );
	inset-inline-end: var( --wp--preset--spacing--30 );
	min-inline-size: var( --chumuk-video-dialog-close-size );
	min-block-size: var( --chumuk-video-dialog-close-size );
	padding-block: var( --wp--preset--spacing--30 );
	padding-inline: var( --wp--preset--spacing--40 );
	border: 0;
	border-radius: var( --wp--custom--pill-radius );
	background-color: var( --chumuk-bg );
	color: var( --chumuk-text );
	font-family: inherit;
	font-size: var( --wp--preset--font-size--label-sm );
	line-height: 1;
	cursor: pointer;
}

/* Inside the dialog the video is shown WHOLE — `contain`, not `cover`. The
   panel in the page is an art-directed 812/750 crop of a 4:5 source; the
   lightbox is where the visitor actually watches it, so it gets the full frame
   and nothing is cut off.

   🔴 WHAT core/video ACTUALLY EMITS ON WP 7.0.4 — MEASURED, NOT ASSUMED
   [build-audit-08 MINOR 1; corrected 2026-08-19]. Read off the rendered
   homepage with curl, and traced to `render_block_core_video()` in
   `wp-includes/blocks/video.php`:

       <video height="1080" style="aspect-ratio: 864 / 1080;" width="864"
              controls poster="…-poster.jpg" preload="none"
              src="…-how-to-make.mp4" playsinline>

   The callback reads the attachment metadata and does three things to the tag:
   `set_attribute('width')`, `set_attribute('height')` and it PREPENDS
   `aspect-ratio: W / H;` to the inline `style`. The build authors none of that
   — there are 0 `style=` in the stored post 45.

   Two premises this comment used to state are therefore FALSE and are struck:
   • ~~"`core/video` has no width/height attributes at all"~~ — it has both,
     plus an inline ratio.
   • ~~"the browser has no metadata to take an intrinsic size from, so an
     undeclared box would fall back to 300×150"~~ — `preload="none"` does
     withhold the file's own metadata, but a `poster` is set, and a poster
     supplies intrinsic dimensions on its own. Measured in the block editor
     canvas, where core injects nothing: the media sized itself on the
     1624 × 2165 poster's 0.7501, never on 300×150.

   CONSEQUENCE FOR THE DECLARATION BELOW: an inline declaration outranks every
   selector, so on the front end `aspect-ratio: 864 / 1080` here is SHADOWED by
   core's identical inline value and changes nothing that renders.

   IT IS KEPT ANYWAY, and this is why — it is not dead, only usually inert.
   `render_block_core_video()` returns the content UNTOUCHED, injecting no
   width, no height and no inline ratio, whenever the attachment metadata has
   no usable integer `width`/`height` (its own early return). In that one state
   this declaration is what still holds the lightbox at the encode's ratio, and
   it is deliberately the SAME number core would have injected, so the two can
   never disagree. Anyone re-encoding the MP4 at a new size must change it in
   both places — core takes its value from the attachment metadata, not from
   here. */
.chumuk-video-dialog__frame .chumuk-howto__player,
.chumuk-video-dialog__frame .chumuk-howto__player video {
	display: block;
	max-block-size: 92vh;
	inline-size: 100%;
	block-size: auto;
	object-fit: contain;
}

.chumuk-video-dialog__frame .chumuk-howto__player video {
	aspect-ratio: 864 / 1080;
}

@keyframes chumuk-dialog-in {
	from {
		opacity: 0;
		transform: scale( 0.96 );
	}
}

@keyframes chumuk-dialog-fade {
	from {
		opacity: 0;
	}
}

/* --------------------------------------------------------------------------
   Responsive — c08-how-it-works.md: "Two-column → stacked below `md`."
   781 px is the breakpoint core itself stacks core/columns at, and the rest of
   this file already uses it, so the CSS and the block layout change together.
   -------------------------------------------------------------------------- */
@media ( max-width: 781px ) {
	.chumuk-howto-section {
		/* Edge to edge below md. The 48 px inset plus the card's own
		   `--chumuk-section-pad` floor would take 192 px of a 375 px viewport
		   before any content is laid out. */
		--chumuk-howto-inset: 0px;
	}

	.chumuk-step {
		/* The icon keeps its own column so the three rows stay a scannable
		   list; only the numeral is dropped, because at this width it would
		   take the space the description needs and it carries no information
		   (it is already aria-hidden). */
		grid-template-columns: minmax( 0, var( --chumuk-step-icon ) ) 1fr;
		column-gap: var( --wp--preset--spacing--30 );
	}

	.chumuk-step::before {
		inset-inline-start: calc( var( --chumuk-step-icon ) + var( --wp--preset--spacing--30 ) );
	}

	.chumuk-step__num {
		display: none;
	}
}

@media ( max-width: 480px ) {
	.chumuk-step {
		--chumuk-step-icon: 56px;
	}
}

/* --------------------------------------------------------------------------
   🔴 C08 STAYS STACKED TO 1199 px — THE TWO-COLUMN SPLIT UN-STACKS 418 px BEFORE
   THE COLUMN CAN CARRY IT [owner decision 2026-08-20, checklist §10.88
   sequencing; defect found by the fix-17 pass and independently confirmed].

   WHAT WAS WRONG, MEASURED. `.chumuk-step` is a `100px 1fr auto` grid with a
   64 px column gap. From 782 px core/columns un-stacks this head and drops the
   three step rows into a ~263 px column, while the row's FIXED furniture is
   100 (icon) + 64 + 64 (gaps) + 76 (the ghost ordinal) = 304 px — already wider
   than the column. The `1fr` text track is therefore crushed to whatever is
   left. Step 1's paragraph, measured at every integer width in the webfont
   state before this rule existed:

     viewport   step-1 paragraph   its line count   tallest step row   ordinal
       781          533.0 px             1              100.00 px      display:none
       782           22.1 px            27              735.50 px      display:block
       900           22.7 px            26              713.22 px      display:block
      1024           65.3 px             9              275.52 px      display:block
      1200          142.7 px             4              156.78 px      display:block
      1440          254.7 px             2              110.53 px      display:block

   ⚠️ TWO BREAKPOINTS THAT SHARE A NUMBER ARE NOT THE SAME EVENT. The
   `@media (max-width: 781px)` block above hides `.chumuk-step__num` and drops the
   column gap to `spacing|30`, so the 76 px ordinal and 128 px of gap return at
   EXACTLY the width where the column becomes narrow. The suppression breakpoint
   was aligned to core's stacking breakpoint on the assumption that un-stacking is
   what makes room; it is what removes it.

   This is PRE-EXISTING and not caused by the Playfair swap or by the reserved
   boxes: the fix-17 pass proved step-paragraph width byte-identical with its new
   C08 reserved box live and neutralised, and git-dated the responsible rules to
   earlier commits.

   ✅ THE DECIDED FIX: keep THIS head stacked over 782–1199 and un-stack at 1200,
   where the column finally has room. Below 781 the section already renders
   stacked and correct (533 px of measure), so this CONTINUES a working layout
   rather than inventing one — and the comp is a 1920 px design that offers no
   evidence for a two-column C08 at 800 px, its arrangement presupposing a wide
   right column. REJECTED: suppressing the ordinal alone (frees only 132 px,
   leaving ~108 px of text at 782 — still about ten lines for one sentence), and
   shrinking the icon and the gap (invents comp-free values at several
   breakpoints, which §3.11 / §4.5 exist to stop).

   HOW, AND WHY `!important`. Core's own stacking is
   `.wp-block-columns { flex-wrap: nowrap !important }` at `min-width: 782px` plus
   `flex-basis: 0; flex-grow: 1` on the columns; below 781 core stacks with
   `flex-basis: 100% !important`. Nothing but `!important` can beat core's own
   `!important`, and the `flex-basis` half is declared the same way core declares
   it so the two halves cannot come apart. SCOPED to `.chumuk-howto`'s own direct
   child so it reaches C08 and nothing else — the two-column split is used by
   several other sections and none of them has C08's fixed-furniture problem.

   ✅ THERE IS ALREADY A PRECEDENT FOR THIS SHAPE OF FIX IN THIS FILE, AND IT IS
   THE SAME CLASS, NOT A NEW IDEA. C07's responsive block (`@media (max-width:
   1319px)` on `.chumuk-store__form`, above) collapses that section to ONE column
   across 782–1319 for the same reason and says so: *"a single column is correct
   and readable at every width in the band; it is simply taller than a tablet
   layout would be"*, with the tablet restructure deferred to build step 11's
   responsive pass by checklist §10.67 r2.

   ⚠️ REPORTED, NOT RESOLVED HERE: C07 releases at 1320 and C08 releases at 1200,
   so 1200–1319 now renders C07 single-column beside a two-column C08. Both
   numbers are derived rather than guessed — C07's from its 1182 px three-column
   content box, C08's from the width at which the step row's 304 px of fixed
   furniture stops crushing the `1fr` text track — so they are not the same
   quantity and there is no arithmetic reason they should coincide. Whether the
   two should nevertheless be UNIFIED is a decision for step 11's responsive
   pass, which §10.67 r2 already owns; it is not taken here.
   -------------------------------------------------------------------------- */
@media ( min-width: 782px ) and ( max-width: 1199px ) {
	.chumuk-howto > .wp-block-columns {
		flex-wrap: wrap !important;
	}

	.chumuk-howto > .wp-block-columns > .wp-block-column {
		flex-basis: 100% !important;
	}
}

/* ==========================================================================
   C09 — STATS (build step 6)
   build-specs/c09-stats.md · design-tokens.md §2.1, §2.4, §2.5 · §4.2

   GEOMETRY, all [MEASURED] from pink-new-3.png at its native 1920:
     band            y 5290–6090 (800)          design-tokens.md §2.5
     photo card      x  173– 934 · y 5340–6039  (762 × 700)  r = 16
     right column    x  985–1746 (762) — the hairline rules' own extent
     gutter          x  935– 984 (50)
     hairline rules  FIVE of them, y 5587 / 5668 / 5749 / 5830 / 5911
     row pitch       81 px, constant across all four gaps
     icon disc       40 × 40, `ink`, x 985, first row y 5608–5647

   ⚠️ THE COLUMNS ARE 50/50 IN THE 1640 BOX, NOT THE COMP'S 173→1746 INSET, AND
   THAT IS A DECISION ALREADY ON RECORD. design-tokens.md §2.4's two-column row
   settles this: the build uses the `70` token (48 px) for the gutter, which
   "places the right column ≈ 15 px right of the comp — accepted under §3.11's
   proportional-approximation clause", and §2.4 lists this section's own 986 as
   one of the two observed readings. So the gutter is `70` and the two columns
   fill the content box; the delta is stated, not hidden behind a token
   claiming to be measured. §3.10 retired ±2 px overlay fidelity.

   ⚠️ THE MEASURED RULE COLOUR IS DARKER THAN THE TOKEN, AND THE TOKEN IS BUILT.
   `--chumuk-border-hairline` is ink at 12 %, which over white composites to
   #E7E7E7. The comp's rules read (214, 214, 214) = #D6D6D6 at all five rows,
   i.e. ≈ 20 %. A 1 px line can only be LIGHTENED by anti-aliasing, never
   darkened, so this is a real difference and not a sampling artefact. Acceptance
   criterion 4 requires this token and no hardcoded grey, so the token is what
   ships; the delta is REPORTED for design-tokens.md §2.1 rather than corrected
   here, where it would become a second definition (§3.11).
   -------------------------------------------------------------------------- */

.chumuk-stats {
	/* Padding is declared here rather than as a block attribute for the same
	   reason as C08's — see the note on `.chumuk-howto-section`.

	   🔴 THE `70` TOKEN, NOT `--chumuk-section-pad`, AND THE BAND CHECK IS WHY.
	   The comp's band is 800 px with a 700 px photo card in it, so the padding
	   is 50 above and 50 below. `--chumuk-section-pad` tops out at 80, which
	   measured 851 px against the 800 px band at 1920 — 51 px over, exactly the
	   overrun 00-conventions.md §4.2 exists to catch. `70` is 48 px, giving
	   700 + 96 = 796 against 800. Vertical padding costs no column width, so
	   there is nothing for a clamp to protect here.
	   ⚠️ ~~`70` is 48 px, giving 700 + 96 = 796 against 800~~ — the 4 px was
	   accepted rather than measured away, and it is 50: the comp's band is
	   y 5290-6089 (800) around a 700 px photo, so the clearance is 50 above and
	   50 below, which is exactly what the note itself computes and then rounds
	   down to the nearest preset. Held as a component value; 50 is not a step. */
	padding-block: var( --chumuk-stat-pad-block );

	/* 700 px is [MEASURED] (the photo card's own height); the floor and the vw
	   term are [DERIVED], as c37's banner height token already is. 36.5vw hits
	   700 exactly at the comp's native 1920, so the ceiling and the vw term
	   agree instead of the ceiling masking a mismatch. */
	--chumuk-stat-media-height: clamp( 320px, 36.5vw, 700px );
	/* 🔴 THE COMP'S CARD, NOT THE FILE'S OWN RATIO [§10.129]. Declared so the box
	   is reserved BEFORE the file loads: with only a height set, the width stays
	   `auto` until the intrinsic ratio is known and the row reflows sideways on
	   load. This is the half of §1.1 rule 1 that the removed `width`/`height`
	   attributes used to cover.

	   762 / 700 is [MEASURED] off `design/pink-new-3.png` at its native 1920 —
	   the card's hard edges are x 173→934 and y 5339→6039 inside a band running
	   5290→6090, i.e. 50 px of clearance above and below, matching the `70`
	   padding token this rule already uses. The five hairlines below it sit at
	   y 5587 / 5668 / 5749 / 5830 / 5911 and each measures 762 px wide, so the
	   text column is the same 762 and the figure is corroborated twice.
	   ⚠️ 762 / 700 = 1.0886 is ALSO what this file's own build-step comment
	   recorded as the slot in 2026-08, from an independent measurement — two
	   passes agreeing, which is why it is taken as the box rather than derived
	   again from the supplied file.

	   ~~The extracted glass's own intrinsic ratio (740 × 1427).~~ STRUCK: that
	   was attachment 86's shape, not the slot's, and it reserved a box of
	   363 × 700 — aspect 0.519 — where the comp draws 762 × 700. Reserving the
	   FILE's ratio is what made a wrong-shaped asset measure as though it fitted. */
	--chumuk-stat-media-aspect: 762 / 700;
	--chumuk-stat-disc: 40px;

	/* 🔴 C09's CONTENT IS NARROWER THAN THE SITE'S [§10.145]. MEASURED off the
	   comp: the image card runs x 173–934 and the text column's five hairlines
	   run x 985–1747, so the pair spans **1574** centred in 1920 — where the
	   global `contentSize` gives this band 1640 (x 140–1780) and made both
	   columns 796 against the comp's 762.

	   ⚠️ IT IS BAND-SPECIFIC, WHICH IS WHY IT IS DECLARED HERE AND NOT GLOBALLY.
	   C16's footer measures 1640 in the SAME comp (logo x 140, card right edge
	   1780), so the two bands genuinely differ and moving `contentSize` would
	   have dragged every other band with it.

	   With this file's existing 48 px column gap the pair solves to 763 each,
	   putting the 762 px image at x 173.5 against the comp's 173 and the text
	   column at 984.5 against 985 — inside a pixel, with no new gap token. */
	--chumuk-stat-measure: 1574px;
	/* 81 px pitch − 1 px rule − the 40 px disc = 40 px of padding, so 20 each
	   side. There is no 20 px entry on the `4`-based spacing scale
	   (design-tokens.md §2.3 goes 16 → 24), which is why this is a property and
	   not a preset. REPORTED for §2.4. */
	--chumuk-stat-row-pad: 20px;
	--chumuk-stat-head-offset: 11px;
	--chumuk-stat-pad-block: 50px;
}

/* Core's constrained layout caps this at `contentSize`; the band's own measure
   caps it further. `margin-inline: auto` already comes from core, so this is one
   declaration and no selector is strengthened. */
.chumuk-stats .wp-block-columns {
	max-inline-size: var( --chumuk-stat-measure );
}

/* 🔴 ~~verticalAlignment: center~~ ON BOTH COLUMNS — the comp top-aligns them, and
   centring is what put this whole column 28 px low. [MEASURED]: the comp's h2 caps
   ink at y 5360 beside a photo card whose top edge is 5339-5340, so the heading's
   line box starts 11 px below the card's top. Top-aligning closed 28 of the 39;
   this is the remaining 11.

   ⚠️ IT IS THE COLUMN'S PADDING, NOT THE HEADING'S MARGIN, AND THE FIRST ATTEMPT
   PROVED WHY. `.chumuk-stats h2 { margin-block-start: … }` is (0,1,1) and core's
   `:root :where(.is-layout-flow) > :first-child { margin-block-start: 0 }` is
   (0,2,0) — `:root` and `:first-child` are each a class-level and `:where()`
   contributes nothing — so core outranked it and the declaration computed 0 while
   the sibling `max-width` in the same rule applied normally. Padding is not in
   that fight at all.

   The four stat rows still sit 61 px below the comp's: that is D3's "Percentage of
   the blend." line (§10.82 r5), which the comp does not draw and which is a
   recorded decision, so it cannot be absorbed without removing the line. The band's
   height is set by the 700 px photo, so the rows moving costs nothing. */
.chumuk-stats .wp-block-columns > .wp-block-column:last-child {
	padding-block-start: var( --chumuk-stat-head-offset );
}

/* The four rows are contiguous in the comp, so their wrapper carries
   `blockGap: 0` in the markup [§10.145] and nothing here needs to zero a margin.
   This rule exists only to stop `core/group`'s default flow margins reaching the
   wrapper itself from the column above it. */
.chumuk-stats__rows {
	margin-block-start: var( --wp--preset--spacing--50 );
}

/* --------------------------------------------------------------------------
   The photograph. `cover` [§10.129] — the correctly-shaped photograph arrived,
   so the treatment that existed to protect a wrong-shaped one retires with it.

   ~~`contain`, and the reason is an asset-shape mismatch that is reported
   rather than papered over: A14's glass is portrait (740 × 1427, aspect 0.519)
   and this slot is 1.089. The image is shown WHOLE at the reserved height and
   centred, so the product is never cropped through and never stretched.~~
   STRUCK on its own terms: the mismatch it described is gone. A35 (attachment
   136) is 743 × 649, aspect 1.1448, against the box's 1.0886 — a 5.2 % ratio
   gap, not a 110 % one. `contain` on that gap would letterbox 17.2 px of the
   section's white above and below a photograph whose own ground is warm grey,
   which the comp does not draw; `cover` fills the card edge to edge, which it
   does. MEASURED cost of `cover` here: scale 1.0786 (max of 762/743 and
   700/649), rendering 801.4 × 700 into 762 × 700, so 19.7 px is cropped from
   each side — 4.9 % of the file's width, taken from empty ground, and the glass,
   the stone and the blossom are all inside what remains. Nothing is stretched.

   ⚠️ The reserved height is still what keeps CLS at zero (§1.1 rule 1), and the
   height token is UNCHANGED by this swap — only the ratio moved, so the band
   height does not.
   -------------------------------------------------------------------------- */
.chumuk-stats .wp-block-image {
	margin-block: 0;
}

.chumuk-stats .wp-block-image img {
	display: block;
	aspect-ratio: var( --chumuk-stat-media-aspect );
	block-size: var( --chumuk-stat-media-height );
	inline-size: auto;
	max-inline-size: 100%;
	margin-inline: auto;
	border-radius: var( --chumuk-card-radius );
	object-fit: cover;
}

/* --------------------------------------------------------------------------
   The four rows.

   The hairline is `border-block-end` on `.chumuk-stat`, exactly as
   c09-stats.md's "Core-block gap" section specifies — which gives the four
   rules BELOW the rows. The comp draws FIVE, one above the first row as well,
   so `:first-of-type` carries a `border-block-start` too. Both edges come from
   the one token.
   -------------------------------------------------------------------------- */
.chumuk-stat {
	display: grid;
	grid-template-columns: var( --chumuk-stat-disc ) 1fr auto;
	align-items: center;
	column-gap: var( --wp--preset--spacing--50 );
	padding-block: var( --chumuk-stat-row-pad );
	border-block-end: 1px solid var( --chumuk-border-hairline );
}

.chumuk-stat:first-of-type {
	margin-block-start: var( --wp--preset--spacing--70 );
	border-block-start: 1px solid var( --chumuk-border-hairline );
}

.chumuk-stat > * {
	margin-block: 0;
}

/* --------------------------------------------------------------------------
   The icon discs. Each is ONE `evenodd` path filled `currentColor`, with the
   glyph knocked out of the disc, so THIS FILE SETS NO FILL AT ALL — the disc
   takes `ink` by inheriting the section's own text colour and the glyph is a
   hole showing the section's `white` through it.

   ⚠️ THE `fill` DECLARATIONS THAT USED TO BE HERE WERE AN EDITOR BUG, NOT A
   TIDINESS PROBLEM. `fill: var( --chumuk-text-invert )` on the glyph resolved
   to nothing inside `core/html`'s sandboxed `srcdoc` preview iframe, which does
   not inherit theme custom properties, so the four discs rendered solid black
   with no glyph in the block editor while looking correct on the front end.
   `currentColor` degrades to the iframe's own default; a `var()` does not. The
   full reasoning is in patterns/stats.php's docblock. Do not reintroduce a
   `fill` here.
   -------------------------------------------------------------------------- */
.chumuk-stat svg {
	display: block;
	inline-size: var( --chumuk-stat-disc );
	block-size: var( --chumuk-stat-disc );
	color: var( --chumuk-text );
}

/* --------------------------------------------------------------------------
   The value. Real text, right-aligned in its own row — never image-baked
   (§2 C09 acceptance, c09-stats.md acceptance 1). `tabular-nums` so 82 / 9 / 8
   / 1 share a right edge instead of drifting by a digit width.

   ⚠️ `h6` is a SIZE and this is a paragraph, so it stays in the body face: the family
   comes from `styles.elements.heading`, which a paragraph is not. Measured, the
   comp's "82%" is 20 px of digit ink → ≈ 27 px, and `h6` is the nearest
   registered entry at 26 (design-tokens.md §2.2). Reported.
   -------------------------------------------------------------------------- */
.chumuk-stat__value {
	justify-self: end;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
}

/* --------------------------------------------------------------------------
   Responsive — c09-stats.md: "Stacks below `md`; the right-aligned value stays
   right-aligned within its row." The grid above is what guarantees the second
   half of that: the value is in its own `auto` track with `justify-self: end`,
   so it holds the right edge at every width without a second rule.
   -------------------------------------------------------------------------- */
@media ( max-width: 781px ) {
	.chumuk-stats {
		--chumuk-stat-disc: 32px;
		--chumuk-stat-row-pad: var( --wp--preset--spacing--40 );
	}

	.chumuk-stat {
		column-gap: var( --wp--preset--spacing--40 );
	}
}

/* ==========================================================================
   COMPONENT LAYER — build step 7 (sections 8–9)

   c10-comparison.md · c11-counters.md
   ========================================================================== */

/* --------------------------------------------------------------------------
   C10 — THE COMPARISON BAND AND ITS VEILED CARD

   The band is `photo` in design-tokens.md §2.5's map (y 6090–7170, 1080 px).
   ✅ THE PHOTOGRAPH IS IN — `BG-2.jpg`, attachment 113, PLACEHOLDER-C10-BG
   closed 2026-08-22 [§10.102]. The page serves `BG-2-2048x1080.jpg` at 0.12 MB.
   ✅ AND THE RESERVED BOX DID ITS JOB: the band measured **1080 px before and
   after the swap** — the media swap cost NO layout change, which is what
   00-conventions.md §1.1 rule 1 reserves a box for. The card's composited
   contrast was re-measured against the real photograph rather than assumed:
   card surface `rgb(255,251,232)`, ink **11.98:1** (12.36:1 over the old `ice`
   placeholder).
   ~~⚠️ IT SHIPS WITHOUT THE PHOTOGRAPH… Tracked as PLACEHOLDER-C10-BG.~~

   `min-block-size` and not `block-size`: the table's own height must be able to
   exceed the comp's band rather than be clipped by it, and at narrow widths it
   does. The band check in §4.2 is against the 1920 comp, where the content
   fits inside 1080.
   -------------------------------------------------------------------------- */
.chumuk-compare-band {
	/* 1080 px is [MEASURED] — the comp's band. The vw term hits it exactly at
	   the comp's native 1920 (56.25vw = 1080), so the ceiling and the vw term
	   agree instead of the ceiling masking a mismatch — the same construction
	   as `--chumuk-stat-media-height`. The floor is [DERIVED]. */
	min-block-size: clamp( 560px, 56.25vw, 1080px );
}

/* --------------------------------------------------------------------------
   THE CARD IS TWO ZONES AND IT IS OPAQUE [§10.146].

   ~~`--chumuk-veil-strong` is 85 % white, so this is a COMPOSITED surface and
   its text contrast is verified against the composite, never against the token
   (00-conventions.md §3.3).~~ STRUCK ON MEASUREMENT: the comp's card is not a
   veil. Tested rather than assumed — an 85 % white veil over the photographic
   band would compute (245,250,236) at band-relative y 600 / x 140, where the
   comp measures (235,255,184). They agree on no channel, and a lemon slice that
   sits behind the card's top-left shows through not at all.

   ZONE 1 — the head. Flat cream, MEASURED `rgb(255,255,228)` across the whole
   strip from the card top to band-relative y 329, where a hard step to
   (255,255,200) begins zone 2. Registered as `compare-cream`.

   ZONE 2 — the table. A gradient, its DIRECTION measured from the four corners
   of the zone rather than guessed:

     top-left  (229,254,187)      top-right    (255,255,213)
     bottom-left (195,232,126)    bottom-right (255,254,172)

   — a pale green at the BOTTOM-LEFT running to a pale cream-yellow at the
   TOP-RIGHT, so `linear-gradient( to top right, … )` with the two extreme
   corners as its stops: `compare-green` and `compare-yellow`.

   ⚠️ IT IS AN APPROXIMATION OF THE INTENT, NOT A DERIVATION, AND IS LABELLED SO
   — the same honesty §10.113 A2 applies to `display-3`. The comp's fill is NOT a
   clean two-stop ramp: red saturates at 255 across the middle, so the centre
   measures (255,255,180) where a linear RGB interpolation of the two corners
   would give (225,243,169). This reproduces the direction, the endpoints and the
   reading. It does not claim to be the comp's own ramp.

   🔴 THE BOUNDARY IS THE HEAD'S OWN BOTTOM EDGE, NOT A LENGTH. The gradient is
   on the card and the cream bleeds out of the head to the card's padding edges,
   so the step lands wherever the head ends and no magic number has to track the
   heading's height. MEASURED in the comp: cream ends at y 329 and the header
   glyphs start at 381 — 52 px of gradient above them, which is what the head's
   existing `75` bottom margin (56 px) already produces.

   THE INK IS `forest`, NOT `ink`. MEASURED: the comp's header cells, its body
   cells and its four underline rules are ONE colour, `rgb(17,58,0)` — a very
   dark green, not the site's `rgb(52,52,52)`.
   -------------------------------------------------------------------------- */
.chumuk-compare {
	background-image: linear-gradient(
		to top right,
		var( --wp--preset--color--compare-green ),
		var( --wp--preset--color--compare-yellow )
	);
	/* 🔴 ~~`--chumuk-card-radius` (16)~~ — [MEASURED] this card's corner is 20.
	   The arc was traced rather than eyeballed: at the top-left the fill's inset
	   from x 140 runs 13, 11, 9, 7, 5, 4, 3, 1, 0 at dy 1, 2, 3, 4, 6, 8, 10,
	   12, 16. A 20px corner predicts 13.8, 11.3, 9.4, 8.0, 5.8, 4.3, 3.2, 1.7,
	   0.4 — every reading within a pixel, low by the constant the antialias
	   threshold costs. A 16px corner predicts 10.4, 8.3, 5.4 at dy 1, 2, 4 and
	   closes by dy 16; it is too tight at every point. The top-right arc agrees.
	   `--chumuk-card-radius-lg` IS 20 and already exists, so this is the wrong
	   token rather than a missing one — nothing new is registered and the 16/20
	   split §10.68 r2 refuses to merge stays exactly as it is. */
	border-radius: var( --chumuk-card-radius-lg );
	/* MEASURED: the comp's card runs x 140–1780 and its table x 240–1681, so the
	   padding is 100 either side and the card is exactly `contentSize` wide. The
	   build had it at x 18, w 1884 — very nearly full-bleed. */
	max-inline-size: var( --wp--style--global--content-size );
	margin-inline: auto;
	/* `isolation` so the head's `z-index: -1` veil paints between this card's own
	   background and its content, instead of dropping behind the card. */
	isolation: isolate;
	--chumuk-compare-pad: 100px;
	/* [MEASURED] the comp's card top is y 6168 and its heading's line box starts
	   at 6231 — 63, not the 100 the other three sides take. */
	--chumuk-compare-pad-top: 63px;
	--chumuk-compare-head-below: 54px;
	--chumuk-compare-head-inset: 40px;
	/* [MEASURED] the comp's five body rows top at y 6559 / 6663 / 6767 / 6871 /
	   6975 — a 104 px pitch against the build's 95. */
	/* 104 px of row around a two-line verdict, whose rendered content box measures
	   68 (two 33 px lines plus the icon's -6 vertical-align), leaves 18 either
	   side. Verified against the rendered row, not computed from the type alone. */
	--chumuk-compare-cell-pad: 18px;
	--chumuk-compare-head-gap: 80px;
	--chumuk-compare-row-h: 104px;
	--chumuk-compare-pad-bottom: 38px;
	/* [MEASURED] the comp's card is y 6168-7089 (921) and its table ends at 7051,
	   so the bottom padding is 38 — not the 100 the sides take. */
	padding: var( --chumuk-compare-pad-top ) var( --chumuk-compare-pad ) var( --chumuk-compare-pad-bottom );
	/* 🔴 `ink`, RESTATED, BECAUSE core/cover FORCES WHITE ON ITS CONTENTS.
	   `.wp-block-cover` sets `color: #fff` for the case where content sits
	   directly on a dimmed photograph. Here the content sits on an 85 % WHITE
	   card instead, so the inherited white rendered white-on-white — measured
	   `rgb(255,255,255)` on `rgba(255,255,255,0.85)`, i.e. the five row labels
	   and every verdict were invisible. The card, not the cover, decides the
	   ink for anything inside it. ⚠️ The value is now `forest`, not `ink`
	   [§10.146]; the reasoning above is unchanged and still load-bearing. */
	color: var( --wp--preset--color--forest );
}

/* Zone 1 bleeds out of the head to the card's padding edges, which is what makes
   the boundary the head's own bottom edge rather than a length that has to track
   the heading's height.

   🔴 IT IS A POSITIONED PSEUDO-ELEMENT, AND THE FIRST ATTEMPT — NEGATIVE MARGINS
   ON THE HEAD ITSELF — WAS MEASURED AND FAILED. `margin-inline: calc( var(
   --chumuk-compare-pad ) * -1 )` computed to **0px**, not −100px: the head is a
   `core/columns` and core's own container rule for it wins. That is §4.8's
   warning arriving in practice — the `calc()` was correct and the cascade still
   took it away, which is why the computed value was checked instead of assumed.
   `position: absolute` insets are not margins, so nothing core emits can reach
   them; VERIFIED computed at −100px on all three sides. */
.chumuk-compare__head {
	position: relative;
}

.chumuk-compare__head::before {
	content: "";
	position: absolute;
	/* 🔴 ~~inset-block: -100px 0~~ — THIS IS WHAT LEFT NOTHING UNDER "CHOOSE
	   NATURE". The strip ended exactly on the head's last line box, so the
	   heading sat flush against the strip's lower edge with 100 px of air above
	   it. [MEASURED] on the comp: the strip runs y 6169-6409 (240) around a
	   heading whose line box is 6231-6355, i.e. 62 above and 54 below — not 100
	   and 0. It is NOT vertical centring (which a bottom margin could not have
	   moved); it is an asymmetric inset, and both halves are stated. */
	inset-block: calc( var( --chumuk-compare-pad-top ) * -1 ) calc( var( --chumuk-compare-head-below ) * -1 );
	/* 🔴 ~~`calc( ( --chumuk-compare-pad + --chumuk-compare-head-inset ) * -1 )`
	   = −140~~ — THAT OVERHUNG THE CARD BY 40 PX ON BOTH SIDES. The reasoning
	   was that the head sits "a further 40 inside" the card, so the strip had to
	   reach back 40 more. It does not: `--chumuk-compare-head-inset` is applied
	   as `padding-inline` on the head, and padding insets the head's CONTENT,
	   not its border box. The head's border box already IS the card's content
	   box, so the offset to the card's edge is `--chumuk-compare-pad` alone.
	   [MEASURED] live strip ran x 100-1820 against a card at 140-1780; the comp
	   puts both at 140-1780, one box, identical edges. */
	inset-inline: calc( var( --chumuk-compare-pad ) * -1 );
	/* 🔴 ~~`compare-cream`, opaque~~ — THE COMP'S STRIP IS GLASS OVER THE CARD.
	   ⚠️ The first test of this was thrown out before it was believed. Regressing
	   the strip against the ground ABOVE the card gave alpha 0.886, but the band
	   above and the strip both warm toward the right, so that slope is a shared
	   design direction as much as a see-through and proves nothing on its own.
	   The test that does work uses the strip's BOTTOM edge, where the card's own
	   background is the same surface on both sides: the strip's red just above
	   the edge tracks the card's red just below it at r = 0.945 over 1620
	   columns, with a slope of 0.203 — ALPHA 0.797, implied fill (253,254,244).
	   The live strip's slope across the same edge is exactly 0.000 and its
	   standard deviation exactly [0,0,0]: nothing read through it at all.
	   Two independent estimates, 0.797 and 0.886, bracket this token's 0.85, and
	   its own note requires the alpha be re-derived for each new ground rather
	   than inherited. It has been, on this one.
	   ⚠️ NO `backdrop-filter`. The strip keeps 0.31 of the card's variation where
	   alpha alone predicts 0.203 — it retains MORE structure than a plain veil,
	   not less, which is the opposite of what a blur does. The autocorrelation
	   agrees: 116px inside the strip against 91px in the card below and 128px in
	   the band above, no change in scale. A blur was written here and measured
	   away — sweeping blur(0..10px) moved the measured alpha by 0.000 at every
	   step, because our card's backdrop is a smooth gradient with nothing for a
	   blur to act on.
	   ⚠️ The composite lands ~8 DN cooler in blue than the comp's strip. That is
	   NOT the alpha: the comp's card carries soft decorative blobs behind the
	   strip and ours carries a flat gradient, so there is less to darken it. The
	   artwork is a missing asset [F104] and the alpha is not bent to hide it. */
	background-color: var( --chumuk-veil-strong );
	/* The strip's top corners ARE the card's top corners — same 20, or the
	   cream would cut a visible notch inside the card's own arc. */
	border-start-start-radius: var( --chumuk-card-radius-lg );
	border-start-end-radius: var( --chumuk-card-radius-lg );
	z-index: -1;
}

/* [MEASURED] the comp insets the header's content 40 px further than the table:
   its h2 inks from x 281 and its intro from 969, against a table whose first
   column starts at 240. */
.chumuk-compare__head {
	/* [MEASURED] the comp's heading box ends y 6355 and its table's head cell tops
	   at 6435 — 80. ~~`75`~~ = 56 left the table 20 px high. */
	margin-block-end: var( --chumuk-compare-head-gap );
	column-gap: var( --wp--preset--spacing--70 );
	padding-inline: var( --chumuk-compare-head-inset );
	/* 🔴 ~~`align-items: flex-end`~~ WAS A DEAD DECLARATION — computed `normal`.
	   Core emits a per-block container rule, `.wp-container-core-columns-is-
	   layout-7387b849`, at the same (0,1,0) specificity as this selector and
	   later in source order, so it simply wins. The same defect was found on
	   C11's and C13's heads during the sweep. Core sets `align-items` on the
	   CONTAINER and never `align-self` on the items, so moving the declaration
	   to the children goes around the collision entirely — no `!important`, no
	   selector strengthening, and no edit to post 45.
	   [MEASURED] the comp bottom-aligns the intro to the heading: its h2's two
	   lines end at y 6346 and its intro's two end at 6345. The build had both
	   columns stretched to the head's full 124.1, so the intro sat at the TOP —
	   its last line ended 67px above the heading's instead of level with it. */
	align-items: flex-end;
	/* 🔴 `ink`, NOT the card's `forest` — AND THIS DOES NOT TOUCH §10.146 r3.
	   That decision reads "the comp's header cells, body cells and four rules
	   are ONE colour, rgb(17,58,0)", and it is exactly right: a dark-pixel
	   census of the comp puts the table's column heads, row labels, body cells
	   and all four rules at rgb(17,58,0) with ZERO pixels of anything else.
	   Every role it names is a TABLE role. The section header is not one of
	   them, and it is a different colour: the h2 carries 7648 pixels of
	   rgb(52,52,52) and the intro 2677, with ZERO forest between them. That is
	   `ink` exactly. The card sets `forest` for the table and the head was
	   inheriting it — 4596 pixels of green where the comp has none. */
	color: var( --wp--preset--color--ink );
}

/* This is what `align-items: flex-end` above could not do — see its note. */
.chumuk-compare__head > .wp-block-column {
	align-self: flex-end;
}

/* --------------------------------------------------------------------------
   THE TABLE SCROLLS, IT DOES NOT STACK [c10-comparison.md Responsive].
   §2 C10's tech note offers either. Stacking destroys the row/column
   relationship that IS the content here — "which column said what about this
   feature" — and a screen-reader user navigating a stacked table loses exactly
   the comparison the section exists to make. So the table keeps its shape and
   the overflow is horizontal, inside the card, never on the page.
   -------------------------------------------------------------------------- */
.chumuk-compare__table {
	overflow-x: auto;
	margin-block: 0;
	/* The scroll affordance (acceptance 6): a shadow that appears only while
	   there is more table to the right. `background-attachment: local` pins the
	   first two layers to the content, so the cover fades reveal the shadow at
	   the scroll extremes and hide it at rest — no scroll listener, and it
	   cannot desynchronise from the actual scroll position the way a JS
	   affordance can. */
}

/* 🔴 THE AFFORDANCE ONLY EXISTS WHERE THE TABLE CAN ACTUALLY SCROLL.
   ⚠️ ~~`var( --wp--preset--color--white )` on the two cover fades~~ was struck
   once already [§10.146]: white hid the shadow against a white card, and when
   the card became the two-zone fill it painted two pale strips on top of the
   gradient. The replacement — `compare-green` at the left edge and
   `compare-yellow` at the right — did not fix that, it only changed its colour.
   A cover fade has to be INVISIBLE against what is behind it, and what is
   behind it is a gradient, not a colour. `compare-green` is that gradient's
   BOTTOM-LEFT endpoint and `compare-yellow` its TOP-RIGHT one, so each matched
   the card at exactly one corner and missed it everywhere else.
   [MEASURED] at the left edge the card steps DOWN 17 DN at x 240 and ramps back
   over the next 32px; at the right it runs 13 DN too light from x 1648 to 1676
   and steps back at 1680. The comp has neither: it ramps smoothly straight
   through both boundaries with no step at all.
   No flat colour can hide against a gradient, so the stack is scoped instead to
   the widths where it earns its keep. [MEASURED] the table's client width is
   viewport − 235 through this range and its content floor is 760, so the
   crossover was walked a pixel at a time rather than solved: 995 gives a client
   of exactly 760 and an overflow of 0, and 994 gives 759 and the first overflow
   of 1. Above 994 there is nothing to scroll and the comp shows nothing; at 994
   and below the affordance is real and acceptance 6 still holds. */
@media ( max-width: 994px ) {
	.chumuk-compare__table {
		background-image:
			linear-gradient( to right, var( --wp--preset--color--compare-green ), transparent ),
			linear-gradient( to left, var( --wp--preset--color--compare-yellow ), transparent ),
			linear-gradient( to right, var( --chumuk-border-hairline ), transparent ),
			linear-gradient( to left, var( --chumuk-border-hairline ), transparent );
		background-position: left center, right center, left center, right center;
		background-repeat: no-repeat;
		background-size: 32px 100%, 32px 100%, 12px 100%, 12px 100%;
		background-attachment: local, local, scroll, scroll;
	}
}

.chumuk-compare__table table {
	border-collapse: collapse;
	inline-size: 100%;
	/* Below this the cells wrap to unreadable slivers; above it the table
	   scrolls rather than compresses, which is the decision above. [DERIVED] */
	min-inline-size: 760px;
}

/* 🔴 NOT `:where( th, td )` — THAT SHIPPED AN OPAQUE INK RULE FOR FIVE DAYS
   [found by F4's consumer census, checklist §10.101]. `:where()` contributes
   ZERO specificity, and `core/table`'s own stylesheet sets `border: 1px solid`
   on its cells WITHOUT a colour, so the colour resolved to `currentColor` —
   MEASURED `rgb(52, 52, 52)`, fully opaque ink, where the hairline's 20 % was
   intended. It was invisible to step 7's acceptance run because that measured
   scope, contrast, icons and geometry, but never the border COLOUR.

   The selectors are written out so the rule carries (0,1,1) and beats core's
   `.wp-block-table td` on order. That is a component rule earning enough weight
   to beat a third-party default — the same case as `.chumuk-footer__social`'s
   focus ring — and NOT strengthening aimed at one of this file's own rules. */
.chumuk-compare__table th,
.chumuk-compare__table td {
	/* 🔴 NO HORIZONTAL PADDING, WHICH THE COMP STATES TWICE. Its four head rules
	   start at x 240 / 637 / 1033 / 1430 — exactly the column edges, not 12 px
	   inside them — and its first row label inks from 241 against a column that
	   also starts at 240. ~~spacing--30~~ (12) put the label at 253.
	   ⚠️ IT ALSO DECIDES A WRAP. "Drink Powder" measures 241 px in Playfair at the
	   38 px the head is now set to, in a 4th column the comp measures at 251; with
	   12 px of padding either side only 227 remained and the head broke onto two
	   lines, inflating the head row from 96 to 153 and the card by 57. The comp
	   does not wrap it because its substituted serif is ~13 % narrower at the same
	   cap height (measured in C01) — 210 px, which fits either way. Removing the
	   padding is what the comp measures AND what lets Playfair fit.
	   The block padding is retargeted below to the comp's 104 px row pitch. */
	padding: var( --chumuk-compare-cell-pad ) 0;
	/* 🔴 ZERO ALL FOUR SIDES FIRST — F24 WAS ONLY HALF-FIXED, AND I FIXED IT
	   [§10.102]. `core/table` sets `border: 1px solid` on its cells with NO
	   colour, so all four sides resolve to `currentColor`. §10.101 r4 replaced
	   the `:where()` selector to win the specificity fight and set
	   `border-block-end` — which corrected the ROW rules and left the top, left
	   and right sides still painting OPAQUE INK. MEASURED afterwards: 72 cell
	   borders at `rgb(52,52,52)` against 16 correct translucent ones, and a
	   screenshot shows heavy dark COLUMN rules the design never had.
	   ⚠️ The half-fix passed its own check because that check asked "is the
	   hairline being used?" and one side was enough to answer yes. The
	   shorthand reset is what makes the answer complete. */
	border: 0;
	/* ⚠️ ~~`border-block-end: 1px solid var( --chumuk-border-hairline )`~~ —
	   STRUCK 2026-08-24 [§10.146]. THE COMP DRAWS NO BODY ROW RULES AT ALL.
	   Verified rather than eyeballed: scanning all 530 rows of the comp's table
	   zone for a continuous dark run turned up 62 rows above threshold and EVERY
	   ONE of them is a line of text — counts of 300–580 px scattered across the
	   columns, never a run spanning the table. The only rules in the comp are the
	   four header underlines below.
	   🔴 AND THIS RETIRES F24's SURFACE, NOT F24's LESSON. §10.102's shorthand
	   reset (`border: 0` above) is what stops `core/table`'s uncoloured 1 px
	   border painting opaque ink on all four sides, and it is STILL REQUIRED —
	   it is now the only thing standing between this table and 88 dark cell
	   borders. What goes is the one side §10.102 kept. */
	text-align: start;
	vertical-align: top;
}

/* 🔴 THE FOUR COLUMNS ARE NOT EQUAL, AND THE COMP'S OWN ARITHMETIC IS THE PROOF
   [§10.146]. MEASURED: the header rules start at x 240 / 637 / 1033 / 1430 and
   the last one ends at 1681, so the columns are **397 / 396 / 397 / 251** and the
   table spans 240–1681 = 1441. That closes against the card twice over — the
   card runs 140–1780, so the padding is 100 on the left and 1780 − 1681 = 99 on
   the right, symmetric; and 1441 is exactly what a 1640 card with 100 either
   side leaves. Four EQUAL columns would put the heads at 240 / 600 / 960 / 1320,
   which is not where the comp draws them.
   ⚠️ The narrow fourth column is why the comp's *Drink Powder* cells wrap to two
   lines where the first three columns' mostly do not — the wrapping is a
   consequence of the width, not a separate thing to tune. */
.chumuk-compare__table :where( th, td ):nth-child( 1 ) { inline-size: 27.55%; }
.chumuk-compare__table :where( th, td ):nth-child( 2 ) { inline-size: 27.48%; }
.chumuk-compare__table :where( th, td ):nth-child( 3 ) { inline-size: 27.55%; }
.chumuk-compare__table :where( th, td ):nth-child( 4 ) { inline-size: 17.42%; }

/* 🔴 SERIF, LARGER, AND EACH WITH ITS OWN RULE [§10.146]. The comp sets the four
   column heads in the display face, not the body face, and underlines each with
   a 1 px `forest` rule 251 px long — MEASURED at y 438 across x 240–491,
   637–888, 1033–1284 and 1430–1681, all four exactly 251. Against a 397 px
   column that is 63.2 %, and ~~a proportion, so it tracks the column instead of
   pinning a pixel width~~ WAS THE WRONG READING OF THAT NUMBER. Four rules that
   are all 251 across columns of 397/396/397/251 cannot be a proportion: a
   proportion gives 251/250/251/**158**, and 63.2 % only looked right because it
   happens to equal 251/397 on the three wide columns. The comp's fourth column
   IS 251 wide and its rule IS 251 — full width — which is exactly the case the
   proportion gets wrong. [MEASURED] live 4th rule 158.5 against the comp's 251.
   It is a fixed length, capped so it cannot overflow a column narrower than
   itself once the table starts scrolling at its 760px floor.
   ~~`font-family: var( --wp--custom--font-body )` / `font-size: body` /
   `border-block-end: 2px solid var( --chumuk-border-hairline )`~~ struck — all
   three measured wrong against the comp. */
.chumuk-compare__table thead th {
	font-family: var( --wp--custom--font-heading );
	font-weight: 500;
	/* ~~h-6~~ = 25. [MEASURED] the comp's "Feature" caps 27 px against this
	   build's 18 at 25 px, so 25 x 27 / 18 = 37.5, and against Playfair's own
	   0.70 cap ratio 27 / 0.70 = 38.6 — both land on `h4` = 38, inside 2 %.
	   ⚠️ The comp's ink is 115 px wide against a live 84, which scales to 34 and
	   NOT to 38. That is the face, not the size: §10.113 records that the comp's
	   export substituted the serif, and C01's marquee measured the substitute
	   13 % narrower than Playfair at an identical cap height — 115 x 1.13 = 130
	   against the 128 Playfair sets at 38. Cap height is the size measurement. */
	font-size: var( --wp--preset--font-size--h-4 );
	border-block-end: 0;
	padding-block-end: 0;
}

.chumuk-compare__table thead th::after {
	content: "";
	display: block;
	inline-size: min( 251px, 100% );
	block-size: 1px;
	margin-block-start: var( --wp--preset--spacing--40 );
	background-color: var( --wp--preset--color--forest );
}

/* 🔴 CORE DRAWS A FIFTH RULE AND THE COMP HAS FOUR. `.wp-block-table thead`
   carries `border-bottom: 3px solid` in the block library stylesheet — CONFIRMED
   as the origin over CDP matched-rules, because it does not appear in any
   sheet reachable from `document.styleSheets`. It painted a continuous 1440px
   band at y 6533-6535 straight across all four columns, which is what made the
   four separate 251px rules read as one unbroken line. The comp has nothing
   there: its four rules sit alone with clear gaps between them.
   No `!important` and no selector strengthening — `.chumuk-compare__table thead`
   is (0,2,1) against core's (0,1,1) and simply wins on its own specificity. */
.chumuk-compare__table thead {
	border-block-end: 0;
}

/* The row label. It is a `<th>` in the body — see the filter's note — so it
   needs the row-label weight without inheriting the column headers' rule. */
/* [MEASURED] the comp's row labels are BIGGER AND LIGHTER than the build's, and
   the two readings agree on the direction:
     cap height — the "C" of "Core" inks 20 px against this build's 11 at 16 px,
       so 16 x 20 / 11 = 27.7. `h7` = 26 is the nearest existing step (6 % under);
       nothing is registered for a single derivation and the residual is recorded.
     ink area — "Core" carries 378 ink pixels in the comp and 377 here, at nearly
       twice the cap height. The same ink over a much larger glyph is a LIGHTER
       stroke, so ~~600~~ goes back to the body default. */
/* [MEASURED] all four of the comp's observable row pitches are 104 — 6559, 6663,
   6767, 6871, 6975 — so the rows are uniform, not content-sized. The build's
   fifth row measured 80.5 against the others' 104 because its verdict is one
   line where theirs are two; the comp draws no rules, so its own fifth row's
   height is unobservable and uniformity is the reading the four visible pitches
   support. On a table row `block-size` is a minimum, so a longer verdict still
   grows its row. */
.chumuk-compare__table tbody tr {
	block-size: var( --chumuk-compare-row-h );
}

.chumuk-compare__table tbody th {
	font-family: var( --wp--custom--font-body );
	font-weight: 400;
	font-size: var( --wp--preset--font-size--h-7 );
}

/* ⚠️ ~~`.chumuk-compare__table tbody tr:last-child :where( th, td ) {
   border-block-end: 0 }`~~ — STRUCK [§10.146]. It existed to suppress the last
   row's rule when every row had one. No row has one now, so it has nothing to
   suppress and is removed rather than left as a rule that cannot fire. */

/* --------------------------------------------------------------------------
   THE VERDICT ICONS — colour is the LAST of three signals, never the only one.
   The filter emits the SVG plus a visually-hidden "Yes"/"No", so the meaning
   survives with CSS off, with colour vision differences, and in a screen
   reader. These rules only tint a glyph whose meaning is already carried.
   The SVG uses `currentColor`, so the two presets below are the single source
   and NO hex literal reaches the pattern, the filter or this rule.
   -------------------------------------------------------------------------- */
/* [MEASURED] the comp's verdict digits ink 20 px against this build's 14 at the
   inherited 18, so 18 x 20 / 14 = 25.7 — `h7` = 26, inside 2 %, and the same step
   the row labels take, which is what the comp draws (label and verdict read at
   one size there). At 26 the first verdict wraps to two lines, as the comp's does. */
.chumuk-compare__verdict {
	font-size: var( --wp--preset--font-size--h-7 );
	/* [MEASURED] the comp sets this verdict over two lines at a 33 px baseline
	   pitch (ink tops 6559 and 6592); the inherited 1.56 gave 41 and pushed every
	   row past the comp's 104. */
	line-height: calc( 33 / 26 );
	white-space: normal;
}

/* 🔴 BOTH VERDICTS ARE BADGES [§10.146] — AND THE BADGE FORM DOES *NOT* FIX
   F19's RATIO, WHICH IS THE OPPOSITE OF WHAT WAS EXPECTED.

   THE SHAPE. MEASURED in the comp: both verdicts are a filled **25 × 25**
   rounded square with a WHITE glyph knocked out of it — `rgb(0,191,89)` for yes
   at band-relative x 638–663 / y 466–491, `rgb(255,0,7)` for no at x 1033–1058.
   Those two are the `green` and `red` presets EXACTLY, to the level. The build
   drew a bare 16 × 16 stroked glyph on the card. **The shape is now the comp's.**

   🔴 THE COLOUR IS NOT, AND THAT IS DELIBERATE. F19 was raised as an
   ICON-COLOUR problem — a green tick at 2.43 : 1 — and this pass was briefed on
   the premise that it is really a SHAPE problem. Measured, that premise does not
   survive: **a WHITE glyph on the comp's `green` is 2.44 : 1**, which is F19's
   own number to two decimals. The badge changes the form and leaves the ratio
   exactly where F19 found it.

     white on `green`     **2.44 : 1**   (the comp's fill)
     white on `mint-ink`  **5.55 : 1**   (what ships)
     white on `red`       **4.00 : 1**   (the comp's fill, and what ships)

   So the fill stays `--chumuk-verdict-yes` = `mint-ink`. That token was chosen on
   measurement for exactly this reason (see its own block at the top of this
   file), this pass was not asked to revert it, and reverting an AA-motivated
   decision as a side effect of a shape change is precisely the accident a
   design-first pass has to avoid. **The residual delta — the comp's badge is
   `green`, ours is `mint-ink` — is REPORTED for the owner, not taken.**

   ⚠️ **F19 IS DISPOSED OF AS SUPERSEDED IN FORM, NOT CLOSED.** Its premise
   (colour alone) and its proposed fix (darken the glyph) are both overtaken; its
   underlying reading is reproduced, not refuted. ➕ And neither ratio is the
   accessible signal in any case: the filter emits a visually-hidden "Yes"/"No"
   beside every icon, so the meaning survives with CSS off, without colour vision
   and in a screen reader.

   The SVG keeps `stroke: currentColor`, so setting `color` to white is the whole
   glyph change and NO hex literal reaches the filter, the pattern or this rule.
   -------------------------------------------------------------------------- */
.chumuk-compare__icon {
	vertical-align: -6px;
	margin-inline-end: var( --wp--preset--spacing--20 );
	flex: none;
	/* MEASURED 25 × 25 in the comp, against the filter's 16 × 16 viewBox — the
	   box grows and the glyph is padded inside it. */
	inline-size: 25px;
	block-size: 25px;
	padding: 4px;
	border-radius: var( --wp--preset--spacing--20 );
	color: var( --wp--preset--color--white );
}

.chumuk-compare__icon--yes {
	background-color: var( --chumuk-verdict-yes );
}

.chumuk-compare__icon--no {
	background-color: var( --chumuk-verdict-no );
}

/* --------------------------------------------------------------------------
   C11 — THE FOUR COUNTER CARDS

   Geometry is [MEASURED]: 398 × 320 cards with a 16 px gap (the `40` token),
   four across the 1640 px content box — 4 × 398 + 3 × 16 = 1640 EXACTLY, which
   is why `contentSize` and this row agree without a fudge factor
   (design-tokens.md §2.4).
   -------------------------------------------------------------------------- */
.chumuk-counters {
	/* 🔴 THE `70` TOKEN, NOT `90`, AND THE BAND CHECK IS WHY — the same finding
	   `.chumuk-stats` records one section up. `90` (80 px a side) measured
	   **700 px** against design-tokens.md §2.5's **650 px** band at 1920, a
	   50 px overrun, which is precisely what 00-conventions.md §4.2 exists to
	   catch. `70` is 48 px, giving 320 + 96 + the head. Vertical padding costs
	   no column width, so there is nothing for a clamp to protect.
	   ⚠️ ~~`70` is 48~~ at the TOP: [MEASURED] the comp's h2 caps ink at y 7242 in
	   a band starting at 7170, and the build's at 7235 — 7 short, so the top is 55.
	   The bottom keeps `70`. */
	padding-block: var( --chumuk-counters-pad-top ) var( --wp--preset--spacing--70 );
}

/* [MEASURED] the comp's intro inks from x 969 here, the same as C05, C06 and
   C07 — so the columns are equal (812 each) with the same 16 px gap, not the
   48 % / 52 % at 48 px the build carried. The explicit widths are removed in the
   markup; only the gap is here.
   🔴 ~~align-items: flex-end~~ WAS DOING NOTHING AND HAD TO BE READ, NOT TRUSTED.
   Computed live it is `normal` — core's columns stylesheet wins — which is why
   the intro sat at the head's TOP, 73 px above the comp's. The other three heads
   are bottom-aligned by the BLOCK attribute (`is-vertically-aligned-bottom`),
   not by this declaration, and this head now carries it too. */
.chumuk-counters__head {
	margin-block-end: var( --wp--preset--spacing--75 );
	column-gap: var( --wp--preset--spacing--40 );
}

/* 🔴 GRID, NOT core/columns' FLEX — and that is how the responsive steps avoid
   `!important`. core/columns sizes its children with `flex-basis` from its own
   stylesheet at equal specificity, so re-basing them for a 2-up row means either
   out-specifying core or overriding it, and both are the kind of fight
   00-conventions.md tells us not to pick. Switching the CONTAINER to grid makes
   `flex-basis` inert without contesting it: the track count is stated once per
   breakpoint and the columns simply fill the tracks.
   4 × 398 + 3 × 16 = 1640 = `contentSize`, so the measured card width falls out
   of `1fr` rather than being asserted anywhere. */
.chumuk-counters__grid {
	display: grid;
	/* 🔴 `minmax( 0, 1fr )`, NOT `1fr`, AND A MEASURED CLS REGRESSION IS WHY
	   [§10.147]. `1fr` is `minmax( auto, 1fr )`, so each track is floored at its
	   content's min-content width — and the counter's numeral changes width on
	   every frame of the count-up. With the card's padding at the comp's 56 the
	   content box is 208 px at 1440, which is EXACTLY "79%"'s width, so every
	   wider intermediate value grew the track, the card, the band and every band
	   below it. MEASURED: the band jittered 636.8 → 657.6 → 636.8 during the
	   animation and page CLS went 0.024 → 0.375, past the 0.1 threshold.

	   ⚠️ AND `font-variant-numeric: tabular-nums` DOES NOT SAVE IT, THOUGH IT IS
	   ASKED FOR ON `.chumuk-counter__value`. Tested on the rendered page:
	   Playfair Display does not honour `tnum`, and the value's width runs
	   170.48 ("11%") to 229.03 ("00%") — a 58.6 px spread across the values the
	   count-up passes through. The declaration is INERT on this face and the
	   layout cannot rely on it (**F85**). `minmax( 0, … )` fixes the track
	   instead, so the widest transient value overflows the 208 px content box by
	   ~10 px a side INTO the card's own 56 px padding, and nothing moves. */
	grid-template-columns: repeat( 4, minmax( 0, 1fr ) );
	gap: var( --wp--preset--spacing--40 );
}

.chumuk-counter {
	/* ⚠️ DECLARED DEVIATION [§10.192] — the ONE `border-box` this band keeps.
	   `block-size: 100%` + `--chumuk-counter-height` is a FILL measurement (the
	   comp's card runs y 7411-7730 = 320 INCLUDING its padding), exactly the case
	   this file states explicitly for the hero CTA and the bento cards. Without it
	   the 88px of block padding is added and the card measures 408 against the
	   comp's 320. Everything else in the band stays content-box, as live computes
	   it — this is not a step towards a global reset. */
	box-sizing: border-box;
	block-size: 100%;
	min-block-size: var( --chumuk-counter-height );
	/* ⬅ `50` (24 px) until §10.147. MEASURED off the comp: card 1's caption block
	   spans x 196–482 inside a card running 140–538, so the padding is **56 both
	   sides** and the content box is 286 — not the 350 a 24 px padding leaves.
	   `75` is 56 px exactly, so the comp's figure is already on the scale and no
	   new token is needed.
	   ⚠️ THE CAPTION'S LINE COUNT FOLLOWS FROM THIS AND IS NOT SET SEPARATELY:
	   the comp sets card 1's caption on FOUR lines (glyph bands at y 440–455,
	   461–476, 482–497, 503–515, a 21 px pitch) where the build set THREE at 350
	   px wide. Narrowing the box to the comp's 286 is the whole change. */
	/* ⚠️ THE 56 IS THE HORIZONTAL FIGURE AND THE SHORTHAND APPLIED IT TO ALL FOUR
	   SIDES. [MEASURED] vertically the comp is asymmetric: card 1 runs y 7411-7730
	   around a numeral whose line box starts at 7458 and a caption box ending at
	   7690, i.e. 47 above and 40 below, with 20 between them. 56/12/56 measured
	   336 against the comp's 320. */
	padding: var( --chumuk-counter-pad-top ) var( --wp--preset--spacing--75 ) var( --chumuk-counter-pad-bottom );
	border-radius: var( --chumuk-card-radius );
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	row-gap: var( --chumuk-counter-gap );
	text-align: center;
}

.chumuk-counters {
	/* 320 px is [MEASURED] — the comp's card height. Declared on the section so
	   the responsive rules below can restate it in one place. */
	--chumuk-counter-height: 320px;
	--chumuk-counter-pad-top: 48px;
	--chumuk-counter-pad-bottom: 40px;
	--chumuk-counter-gap: 20px;
	--chumuk-counters-pad-top: 55px;
}

/* 🔴 THE NUMERAL IS `ink`, NOT WHITE, AND THE SIZE DOES NOT EXEMPT IT
   [checklist §10.30]. White on `cyan` is 2.23:1 — it fails even the 3:1
   large-text floor, so the large-text exemption never applied. The colour is
   set on the block (`textColor: ink`) so the editor shows the truth; this rule
   only handles the metrics.
   `tabular-nums` so the count-up does not reflow the card while it runs: with
   proportional digits, `7` and `9` differ in width and the numeral jitters
   horizontally through the whole animation.

   ✅ F37 CLOSED 2026-08-23 [§10.116], authorised by the project owner. The
   numerals rendered the **body face** because this element is a `core/paragraph` and
   `styles.elements.heading` never reaches it — §10.95 r3's trap, of which this
   was the second instance. The comp draws them serif, and §10.113 fixed the
   typeface decision at **Playfair Display**, so the target is the
   specification, not the comp's ink (which that same ruling found unreliable).

   🔴 `lining-nums` IS LOAD-BEARING AND IS SET WITH THE FAMILY, NOT AFTER IT.
   §10.95 r6 measured the same numeral at **223 × 113 with lining figures and
   208 × 125 without** — Playfair defaults to OLDSTYLE figures, which sit at
   x-height with descenders. Setting the family alone would render oldstyle
   digits and silently invalidate `display-3`'s 128 px, which was derived WITH
   lining figures. The two values combine because they are different
   sub-properties: `lining-nums` is a figure style, `tabular-nums` a spacing
   one, so the anti-jitter guarantee above is preserved exactly.

   ⚠️ The family now comes from `--wp--custom--font-heading`, the role token
   registered by §10.123, which resolves to
   `--wp--preset--font-family--playfair-display`. The slug `instrument-serif`
   that `design-tokens.md` §2.2 once named resolves EMPTY (F57) — building this
   `calc`-free declaration on it would have been dropped silently at
   computed-value time, which is §4.8's trap. Both the role token and the preset
   it points at were verified non-empty before this was written. */
.chumuk-counter__value {
	margin: 0;
	/* 🔴 OVERFLOW BEHAVIOUR, NOT SIZING [§10.192]. Below 1440 the numeral box is
	   207.95 in a 200px content box — on both sides, and correct. Standard block
	   overflow left-pins it at the padding edge; a centred flex item splits the
	   overflow evenly and reads as a 3.97px shift at 1440 (cards 2-4 measured
	   7.89 / 9.06 / 7.67). `safe center` centres while the item fits and falls
	   back to start alignment when it does not, which is the live behaviour. */
	align-self: safe center;
	line-height: 1;
	font-family: var( --wp--custom--font-heading );
	font-variant-numeric: lining-nums tabular-nums;
}

.chumuk-counter__caption {
	margin: 0;
	text-wrap: pretty;
	/* ~~body-sm (13)~~ — the size is a block attribute; only the pitch is here.
	   [MEASURED] two ways on card 1: the "T" of "Trust" caps 12 px against this
	   build's 9 at 13 (-> 17.3), and the comp fits 33 characters on its first
	   line where the build fits 43 in the same 252-260 px of ink (-> 16.5).
	   `label-sm` = 17 sits inside 1 % of the mean. The comp's baseline pitch is
	   21 at that size, not the inherited 1.56's 26.5 — which is why it sets the
	   caption over FOUR lines in a 320 px card and still fits. */
	line-height: calc( 21 / 17 );
}

/* The citation, and the placeholder that says it is incomplete. */
.chumuk-counters__citation {
	margin-block-start: var( --wp--preset--spacing--50 );
	margin-block-end: 0;
	opacity: 0.75;
}

/* 🔴 A LAUNCH-GATE MARKER, NOT A DESIGN ELEMENT [gap G2, content-inventory K2].
   It is deliberately loud. c11-counters.md acceptance 7 requires the incomplete
   citation not be "quietly published as-is", and a marker only the repository
   can see would be exactly that. It is removed by deleting the block once the
   client supplies N and a date — not by restyling this rule. */
.chumuk-placeholder {
	margin-block-start: var( --wp--preset--spacing--20 );
	padding: var( --wp--preset--spacing--30 );
	border: 2px dashed var( --wp--preset--color--red );
	border-radius: var( --chumuk-bento-panel-radius );
	color: var( --wp--preset--color--ink );
	font-family: var( --wp--custom--font-body );
}

/* --------------------------------------------------------------------------
   Responsive — c11-counters.md: 4-up → 2-up → 1-up. core/columns stacks to
   1-up on its own below 782 px, so only the 2-up step needs declaring.
   -------------------------------------------------------------------------- */
/* ⬅ `1199px` until §10.147, and the comp's own padding is what moved it.
   MEASURED: with the card's padding at the comp's 56 (was 24), a 4-up track
   cannot hold the 128 px numeral plus 112 px of padding below **1440** — the
   document overflowed by 117 px at 1200, 153 at 1280 and 189 at 1360, and was
   clean from 1440 up. Swept at 8 px steps: 27 widths overflowed, ALL of them in
   1200–1439 and none outside it.
   ⚠️ THIS IS THE HONEST COST OF THE PADDING, NOT A SEPARATE DECISION. Four
   398 px cards need 1640 of content and that only exists at ≥ 1840; between
   1440 and 1839 they ride down to 320–384 without overflowing, and below 1440
   they cannot. So 4-up starts where it fits and 2-up takes the range it used to
   share. */
@media ( max-width: 1439px ) {
	.chumuk-counters__grid {
		grid-template-columns: repeat( 2, minmax( 0, 1fr ) );
	}
}

@media ( max-width: 781px ) {
	.chumuk-counters__grid {
		grid-template-columns: minmax( 0, 1fr );
	}

	.chumuk-counters {
		--chumuk-counter-height: 260px;
	}

	.chumuk-compare {
		padding: var( --wp--preset--spacing--50 );
	}
}

/* ==========================================================================
   COMPONENT LAYER — build step 8 (sections 10–11)

   c13-testimonials.md · c35-experts.md
   ========================================================================== */

/* --------------------------------------------------------------------------
   C13 — THE TESTIMONIAL CARDS

   Geometry [MEASURED] off the comp at native 1920, band y 7820–8520:
   card **550 × 400**, of which the photograph is **275 × 400** and the text
   panel the other 275. Card pitch 560, so the gutter is 10. The chip measures
   **160 × 30**.

   🔴 THE CARDS BLEED PAST THE CONTENT BOX ON BOTH EDGES, and the comp's first
   card starts at **x 20** — not at the 140 px content edge c13-testimonials.md
   asserts. Measured: the ice gutters between cards fall at x 570–574,
   1130–1137 and 1690–1699, and the run before the first card is x 0–19. The
   heading above it starts at x ~140, so the track genuinely overhangs its own
   section's text column on the left. See the step-08 report, finding F20.
   -------------------------------------------------------------------------- */
/* 🔴 THE BAND'S GROUND IS NOT WHITE. [MEASURED] flat across the comp's band,
   above the cards and below them, it is rgb(233 251 255) — the same near-ice
   tone C06's description panels carry, and `ice` (rgb(229 251 251)) is within
   1.6 % on every channel. The build left it transparent, so the white cards had
   no card edge at all against the body's white.
   [MEASURED] the band is y 7820-8519 (700) around cards at 8061-8460, i.e. 241
   above and 59 below; `70` (48) gave 228 and 47.7. */
.chumuk-testimonials {
	background-color: var( --wp--preset--color--ice );
	padding-block: var( --chumuk-testimonials-pad-top ) var( --chumuk-testimonials-pad-bottom );
	/* [MEASURED] — the comp's own card box and its 10 px gutter. */
	--chumuk-testimonial-card: 550px;
	--chumuk-testimonial-media: 275px;
	--chumuk-testimonial-height: 400px;
	/* 20 px at the comp's 1920. Below that the bleed would push the first card
	   off-screen before the track has anywhere to scroll, so it collapses to
	   the section's own gutter. [MEASURED at 1920, DERIVED below it] */
	--chumuk-testimonial-bleed: clamp( 16px, 1.04vw, 20px );
	--chumuk-testimonials-pad-top: 59px;
	--chumuk-testimonials-pad-bottom: 59px;
	--chumuk-testimonial-body-pad-bottom: 30px;
	--chumuk-testimonial-body-pad-top: 6px;
	--chumuk-testimonial-body-pad-inline: 27px;
}

/* The same two corrections C11's head needed, and for the same two reasons: the
   comp's intro inks from x 969 (equal 812 px columns at a 16 px gap, not 48 % /
   52 % at 48), and `align-items: flex-end` computes `normal` here as well — core's
   columns stylesheet wins — so the bottom alignment is the BLOCK attribute. */
.chumuk-testimonials__head {
	margin-block-end: var( --wp--preset--spacing--75 );
	column-gap: var( --wp--preset--spacing--40 );
}

/* 🔴 THE TRACK IS `align:full`, NOT A NEGATIVE MARGIN. It first shipped as
   `margin-inline: calc(50% - 50vw)` and MEASURED at x 160 instead of the
   comp's 20: the section is a `constrained` layout, and core's own
   `.is-layout-constrained > *` rule carries more specificity than a single
   class, so the pull-out never applied. `align:full` is core's supported way
   to say this and needs no override at all — the same lesson as step 7's
   `display: grid` losing to `core/columns`' flex: when core already models
   the thing you want, ask core for it instead of out-specifying it.
   The bleed then comes from the track's own padding, below. */

/* 🔴 THE BLEED COMES FROM THE SECTION BEING `align:full`, AND TWO EARLIER
   ATTEMPTS FAILED SILENTLY — BOTH WORTH RECORDING.
   (1) `margin-inline: calc(50% - 50vw)` lost to core's
       `.is-layout-constrained > *`, which carries more specificity than one
       class. MEASURED x 160 against the comp's 20.
   (2) `margin-inline: calc(-1 * var(--wp--style--root-padding-left))` was
       WORSE, because it did not fail visibly at all: that property is EMPTY on
       this site (`useRootPaddingAwareAlignments` is not in play — the section's
       own `padding-left` computes 0), so the `calc()` was invalid at
       computed-value time and the whole declaration was DROPPED. Still x 160,
       with nothing in the cascade to show why. Third instance of that trap in
       this project after §10.98 r6 and §10.100 r3.
   The actual cause was neither: the SECTION was 1640 px wide, so nothing
   inside it could reach the viewport. `align:full` on the section — the same
   thing C10's band and C35 already do — is the whole fix, and the track's own
   padding then places the first card. */

.chumuk-testimonials__carousel .chumuk-carousel__track {
	scroll-padding-inline-start: var( --chumuk-testimonial-bleed );
	padding-inline: var( --chumuk-testimonial-bleed );
	column-gap: 10px;
	/* 🔴 C06's STAGGER IS NOT C13's — AND UNTIL §10.104 THIS ONLY *SAID* SO.
	   ~~`.chumuk-carousel__track` ships `padding-block-end: 92px` to make room
	   for C06's transformed even cards, which contribute no layout height.
	   C13's cards are not staggered, so that 92 px was pure dead space inside a
	   700 px band — it is the shared mechanism's cost, and paying it here
	   rather than forking the track rule is the right trade: one carousel
	   implementation, one local opt-out.~~ — struck: the premise was FALSE and
	   never tested. C13 never opted out of
	   `.chumuk-carousel__card:nth-child(even){transform:translateY(…)}`, so its
	   even cards WERE offset 92 px [MEASURED: card tops 0 / 92 / 0 / 92 / 0],
	   and removing the padding that made room for them clipped their last
	   92 px — cards 2 and 4 lost the role line under the name outright (F32).
	   The comp settles it: its C13 card row measures y 8061–8460, i.e. 400 tall
	   and FLAT, where a staggered row would be 492.
	   The opt-out is now real, and it is made by handing the shared mechanism a
	   value rather than out-specifying its `transform` — the same lever the
	   ≤782 px block already pulls. `padding-block-end: 0` is then correct
	   BECAUSE there is nothing left to make room for. */
	--chumuk-carousel-stagger: 0px;
	padding-block-end: 0;
}

.chumuk-testimonial {
	inline-size: var( --chumuk-testimonial-card );
	max-inline-size: calc( 100vw - 2 * var( --chumuk-testimonial-bleed ) );
	/* 🔴 `flex: none`, or the cards SHRINK instead of the track SCROLLING.
	   The track is a core flex layout and flex items default to
	   `flex-shrink: 1`, so four 550 px cards compressed themselves to 320 to
	   fit 1920 — MEASURED — which silently turned a carousel into a squeezed
	   row and left both arrows `aria-disabled` because nothing overflowed. */
	flex: none;
	min-block-size: var( --chumuk-testimonial-height );
	display: grid;
	/* 🔴 A PROPORTION, NOT A FIXED TRACK. This was
	   `var( --chumuk-testimonial-media ) 1fr` — 275 px fixed — which is exactly
	   right at the comp's 550 px card and starves the text everywhere else:
	   MEASURED at a 375 px viewport the card is 343 and the body column got
	   **68 px**, wrapping the Bengali quote to roughly one glyph per line and
	   standing it 250 px tall. The comp's media is 275 of 550, i.e. EXACTLY
	   half, so expressing it as a proportion reproduces the comp at the comp's
	   width and degrades sanely below it. `minmax(0, …)` because a grid track
	   floors at `auto` — its content's min-content width — and the portrait
	   would otherwise refuse to go below its own intrinsic size. */
	grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
	background-color: var( --wp--preset--color--white );
	border-radius: var( --chumuk-card-radius );
	overflow: hidden;
}

/* 🔴 THE PORTRAIT BOX'S RATIO IS THE COMP'S — 275 / 400 — AND IT PREDATES THE
   PHOTOGRAPHY BY DESIGN. ~~The photography is MISSING (gap G15: the client
   document gives a Drive link per testimonial and none of those files is in the
   archive), so this ships as the standing missing-photography treatment.~~
   ✅ G15 CLOSED §10.104: the client supplied five portraits and attachments
   117–121 now fill these boxes. The claim the struck text encoded — that
   declaring the ratio here makes the real portraits a zero-CLS MEDIA swap —
   was TESTED at the swap, not assumed: the band's height is unchanged to the
   pixel (§10.104). 00-conventions.md §1.1 rule 1 required the ratio be settled
   per slot at BUILD time against the comp; it was, and that is what paid. */
.chumuk-testimonial__portrait {
	aspect-ratio: var( --chumuk-testimonial-media ) / var( --chumuk-testimonial-height );
	block-size: 100%;
	min-block-size: 0;
	/* core/image ships a `figure`, which carries a bottom margin in the block
	   stylesheet; unset it here or the portrait sits short of the card edge. */
	margin: 0;
}

/* The crops are already 275 : 400 (scripts/crop-portraits.py exports 550 × 800),
   so `cover` should never actually crop — it is here because the box, not the
   file, is the contract: any future re-crop or wrong-ratio replacement fills the
   slot instead of letterboxing it or stretching a face. */
.chumuk-testimonial__portrait img {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
}

/* 🔴 ~~justify-content: center~~ — THE COMP SPREADS THIS COLUMN, IT DOES NOT
   CENTRE IT. [MEASURED] inside card 1 (y 8061-8461): the chip inks 8091-8120,
   i.e. its box sits on the body's own top edge at 8085; the star row inks
   8422-8430, 30 px clear of the card's bottom; and the quote sits between them.
   Centred, the build packed all four blocks into the middle — chip 74 px low,
   name 73 px high, stars 48 px high. `space-between` with an asymmetric pad puts
   each of them where the comp draws it. */
.chumuk-testimonial__body {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	row-gap: var( --wp--preset--spacing--40 );
	/* [MEASURED] the comp's chip fill tops at y 8091 in a card starting at 8061 —
	   30 — and the card's own padding already spends 24 of it. */
	/* [MEASURED] the inline padding is 30, not 24, and the quote's LINE COUNT is
	   what shows it: the comp breaks card 1 after "চুমুকই" where a 227 px measure
	   fits "যথেষ্ট" as well. Its widest line inks 212 and the line the build fits
	   inks 222, so the measure is between the two.
	   ⚠️ THE WINDOW IS ONLY 2 px WIDE AND THAT IS THE FACE, NOT THE DESIGN. Hind
	   Siliguri sets the comp's three words at 220 where the comp's substituted
	   Bengali sets them at 212, so the measure has to clear 220 and stop short of
	   the 222 the next word would need: 275 - 2 x 27 = 221. Recorded as knife-edge
	   rather than presented as a clean measurement. */
	padding: var( --chumuk-testimonial-body-pad-top ) var( --chumuk-testimonial-body-pad-inline ) var( --chumuk-testimonial-body-pad-bottom );
	text-align: center;
}

/* The card is a grid item inside a flex track; without this the portrait's
   aspect-ratio and the body's content fight over the 400 px row. */
.chumuk-testimonial__body {
	min-inline-size: 0;
}

/* 🔴 CHIP TEXT IS `ink`, NOT WHITE [checklist §10.30]. White on `cyan` is
   2.23:1, and at `label-xs` (14 px) the large-text exemption is not even
   arguable. The colour is set on the block so the editor shows the truth; this
   rule carries the pill geometry only — [MEASURED] 160 × 30 in the comp. */
.chumuk-chip {
	margin: 0;
	padding-block: var( --wp--preset--spacing--20 );
	padding-inline: var( --wp--preset--spacing--30 );
	border-radius: var( --wp--custom--pill-radius );
	text-transform: uppercase;
	letter-spacing: 0.06em;
	/* [MEASURED] the comp's pill is 30 px tall — that value is unchanged and
	   still the target. ~~`block-size` and not `min-block-size`: with vertical
	   padding on top of the line box it measured 55.~~ — struck 2026-08-23
	   [F34, §10.107, authorised by the project owner (Ashiq)]. The struck
	   reasoning solved the right problem with a tool that could not fail
	   safely: `padding-block: 0` two lines below is what actually removes the
	   55 px, and the fixed `block-size` was belt AND braces. It only ever
	   mattered when the label WRAPPED, and then it was wrong — `FOR
	   REFRESHMENT` needs 37.59 px at ≤414 px viewports, so with `overflow`
	   visible the text escaped the pill by 4.59 px above and 3.00 px below and
	   rendered on the white card instead of the cyan.
	   `min-block-size` holds the measured 30 px exactly wherever the label fits
	   on one line — verified unchanged to the decimal at every width — and lets
	   the two-line case grow instead of spilling. The flex centring is what
	   keeps the label optically centred either way. */
	min-block-size: 30px;
	padding-block: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
}

/* ~~Bengali sets taller than Latin at the same size, so the Latin line-height
   clips its ascenders and descenders. c13-testimonials.md calls this out
   explicitly; 1.6 is the value that clears both without changing the token.~~
   — superseded 2026-08-24 [§10.118]. The reasoning still holds and is why a
   Bengali-specific line-height exists at all; only the value changed, and it
   changed because it was SPECIFIED rather than because 1.6 was measured wrong.

   🔴 `[SPEC-GIVEN]` — NOT `[MEASURED]`, NOT `[DERIVED]`. The project owner
   supplied Hind Siliguri 600 / 19 px / 1.55 for these quotes. **No derivation
   was performed and none is owed**: the three-part registration test does not
   apply to a value the owner specified, and Latin cap-height and glyph-ratio
   methods still do not transfer to Bengali script — which is why this quote was
   twice reported NOT VERIFIED (§10.112, §10.114). Those findings were CORRECT
   and are superseded by specification, not overturned by measurement. **A later
   pass must not try to verify these four values against comp ink; there is no
   valid method, and looking for one is what cost two passes already.**

   The family is applied here rather than on the block because `fontFamily` on a
   `core/paragraph` would emit a `has-…-font-family` class that also reaches the
   name and chip; the size DOES come from the block, as `h8`. */
.chumuk-testimonial__quote,
.chumuk-testimonial__quote p {
	margin: 0;
	border: 0;
	padding: 0;
	/* ~~1.55~~ at h8. [MEASURED] the comp sets card 1's quote over three lines
	   spanning 76 px of ink (8202-8277), which is 2L + one line's 17 px of ink,
	   so L = 29.5 — the same leading the build already had, but now at h7 (26)
	   instead of h8 (19), which makes it 1.135. The SIZE is measured from word
	   widths on the shared first line: the comp's "প্রশান্ত" and "করতে" ink 58 and
	   61 against this build's 42 and 45, i.e. 1.38 and 1.36, and 19 x 1.37 = 26.0
	   — `h7`, inside 0.2 %. Bengali ink HEIGHT is not usable here (it spans matra
	   to descender and read 1.06), which is why word width is what decided it. */
	line-height: calc( 29.5 / 26 );
}

.chumuk-testimonial__quote p {
	font-family: var( --wp--custom--font-bengali );
	font-weight: 600;
}

/* See the note on .chumuk-testimonial__body — this auto margin is what spreads
   the card, and it survives a card whose quote runs to two lines. */
.chumuk-testimonial__quote {
	margin-block: auto;
}

/* 🔴 THE COMP SETS THE QUOTE IN QUOTATION MARKS AND THE SOURCE STRING HAS NONE.
   content-source.md's row 1 is SOURCED as `আমাকে প্রশান্ত করতে এক গ্লাস চুমুকই যথেষ্ট`
   without them, so they are PRESENTATION and are added here rather than to the
   copy — the same division `.chumuk-bento__title`'s `text-transform` uses, and
   the DOM string stays byte-identical to the source.
   ⚠️ THEY ALSO EXPLAIN A LINE COUNT. The comp sets card 1's quote over THREE
   lines and the build set two: the body's measure is 227 px, the build's first
   line inks 218, and the marks add ~14 — which is what pushes "এক গ্লাস" onto
   the next line. The line count was a consequence of the marks, not of the size. */
.chumuk-testimonial__quote p::before {
	/* STRAIGHT, not curly — the comp draws a plain double quote, and the curly
	   pair also inks 7 px wider, which was enough to break card 1 a word early. */
	content: "\0022";
}

.chumuk-testimonial__quote p::after {
	content: "\0022";
}

.chumuk-testimonial__name {
	margin: 0;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	line-height: 1.7;
}

/* C13's five-star rating — RESTORED 2026-08-24 by owner ruling 1 [checklist §10.125].
   ~~"The five-star ratings stay dropped" [§10.105 / G28]~~ — struck, not deleted: G28
   approved the CHIP vocabulary and explicitly did NOT approve the ratings, and that
   reading was correct at the time. Ruling 1 overrides it — the design draws them.

   🔴 EVERY VALUE HERE IS MEASURED OFF `pink-new-3.png`, NOT CHOSEN:
     glyph   9 x 9 px ink, five of them
     pitch   16 px, i.e. a 7 px gap
     run     73 px total (x 397-469), CENTRED in a 275 px card (centre 432 vs 433)
     colour  rgb(255,179,0) sampled at the glyph core — which is `gold` #FFB300
             EXACTLY, already in the palette. No colour was coined.
     y       ink 8422-8430, 25 px below the name ink and 29 px above the card's
             own bottom edge (card y 8061-8460, height 400 — the build's fixed
             400 is the comp's own number).

   ⚠️ The rating ASSERTS A REVIEW SYSTEM this project does not have. Registered `[L]`
   in placeholders.md alongside the marquee claims. `role="img"` with an explicit label
   rather than `aria-hidden`, because the visual makes the assertion either way and
   hiding it from assistive tech would state it to some users and not others. */
.chumuk-testimonial__stars {
	display: flex;
	justify-content: center;
	align-items: center;
	gap: 7px;
	color: var( --wp--preset--color--gold );
	line-height: 1;
}

/* --------------------------------------------------------------------------
   C35 — EXPERT GUIDANCE
   -------------------------------------------------------------------------- */
.chumuk-experts {
	--chumuk-experts-pad-top: 101px;
	--chumuk-experts-pad-bottom: 116px;
	--chumuk-expert-disc: 100px;
	--chumuk-expert-card-gap: 32px;
	--chumuk-expert-card-pad-block: 27px;
	--chumuk-trustbar-height: 98px;
	--chumuk-trustbar-icon: 42px;
	--chumuk-trustbar-icon-gap: 18px;
	--chumuk-expert-card-pad-inline: 49px;
	--chumuk-experts-button-gap: 57px;
	--chumuk-experts-col-offset: 10px;
	/* `70`, not `90`, and the band check is why — the third time this file has
	   made that correction (see `.chumuk-stats` and `.chumuk-counters`). At
	   `90` the section MEASURED 960 px against design-tokens.md §2.5's 900 px
	   band, a 60 px overrun. Vertical padding costs no column width.
	   ⚠️ ~~`70`~~ (48) WAS COMPENSATING FOR UNDERSIZED CONTENT, and once the cards
	   and type take the comp's measurements it is 53 px short at the top and 67
	   at the bottom. [MEASURED] the comp's first card tops at y 8621 in a band
	   starting at 8520, and its trust bar ends at 9303 in a band ending at 9419. */
	padding-block: var( --chumuk-experts-pad-top ) var( --chumuk-experts-pad-bottom );
}

/* ⬅ `90` (80 px) until §10.148. MEASURED off the comp: the left column's widest
   paragraph line runs x 141–660 and the cards run x 969–1779, inside a content
   box of 140–1780. That gives left 528 · gap 301 · cards 811 = 1640, which
   closes exactly. As proportions of the container: 32.2 % · 18.35 % · 49.45 %,
   and a PERCENTAGE gap is what lets all three ride down together instead of an
   80 px gap eating the columns at narrow widths. */
.chumuk-experts__grid {
	column-gap: 18.35%;
	align-items: flex-start;
}

/* ⚠️ TOMBSTONE — `.chumuk-experts__media` NO LONGER EXISTS [§10.130].
   The rule below is kept struck rather than deleted for two reasons: its
   `min-block-size: 0` finding is still LIVE — `.chumuk-footer__card-media`
   cites this block BY NAME for it, and `.chumuk-testimonial__portrait` carries
   the same declaration — and its own justifying comment had already gone false,
   which is worth showing. ⚠️ CHECKED, not assumed: `min-block-size: 0` appears
   twice elsewhere in this file (the portrait and the footer card), and only the
   footer's comment names this rule.

   WHY THE ELEMENT WENT. The box reserved a `[DERIVED]` 4 / 3 cover that
   MEASURED 655.2 × 491.4 at 1920 for a product photograph the design does not
   contain. Verified against `design/pink-new-3.png` before removal: C35's band
   runs y 8520–9420 and its entire ground is `expert-scene.png` (A33), read at
   full resolution — the left column carries heading, paragraph and the MEET OUR
   EXPERTS pill directly over that background, with no card edge and no second
   photograph. `PLACEHOLDER-C35-PHOTO` is CLOSED as RESOLVED BY REMOVAL.

   ⚠️ AND ITS OWN COMMENT WAS ALREADY FALSE. "now that the MEET OUR EXPERTS
   button is omitted (§10.23)" — pass 38 RESTORED that button, so the premise
   under which the media block was said to close the stack had already expired
   before this pass touched it. The column is closed by the button, which is
   what the comp draws.

   ~~The left column carries the section on its own now that the "MEET OUR
   EXPERTS" button is omitted (§10.23). The media block below the paragraph is
   what closes the stack so the column does not read as ending early — that is
   c35-experts.md acceptance 1's "reads as balanced without it".
   .chumuk-experts__media {
       margin-block-start: var( --wp--preset--spacing--70 );
       [DERIVED] — no asset is named for this slot in content-inventory.md, so
       the ratio cannot be MEASURED from a file that does not exist. The box is
       reserved at the comp's own column proportion so the swap is layout-neutral
       in the vertical axis; re-measure when the asset is chosen.
       Tracked as PLACEHOLDER-C35-PHOTO.
       aspect-ratio: 4 / 3;
       🔴 `min-block-size: 0` OR core's COVER DEFAULT DRIVES THE WIDTH.
       `core/cover` ships `min-height: 430px`. Combined with an `aspect-ratio`
       and no explicit height, the 430 becomes the DRIVING dimension and the
       box solves for width — MEASURED 573 px inside a 375 px viewport, which
       put a horizontal scrollbar on the whole document at every width from
       320 to 600. The same guard is on `.chumuk-testimonial__portrait` for the
       same reason.
       min-block-size: 0;
       border-radius: var( --chumuk-card-radius );
       overflow: hidden;
   }~~ */

/* [MEASURED] the comp's MEET OUR EXPERTS pill is x 141-338 (198) and y 8998-9047
   (50) against a build pill of 172 x 45, and it sits 57 px below the body's last
   line where the build put 24. The label size is what carries most of it: 14 ->
   16 puts the pill at 196 x 48. */
/* [MEASURED] the comp's heading line box starts at y 8631 beside a first card
   whose top edge is 8621 — the same 10-11 px offset C09's text column carries
   against its photo card. */
.chumuk-experts__grid > *:first-child {
	padding-block-start: var( --chumuk-experts-col-offset );
}

.chumuk-experts__actions {
	margin-block-start: var( --chumuk-experts-button-gap );
}

.chumuk-experts__button .wp-block-button__link {
	font-size: var( --wp--preset--font-size--body );
}

.chumuk-expert-card {
	display: grid;
	grid-template-columns: auto 1fr;
	/* [MEASURED] the comp's disc ends x 1117 and its title inks from 1149 — 32. */
	column-gap: var( --chumuk-expert-card-gap );
	align-items: center;
	background-color: var( --wp--preset--color--white );
	border-radius: var( --chumuk-card-radius );
	/* [MEASURED] the comp's card is y 8621-8798 (178) with its disc at x 1018
	   inside a card starting at 969 — 49 horizontally — and the disc's centre at
	   8710 against a card centre of 8709.5, i.e. vertically CENTRED, which is why
	   `align-items` changes with the padding. 29 vertical closes the 178. */
	padding: var( --chumuk-expert-card-pad-block ) var( --chumuk-expert-card-pad-inline );
}

.chumuk-experts__cards > * + * {
	margin-block-start: var( --wp--preset--spacing--40 );
}

/* The icon disc. `mint` ground, `mint-ink` glyph via `currentColor`, so the
   pattern's SVG carries no colour of its own and no hex literal. Decorative:
   the meaning is in the title and list beside it. */
.chumuk-expert-card__disc {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* [MEASURED] the comp's mint disc is 100 x 100 — x 1018-1117, y 8660-8760 in
	   card 1 — against the 48 the build drew. The mint fill itself was already
	   right (rgb(220 255 233) sampled = the `mint` slug).
	   🔴 THIS RULE NOW SERVES ONE CARD, NOT THREE, AND THAT IS DELIBERATE. Cards 2
	   and 3 ship the supplied artwork, which carries its OWN disc baked into the
	   image — measured: all three delivered card icons have pixel-identical alpha
	   masks describing a full 94 px circle, and `icon-exp-2`/`-3` reproduce the
	   comp's card icons at a stroke IoU of 100.0 %. Painting this background
	   behind them would put a CSS disc under a drawn one. Card 1 keeps it because
	   `icon-exp-1` is clipped and was NOT installed — see §10.164 r3 and F100. */
	inline-size: var( --chumuk-expert-disc );
	block-size: var( --chumuk-expert-disc );
	border-radius: var( --wp--custom--pill-radius );
	background-color: var( --wp--preset--color--mint );
	color: var( --wp--preset--color--mint-ink );
}

.chumuk-expert-card__body > * {
	margin-block: 0;
}

.chumuk-expert-card__body > * + * {
	margin-block-start: var( --wp--preset--spacing--20 );
}

.chumuk-expert-card__list {
	padding-inline-start: var( --wp--preset--spacing--40 );
}

/* --------------------------------------------------------------------------
   THE TRUST BAR — dividers are `border-inline-start` on the items themselves,
   never separate blocks, so the mobile stack below can swap the axis without
   leaving an orphan rule (c35-experts.md acceptance 6). `:first-child` is what
   keeps the leading edge clean in BOTH orientations.
   -------------------------------------------------------------------------- */
.chumuk-trustbar {
	display: grid;
	grid-template-columns: repeat( 3, 1fr );
	background-color: var( --wp--preset--color--white );
	border-radius: var( --chumuk-card-radius );
	/* [MEASURED] the comp's trust bar is y 9206-9303 — 98 — against the 71.8 a
	   24 px block padding produced. ~~Stated as a height because its three items
	   are single-line and no whole-pixel padding lands on 98.~~
	   SUPERSEDED 2026-08-28 [§10.185]: stated as a MINIMUM — the F34 chip-release
	   shape — because "single-line" is width-conditional: item 3 takes two lines
	   at 1439 and below, the 98 px box overflows its content below ~1140 (21 px
	   at 1024, 188 px at the 782 breakpoint edge), and the ≤781 stack needs
	   ~200 px against a box pinned at 98 (items 2–3 painted outside the pill;
	   102 px spill measured at 375). `min-block-size` keeps the comp's 98 EXACT
	   wherever the content fits — measured 1140 and up — and releases the box
	   only where it does not. The no-whole-pixel-padding rationale is untouched:
	   the value stays a block-size figure, not padding. */
	box-sizing: border-box;
	min-block-size: var( --chumuk-trustbar-height );
	align-items: center;
	padding: 0;
	margin-block-start: var( --wp--preset--spacing--40 );
}

.chumuk-trustbar__item {
	margin: 0;
	padding-inline: var( --wp--preset--spacing--40 );
	border-inline-start: 1px solid var( --chumuk-border-hairline );
	text-align: center;
	/* The comp sets an icon to the left of each label, both on one centre line.
	   [MEASURED] its ink-to-ink gaps are 26 / 22 / 22 — near-constant — but the
	   three icons carry 0 / 5 / 12 px of transparent canvas on their right, so a
	   single flex gap CANNOT reproduce all three. The gap below is the value that
	   centres the residual; the per-item error is recorded rather than closed by
	   trimming a supplied asset. */
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var( --chumuk-trustbar-icon-gap );
}

/* 🔴 NO DISC HERE, AND THE ASSETS SAY SO. `icon-trust-1` is 12.2 % fully opaque
   against the card icons' 68.2 % — line art on transparency, with no filled
   ground of its own. Rendered at its native 42 x 42: the comp's three trust
   icons ink 32 x 33, 30 x 33 and 27 x 33, and the three files ink 32 x 33,
   30 x 33 and 27 x 33 — 1 : 1, which is also what established the mapping. */
.chumuk-trustbar__icon {
	flex: none;
	inline-size: var( --chumuk-trustbar-icon );
	block-size: var( --chumuk-trustbar-icon );
}

/* The supplied card artwork carries its own disc, so this box paints nothing —
   it only reserves the measured 100 x 100 so a lazily-loaded icon cannot shift
   the row. */
.chumuk-expert-card__icon {
	display: block;
	inline-size: var( --chumuk-expert-disc );
	block-size: var( --chumuk-expert-disc );
}

.chumuk-trustbar__item:first-child {
	border-inline-start: 0;
}

/* --------------------------------------------------------------------------
   Responsive — c13: the track stays a track at every width (it is a carousel,
   not a stack). c35: two columns → stacked below `md`, and the trust bar's
   dividers change axis rather than disappearing.
   -------------------------------------------------------------------------- */
@media ( max-width: 781px ) {
	.chumuk-experts__grid {
		row-gap: var( --wp--preset--spacing--70 );
	}

	.chumuk-trustbar {
		grid-template-columns: 1fr;
		/* §10.192 — the 98px min-block-size is a ONE-ROW measurement. Stacked, the
		   three items need their own height, and `auto` releases the floor rather
		   than leaving a min that only happens to be large enough today. */
		block-size: auto;
	}

	.chumuk-trustbar__item {
		border-inline-start: 0;
		border-block-start: 1px solid var( --chumuk-border-hairline );
		padding-block: var( --wp--preset--spacing--30 );
	}

	.chumuk-trustbar__item:first-child {
		border-block-start: 0;
	}
}

/* --------------------------------------------------------------------------
   🔴 C13's ARROWS SIT INSIDE THE VIEWPORT, BECAUSE ITS TRACK IS FULL-BLEED.

   The shared arrows are `position: absolute` on the carousel root, centred ON
   its edges — `translate(±50%, -50%)` — which is [MEASURED] correct for C06,
   whose root is the 1640 px content box, so half of each 38 px circle
   overhangs into the page margin.

   C13's root is the full 1920. MEASURED: the next arrow's right edge landed at
   **1939**, i.e. 19 px past `clientWidth`, and it was the ONLY unclipped
   overflow on the page — page `scrollWidth` went 1920 → 1939. A horizontal
   scrollbar on the whole document, caused by half an arrow.

   So the arrows are pulled fully inside for this consumer only. This is a
   COMPONENT-SCOPED override of a shared mechanism, not selector strengthening
   to win a specificity fight: C06 keeps its measured position untouched.
   -------------------------------------------------------------------------- */
.chumuk-testimonials__carousel .chumuk-carousel__prev {
	left: var( --chumuk-testimonial-bleed );
	transform: translateY( -50% );
}

.chumuk-testimonials__carousel .chumuk-carousel__next {
	right: var( --chumuk-testimonial-bleed );
	transform: translateY( -50% );
}

/* ==========================================================================
   COMPONENT LAYER — build step 9 (sections 12–13)

   c14-faq.md · c15-cta.md
   ========================================================================== */

/* --------------------------------------------------------------------------
   C14 — THE FAQ ACCORDION

   The cleanest component on the page: `core/details` supplies the whole
   accordion natively, so there is nothing here but presentation.
   -------------------------------------------------------------------------- */
.chumuk-faq-section {
	--chumuk-faq-measure: 760px;
	/* [MEASURED] the comp's eyebrow caps at y 9474 in a band starting at 9420 —
	   54 — and `90` (80) put it at 85. The bottom keeps `90`. */
	/* ⚠️ AND THE BOTTOM IS 54, NOT 80 — the band boundary below this one was read
	   wrong the first time. C15's photograph fades to a pale cream at its top
	   edge, which a modal-row scan reports as C14's `ice`; sampled per column the
	   ice actually stops at comp y 10374 and the CTA begins at 10375. So C14's
	   band is 955, not 997, and the comp leaves 99 px under its last question
	   (ink 10275) where `90` (80) left 125. */
	padding-block: var( --chumuk-faq-pad-top ) var( --chumuk-faq-pad-bottom );
	--chumuk-faq-pad-top: 52px;
	--chumuk-faq-item-pad: 14px;
	--chumuk-faq-pad-bottom: 54px;
}

/* 🔴 ~~text-transform: uppercase; letter-spacing: 0.08em~~ — THE COMP SETS THIS
   EYEBROW IN TITLE CASE. Enlarged, "Still Have Questions?" reads with a capital
   S, H and Q and lower-case everything else, and it inks 163 px against the
   build's 218 — which is what upper-casing a 20-character line costs. The
   `label` role's tracking goes with it: the comp shows none.
   ⚠️ `.chumuk-eyebrow` has exactly one consumer (patterns/faq.php), so this
   reaches nothing else. */
.chumuk-eyebrow {
	margin-block-end: var( --wp--preset--spacing--20 );
}

.chumuk-faq__intro {
	margin-block-end: var( --wp--preset--spacing--75 );
	margin-inline: auto;
	max-inline-size: 60ch;
}

/* Single column throughout — c14-faq.md Responsive. The measure keeps the
   answers readable at 1920 without a second breakpoint. */
.chumuk-faq {
	margin-inline: auto;
	/* [MEASURED] the comp's question ink starts at x 585 and its toggle ends at
	   1335, centred on 960 — a 760 px column, not 900. */
	max-inline-size: var( --chumuk-faq-measure );
}

.chumuk-faq .wp-block-details {
	/* 🔴 ~~border-block-end: 1px solid --chumuk-border-hairline~~ — THE COMP DRAWS
	   NO RULE BETWEEN THESE ITEMS. Sampled straight down the gap between items 2
	   and 3 (comp y 9960-9995 at x 900) every row is the flat `ice` ground; the
	   items are separated by space alone. */
	/* [MEASURED] the comp's five closed questions ink at y 9915 / 10005 / 10095 /
	   10185 / 10275 — a 90 px pitch. With a 37.8 px summary line box `40` (16)
	   gave 94. */
	padding-block: var( --chumuk-faq-item-pad );
	color: var( --wp--preset--color--blue-deep );
}

.chumuk-faq .wp-block-details:last-child {
	border-block-end: 0;
}

/* 🔴 THE ⊖/⊕ DISC IS A PSEUDO-ELEMENT [c14-faq.md acceptance 6]. That is not a
   stylistic preference: 00-conventions.md §2 forbids a class on an inner DOM
   element, and `core/details`' summary has no hook of its own. A pseudo-element
   is invisible to the block markup, so the content stays exactly what the
   editor produced and the glyph cannot be edited away by an author.

   `list-style: none` + the WebKit marker rule removes the browser's own
   triangle; without BOTH, Safari keeps drawing it beside ours. */
.chumuk-faq summary {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var( --wp--preset--spacing--40 );
	padding-inline-end: 0;
	cursor: pointer;
	list-style: none;
	font-family: var( --wp--custom--font-body );
	font-weight: 600;
}

.chumuk-faq summary::-webkit-details-marker {
	display: none;
}

/* The disc itself. `content` is empty and the glyph is drawn with two bars, so
   no character from an unknown font is relied on and the ⊖/⊕ pair cannot
   render as tofu the way a `−`/`+` glyph could. */
.chumuk-faq summary::after {
	content: "";
	flex: none;
	inline-size: var( --chumuk-faq-disc );
	block-size: var( --chumuk-faq-disc );
	border-radius: var( --wp--custom--pill-radius );
	background-color: var( --wp--preset--color--blue-deep );
	/* Two crossed bars via gradients: the vertical one disappears when open,
	   turning ⊕ into ⊖ with no second element and no glyph. */
	background-image:
		linear-gradient( var( --wp--preset--color--white ), var( --wp--preset--color--white ) ),
		linear-gradient( var( --wp--preset--color--white ), var( --wp--preset--color--white ) );
	background-repeat: no-repeat;
	background-position: center center, center center;
	background-size: var( --chumuk-faq-bar ) 2px, 2px var( --chumuk-faq-bar );
	transition: background-size var( --chumuk-dur-fast ) var( --chumuk-ease );
}

.chumuk-faq .wp-block-details[open] summary::after {
	/* ⊖ — the vertical bar collapses to nothing; the horizontal one stays. */
	background-size: var( --chumuk-faq-bar ) 2px, 2px 0;
}

.chumuk-faq {
	--chumuk-faq-disc: 32px;
	--chumuk-faq-bar: 14px;
}

.chumuk-faq .wp-block-details p {
	margin-block: var( --wp--preset--spacing--30 ) 0;
	color: var( --wp--preset--color--ink );
	max-inline-size: 70ch;
}

/* --------------------------------------------------------------------------
   C15 — THE CLOSING CTA BAND

   ✅ THE PHOTOGRAPH IS IN — `BG-1.png`, attachment 114, PLACEHOLDER-C15-BG
   closed 2026-08-22 [§10.102]. Band measured **910 px before and after**, so
   the reserved box held. ⚠️ Two findings came with it: **F27** — it is a PNG
   and the served derivative is **2.33 MB** against BG-2's 0.12 MB, with an
   alpha channel that is 99.86 % opaque and therefore carries nothing; and
   **F28** — the sub-line still crosses a dark region, below.
   ~~⚠️ SHIPS WITHOUT ITS PHOTOGRAPH… PLACEHOLDER-C15-BG.~~
   -------------------------------------------------------------------------- */
.chumuk-cta {
	/* 🔴 THE CONTENT SITS AT THE TOP OF THE BAND, NOT CENTRED — AND THAT IS A
	   LEGIBILITY FIX, NOT A STYLISTIC ONE [§10.102].

	   `core/cover` centres its inner container vertically by default. With the
	   real `BG-1.png` in place that put the heading and sub-line straight over
	   the jar lineup and the props, and MEASURED against the actual photograph
	   — text hidden, band screenshotted, contrast computed per pixel across
	   each text element's own box — `ink` failed badly:

	     heading   26.8 % of its ground below 4.5:1, 18.5 % below 3:1, min 1.00
	     sub-line  33.3 % below 4.5:1, 25.8 % below 3:1, min 1.00
	     button    12.0 % below 4.5:1

	   ⚠️ AND NO INK COLOUR FIXES IT. White fails on the pale yellow (median
	   ground `rgb(238,237,155)`), `ink` fails on the dark foliage — the ground
	   is bimodal, so no single text colour clears both.

	   🔴 A SCRIM WAS DERIVED AND REJECTED. The minimum white overlay reaching AA
	   on all three boxes at the 1st percentile is **dimRatio 0.60** — which
	   washes the photograph to 40 % and buries the four-jar lineup that IS the
	   asset (c15-cta.md forbids compositing the lineup separately precisely
	   because it is baked into this image). Fixing legibility by destroying the
	   content is not a fix.

	   ✅ THE COMP ALREADY SOLVES IT, AND THE BUILD HAD SIMPLY NOT COPIED THE
	   LAYOUT. In `pink-new-3.png` the text sits in the PALE, BLURRED UPPER THIRD
	   and the lineup sits below it — heading ~90 px into the band, button ending
	   ~410 of 910. Anchoring the content to the top reproduces that, keeps the
	   photograph at full strength, and needs no new token.

	   ⚠️ `align-items`, NOT `justify-content`. `.wp-block-cover` is a ROW-
	   direction flex container, so the cross axis is the vertical one and
	   `align-items: center` is what centres the inner container.
	   `justify-content: flex-start` was tried first and moved nothing — the
	   computed value changed, the layout did not, which is §4.8's lesson
	   arriving through a different door: verify the CONSEQUENCE, not the
	   property. */
	align-items: flex-start;

	/* 🔴 `ink`, RESTATED, BECAUSE core/cover FORCES WHITE ON ITS CONTENTS —
	   AND THIS IS THE SECOND TIME [checklist §10.101]. `.wp-block-cover` sets
	   `color: #fff` for content sitting on a dimmed photograph. This band has
	   no photograph yet (PLACEHOLDER-C15-BG) and its overlay is `mint`, so the
	   heading and sub-line rendered **white on `#DCFFE9` = 1.08:1** — sampled
	   from a screenshot of the rendered band, not inferred. `ink` gives
	   **11.57:1**. `mint` is on 00-conventions.md §3.1's explicit list of light
	   grounds that take `ink`, so this was the ink rule being silently
	   overridden by a core default.

	   ⚠️ STEP 7 FIXED EXACTLY THIS ON `.chumuk-compare` AND STEP 9 STILL
	   SHIPPED IT HERE. Step 9's acceptance run measured the BUTTON's contrast
	   (12.45:1 on the ink pill, which was correct) and never measured the
	   heading's. A per-component contrast check that picks one element is not a
	   contrast check — the band sweep is what caught it. */
	color: var( --wp--preset--color--ink );

	/* ~~910 px is the comp's band (y ≈10365–11275)~~ — re-measured per column
	   rather than by modal row colour: the photograph's pale cream top edge starts
	   at comp y 10375 (x 60 reads rgb(253 251 227), x 1860 rgb(238 239 178), both
	   already off `ice`) and the footer's cyan begins at 11275, so the band is
	   900. 46.875vw hits it exactly at 1920. */
	min-block-size: clamp( 480px, 46.875vw, 900px );
}

/* ⬅ **RE-KEYED FROM `display-2` TO `h2`, 2026-08-26.** ~~`display-2` at 102 px,
   uppercase~~ — the heading now takes the `h2` size token, matching C35's
   "Expert Guidance in Every Sip", and it is **no longer uppercased**.
   Still breaking to two lines at desktop WITHOUT a hard `<br>` — c15-cta.md
   Responsive is explicit about that. The measure is what forces the break, so
   the line count follows the width instead of being frozen into the markup
   where it would be wrong at every other size. */
/* ✅ THE BAND PADDING IS RIGHT AND WAS CHECKED. The comp's headline caps at
   y 10465 in a band starting at 10375, and with the h2's own 13.9 px box-to-cap
   offset that is 76 px of padding against the cover's 80 — inside 4. An earlier
   reading of this gap said 34, from the wrong band top; it is recorded here so
   the figure is not re-derived from the same mistake. */
.chumuk-cta__heading {
	margin-block: 0;

	/* 🔴 ~~`text-transform: uppercase`~~ — REMOVED 2026-08-26. The all-caps was
	   produced here, not stored: `patterns/cta.php` has always held the string as
	   "Ready To Feel The Difference?" in title case. Removing the declaration is
	   therefore a PRESENTATION change and not a copy change — the SOURCED string
	   is untouched, and `textContent` is byte-identical before and after. */

	/* 🔴 ~~`line-height: calc( 95 / 102 )`~~ — RETIRED 2026-08-26, not re-derived,
	   because there is nothing left to derive it from.
	   ~~[MEASURED] the comp sets its two headline lines with their caps 95 px apart
	   (ink tops 10465 and 10560); 0.91 at 102 gave 87.~~
	   That figure is a measurement of a **102 px** headline. The heading now renders
	   at the `h2` token (fluid 32→58), and **the comp never drew this headline at
	   that size**, so no comp figure exists to re-key the ratio to. Carrying the old
	   RATIO forward (0.9314) would have preserved the comp's proportion but left
	   C15 visibly tighter than C35 at the same size — and parity with C35 is the
	   whole point of the change.
	   ✅ THE `h2` SIZE PRESET ALREADY MODELS THIS: it carries its own line-height,
	   computed **1.07** at every width, which is exactly what C35's heading uses.
	   So the override is dropped and the token answers — §4.8's "when core already
	   models the layout, ask core for it". VERIFIED COMPUTED, not assumed: C15 and
	   C35 both report 1.0700 at 320/768/1180/1440/1920. */

	margin-inline: auto;

	/* ⬅ ~~18ch~~ RE-DERIVED 2026-08-26. `ch` scales with font-size, and the size
	   dropped from 102 to the `h2` token, so 18ch narrowed with it and would have
	   broken the headline into three lines. The new figure is measured, not guessed
	   — see build-reports/50 for the sweep that chose it. */
	max-inline-size: 18ch;
}

.chumuk-cta__sub {
	margin-block: var( --wp--preset--spacing--50 ) 0;
	margin-inline: auto;
	max-inline-size: 60ch;
}

/* 🔴 ~~`.chumuk-cta__actions { margin-block-start: var( --wp--preset--spacing--50 ) }`~~
   — REMOVED 2026-08-26 with the SHOP CHUMUK button it spaced. The `wp:buttons`
   group, its `wp:button` and this rule are all gone; nothing else emitted the
   class, so the rule had no other consumer. ⚠️ There was never a
   `.chumuk-cta__button` rule to remove — the button took its colours from the
   `ink`/`white` presets in the block's own attributes, which is why the pattern's
   docblock could quote 12.45:1 without any CSS here. Verified by grep across the
   theme and the plugin before removal, not assumed. */

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */
@media ( max-width: 781px ) {
	.chumuk-faq {
		--chumuk-faq-disc: 26px;
		--chumuk-faq-bar: 12px;
	}

	.chumuk-cta__heading {
		max-inline-size: none;
	}
}

/* ==========================================================================
   COMPONENT LAYER — build step 10 (footer content)

   c16-footer.md
   ========================================================================== */

/* --------------------------------------------------------------------------
   THE DOODLE LAYER'S MECHANISM — A TONED RASTER, AND THE CSS MASK WAS
   CONSIDERED AND MEASURED AGAINST IT [§10.134].

   The artwork is single-colour line art, so the obvious alternative is to use
   the file as an alpha mask and paint it with a registered token, which would
   make the tone a one-line change. It was rejected on three measured grounds,
   recorded here so the decision can be re-opened on evidence rather than taste:

   1. THE SUPPLIED FILE IS ALREADY AT THE SHIPPING TONE, so the usual reason to
      mask — getting the tone right without a re-export — does not apply.
      `design/footer-doodles-ref.png`'s own ink measures rgb(20,177,214) where
      the comp's doodle ink measures rgb(20,176,214). One level apart, on one
      channel.
   2. A MASK NEEDS A URL IN A LIVE DECLARATION HERE, AND THIS FILE HAS NONE.
      Counted, not assumed: outside this comment, `url(` appears 0 times in
      style.css — no rule in the theme references an asset by path, only
      theme.json's `fontFace.src` does. The only URL available is a
      date-stamped `/wp-content/uploads/2026/08/…` path, so masking would
      introduce the first hardcoded uploads path in the theme's stylesheet —
      a fragility class this project has so far avoided entirely.
   3. THE WAY ROUND THAT IS WORSE. Delivering the URL as an inline custom
      property on the `core/group` means hand-writing a `style` attribute
      declaration that core's own `save()` never produces — which is exactly
      the construction that made `core/image` report "Block contains unexpected
      or invalid content" in patterns/stats.php. Not worth the trade.

   ⚠️ WHAT THIS COSTS: the tone is inside a binary. If the owner wants it
   changeable, the route is the mask plus a THEME-relative asset
   (`assets/img/…`), not an uploads path — that keeps rule 2 satisfied. The
   colour is registered as `doodle-cyan` in theme.json regardless, so the
   design value is recorded whether or not CSS consumes it.

   The layer itself is a core block-support background on the group, so there
   is no rule for it here and nothing in this file paints it.

   ⚠️ IT SHIPS AS LOSSLESS WebP, NOT PNG [§10.137]. 355,103 → 78,892 B, 4.50×,
   with RGBA max difference 0 — bit-exact, so the 13 distinct alpha levels the
   source carries all survive. That matters more here than anywhere else on the
   site: 0.83 % of this file is fully opaque, so nearly every pixel of it is an
   antialiased edge, and the alpha IS the artwork.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   🔴 REVERSED 2026-08-24 BY OWNER RULING [§10.135]. THE WHOLE FOOTER IS NOW
   WHITE, AND IT FAILS AA — KNOWINGLY, MEASURED, AND RECORDED.

   ⚠️ THE BLOCK BELOW IS NOT WRONG AND IS NOT STRUCK ON ITS EVIDENCE. Its
   arithmetic re-measures correctly today: white on the footer ground is
   2.2415:1 and `ink` on it is 5.5541:1, and the shipped build measured a
   worst-case 5.59:1 by pixel-sampling before this change. **The ruling
   overrides a KNOWN, MEASURED AA failure across the whole band — it does not
   correct a mistake.** Same class as §10.126's hero card, applied the same way:
   the design's treatment ships, the failure is recorded per surface with its
   ratio, and nothing is quietly substituted.

   WHAT SHIPS NOW: ground `footer-cyan #1ABCE5`, text `white`, doodle layer
   `doodle-cyan #14B0D6`. All three are OWNER-SPECIFIED, not measured — see
   design-tokens.md §2.4. Measured consequences, by pixel-sampling the ground
   under real glyphs: white sits at **2.24:1** over the flat ground and
   **2.56:1** over a doodle stroke, so every one of the 18 text surfaces fails
   both the 4.5 and the 3.0 floor. Flagged for decision before launch.

   ⚠️ ONE FIGURE IN THE AUTHORISING BRIEF DID NOT REPRODUCE and is recorded
   rather than carried: it gave `ink` on `#1abce5` as 7.76:1. Direct computation
   gives **5.5541:1** and pixel-sampling the shipped build gave **5.59:1**. Every
   other ratio in that brief reproduced to two decimals, so this is treated as a
   single stray figure, not a different method. It changes no decision — `ink`
   passed and `white` fails either way.

   ~~THE WHOLE FOOTER IS `ink`, NOT WHITE [checklist §10.30]. This is the site's
   LARGEST SINGLE CYAN SURFACE, which makes it the most consequential instance
   of the ink rule: white on `cyan #12BDE5` is 2.23:1 across the column
   headings, the links, the body copy, the contact rows and the copyright line.
   `ink` gives 5.59:1. The colour is set on the group block itself
   (`textColor: ink`) so the editor shows the truth; these rules carry geometry
   only.~~ The colour is still set on the group block itself, now
   `textColor: white` with `backgroundColor: footer-cyan`, for the same reason:
   the editor shows the truth.

   ~~The doodle pattern behind it would be decorative and unaffected — see the
   note at the end of this block on why it is not shipped.~~ STRUCK: the doodle
   layer HAS shipped since §10.116 and was replaced with the design's own
   artwork at §10.134. It is still decorative, and it is no longer unaffected —
   it is the darker of the two grounds the white text sits on.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   C16's BRAND LINE BREAKS IN TWO — `max-inline-size`, NOT `<br>` [§10.141],
   derived by the method §10.87 and the `.chumuk-bento-section__head h2` block
   established, and derived AFTER the column widths, because the column is what
   used to bind.

   🔴 NO COPY CHANGED. The shipped string is byte-identical before and after —
   `Bring Fresh Natural Energy To Your Home`, 39 bytes, md5 `6cf5965b…`. Only
   the line break moved.

   MEASURED at 26 px (`h7` is `fluid: false`, so `em` here is invariant by
   construction rather than by clamp arithmetic), Playfair Display 500 against
   the Georgia fallback. Webfont state proven by
   `document.fonts.check('26px "Playfair Display"')` returning true with the file
   served and false with the request aborted at the network layer:

                                    webfont    fallback
     "Bring Fresh Natural Energy"   12.4105     12.2163   <- measure must be >=
     "To Your Home"                  6.4111      6.4976
     + "To"                         13.7512     13.6154   <- measure must be <

   Two-state intersection **[12.4105 em, 13.6154 em)**, 1.2049 em wide,
   **midpoint 13.013 em** — which is what ships.

   ⚠️ THIS COULD NOT HAVE WORKED BEFORE THE COLUMN WIDTHS. With core's equal
   five-way split the brand column offered 11.1382 em at 1920 against the
   12.4105 em line 1 needs, so NO measure could have reached the design's break.
   The column bound, not the measure — §10.87 r6's C08 finding, and §10.88's
   resolution: fix the column.

   🔴 TWO WIDTHS STILL CANNOT HOLD IT, AND THE COLUMN STILL BINDS THERE.
   At 1024 the brand column offers 9.8131 em and at 320 it offers 10.7692 em,
   both under 12.4105. The heading takes three lines at those widths in BOTH
   font states — identical in both, so it costs no swap CLS. Recorded as F79;
   not fixed here, because the fix is a column-width decision at those
   breakpoints and this task's authority was the break, not the grid. */
:root {
	--chumuk-footer-base-gap: 21px;
}

.chumuk-footer__tagline {
	margin-block: var( --wp--preset--spacing--40 ) 0;
	max-inline-size: 13.013em;
}

.chumuk-footer__intro {
	margin-block: var( --wp--preset--spacing--30 ) 0;
	max-inline-size: 42ch;
}

/* The contact rows. `core/html`, because the spec calls for an inline-SVG icon
   per row and a paragraph cannot host one without a class on an inner element
   (00-conventions.md §2). The icons take `currentColor`, so they inherit the
   footer's `ink` and no hex literal enters the markup. */
/* ✅ F29 CLOSED [MEASURED] 2026-08-23, §10.108. These rows had no explicit size
   token and were inheriting `body-lg`'s fluid clamp — computing **17.86 px** at
   1440, not the flat 18 the census reads at 1920. They are a `core/html` block,
   so no `has-…-font-size` class can reach them and the token has to be assigned
   here.
   DERIVED FROM THE COMP, TWO INDEPENDENT WAYS, both on the comp's own strings:
     D1  phone digits `+88 019 44 82 08 01` — ink 156 x 13. Digit height is
         TRACKING-INDEPENDENT; Geist draws 12.75 at 17 px and 13.5 at 18 px, so
         13 solves at **17.2 px**.
     D2  the same string's width — 157.5 at 17 px against the comp's 156, **+0.96 %**.
     cross-check: `chumukstore@gmail.com` width 194.75 at 17 px vs 198, **-1.64 %**.
   ⚠️ The email's ink HEIGHT is not used: `@` and `g` differ enough between faces
   to make it unreliable, the same way `%` wrecked the C11 digit measurements in
   §10.95 r6. The digit height is the clean measure and it decides.
   🔴 NO NEW TOKEN: `label-sm` is already exactly 17 px, so the three-part test
   fails at "no existing token within 2 %" — as it should. F29's note that this
   must not be guessed at 16 px is confirmed: 16 px measures **-7.5 %** on width.
   The custom property was verified non-empty (17px) before this was written,
   per §4.8. */
.chumuk-footer__contact {
	margin-block: var( --wp--preset--spacing--50 ) 0;
	padding: 0;
	list-style: none;
	display: grid;
	row-gap: var( --wp--preset--spacing--30 );
	font-size: var( --wp--preset--font-size--label-sm );
}

.chumuk-footer__contact li {
	display: flex;
	align-items: center;
	gap: var( --wp--preset--spacing--30 );
}

.chumuk-footer__contact svg {
	flex: none;
}

/* ⚠️ THESE TWO ARE REAL DESTINATIONS, so they are NOT the `#` treatment.
   `tel:` and `mailto:` resolve; the deferred-link rule (§1.1 rule 3) covers
   links with no destination, which these are not. The underline is mandatory
   per 00-conventions.md §3.4 and is inherited, not re-declared here. */
/* 🔴 THE COMP DRAWS NO UNDERLINE HERE, AND MATCHING IT COSTS WCAG 1.4.1 [§10.143].
   MEASURED on `design/pink-new-3.png`: scanning the phone and email rows
   (band-relative y 537-552 and 577-594) for any run lighter than the ground
   returns NOTHING — no rule, no underline, at any threshold. The build drew one,
   from theme.json's `styles.elements.link.typography.textDecoration`.

   ⚠️ §10.57 r1 SAYS IN TERMS "The underline is NOT optional … the only
   affordance — WCAG 1.4.1. Do not drop it for aesthetics." THAT REASONING IS
   STILL SOUND AND IS NOT STRUCK: the link colour is identical to the surrounding
   body text — both are now `white` — so colour conveys nothing and the static
   underline was the only affordance. Removing it is a KNOWN 1.4.1 failure on
   two surfaces, applied under the design-first ruling §10.121 exactly as
   §10.135 applied the AA failures, and recorded here rather than substituted.

   PARTIAL MITIGATION, and it is partial: `:hover` and `:focus-visible` still
   draw the underline, because the rule above this one only sets its geometry and
   the comp only ever shows the static state. A keyboard or pointer user gets the
   affordance back; a reader looking at the page does not. Flagged for decision
   before launch with the rest of C16's a11y debt.

   The scope is deliberately these two links and nothing else — every other link
   on the site keeps §10.57 r1's underline. */
.chumuk-footer__contact a {
	color: inherit;
	text-decoration: none;
}

/* The comp draws no underline here, and matching it is a known 1.4.1 failure
   applied under the design-first ruling. Hover and focus restore it [§10.192] —
   which is what keeps the link distinguishable on interaction even though it is
   not at rest. */
.chumuk-footer__contact a:hover,
.chumuk-footer__contact a:focus-visible {
	text-decoration: underline;
}

/* ⚠️ RULE R5 [§14.0] — HALF OF THIS IS STILL LIVE AND HALF IS SUPERSEDED
   [§10.141]. Read both halves before changing anything here.

   🔴 STILL LIVE, AND STILL THE REASON: NO FOOTER COLUMN GETS A FIXED WIDTH.
   Bengali strings run longer than their English equivalents, and a fixed column
   that fits today clips at the deferred Bengali phase. The five columns are
   sized in PER CENT — 30.85 / 13.84 / 13.84 / 13.84 / 15.85 — so they flex with
   the container and a longer string wraps rather than clipping. Nothing here is
   a px width.

   ~~The columns are left to core's own equal distribution.~~ SUPERSEDED: equal
   distribution gave the brand column 11.1382 em at 1920 against the 12.4105 em
   its heading's first line needs, so the comp's break was unreachable by any
   `max-inline-size` — the column bound, not the measure. The widths are derived
   from the comp (link content edges x 694 / 969 / 1244 at a 275 pitch, card
   1520-1780, brand from x 140), and they close: brand 506 + link 227×3 + card
   260 + 4 × 48 gap = 1,639 against a 1,640 container.

   ⚠️ WHAT THIS COSTS AT THE BENGALI PHASE, stated rather than discovered later:
   the link columns drop from 290 px to 227 px at 1920. Longer Bengali labels
   will wrap onto more lines there than they would have. They will NOT clip —
   that is what R5 exists to prevent and per cent still prevents it — but the
   column heights will grow. Re-measure this band when Bengali ships. */
/* --------------------------------------------------------------------------
   THE FOOTER CARD — TWO BOXES, BOTH NOW MEASURED [§10.136].

   🔴 THE `3 / 4` WAS `[DERIVED]` AND IT TURNED OUT TO BE RIGHT, WHICH IS WORTH
   SAYING PLAINLY RATHER THAN QUIETLY REPLACING. The comp draws a WHITE tile at
   x 1520–1780, y 11620–11968 — 260 × 348, ratio **0.7471** — against a declared
   0.75. That is 0.4 % out, and the guess was the TILE's ratio all along.
   It is re-declared as `260 / 348` anyway, because a measured value and a lucky
   one are not the same thing to the next reader.

   ⚠️ AND THE SUPPLIED FILE IS NEITHER BOX. `footer-card-tile.png` is 940 × 1048,
   ratio 0.897 — it is the PHOTOGRAPH, and it belongs inside a second box the
   comp also draws: a cyan panel at x 1530–1770, y 11698–11958, **240 × 260,
   ratio 0.9231**, inset 10 px left, right and bottom. Letterboxing the
   photograph inside the tile's 0.7471 would have looked like a fix and measured
   like one, which is exactly what the two separate declarations below prevent.

   THE INSETS ARE PROPORTIONAL, NOT PIXEL. 10 / 260 = 3.846 % of the tile's own
   width, and percentage padding resolves against width, so the whole card scales
   with its column instead of holding a 10 px inset at every size.

   🔴 THE COMP'S WORDMARK IS NOT SHIPPED AND ITS SPACE IS DELIBERATELY LEFT.
   The comp draws a cyan wordmark 99 × 60 between the tile top and the panel
   (y 11630–11690, so 78 px of the tile's 348 above the panel). The only logo
   asset that exists is attachment 40, `chumuk-wordmark-white.png` — white, and
   invisible on a white tile. Rather than close the gap up and stretch the
   photograph to fill it, the panel keeps its measured 240 / 260 and sits at the
   BOTTOM of the tile, so the missing element reads as missing. G29 / F74.

   ~~Same guard as `.chumuk-experts__media` USED TO CARRY — `core/cover` ships
   `min-height: 430px`, which with an `aspect-ratio` becomes the DRIVING
   dimension and solves for width.~~ STRUCK: this is a `core/group` now, not a
   `core/cover`, so there is no 430 px minimum to defeat. The finding itself is
   still live and still written out in full in the `.chumuk-experts__media`
   tombstone above; `.chumuk-footer__card-media` simply no longer needs it.
   -------------------------------------------------------------------------- */
.chumuk-footer__card-media {
	aspect-ratio: 260 / 348;
	padding: 3.846%;
	display: flex;
	flex-direction: column;
	/* ⬅ `flex-end` UNTIL §10.142, when the wordmark filled the space it was
	   holding open. The comp's tile is 10 + 60 + 8 + 260 + 10 = 348 exactly, so
	   with both children at their measured sizes `space-between` leaves precisely
	   the comp's 8 px between them — no gap value is chosen, it falls out of the
	   arithmetic closing. VERIFIED, not assumed: measured 78 px from tile top to
	   panel top at 1920 against the comp's 78. */
	justify-content: space-between;
	border-radius: var( --chumuk-card-radius );
	overflow: hidden;
}

/* The card's cyan wordmark [§10.142, closes G29]. 99 of the comp's 260 px tile,
   which is 41.25 % of the 240 px content box the 3.846 % padding leaves — a
   percentage so it scales with the card rather than pinning a pixel width. */
.chumuk-footer__card-mark {
	margin-block: 0;
	align-self: center;
	inline-size: 41.25%;
}

.chumuk-footer__card-mark img {
	display: block;
	inline-size: 100%;
	block-size: auto;
}

.chumuk-footer__card-photo {
	margin-block: 0;
}

.chumuk-footer__card-photo img {
	display: block;
	aspect-ratio: 240 / 260;
	inline-size: 100%;
	block-size: auto;
	object-fit: cover;
	/* The comp's inner panel carries a ~8 px radius on a 240 px panel, against
	   the tile's ~20 px on 260 — a third of the outer corner. `--chumuk-card-radius`
	   is 16 px and is the tile's; the panel gets half of it, which lands at 8 px
	   at the comp's own size. No new token for one corner. */
	border-radius: calc( var( --chumuk-card-radius ) / 2 );
}

/* --------------------------------------------------------------------------
   THE BOTTOM ROW — THREE SLOTS, THE MIDDLE ONE EMPTY ON PURPOSE [§10.103].

   The comp draws `[email field + Subscribe Now]` left · `© 2026 CHUMUK` centre ·
   `Follow Us: [f][tiktok][ig][x]` right. The client removed the newsletter on
   2026-08-22 — **nothing on this site collects an email address**, and Jetpack
   Forms was never activated — so the copyright takes the left slot the form
   vacated and the middle slot stays empty.

   🔴 THE EMPTY SLOT IS KEPT, NOT DELETED. It is where the form returns when an
   ESP is chosen, and keeping it means that return is a content edit rather than
   a re-derivation of this row's geometry.

   Three explicit tracks rather than `space-between`, so the social block holds
   the right edge whether or not the middle slot ever has content in it — with
   `space-between` and two children the copyright and the social would drift to
   the extremes and the row would silently change shape the day the form comes
   back.

   ⚠️ THE BLOCK'S LAYOUT IS `default`, NOT `constrained`, AND THAT IS LOAD-
   BEARING. With `constrained`, core emits `.is-layout-constrained > * {
   margin-inline: auto }`, which CENTRES every child inside its own grid track:
   MEASURED, the copyright sat at x 200 of a 1640 row instead of 0, and the
   social block ended at 1411 instead of 1640. `justify-self` was being applied
   and then overridden by the auto margins. Flow layout emits no such rule and
   the grid places the children itself.
   -------------------------------------------------------------------------- */
.chumuk-footer__base {
	/* [MEASURED] the comp leaves 21 px between the footer card's bottom edge
	   (y 11967) and its bottom row (ink 11988); `70` (48) left 52.5.
	   🔴 THE FOOTER'S TOP PADDING IS ALSO CORRECTED, IN parts/footer.html: `90`
	   (80) -> `110` (160). [MEASURED] on five independent runs down the left
	   column, the comp's whole footer column sat 63 px lower than the build's —
	   logo ink 11436 against 11373, brand 11627 against 11573, body 11710 against
	   11662, phone 11812 against 11758, email 11852 against 11796 — and the comp's
	   band starts at 11275 with its logo box at 11435. */
	margin-block-start: var( --chumuk-footer-base-gap );
	padding-block-start: var( --wp--preset--spacing--50 );
	border-block-start: 1px solid var( --chumuk-border-hairline );
	display: grid;
	/* 🔴 `auto 1fr auto`, NOT `1fr 1fr 1fr` [§10.192] — equal thirds STARVED THE
	   RIGHT-HAND GROUP. [MEASURED at viewport 924] the base is 817px, so equal
	   thirds gave each track 256. `.chumuk-footer__follow` needs 268 (label 76 +
	   24 gap + 168 icon run) and was handed 256 — a 12px deficit that pushed the
	   X icon's right edge to 957 against a footer edge of 924, while the MIDDLE
	   track, which has no content at all, was holding 256px of the row.
	   `auto` sizes the copyright and the follow group to what they need and the
	   empty middle takes the remainder, so the row cannot starve either end. */
	grid-template-columns: auto 1fr auto;
	align-items: center;
	column-gap: var( --wp--preset--spacing--50 );
}

/* ⚠️ NECESSARY BUT NOT SUFFICIENT ON ITS OWN, and the pair is the point
   [§10.192]. The icon list is both shrinkable (`flex: 0 1 auto`) and wrappable,
   so it compressed under its content width and wrapped INTERNALLY: 3 + 1, 72px
   tall instead of 24. `flex-shrink: 0` makes it hold its content width — but on
   its own it only moved the deficit onto the label, which wrapped to
   "Follow / Us:" while the X still overflowed. The real cause was the base
   grid's equal thirds above. Both are kept: the track is wide enough AND the
   icon run is no longer compressible. */
.chumuk-footer__social {
	flex-shrink: 0;
}

/* ==========================================================================
   🔴 THE FOOTER COLUMNS WRAP — THE HEADINGS WERE BREAKING MID-WORD  [§10.192]

   [MEASURED] between ~782 and ~1179 the columns row is `flex-wrap: nowrap` with
   five children, so each column compressed to 98px while the headings need, on
   one line: TRUST & LEGAL 166 · NAVIGATION 131 · SUPPORT 101 (20px type +
   1.6px tracking). The result was "NAVIGAT/ION", "SUPPOR/T", "TRUST &/LEGAL".

   🔴 AND THIS IS WHY THE RESPONSIVENESS SWEEP MISSED IT. Core sets
   `word-break: break-word` on `.wp-block-column`, which converts the fit failure
   into a BROKEN WORD instead of an overflow: the heading measured 98 × 56 with
   scrollWidth 98 === clientWidth 98, so "zero document overflow at all widths"
   was TRUE and still hid this. A document-overflow assertion is structurally
   blind to this class of defect — the check has to compare each heading's
   single-line requirement against its column width.
   Same defect class as C04's nowrap fieldset and C06's tab strip: a nowrap flex
   row that cannot fit its content. Fixed the same way — WRAP, not a breakpoint,
   so the row reflows exactly when it stops fitting.

   ⚠️ THE TWO `!important`s ARE DELIBERATE AND THEY ARE THE ONLY TWO IN THIS
   PASS. The rules being beaten are core's own, not this theme's:
     `@media (min-width: 782px) { .wp-block-columns { flex-wrap: nowrap !important } }`
     `style="flex-basis:13.84%"` — an INLINE style in the transcribed markup
   A stylesheet declaration cannot beat either without `!important`, at any
   specificity, and both are left byte-identical rather than edited.

   ⚠️ THE MINIMUM IS THE MEASURED 166px, not a round number, and it is scoped to
   the three nav columns via `:has( > h2.is-style-label )` — the brand column's
   tagline is PROSE and is supposed to wrap over two lines, so forcing a minimum
   on it would break a layout that is correct.

   🔴 BASIS 166 TOO, NOT JUST A MINIMUM — OTHERWISE THE ROW WRAPS AND THE CARD
   MOVES. A flex line is broken using each item's BASE size; shrinking happens
   only after the line is decided. With the dump's `flex-basis: 13.84%` the three
   nav columns based at 181 each and [MEASURED at a 1308px row] the five bases
   plus four 48px gaps needed 1346 — the line broke by 38px even though every
   column could have shrunk to fit, so the product card led row 2 at the LEFT
   instead of ending row 1 at the right. Basing them at the same 166 makes the
   bases 404 + 498 + 207 + 192 = 1301, which fits. `flex-grow: 1` is untouched,
   so above that they still grow: 166 is a floor, never a cap.

   ⚠️ `word-break: normal` on these headings is deliberate: if they ever fail to
   fit again it must show as visible overflow rather than silently breaking a
   word — i.e. the failure has to be the kind a sweep can see.
   ========================================================================== */
.chumuk-footer .wp-block-columns {
	flex-wrap: wrap !important;
}

.chumuk-footer .wp-block-column:has( > h2.is-style-label ) {
	min-inline-size: 166px;
	flex-basis: 166px !important;
}

/* The card is the LAST column and belongs on the right at every width. On the
   five-column row an auto start-margin absorbs the leftover free space so it
   sits flush to the content edge; on the narrower widths where the row genuinely
   cannot fit five columns and the card takes a row of its own, the same
   declaration keeps it at the right instead of stranding it at the left. One
   rule, both cases, and no width named. */
.chumuk-footer .wp-block-column.chumuk-footer__card {
	margin-inline-start: auto;
}

.chumuk-footer h2.is-style-label {
	word-break: normal;
	overflow-wrap: normal;
}

/* core's flow layout puts `margin-block-start` on every child but the first,
   which inside a grid pushes items down within their own cells — the same
   defect measured at §10.101 on the counter cards. */
.chumuk-footer__base > * {
	margin-block: 0;
}

.chumuk-footer__copyright {
	justify-self: start;
}

/* ⬅ `.chumuk-footer__social` held `justify-self` until §10.143. The comp puts a
   `Follow Us:` label beside the icons, so a wrapper now owns the right slot and
   the list sits inside it.

   The comp measures the label at x 1522-1597 and the icon run starting at 1623,
   so 26 px of gap on a 1920 band. `50` is 24 px — the nearest step on the scale,
   and no new token for one gap. */
.chumuk-footer__follow {
	justify-self: end;
	column-gap: var( --wp--preset--spacing--50 );
}

/* 🔴 TOMBSTONE — THIS RULE NEVER DID WHAT IT SAID, AND IT IS NOW GONE [§10.135].
   (The struck `margin-block-start` note it carried belongs to §10.103: the
   bottom row is a grid, so the social block sits in its own track rather than
   stacking under the copyright. That part is still true and still not a rule.)

   ~~Social icons take `ink` fills [c16-footer.md Contrast]. `is-style-logos-only`
   renders the glyph in `currentColor` with no pill behind it, so the colour
   comes from here and NOT from an `iconColorValue` hex baked into the block
   markup — which is what keeps the part free of hex literals.~~
   ~~.chumuk-footer__social { color: var( --wp--preset--color--ink ); }~~

   TESTED BEFORE REWRITING, and the claim is false as shipped. The rule DID
   compute — `getComputedStyle` on the `ul` returned `rgb(52, 52, 52)` — but
   core's `is-style-logos-only` paints each `li` from a PER-SERVICE brand colour
   at `.wp-block-social-links.is-style-logos-only .wp-social-link-<service>`,
   which outranks a single class on the parent. MEASURED on the shipped page:
   Facebook rendered `rgb(8, 102, 255)` at **2.17:1** and Instagram
   `rgb(240, 0, 117)` at **1.90:1** — two AA failures that predate this pass and
   that the comment above asserted did not exist (**F72**).

   ⚠️ AND THE FIX IS NOT THE OBVIOUS ONE. Strengthening the selector is
   forbidden, and `iconColorValue` bakes a hex into the part — the exact fault
   the struck comment was right to avoid. The block's `iconColor` slug does it
   instead: core resolves `{"iconColor":"white"}` server-side into a
   `has-white-color` class on each `li`, so the markup carries a SLUG and no hex,
   and no selector here is strengthened. Verified: all four computed values
   (`li`, `a`, `svg` fill, `svg` color) read `rgb(255, 255, 255)` afterwards.
   The comp draws these icons white, so this is also the design's own treatment
   — at **2.24:1**, recorded with the rest of the band's failures. */

@media ( max-width: 781px ) {
	.chumuk-footer__intro {
		max-inline-size: none;
	}

	/* One column below `md`. The empty middle slot collapses to nothing here —
	   it has no content and no min-height — so the copyright and the social
	   block sit directly on top of each other rather than with a hole between
	   them. Verified by measuring the row's height, not assumed. */
	.chumuk-footer__base {
		grid-template-columns: 1fr;
		row-gap: var( --wp--preset--spacing--40 );
		justify-items: center;
	}

	.chumuk-footer__copyright,
	.chumuk-footer__social {
		justify-self: center;
	}
}

/* ==========================================================================
   BUILD STEP 11 — MOTION: C31, the site-wide reveal

   x-cross-cutting.md · 00-conventions.md §5
   ========================================================================== */

/* 🔴 READ THIS BEFORE CHANGING ANY SELECTOR BELOW.

   NOTHING HERE HIDES ANYTHING BY DEFAULT. Every rule in this block is scoped to
   `.chumuk-reveal-ready`, a class that ONLY `assets/js/reveal.js` adds, and only
   after it has confirmed `IntersectionObserver` exists, confirmed the visitor
   has not asked for reduced motion, and built the observer that will reveal
   these elements again.

   That ordering is the whole contract, and it is what x-cross-cutting.md means
   by "CSS holds the final visible state" and "an element that is invisible
   until JS runs is a defect":

     script 404s / fails to parse   -> class absent -> nothing hidden
     no IntersectionObserver        -> class absent -> nothing hidden
     prefers-reduced-motion: reduce -> class absent -> nothing hidden
     JavaScript disabled            -> class absent -> nothing hidden

   🔴 DO NOT "simplify" this by moving the pre-reveal state onto the bare
   section selectors and letting JS remove it. That inverts the failure mode
   from "no animation" to "blank page", which is the defect this file's own
   spec names.

   The selector list is enumerated in BOTH this file and reveal.js. They must
   agree: a section listed here but not there would be hidden and never
   revealed. The hero and marquee are absent from both on purpose — they are
   the LCP-critical pair — and so is the footer.
   -------------------------------------------------------------------------- */
.chumuk-reveal-ready :is(
	.chumuk-bento-section,
	.chumuk-ingredients,
	.chumuk-store,
	.chumuk-howto-section,
	.chumuk-stats,
	.chumuk-compare-band,
	.chumuk-counters,
	.chumuk-testimonials,
	.chumuk-experts,
	.chumuk-faq-section,
	.chumuk-cta
) {
	transition:
		opacity var( --chumuk-dur-slow ) var( --chumuk-ease ),
		transform var( --chumuk-dur-slow ) var( --chumuk-ease );
}

.chumuk-reveal-ready :is(
	.chumuk-bento-section,
	.chumuk-ingredients,
	.chumuk-store,
	.chumuk-howto-section,
	.chumuk-stats,
	.chumuk-compare-band,
	.chumuk-counters,
	.chumuk-testimonials,
	.chumuk-experts,
	.chumuk-faq-section,
	.chumuk-cta
):not( .is-in ) {
	opacity: 0;
	/* Small, and vertical only. A large offset would reflow the page as each
	   section settles and register as layout shift; 20 px is below the
	   threshold that moves CLS while still reading as movement. */
	transform: translateY( 20px );
}

/* --------------------------------------------------------------------------
   🔴 TWO MORE CONTROLS THAT DEFEATED THE COMPANION TONE — F11, second sweep
   [checklist §10.100 r1 closed the carousel arrows; step 11 found these].

   The global ring is `:where(…)`, zero specificity, and `box-shadow` does not
   cascade per-layer: one declaration replaces the whole list. So ANY component
   that sets its own `box-shadow` — or resets it to `none` — silently drops the
   companion. §10.100 r1 fixed the two carousel arrows and PROVED by grep that
   no other control in `style.css` was affected. That grep was correct and
   still missed these, because neither shadow is in this file:

     - `a.skip-link` carries `box-shadow: rgba(0,0,0,0.6) 0 0 2px 2px` from
       WordPress's own core styles.
     - `a.wp-block-social-link-anchor` computes `box-shadow: none` from
       core/social-links' stylesheet — a RESET, which is just as effective at
       removing the companion as a value is.

   ✅ STANDING LESSON: grepping this file cannot enumerate the controls at
   risk, because the defeating declaration may live in core's CSS. The reliable
   test is the one step 11 ran — focus every focusable control on the rendered
   page and read the computed ring.
   -------------------------------------------------------------------------- */
.skip-link:focus-visible,
/* ⚠️ SCOPED THROUGH `.chumuk-footer__social` ON PURPOSE. A bare
   `.wp-block-social-link-anchor:focus-visible` is (0,2,0) and LOST to core's
   own `.wp-block-social-links .wp-social-link a` reset at (0,3,0) — measured,
   the shadow stayed `none` after the first attempt. Adding the component class
   ties the specificity and wins on order. This is a component-scoped override
   of a third-party reset, not strengthening aimed at our own global rule. */
.chumuk-footer__social .wp-block-social-link-anchor:focus-visible {
	box-shadow: 0 0 0
		calc(
			var(--wp--custom--focus-ring-offset) + var(--wp--custom--focus-ring-width) +
				var(--chumuk-focus-ring-companion-width)
		)
		var(--chumuk-focus-ring-companion);
}


/* ==========================================================================
   §I  THE INNER-PAGE VOCABULARY  [build step 12 — the shared frame]
   ==========================================================================
   🔴 TRANSCRIBED, NOT AUTHORED. The design ships this block already written, in
   every one of the nine inner-page files (`.tmp/design-verify/chumuk-*.dc.html`,
   identical in each). It is reproduced here rather than reconstructed from the
   READMEs, because a reconstruction is a second set of decisions wearing the
   first one's name. 184 selectors, 96 distinct `chumuk-*` class names.

   ⚠️ EVERY `chumuk-*` NAME IN THIS BLOCK WAS GREPPED AGAINST THE WHOLE THEME AND
   PLUGIN BEFORE IT WAS WRITTEN — the rule three defects paid for (`.chumuk-step`,
   `.chumuk-chip`, and the `--dot` scope). **95 of 96 were clean.** Six names that
   a substring grep flags are NOT collisions and were checked individually:
     · `chumuk-card`  — the theme has `--chumuk-card-radius` and friends, TOKENS.
                        There is no `.chumuk-card` class selector. Clean.
     · `chumuk-qty`   — the store has `data-chumuk-qty`, an ATTRIBUTE, and its own
                        `.cs-qty`. `grep -c '\.chumuk-qty' style.css` = 0. Clean.
     · `chumuk-choice`— the hero has `data-chumuk-choice`, an ATTRIBUTE, and
                        `.chumuk-hero__variant-choice`, a different class. Clean.
     · `chumuk-chip` / `chumuk-step` / `chumuk-store` — appear in this block only
                        inside COMMENTS, which is how the design records the two
                        renames. No selector. Clean.

   🔴 THREE DELIBERATE DEPARTURES FROM THE DESIGN SOURCE, AND ONLY THREE:

   1. `.chumuk-eyebrow` IS SCOPED TO `.chumuk-page`. **This is the one real
      collision of the 96.** `.chumuk-eyebrow` already exists at style.css §12 with
      one consumer, C14's FAQ eyebrow (`patterns/faq.php`). The design's own README
      saw it and said §I "happens to win only because it sets `margin: 0` and comes
      later — that is luck, not design." Transcribed bare, this block WOULD HAVE
      MOVED THE HOMEPAGE: it declares `font-weight: 700`, `letter-spacing: 0.08em`,
      `line-height: 1.4` and `margin: 0`, none of which C14's preset classes carry,
      and `.has-*-font-size` presets only defend size and colour. Scoping to the
      inner-page root makes the separation structural instead of ordinal. The
      design's markup is unchanged — its root already IS `.chumuk-page`.

   2. THE `--dot` HOIST TAKES REGISTERED SLUGS, NOT THE DESIGN'S HEX. The design
      writes `--dot: #9e1b3c`. This build's standing rule is zero hex literals, and
      all four are in the palette — `dot-wine` `dot-magenta` `dot-teal` `dot-amber`,
      registered at §10.194 A. [MEASURED] the slug values are byte-identical to the
      design's four hexes, so this is a spelling change and not a colour change.

   3. `.chumuk-checkout__*` IS KEPT IN THIS BLOCK rather than deferred to the
      checkout template. The design authored §I as one set; splitting it would be a
      seam the design did not draw. The rules are inert until checkout markup
      exists, so they cost nothing now and cannot drift later.

   ⚠️ WHY THE `--dot` HOIST IS UNSCOPED, AND WHY C07 DOES NOT MOVE.
   `chumuk_store_dot_rules()` emits `.chumuk-store [data-chumuk-key="…"]` — (0,2,0)
   and, since §10.195, keyed on the PRODUCT, not the flavour. The four rules below
   are (0,1,0) and keyed on the flavour, so the PDP thumb strip and the empty-cart
   chips — which sit outside `.chumuk-store` and resolved `--dot` to nothing, three
   16px holes at `rgba(0,0,0,0)` — now resolve, while every C07 card keeps the
   store's higher-specificity value. Verified by measurement, not by reading.

   ~~ONE VALUE IN THIS BLOCK FAILS A CRITERION THIS PROJECT MEASURES ELSEWHERE.
   `--chumuk-field-border: #CBD9E2` gives the form field 1.44:1 on white … it is
   transcribed as instructed. Reported, not silently overridden.~~ — CLOSED, and the
   swap is made [§10.198 TASK A]. 🔴 THE TWO DOCUMENTS DISAGREED AND THE WRONG ONE
   WAS CARRIED: the pages README's #CBD9E2 was quoted over the same brief's own rule
   that contrast applies to control boundaries WITHOUT EXCEPTION. A form control is
   not a marketing band, so none of the sub-AA design rulings reach it.
   🔴 THE DESIGN SYSTEM'S OWN RATIOS ARE OPTIMISTIC — AND I NEARLY CARRIED THEM.
   Its own note claiming "≥3.56:1 on all six grounds", and its 3.90 / 3.77 / 3.68 / 3.56, do not
   survive measurement. [MEASURED] by PIXEL-SAMPLING the painted border against the
   painted ground: **3.90 white · 3.62 ice · 3.36 pink-soft · 3.14 sand** — which is
   the figure pair this comment carried all along (3.89 / 3.61 / 3.35 / 3.13, to
   rounding). I had already struck those as mine-and-wrong on the design system's
   authority BEFORE measuring, and the measurement put them back. Take the design
   system's VALUE, which is sound; do not take its arithmetic.
   ⚠️ THE WORST GROUND IS SAND AT 3.14:1. It passes, with 0.14 of margin. Any future
   darkening of `sand` spends that margin.

   ⚠️ THE NEW VALUE IS THE INK SLUG AT 62%, NOT A LITERAL. The design system writes
   `rgb(52 52 52 / 0.62)`; `ink` IS #343434 = rgb(52,52,52), so `color-mix` expresses
   the identical colour through the registered slug and keeps the zero-hex rule
   whole. [MEASURED] it computes — an unsupported colour function would void the
   whole declaration and leave the control with NO boundary, which is worse than a
   faint one, so this was measured before it was trusted.

   ⚠️ SCOPED TO CONTROL BOUNDARIES ONLY. `--chumuk-field-border` stays, at its
   original value, on the two things that are NOT controls: `.chumuk-flowsteps`'
   connector line and `.chumuk-flowstep`'s status ring. 1.4.11 does not reach
   decoration, and darkening them would be a visual change nobody asked for.

   ⚠️ FIVE COLOURS HERE HAVE NO PALETTE SLUG and are declared as §I tokens rather
   than repeated as literals: `--chumuk-field-border` #CBD9E2, `--chumuk-field-ink`
   #4A4249 (= C07's `--cs-ink-soft`), `--chumuk-rule` #E3ECF2, `--chumuk-ink-dark`
   #232323 (= C07's `--cs-dark`, which the design reuses because `.chumuk-btn` IS
   `.cs-add`), and `--chumuk-page-shadow` rgba(2, 63, 130, 0.08) — `blue-deep` at
   8%. Registering four more palette entries would put them in the editor colour
   picker, which §15.4 argues against for values an author never picks.
   ========================================================================== */
/* ==========================================================================
   §I  THE INNER-PAGE VOCABULARY — ONE AUTHORED SET, SHARED BY EVERY PAGE.
   🔴 NOTHING HERE IS A NEW DESIGN DECISION WHERE AN OLD ONE EXISTS. Each value
   below is either a token already in this file or a value already measured in a
   band, re-declared under a page-level name so the inner pages cannot drift
   from the homepage or from each other:
     · sections alternate WHITE and `ice` #E5FBFB — C09's and C14's own grounds,
       and the only two the homepage uses for a plain content band;
     · headings are the heading face at theme.json's `h-2` / `h-4` clamps;
     · every label is `.is-style-label` — the body face, uppercase, 0.08em,
       exactly as the footer's column headings;
     · the primary button IS `.cs-add`: #232323 pill, 18/32, 15px/700/0.1em,
       crimson on hover. It is the site's buy button and these pages are a buy
       flow, so it is reused rather than re-drawn;
     · the card radius is `--chumuk-card-radius` (16px), already in the file.
   ⚠️ THE ONE GENUINELY NEW SURFACE IS THE FORM FIELD. No band on the homepage
   has a text input — the newsletter block does not exist and the FAQ has no
   search — so there is no measured control to copy. It is built from the tokens
   the rest of the page uses (body face, `--chumuk-card-radius` less 4, the
   global focus ring) and it is flagged as authored, not transcribed.
   ========================================================================== */
:root {
	--chumuk-page-shadow: 0 10px 30px rgba( 2, 63, 130, 0.08 );
	--chumuk-field-border: #CBD9E2;
	--chumuk-control-border: color-mix( in srgb, var( --wp--preset--color--ink ) 62%, transparent );
	--chumuk-text-secondary: color-mix( in srgb, var( --wp--preset--color--ink ) 75%, transparent );
	--chumuk-error-ink: #B3000A;
	--chumuk-field-ink: #4A4249;
	--chumuk-rule: #E3ECF2;
	--chumuk-ink-dark: #232323;

	/* --- the summary card's two colours, promoted to :root [§10.203] --------
	   🔴 THESE REPLACE TWO HEX LITERALS AND THE OBVIOUS FIX WOULD HAVE BROKEN THEM.
	   `.chumuk-summary` was carrying `rgba( 158, 27, 60, 0.1 )` and `#E4C8D4`
	   inline. The store band already names both — `--cs-shadow-card` and
	   `--cs-note-rule` — so swapping the names in looks like the whole job.
	   [MEASURED] it is not: both `--cs-*` tokens are declared on `.chumuk-store`
	   (style.css:4000), and `.chumuk-summary` on the cart and checkout pages is
	   not inside that band. ⚠️ AN UNDECLARED `var()` VOIDS ITS WHOLE DECLARATION,
	   so the card would have shipped with no shadow and no rule — a change that
	   names real tokens and still breaks the thing it touches.
	   [MEASURED] `dot-wine` is #9E1B3C in theme.json's palette, which is exactly
	   `rgb( 158 27 60 )` — read from the palette, not inferred from the number.
	   The dashed rule is not a tint of any registered colour (its three channels
	   solve to three different alphas: 0.278 / 0.241 / 0.220), so it is expressed
	   as the nearest mix of one — 25% `dot-wine` on white, #E7C6D3 against the
	   design's #E4C8D4. On a 1px dashed rule that difference is not resolvable. */
	--wp--preset--color--dot-wine-rgb: 158 27 60;   /* #9E1B3C — theme.json slug `dot-wine` */
	--chumuk-summary-shadow: 0 10px 26px rgb( var(--wp--preset--color--dot-wine-rgb) / 0.1 );
	--chumuk-summary-rule: color-mix( in srgb, var(--wp--preset--color--dot-wine) 25%, var(--wp--preset--color--white) );

	/* --- PDP additions [§10.200] -----------------------------------------
	   ⚠️ THREE COLOURS THE PALETTE DOES NOT CARRY, added as §I tokens on the
	   documented precedent (`--chumuk-field-ink`, `--chumuk-rule`), not as hex
	   literals at their point of use. Each is the design's own value, unchanged.
	   `--chumuk-muted-ink` is NOT `--chumuk-text-secondary`: that token is `ink`
	   at 75 %, which composites to #676767 — a neutral grey. This one is
	   #6B6068, warm and purple-leaning, and the two are visibly different.
	   [MEASURED] #6B6068 on `pink-soft` = 5.17:1, so the PDP subtitle clears
	   4.5:1 on the band it actually sits on.
	   🔴 `--chumuk-save-bg` #006C90 IS NOT `dot-teal` #006C94, though it is four
	   units away and reads identical. It is transcribed rather than rounded to
	   the slug, because a colour that is nearly a token is still not that token,
	   and silently substituting one would put a false equivalence in the sheet.
	   Raised for the owner in build report 79. */
	--chumuk-muted-ink: #6B6068;
	--chumuk-rule-pink: #EFD8E2;
	--chumuk-save-bg: #006C90;
}

.chumuk-band { padding-block: clamp( 56px, 6vw, 104px ); }
.chumuk-band--ice { background-color: var(--wp--preset--color--ice); }
.chumuk-band--pink { background-color: #FDEAF1; }
.chumuk-band__inner {
	max-width: var(--wp--style--global--content-size);
	margin-inline: auto;
}
.chumuk-band > * { margin-block-start: 0; }

.chumuk-lede-head { display: grid; gap: 14px; max-width: 62ch; margin-bottom: clamp( 32px, 3vw, 56px ); }
.chumuk-page .chumuk-eyebrow {
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	line-height: 1.4;
	font-size: 13px;
	font-weight: 700;
	color: var(--wp--preset--color--dot-wine);
	margin: 0;
}
.chumuk-h2 {
	margin: 0;
	font-family: var(--wp--custom--font-heading);
	font-weight: 500;
	font-size: var(--wp--preset--font-size--h-2);
	line-height: 1.1;
	text-wrap: pretty;
}
.chumuk-h3 {
	margin: 0;
	font-family: var(--wp--custom--font-heading);
	font-weight: 500;
	font-size: var(--wp--preset--font-size--h-4);
	line-height: 1.15;
	text-wrap: pretty;
}
.chumuk-prose { margin: 0; font-size: var(--wp--preset--font-size--body-lg); line-height: 1.6; color: var(--chumuk-field-ink); text-wrap: pretty; }
.chumuk-prose + .chumuk-prose { margin-top: 1em; }

.chumuk-grid { display: grid; gap: clamp( 16px, 1.5vw, 24px ); }

/* 🔴 CORE'S FLOW-LAYOUT BLOCK GAP, NEUTRALISED INSIDE A GRID. A `core/group` carrying
   `.chumuk-grid` is still `is-layout-flow` to WordPress, so core emits
   `:where(.is-layout-flow) > :where(:not(:first-child)) { margin-block-start: 24px }`.
   In a flow container that IS the gap; in a grid container it is 24px of margin on
   every item EXCEPT the first — so the first card of every row sits 24px higher than
   its neighbours while `gap` is separately doing the real spacing.

   [MEASURED] before this rule, at 1440: About's values row `1537.4, 1561.4, 1561.4,
   1561.4` and Contact's channel row `715.6, 739.6, 739.6`, with computed
   `margin-block-start` of `0px` on the first child and `24px` on the rest.

   ⚠️ CONTACT SHIPPED WITH THIS AND FIVE-WIDTH SWEEPS PASSED IT FIVE TIMES. The sweep
   measures overflow, counts and rendered text; nothing in it compares the tops of
   siblings, so a 24px stagger is invisible to it. Found by looking at a screenshot.

   ⚠️ NOT `!important` AND NOT A STRENGTHENED SELECTOR. Core wraps its own selector in
   `:where()`, which zeroes its specificity, so this plain `0,1,0` rule wins on merit.
   The grid's `gap` above is untouched and remains the only thing spacing these items. */
.chumuk-grid > * {
	margin-block-start: 0;
}

.chumuk-grid--2 { grid-template-columns: repeat( auto-fit, minmax( 300px, 1fr ) ); }
.chumuk-grid--3 { grid-template-columns: repeat( auto-fit, minmax( 260px, 1fr ) ); }
.chumuk-grid--4 { grid-template-columns: repeat( auto-fit, minmax( 210px, 1fr ) ); }

/* ⚠️ `--fixed4` IS NOT `--4`, AND IT LIVES HERE RATHER THAN IN §I-D BECAUSE IT IS A
   GRID UTILITY, NOT AN ABOUT-PAGE RULE. Transcribed from `chumuk-about.dc.html:5607`
   — a §I utility the frame never received, because no page before About laid out
   eight equal cards. The three above are `auto-fit minmax`, which lets the track
   count fall out of the available width; this one PINS it to 2 below 900 and 4 above,
   so eight ingredient cards read as 4×2 and 2×4 and never as a ragged 3+3+2. */
.chumuk-grid--fixed4 { grid-template-columns: repeat( 2, minmax( 0, 1fr ) ); }

@media ( min-width: 900px ) {
	.chumuk-grid--fixed4 { grid-template-columns: repeat( 4, minmax( 0, 1fr ) ); }
}

.chumuk-card {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	padding: clamp( 20px, 2vw, 30px );
	box-shadow: var(--chumuk-page-shadow);
	display: grid;
	gap: 12px;
	align-content: start;
}
.chumuk-card--flat { box-shadow: none; border: 1px solid var(--chumuk-rule); }
.chumuk-card__label {
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 12px;
	font-weight: 700;
	color: var(--wp--preset--color--dot-wine);
}
.chumuk-card__title { margin: 0; font-family: var(--wp--custom--font-heading); font-weight: 500; font-size: 24px; line-height: 1.2; }
.chumuk-card__text { margin: 0; font-size: 16px; line-height: 1.6; color: var(--chumuk-field-ink); }

/* Media. `aspect-ratio` + `object-fit` rather than a fixed height, so one rule
   holds at every width and no image can letterbox. */
.chumuk-media { border-radius: var(--chumuk-card-radius); overflow: hidden; background: var(--wp--preset--color--ice); }
.chumuk-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.chumuk-media--wide { aspect-ratio: 16 / 9; }
.chumuk-media--square { aspect-ratio: 1; }
.chumuk-media--portrait { aspect-ratio: 4 / 5; }

/* --- buttons: `.cs-add`'s geometry and colours, page-scoped --------------- */
.chumuk-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	border: 0;
	/* This theme does not set border-box globally, so a width: 100% button added
	   its 64px of horizontal padding on top of the track and spilled the card. */
	box-sizing: border-box;
	max-inline-size: 100%;
	cursor: pointer;
	font-family: var(--wp--custom--font-body);
	background: var(--chumuk-ink-dark);
	color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--pill-radius);
	padding: 18px 32px;
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: none;
	min-height: 44px;
}
.chumuk-btn:hover { background: var(--wp--preset--color--dot-wine); color: var(--wp--preset--color--white); }
.chumuk-btn--ghost {
	background: transparent;
	color: var(--wp--preset--color--ink);
	box-shadow: inset 0 0 0 2px #1C1C3C;
}
.chumuk-btn--ghost:hover { background: #1C1C3C; color: var(--wp--preset--color--white); }
.chumuk-btn--block { box-sizing: border-box; width: 100%; max-inline-size: 100%; }

.chumuk-textlink {
	font-family: var(--wp--custom--font-body);
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 4px;
	color: var(--wp--preset--color--ink);
}
.chumuk-textlink:hover { color: var(--wp--preset--color--dot-wine); }

/* --- form fields: THE ONE AUTHORED CONTROL, flagged in the block above --- */
/* min-inline-size: 0 lets the field shrink inside a grid track; without it the
   input's intrinsic width sets the track floor and neighbouring columns collide.
   box-sizing: border-box because this theme does not set it globally, so a
   width: 100% control was 35px wider than its track. */
.chumuk-field { display: grid; gap: 8px; min-inline-size: 0; }
.chumuk-field__label {
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 12px;
	font-weight: 700;
	color: var(--chumuk-field-ink);
}
.chumuk-field__label span { color: var(--wp--preset--color--dot-wine); }
.chumuk-field input,
.chumuk-field select,
.chumuk-field textarea {
	font-family: var(--wp--custom--font-body);
	font-size: 16px;
	line-height: 1.5;
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--white);
	border: 1.5px solid var(--chumuk-control-border);
	border-radius: 12px;
	padding: 13px 16px;
	width: 100%;
	min-height: 48px;
	box-sizing: border-box;
	max-inline-size: 100%;
}
.chumuk-field textarea { min-height: 132px; resize: vertical; }
/* 🔴 THE FIELD'S REMAINING STATES [§10.199 TASK C]. The design system specifies
   seven — default · hover · focus · filled · disabled · error · read-only — and only
   four rendered: default, hover, focus and filled all resolve to the same paint, which
   is correct and deliberate. The design system says focus and filled "declare nothing"
   (the global two-tone ring owns focus, and a filled field is a default field with a
   value), so the three rules below are the whole of what was missing.

   ⚠️ THE ERROR STATE DOES NOT RELY ON COLOUR (WCAG 1.4.1). Its second channel is
   BORDER WEIGHT — 1.5px to 2px, the design system's own figure — and it is paired with
   an `aria-describedby`-linked message in the markup, which is Lane A's to emit. Colour
   is the third channel, not the only one.

   ⚠️ `--chumuk-error-ink` #B3000A HAS NO PALETTE SLUG and is declared as a §I token
   rather than repeated as a literal, exactly as the five §I tokens above are, and for
   the reason §15.4 gives: registering it would put it in the editor colour picker for a
   value no author picks. 🔴 IT IS NOT THE `red` SLUG. [MEASURED] `red` #FF0007 is
   4.00:1 and FAILS the 4.5:1 a message needs; #B3000A is 7.19:1.

   ⚠️ `--chumuk-text-secondary` IS THE INK SLUG AT 75%, the same shape as
   `--chumuk-control-border`, so the disabled value is expressed through a registered
   colour rather than as a second literal.

   ⚠️ DISABLED IS EXEMPT FROM 1.4.11 — a disabled control has no contrast requirement.
   It is given the design system's sand ground and secondary ink anyway, and measured
   anyway, so the exemption is stated rather than assumed. */
.chumuk-field input:disabled,
.chumuk-field select:disabled,
.chumuk-field textarea:disabled {
	background-color: var( --wp--preset--color--sand );
	color: var( --chumuk-text-secondary );
	cursor: not-allowed;
}

.chumuk-field input[readonly],
.chumuk-field textarea[readonly] {
	background-color: var( --wp--preset--color--ice );
	color: var( --wp--preset--color--ink );
}

.chumuk-field input[aria-invalid="true"],
.chumuk-field select[aria-invalid="true"],
.chumuk-field textarea[aria-invalid="true"] {
	border-width: 2px;
	border-color: var( --chumuk-error-ink );
}

.chumuk-error-msg {
	margin: 0;
	font-size: 13px;
	line-height: 1.45;
	color: var( --chumuk-error-ink );
}

.chumuk-field input::placeholder,
.chumuk-field textarea::placeholder { color: #93A3AE; }
.chumuk-field__hint { font-size: 13px; line-height: 1.45; color: #6B6068; }


/* --- the flavour pill: ONE COMPONENT, TWO PAGES ---------------------------
   🔴 PROMOTED INTO §I BECAUSE A SECOND PAGE NEEDED IT, AND THAT IS A BUG I
   SHIPPED. These rules lived only in the product page's own block while the
   cart's empty state referenced them by name. A borrowed class that does not
   exist in the sheet does not fail loudly — it renders as an UNSTYLED ANCHOR.
   [MEASURED] on the cart's chips before the promotion: `display: block` instead
   of `inline-flex`, `background-color: rgba(0,0,0,0)`, `border-radius: 0`,
   `padding: 0`, `text-decoration: underline`, height 27.25px — five underlined
   text links, and the dot 0px wide with no background. At 27px they also broke
   the project's own 44 × 44 tap-target ruling, since `min-height: 44px` is
   carried by this very rule.
   ⚠️ THE NAME IS `chumuk-pill`, NOT `chumuk-chip`: `.chumuk-chip` ALREADY EXISTS
   in the frame (C10's comparison pill, 160 × 30 measured). This is the rule the
   step-rail rename established, applied before writing the class rather than
   after measuring the damage.
   ⚠️ Values are unchanged from the product page's originals — this is a move,
   not a restyle. */
.chumuk-pillrow { display: flex; flex-wrap: wrap; gap: 10px; }
.chumuk-pill {
	display: flex;
	align-items: center;
	gap: 9px;
	text-decoration: none;
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--pill-radius);
	padding: 9px 16px 9px 12px;
	color: var(--wp--preset--color--ink);
	font-family: var(--wp--custom--font-body);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	min-height: 44px;
}
.chumuk-pill:hover { box-shadow: 0 8px 20px rgba( 158, 27, 60, 0.1 ); color: var(--wp--preset--color--ink); }
.chumuk-pill__dot { inline-size: 16px; block-size: 16px; border-radius: var(--wp--custom--pill-radius); flex: 0 0 auto; background: var(--dot); }
.chumuk-pill--combo .chumuk-pill__dot { background: conic-gradient( from 45deg, #9e1b3c 0 25%, #b20098 0 50%, #006c94 0 75%, #9a5200 0 ); }
.chumuk-pill--on { background: var(--chumuk-ink-dark); color: var(--wp--preset--color--white); }
.chumuk-pill--on:hover { background: var(--chumuk-ink-dark); color: var(--wp--preset--color--white); }
.chumuk-pill--on .chumuk-pill__dot { background: var(--wp--preset--color--white); }

/* --- `--dot` AT SITE LEVEL ----------------------------------------------
   🔴 THE FOUR FLAVOUR COLOURS WERE INVISIBLE OUTSIDE `.chumuk-store`, AND THIS
   IS THE SAME SCOPING TRAP THE C07 README ALREADY RECORDS FOR `--cs-cyan`.
   `chumuk_store_variant_styles()` emits `.chumuk-store [data-chumuk-flavor="…"]`,
   so a `[data-chumuk-flavor]` element anywhere else resolves `--dot` to nothing.
   [MEASURED] all five PDP thumbs: `closest('.chumuk-store') === null` and
   `getPropertyValue('--dot') === ''`; three of the dots computed
   `background-color: rgba(0,0,0,0)` with `background-image: none` — a 16px hole.
   Only the active thumb (white, from `--on`) and the bundle (its gradient is a
   literal) painted.
   ⚠️ HOISTED, NOT RE-DECLARED PER PAGE. The four hexes stay in ONE place and the
   store-scoped rules above keep the same values at higher specificity, so nothing
   inside C07 changes. Copying the hexes into each page is exactly what the design
   system forbids — "a value used site-wide needs a site-wide token". */
[data-chumuk-flavor="beetroot-blast"] { --dot: var(--wp--preset--color--dot-wine); }
[data-chumuk-flavor="himalayan-revive"] { --dot: var(--wp--preset--color--dot-magenta); }
[data-chumuk-flavor="jira-twist"] { --dot: var(--wp--preset--color--dot-amber); }
[data-chumuk-flavor="natural-bliss"] { --dot: var(--wp--preset--color--dot-teal); }


/* --- SHARED BY MORE THAN ONE PAGE, SO DECLARED ONCE ----------------------
   🔴 EIGHT COMPONENTS WERE AUTHORED INSIDE ONE PAGE'S BLOCK AND REFERENCED BY
   OTHERS, WHICH IS THE SAME DEFECT THREE TIMES OVER. A class that is used in the
   markup but declared in a DIFFERENT file resolves to NO RULES AT ALL — and it
   fails silently, because an unstyled element is still an element.
   [MEASURED] the step row on the product page before this move: 0 stylesheet
   rules matched `chumuk-steprow__n` or `chumuk-steprow__text`; the numeral
   computed `display: block`, 5.31 × 27.25px, transparent, `border-radius: 0`
   where the design specifies a 26px cyan disc with white 12px/700 figures, and
   the text group lost `display: grid` so the title and the body ran together as
   "Drink it freshBest within five minutes…" at 17.5px instead of 15/14.
   🔴 THE FIX IS STRUCTURAL, NOT ANOTHER PATCH: every page's markup was audited
   against its own stylesheet, and everything used by two or more pages now lives
   here. The remaining page-local names are used by exactly one page.
   ⚠️ EVERY NAME BELOW WAS GREPPED AGAINST THE FRAME FIRST. `.chumuk-step*` is
   C08's and `.chumuk-chip` is C10's — both already cost a defect — so the
   promoted components take names the frame does not own.
   ⚠️ VALUES ARE UNCHANGED. This is a move; the About page rendered correctly
   before it and must render identically after. */
.chumuk-steprow__n { display: grid; place-items: center; inline-size: 26px; block-size: 26px; flex: 0 0 auto; border-radius: var(--wp--custom--pill-radius); background: var(--wp--preset--color--footer-cyan); color: var(--wp--preset--color--white); font-family: var(--wp--custom--font-body); font-size: 12px; font-weight: 700; }
.chumuk-steprow__text { display: grid; gap: 3px; }
.chumuk-steprow__text strong { font-size: 15px; font-weight: 700; letter-spacing: 0.02em; }
.chumuk-steprow__text span { font-size: 14px; line-height: 1.55; color: var(--chumuk-field-ink); }

.chumuk-lines { display: grid; }
.chumuk-line__body { display: grid; gap: 2px; align-content: center; }

.chumuk-backlink { display: inline-block; margin-top: 16px; }

.chumuk-panel { background: var(--wp--preset--color--white); border-radius: var(--chumuk-card-radius); padding: clamp( 22px, 2.4vw, 34px ); box-shadow: var(--chumuk-page-shadow); display: grid; gap: 8px; }
.chumuk-panel > * { margin: 0; }
.chumuk-addresscard { gap: 10px; }
.chumuk-recapbody { margin: 0; font-size: 16px; line-height: 1.7; color: var(--chumuk-field-ink); }

.chumuk-sumitems { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 10px; }
.chumuk-sumitems li { display: flex; justify-content: space-between; gap: 16px; font-size: 15px; line-height: 1.5; }
.chumuk-sumitems__name { color: var(--chumuk-field-ink); }
.chumuk-sumitems__price { font-weight: 600; white-space: nowrap; }

/* A band-width split: statement left, one action right. Cart, contact, product
   and about all close on it. */
.chumuk-splitcta { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 24px 32px; }
.chumuk-splitcta > div { display: grid; gap: 10px; max-width: 56ch; }

/* --- the flow's own furniture -------------------------------------------- */
/* THE STEP RAIL, AND IT IS `flowstep`, NOT `step`, FOR A MEASURED REASON.
   🔴 `.chumuk-step` ALREADY EXISTS IN THIS STYLESHEET — it is C08 "How It Works"'s
   step row, and §I sits in the same sheet, so the rail inherited it wholesale.
   [MEASURED] on the cart at 924 before the rename: `.chumuk-step` computed
   `min-block-size: 100px`, `height: 100px`, `grid-template-columns: 100px 1fr auto`
   and `margin-block-start: 64px` — none of it authored here (§I sets only
   `display: flex; align-items: center; gap: 10px`, which loses on every box
   property). Each `<li>` measured 164px against the ~28px the pill needs, the step
   sat 64px down inside it, and the connector — correctly centred in the `<li>` —
   painted ~36px ABOVE the pills as a row of floating dashes. C08's
   `.chumuk-step::before` veil card painted too.
   ⚠️ RENAMED RATHER THAN OUT-SPECIFIED, because `::before` is a SINGLE SLOT PER
   ELEMENT and both components need it — C08 for its veil, the rail for its
   connector. Two components cannot share the name at any specificity. This is the
   third instance of this defect class on the project (`.cs-combo-card` twice), so:
   ⚠️ EVERY NEW §I CLASS NAME MUST BE GREPPED AGAINST THE FRAME BEFORE IT IS ADDED.
   `.chumuk-eyebrow` is also already defined above (`margin-block-end:
   spacing--20`); §I happens to win only because it sets `margin: 0` and comes
   later. That is luck, not design.
   `aria-current="step"` carries the state; the classes only paint it, so the rail
   reads correctly with CSS off. */
.chumuk-flowsteps { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; list-style: none; margin: 0 0 clamp( 28px, 3vw, 44px ); padding: 0; }
.chumuk-flowstep {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 12px;
	font-weight: 700;
	color: #93A3AE;
}
.chumuk-flowstep__n {
	display: grid;
	place-items: center;
	inline-size: 28px;
	block-size: 28px;
	border-radius: var(--wp--custom--pill-radius);
	background: #FFFFFF;
	box-shadow: inset 0 0 0 1.5px var(--chumuk-field-border);
	font-size: 12px;
}
.chumuk-flowstep--done { color: var(--wp--preset--color--ink); }
.chumuk-flowstep--done .chumuk-flowstep__n { background: var(--wp--preset--color--footer-cyan); box-shadow: none; color: var(--wp--preset--color--white); }
.chumuk-flowstep--now { color: var(--wp--preset--color--ink); }
.chumuk-flowstep--now .chumuk-flowstep__n { background: var(--chumuk-ink-dark); box-shadow: none; color: var(--wp--preset--color--white); }
.chumuk-flowsteps li + li::before { content: ''; inline-size: 26px; block-size: 1.5px; background: var(--chumuk-field-border); }
.chumuk-flowsteps li { display: flex; align-items: center; gap: 14px; }

/* The two-column flow layout: content left, a sticky summary right. ⚠️ ONE
   breakpoint, and it is C07's 1180 — the site already has that threshold, so no
   second one is introduced. */
.chumuk-flow { display: grid; grid-template-columns: minmax( 0, 1fr ) 30.5%; column-gap: clamp( 24px, 3vw, 56px ); row-gap: 32px; align-items: start; }
.chumuk-flow__aside { position: sticky; top: 104px; display: grid; gap: 16px; }
@media ( max-width: 1180px ) {
	.chumuk-flow { grid-template-columns: minmax( 0, 1fr ); }
	.chumuk-flow__aside { position: static; }
}

/* The summary card. Its rows, its dashed rule and its total are the store
   band's own: pink ground rows, ~~`--cs-note-rule` #E4C8D4 dashes~~ — the token
   named here is band-scoped and does not reach this card; see the two
   `--chumuk-summary-*` tokens at :root [§10.203] — the price at
   26px/600 as `.cs-offer__price` sets it. */
.chumuk-summary { background: var(--wp--preset--color--white); border-radius: 18px; padding: 26px 26px 22px; box-shadow: var(--chumuk-summary-shadow); }
.chumuk-summary__title { margin: 0 0 18px; font-family: var(--wp--custom--font-body); text-transform: uppercase; letter-spacing: 0.1em; font-size: 13px; font-weight: 700; color: var(--wp--preset--color--dot-wine); }
.chumuk-sumrow { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; font-size: 15px; line-height: 1.5; padding-block: 7px; }
.chumuk-sumrow span:last-child { font-weight: 600; white-space: nowrap; }
.chumuk-sumrow--muted { color: #6B6068; }
.chumuk-summary__rule { border: 0; border-top: 1px dashed var(--chumuk-summary-rule); margin: 14px 0; }
.chumuk-sumtotal { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.chumuk-sumtotal__label { font-family: var(--wp--custom--font-body); text-transform: uppercase; letter-spacing: 0.08em; font-size: 13px; font-weight: 700; }
.chumuk-sumtotal__value { font-size: 26px; font-weight: 600; white-space: nowrap; }

/* Line items — the same row anatomy as the store's combo rows, at cart scale. */
.chumuk-line { display: grid; grid-template-columns: 88px minmax( 0, 1fr ) auto; gap: 18px; align-items: center; padding-block: 22px; border-bottom: 1px solid var(--chumuk-rule); }
.chumuk-line:last-of-type { border-bottom: 0; }
.chumuk-line__thumb { inline-size: 88px; block-size: 88px; border-radius: 14px; background: #FDEAF1; display: grid; place-items: center; overflow: hidden; }
.chumuk-line__thumb img { max-inline-size: 74px; max-block-size: 80px; width: auto; height: auto; display: block; }
.chumuk-line__name { display: block; font-size: 16px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
/* ⚠️ THE CART LINE NAME IS A LINK, and these two rules are the design's own, missed
   in TASK A [TASK E]. The design declares `.chumuk-line__name` TWICE — once for the
   type above, once for the link treatment here — and only the first was transcribed.
   Without them the product name inherits the global anchor colour and underline,
   which is the one place the cart's type would have disagreed with every other
   inner page. */
.chumuk-line__name { text-decoration: none; color: var(--wp--preset--color--ink); }
.chumuk-line__name:hover { color: var(--wp--preset--color--dot-wine); text-decoration: underline; text-underline-offset: 4px; }
.chumuk-line__meta { display: block; font-size: 14px; color: #6B6068; margin-top: 4px; }
.chumuk-line__right { display: grid; justify-items: end; gap: 12px; }
.chumuk-line__price { font-size: 20px; font-weight: 600; white-space: nowrap; }

/* The store band's stepper, re-declared on a white ground (the band's own sits
   on pink and therefore paints itself white). */
/* 🔴 WOOCOMMERCE'S OWN QUANTITY WRAPPER IS THE SECOND SELECTOR ON EVERY RULE, NOT
   A SECOND STEPPER [§10.212]. The product page needs the design's `− 1 +` control,
   and WooCommerce already renders `div.quantity > input.qty` there — the input that
   actually posts. Restating these declarations under a new class would be a second
   stepper to keep in step with this one; adding `.chumuk-pdp__cart .quantity` to the
   selector lists dresses Woo's markup in the component that already exists, which is
   the standing rule (style Woo's blocks, do not replace them). The `−` and `+`
   buttons arrive through Woo's own `woocommerce_before/after_quantity_input_field`
   actions, so no template is overridden.
   ⚠️ THE INPUT TAKES `output`'s TYPOGRAPHY because it stands where the design's
   `<output>` stands. It keeps `type="number"`: the spinners are hidden, not the
   control — a keyboard user can still type a quantity, and it remains the field Woo
   validates and posts. */
.chumuk-qty,
.chumuk-pdp__cart .quantity { display: inline-flex; align-items: center; gap: 16px; border: 1.5px solid var(--chumuk-control-border); border-radius: var(--wp--custom--pill-radius); padding: 8px 16px; }
.chumuk-qty button,
.chumuk-pdp__cart .quantity button { position: relative; border: 0; background: none; font: inherit; font-size: 20px; line-height: 1; color: var( --chumuk-muted-ink ); cursor: pointer; padding: 0; }
.chumuk-qty output,
.chumuk-pdp__cart .quantity input.qty { font-size: 15px; font-weight: 600; min-width: 16px; text-align: center; }
.chumuk-qty button::after,
.chumuk-pdp__cart .quantity button::after { content: ''; position: absolute; left: 50%; top: 50%; translate: -50% -50%; min-inline-size: 44px; min-block-size: 44px; }
.chumuk-pdp__cart .quantity input.qty { appearance: textfield; border: 0; background: none; padding: 0; font-family: inherit; color: inherit; inline-size: 2.5ch; }
.chumuk-pdp__cart .quantity input.qty::-webkit-outer-spin-button,
.chumuk-pdp__cart .quantity input.qty::-webkit-inner-spin-button { appearance: none; margin: 0; }

/* A notice. Three tones, and each one's ground is a palette token at 10% rather
   than a new hex: cyan for information, crimson for failure, forest for success. */
.chumuk-notice { display: grid; gap: 6px; border-radius: 14px; padding: 18px 20px; font-size: 15px; line-height: 1.55; }
.chumuk-notice strong { font-weight: 700; letter-spacing: 0.02em; }
.chumuk-notice--info { background: #E5FBFB; color: #0B4F5F; }
.chumuk-notice--fail { background: #FDEAF1; color: #7A1330; }
.chumuk-notice--good { background: #DCFFE9; color: #14400A; }

/* Radio / checkbox rows — used for the payment choice, the account choice and
   the consent boxes. The filled ring is `.cs-offer__radio`'s inset-shadow
   construction, so the selected control matches the store band exactly. */
.chumuk-choice { display: flex; align-items: flex-start; gap: 16px; background: var(--wp--preset--color--white); border: 2px solid var(--chumuk-rule); border-radius: 14px; padding: 18px 20px; cursor: pointer; }
.chumuk-choice--on { border-color: #1C1C3C; }
.chumuk-choice__ring { inline-size: 20px; block-size: 20px; border-radius: var(--wp--custom--pill-radius); flex: 0 0 auto; border: 2px solid var(--chumuk-control-border); background: #FFFFFF; margin-top: 2px; }
.chumuk-choice--on .chumuk-choice__ring { border-color: #1C1C3C; box-shadow: inset 0 0 0 3px #FFFFFF, inset 0 0 0 9px #1C1C3C; }
.chumuk-choice__body { display: grid; gap: 4px; }
.chumuk-choice__name { font-size: 15px; font-weight: 700; letter-spacing: 0.04em; }
.chumuk-choice__note { font-size: 14px; color: #6B6068; line-height: 1.5; }

/* An icon disc, for the contact cards and the confirmation head. */
.chumuk-disc { display: grid; place-items: center; inline-size: 48px; block-size: 48px; border-radius: var(--wp--custom--pill-radius); background: var(--wp--preset--color--ice); color: #0B4F5F; }
.chumuk-disc svg { inline-size: 22px; block-size: 22px; }

/* image-slot: the component fills its container, so every slot on these pages
   sits in a sized wrapper rather than carrying its own dimensions. */
image-slot { display: block; }

/* --- CHECKOUT -----------------------------------------------------------
   🔴 ONE PAGE, TWO COLUMNS, AND THE PAYMENT STEP IS A STATE OF IT — not a
   second template. `checkoutStep` moves the page between `details`, `payment`
   and `failed`; the summary column, the step rail and the totals are the same
   markup in all three, so they cannot drift.
   ⚠️ CASH ON DELIVERY IS THE ONLY METHOD, and it is still drawn as a CHOICE row
   rather than a statement. A single-option radio looks redundant today and is
   the correct pattern the moment bKash or a card is switched on; the note under
   it says so, so nobody has to guess whether the design forgot the others.
   ⚠️ THE REAL RADIO IS PRESENT AND VISUALLY HIDDEN, with the painted ring beside
   it. A `<span>` alone would not post, would not be reachable by keyboard and
   would not announce as a radio — the store band's own offer row has that
   problem and this does not repeat it. */
.chumuk-checkout__fail { margin-bottom: clamp( 20px, 2vw, 32px ); max-width: 96ch; }
.chumuk-checkout__main { display: grid; gap: clamp( 20px, 2vw, 32px ); }
.chumuk-checkout__form { display: grid; gap: clamp( 20px, 2vw, 32px ); }
.chumuk-checkout__form > * { margin: 0; }
.chumuk-checkout__block { border: 0; margin: 0; padding: clamp( 22px, 2.4vw, 34px ); background: var(--wp--preset--color--white); border-radius: var(--chumuk-card-radius); box-shadow: var(--chumuk-page-shadow); display: grid; gap: 20px; }
.chumuk-checkout__block > * { margin: 0; }
.chumuk-checkout__legend {
	padding: 0;
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 13px;
	font-weight: 700;
	color: var(--wp--preset--color--dot-wine);
	margin-bottom: 4px;
}
.chumuk-checkout__row { display: grid; grid-template-columns: repeat( auto-fit, minmax( 220px, 1fr ) ); gap: 20px; }
.chumuk-checkout__choices { display: grid; gap: 14px; }
/* Visually hidden, NOT `display: none` — a hidden input does not post and takes
   no focus. Core's own `.screen-reader-text` construction. */
.chumuk-checkout__srradio { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset( 50% ); border: 0; }
.chumuk-checkout__srradio:focus-visible + .chumuk-choice__ring { outline: var(--wp--custom--focus-ring-width) solid var(--wp--custom--focus-ring); outline-offset: var(--wp--custom--focus-ring-offset); }
.chumuk-checkout__pw { max-width: 380px; }
.chumuk-checkout__only { font-size: 14px; line-height: 1.55; color: #6B6068; max-width: 74ch; }
/* The whole label is the target, held at 44px tall — the 22px box is never the
   target on its own. */
.chumuk-checkout__consent { display: grid; grid-template-columns: 22px minmax( 0, 1fr ); gap: 14px; align-items: start; min-block-size: 44px; padding-block: 4px; font-size: 15px; line-height: 1.55; cursor: pointer; }
.chumuk-checkout__consent input { inline-size: 22px; block-size: 22px; margin: 0; accent-color: #1C1C3C; }

.chumuk-checkout__recap { background: var(--wp--preset--color--white); border-radius: var(--chumuk-card-radius); padding: clamp( 22px, 2.4vw, 34px ); box-shadow: var(--chumuk-page-shadow); display: grid; gap: 12px; }
.chumuk-checkout__recaphead { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 12px 20px; }

.chumuk-checkout__cta { margin-top: 20px; }

/* --- THE MINI-CART DRAWER (C02) -----------------------------------------
   🔴 WOOCOMMERCE'S OWN BLOCK, UNDER ITS OWN CLASS NAMES. Every selector below is
   a real class from the Mini-Cart block — `__screen-overlay`, `--is-hidden`,
   `__drawer`, `__content`, `__close`, `__title`, `__items`, `__footer`,
   `wc-block-cart-item__*`, `wc-block-components-quantity-selector` — so the
   build STYLES the block rather than replacing it with a bespoke panel.
   ⚠️ VISIBILITY, NOT DISPLAY, is the hiding mechanism, keyed to the same
   `aria-hidden` Woo toggles: `display: none` would remove the slide-out that the
   block animates, and `visibility` is the only mechanism that also takes the
   contents out of the tab order.
   ⚠️ The overlay is a SIBLING OF THE HEADER here; on the served page Woo attaches
   it to `body` via `data-wp-router-region`. Same stacking result, and nothing in
   the design depends on the parent. */
.wc-block-components-drawer__screen-overlay {
	position: fixed;
	inset: 0;
	z-index: 9999;
	background: rgb( 28 28 60 / 0.42 );
	display: flex;
	justify-content: flex-end;
}
/* 🔴 NO TRANSITION ON THE OPEN/CLOSED STATE, and this is a correctness decision.
   [MEASURED] with `transition: opacity .24s` / `translate .24s`, opening the drawer
   left it PARKED at the hidden end — computed `opacity: 0`, `translate: 100%`,
   `drawerX 924` in a 924px viewport — while the class, `aria-hidden="false"`,
   `aria-modal="true"` and the scroll lock all said open. A transition only advances
   while the compositor is producing frames, so anywhere that is throttled (an
   inactive tab, an offscreen preview, a capture harness) the drawer is a modal you
   cannot see over a page that cannot scroll. That failure mode is worse than no
   animation, and it survived a state-machine test because the STATE was right.
   Both ends are still declared as real values (`translate: 0 0`, never `none`) so
   there is nothing to interpolate to. WooCommerce's block brings its own slide-out
   on the served page; the build should let it, and not reintroduce this. */
.wc-block-components-drawer__screen-overlay:not(.wc-block-components-drawer__screen-overlay--is-hidden) { opacity: 1; }
.wc-block-components-drawer__screen-overlay:not(.wc-block-components-drawer__screen-overlay--is-hidden) .wc-block-mini-cart__drawer { translate: 0 0; }
.wc-block-components-drawer__screen-overlay--is-hidden { opacity: 0; pointer-events: none; }
.wc-block-mini-cart__drawer {
	inline-size: min( 480px, 100vw );
	max-inline-size: 100%;
	background: var(--wp--preset--color--white);
	box-shadow: -18px 0 48px rgb( 28 28 60 / 0.18 );
	display: flex;
	flex-direction: column;
}
.wc-block-mini-cart__drawer[aria-hidden="true"] { visibility: hidden; }
.wc-block-components-drawer__screen-overlay--is-hidden .wc-block-mini-cart__drawer { translate: 100% 0; }
.wc-block-components-drawer__content,
.wc-block-mini-cart__template-part,
.wp-block-woocommerce-mini-cart-contents { display: flex; flex-direction: column; min-block-size: 0; block-size: 100%; }

.wc-block-components-drawer__close-wrapper { display: flex; justify-content: flex-end; padding: 18px 18px 0; }
.wc-block-components-drawer__close {
	display: grid;
	place-items: center;
	inline-size: 44px;
	block-size: 44px;
	border: 0;
	border-radius: var(--wp--custom--pill-radius);
	background: transparent;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
}
.wc-block-components-drawer__close:hover { background: var(--wp--preset--color--ice); }
.wc-block-components-drawer__close svg { inline-size: 24px; block-size: 24px; fill: currentColor; }

/* 🔴 `h2.` IS TARGETING, NOT OUT-SPECIFYING, AND WITHOUT IT THIS RULE WAS
   TWO-THIRDS WORKING. [MEASURED] as `.wc-block-mini-cart__title` (0,1,0) it won
   `padding-inline`, `gap`, `flex-wrap`, `font-family` and `line-height` and
   SILENTLY LOST `margin`, `padding-block-end` and `font-size` to Woo's own
   `h2.wc-block-mini-cart__title` (0,1,1) in `mini-cart.css`, which ships
   `margin: 16px 16px -32px; padding-bottom: 32px; font-size: 2em` — so the
   title computed 32px with a NEGATIVE bottom margin instead of 28px with an
   18px gutter. ⚠️ "The title is in Playfair, so the rule works" would have been
   the wrong check: the font-family was one of the declarations that WON.
   Matching Woo's own selector is the §8 remedy; a third class or an
   `!important` would both have been the forbidden one. Woo's `mask-image` and
   `z-index` are left to Woo. */
h2.wc-block-mini-cart__title { margin: 0; padding: 0 clamp( 20px, 2.2vw, 32px ) 18px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; font-family: var(--wp--custom--font-heading); font-size: 28px; line-height: 1.2; }
.wc-block-mini-cart__title-items-counter { font-family: var(--wp--custom--font-body); font-size: 14px; font-weight: 700; letter-spacing: 0.04em; color: var(--chumuk-field-ink); }

/* `min-block-size: 0` is load-bearing in a flex column: without it the list
   refuses to shrink and the footer is pushed off the bottom of the drawer. */
/* ⚠️ `overflow-x: hidden` is not defensive: setting one axis to `auto` makes the
   other compute to `auto` too, which draws a horizontal scrollbar the list does
   not need. */
.wc-block-mini-cart__items { flex: 1 1 auto; overflow-y: auto; overflow-x: hidden; min-block-size: 0; padding: 0 clamp( 20px, 2.2vw, 32px ); }
/* 🔴 THE `<ul><li>` RULES THAT STOOD HERE ARE RETIRED, AND THE MEASUREMENT THAT
   RETIRED THEM IS THE ONE THREE RUNS DEFERRED. Signed in, cart populated, in a
   real browser at 1040:
     ul.wc-block-cart-items                                  0
     table.wc-block-cart-items                               1
     tr.wc-block-cart-items__row                             1
     `.wc-block-mini-cart__items .wc-block-cart-items li`    0 MATCHES
   Woo's drawer renders a TABLE. The three `li` rules — the row grid, its
   `:last-child` and the 560px override — never matched anything on either
   surface, so deleting them changes no computed value. Verified by re-measuring
   after: the row is unchanged.
   ⚠️ NO REPLACEMENT ROW RULE IS WRITTEN, AND THAT IS DELIBERATE. Woo's own
   `.wc-block-cart-items__row` already computes `display: grid` with
   `80px 132px 62px 112px`, and THE DRAWER HAS NO DESIGN FILE (§10.2 — "the cart
   drawer is undesigned"). There is no Δ to measure a bespoke row against, so
   re-laying it out would be inventing a design in the owner's absence. The
   pieces that DO have a design — the thumb, which the cart page draws — are
   transcribed below and nothing else is. */
/* 🔴 THE DRAWER'S LINE CONTROLS GET THE SAME 44px OVERLAY AS THE CART PAGE'S.
   [MEASURED] with a populated drawer: the quantity buttons computed 34px, the
   remove link 16px and the product name 22px, while the identical controls on the
   cart page carry `::after` overlays. The drawer ships on every page, so the rule
   lives with the drawer. Vertical only — the quantity buttons flank an input. */
.wc-block-cart-item__remove-link,
.wc-block-components-product-name,
.wc-block-components-quantity-selector__button { position: relative; }
.wc-block-cart-item__remove-link::after,
.wc-block-components-product-name::after,
.wc-block-components-quantity-selector__button::after {
	content: '';
	position: absolute;
	inset-inline: 0;
	top: 50%;
	translate: 0 -50%;
	min-block-size: 44px;
}
/* 🔴 EVERY `.wc-block-cart-item*` RULE IN THIS SECTION IS NOW SCOPED TO
   `.wc-block-mini-cart__items`, AND THE SCOPE IS A BUG FIX, NOT TIDYING. The
   rules were written unscoped in the belief — stated in the note below — that
   the drawer and the cart page are the same component and may share one set of
   declarations. They are not. [MEASURED] `display: grid` from the thumb rule
   below reached the cart PAGE, where the item is a `<td>`; `display: grid` on
   a table cell takes it out of table layout altogether, and the row computed
   397px tall with the product cell stacked underneath the image instead of
   beside it. Nothing was wrong with these declarations — they were right, in
   the wrong room. §R styles the cart page's cells separately.

   ⚠️ ~~"a following pass can retire them once the drawer has been measured with
   items in it, which needs a signed-in session this run did not have"~~ — THAT
   PASS HAS NOW HAPPENED and the `li` rules are gone; see the retirement note
   above the thumb. The scoping this paragraph describes is still load-bearing
   for every rule that remains. */
/* 🔴 THE CART PAGE'S OWN THUMB, TRANSCRIBED — `.chumuk-line__thumb`'s 88 square,
   14px radius, #FDEAF1 ground and `max-inline-size: 74px / max-block-size: 80px`
   image bound. The drawer and the cart page show the same product the same way,
   so they cannot look like two different components.
   [MEASURED] why `max-*` + `auto` and not `inline-size: 100%`: the jar renders
   600 × 1235, and a sized image computed 72 × 148 and broke out of the thumb —
   `block-size: 100%` loses to the theme's own `img { height: auto }`. */
/* 🔴 THE THUMB HAS NO GROUND, AND THAT IS A DECISION RATHER THAN AN OMISSION.
   [MEASURED] the cell computed `background-color: rgba(0,0,0,0)` while
   `inline-size`, `block-size`, `border-radius`, `display` and `place-items` from
   this same rule ALL applied — a rule winning five declarations and losing one,
   the second instance in this run alone. The cause is Woo's
   `table.wc-block-cart-items td { background: none !important }` in `cart.css`:
   author `!important` beats any author normal declaration at any specificity, so
   no longer selector and no extra class can recover it, and the standing
   constraints forbid answering `!important` with `!important`.
   🔴 TWO ROUTES AROUND IT WERE BUILT AND MEASURED BEFORE BEING WITHDRAWN:
     `::before` carrying the ground  — works, but NO INSTRUMENT AVAILABLE HERE CAN
                                       SAMPLE A PSEUDO-ELEMENT'S COMPUTED STYLE, so
                                       the fix could not be verified. An
                                       unverifiable fix is not a fix on this project.
     `box-shadow: inset 0 0 0 88px`  — measurable, and it did read back correctly as
                                       `rgb(253,234,241) 0px 0px 0px 88px inset`.
                                       Still wrong: an inset shadow paints to the
                                       PADDING box, the cell computes
                                       `box-sizing: content-box` with Woo's
                                       `padding-right: 16px`, so the pink filled
                                       104 x 88 and the 14px radius was struck on the
                                       wrong rectangle — §6's content-box trap
                                       arriving through a property that is not
                                       `width`. `padding: 0` to correct it LOST too,
                                       and Woo's grid track for this column is 80px
                                       against an 88px cell.
   ⚠️ Forcing the ground needs three more Woo rules beaten on a surface that HAS NO
   DESIGN FILE (§10.2 — "the cart drawer is undesigned"). With no Δ to verify
   against, the result would be a look invented while the owner is asleep, and a
   ground overfilling its own square by 16px is worse than no ground at all. Woo's
   `!important` is left to stand. The 88px box, the 14px radius and the image bound
   are kept — those are `.chumuk-line__thumb`'s geometry and they verifiably apply.
   ⚠️ `#FDEAF1` is therefore no longer referenced here. It remains a bare hex at
   `.chumuk-line__thumb` (§R) and in two other places; `theme.json` has no slug for
   it and the nearest, `pink-soft #FFE8F3`, is a DIFFERENT colour. Registering the
   real value is a palette change, not a drawer change. Recorded, not made. */
.wc-block-mini-cart__items .wc-block-cart-item__image { inline-size: 88px; block-size: 88px; border-radius: 14px; display: grid; place-items: center; overflow: hidden; }
.wc-block-mini-cart__items .wc-block-cart-item__image img { max-inline-size: 74px; max-block-size: 80px; width: auto; height: auto; display: block; }
.wc-block-mini-cart__items .wc-block-cart-item__product { display: grid; gap: 6px; min-inline-size: 0; }
.wc-block-components-product-name { font-size: 16px; font-weight: 700; line-height: 1.35; color: var(--wp--preset--color--ink); text-decoration: none; }
.wc-block-components-product-name:hover { color: var(--wp--preset--color--dot-wine); }
.wc-block-components-product-metadata { font-size: 13px; line-height: 1.45; color: #6B6068; }
.wc-block-mini-cart__items .wc-block-cart-item__quantity { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin-top: 2px; }
.wc-block-components-quantity-selector { display: inline-flex; align-items: center; gap: 2px; border: 1.5px solid var(--chumuk-control-border); border-radius: var(--wp--custom--pill-radius); }
.wc-block-components-quantity-selector__button { inline-size: 34px; block-size: 34px; display: grid; place-items: center; border: 0; background: transparent; color: var(--wp--preset--color--ink); font-size: 17px; font-weight: 700; line-height: 1; cursor: pointer; border-radius: var(--wp--custom--pill-radius); }
.wc-block-components-quantity-selector__button:hover { background: var(--wp--preset--color--ice); }
.wc-block-components-quantity-selector__input { inline-size: 34px; text-align: center; border: 0; background: transparent; font-family: var(--wp--custom--font-body); font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; padding: 0; box-sizing: border-box; }
.wc-block-cart-item__remove-link { border: 0; background: none; padding: 0; font-family: var(--wp--custom--font-body); font-size: 13px; color: #6B6068; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.wc-block-cart-item__remove-link:hover { color: var(--wp--preset--color--dot-wine); }
.wc-block-mini-cart__items .wc-block-cart-item__total { justify-self: end; font-size: 15px; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }

.wc-block-mini-cart__footer { border-block-start: 1px solid var(--chumuk-rule); padding: 20px clamp( 20px, 2.2vw, 32px ) clamp( 20px, 2.2vw, 32px ); display: grid; gap: 14px; background: var(--wp--preset--color--white); }
.wc-block-mini-cart__footer-subtotal { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
/* 🔴 `.label` / `.value` WERE INVENTED CLASS NAMES AND BOTH MATCHED ZERO NODES.
   [MEASURED] signed in with a populated cart: `.wc-block-mini-cart__footer-subtotal
   .value` → 0. The subtotal is a Woo TOTALS ITEM — Woo's own stylesheet names it
   `.wc-block-components-totals-item.wc-block-mini-cart__footer-subtotal` — and its
   two children are `__label` and `__value` under the `wc-block-components-totals-item`
   prefix, not bare `.label` / `.value`. Same class of error as the `<ul><li>` rules
   and found by the same measurement. Repointed at the real nodes. */
.wc-block-mini-cart__footer-subtotal .wc-block-components-totals-item__label { font-family: var(--wp--custom--font-body); text-transform: uppercase; letter-spacing: 0.08em; font-size: 13px; font-weight: 700; }
.wc-block-mini-cart__footer-subtotal .wc-block-components-totals-item__value { font-family: var(--wp--custom--font-heading); font-size: 26px; line-height: 1; font-variant-numeric: lining-nums tabular-nums; }
.wc-block-mini-cart__footer-note { margin: 0; font-size: 13px; line-height: 1.5; color: #6B6068; }
.wc-block-mini-cart__footer-actions { display: grid; gap: 10px; }

/* The empty state is the SAME drawer, not a second panel. */
.wc-block-mini-cart__empty-cart { display: grid; justify-items: center; text-align: center; gap: 14px; padding: clamp( 24px, 5vw, 56px ) clamp( 20px, 2.2vw, 32px ); }
.wc-block-mini-cart__empty-cart .mark { display: grid; place-items: center; inline-size: 78px; block-size: 78px; border-radius: var(--wp--custom--pill-radius); background: var(--wp--preset--color--ice); color: #0B4A63; }
.wc-block-mini-cart__empty-cart .mark svg { inline-size: 34px; block-size: 34px; fill: currentColor; }

@media ( max-width: 560px ) {
	.wc-block-mini-cart__items .wc-block-cart-item__image { inline-size: 72px; block-size: 72px; }
	.wc-block-mini-cart__items .wc-block-cart-item__image img { max-inline-size: 60px; max-block-size: 66px; }
	.wc-block-mini-cart__items .wc-block-cart-item__total { grid-column: 2; justify-self: start; }
}

/* THE DRAWER'S OWN BUTTONS, under Woo's names. 🔴 They may NOT borrow `.chumuk-btn`:
   that class belongs to the inner-page vocabulary (§I) and does not exist on the
   home, shop, about or contact pages, so a drawer button using it renders as
   unstyled underlined text on four of the eleven files. The drawer ships on every
   page, so its furniture has to be defined where the drawer is. Geometry is
   `.chumuk-btn`'s, transcribed. */
/* 🔴 THIS RULE WAS ALREADY WINNING AND I ALMOST "FIXED" IT. [MEASURED] the filled
   button computes `background-color: rgb(35, 35, 35)`, which I first read as a
   loss because the declaration's FALLBACK is `#1C1C3C`. It is not a loss:
   `--chumuk-ink-dark` is declared `#232323` at line 8314, the fallback is dead
   code, and `rgb(35,35,35)` IS `#232323` — this rule applying exactly as written.
   A `:not(.is-link)` was added here to "win" the tie and then reverted, because
   there was no tie. ⚠️ Reading a computed value against a fallback instead of
   against the token that is actually declared is the same class of error as
   trusting a token declared on another band — the value was right and the
   expectation was wrong. */
.wc-block-mini-cart__footer-actions .wc-block-components-button,
.wc-block-mini-cart__empty-cart .wc-block-components-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	box-sizing: border-box;
	max-inline-size: 100%;
	border: 0;
	cursor: pointer;
	text-decoration: none;
	font-family: var(--wp--custom--font-body);
	background: var(--chumuk-ink-dark, #1C1C3C);
	color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--pill-radius);
	padding: 18px 32px;
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	line-height: 1;
	min-block-size: 48px;
	transition: background 0.18s ease, color 0.18s ease;
}
.wc-block-mini-cart__footer-actions .wc-block-components-button { inline-size: 100%; }
.wc-block-mini-cart__footer-actions .wc-block-components-button:hover,
.wc-block-mini-cart__empty-cart .wc-block-components-button:hover { background: var(--wp--preset--color--dot-wine); color: var(--wp--preset--color--white); }
/* ⚠️ `.is-style-outline` IS THE CLASS THIS BLOCK ACTUALLY EMITS. [MEASURED] the
   "View my cart" control carries
   `wc-block-components-button wp-element-button wc-block-mini-cart__footer-cart
   is-style-outline wp-block-woocommerce-mini-cart-cart-button-block` — no
   `outlined` anywhere on it. `.outlined` is a real Woo variant class (it is named
   beside `.contained` further down) but it is NOT what the mini-cart's own footer
   blocks render, so this rule styled nothing and Woo's default 1px ring was what
   showed. Both are kept: `.outlined` because it is Woo's vocabulary and costs one
   selector, `.is-style-outline` because it is the one on the page. */
.wc-block-mini-cart__footer-actions .wc-block-components-button.outlined,
.wc-block-mini-cart__footer-actions .wc-block-components-button.is-style-outline {
	background: transparent;
	color: var(--chumuk-ink-dark, #1C1C3C);
	box-shadow: inset 0 0 0 2px var(--chumuk-ink-dark, #1C1C3C);
}
.wc-block-mini-cart__footer-actions .wc-block-components-button.outlined:hover,
.wc-block-mini-cart__footer-actions .wc-block-components-button.is-style-outline:hover { background: var(--chumuk-ink-dark, #1C1C3C); color: var(--wp--preset--color--white); box-shadow: none; }

/* Woo's own block wrappers. The FILLED one is not decoration: it is the flex
   column between the drawer and the list, and without `min-block-size: 0` on it
   the scroller cannot shrink and the footer is pushed off the bottom. */
.wp-block-woocommerce-filled-mini-cart-contents-block { display: flex; flex-direction: column; min-block-size: 0; block-size: 100%; }
.wp-block-woocommerce-empty-mini-cart-contents-block { display: flex; flex-direction: column; }
/* `contained` / `outlined` are Woo's own button variants; `contained` takes the
   default fill above, so it needs no declarations of its own beyond existing. */
.wc-block-mini-cart__footer-actions .wc-block-components-button.contained,
.wc-block-mini-cart__empty-cart .wc-block-components-button.contained { background: var(--chumuk-ink-dark, #1C1C3C); color: var(--wp--preset--color--white); }
/* The empty state's own type, NOT `.chumuk-h3`/`.chumuk-prose`: those belong to
   the inner-page vocabulary and do not exist on the home, shop or header files. */
.wc-block-mini-cart__empty-cart .title { margin: 0; font-family: var(--wp--custom--font-heading); font-size: 24px; line-height: 1.25; color: var(--wp--preset--color--ink); }
.wc-block-mini-cart__empty-cart .body { margin: 0; font-size: 16px; line-height: 1.6; color: #6B6068; max-width: 40ch; }


/* ==========================================================================
   §I-B  THE INNER-PAGE FRAME — root, page-title band, breadcrumb  [TASK B]
   ==========================================================================
   Transcribed from the nine design files, which agree character for character.

   ⚠️ THREE ADAPTATIONS, ALL FORCED BY WHERE WORDPRESS PUTS THINGS:

   1. THE ROOT CLASSES GO ON `<body>`, NOT ON `.wp-site-blocks`. The design writes
      them on its own root div; WordPress emits `.wp-site-blocks` from
      `get_the_block_template_html()` and offers no filter for its class list.
      `body_class` is the idiomatic seam and every descendant selector in §I and
      here behaves identically from either element. The one rule that cared about
      being the direct parent — `.chumuk-page > *` — is re-anchored to
      `body.chumuk-page .wp-site-blocks > *`, which is the same set of elements.

   2. THE DOODLE ARTWORK IS THE BLOCK'S BACKGROUND SUPPORT, NOT A CSS `url()`. The
      design's `url('assets/footer/footer-doodles-ref.webp')` is relative to the
      design FILE. The theme has no `assets/footer/`, and the image is already
      attachment 146 — the exact layer C16 paints. A second copy in the theme is
      what §4.4 forbids, so `parts/page-banner.html` points at the attachment the
      way the footer does, and the three background properties move with it.

   3. 🔴 `.chumuk-home` IS NOT REMOVED FROM ANYTHING, BECAUSE IT HAS NEVER EXISTED.
      The brief says it must not be on the inner root. [MEASURED] `grep -c` across
      theme and plugin: the class is not applied anywhere, and nothing keys off it.
      The front page's one-cell grid is `body.home` — core's own class — at
      style.css §3, and STICKY IS ALREADY INDEPENDENT of both: it is keyed on
      `.wp-site-blocks > header.wp-block-template-part:has(> .chumuk-header)`. So
      the inner pages get the behaviour the brief asks for by adding a class, with
      nothing to take away.

   ⚠️ THE BREADCRUMB'S 44px OVERLAY IS DECLARED HERE, not with the other tap
   targets, because it belongs to the band. It is `inset-inline: 0` with only
   `min-block-size` — VERTICAL ONLY. A 44px-wide overlay in this flex row would
   swallow the neighbouring crumb, which is the whole reason the ruling is
   one-axis.
   ========================================================================== */
body.chumuk-page .wp-site-blocks > * { margin-block-start: 0; }
.chumuk-page .entry-content > * { margin-block-start: 0; }
.chumuk-pagetitle {
	padding-block: 72px 76px;
	background-color: var(--wp--preset--color--footer-cyan);
	color: var(--wp--preset--color--white);
	text-align: center;
}
.chumuk-pagetitle__inner {
	max-width: var(--wp--style--global--content-size);
	margin-inline: auto;
	display: grid;
	justify-items: center;
	gap: 18px;
}
.chumuk-pagetitle__title {
	margin: 0;
	color: var(--wp--preset--color--white);
	font-family: var(--wp--custom--font-heading);
	font-weight: 500;
	font-size: clamp(38px, 2.375rem + ((1vw - 3.2px) * 1.667), 60px);
	line-height: 1.06;
	text-wrap: balance;
}
.chumuk-pagetitle__crumbs { font-size: 13px; }
.chumuk-pagetitle__crumbs ol {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: 10px;
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	line-height: 1.4;
}
.chumuk-pagetitle__crumbs li + li::before {
	content: '/';
	margin-inline-end: 10px;
	opacity: 0.6;
}
.chumuk-pagetitle__crumbs [aria-current="page"] { font-weight: 700; }
.chumuk-pagetitle a { color: var(--wp--preset--color--white); text-decoration: none; }
.chumuk-pagetitle a:hover { text-decoration: underline; text-underline-offset: 4px; }
/* 🔴 44 × 44 TAP TARGETS FOR THE INNER PAGES' TEXT LINKS — the cross-band ruling,
   applied the way the band files apply it: an `::after` overlay, so no box grows
   and no layout moves. [MEASURED] before this rule the breadcrumb link computed
   16px tall, `.chumuk-textlink` 20px and the cart's product-name link 25px, against
   the 44 the stepper and the "see full product details" link already carry.
   ⚠️ VERTICAL ONLY (`inset-inline: 0`): these links sit in flex rows next to other
   links, and a 44px-WIDE overlay would swallow the neighbour's left edge.
   ⚠️ THE GROUP IS THE DESIGN'S, RESTORED WHOLE [TASK E]. TASK B transcribed only
   the `__crumbs a` third of this three-selector rule, because that was the only
   third the page-title band needed. Splitting a grouped selector leaves the other
   two members looking deliberate-by-omission — they were not. */
/* 🔴 THE DEMOTED PAGE HEADING KEEPS ITS RENDERING [§10.199 TASK A]. WooCommerce's
   templates draw the page's name a second time under the page-title band, so that
   copy becomes an `<h2>` and the band keeps the document's one `<h1>`. The LEVEL is
   what changes; the appearance must not.
   ⚠️ `2em` IS NOT A CHOSEN VALUE — it is what the browser's own stylesheet gave the
   `<h1>`, and this restores it. [MEASURED] nothing in this theme sized that heading:
   `theme.json` styles `elements.heading` with no per-level typography and `style.css`
   has no bare `h1` rule, so demoting alone dropped it 35.7184px → 26.7888px, exactly
   the UA stylesheet's 2em-to-1.5em step. The line-height is a ratio and follows.
   ⚠️ KEYED ON THE ATTRIBUTE THE FILTER ADDS, not on `.wp-block-post-title`, which the
   BAND'S OWN TITLE also carries — that selector would have restyled the very heading
   this pass is protecting, at equal specificity and later in the file. */
[data-chumuk-demoted] {
	font-size: 2em;
}

.chumuk-textlink,
.chumuk-line__name,
.chumuk-pagetitle__crumbs a { position: relative; }
.chumuk-textlink::after,
.chumuk-line__name::after,
.chumuk-pagetitle__crumbs a::after {
	content: '';
	position: absolute;
	inset-inline: 0;
	top: 50%;
	translate: 0 -50%;
	min-block-size: 44px;
}

/* ==========================================================================
   §P — PRODUCT PAGE (PDP)                                     [§10.200]
   ==========================================================================
   ⚠️ THE BUY PANEL IS THE STORE BAND'S, RE-COLUMNED — transcribed from the
   design's own sheet, values unchanged. Its badge is C07's `.cs-buy__badge`
   and its price is `.cs-offer__price`'s weight at PDP scale; what changes is
   the ARRANGEMENT, because a product page leads with the price rather than
   boxing it inside an offer card.
   ⚠️ ONLY `.chumuk-pdp*` IS NEW. `.chumuk-pill`, `.chumuk-splitcta`,
   `.chumuk-qty`, `.chumuk-notice`, `.cs-buy__badge` and `.chumuk-steprow__*`
   were already in this sheet and are NOT re-declared here — a second copy of
   a component is the defect the design's own README opens with.
   🔴 NO `!important` AND NO SELECTOR STRENGTHENING. Every rule below is a
   single class at its natural specificity.
   ⚠️ WOOCOMMERCE'S FORM IS STYLED, NOT REPLACED. `.chumuk-pdp__cart` is a
   wrapper the block puts AROUND Woo's rendered `add-to-cart-form`; the
   selectors that reach into it name Woo's own classes and change layout only.
   ========================================================================== */

.chumuk-pdp {
	display: grid;
	grid-template-columns: minmax( 0, 1fr ) 42%;
	gap: clamp( 24px, 3vw, 64px );
	align-items: start;
}
.chumuk-pdp__media { display: grid; gap: 20px; }
.chumuk-pdp__plate {
	background: var( --wp--preset--color--white );
	border-radius: 22px;
	padding: clamp( 20px, 2vw, 40px );
	display: grid;
	place-items: center;
	box-shadow: 0 10px 26px color-mix( in srgb, var( --wp--preset--color--dot-wine ) 10%, transparent );
	min-block-size: 380px;
}
/* The jar keeps C07's measured 296px CEILING and shrinks below it — a bare
   296px width was the 46px-overflow defect in the store band. */
.chumuk-pdp__plate img { display: block; height: auto; width: min( 320px, 100% ); }
.chumuk-pdp__plate img.chumuk-pdp__img--wide { width: min( 620px, 100% ); }

.chumuk-pdp__buy { display: grid; gap: 16px; align-content: start; }
.chumuk-pdp__title {
	margin: 0;
	font-family: var( --wp--custom--font-heading );
	font-weight: 500;
	font-size: clamp( 34px, 2.125rem + ( ( 1vw - 3.2px ) * 1.212 ), 50px );
	line-height: 1.06;
}
.chumuk-pdp__sub { margin: 0; font-size: 17px; line-height: 1.5; color: var( --chumuk-muted-ink ); }

.chumuk-pdp__pricerow { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 14px; }
/* 🔴 `wc_price()` PUTS U+00A0 BETWEEN ৳ AND ITS NUMBER. `nowrap` is what keeps
   the sign with the figure when the row wraps; without it a narrow column can
   leave a bare ৳ at the end of one line. Woo's own `<del>`/`<ins>` markup is
   what carries the struck regular price, so `.chumuk-pdp__was` styles Woo's
   element rather than a second one this theme would have to keep in step. */
.chumuk-pdp__price { font-size: 34px; font-weight: 600; white-space: nowrap; }
.chumuk-pdp__price del,
.chumuk-pdp__was { font-size: 18px; color: var( --chumuk-muted-ink ); white-space: nowrap; }
.chumuk-pdp__price ins { text-decoration: none; }
.chumuk-pdp__save {
	background: var( --chumuk-save-bg );
	color: var( --wp--preset--color--white );
	border-radius: var( --wp--custom--pill-radius );
	padding: 5px 13px;
	font-family: var( --wp--custom--font-body );
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	white-space: nowrap;
}
.chumuk-pdp__desc { max-width: 54ch; }

.chumuk-pdp__facts { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 0; }
.chumuk-pdp__facts li {
	display: flex;
	justify-content: space-between;
	gap: 18px;
	font-size: 15px;
	line-height: 1.5;
	padding-block: 11px;
	border-bottom: 1px solid var( --chumuk-rule-pink );
}
.chumuk-pdp__facts li:last-child { border-bottom: 0; }
.chumuk-pdp__facts span:first-child { color: var( --chumuk-muted-ink ); }
.chumuk-pdp__facts span:last-child { font-weight: 600; text-align: right; }

/* --- Woo's add-to-cart form, arranged --------------------------------------
   The design draws the stepper and the button on one row. Woo emits
   `<form class="cart">` containing `.quantity` and `button.single_add_to_cart_button`,
   and for a variable product a `<table class="variations">` above them. The
   row is expressed on Woo's own form element; nothing is re-emitted. */
.chumuk-pdp__cart { margin-top: 4px; }
.chumuk-pdp__cart form.cart { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.chumuk-pdp__cart form.variations_form { display: block; }
.chumuk-pdp__cart .woocommerce-variation-add-to-cart { display: flex; flex-wrap: wrap; align-items: center; gap: 14px; }
.chumuk-pdp__cart .quantity { background: var( --wp--preset--color--white ); border-radius: var( --wp--custom--pill-radius ); padding: 6px 10px; }
.chumuk-pdp__cart .single_add_to_cart_button { flex: 1 1 240px; }
.chumuk-pdp__notice { margin-top: 4px; }

/* --- how to make ---------------------------------------------------------- */
.chumuk-pdp__how {
	display: grid;
	grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1.1fr );
	gap: clamp( 24px, 3vw, 56px );
	align-items: center;
}
.chumuk-pdp__howtext { display: grid; gap: 14px; align-content: start; }
.chumuk-pdp__steps { list-style: none; margin: 6px 0 0; padding: 0; display: grid; gap: 14px; }
.chumuk-pdp__steps li { display: flex; gap: 14px; align-items: flex-start; }

/* ⚠️ TWO BREAKPOINTS, NOT ONE, AND THEY ARE THE DESIGN'S OWN: the buy panel
   collapses at 1080px because its 42 % column stops holding a price row, and
   the how-to band holds its two columns down to 900px. Collapsing both at one
   width would be a tidier sheet and a different design. */
@media ( max-width: 1080px ) {
	.chumuk-pdp { grid-template-columns: minmax( 0, 1fr ); }
}
@media ( max-width: 900px ) {
	.chumuk-pdp__how { grid-template-columns: minmax( 0, 1fr ); }
}

/* 🔴 ON A VARIABLE PRODUCT WOO'S OWN PRICE IS THE ONLY PRICE. It is promoted to
   the design's price scale here rather than duplicated by a static row the
   theme would have to keep in step with the shopper's selection. `del`/`ins`
   are Woo's own sale markup; `ins` loses the UA underline exactly as the
   simple-product row does. */
.chumuk-pdp__cart--priced .woocommerce-variation-price { margin-block-end: 14px; }
.chumuk-pdp__cart--priced .woocommerce-variation-price .price {
	font-size: 34px;
	font-weight: 600;
	white-space: nowrap;
	display: inline-flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 8px 14px;
}
.chumuk-pdp__cart--priced .woocommerce-variation-price del { font-size: 18px; color: var( --chumuk-muted-ink ); }
.chumuk-pdp__cart--priced .woocommerce-variation-price ins { text-decoration: none; }

/* ==========================================================================
   §Q — SHOP  (archive-product: /shop/, every product category, every product tag)
   --------------------------------------------------------------------------
   🔴 ONE GROUND SHIPS, NOT SIX. The design file carries the bundle strip in six
   treatments — crimson, ink, cyan, pink, card-on-ice and card-on-pink — behind a
   `{{ bundleClass }}` token, because it was still choosing. Five of them are CSS
   describing a design nobody can see, which the design's own README calls the
   defect this project audits for. The card-on-ice treatment ships because the
   design's own newest prose rules on it: "🔴 THE CARD'S GROUND IS `ice` #E5FBFB,
   NOT PINK, AND THAT IS THE WHOLE POINT OF THE BAND BREAK" — the store above sits
   on pink, and a pink banner under it read as one continuous block. `ice` is C09's
   and C14's ground, so the alternation is the page's existing rhythm.
   The five unshipped grounds are recorded in build report 80, not left here.

   ⚠️ ZERO HEX LITERALS. The design declares `#E5FBFB`, `#9E1B3C` and `#1C1C3C` at
   their point of use; the first two are registered slugs (`ice`, `dot-wine`) and
   the third is not — see the note on the chip below.
   ========================================================================== */

/* --- the footer guard ------------------------------------------------------
   ⚠️ PRESSING A TAB MOVED THE FOOTER, AND ONLY ON THIS PAGE. The combo panel is
   the taller of the two, so swapping panels changed the document height and the
   footer with it. On the homepage the band sits mid-page and the shift is not
   visible; here it is the last thing above the banner.
   🔴 A STACK, NOT A `min-block-size`: a pixel floor is only correct at the width
   it was measured at, and these panels are percentage grids that re-proportion at
   every breakpoint. A stack re-measures itself for free.
   ⚠️ `visibility: hidden`, NOT `display: none` — hidden still reserves the cell,
   which is the whole point, while staying out of the tab order and the
   accessibility tree, so the tablist still exposes exactly one live panel.
   ⚠️ SCOPED TO `.chumuk-shop`. The homepage's store band keeps its verified
   behaviour; `.chumuk-store__panels` is an unstyled wrapper there. */
.chumuk-shop .chumuk-store__panels { display: grid; }

.chumuk-shop .chumuk-store__panels > .cs-panel {
	grid-area: 1 / 1;
	display: grid;
	visibility: hidden;
}

.chumuk-shop .chumuk-store__panels > .cs-panel.is-active { visibility: visible; }

/* --- the bundle banner ----------------------------------------------------
   ⚠️ WHY IT EXISTS: this template carries ONE band, so the page ended on the
   picker and the footer arrived immediately. The banner is the promo bar's own
   line — BUY MORE SAVE MORE — finally shown the product it refers to. */
.chumuk-bundle {
	background: var( --wp--preset--color--ice );
	color: var( --wp--preset--color--ink );
	padding-block: clamp( 40px, 4.4vw, 72px );
	padding-inline: var( --wp--style--root--padding-right, 0 );
}

.chumuk-bundle__inner {
	max-inline-size: var( --wp--style--global--wide-size );
	margin-inline: auto;
	display: grid;
	grid-template-columns: minmax( 0, 1fr ) minmax( 0, 0.9fr );
	gap: clamp( 28px, 3.4vw, 64px );
	align-items: center;
	background: var( --wp--preset--color--white );
	border-radius: 18px;
	/* ⚠️ AN ALPHA COMPOSITE THROUGH A REGISTERED SLUG, the §I precedent. The design
	   writes `rgba( 17, 17, 17, 0.08 )`; `ink` is #343434 and 8% of it on white is
	   within a hair of that, and it is a colour this site has a name for. */
	box-shadow: 0 18px 40px color-mix( in srgb, var( --wp--preset--color--ink ) 8%, transparent );
	padding: clamp( 28px, 3vw, 56px );
}

.chumuk-bundle__eyebrow {
	margin: 0 0 14px;
	font-family: var( --wp--custom--font-body );
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	opacity: 0.86;
}

.chumuk-bundle__title {
	/* 🔴 EXPLICIT `inherit`, AND IT IS THE C07 HEADING TRAP AGAIN (see
	   `.cs-head__title`): theme.json sets `elements.heading.color` to `ink`, and ANY
	   direct rule beats inheritance — so a band's own `color` never reaches its own
	   `<h2>`. Harmless on this ground, where the two agree, and load-bearing the day
	   the ground changes. */
	margin: 0;
	color: inherit;
	font-family: var( --wp--custom--font-heading );
	font-weight: 500;
	line-height: 1.08;
	font-size: clamp( 32px, 2rem + ( ( 1vw - 3.2px ) * 1.515 ), 52px );
	text-wrap: pretty;
}

.chumuk-bundle__text {
	margin: 16px 0 0;
	max-inline-size: 48ch;
	font-size: 17px;
	line-height: 1.6;
	opacity: 0.92;
}

.chumuk-bundle__prices {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 8px 16px;
	margin-block-start: 24px;
}

/* ⚠️ `wc_price()` PUTS A NON-BREAKING SPACE BETWEEN ৳ AND ITS NUMBER. `nowrap` on
   all three is what keeps the sign from wrapping away from the figure it belongs
   to — the same guard §P puts on the PDP's prices. */
.chumuk-bundle__price { font-size: 34px; font-weight: 600; white-space: nowrap; }
.chumuk-bundle__was { font-size: 18px; opacity: 0.72; white-space: nowrap; }

/* The chip and the button on a light ground are not inversions of anything — they
   are the components the rest of the site already ships: an ink chip and the
   `.cs-add` pill, `dot-wine` on hover.
   🔴 THE DESIGN GIVES THE CHIP #1C1C3C AND THE BUTTON #232323, TWO DARKS FOUR
   UNITS APART THAT READ IDENTICAL. Only #232323 has a name here
   (`--chumuk-ink-dark`), so both take it: a colour that is nearly a token is still
   not that token, and shipping the near-miss would put a second unnamed dark in
   the sheet. Raised for the owner in report 80 — the same finding as
   `--chumuk-save-bg` #006C90 against `dot-teal` #006C94 in report 79. */
.chumuk-bundle__save {
	background: var( --chumuk-ink-dark );
	color: var( --wp--preset--color--white );
	border-radius: var( --wp--custom--pill-radius );
	padding: 5px 13px;
	font-family: var( --wp--custom--font-body );
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.08em;
	white-space: nowrap;
}

.chumuk-bundle__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin-block-start: 28px;
	min-block-size: 44px;
	padding: 18px 32px;
	border: 0;
	border-radius: var( --wp--custom--pill-radius );
	background: var( --chumuk-ink-dark );
	color: var( --wp--preset--color--white );
	font-family: var( --wp--custom--font-body );
	font-size: 15px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: none;
	cursor: pointer;
	transition: background 160ms ease, color 160ms ease;
}

.chumuk-bundle__cta:hover,
.chumuk-bundle__cta:focus-visible {
	background: var( --wp--preset--color--dot-wine );
	color: var( --wp--preset--color--white );
}

/* The plate can bleed to the card's edge — it is a photograph on white, and the
   card's own padding already gives it air. */
.chumuk-bundle__media { display: grid; justify-items: center; }

.chumuk-bundle__media img {
	display: block;
	inline-size: 100%;
	max-inline-size: 480px;
	block-size: auto;
}

/* ⚠️ THE DESIGN'S COLLAPSE, NOT A CHOSEN ONE: its second `grid-template-columns`
   declaration drops the banner to one column. It carries no media query in the
   design file because the design draws one width at a time; 900px is the same
   breakpoint §P uses for the PDP's how-to band, which is the same two-column
   copy-beside-photograph shape. */
@media ( max-width: 900px ) {
	.chumuk-bundle__inner { grid-template-columns: minmax( 0, 1fr ); }
	.chumuk-bundle__media { order: -1; }
}

/* =========================================================================
   §R — CART
   =========================================================================
   🔴 EVERY SELECTOR BELOW IS A WOOCOMMERCE CLASS. The design draws its own
   `.chumuk-line` / `.chumuk-summary` markup, and the brief's rule is to style
   Woo's blocks rather than replace them: the cart block owns the Store API,
   the quantity steppers, the coupon round-trip and the shipping calculator,
   and a hand-built copy of it is a cart that cannot take an order. So the
   design's component names appear here only where the design's OWN markup
   ships (the flow rail, the empty state); everything else is Woo's block
   wearing the design's clothes.

   🔴 THE RULES ARE SCOPED TO `.chumuk-flowpage`, AND THAT IS NOT SELECTOR
   STRENGTHENING. [MEASURED] Woo ships its cart-page rules as
   `table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__image`
   — specificity 0,3,1. An unscoped `.wc-block-cart-item__image` (0,1,0) loses
   to it and computes to nothing, which is why the first capture of this page
   showed a correctly-classed cart with none of the design's geometry. Writing
   at the same level as the rule being overridden is not a hack; adding
   `!important` to a 0,1,0 rule would have been. `.chumuk-flowpage` is a real
   class on this template's `<main>`, so the scope is also true.

   ⚠️ `.wc-block-cart-items li` IN §? IS NOT DEAD AND IS NOT TOUCHED HERE. It
   reads like a rule for this page and it is not: the MINI-CART drawer renders
   its items as `<ul><li>` while the cart PAGE renders `<table><tr>`. Same
   block name, two markups. I nearly rewrote a working rule on the strength of
   a class name — the same shape of mistake as reading an elided CLI listing as
   an empty one (report 80). Both sets stay, each scoped to where its markup
   actually exists.

   🔴 THE TABLE STAYS A TABLE. The design's row is a three-track grid, and
   making `tr`/`td` into grid boxes would have got there in four declarations —
   at the cost of the table's row and column semantics, so a screen reader
   would lose the PRODUCT/TOTAL headers that are this page's only column
   labels. The cells are styled where they sit instead. The visible delta from
   the design: the quantity stepper and Remove sit under the product name
   rather than in the right-hand rail with the price. That is Woo's cell
   assignment, it reads correctly, and it is not worth an accessibility
   regression to move. */

.chumuk-flowpage { padding-block-end: clamp( 40px, 5vw, 76px ); }

/* ⚠️ THE RAIL'S OWN MARGIN IS IN §? ALREADY — this only closes the gap that
   the store-notice leaves above it when Woo has just added something. */
.chumuk-flowpage .wc-block-components-notices { margin-block-end: clamp( 18px, 2vw, 28px ); }

/* --- THE TWO COLUMNS ------------------------------------------------------
   🔴 THE COLUMN WIDTHS ARE WOO'S AND NOTHING HERE RE-DECLARES THEM. This rule
   first read `gap: 48px`, `flex: 1 1 auto` on the main column and
   `flex: 0 0 clamp(300px,32%,360px)` on the sidebar, with Woo's gutter zeroed
   out. [MEASURED] that stacked the whole cart: Woo already sizes the main
   column at `width: 65%` and spaces the two with `padding-right: 4.528%` on
   the main column rather than with a gap, so 65% (608px) + a 300px basis +
   a 48px gap came to 956px inside a 936px row and the sidebar wrapped onto
   its own line. Re-stating a layout the block already has is how you break it.
   The design's proportions and Woo's are the same 2:1 anyway.

   ⚠️ `flex-wrap` IS ALREADY WOO'S — restated here only so the reason survives.
   The COD foot lives inside `filled-cart-block`, so that it appears only when
   there is something to pay for, which makes it a third flex child. The
   full-width basis below puts it on its own row under both columns where the
   design draws it. Moving it out of the block instead would have printed "pay
   the rider" beneath an empty cart. */
.chumuk-flowpage .wc-block-cart { align-items: flex-start; }
.chumuk-flowpage .chumuk-cart__foot { flex: 1 1 100%; }

/* --- THE LINE-ITEM TABLE --------------------------------------------------
   🔴 THE CELL GEOMETRY IS SCOPED TO `.is-large`, WHICH IS WOOCOMMERCE'S OWN
   WIDTH STATE. Woo's script measures the cart container and stamps
   `is-large` / `is-medium` / `is-small` on it, then lays the row out
   differently in each — at narrow widths the total is lifted out of its cell
   and positioned against the product cell. [MEASURED] applying our cell
   padding and `vertical-align` at every width collided with that and the
   description ran under the price on a 390px viewport. Scoping to Woo's own
   state class hands the narrow layout back to Woo, which already handles it,
   rather than writing a second responsive cart on top of the first. */
.chumuk-flowpage table.wc-block-cart-items { inline-size: 100%; border-collapse: collapse; margin: 0; }

/* The design has no PRODUCT/TOTAL row. It is kept and quietened rather than
   hidden: `display: none` on a `<thead>` takes the table's only column labels
   away from assistive technology to save two words of ink. */
.chumuk-flowpage .wc-block-cart.is-large table.wc-block-cart-items .wc-block-cart-items__header th {
	font-family: var(--wp--custom--font-body);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--chumuk-field-ink);
	border-block-end: 1px solid var(--chumuk-rule);
	padding-block: 0 12px;
}

.chumuk-flowpage .wc-block-cart.is-large table.wc-block-cart-items .wc-block-cart-items__row td {
	border-block-end: 1px solid var(--chumuk-rule);
	padding-block: 22px;
	vertical-align: top;
}

.chumuk-flowpage .wc-block-cart.is-large table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__image {
	inline-size: 88px;
	padding-inline-end: 18px;
}
.chumuk-flowpage .wc-block-cart.is-large table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__image img {
	inline-size: 88px;
	block-size: 88px;
	object-fit: cover;
	border-radius: 14px;
	background: var(--wp--preset--color--ice);
	display: block;
	margin: 0;
}

.chumuk-flowpage .wc-block-components-product-name {
	font-family: var(--wp--custom--font-heading);
	font-size: clamp( 17px, 1.5vw, 20px );
	line-height: 1.25;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
}
.chumuk-flowpage .wc-block-components-product-name:hover { color: var(--wp--preset--color--dot-wine); }

.chumuk-flowpage .wc-block-components-product-metadata,
.chumuk-flowpage .wc-block-cart-item__prices {
	font-size: 14px;
	line-height: 1.5;
	color: var(--chumuk-field-ink);
}

/* ⚠️ `wc_price()` PUTS A NON-BREAKING SPACE BETWEEN ৳ AND ITS NUMBER, and the
   sign must not wrap away from the number it belongs to. Same rule §Q gives
   the shop's bundle figures. */
.chumuk-flowpage .wc-block-components-product-price,
.chumuk-flowpage .wc-block-cart-item__total,
.chumuk-flowpage .wc-block-components-totals-item__value {
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

.chumuk-flowpage .wc-block-cart.is-large table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__total {
	text-align: end;
	font-size: 16px;
	font-weight: 700;
	color: var(--wp--preset--color--ink);
}

.chumuk-flowpage .wc-block-cart-item__quantity { margin-block-start: 14px; }

/* 🔴 44px OF TARGET ON BOTH STEPPER BUTTONS AND THE REMOVE LINK (WCAG 2.5.8).
   The stepper is the control a shopper uses most on this page and Woo draws it
   at its own size; the overlay is applied without moving the glyph. */
.chumuk-flowpage .wc-block-components-quantity-selector { border-radius: var(--wp--custom--pill-radius); border: 1px solid var(--chumuk-field-border); overflow: hidden; }
.chumuk-flowpage .wc-block-components-quantity-selector__button { min-inline-size: 44px; min-block-size: 44px; }
.chumuk-flowpage .wc-block-components-quantity-selector__input { min-block-size: 44px; }
.chumuk-flowpage .wc-block-cart-item__remove-link { min-block-size: 44px; display: inline-flex; align-items: center; }

/* --- THE SUMMARY CARD -----------------------------------------------------
   The design's `.chumuk-summary` is already declared in §?; these rules give
   Woo's sidebar the same treatment rather than re-declaring the component. */
/* ⚠️ THE SIDEBAR AND `.wc-block-components-sidebar` ARE THE SAME ELEMENT, NOT
   PARENT AND CHILD. [MEASURED] the sidebar column carries both classes, so the
   descendant selector this rule was first written with matched nothing and the
   summary shipped with no card at all — a rule that existed, applied to a real
   class, and changed nothing. Verify the computed value, never that a rule is
   present. */
.chumuk-flowpage .wc-block-cart__sidebar {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	box-shadow: var(--chumuk-page-shadow);
	padding: clamp( 22px, 2.2vw, 30px );
}
.chumuk-flowpage .wc-block-cart__totals-title {
	font-family: var(--wp--custom--font-body);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	font-size: 13px;
	font-weight: 700;
	color: var(--wp--preset--color--dot-wine);
	margin-block: 0 16px;
}
.chumuk-flowpage .wc-block-components-totals-item { font-size: 15px; padding-block: 8px; }
.chumuk-flowpage .wc-block-components-totals-item__label { color: var(--chumuk-field-ink); }
.chumuk-flowpage .wc-block-components-totals-footer-item {
	border-block-start: 1px solid var(--chumuk-rule);
	margin-block-start: 8px;
	padding-block-start: 16px;
	font-size: 19px;
	font-weight: 700;
}
.chumuk-flowpage .wc-block-components-totals-wrapper { padding-block: 4px; }
.chumuk-flowpage .wc-block-components-totals-coupon__form { margin-block-start: 10px; }

/* The checkout button is the page's one commitment, and it wears the site's
   button rather than Woo's black pill. */
.chumuk-flowpage .wc-block-cart__submit-button {
	min-block-size: 44px;
	border-radius: var(--wp--custom--pill-radius);
	background: var(--wp--preset--color--dot-wine);
	color: var(--wp--preset--color--white);
	font-family: var(--wp--custom--font-body);
	font-weight: 700;
	letter-spacing: 0.02em;
}
.chumuk-flowpage .wc-block-cart__submit-button:hover { background: var(--chumuk-ink-dark); }

/* --- THE FOOT: COD TERMS AND THE WAY BACK ---------------------------------
   🔴 THE COD NOTICE CARRIES NO FIGURE, AND THE DESIGN'S DOES. Its line reads
   "Pay the rider {{ totalText }} when the box arrives." The cart total on this
   page is recomputed by the Store API without a reload — change a quantity and
   every figure in the summary updates in place — so a total rendered into
   prose on the server is correct only until the shopper's first click, and
   then it is a payment amount that is wrong. The summary states the total four
   inches above; the notice states the terms. */
.chumuk-flowpage .chumuk-cart__foot { margin-block-start: clamp( 26px, 3vw, 40px ); display: grid; gap: 14px; justify-items: start; }
.chumuk-flowpage .chumuk-cart__back { margin: 0; font-size: 15px; }

/* --- THE EMPTY STATE ------------------------------------------------------
   ⚠️ THE CART ICON IS WOOCOMMERCE'S, NOT THE DESIGN'S SVG. `with-empty-cart-icon`
   is a class Woo's own cart stylesheet paints a basket onto; using it costs no
   markup, and core blocks cannot emit an inline `<svg>` without a `core/html`
   block, which this project forbids. It draws a basket; so did the design's. */
.chumuk-flowpage .wp-block-woocommerce-empty-cart-block { text-align: center; padding-block: clamp( 24px, 4vw, 56px ); }
.chumuk-flowpage .wc-block-cart__empty-cart__title { margin-block-end: 12px; }
.chumuk-flowpage .chumuk-cart__emptyprose { margin-block: 0 26px; color: var(--chumuk-field-ink); }
.chumuk-flowpage .chumuk-cart__emptybtns { justify-content: center; margin-block-end: 30px; }
.chumuk-flowpage .wp-block-woocommerce-empty-cart-block .chumuk-pillrow { justify-content: center; }

@media ( max-width: 860px ) {
	.chumuk-flowpage .wc-block-cart { flex-wrap: wrap; }
	.chumuk-flowpage .wc-block-cart__main,
	.chumuk-flowpage .wc-block-cart__sidebar { flex: 1 1 100%; }
}

/* 🔴 WOO'S EMPTY-CART GLYPH IS RESIZED AND RECOLOURED, NOT REPLACED. [MEASURED]
   `with-empty-cart-icon::before` is a `5em` masked square painted in
   `currentColor` — against this page's 32px heading that rendered a ~210px
   dark-grey crying face, which is both four times the design's 34px mark and
   a tone the brand does not use anywhere else. The mask is Woo's; only its
   size, colour and the space under it are ours, so a Woo update that changes
   the artwork still lands. `--dot-teal` is the ice-band ink the design uses
   for its own empty-state mark. */
.chumuk-flowpage .wc-block-cart__empty-cart__title::before {
	block-size: 78px;
	inline-size: 78px;
	mask-size: 78px;
	margin-block-end: 22px;
	color: var(--wp--preset--color--dot-teal);
}

/* The empty state's primary action is the same button the rest of the site
   uses, not core's default dark pill. */
.chumuk-flowpage .chumuk-cart__emptybtns .wp-block-button:not(.is-style-outline) .wp-block-button__link {
	background: var(--wp--preset--color--dot-wine);
	color: var(--wp--preset--color--white);
	min-block-size: 44px;
	display: inline-flex;
	align-items: center;
}
.chumuk-flowpage .chumuk-cart__emptybtns .is-style-outline .wp-block-button__link {
	min-block-size: 44px;
	display: inline-flex;
	align-items: center;
	color: var(--wp--preset--color--ink);
}

/* ⚠️ The flow rail needs air above it when Woo has no notice to show. Set on
   the rail rather than on `main`, so it does not double up under a notice. */
.chumuk-flowpage .chumuk-flowsteps { margin-block-start: clamp( 22px, 3vw, 40px ); }

/* ==========================================================================
   §S — CHECKOUT [§10.203]
   ==========================================================================
   🔴 THIS SECTION PAINTS WOO'S CHECKOUT BLOCK. IT DECLARES NO LAYOUT.
   [MEASURED] at 1040 before a line of this was written, Woo already sizes the
   two columns exactly as it sizes the cart's:
     .wc-block-checkout.is-large        display:flex  flex-wrap:wrap  936px
     .wc-block-checkout__main           width 608.391px (65%)  padding-right 42.375px
     .wc-block-checkout__sidebar        width 327.594px (35%)  padding-left 21.1875px  position:sticky
   There is NO gap — the gutter is padding on the columns. §R's first draft was
   deleted for re-stating exactly this on the cart and pushing the sidebar onto
   its own line (report 81 §4.2). ⚠️ RE-STATING A LAYOUT THE BLOCK ALREADY HAS IS
   HOW YOU BREAK IT. Nothing below sets width, flex, gap or the column padding.
   ⚠️ `.wc-block-checkout` IS ON TWO NESTED ELEMENTS — the outer
   `.wp-block-woocommerce-checkout.alignwide` and the inner
   `.wc-block-components-sidebar-layout.is-large`. A rule scoped to that class
   alone hits both. Everything here is scoped to `.chumuk-flowpage`, a real class
   on `<main>`, and reaches for the specific inner class it means.
   ⚠️ SCOPED TO `.chumuk-flowpage`, NOT TO `.chumuk-checkoutpage`, WHERE THE
   SURFACE IS SHARED. Cart and Checkout render the same summary rows, the same
   totals and the same buttons; a checkout-only scope would fork them. The
   checkout-only scope is used where the surface genuinely exists on one page. */

/* --- the step cards ------------------------------------------------------
   The design's `.chumuk-checkout__block` is a white card per fieldset. Woo's
   equivalent is `.wc-block-components-checkout-step`, one per step. */
.chumuk-flowpage .wc-block-components-checkout-step {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	box-shadow: var(--chumuk-page-shadow);
	padding: clamp( 20px, 2.2vw, 30px );
	margin-block-end: 20px;
}
.chumuk-flowpage .wc-block-components-checkout-step__title {
	font-family: var(--wp--custom--font-heading);
	font-size: clamp( 19px, 1.5vw, 22px );
	line-height: 1.25;
	color: var(--wp--preset--color--ink);
}
.chumuk-flowpage .wc-block-components-checkout-step__description {
	font-size: 14px;
	line-height: 1.6;
	color: var(--chumuk-field-ink);
}

/* --- fields --------------------------------------------------------------
   The design's `.chumuk-field` input: 1.5px border, pill-free radius, ink at
   16px so iOS does not zoom the viewport on focus. */
.chumuk-flowpage .wc-block-components-text-input input[type="text"],
.chumuk-flowpage .wc-block-components-text-input input[type="tel"],
.chumuk-flowpage .wc-block-components-text-input input[type="email"],
.chumuk-flowpage .wc-block-components-text-input input[type="number"],
.chumuk-flowpage .wc-block-components-combobox input,
.chumuk-flowpage .wc-block-components-textarea {
	border: 1.5px solid var(--chumuk-field-border);
	border-radius: 12px;
	font-family: var(--wp--custom--font-body);
	font-size: 16px;
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--white);
	min-block-size: 44px;
}
.chumuk-flowpage .wc-block-components-text-input input:focus,
.chumuk-flowpage .wc-block-components-combobox input:focus,
.chumuk-flowpage .wc-block-components-textarea:focus {
	border-color: var(--wp--preset--color--dot-wine);
	box-shadow: inset 0 0 0 1px var(--wp--preset--color--dot-wine);
}
.chumuk-flowpage .wc-block-components-text-input label,
.chumuk-flowpage .wc-block-components-combobox label {
	font-family: var(--wp--custom--font-body);
	color: var(--chumuk-field-ink);
}

/* --- the choice rows: shipping method and payment method -----------------
   The design draws these as `.chumuk-choice` — a ring, a name and a note.
   🔴 COD IS THE ONLY GATEWAY AND THE CHOOSER STILL RENDERS. [MEASURED]
   `get_available_payment_gateways()` returns exactly one entry, `cod`, so this
   is a radio group of one. It is kept, for three reasons: the shopper is told
   what will happen to their money rather than left to assume; the design draws
   the chooser rather than a sentence; and a second gateway added later appears
   in a control that is already styled, instead of arriving unstyled. Woo also
   keeps the input focusable, so the group is reachable by keyboard either way. */
/* ⚠️ `box-sizing: border-box` IS LOAD-BEARING HERE, NOT HOUSEKEEPING. [MEASURED]
   Woo leaves these labels at `content-box`, so the 46px + 16px padding added
   below is laid OUTSIDE the measured width: the row computed 456.266 + 46 + 16 +
   border = ~520px inside a ~486px card and both choice rows visibly broke out
   through the right edge of their step card. Padding on a content-box element is
   not padding, it is width. */
.chumuk-flowpage .wc-block-components-radio-control__option {
	box-sizing: border-box;
	inline-size: 100%;
	border: 1.5px solid var(--chumuk-field-border);
	border-radius: 14px;
	padding: 14px 16px 14px 46px;
	margin-block-end: 10px;
	min-block-size: 44px;
}
.chumuk-flowpage .wc-block-components-radio-control__option:has( input:checked ) {
	border-color: var(--wp--preset--color--dot-wine);
	background: var(--wp--preset--color--pink-soft);
}
/* 🔴 THE TWO CHOICE ROWS RENDERED AS TWO DIFFERENT COMPONENTS AND THE FIRST DRAFT
   OF THIS SECTION CAUSED IT. [MEASURED] after the rules above were added:
     shipping row   border-radius 4px    inset ring rgb(52,52,52)   border-top 1px
     payment row    border-radius 14px   no ring                    border-top 0
   Woo highlights the CHECKED SHIPPING RATE through a modifier the payment group
   does not carry, at
   `.wc-block-components-radio-control--highlight-checked label.wc-block-components-radio-control__option--checked-option-highlighted`
   — specificity (0,3,1) against the (0,2,0) written above, so the radius simply
   lost on one of the two rows. ⚠️ A RULE THAT EXISTS, NAMES REAL CLASSES AND
   CHANGES NOTHING — the third instance of that shape on this flow.
   ⚠️ THIS IS WOO'S OWN SELECTOR PLUS THE PAGE IT APPLIES ON, NOT AN INVENTED
   SPECIFICITY RAISE. `.chumuk-flowpage` is a real class on `<main>`; the rest is
   copied from Woo's stylesheet so the two stay in step if Woo renames the state.
   The inset ring is re-pointed rather than removed: `currentColor` on a crimson
   row is the brand colour already, so the ring survives as the checked
   affordance and only its geometry is brought back in line. */
.chumuk-flowpage .wc-block-components-radio-control--highlight-checked label.wc-block-components-radio-control__option--checked-option-highlighted {
	border-radius: 14px;
	box-shadow: inset 0 0 0 1.5px var(--wp--preset--color--dot-wine);
	border-color: var(--wp--preset--color--dot-wine);
	background: var(--wp--preset--color--pink-soft);
}
/* 🔴 THE PAYMENT ROW IS WRAPPED AND THE WRAPPER CARRIES ITS OWN RING. [MEASURED]
   the COD option is a `<label>` inside
   `div.wc-block-components-radio-control-accordion-option--checked-option-highlighted`,
   and that DIV computed `box-shadow: rgb(52,52,52) 0 0 0 1.5px inset` at
   `border-radius: 4px` — a black rectangle drawn around the whole option,
   description included, while the shipping row beside it wore crimson at 14px.
   ⚠️ I MISSED THIS ONCE BY GREPPING THE WRONG NAME. The class is
   `radio-control-accordion-option`, single dash; the earlier check asked for
   `radio-control-accordion__option` with the BEM underscores, got "not found",
   and I read that as "this wrapper does not exist". 🔴 AN INSTRUMENT RETURNING
   NOTHING IS NOT EVIDENCE OF NOTHING — it was answering a different question.
   The ground stays on the wrapper and comes OFF the inner label, so the checked
   state is one card rather than a pink block inside a ringed box. */
.chumuk-flowpage .wc-block-components-radio-control--highlight-checked .wc-block-components-radio-control-accordion-option--checked-option-highlighted {
	box-sizing: border-box;
	border-radius: 14px;
	box-shadow: inset 0 0 0 1.5px var(--wp--preset--color--dot-wine);
	background: var(--wp--preset--color--pink-soft);
}
.chumuk-flowpage .wc-block-components-radio-control-accordion-option .wc-block-components-radio-control__option {
	background: transparent;
	border-color: transparent;
	box-shadow: none;
	margin-block-end: 0;
}
.chumuk-flowpage .wc-block-components-radio-control__label {
	font-weight: 700;
	color: var(--wp--preset--color--ink);
}
.chumuk-flowpage .wc-block-components-radio-control__description {
	font-size: 14px;
	line-height: 1.55;
	color: var(--chumuk-field-ink);
}

/* --- the order summary ---------------------------------------------------
   The sidebar is Woo's `.wc-block-checkout__sidebar`, and it is the SAME element
   as `.wc-block-components-sidebar`. ⚠️ TWO CLASSES ON ONE ELEMENT, NOT PARENT
   AND CHILD — written as a descendant on the cart it matched nothing and shipped
   a summary with no card at all (report 81 §4.2). */
.chumuk-flowpage .wc-block-checkout__sidebar .wc-block-components-order-summary,
.chumuk-flowpage .wc-block-checkout__sidebar .wp-block-woocommerce-checkout-order-summary-block {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	box-shadow: var(--chumuk-summary-shadow);
	padding: clamp( 18px, 2vw, 26px );
}
.chumuk-flowpage .wc-block-components-totals-item__label {
	font-size: 15px;
	color: var(--chumuk-field-ink);
}
.chumuk-flowpage .wc-block-components-totals-item__value {
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}
.chumuk-flowpage .wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
	font-family: var(--wp--custom--font-heading);
	font-size: 26px;
	line-height: 1.1;
}

/* --- place order ---------------------------------------------------------
   The same crimson the cart's checkout button carries, so the two ends of the
   flow read as one action. 44px is the tap target, not a decoration. */
.chumuk-flowpage .wc-block-components-checkout-place-order-button {
	background: var(--wp--preset--color--dot-wine);
	color: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--pill-radius);
	font-family: var(--wp--custom--font-body);
	font-weight: 700;
	min-block-size: 48px;
}
.chumuk-flowpage .wc-block-components-checkout-place-order-button:hover {
	background: var(--chumuk-ink-dark);
}

/* ═══════════════════════════════════════════════════════════════════════════
   §T — CONFIRMATION
   The order-received page. Every selector below is WooCommerce's own class name,
   scoped to `.chumuk-confpage`, which is a real class on `<main>` in
   `templates/order-confirmation.html`.

   🔴 THIS SECTION DECLARES NO PAGE LAYOUT, and that is the lesson of report 81
   §4.2 rather than a style preference. The confirmation blocks are siblings in a
   `constrained` group and WooCommerce already spaces them with its own
   `--wp--style--block-gap: 24px`. Restating a column geometry a block already
   owns is what put the cart's sidebar on its own line.

   ⚠️ THE ONE GRID BELOW IS ON `…summary-list`, WHICH IS A BARE `<ul>` — Woo gives
   it no track geometry of its own, so this adds a layout rather than fighting one.
   The design draws those facts as a row of cards; Woo renders them as a list.

   ⚠️ EVERY COLOUR IS A REGISTERED SLUG read from `theme.json`'s palette, and each
   was confirmed to exist before it was used here. An undeclared `var()` voids its
   WHOLE declaration silently — the trap that would have shipped the checkout
   summary card with no shadow at all (report 82 §5).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── The thank-you panel ─────────────────────────────────────────────────────
   ⚠️ Its heading arrives here as `h2[data-chumuk-demoted]`, not `h1`. WooCommerce
   hard-codes `<h1>` in six branches of its Status block; the band above already
   owns the page's only `h1`, so `chumuk_demote_duplicate_page_heading()` is
   registered for the block in `functions.php`. Styled on the block, not the tag,
   so the level can change again without this rule noticing. */
.chumuk-confpage .wp-block-woocommerce-order-confirmation-status {
	background: var(--wp--preset--color--mint);
	border-radius: var(--chumuk-card-radius);
	padding: clamp( 22px, 2.6vw, 34px );
	margin-block-end: 22px;
}

.chumuk-confpage .wp-block-woocommerce-order-confirmation-status h2 {
	color: var(--wp--preset--color--mint-ink);
	margin-block: 0 10px;
}

.chumuk-confpage .wc-block-order-confirmation-status-description {
	color: var(--wp--preset--color--ink);
	margin-block-end: 0;
}

/* ── The facts row ───────────────────────────────────────────────────────────
   The design's four cards: order number, cash due, arrives in, placed. Woo emits
   however many it has, so the track is `auto-fit` rather than a hard `4` — a
   store that later adds a field gets a fifth card, not a broken row. */
.chumuk-confpage .wc-block-order-confirmation-summary-list {
	display: grid;
	/* ⚠️ 175px, NOT 190px, AND THE NUMBER WAS MEASURED. The design draws FOUR fact
	   cards; [MEASURED] WooCommerce emits FIVE — it adds "Email:", which the owner's
	   §1 ruling keeps as transactional. At 190px the fifth card wrapped alone onto a
	   second row. 5 × 175 + 4 × 14 = 931px inside the 936px row, so all five sit on
	   one line at desktop and the track still reflows on its own below that. */
	grid-template-columns: repeat( auto-fit, minmax( 175px, 1fr ) );
	gap: 14px;
	list-style: none;
	margin-block: 0 22px;
	padding-inline-start: 0;
}

.chumuk-confpage .wc-block-order-confirmation-summary-list-item {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	box-shadow: var(--chumuk-page-shadow);
	/* 🔴 `border-box` IS LOAD-BEARING HERE, AND ITS ABSENCE WAS A REAL DEFECT.
	   [MEASURED] at 320 the card computed `content-box` with `width: 280px` and this
	   rule's 20px of inline padding on each side, so its border box was **320px inside
	   a 280px grid track** — 40px of overflow in the list, surfacing as +20px of
	   horizontal scroll on the document. The page scrolled sideways on a phone.
	   ⚠️ THE PADDING IS OURS; THE BOX MODEL WAS NOT SET TO MATCH IT. §10.192 recorded
	   that this theme ships NO global `box-sizing` reset and sets `border-box` case by
	   case. This rule added padding to one of Woo's elements and did not do that, which
	   is the same failure as `box-sizing: content-box` on Woo's radio labels breaking
	   both choice rows out of their card — second occurrence, same cause.
	   ⚠️ IT WAS WRONG AT EVERY WIDTH, NOT ONLY AT 320. The cards were 40px wider than
	   their tracks everywhere; only 320 is narrow enough for the excess to reach the
	   viewport edge, which is why five widths caught what two could not.
	   ⚠️ NOT A RE-DECLARATION OF WOO'S LAYOUT. Woo sets no `box-sizing` on this element;
	   the grid, the track and the gap all stay Woo's and ours as they were. */
	box-sizing: border-box;
	padding: 18px 20px;
}

/* 🔴 `display` IS SET ON WOO'S OWN SELECTOR, NOT ON A SHORTER ONE, AND THE FIRST
   DRAFT GOT THIS WRONG IN A WAY ONLY A MEASUREMENT SHOWED. Every other declaration
   in these two rules landed — colour, size, weight, letter-spacing, margin all
   computed as written — while `display: block` silently lost and the label sat
   inline with its value. WooCommerce ships
     `.wc-block-order-confirmation-summary ul li > .…__key, … __value { display:inline }`
   at specificity (0,2,2); the rule below was (0,2,0). ⚠️ A RULE THAT MATCHES IS NOT
   A RULE THAT APPLIES — and a rule can lose ONE declaration while winning the rest,
   which is why "the label is teal, so the rule works" would have been the wrong
   check. The fix is Woo's own selector plus the page it applies on, which is
   targeting rather than an invented specificity raise; if Woo restructures this
   list, ours stops matching at the same moment theirs does. */
.chumuk-confpage .wc-block-order-confirmation-summary ul li > .wc-block-order-confirmation-summary-list-item__key,
.chumuk-confpage .wc-block-order-confirmation-summary ul li > .wc-block-order-confirmation-summary-list-item__value {
	display: block;
}

.chumuk-confpage .wc-block-order-confirmation-summary-list-item__key {
	color: var(--wp--preset--color--dot-teal);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	margin-block-end: 6px;
}

.chumuk-confpage .wc-block-order-confirmation-summary-list-item__value {
	color: var(--chumuk-ink-dark);
	font-size: clamp( 1.05rem, 1.5vw, 1.25rem );
	font-weight: 700;
	/* 🔴 [MEASURED] `admin@localhost.com` OVERFLOWED ITS CARD at 175px and was clipped
	   at the right edge. An email address is one unbroken token, so it cannot wrap on
	   its own — and this card is the one the shopper checks to see the receipt is
	   going somewhere they can read. `anywhere` rather than `break-word` because the
	   latter only breaks after trying to place the whole token on a line of its own,
	   which is exactly the overflow being fixed. */
	overflow-wrap: anywhere;
}

/* ── What you ordered, and what it costs ─────────────────────────────────────
   ⚠️ THE `<table>` STAYS A TABLE, for the reason report 81 decision 2 gives: the
   row/column semantics are this panel's only labelling. Cells are styled where
   they sit. */
.chumuk-confpage .wp-block-woocommerce-order-confirmation-totals-wrapper,
.chumuk-confpage .wp-block-woocommerce-order-confirmation-shipping-wrapper,
.chumuk-confpage .chumuk-conf__nextpanel {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	box-shadow: var(--chumuk-page-shadow);
	padding: clamp( 20px, 2.4vw, 30px );
	margin-block-end: 22px;
}

.chumuk-confpage .chumuk-conf__totalshead,
.chumuk-confpage .chumuk-conf__addrhead,
.chumuk-confpage .chumuk-conf__nexthead {
	margin-block: 0 16px;
}

.chumuk-confpage .wc-block-order-confirmation-totals__table {
	inline-size: 100%;
	border-collapse: collapse;
}

.chumuk-confpage .wc-block-order-confirmation-totals__table th,
.chumuk-confpage .wc-block-order-confirmation-totals__table td {
	padding-block: 12px;
	border-block-end: 1px solid var(--chumuk-summary-rule);
	text-align: start;
	vertical-align: top;
}

.chumuk-confpage .wc-block-order-confirmation-totals__table td:last-child,
.chumuk-confpage .wc-block-order-confirmation-totals__table th:last-child {
	text-align: end;
	/* ⚠️ `wc_price()` emits `&nbsp;` between the taka sign and the number — this
	   keeps the pair from wrapping apart at a narrow width, where `৳` alone on a
	   line reads as a different figure. */
	white-space: nowrap;
}

/* The final total is the figure a rider will be handed. It gets the weight. */
.chumuk-confpage .wc-block-order-confirmation-totals__total {
	color: var(--wp--preset--color--dot-wine);
	font-size: clamp( 1.1rem, 1.6vw, 1.35rem );
	font-weight: 700;
}

.chumuk-confpage .wc-block-order-confirmation-totals__table tr:last-child th,
.chumuk-confpage .wc-block-order-confirmation-totals__table tr:last-child td {
	border-block-end: 0;
}

/* ── What happens next ───────────────────────────────────────────────────────
   ⚠️ This is `chumuk/next-steps`, NOT the flow rail. The rail is where the shopper
   is in checkout; this is where the parcel goes. Two blocks, two components. */
.chumuk-confpage .chumuk-conf__next {
	list-style: none;
	margin: 0;
	padding-inline-start: 0;
}

.chumuk-confpage .chumuk-conf__next > li {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	padding-block: 14px;
	border-block-start: 1px solid var(--chumuk-summary-rule);
}

.chumuk-confpage .chumuk-conf__next > li:first-child {
	border-block-start: 0;
	padding-block-start: 0;
}

.chumuk-confpage .chumuk-steprow__n {
	flex: 0 0 auto;
	display: grid;
	place-items: center;
	inline-size: 30px;
	block-size: 30px;
	border-radius: 999px;
	background: var(--wp--preset--color--pink-soft);
	color: var(--wp--preset--color--dot-wine);
	font-weight: 700;
	font-size: 0.9rem;
}

.chumuk-confpage .chumuk-steprow__text {
	display: block;
}

.chumuk-confpage .chumuk-steprow__text strong {
	display: block;
	color: var(--chumuk-ink-dark);
	margin-block-end: 3px;
}

.chumuk-confpage .chumuk-steprow__text > span {
	display: block;
	color: var(--wp--preset--color--ink);
}

/* ── Delivering to ───────────────────────────────────────────────────────── */
.chumuk-confpage .wc-block-order-confirmation-shipping-address address {
	font-style: normal;
	color: var(--wp--preset--color--ink);
	line-height: 1.7;
	margin: 0;
}

/* ── The gateway's own words ─────────────────────────────────────────────────
   COD's instructions land here. Kept visually quieter than the panels above it:
   it is a note, not a fact the shopper has to act on. */
.chumuk-confpage .wc-block-order-confirmation-additional-information,
.chumuk-confpage .wp-block-woocommerce-order-confirmation-additional-information {
	color: var(--wp--preset--color--ink);
}

/* ==========================================================================
   §I-C  THE CONTACT PAGE  [build step 13 — page 6 of 8]
   Four bands, transcribed from `chumuk-contact.dc.html` §"CONTACT PAGE"
   (design lines 5942–5979). ⚠️ EVERY CLASS NAME BELOW WAS GREPPED AGAINST THE
   FRAME FIRST, as the note at §I demands: `.chumuk-contact*` returned ZERO
   matches in this file and 23 in the design, so nothing here collides and
   nothing here re-declares a §I rule. The page's scaffolding —
   `.chumuk-pagetitle`, `.chumuk-band`, `.chumuk-grid`, `.chumuk-card`,
   `.chumuk-disc`, `.chumuk-field`, `.chumuk-btn`, `.chumuk-textlink`,
   `.chumuk-splitcta`, `.chumuk-notice` — ALREADY EXISTS and is reused
   untouched. Only the contact-specific rules are new.

   ⚠️ THE THREE CHANNEL CARDS ARE ANCHORS, NOT DIVS — a `tel:`, a `wa.me` and
   a `mailto:` — so the whole card is the target and no separate "call now"
   link is needed. The phone and the email are the FOOTER'S OWN values, read
   from C16 rather than retyped as new facts.

   🔴 TWO HEX LITERALS IN THE DESIGN, BOTH RESOLVED TO REGISTERED TOKENS, per
   the standing zero-hex rule:
     · `#9E1B3C` on the tick → `dot-wine`, the same identification §10 already
       made at line 8346 ("[MEASURED] `dot-wine` is #9E1B3C in theme.json's
       palette");
     · `rgba( 2, 63, 130, 0.14 )` on the card hover → `blue-deep` at 14%,
       through `--wp--preset--color--blue-deep-rgb` (line 94). It is the SAME
       colour `--chumuk-page-shadow` already carries at 8%, so the hover is
       that shadow deepened, not a second blue.
   ========================================================================== */
.chumuk-contact__channel {
	text-decoration: none;
	color: var(--wp--preset--color--ink);
	gap: 10px;
}

/* The hover is `--chumuk-page-shadow` deepened: same colour, 0.08 -> 0.14, and
   lifted 10px -> 14px. Re-stating the colour rather than reusing the token
   because the token is a whole shadow, not a colour. */
.chumuk-contact__channel:hover {
	box-shadow: 0 14px 34px rgb( var( --wp--preset--color--blue-deep-rgb ) / 0.14 );
	color: var(--wp--preset--color--ink);
}

.chumuk-contact__channel .chumuk-disc {
	margin-bottom: 6px;
}

.chumuk-contact__value {
	font-size: 19px;
	font-weight: 700;
	letter-spacing: 0.01em;
	word-break: break-word;
}

.chumuk-contact__split {
	display: grid;
	grid-template-columns: minmax( 0, 1.25fr ) minmax( 0, 1fr );
	gap: clamp( 24px, 3vw, 56px );
	align-items: stretch;
}

.chumuk-contact__formwrap {
	background: var(--wp--preset--color--white);
	border-radius: var(--chumuk-card-radius);
	padding: clamp( 22px, 2.4vw, 38px );
	box-shadow: var(--chumuk-page-shadow);
}

.chumuk-contact__formhead {
	margin-bottom: 24px;
}

.chumuk-contact__form {
	display: grid;
	gap: 20px;
}

/* Core's flow-layout margin would double every gap in this grid. */
.chumuk-contact__form > * {
	margin: 0;
}

.chumuk-contact__row {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 220px, 1fr ) );
	gap: 20px;
}

.chumuk-contact__submit {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 14px 20px;
	margin-top: 4px;
}

/* ⚠️ AUTHORED, NOT TRANSCRIBED — the design has no honeypot because it has no
   handler. Off-screen rather than `display: none`: a bot must still find and
   fill it, and `display: none` is the one thing the cheaper ones skip.
   `aria-hidden` and `tabindex="-1"` in the markup keep it off both the screen
   reader and the keyboard path. */
.chumuk-contact__hp {
	position: absolute;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
}

/* The notice sits between the form's head and its first field, so it takes the
   form's own gap rather than a margin of its own. */
.chumuk-contact__notice {
	margin-bottom: 20px;
}

/* auto + 1fr so the map takes whatever height the form column leaves, which is
   what makes the two columns end on the same line. */
.chumuk-contact__aside {
	display: grid;
	grid-template-rows: auto minmax( 0, 1fr );
	gap: clamp( 16px, 1.5vw, 24px );
	align-content: stretch;
}

.chumuk-contact__block {
	gap: 10px;
}

.chumuk-contact__block .chumuk-disc {
	margin-bottom: 4px;
}

.chumuk-contact__map {
	min-block-size: 260px;
	border-radius: var(--chumuk-card-radius);
	overflow: hidden;
	box-shadow: var(--chumuk-page-shadow);
}

/* ⚠️ 980, AND IT IS THE DESIGN'S OWN NUMBER, not the site's 1180. The two
   columns here are a form and an aside, not C07's panel grid, and the design
   collapses them where the form's own fields stop fitting. Transcribed. */
@media ( max-width: 980px ) {
	.chumuk-contact__split {
		grid-template-columns: minmax( 0, 1fr );
		align-items: start;
	}

	.chumuk-contact__aside {
		grid-template-rows: auto auto;
	}

	.chumuk-contact__map {
		aspect-ratio: 4 / 3;
		/* 🔴 AUTHORED, AND IT IS THE ONE PLACE THE DESIGN COULD NOT HAVE CAUGHT THIS.
		   `min-block-size: 260px` above and `aspect-ratio: 4/3` here are both the
		   design's, and together they overflow: the min height wins, 260 × 4/3 makes
		   the box 346.66 wide, and [MEASURED] at 320 that put the map's right edge at
		   386.66 — a +67px document overflow. The design's slot is an `image-slot`
		   placeholder that never resolved an aspect ratio against a real box, so the
		   conflict could only appear once a live iframe filled it. Releasing the floor
		   lets `aspect-ratio` derive the height from the width it actually has. */
		min-block-size: 0;
	}
}

.chumuk-contact__wholesale {
	display: grid;
	grid-template-columns: minmax( 0, 1.3fr ) minmax( 0, 1fr );
	gap: clamp( 24px, 3vw, 56px );
	align-items: start;
}

.chumuk-contact__wholesaletext {
	display: grid;
	gap: 14px;
	align-content: start;
}

.chumuk-contact__list {
	list-style: none;
	margin: 6px 0 0;
	padding: 0;
	display: grid;
	gap: 10px;
}

/* The tick is a pseudo-element so the list carries no glyph in its markup — the
   same reason the breadcrumb's separator is one. */
.chumuk-contact__list li {
	display: grid;
	grid-template-columns: 22px minmax( 0, 1fr );
	gap: 12px;
	font-size: 16px;
	line-height: 1.55;
	color: var(--chumuk-field-ink);
}

.chumuk-contact__list li::before {
	content: '\2713';
	color: var(--wp--preset--color--dot-wine);
	font-weight: 700;
}

.chumuk-contact__wholesalecard {
	gap: 16px;
}

@media ( max-width: 980px ) {
	.chumuk-contact__wholesale {
		grid-template-columns: minmax( 0, 1fr );
	}
}

/* =========================================================================
   §I-D  THE ABOUT PAGE  [build step 14 — page 7 of 8]
   -------------------------------------------------------------------------
   Transcribed from `chumuk-about.dc.html:5940–5964`. Five bands on the shared
   §I vocabulary; only the rules below are the page's own, everything else is
   §I or the frame.

   ⚠️ TWO GROUNDS AND ONE ACCENT — white / ice alternating, with the closing CTA
   on the store's pink so the hand-off to the shop is visibly the shop's colour.

   🔴 THE DESIGN'S THREE `#6B6068` LITERALS ARE RESOLVED TO `--chumuk-muted-ink`
   (declared style.css:8370, the same value). ⚠️ NOT `--chumuk-text-secondary`:
   §10 already records that that token is `ink`-based and neutral where this one
   is warm and purple-leaning, and the two are visibly different. The literal is
   not carried through — the standing rule is zero hex literals.

   ⚠️ `.chumuk-grid--fixed4` IS NOT DEFINED HERE. It is a grid utility and sits
   with the other three at the top of §I.
   ========================================================================= */

/* The story band: text beside the glass, text slightly the wider of the two. */
.chumuk-about__story {
	grid-template-columns: minmax( 0, 1.05fr ) minmax( 0, 1fr );
	align-items: center;
	gap: clamp( 24px, 3vw, 60px );
}

.chumuk-about__storytext {
	display: grid;
	gap: 14px;
	align-content: start;
}

/* ⚠️ 900px, NOT one of the five sweep widths, and that is the design's own
   breakpoint — it is where the two columns stop having room, not where anything
   is measured. `order: -1` lifts the image above the prose when they stack, so
   the band still opens on the photograph the way it does side by side. */
@media ( max-width: 900px ) {
	.chumuk-about__story {
		grid-template-columns: minmax( 0, 1fr );
	}

	.chumuk-about__storymedia {
		order: -1;
	}
}

/* The sourcing band: eight flat cards, photo / name / note / origin. */
.chumuk-about__source {
	gap: 14px;
}

.chumuk-about__origin {
	margin: 0;
	font-family: var( --wp--custom--font-body );
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 11px;
	font-weight: 700;
	color: var( --chumuk-muted-ink );
}

/* The compliance band. */
.chumuk-about__cert {
	gap: 14px;
}

.chumuk-about__certmark {
	inline-size: 56px;
	block-size: 56px;
	display: grid;
	place-items: center;
}

/* ⚠️ `max-*` PLUS `width/height: auto` — the icons are 120px PNGs rendered into a
   56px mark, and without the auto pair the intrinsic attributes win one axis and
   the glyph distorts. */
.chumuk-about__certmark img {
	max-inline-size: 100%;
	max-block-size: 100%;
	width: auto;
	height: auto;
	display: block;
}

/* 🔴 MONOSPACE IS LOAD-BEARING, NOT DECORATION. This line carries a licence or
   certificate number, and a proportional face makes 1/l and 0/O ambiguous in the
   one string on the page a reader may need to copy onto a form. */
.chumuk-about__certno {
	margin: 0;
	font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
	font-size: 12px;
	color: var( --chumuk-muted-ink );
}

.chumuk-about__certnote {
	margin: 22px 0 0;
	font-size: 14px;
	line-height: 1.55;
	color: var( --chumuk-muted-ink );
	max-width: 78ch;
}

/* The closing CTA. */
.chumuk-about__cta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}

.chumuk-about__cta > div:first-child {
	display: grid;
	gap: 10px;
	max-width: 46ch;
}

.chumuk-about__ctabtns {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 20px 28px;
}

/* 🔴 THE TWO CTAs SAT 27.3 PX APART AND IT WAS CORE'S FLOW BLOCK-GAP, AGAIN [§10.214].
   [MEASURED] at 1440 before this rule: the button anchor top y=4022.9 h=44.5, the
   "Talk to us first" anchor top y=4050.2 h=16 — the second 27.3px lower, centres
   13.1px apart, and visibly below the pill in a screenshot.

   The row is declared `{"type":"default"}` in the block attrs, so core tags it
   `is-layout-flow` and emits `:where(body .is-layout-flow) > * { margin-block-start:
   24px }` on every child but the first. The rule above then makes the same element a
   FLEX row in CSS. [MEASURED] `child#0 mt=0px`, `child#1 mt=24px`. Under
   `align-items: center` it is the MARGIN box that is centred, so the paragraph's 24px
   top margin made its margin box (24+27.9=51.9) the tallest thing in the row, set the
   row height to 51.9, and pushed the link itself down to y=4043.2. The declared layout
   and the painted layout disagreed, and the block-gap is what fell through the crack.

   ⚠️ THE SAME DEFECT AS `.chumuk-grid > *` AT :8434 — the 24px that staggered Contact's
   cards and shipped through five sweeps. Third instance; same one-line stand-down.

   ⚠️ THE DESIGN HAS TWO BARE `<a>` SIBLINGS HERE; LIVE HAS A `core/buttons` WRAPPER AND
   A `<p>`. That difference is not the defect and is not being flattened — with the
   margin gone, `align-items: center` centres both boxes on the 44.5px row exactly as
   the design does. The structure stays as authored.

   ⚠️ NOT `!important` AND NOT A STRENGTHENED SELECTOR. Core's selector is wrapped in
   `:where()`, so this plain `0,1,0` rule wins on merit. The `gap` above is untouched
   and remains the only thing spacing these two items.

   ⚠️ FIXED HERE RATHER THAN IN THE BLOCK ATTRS BECAUSE POST 306 IS THE OWNER'S
   PUBLISHED CONTENT. Re-declaring the group as `{"type":"flex"}` would be the tidier
   answer to "ask core for the layout", but it means rewriting a page the owner has
   just published, and the stylesheet already owns this row's display, gap and
   alignment two rules above. */
.chumuk-about__ctabtns > * {
	margin-block-start: 0;
}

/* =========================================================================
   §I-E  THE ACCOUNT PAGE  [build step 15 — page 8 of 8]
   -------------------------------------------------------------------------
   Transcribed from `chumuk-my-account.dc.html` / `-signed-in.dc.html:5940–6041`.

   🔴 EVERY SELECTOR BELOW IS WOOCOMMERCE'S OWN CLASS NAME, NOT THE DESIGN'S.
   This is the one page whose markup the build does not author: post 16 holds
   `[woocommerce_my_account]` and Woo renders the `templates/myaccount/` set. The
   design calls a cell `.chumuk-acct__ono`; Woo calls it
   (⚠️ the template path is written without a glob on purpose — `myaccount/` plus a
   star reads as a comment opener to anything scanning this file, including a person.)
   `.woocommerce-orders-table__cell-order-number`, and no amount of CSS on the
   first name paints the second. The design's names are kept ONLY where the
   markup is ours — the dashboard tiles and the status pill, both rendered
   through Woo's own hooks in `chumuk-core/inc/account.php`.

   🔴 ONE PAGE, TWO STATES, AND THE FRAME ALREADY SAYS SO. [MEASURED] the body
   carries `chumuk-page--account` signed out and `chumuk-page--account`
   PLUS `chumuk-page--account-in` signed in — the design's own modifier, already
   emitted. Signed-out is not a second page and gets no second template; the
   two-column shell is simply scoped to the signed-in modifier, because signed
   out there is no rail to put in the first column.

   ⚠️ WOO'S OWN STYLESHEETS ARE LOADED AND ARE NOT FOUGHT. [MEASURED] thirteen
   sheets load here and the theme's is the last, so a tie in specificity falls
   this way without strengthening a selector. `woocommerce-smallscreen.css` is
   enqueued at `max-width: 768px` and already stacks `.shop_table_responsive`
   into blocks with `content: attr(data-title)` labels — that stacking is left
   to Woo and painted, rather than re-implemented at a breakpoint of our own.
   ⚠️ ITS `text-align: right !important` ON THE STACKED CELLS IS ACCEPTED. Beating
   it would need `!important`, which is forbidden here, and the alignment is
   Woo's own considered choice for that layout.
   ========================================================================= */

/* --- the shell -----------------------------------------------------------
   The design's `.chumuk-acct`. Woo renders the rail and the content as siblings
   inside `.woocommerce`, which is exactly the two-child grid the design draws. */
.chumuk-page--account-in .woocommerce {
	display: grid;
	grid-template-columns: 240px minmax( 0, 1fr );
	gap: clamp( 24px, 3vw, 56px );
	align-items: start;
}

/* 🔴 WOO SHIPS ITS OWN TWO-COLUMN LAYOUT AND IT HAS TO BE STOOD DOWN, NOT OUT-WEIGHED.
   [MEASURED] `woocommerce-layout.css` declares
   `.woocommerce-account .woocommerce-MyAccount-navigation { float: left; width: 30% }`
   and `… .woocommerce-MyAccount-content { float: right; width: 68% }` — a float pair
   from before grid. Left alone, the 68% won against a 716.8px track and the orders
   table rendered 429.9px wide inside it, which is how this was found: the grid was
   correct and its child was not filling it.
   ⚠️ EXACT SPECIFICITY PARITY, NOT MORE. Woo's selectors are (0,2,0) and both of these
   are (0,2,0); they win on source order, because the theme's sheet is the last of the
   thirteen that load. Nothing here is strengthened and nothing is `!important`. */
.chumuk-page--account-in .woocommerce-MyAccount-navigation,
.chumuk-page--account-in .woocommerce-MyAccount-content {
	float: none;
	width: auto;
}

/* 🔴 AND ITS CLEARFIX HAS TO GO WITH THEM, BECAUSE A PSEUDO-ELEMENT IS A GRID ITEM.
   [MEASURED] `.woocommerce-account .woocommerce::before` and `::after` are
   `content: " "; display: table` — the clearfix that made the float pair above work.
   In a flow container they are invisible. In a GRID container they are two more grid
   items, and they take real tracks: `::before` claimed column 1, which pushed the nav
   into column 2 and wrapped the content onto row 1 of column 1. The rail rendered
   716.8px wide and the content 240px — the layout exactly inverted.
   ⚠️ THIS IS WHY THE TABLE MEASURED 427.9px INSIDE A 716.8px COLUMN. The number that
   started the search was three steps downstream of the cause; bisecting the table, or
   the panel, or the grid template would each have found a correct box and moved on.
   🔴 AND NO INSTRUMENT BUT A LOOK WOULD HAVE CAUGHT IT. There is no overflow, no count
   changes, no rendered text changes, no duplicate id — the five-width sweep passes an
   inverted two-column layout without a murmur. Second entry for `00-conventions.md`
   §4.13 in as many pages. */
.chumuk-page--account-in .woocommerce::before,
.chumuk-page--account-in .woocommerce::after {
	content: none;
}

/* --- the rail ------------------------------------------------------------
   ⚠️ `list-style: none` IS LOAD-BEARING. [MEASURED] the computed `list-style-type`
   on Woo's `<ul>` is `disc` with `padding-left: 0`, so the markers are drawn
   outside the box and clipped — invisible by accident, not by declaration. */
.chumuk-page--account .woocommerce-MyAccount-navigation ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 2px;
	align-content: start;
}

/* ⚠️ THE PADDING BELONGS TO THE LINK, NOT THE ITEM. [MEASURED] `woocommerce-blocktheme.css`
   puts `padding: 1em 0` on the `<li>` — 17.86px top and bottom — which is how a rail
   the design draws at `gap: 2px` rendered with 83.5px rows around a 47.8px link. The
   design pads the anchor so the whole 44px target is clickable; padding the item
   instead makes the gap look like the target and the target smaller than it looks.
   Woo's selector is (0,2,1) and so is this one. */
.chumuk-page--account .woocommerce-MyAccount-navigation li {
	padding: 0;
	list-style: none;
}

.chumuk-page--account .woocommerce-MyAccount-navigation a {
	display: block;
	padding: 13px 18px;
	border-radius: 12px;
	text-decoration: none;
	color: var( --chumuk-field-ink );
	font-family: var( --wp--custom--font-body );
	font-size: 14px;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	min-block-size: 44px;
	/* ⚠️ §10.192 — this theme ships NO global reset and sets `border-box` case by
	   case. A 44px floor plus 13px of vertical padding is exactly the pair that
	   needs it, and two rules have already been caught skipping it. */
	box-sizing: border-box;
}

.chumuk-page--account .woocommerce-MyAccount-navigation a:hover {
	background: var( --wp--preset--color--ice );
	color: var( --wp--preset--color--ink );
}

/* 🔴 `.is-active` IS WOO'S STATE CLASS AND THE DESIGN'S IS `--on`. Matching Woo's
   is the whole rule: the current item is decided by Woo, on the endpoint it
   already knows, and re-deriving it from the URL would be a second answer to a
   question that already has one.
   ⚠️ WRITTEN AS `li.is-active a` RATHER THAN `.…-navigation-link.is-active a` FOR
   WEIGHT, NOT STYLE. Woo also declares
   `.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a
   { text-decoration: underline }` at (0,3,2); the class-only form of this selector is
   (0,3,1) and lost the underline while winning the ground — the filled pill rendered
   with its label underlined inside it. This form is (0,3,2): parity, source order. */
.chumuk-page--account .woocommerce-MyAccount-navigation li.is-active a,
.chumuk-page--account .woocommerce-MyAccount-navigation li.is-active a:hover {
	background: var( --chumuk-ink-dark );
	color: var( --wp--preset--color--white );
	text-decoration: none;
}

/* --- the content panel ---------------------------------------------------
   The design wraps each view in `.chumuk-panel`. Woo gives one container for all
   five, so the panel's own declarations are repeated here rather than the class
   being added to markup the build does not own. Values match `.chumuk-panel`
   (style.css:8708) and must move with it. */
.chumuk-page--account-in .woocommerce-MyAccount-content {
	background: var( --wp--preset--color--white );
	border-radius: var( --chumuk-card-radius );
	padding: clamp( 22px, 2.4vw, 34px );
	box-shadow: var( --chumuk-page-shadow );
	min-inline-size: 0;
}

.chumuk-page--account-in .woocommerce-MyAccount-content > p {
	font-size: 16px;
	line-height: 1.7;
	color: var( --chumuk-field-ink );
}

/* --- the orders table ----------------------------------------------------
   🔴 IT STAYS A `<table>`. The design builds this as a CSS grid and gives its
   reason: *"the head row is the ONE place the columns are declared — the rows
   inherit it, so a column cannot drift between head and body."* A real table
   does that by construction, and it also gives the row/column semantics a grid
   of `<span>`s throws away. The design used a grid because it had no table to
   use; Woo has one, so the design's stated goal is met more completely by
   keeping it than by reproducing the workaround. */
/* ⚠️ THESE THREE CARRY `table.shop_table` TO REACH WOO'S OWN WEIGHT, AND FOR NO OTHER
   REASON. Woo declares `.woocommerce table.shop_table` (0,2,1) and
   `.woocommerce table.shop_table td` / `… th` (0,2,2). A rule at (0,2,0) here won its
   colours and its borders and quietly LOST `padding` and `vertical-align` to the (0,2,2)
   pair — "a rule can win five declarations and lose one", found by reading the computed
   padding rather than by reading this file. `.chumuk-page--account-in table.shop_table`
   is (0,2,1) and `… td` is (0,2,2): parity with Woo, decided by source order. */
.chumuk-page--account-in table.shop_table {
	inline-size: 100%;
	border-collapse: collapse;
	border: 0;
	border-radius: 0;
	margin: 0;
}

.chumuk-page--account-in table.shop_table th {
	padding: 0 16px 10px 0;
	text-align: start;
	border-top: 0;
	border-bottom: 1.5px solid var( --chumuk-rule );
	font-family: var( --wp--custom--font-body );
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 11px;
	font-weight: 700;
	color: var( --chumuk-field-ink );
}

.chumuk-page--account-in table.shop_table td,
.chumuk-page--account-in table.shop_table tbody th {
	padding: 16px 16px 16px 0;
	border-top: 0;
	border-bottom: 1px solid var( --chumuk-rule );
	font-size: 15px;
	text-align: start;
	vertical-align: middle;
	text-transform: none;
	letter-spacing: normal;
	color: inherit;
}

.chumuk-page--account-in table.shop_table tbody tr:last-child td,
.chumuk-page--account-in table.shop_table tbody tr:last-child th {
	border-bottom: 0;
}

.chumuk-page--account-in .woocommerce-orders-table__cell-order-number,
.chumuk-page--account-in .woocommerce-orders-table__cell-order-total {
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.chumuk-page--account-in .woocommerce-orders-table__cell-order-date {
	color: var( --chumuk-field-ink );
}

.chumuk-page--account-in .woocommerce-orders-table__cell-order-actions {
	padding-right: 0;
	text-align: end;
}

/* --- the status pill -----------------------------------------------------
   🔴 THREE GROUNDS, AND THE THIRD IS AUTHORED. The design branches on one boolean
   and names two grounds; [MEASURED] this store registers thirteen statuses. The
   reasoning — that `live` asks "still moving?" while the GROUNDS also answer
   "did it succeed?", and that the two questions only look like one because the
   design's three seeded rows never separated them — is recorded in full at
   `chumuk-core/inc/account.php`, beside the mapping itself.
   ⚠️ THE MAPPING IS NOT DUPLICATED HERE. PHP picks the modifier; this file only
   says what each modifier looks like. */
.chumuk-page--account-in .chumuk-acct__opill {
	display: inline-flex;
	align-items: center;
	padding: 6px 14px;
	border-radius: var( --wp--custom--pill-radius );
	font-family: var( --wp--custom--font-body );
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	white-space: nowrap;
}

/* Still moving. The design's `--live`: `ice`, with the darkest registered teal. */
.chumuk-page--account-in .chumuk-acct__opill--live {
	background: var( --wp--preset--color--ice );
	color: var( --wp--preset--color--dot-teal );
}

/* Finished, and finished well. The design's `--done`. */
.chumuk-page--account-in .chumuk-acct__opill--done {
	background: var( --wp--preset--color--mint );
	color: var( --wp--preset--color--forest );
}

/* Finished, and not well — cancelled, failed, refunded. ⚠️ AUTHORED, and the one
   thing on this page the design does not show. */
.chumuk-page--account-in .chumuk-acct__opill--void {
	background: var( --wp--preset--color--sand );
	color: var( --wp--preset--color--dot-wine );
}

/* --- the dashboard tiles -------------------------------------------------
   Our markup, so the design's own names survive intact. Rendered through
   `woocommerce_account_dashboard`. */
.chumuk-acct__tiles {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 180px, 1fr ) );
	gap: clamp( 14px, 1.4vw, 20px );
	margin-top: 24px;
}

.chumuk-acct__tile {
	display: grid;
	gap: 4px;
	padding: 20px;
	border-radius: 14px;
	background: var( --wp--preset--color--ice );
	align-content: start;
}

.chumuk-acct__tilelabel {
	font-family: var( --wp--custom--font-body );
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 11px;
	font-weight: 700;
	color: var( --chumuk-field-ink );
}

.chumuk-acct__tilevalue {
	font-family: var( --wp--custom--font-heading );
	font-size: 30px;
	line-height: 1.1;
	font-variant-numeric: lining-nums tabular-nums;
}

.chumuk-acct__tilenote {
	font-size: 13px;
	line-height: 1.45;
	color: var( --chumuk-muted-ink );
}

/* --- addresses -----------------------------------------------------------
   ⚠️ ONE COLUMN, AND NOT BECAUSE OF THIS FILE. [MEASURED]
   `woocommerce_ship_to_destination` is `billing_only`, so Woo renders a single
   address. The design's two-card row is `auto-fit`, which resolves to one card
   at one card — no rule is needed to produce the state the design draws. */
.chumuk-page--account-in .woocommerce-Address {
	display: grid;
	gap: 10px;
	align-content: start;
	padding: clamp( 18px, 2vw, 26px );
	border-radius: var( --chumuk-card-radius );
	border: 1.5px solid var( --chumuk-rule );
	box-sizing: border-box;
}

.chumuk-page--account-in .woocommerce-Address-title {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px 20px;
}

.chumuk-page--account-in .woocommerce-Address-title h2 {
	margin: 0;
	font-family: var( --wp--custom--font-body );
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 11px;
	font-weight: 700;
	color: var( --chumuk-field-ink );
}

.chumuk-page--account-in .woocommerce-Address address {
	margin: 0;
	font-style: normal;
	font-size: 16px;
	line-height: 1.7;
	color: var( --chumuk-field-ink );
}

/* --- the account-details and login forms ---------------------------------
   ⚠️ NOTHING HERE IS A NEW CONTROL. Fields, labels and buttons are §I's, already
   painted by the shared form rules; these lay the rows out and nothing more. */
.chumuk-page--account .woocommerce-EditAccountForm,
.chumuk-page--account .woocommerce-form-login {
	display: grid;
	gap: 20px;
	margin: 0;
}

.chumuk-page--account .woocommerce-EditAccountForm > *,
.chumuk-page--account .woocommerce-form-login > * {
	margin: 0;
}

/* Woo's paired half-width rows. `.form-row-first` / `-last` are its own names for
   what the design lays out as one `auto-fit` row. */
.chumuk-page--account .woocommerce-EditAccountForm .form-row-first,
.chumuk-page--account .woocommerce-EditAccountForm .form-row-last {
	inline-size: 100%;
	box-sizing: border-box;
}

.chumuk-page--account .woocommerce-EditAccountForm fieldset {
	margin: 0;
	padding: 0;
	border: 0;
}

.chumuk-page--account .woocommerce-EditAccountForm legend {
	padding: 0;
	font-family: var( --wp--custom--font-body );
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 11px;
	font-weight: 700;
	color: var( --chumuk-field-ink );
}

/* ⚠️ `div.clear` IS WOO'S FLOAT CLEARER and this grid has no floats to clear. Left
   in the DOM (it is Woo's), taken out of the flow so it does not open a 20px gap
   between every pair of rows. */
.chumuk-page--account .woocommerce-EditAccountForm .clear {
	display: none;
}

/* --- signed out ----------------------------------------------------------
   🔴 THE DESIGN SHOWS TWO PANELS HERE AND ONLY ONE CAN RENDER. Its signed-out
   state is `.chumuk-acct__auth`, an `auto-fit` pair: "Login" beside "Create
   account". [MEASURED] `woocommerce_enable_myaccount_registration` is `no`, so Woo
   renders the login form alone and the second panel cannot exist.
   ⚠️ THE 560px CAP IS AUTHORED AND IS NOT WHAT THE DESIGN'S RULE WOULD DO. `auto-fit`
   with a single child collapses the empty track and gives that child the whole `1fr`,
   so transcribing the design here would stretch two fields across the full 1000px
   content width — a shape the design never draws, because in the design there is
   always a second panel beside this one. The cap holds the form at roughly the width
   the design gives it when it has company.
   🔴 THE OWNER'S CALL IS THE REGISTRATION SETTING, NOT THIS RULE. Turning
   registration on is a decision about who may open an account on a live store, and it
   is not a build's to make.

   🔴 §10.213 — THE OWNER MADE THAT CALL. `woocommerce_enable_myaccount_registration`
   is now `yes`, so the second panel exists and the paragraph above resolves: the 560px
   cap is GONE and the design's own rule applies, because the condition it was authored
   around — "in the design there is always a second panel beside this one" — is now
   true on the page as well. Nothing below is invented: it is the design's
   `.chumuk-acct__auth` transcribed onto the markup WooCommerce actually emits.
   ⚠️ WOO'S OWN WRAPPER IS THE GRID, NOT A NEW ELEMENT. Woo renders
   `div.u-columns.col2-set > div.u-column1.col-1 | div.u-column2.col-2`, which is the
   design's `.chumuk-acct__auth > .chumuk-panel` shape under different names. Styling
   those is the standing rule; replacing them would fork markup Woo maintains.
   ⚠️ WOO LAYS THOSE COLUMNS OUT WITH FLOATS AT 48%, stood down at plain class weight
   rather than beaten with `!important` — Woo's own are (0,2,0) and the theme's sheet
   loads last, so equal specificity wins on source order. Same route §10.210 used for
   the signed-in rail.
   ⚠️ THE CARDS STRETCH TO A COMMON HEIGHT because the design says `align-items:
   stretch` over a panel that is itself `display: flex; flex-direction: column`. Woo's
   heading sits OUTSIDE the form where the design's sits inside its panel, so here the
   COLUMN is the flex container and the form is the item that grows; the two cards then
   bottom-align even though Register carries two paragraphs of privacy copy and Login
   carries none. ⚠️ That heading position is a difference from the design and is NOT
   changed here — it was verified that way in the one-panel state (§10.210), and moving
   it is a restructure of a shipped page rather than a consequence of a settings
   change. Named in build report 92.
   🔴 `min( 340px, 100% )` AND NOT THE DESIGN'S BARE `340px`. Transcribed literally, the
   design's track floor overflowed the page by [MEASURED] 40px at 320 — a 340px column
   cannot sit in the 280px the gutter leaves, and `auto-fit` will not shrink below a
   fixed minimum. The design file never shows this because its own capture is of the
   band, not of a 320px viewport with this markup in it. `min()` keeps the 340px floor
   at every width that can hold it and lets the single column fall back to the
   container below that, which is what the design draws at 320 anyway. Caught by the
   overflow guard, not by reading. */
.chumuk-page--account .woocommerce > h2 {
	margin: 0 0 18px;
}

/* 🔴 WOO'S CLEARFIX PSEUDO-ELEMENTS ARE GRID ITEMS, AND THIS IS THE SECOND TIME.
   §10.210 found `.woocommerce::before/::after` (`content: " "; display: table`) each
   taking a real track the moment that element became a grid, which inverted the
   signed-in rail. `.col2-set` carries the same pair, and it did exactly the same thing
   here: [MEASURED] `::before` claimed row 1 column 1, so the Login column landed at
   x=734 in row 1 and the Register column wrapped to x=220 in row 2 — the two cards
   stacked diagonally.
   🔴 EVERY INSTRUMENT PASSED IT. Two forms, 486px each, correct widths, correct total,
   no overflow, one h1, one crumb, dupIds 0, and the design-diff count did not move by a
   single delta — because both panels are Woo's markup and carry no design-namespace
   class. **It was found by looking at the screenshot**, §4.13's fourth instance and the
   one the brief predicted for exactly this page. */
.chumuk-page--account:not( .chumuk-page--account-in ) .u-columns.col2-set::before,
.chumuk-page--account:not( .chumuk-page--account-in ) .u-columns.col2-set::after {
	content: none;
}

.chumuk-page--account:not( .chumuk-page--account-in ) .u-columns.col2-set {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( min( 340px, 100% ), 1fr ) );
	gap: clamp( 20px, 2vw, 32px );
	align-items: stretch;
}

.chumuk-page--account:not( .chumuk-page--account-in ) .col2-set .col-1,
.chumuk-page--account:not( .chumuk-page--account-in ) .col2-set .col-2 {
	float: none;
	inline-size: auto;
	display: flex;
	flex-direction: column;
}

.chumuk-page--account:not( .chumuk-page--account-in ) .woocommerce-form-login,
.chumuk-page--account:not( .chumuk-page--account-in ) .woocommerce-form-register {
	flex: 1 1 auto;
	background: var( --wp--preset--color--white );
	border-radius: var( --chumuk-card-radius );
	padding: clamp( 22px, 2.4vw, 34px );
	box-shadow: var( --chumuk-page-shadow );
	box-sizing: border-box;
}

/* The whole label is the target and it is held at 44px, so the 22px box is never
   the target on its own — the design's own note, and its measurement. */
.chumuk-page--account .woocommerce-form-login__rememberme {
	display: inline-grid;
	grid-template-columns: 22px minmax( 0, 1fr );
	gap: 14px;
	align-items: center;
	min-block-size: 44px;
	font-size: 15px;
	line-height: 1.55;
	cursor: pointer;
	box-sizing: border-box;
}

.chumuk-page--account .woocommerce-form-login__rememberme input {
	inline-size: 22px;
	block-size: 22px;
	margin: 0;
}

.chumuk-page--account .woocommerce-LostPassword {
	margin: 0;
	font-size: 15px;
}

/* --- the collapse --------------------------------------------------------
   The design collapses the shell at 900. ⚠️ THE RAIL BECOMES A SCROLLING STRIP
   RATHER THAN A STACK: six items stacked would push the content a screen down
   the page on a phone. */
@media ( max-width: 900px ) {
	.chumuk-page--account-in .woocommerce {
		grid-template-columns: minmax( 0, 1fr );
	}

	.chumuk-page--account .woocommerce-MyAccount-navigation ul {
		display: flex;
		gap: 8px;
		overflow-x: auto;
		padding-bottom: 4px;
	}

	.chumuk-page--account .woocommerce-MyAccount-navigation a {
		white-space: nowrap;
	}
}

/* 🔴 WOO HIDES THE ORDER NUMBER ON A PHONE, AND THAT IS A DEFECT.
   [MEASURED] at 320 the `#298` cell computes `display: none` with zero client
   rects: `woocommerce-smallscreen.css` declares `table.shop_table_responsive
   tbody th { display: none }`, and Woo renders the order number as a `<th>`. The
   rule is sound for the cart, where the row header is a product thumbnail that
   repeats the cell beside it. On the orders table it removes the only thing that
   says WHICH order the row is — a customer on a phone sees a date, a status and a
   total belonging to nothing.
   ⚠️ THIS IS THE ONE PLACE WOO IS OVERRULED, and it is done at equal specificity:
   Woo's selector is `.woocommerce-page table.shop_table_responsive tbody th`
   (0,2,3) and this is (0,2,3) too, winning on source order because the theme's
   sheet is the last of the thirteen. No `!important` and no added weight. */
@media ( max-width: 768px ) {
	.chumuk-page--account-in table.shop_table_responsive tbody th.woocommerce-orders-table__cell {
		display: block;
		padding-right: 0;
		text-align: end;
		border-bottom: 1px solid var( --chumuk-rule );
	}

	.chumuk-page--account-in .woocommerce-orders-table__cell-order-actions {
		padding-bottom: 0;
	}
}
