/*
Theme Name: Daylon
Theme URI: https://www.wp-web.daylonlabs.com
Description: Daylon's child theme of Ollie. This is where the client's own design tokens live — typography, palette, spacing — in theme.json. Ollie itself is never edited in place.
Author: Atelier
Template: ollie
Version: 1.1.1+20261106T210508Z-c0382a1f
Requires PHP: 8.1
Text Domain: daylon
*/

/*
Adding or removing a file in patterns/ needs no Version bump. WordPress caches the list of a
theme's pattern files under this Version, so deploy/deploy.sh appends a per-deploy stamp to it
on the host (DAY-121) and every deploy is registered from disk. Before that, DAY-19's new
patterns were deployed and invisible under 1.0.0 (comment 11179). Keep this line a single
`Version: x.y.z` — the deploy refuses to ship a header it cannot stamp.
*/

/*
Little CSS lives here on purpose (STANDARDS.md §2). The design system is theme.json; this file
holds what every page needs and theme.json cannot express, in two parts:

1. DAY-58's site-wide rules: the two-tone focus ring, the link underline offset, and tabular
   figures. All colours and durations are theme.json custom properties — nothing here is a raw
   value theme.json could have carried instead.
2. The chrome — header, menu panel, search, footer (DAY-34) — below the "chrome" banner. It was
   its own file, assets/css/chrome.css, until DAY-449: the two were enqueued on every page one
   right after the other, so they were one render-blocking request too many on every page
   (PERFORMANCE-BUDGET.md §2), and joining them in the same order changes no rule's place in
   the cascade.
*/

/* ---------------------------------------------------------------- the page container, DAY-362 */

/*
"Page container" spec v1 §2: one content box, at most 1280px wide and centred, with a side
gutter of 16px under 640px, 24px from 640px and 32px from 1024px. The numbers are written
once, in theme.json — `settings.layout` (the box) and `settings.custom.container` (the three
gutters and the reading column) — and the two breakpoints once, here. Nothing else in the
theme sets an outer width, an outer margin or a side padding of its own.

Two ways to sit in the box, both reading those values:

- A block template: theme.json hands `--daylon-gutter` to WordPress as the root padding, so
  every constrained group pads by the gutter and holds its children to the box. Content size
  and wide size are the same number on purpose — on this site there is one width, not two.
- Markup WordPress does not lay out (the header, the footer, the home page's sections):
  `padding-inline: var(--daylon-edge)` on a box as wide as the page. The background stays
  full-bleed and the content starts on the box's edge. ⚠️ The percentage is resolved where
  the property is used, so it is only right on a full-width box, or on something positioned
  against one. Not `100vw`: that counts the scrollbar, and the spec's width does not.
*/
:root {
	--daylon-gutter: var(--wp--custom--container--gutter--small);
	--daylon-edge: max(var(--daylon-gutter), calc((100% - var(--wp--style--global--wide-size)) / 2));
}

@media (min-width: 640px) {
	:root {
		--daylon-gutter: var(--wp--custom--container--gutter--medium);
	}
}

@media (min-width: 1024px) {
	:root {
		--daylon-gutter: var(--wp--custom--container--gutter--large);
	}
}

/*
Ollie's WooCommerce stylesheet lifts that cap from the title and the shortcode wrapper of the
account, cart and checkout pages (`max-width: 100%`, two classes): My account's title stood
at the gutter while every other page's stood on the box. One class more puts the box back.
*/
body.woocommerce-page .is-layout-constrained > :is(.wp-block-post-title, .woocommerce) {
	max-width: var(--wp--style--global--content-size);
}

/*
The one exception (§4): a page that is read — legal, help, Contacto. Its title stays on the
box's edge and its text is a column of at most 720px starting on that same edge, not centred:
a centred column moves the edge again, which is the defect this rule removes. Every page
that is not a WooCommerce screen (those carry `woocommerce-page`: cart, checkout, My account)
is a reading page; a block the client sets wide or full keeps what she chose (§5).

`!important` because core centres a constrained group's children with
`margin-left: auto !important`, and nothing short of it moves them. The margin is what core's
centring of the whole box would have given, so the column starts where the title does.
*/
body:not(.woocommerce-page) .wp-block-post-content.is-layout-constrained > :not(.alignwide, .alignfull, .alignleft, .alignright) {
	max-width: var(--wp--custom--container--reading);
	margin-left: max(0px, calc((100% - var(--wp--style--global--content-size)) / 2)) !important;
	overflow-wrap: break-word;
}

/* ---------------------------------------------------------------- links, DAY-28 v2 §4.3 */

/*
Underline at rest, everywhere: on the phone this shop is designed for there is no cursor
to discover a link with. theme.json's own `elements.link` sets the underline (so it also
reaches content the block editor renders); this file only adds the offset, which
theme.json's typography settings have no property for.

Chrome/nav/footer links already carry their own `text-decoration: none` in the chrome, below
(higher specificity, class selectors) — they stay exempt without anything special here,
per DAY-28 v2 §4.3: "Navigation and buttons are exempt — position and shape already say
what they are."
*/
a {
	text-underline-offset: 0.15em;
}

/*
WordPress core resets the underline specifically on post-title links —
:root :where(.wp-block-post-title a:where(:not(.wp-element-button))){text-decoration:none},
re-added only on :hover — which is what the product grid's card titles render with. Both that
rule and theme.json's `elements.link` sit inside `:where()`, so today's win is source order,
not specificity: nothing guarantees core keeps losing. Matched directly, with real specificity
((0,2,0), the same move as the focus ring below), instead of relied on to keep losing by luck.
On the mobile-first, no-cursor device this shop targets, a hover-only underline is no underline
at all (DAY-28 v2 §4.3).
*/
.wp-block-post-title a:not(.wp-element-button) {
	text-decoration: underline;
}

@media (prefers-reduced-motion: no-preference) {
	a {
		transition: color var(--wp--custom--motion--quick) var(--wp--custom--motion--easing);
	}
}

/* ---------------------------------------------------------------- the focus ring, DAY-28 v2 §7 */

/*
A two-tone ring — 2px `base` inner, 2px `main` outer — because no single colour in this
palette clears 3:1 on both the page's cream and the primary button's golden-bronze at once.
`box-shadow`, not `outline`, because an outline can only ever be one colour: two stacked
shadows with no blur paint two concentric rings instead.

`html body :focus-visible` alone is (0,1,2) — beaten by any WooCommerce component rule that
pairs the pseudo-class with even one class (e.g. `.wc-block-components-button:focus-visible`,
(0,2,0)): the class tier is compared before the element tier, and one class always outweighs
extra elements. DAY-28 v2 §7 says WooCommerce hard-codes its ring on block buttons — class-scoped
CSS by construction — so that loss is the common case, not an edge one.

The pseudo-class doubled — `:focus-visible:focus-visible`, valid CSS, matches the same elements
— adds a second class-tier point: (0,2,2). That structurally beats any single-class competitor
((0,2,0): class tier ties, element tier 2 > 0) without `!important`, which the scope forbids.
It still loses to a two-class competitor, which is why the quantity-stepper below is matched
explicitly rather than relied on to fall under this rule.
*/
html body :focus-visible:focus-visible {
	outline: none;
	box-shadow:
		0 0 0 2px var(--wp--preset--color--base),
		0 0 0 4px var(--wp--preset--color--main);
}

/*
Ollie's own quantity-stepper buttons set `box-shadow: none` on a plain `:focus` (not
`:focus-visible`) at a higher specificity than the rule above (two classes) — verified
live on staging, 2026-09-13: the rule exists and would otherwise cancel this ring on the
one control cart and checkout use it on most. Matched, not beaten with `!important`.
*/
html body .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button:focus-visible {
	outline: none;
	box-shadow:
		0 0 0 2px var(--wp--preset--color--base),
		0 0 0 4px var(--wp--preset--color--main);
}

/*
Forced colours (Windows high contrast) drop every box-shadow, and the two rules above set
`outline: none`: the ring vanished and nothing took its place, on every control of the site.
There the browser paints the system palette, so the two-tone reasoning does not apply — one
real outline in a system colour, at the specificities of the two rules it answers (DAY-399).
A rule elsewhere that draws its own ring and resets the outline carries its own answer, beside it.
*/
@media (forced-colors: active) {
	html body :focus-visible:focus-visible,
	html body .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button:focus-visible {
		outline: 2px solid CanvasText;
		outline-offset: 2px;
	}

	/* WooCommerce's checkbox and radio keep an outline of their own on `:focus`, above the rule
	   above — 1.5px and 1px. Without forced colours the ring is drawn around it; here that
	   hairline is all there is, so it is brought to the same 2px. */
	html body .wc-block-components-checkbox .wc-block-components-checkbox__input[type="checkbox"]:focus-visible,
	html body .wc-block-components-radio-control .wc-block-components-radio-control__input:focus-visible {
		outline: 2px solid CanvasText;
		outline-offset: 2px;
	}

	/* The quantity field between those two buttons: WooCommerce resets its outline on `:focus` at
	   (0,3,1), above the rule above, and marks it with an inset shadow — dropped too. Drawn
	   inwards: the stepper's buttons stand flush against it on both sides. */
	html body .wc-block-components-quantity-selector input.wc-block-components-quantity-selector__input:focus-visible {
		outline: 2px solid CanvasText;
		outline-offset: -2px;
	}
}

/*
The same mode replaces every background with the system's, and a filled button is drawn by its
background alone — theme.json fills `.wp-element-button` and gives it no border — so «Añadir»,
«Iniciar sesión», «Finalizar compra» and «Pagar» stood as loose words, with nothing to say they
were buttons or how far they reached (DAY-401). One border in a system colour gives the box back.
`.wp-element-button` is the class every filled button of the site carries, WooCommerce's
included — walked on staging: home, listing, product, cart, checkout, My account. The `:not()`
leaves out the outlined variation, which already draws its edge with an outline that survives
here, and lifts the rule above the `border: 0` those buttons set with one or two classes.
A control with no fill — an icon, a text button — loses nothing here and is left as it is.
*/
@media (forced-colors: active) {
	html body .wp-element-button:not(.is-style-outline > .wp-element-button) {
		border: 1px solid ButtonText;
	}
}

/* ---------------------------------------------------------------- the privacy note, DAY-503 */

/*
Privacy spec v3 §3: who holds her data, what for, her rights and where the policy is — printed
by daylon-core (includes/privacy/privacy-note.php) above the submit of the checkout, the
withdrawal form, registration and the account offer. Here, not in one page's stylesheet,
because those are four pages with three different stylesheets and the note is one component.
The field-hint token, nothing new (§3, Visual system v9): the small size and the text colour it
inherits. Plain text — no box, no colour, no icon.

§10: «on 320px the line spacing keeps [the link] above» a 24px target. At the small size the
hints' 1.4 line is 20px, so the note's line is 1.7 — 24.8px. Padding the link instead reached
24px too, but its focus ring then cut through the line above (staging, 320px, DAY-503).
*/
.daylon-privacy-note {
	margin-block: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.7;
}

/* Inside WooCommerce's classic forms (registration, withdrawal) every row is inset 3px
   (`.woocommerce form .form-row`); the note lines up with the labels and hints above it. */
.woocommerce-form-register .daylon-privacy-note,
.woocommerce-OrderWithdrawalForm .daylon-privacy-note {
	padding-inline: 3px;
}

/* «(se abre en una pestaña nueva)»: part of the link's name, not of what she sees (S5 notes).
   Its own rule: `.screen-reader-text` is not defined on every page the note is on. */
.daylon-privacy-note__hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* ---------------------------------------------------------------- tabular figures, DAY-28 v2 §5.5 */

/*
Every price, quantity and total — so a recalculation on tap does not shift a column
sideways (cart and checkout v4 §3.3). Applied to WooCommerce's own price/quantity
markup, which every page renders regardless of which Daylon template exists yet, plus
the product card's own price class.
*/
.woocommerce-Price-amount,
.wc-block-components-formatted-money-amount,
.wc-block-components-quantity-selector__input,
.quantity .qty,
.daylon-product-card__price {
	font-variant-numeric: tabular-nums;
}

/* ================================================================ chrome — header, menu panel, search, footer (DAY-34; assets/css/chrome.css until DAY-449) */

/*
 * Daylon — header, navigation and footer (DAY-34).
 *
 * Breakpoint: 1024px, per DAY-33 §2 — the flat six-category nav only measures out
 * at 1024px (Elena's arithmetic in DAY-9 §10.1); 768–1023px gets the compact header
 * too, not the desktop one DAY-9 originally assumed.
 *
 * Tokens come from theme.json (STANDARDS.md §7 — no raw hex/px when a preset
 * exists). DAY-58 lands DAY-28 v2's two-tone focus ring and state colours; the
 * placeholder --primary/--base ring this file used before that (a single colour,
 * named here so the swap would be a find/replace) is replaced below.
 */

/* ---------------------------------------------------------------- focus, everywhere */

/*
The site-wide two-tone ring (style.css) already reaches every `a` and `button` in the
header, the menu panel and the footer — nothing header-specific is needed for
`:focus-visible` any more. What stays here is the one control that needs a PLAIN
`:focus`, not `:focus-visible`:
*/

/* The close control is focused by OUR OWN script the moment the panel opens (DAY-33
   §4.1), including when opening was a tap or a click — a browser's :focus-visible
   heuristic hides the ring on a pointer-triggered programmatic focus() call, which is
   exactly the gap DAY-28 flagged and Tomás's FAIL 2 caught: the first tab stop landed
   with no visible ring. A plain :focus rule guarantees it shows whenever this specific
   control is focused, however it got there — same two-tone ring as everywhere else. */
.daylon-menu-panel__close:focus {
	outline: none;
	box-shadow:
		0 0 0 2px var(--wp--preset--color--base),
		0 0 0 4px var(--wp--preset--color--main);
}

/* Forced colours drop the shadow: a real outline in a system colour, as in style.css — on the
   same plain :focus, for the same reason. */
@media (forced-colors: active) {
	.daylon-menu-panel__close:focus {
		outline: 2px solid CanvasText;
		outline-offset: 2px;
	}
}

/* ---------------------------------------------------------------- focus never under a fixed bar */

/* WCAG 2.2, 2.4.11 Focus Not Obscured (DAY-21). Everything fixed to the bottom of the viewport
   is counted: the cookie banner (`--daylon-consent-offset`, set by daylon-core's consent.js
   while it is open) or, once she has chosen, the "Preferencias de cookies" pill that replaces
   it (`--daylon-consent-reopen-offset`, same file), plus the bar standing under the pill or on
   top of the banner (`--daylon-bottom-bar`, set by cart-checkout.js and product.js while one
   shows). Each is absent — so 0 — otherwise, and a focused control the browser scrolls into
   view lands clear of all of them. */
html {
	scroll-padding-bottom: calc(var(--daylon-consent-offset, 0px) + var(--daylon-consent-reopen-offset, 0px) + var(--daylon-bottom-bar, 0px));
}

/* The same rule at the top (DAY-361): the header is pinned there, and nothing kept room for it.
   WooCommerce's checkout calls scrollIntoView() on the first invalid field and aligns it to
   the top edge — measured at top: 0, under the header — and an in-page anchor or a Shift+Tab
   towards the top lands the same way. An error she cannot see is an order she does not place.

   The height is the header's own, published by chrome.js on every page
   (`--daylon-header-height`): it follows the reader's font size, the logo, and the second row
   the open search takes below 1024px. Until that script has run the measured heights stand in
   — 66px compact, 102px from 1024px — so an anchor followed on arrival is clear too. 8px on
   top of it, so the site's focus ring (4px outwards, style.css) is not cut by the header's
   edge. The admin bar counts wherever the header leaves room for it. The 102px and the
   admin bar's exception are further down, in the media queries that change the header itself.

   `html:root`, not `html`: WordPress's admin-bar stylesheet sets this same property on `html`
   for a signed-in view, and which of the two loads last is not ours to rely on. */
html:root {
	scroll-padding-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--daylon-header-height, 66px) + 8px);
}

/* Scroll-padding cannot scroll past the end of the document: while the banner or the pill
   shows, the last controls on the page ("Realizar el pedido", the footer's links) would stay
   under it. The page grows by that height, and only while one of them shows. */
body {
	padding-block-end: calc(var(--daylon-consent-offset, 0px) + var(--daylon-consent-reopen-offset, 0px));
}

/* A word longer than its line breaks inside the line instead of pushing the page sideways
   (WCAG 1.4.10, DAY-633). With text at 400% at 320px, «Devoluciones» in the announcement bar
   and the category heading's words were wider than their boxes. `break-word`, not `anywhere`:
   it acts only when a word cannot fit a line on its own, and leaves every box's intrinsic size
   alone — at 100% and 200% no box on the page moves (measured at 320, 375 and 1280). */
body {
	overflow-wrap: break-word;
}

/* ---------------------------------------------------------------- announcement bar */

/* DAY-33 §3.0 / §9.0 (DAY-104): one line of text above the header, not sticky, no script. It
   is absent in the corridor because it is never rendered there (inc/chrome.php), not hidden —
   unless the shop has a notice to give, which the bar then carries on every page (DAY-333). */
.daylon-announcement {
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--primary-accent);
	color: var(--wp--preset--color--main);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.4;
	text-align: center;
}

.daylon-announcement__text {
	margin: 0;
}

/* Below 360px the line does not fit on one row at x-small (measured: ~324px of text in
   ~304px). Rather than shrink the text or cut a fact in half, each fact takes its own row. */
@media (max-width: 359px) {
	.daylon-announcement__fact {
		display: block;
	}

	.daylon-announcement__sep {
		display: none;
	}
}

/* ---------------------------------------------------------------- the bar's second content: the shop's notice */

/* DAY-335, «Site notice banner» spec v2 §9–§11. The notice is the owner's text, up to 240
   characters: it wraps, entire, and the band's height is whatever the text needs — never a
   fixed height, never a scroll of its own. No colour of its own either: the bar's tokens
   (`main` on `primary-accent`, measured 13.3:1). The measure is capped where the band is wide
   (§10), and one unbroken run of characters breaks rather than pushing the page sideways. */
.daylon-announcement--notice {
	position: relative;
}

.daylon-announcement__notice {
	max-width: 75ch;
	margin-inline: auto;
	overflow-wrap: anywhere;
}

/* The close control is in the markup `hidden`, and stays out of the page unless the dismissal
   script is running (`daylon-notice-closable` on <html>, set in the head before the band is
   parsed — assets/js/notice-dismissal.js). No JavaScript, no control (§9 state 9); cart and
   checkout never print it. */
.daylon-announcement__close {
	position: absolute;
	inset-block-start: 0;
	inset-inline-end: 0;
	display: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: transparent;
	border: 0;
	border-radius: 0;
	color: inherit;
	cursor: pointer;
}

.daylon-notice-closable .daylon-announcement__close {
	display: inline-flex;
}

/* With the control showing, the band is at least as tall as its 44px, so the control can never
   hang over the header, and the text keeps clear of it (§9 state 7). At 320px the room is
   taken from the control's side only — every pixel of measure is a line saved — and from 768px
   from both sides, so the text is centred in the band and not in what the control left. */
.daylon-notice-closable .daylon-announcement--notice {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding-inline-end: 44px;
}

@media (min-width: 768px) {
	.daylon-notice-closable .daylon-announcement--notice {
		padding-inline-start: 44px;
	}
}

/* The site's two-tone ring is drawn outside the control (style.css), and this control sits in
   the page's top corner: two of its sides would be drawn off the screen. Same two tones, same
   widths, drawn inwards. The selector repeats style.css's doubled pseudo-class to outrank it. */
html body .daylon-announcement__close:focus-visible:focus-visible {
	outline: none;
	box-shadow:
		inset 0 0 0 2px var(--wp--preset--color--main),
		inset 0 0 0 4px var(--wp--preset--color--base);
}

/* Forced colours drop the shadow: a real outline in a system colour, still drawn inwards. */
@media (forced-colors: active) {
	html body .daylon-announcement__close:focus-visible:focus-visible {
		outline: 2px solid CanvasText;
		outline-offset: -2px;
	}
}

/* Dismissed in this session: the bar goes back to its standing line — never a hole (§2). The
   line is printed `hidden` behind the notice; an author `display` outranks the browser's own
   `[hidden]` rule, which is all that attribute is, so it is shown and read again. */
.daylon-notice-dismissed .daylon-announcement__notice {
	display: none;
}

.daylon-notice-dismissed .daylon-announcement__standing {
	display: block;
}

/* ---------------------------------------------------------------- header shell */

/* The header template part's own wrapper (`<header class="wp-block-template-part">`) is
   exactly as tall as what it holds, and a sticky element can only stick inside its parent —
   so the header used to scroll away with the page (measured on staging: 152px above the top
   after a 600px scroll). Taking the wrapper out of the box tree makes the whole page the
   header's scroll container, and lets the announcement bar above it scroll away first
   (§3.3) whatever its height. */
.wp-block-template-part:has(> .daylon-header) {
	display: contents;
}

.daylon-header {
	position: sticky;
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: 40;
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--40);
	min-height: 56px;
	/* The ground runs edge to edge; the first and the last control sit on the page
	   container's edges (style.css, "Page container" spec §3). */
	padding: var(--wp--preset--spacing--30) var(--daylon-edge);
	background: var(--wp--preset--color--base);
	border-bottom: 1px solid var(--wp--preset--color--border-light);
}

/* Product page spec §2.1b rule 2 (v31, DAY-617): a header that does not fit stops being pinned.
   chrome.js sets `is-unpinned` while the header is taller than 25 % of the viewport's height —
   text at 400 % on 320×568 makes it 173px, 30 % of the screen. It is then an ordinary block at
   the top of the page that scrolls away and comes back by scrolling up; content, size and tab
   order are untouched, and it switches with the viewport, never with scroll. A condition on the
   measured height rather than a rem media query, because a rem query follows the browser's text
   setting but not `html { font-size }`, and the header's 44px targets do not scale with either.
   `relative`, not `static`: it keeps z-index 40 for the clothing disclosure and is still the
   containing block of the open search field below 1024px. */
.daylon-header.is-unpinned {
	position: relative;
}

/* The group's flow layout gives every child after the first a block-start margin, which in a
   row only pushes the nav and the utilities below the logo's line. */
.daylon-header > * {
	margin-block: 0;
}

.daylon-header__bar {
	display: flex;
	align-items: center;
}

/* The logo already on the site — the triangle over DAYLON (DECISIONS.md 2026-09-17), sized
   here rather than by the block's own width, so the Site Editor copy of this part (which
   saved it at 149px) renders at the same size. */
.daylon-wordmark {
	flex-shrink: 0;
	margin: 0;
	line-height: 0;
}

.daylon-wordmark img {
	width: 48px;
	height: auto;
}

.daylon-header__utility {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	margin-left: auto;
}

/* Every header control: 44x44 minimum target (DAY-9 §11, DAY-33 §3.1). How far apart is the
   compact bar's own section, below. */
.daylon-menu-toggle,
.daylon-cart-link,
.wp-block-search__button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	background: transparent;
	border: none;
	color: var(--wp--preset--color--main);
	cursor: pointer;
}

.daylon-cart-link {
	position: relative;
	text-decoration: none;
}

/* Every glyph is centred in its 44x44 target (header spec §3.1), and on its own drawing, not
   on its 24-unit canvas (DAY-483). Two things kept the row off one line. An inline SVG stands
   on the text baseline, which left the menu, the magnifier, the person and the bag 3px above
   the centre while the heart, a block already (favourites.css), sat on it: as blocks they all
   do. And two drawings are not centred in their own canvas — the heart's runs from 6 to 20.5,
   the bag's from 3 to 20 — so each moves by what it is off, in canvas units, at whatever size
   it is drawn. `translate`, not `transform`: the favourite control's pulse owns that one. */
.daylon-menu-toggle svg,
.daylon-search__toggle svg,
.daylon-account-link--bar svg,
.daylon-cart-link svg {
	display: block;
}

.daylon-favourites-link__icon svg {
	translate: 0 calc(-1.25 / 24 * 100%);
}

.daylon-cart-link__icon svg {
	translate: 0 calc(0.5 / 24 * 100%);
}

.daylon-cart-link__badge {
	position: absolute;
	top: 2px;
	right: 2px;
	min-width: 16px;
	padding: 0 4px;
	border-radius: 999px;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.6;
	text-align: center;
}

/* ---------------------------------------------------------------- desktop primary nav */

.daylon-flat-nav {
	display: none;
}

.daylon-primary-nav {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--40);
	margin: 0;
	padding: 0;
	list-style: none;
}

.daylon-primary-nav a {
	color: var(--wp--preset--color--main);
	text-decoration: none;
	white-space: nowrap;
}

.daylon-primary-nav a:hover {
	color: var(--wp--preset--color--primary);
}

.daylon-primary-nav__item--clothing {
	position: relative;
	display: flex;
	align-items: center;
}

/* The disclosure control is separate from the "Ropa" link (DAY-33 §3.2 — two
   adjacent actions, never merged into one ambiguous control). */
.daylon-clothing-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: flex-start;
	min-width: 44px;
	min-height: 44px;
	/* The ▾ belongs to its word: 8px from "Ropa", not centred in a 44px target 24px away
	   (DAY-324). The target keeps its 44px and spends the rest on the far side, over the
	   nav's own gap, so the next item is no further away than any other. */
	margin-inline-end: calc(-1 * var(--wp--preset--spacing--40));
	padding: 0 0 0 8px;
	background: transparent;
	border: none;
	color: var(--wp--preset--color--main);
	cursor: pointer;
}

/* The state change is visible through the arrow's direction, never through
   colour alone (DAY-33 §3.2). */
.daylon-clothing-toggle__icon {
	display: inline-block;
}

.daylon-clothing-toggle[aria-expanded="true"] .daylon-clothing-toggle__icon {
	transform: rotate(180deg);
}

@media (prefers-reduced-motion: no-preference) {
	.daylon-clothing-toggle__icon {
		transition: transform var(--wp--custom--motion--quick) var(--wp--custom--motion--easing);
	}
}

.daylon-clothing-disclosure {
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 45;
	min-width: 12rem;
	margin-top: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--base);
	/* `border`, not `border-light`: on the white header the light one read as no edge. */
	border: 1px solid var(--wp--preset--color--border);
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}

.daylon-clothing-disclosure[hidden] {
	display: none;
}

/* The hover region is one piece: the word, the ▾ and the panel (header spec v16
   §4.1a, DAY-255). The panel's margin leaves a strip between the item and the
   panel where the pointer would otherwise be outside both; this invisible
   bridge spans that margin and the top border, so a straight drop into the
   panel never counts as leaving. It paints nothing and belongs to the panel,
   so it exists only while the panel is open. */
.daylon-clothing-disclosure::before {
	content: "";
	position: absolute;
	right: -1px;
	bottom: 100%;
	left: -1px;
	height: calc(var(--wp--preset--spacing--20) + 1px);
}

.daylon-clothing-disclosure ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Each row is a 44px target (DAY-9 §11), like every other header control. */
.daylon-clothing-disclosure a {
	display: flex;
	align-items: center;
	min-height: 44px;
	color: var(--wp--preset--color--main);
	text-decoration: none;
	white-space: nowrap;
}

.daylon-clothing-disclosure a:hover {
	color: var(--wp--preset--color--primary);
}

/* ---------------------------------------------------------------- shop-nav (panel + footer) */

.daylon-shop-nav {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--40);
	margin: 0;
	padding: 0;
	list-style: none;
}

.daylon-shop-nav a {
	color: var(--wp--preset--color--main);
	text-decoration: none;
	white-space: nowrap;
}

.daylon-shop-nav a:hover {
	color: var(--wp--preset--color--primary);
}

/* Clothing's categories, nested under it (§4.2, §8 — "visually and
   programmatically grouped," a plain list, never a second disclosure). */
.daylon-shop-nav__children {
	margin: var(--wp--preset--spacing--20) 0 0;
	padding: 0 0 0 var(--wp--preset--spacing--40);
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	width: 100%;
}

/* ---------------------------------------------------------------- search */

.daylon-search {
	display: flex;
	align-items: center;
}

/* The gap separates the toggle from the field, so it exists only while both show:
   on a collapsed field it was a 7px footprint of its own (DAY-248). At >=1024 and
   on the 404 the toggle is display: none, and a gap next to nothing is no gap. */
.daylon-search.is-open {
	gap: var(--wp--preset--spacing--20);
}

.daylon-search__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	background: transparent;
	border: none;
	color: var(--wp--preset--color--main);
	cursor: pointer;
}

/* Two classes and an attribute (0,3,0), on every rule for this field: Ollie's
   `input:not([type="submit"]):not([type="radio"])` is (0,2,1) and sets border,
   padding, radius, font-size and box-shadow, so a plain `.daylon-search__field`
   (0,1,0) lost every property the two share. DAY-247 claimed back the border
   colour; DAY-248 claims back the rest of what is declared here — padding and
   the collapsed state's border-width, which left the "collapsed" field ~31px
   wide at 320. Specificity alone, no !important, not load order. What this file
   does not declare (radius, font-size, box-shadow at rest) stays Ollie's on
   purpose: a new look for the field is Dana's call, not a side effect. */
.daylon-search .daylon-search__field[type="search"] {
	min-height: 44px;
	padding: 0 var(--wp--preset--spacing--30);
	/* border, not border-dark (DAY-28 v7 §4.2): this is a control boundary, and
	   border-dark is reserved for an emphatic rule, not an input's edge. */
	border: 1px solid var(--wp--preset--color--border);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--main);
	/* Compact: collapsed until the toggle opens it (chrome.js adds .is-open). A
	   flex item's default min-width is "auto" (content-based), which silently
	   wins over an explicit width: 0 — min-width: 0 is what actually lets it
	   collapse (caught via browser_responsive's 320px overflow). */
	min-width: 0;
	width: 0;
	padding-left: 0;
	padding-right: 0;
	border-width: 0;
	opacity: 0;
}

.daylon-search.is-open .daylon-search__field[type="search"] {
	width: 12rem;
	padding-left: var(--wp--preset--spacing--30);
	padding-right: var(--wp--preset--spacing--30);
	border-width: 1px;
	opacity: 1;
}

/* ---------------------------------------------------------------- account link */

.daylon-account-link--flat {
	display: none;
}

/* ---------------------------------------------------------------- compact bar: account and favourites */

/* Header spec v19 §3.1 (DAY-350), in the order of DAY-412. Below 1024px the bar is menu ·
   wordmark · search · favourites · account · cart, in that order in the DOM too: these two
   links are the bar's own, printed between the search and the desktop row's favourites and
   account, which stay hidden here — and these are hidden there. Exactly 44x44, the glyph
   centred, nothing drawn at rest. */
.daylon-account-link--bar,
.daylon-favourites-link--bar {
	position: relative;
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	color: var(--wp--preset--color--main);
	text-decoration: none;
}

/* Never filled in the bar (§3.1): a filled heart means "this garment is saved", and the bar is
   not about one garment. Said here as well as in favourites.css, so the outline does not
   depend on a second stylesheet having loaded. */
.daylon-favourites-link--bar svg {
	fill: none;
}

/* The page she is on (§3.1): a 2px bar under the glyph, inside the link's own box and clear of
   the focus ring drawn around its edge. A border rather than a background, so it is still
   there in forced colours; `aria-current` says the same to a screen reader. */
.daylon-account-link--bar[aria-current="page"]::after,
.daylon-favourites-link--bar[aria-current="page"]::after {
	content: "";
	position: absolute;
	bottom: 6px;
	left: 50%;
	width: 20px;
	border-bottom: 2px solid var(--wp--preset--color--primary);
	transform: translateX(-50%);
}

/* ---------------------------------------------------------------- mobile menu panel */

.daylon-menu-panel {
	position: fixed;
	inset: 0;
	z-index: 50;
	overflow-y: auto;
	background: var(--wp--preset--color--base);
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
}

.daylon-menu-panel[hidden] {
	display: none;
}

html.daylon-menu-open,
body.daylon-menu-open {
	overflow: hidden;
}

/* The "Preferencias de cookies" pill (daylon-core, consent.css) is fixed above everything at
   the bottom left, the panel included, and sat on the panel's last entries (DAY-338). It steps
   out while the panel is open: `visibility` takes it out of the tab order and the
   accessibility tree as well, and leaves `hidden` — its "no choice made yet" state — to
   consent.js. The class is only ever set below 1024px, where the toggle exists. */
.daylon-menu-open .daylon-consent-reopen {
	visibility: hidden;
}

.daylon-menu-panel__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	margin-left: auto;
	background: transparent;
	border: none;
	font-size: 1.25rem;
	cursor: pointer;
}

.daylon-menu-panel .daylon-shop-nav--panel {
	flex-direction: column;
	gap: var(--wp--preset--spacing--40);
	margin-top: var(--wp--preset--spacing--50);
	font-size: var(--wp--preset--font-size--medium);
}

/* «Envíos y devoluciones» is a plain row at Favoritos' rung, with no «Ayuda» heading over it:
   a heading over a single link groups nothing (header spec v36 §4.2, DAY-650). Same box as the
   Favoritos row below it — 44px tall — and the space above it is the one the heading opened. */
.daylon-menu-panel__link {
	display: flex;
	align-items: center;
	min-height: 44px;
	margin-top: var(--wp--preset--spacing--60);
	color: var(--wp--preset--color--main);
	text-decoration: none;
}

.daylon-account-link--panel {
	display: block;
	margin-top: var(--wp--preset--spacing--60);
}

/* The row is the link inside the block's wrapper, and it is Favourites' peer (header spec §4.2):
   same 44px target, same colour, no underline. Styled on the wrapper only, theme.json's link
   style (primary, underlined, and `:root :where(a…):hover`) reached the <a>, and the block's own
   CSS left it 32px tall and its 0.5em padding set the word 8px in from Favourites' (DAY-652).
   Two classes outrank those global rules in every state; the focus ring stays the site's
   `:focus-visible` one. */
.daylon-account-link--panel .wc-block-customer-account__link,
.daylon-account-link--panel .wc-block-customer-account__link:hover {
	display: flex;
	align-items: center;
	min-height: 44px;
	padding: 0;
	color: var(--wp--preset--color--main);
	text-decoration: none;
}

/* ---------------------------------------------------------------- footer */

/* Cream from edge to edge; the columns start on the page container's edge (style.css). */
.daylon-footer {
	padding: var(--wp--preset--spacing--60) var(--daylon-edge);
	background: var(--wp--preset--color--main-accent);
}

/* `minmax(0, 1fr)`, not `1fr`, at every width: a bare `1fr` track is never narrower than its
   widest unbreakable content, and with text at 200 % at 320 the script below (10rem = 320px)
   and the longest links held all four groups at 339px, 35px past the screen (DAY-603, WCAG
   1.4.10). */
.daylon-footer__groups {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--wp--preset--spacing--50);
}

.daylon-footer__heading {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-weight: 600;
}

.daylon-footer .daylon-shop-nav--footer {
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
}

.daylon-footer__group ul {
	margin: 0;
	padding: 0;
	list-style: none;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
}

/* Beats the generic ".daylon-footer__group ul" rule above on specificity
   (two classes vs. one class + tag) without !important, so the nested
   category list still reads as grouped under "Ropa" (§8). */
.daylon-footer__group .daylon-shop-nav__children {
	margin-top: var(--wp--preset--spacing--20);
	padding-left: var(--wp--preset--spacing--40);
}

.daylon-footer__group a {
	color: var(--wp--preset--color--main);
	text-decoration: none;
}

/* «Preferencias de cookies» in the Legal list (header/footer spec §8a, §8a.1; DAY-658). A button,
   because it opens the consent preferences and goes nowhere, but it reads as one more legal item:
   the browser's button look goes and it takes its neighbours' type and colour. It tells itself
   apart from «Política de cookies» by what it is announced as, not by style. Its `<li>` is
   `hidden` in the markup and consent.js reveals it: without the script there is nothing to
   withdraw, and a button that does nothing would be a dead control. */
.daylon-footer__button {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	letter-spacing: inherit;
	color: var(--wp--preset--color--main);
	text-align: start;
	cursor: pointer;
}

/* Every footer link is a 44px target ("Desistimiento online" spec v2 §5, §6 — the footer is a
   door to the withdrawal form on every page; DAY-314). They measured 26px, one text line. The
   height comes from the link itself, so the lists' own gap goes: 44px rows already stand apart. */
.daylon-footer__group li > :is(a, button) {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	/* A link longer than the column wraps inside its own 44px box instead of widening the
	   column: «Abrigos y chaquetas» at 200 % text is wider than a 320 screen. In the footer the
	   shop nav's `nowrap` (above) gives way for the same reason (DAY-603). */
	max-width: 100%;
	overflow-wrap: anywhere;
	white-space: normal;
}

.daylon-footer__group ul,
.daylon-footer .daylon-shop-nav--footer,
.daylon-footer__group .daylon-shop-nav__children {
	gap: 0;
}

.daylon-footer__group .daylon-shop-nav__children {
	margin-top: 0;
}

/* `main`, not `secondary`: the footer's ground is `main-accent`, and secondary on it measured
   4.47:1 on staging — under the 4.5:1 its 18.64px regular text needs (DAY-21, WCAG 1.4.3). The
   palette has no step between the two, and the accent is adjusted before the rule is. */
.daylon-footer__brand {
	margin: 0;
	color: var(--wp--preset--color--main);
}

/* «Vestir con calma» (DAY-33 §8, §9.2a; DAY-104), beside the brand line. Decorative and
   aria-hidden: the brand line above it stays the words a screen reader reads. Drawn like the
   hero's phrase — outlines of Allura (Copyright 2010 The Allura Project Authors, SIL Open Font
   License 1.1, which binds the font software, not artwork made with it; no font file ships),
   repeated glyphs drawn once and reused: 4.7 KB inline, no request. */
.daylon-footer-script {
	display: block;
	width: 10rem;
	max-width: 100%;
	height: auto;
	margin-top: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--primary);
}

/* The shop's networks, under the brand line (DAY-348, "Footer social links" spec v2 §3, §4). The
   list is the footer's own — the `.daylon-footer__group ul` and `li > a` rules above already
   give it the other groups' link style and 44px rows. The space above belongs to this block and
   not to the group: with no address the block is not printed, and it must leave no gap. */
.daylon-footer__social {
	margin-top: var(--wp--preset--spacing--40);
}

/* A label, not a heading: quieter than the groups' headings by weight and size. `main` like the
   brand line, for the reason given there — `secondary` on this ground is 4.47:1, and this text
   is smaller still. */
.daylon-footer__social-label {
	margin: 0;
	color: var(--wp--preset--color--main);
	font-size: var(--wp--preset--font-size--small);
}

/* The customer-service chat line (DAY-376, «Daylon — WhatsApp links (UX spec)» v2 §4, §7, §9):
   a quiet paragraph, the lead-in in the secondary tone and then the link, on the product page,
   three help pages, the cart, the checkout and the order-received page. It is here, in the one
   stylesheet every page loads, because it has no page of its own.

   The space above belongs to the line and not to what precedes it: with no chat address the
   line is not printed, and it must leave no gap. `p.` so it also wins over the block gap a
   layout container gives its children. 1rem keeps it more than the 12px §9 asks from the button
   it follows in the cart, even where nothing else stands between them.

   The link is a 44px target by its own height, not by a larger font (§9). A flex row that wraps,
   so at 320 the link may take a line of its own (§7) and its box stays in one piece — an inline
   link broken across two lines is two targets, neither of them 44px. The link keeps the theme's
   link style and the site-wide two-tone focus ring (style.css). */
p.daylon-whatsapp-chat {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	column-gap: 0.35em;
	margin-block: var(--wp--preset--spacing--40) 0;
	color: var(--wp--preset--color--secondary);
	text-align: start;
}

.daylon-whatsapp-chat__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

/* In the checkout the terms tick follows the line directly, and its box starts 8px under the
   link (measured on staging at 320): this brings it past the 12px §9 asks between controls. */
.wc-block-checkout__form > p.daylon-whatsapp-chat {
	margin-block-end: var(--wp--preset--spacing--20);
}

.daylon-footer__payments {
	display: flex;
	/* Four marks since DAY-781: at 320 they do not fit one line. They wrap whole, never inside
	   one — «Klarna desde 80 €» is one mark, and «80» must not part from «€». */
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	margin-top: var(--wp--preset--spacing--60);
	/* Same ground, same 4.47:1 as the brand line above — and smaller text. */
	color: var(--wp--preset--color--main);
	font-size: var(--wp--preset--font-size--x-small);
}

.daylon-footer__payment-mark {
	white-space: nowrap;
}

/* ---------------------------------------------------------------- breakpoints */

/* The compact bar's geometry — the numbers Tomás measures. The gaps are header spec v19 §3.1
   (DAY-350); the side padding is the page container's gutter since DAY-362 ("Page container"
   spec v1 §3), which is what moved the row's arithmetic at 320:

     width      | side padding | menu → wordmark | between the four icons | wordmark → search
     320–359    | 16           | 4               | 4                      | 4 at 320, and growing
     360–639    | 16           | 16              | 8                      | 20 at 360, and growing
     640–1023   | 24           | 16              | 8                      | growing

   ⚠️ The gaps are px on purpose, not the spacing presets: those are rem, and at 320 the row is
   full to the pixel (16 + 44 + 4 + 48 + 4 + 4 × 44 + 3 × 4 + 16 = 320). A preset that grows
   with the reader's font size would push a 44px icon off a screen that has no room to give,
   and the targets are px already. The gutter does not shrink to make room (container spec
   §6), so at 320 the 8px the wider gutter takes came out of the two gaps beside the wordmark.
   A wider wordmark or gap is a new decision (§3.1), not a tweak here.

   The free space is the utility group's `margin-left: auto`; the bar's own gap is its floor. */
@media (max-width: 1023px) {
	.daylon-header {
		gap: 16px;
	}

	.daylon-header__utility {
		gap: 8px;
	}

	/* The open field does not fit beside the bar's six controls, at any compact width: at
	   12rem it pushed the menu to x = -47 and the cart to x = 330 at 320px (DAY-249), and with
	   account and favourites in the row there is no room up to 1023px either (§5, v18). It
	   takes a second row instead, full width, inside the header: the header grows by one
	   control-height plus a gap and pushes the page down, so it overlays nothing and the six
	   controls keep exactly their closed positions. Absolute against the sticky header rather
	   than a wrapping row, because the field sits inside the utility group and the form — only
	   leaving the flow gets it out of them without dropping the form's search landmark. */
	.daylon-header:has(.daylon-search.is-open) {
		padding-bottom: calc(var(--wp--preset--spacing--30) + 44px + var(--wp--preset--spacing--20));
	}

	.daylon-search.is-open .daylon-search__field[type="search"] {
		position: absolute;
		right: var(--daylon-edge);
		bottom: var(--wp--preset--spacing--30);
		left: var(--daylon-edge);
		width: auto;
	}

	/* Six stops, in the order she sees them (§3.1). The collapsed field is 0px wide but was
	   still a tab stop between search and favourites: focus went somewhere with nothing to show
	   for it. Until the toggle opens it, it is out of the tab order and the accessibility
	   tree; the toggle beside it names what it does. Only in the bar: the 404's own search is
	   never collapsed. */
	.daylon-header .daylon-search:not(.is-open) .daylon-search__field[type="search"] {
		visibility: hidden;
	}

	/* Focus is drawn inside each of the six stops (§3.1): the site's ring grows 4px outwards
	   (style.css), and at 320 the next icon starts 4px away and would cover it. Same two
	   tones, same widths, drawn inwards — the dark one as an outline, because an inset shadow
	   is painted under the link's content and the wordmark's image fills its link. The
	   selector repeats style.css's doubled pseudo-class to outrank it. */
	html body .daylon-header :is(.daylon-menu-toggle, .daylon-wordmark a, .daylon-search__toggle, .daylon-account-link--bar, .daylon-favourites-link--bar, .daylon-cart-link):focus-visible:focus-visible {
		outline: 2px solid var(--wp--preset--color--main);
		outline-offset: -2px;
		box-shadow: inset 0 0 0 4px var(--wp--preset--color--base);
	}
}

/* 320 to 359: the one width where the icons stand 4px apart instead of 8, and the wordmark
   4px from its neighbours instead of 16 (§3.1, and the table above). The targets stay 44x44
   and never overlap. */
@media (max-width: 359px) {
	.daylon-header {
		gap: 4px;
	}

	.daylon-header__utility {
		gap: 4px;
	}
}

@media (min-width: 768px) {
	.daylon-footer__groups {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Below 600px WordPress's admin bar scrolls away with the page, so a signed-in view must not
   leave a gap for it above the pinned header. */
@media (max-width: 600px) {
	.daylon-header {
		top: 0;
	}

	html:root {
		scroll-padding-top: calc(var(--daylon-header-height, 66px) + 8px);
	}
}

@media (min-width: 1024px) {
	.daylon-menu-toggle,
	.daylon-menu-panel,
	.daylon-header__bar {
		display: none;
	}

	/* Three regions — logo | centred nav | utilities (DAY-33 §3.2, DAY-92 layout note). The
	   side columns share what is left equally, so the nav sits on the row's centre; the DOM,
	   and with it the tab order, stays logo → nav → search → favourites → account → cart. */
	.daylon-header {
		display: grid;
		grid-template-columns: 1fr auto 1fr;
	}

	.daylon-wordmark {
		justify-self: start;
	}

	/* 88 × 80 from here up, one size (DAY-394, "Header: desktop wordmark size" spec §3): the
	   largest that still leaves the 1024 row its margin for a longer label. Both sides are
	   set, as the image's `width` and `height` say (inc/logo.php), so the box is 88 × 80
	   before the file arrives and if it never does; `contain` keeps the mark's own
	   proportions inside it. */
	.daylon-wordmark img {
		width: 88px;
		height: 80px;
		object-fit: contain;
	}

	/* The taller logo makes a taller header — 80 + the row's padding + its border: what stands
	   in until chrome.js has measured it. */
	html:root {
		scroll-padding-top: calc(var(--wp-admin--admin-bar--height, 0px) + var(--daylon-header-height, 102px) + 8px);
	}

	.daylon-header__utility {
		justify-self: end;
		margin-left: 0;
	}

	/* Two rows when the one does not fit (header spec §3.2a, DAY-636). Enlarged text grows the
	   three regions, not the viewport, so neither a px nor an em media query can say when the
	   row is full (`html { font-size: 200% }` moves neither): chrome.js measures the regions at
	   their natural widths (`is-measuring`, below) and sets `is-two-rows` when they do not fit.
	   Row 1 is the wordmark and the nav, centred in what the wordmark leaves; row 2 the
	   utilities, right-aligned. That is the DOM's order, so reading order and Tab order stay the
	   same list. At 100 % text it never fires — 1024px has ≈40px to spare — and the rules above
	   are the header, untouched. */
	/* The rows stand the small step apart, not the columns' gap: what is not spent between them
	   keeps the header under the 25 % that unpins it (§3.3) — at 200 % on 1280×900 it is ~24 %
	   with the column gap, the threshold's edge. The step is still twice the focus ring's 4px. */
	.daylon-header.is-two-rows {
		grid-template-columns: auto minmax(0, 1fr);
		row-gap: var(--wp--preset--spacing--20);
	}

	.daylon-header.is-two-rows .daylon-flat-nav {
		justify-self: center;
		min-width: 0;
	}

	/* Beyond 200 % the rows may wrap inside themselves, never clip (§3.2a): the nav between its
	   items, the utilities onto a third line. Each item wraps whole — "Ropa" and its ▾ are one
	   item, and every icon carries its badge inside its own box (§6). */
	.daylon-header.is-two-rows .daylon-primary-nav {
		flex-wrap: wrap;
		justify-content: center;
	}

	.daylon-header.is-two-rows .daylon-header__utility {
		grid-column: 1 / -1;
		flex-wrap: wrap;
		justify-content: flex-end;
	}

	/* The measure chrome.js takes, for as long as one synchronous read lasts — never painted:
	   one unwrapped row, every region at its natural width, whichever layout is showing. */
	.daylon-header.is-measuring {
		display: flex;
	}

	.daylon-header.is-measuring > * {
		flex: none;
		width: max-content;
	}

	.daylon-header.is-measuring :is(.daylon-primary-nav, .daylon-header__utility) {
		flex-wrap: nowrap;
	}

	/* The count stands beside the icon, never on it (DAY-324): it starts past the icon's own
	   right edge and grows away from it, so "1", "9" and "10" all leave the stroke alone.
	   Favourites' badge is this one, in favourites.css.
	   The disc is measured in the count's own em, so enlarged text grows the disc with the
	   figure instead of spilling past it (DAY-637): at 12px text that is the 18px it always was.
	   It grows rightwards and down, away from the icon, so DAY-324 holds at any size. */
	.daylon-cart-link__badge {
		top: 2px;
		right: auto;
		left: calc(50% + 9px);
		box-sizing: border-box;
		min-width: 1.5em;
		padding: 0 5px;
		font-size: 0.75rem;
		font-weight: 600;
		line-height: 1.5;
	}

	.daylon-flat-nav {
		display: block;
	}

	.daylon-account-link--flat {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}

	/* The compact bar's two icons: the desktop row has its own favourites and account. */
	.daylon-account-link--bar,
	.daylon-favourites-link--bar {
		display: none;
	}

	/* Flat header (DAY-33 §5): the field is permanently open and the toggle
	   button is redundant — same markup as compact, no second component and
	   no !important, because both states live in this theme's own classes. */
	.daylon-search__toggle {
		display: none;
	}

	.daylon-search .daylon-search__field[type="search"] {
		width: 12rem;
		padding-left: var(--wp--preset--spacing--30);
		padding-right: var(--wp--preset--spacing--30);
		border-width: 1px;
		opacity: 1;
	}

	.daylon-footer__groups {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}
