/*
 * VNM CHROME — masthead, footer, page-title band and the design-token repair
 * that the rest of it stands on.   A2 / hub#4279, part of #4277.
 * =============================================================================
 *
 * §0. THE ACTUAL ROOT CAUSE (measured, 2026-08-11, dev.vania-novikau.me)
 * -----------------------------------------------------------------------------
 * The brief for this lane said the identity was lost because `theme_mods_solutech`
 * (73 entries) was never migrated to `arneiron-child`. That is true of the LOGO
 * and of nothing else. The type scale, the fonts, the page background and the
 * vertical rhythm are all broken by one different mechanism, and it is worth
 * writing down because it will happen again on the next tenant:
 *
 *   WordPress does NOT merge theme.json preset ARRAYS between a parent and a
 *   child. WP_Theme_JSON::merge() replaces them wholesale, per family. The child
 *   declares its own `color.palette`, `typography.fontSizes`,
 *   `typography.fontFamilies`, `color.gradients` and `spacing.spacingSizes`, so
 *   every parent slug the child does not re-declare is DELETED — 41 of them,
 *   enumerated by tools/token-audit.py.
 *
 *   The parent's style layer keeps referencing them. `theme.json` still emits
 *   `h1{font-family:var(--wp--preset--font-family--ui);font-size:var(--wp--preset--font-size--3-xl)}`
 *   and `ds.css` still opens with `body{background:var(--c-bg);font-family:var(--wp--preset--font-family--ui)}`
 *   where `--c-bg: var(--wp--preset--color--base)`. Both `ui` and `3-xl` and
 *   `base` are now undefined, so those declarations are invalid at computed-value
 *   time and simply do not apply. There is no error, nothing goes red, and every
 *   byte of both files is correct.
 *
 *   MEASURED CONSEQUENCES on dev before this file:
 *     h1            18px  (inherits body; the parent's size token is gone)
 *     h4            38px  (lands on the CHILD's `lg`, so h4 == h2 and h4 > h3)
 *     every heading + body renders in "Times New Roman" — the *initial* family,
 *                   because `--wp--preset--font-family--ui` is undefined. Jost is
 *                   downloaded, declared, and never used.
 *     body          background transparent, not the intended page colour
 *     main          margin-top 0, because `--wp--preset--spacing--6` is gone —
 *                   this is the "content starts hard against the header"
 *
 * §1 below re-declares the deleted slugs, mapped onto VNM's palette. That single
 * block repairs the type scale, the fonts, the page surface, the spacing rhythm
 * AND the whole `--c-*` bridge in ds.css, without touching theme.json — which
 * belongs to another lane and must not be edited from here.
 *
 * ACCESSIBILITY DEVIATION FROM THE REFERENCE (deliberate, stated):
 * prod paints white text on the brand purple #8888ea. That is 3.11:1 and fails
 * WCAG AA (1.4.3 needs 4.5:1 for body-sized text). Every white-on-brand surface
 * in this file therefore uses #5b5bd6 — the `brand-aa` swatch the child's own
 * theme.json already ships for this purpose — which measures 5.37:1. #8888ea is
 * kept for decorative fills that carry no text. This is the one place this file
 * does not reproduce prod, and it is on purpose.
 *
 * SCOPE: every selector here is either a `--vnm-*`/`--wp--preset--*` declaration
 * on :root, a `.vnm-*` class this lane owns, or a heading/element rule that is
 * repairing a value the parent already tried to set. Nothing here targets a
 * class owned by L1/L2/L3 or by A1/A3.
 */

/* =============================================================================
 * §1. RESTORE THE 41 PARENT PRESET SLUGS THE CHILD'S theme.json DELETED
 * =========================================================================== */

:root {
	/* ---- colour ---------------------------------------------------------
	 * Neutral ramp values are the parent's originals (they are greys; inventing
	 * new ones would be design work nobody asked for). The semantic slots that
	 * carry brand meaning — accent, link — are re-pointed at VNM's purple, in
	 * its AA-passing form because those two are precisely the ones that end up
	 * under white text.
	 *
	 * `bg`/`base` are WHITE, and that is a considered departure from prod, where
	 * body is #020202. On solutech the page content sits inside an opaque white
	 * container, so a black body only shows around the edges. arneiron has no
	 * such container: `main` is transparent. Copying prod's value literally would
	 * put this site's black body text on a black page. The VNM dark is applied
	 * here where it belongs — to the chrome — and the content sheet stays white,
	 * which is what prod LOOKS like even though it is not what prod SAYS.
	 */
	--wp--preset--color--bg:              #ffffff;
	--wp--preset--color--base:            #ffffff;
	--wp--preset--color--base-2:          #eceef2;
	--wp--preset--color--surface-2:       #f1f1f6;
	--wp--preset--color--surface-3:       #e6e6ef;
	--wp--preset--color--border:          #dcdce7;
	--wp--preset--color--border-strong:   #bcbcd0;
	--wp--preset--color--ink-2:           #444444;  /* pixtheme_font_color */
	--wp--preset--color--ink-3:           #777777;
	--wp--preset--color--muted:           #777777;
	--wp--preset--color--subtle:          #777777;
	--wp--preset--color--contrast:        #000000;
	--wp--preset--color--contrast-2:      #020202;  /* background_color */
	--wp--preset--color--on-surface:      #000000;
	--wp--preset--color--accent:          #8888ea;  /* exam parity 2026-09-13 (was brand-aa #5b5bd6 for AA); white-on-it is 3.11:1 */
	--wp--preset--color--accent-strong:   #4a49c0;  /* 6.99:1 on white */
	--wp--preset--color--on-accent:       #ffffff;
	--wp--preset--color--accent-contrast: #ffffff;
	--wp--preset--color--link:            #8888ea;  /* exam parity 2026-09-13 (was brand-aa #5b5bd6) */
	--wp--preset--color--link-hover:      #4a49c0;
	--wp--preset--color--success:         #3f7a4a;
	--wp--preset--color--warning:         #8a5a1f;
	--wp--preset--color--danger:          #9a3535;

	/* ---- font family ----------------------------------------------------
	 * VNM is a Jost site: `pixtheme_font`, `pixtheme_title_font`,
	 * `pixtheme_subtitle_font`, `pixtheme_buttons_font` and `pixtheme_link_font`
	 * are all "Jost", and prod's computed body family is Jost. The parent's four
	 * generic family slots therefore all resolve to Jost except `display`, which
	 * is the one place the child's MuseoModerno belongs, and `mono`, which must
	 * stay an actual monospace — the child's `rubik-mono-one` is a display face
	 * whose CSS fallback merely says "monospace", and routing <code> at it would
	 * be a regression dressed as a brand.
	 */
	--wp--preset--font-family--ui:      var(--wp--preset--font-family--jost);
	--wp--preset--font-family--sans:    var(--wp--preset--font-family--jost);
	--wp--preset--font-family--prose:   var(--wp--preset--font-family--jost);
	--wp--preset--font-family--display: var(--wp--preset--font-family--museomoderno, var(--wp--preset--font-family--jost));
	--wp--preset--font-family--mono:    ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

	/* ---- font size ------------------------------------------------------
	 * VNM's scale is geometric: base 18px, ratio 1.2 (`pixtheme_font_size 18`,
	 * `pixtheme_font_ratio 1.2`), which prod's own engine confirms — a bare
	 * probe heading there measures 44.8 / 37.33 / 31.1 / 25.92 / 21.6 / 18.
	 * 18*1.2^4 = 44.8 exactly.
	 *
	 * `--2xl` / `--3xl` (no hyphen before the digit) are ALSO defined because
	 * blocks.css asks for them in that spelling. Those two have never existed:
	 * WordPress emits the slug `2xl` as `--wp--preset--font-size--2-xl`, so those
	 * references were dead in the parent theme long before this port. Defining
	 * both spellings is one line and repairs a latent parent defect; it is
	 * reported upstream rather than left silently patched here.
	 */
	--wp--preset--font-size--2-xl: 37.33px;
	--wp--preset--font-size--2xl:  37.33px;
	--wp--preset--font-size--3-xl: var(--vnm-fs-h1);
	--wp--preset--font-size--3xl:  var(--vnm-fs-h1);
	--wp--preset--font-size--4-xl: 53.76px;

	/* ---- gradients (parent originals; neutral, no brand hue) ------------ */
	--wp--preset--gradient--fade-up:       linear-gradient(0deg, #eceef2 0%, #ffffff 100%);
	--wp--preset--gradient--fade-down:     linear-gradient(180deg, #ffffff 0%, #eceef2 100%);
	--wp--preset--gradient--surface-sheen: linear-gradient(135deg, #ffffff 0%, #f6f7f9 100%);
	--wp--preset--gradient--hairline:      linear-gradient(90deg, transparent, #dcdce7, transparent);

	/* ---- spacing --------------------------------------------------------
	 * The child renumbered the spacing scale to 10..80; the parent's 0..9 are
	 * consumed by ds.css, blocks.css, woocommerce.css, four block stylesheets and
	 * the page templates (`main{margin-top:var(--wp--preset--spacing--6)}`).
	 * Restored to the parent's own values — this is the vertical rhythm.
	 */
	--wp--preset--spacing--0: 0;
	--wp--preset--spacing--1: 2px;
	--wp--preset--spacing--2: 4px;
	--wp--preset--spacing--3: 8px;
	--wp--preset--spacing--4: 12px;
	--wp--preset--spacing--5: 16px;
	--wp--preset--spacing--6: 24px;
	--wp--preset--spacing--7: 32px;
	--wp--preset--spacing--8: 48px;
	--wp--preset--spacing--9: 64px;

	/* ---- this lane's own tokens ---------------------------------------- */
	/* Floor is 38px, not the 34px this first shipped with: h2 is pinned at a flat
	   38px in the child's theme.json, so a fluid h1 with a 34px floor renders
	   SMALLER than h2 below ~600px. Measured at 414px: h1 34 / h2 38. A scale that
	   inverts on phones is the same defect this lane exists to fix, one breakpoint
	   further along. */
	--vnm-fs-h1:      clamp(38px, 2.4vw + 24px, 44.8px);
	--vnm-chrome-bg:  #000000;   /* pixtheme_header_background: black */
	--vnm-page-ink:   #020202;   /* background_color */
	--vnm-on-dark:    #ffffff;
	--vnm-on-dark-2:  #c9c9dd;
	--vnm-brand:      #8888ea;   /* pixtheme_style_settings_main_color — decorative */
	--vnm-brand-aa:   #5b5bd6;   /* the same brand, at AA, wherever text sits on it */
	--vnm-brand-aa-h: #4a49c0;
	--vnm-header-h:   123px;     /* pixtheme_general_settings_logo_height */
	--vnm-gutter:     clamp(20px, 5vw, 70px);
	--vnm-lip:        26px;
	--vnm-chrome-veil: rgba(0, 0, 0, 0.2); /* prod .pix-header background */
}

/* =============================================================================
 * §2. TYPE SCALE
 * -----------------------------------------------------------------------------
 * Only the two levels that are demonstrably broken are set here.
 *
 *   h1 — had NO font-size at all (its token was deleted) and rendered at the
 *        inherited 18px. This is the single most visible symptom in #4279.
 *   h4 — resolves to the child's redefined `lg` (38px), which makes it equal to
 *        h2 and larger than h3. A scale that goes 38 / 20 / 38 is not a scale.
 *
 * h2 (38px) and h3 (20px/500) are LEFT ALONE. They are set deliberately in the
 * child's theme.json, with a recorded rationale, and they belong to another lane.
 *
 * RESIDUAL, stated rather than hidden: because h3 is pinned to a component size
 * (20px card titles) rather than a scale step (31.1px on prod), h3–h6 land on a
 * 20/20/18/14 plateau instead of a ratio. The real fix is to give h3 back its
 * scale step and move 20px onto the card-title selector — that is a theme.json
 * change and is not this lane's to make.
 * =========================================================================== */

:root h1 {
	font-size: var(--vnm-fs-h1);
	line-height: 1.4;
	font-weight: 700;
}

:root h4 {
	font-size: 20px;
	line-height: 1.4;
	font-weight: 600;
}

/* Headings inherit Jost through the restored `ui` slot; body copy keeps
   `pixtheme_font_line_height: 1.8`, which the child's theme.json already sets. */

/* =============================================================================
 * §3. MASTHEAD
 * =========================================================================== */

.vnm-header {
	background: var(--vnm-chrome-bg);
	color: var(--vnm-on-dark);
	font-family: var(--wp--preset--font-family--jost);
}

.vnm-header__inner {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--6);
	min-height: var(--vnm-header-h);
	padding-inline: var(--vnm-gutter);
	margin-inline: auto;
	max-width: 1720px;
}

.vnm-header__brand {
	display: flex;
	align-items: center;
	flex: 0 0 auto;
	text-decoration: none;
	color: inherit;
}

.vnm-header__logo {
	width: 123px;
	height: 123px;
	max-height: calc(var(--vnm-header-h) - 8px);
	object-fit: contain;
	display: block;
}

.vnm-header__wordmark {
	font-size: 28px;
	font-weight: 700;
	letter-spacing: -0.01em;
}

.vnm-header__nav {
	flex: 1 1 auto;
	display: flex;
	justify-content: center;
}

.vnm-header__nav ul {
	display: flex;
	align-items: center;
	gap: clamp(18px, 2.2vw, 34px);
	margin: 0;
	padding: 0;
	list-style: none;
}

.vnm-header__nav a {
	display: inline-block;
	padding: 6px 0;
	color: var(--vnm-on-dark);
	font-size: 18px;
	font-weight: 500;
	text-decoration: none;
	border-bottom: 2px solid transparent;
	transition: color .15s ease, border-color .15s ease;
}

.vnm-header__nav a:hover,
.vnm-header__nav a:focus-visible {
	color: var(--vnm-brand);
}

/* The current page is marked with a rule AND aria-current, so the state is not
   carried by colour alone (WCAG 1.4.1). */
.vnm-header__nav a.is-current {
	border-bottom-color: var(--vnm-brand);
}

.vnm-header__actions {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 12px;
}

/*
 * SHAPED FROM THE REFERENCE, not invented. solutech's header button is
 * `a.pix-button.pix-h-s.pix-v-s`; measured on the surviving install
 * (exam.vania-novikau.me) it is 83x38 — `padding: 9px 18px`, `border-radius: 4px`,
 * `1px solid transparent`, `font: 500 18px/18px Jost`. Ours was a 94x40 PILL:
 * `border-radius: 100px`, `padding: 10px 26px`, `17px/20.4px`. The pill was the
 * conspicuous part — the reference is a barely-rounded rectangle.
 *
 * The transparent 1px border is load-bearing rather than decoration: it is what
 * makes 9 + 18 + 9 + 2 come to 38, so a bordered variant of the same button
 * cannot change size.
 *
 * COLOUR IS THE REFERENCE'S: `--pix-main-color` (#8888ea) with
 * `--pix-main-color-lighter-2x` (#A0A0FF) on hover, which is what solutech's
 * `.pix-button` / `.pix-button:hover` resolve to — both confirmed live.
 *
 * An earlier pass substituted `--vnm-brand-aa` (#5b5bd6) here because white on
 * #8888ea measures 3.11:1, under WCAG AA's 4.5:1 for normal text. That is still
 * true and is worth knowing, but it is a brand call and the brand colour is the
 * one that ships. Noted rather than acted on.
 */
.vnm-header__login {
	display: inline-block;
	padding: 9px 18px;
	border: 1px solid transparent;
	border-radius: 4px;
	background: var(--pix-main-color, #8888ea);
	color: #fff;
	font-size: 18px;
	font-weight: 500;
	line-height: 1;
	text-decoration: none;
	transition: background .15s ease;
}

.vnm-header__login:hover,
.vnm-header__login:focus-visible {
	background: var(--pix-main-color-lighter-2x, #A0A0FF);
	color: #fff;
}

/* BODY BASE — exam parity, measured 2026-09-13 ( 18px Jost 400 was already
   right ). ds.css's generic body rule shares specificity ( 0-0-1 ) with the
   global-styles body rule and loads AFTER it, so the parent's --c-ink / 1.6
   clobbered theme.json's ink-soft / 1.8 on every page. Declared here — chrome
   loads after ds — with the shim's own tokens. */
body {
	color: var(--wp--preset--color--ink-2, #444444);
	line-height: 1.8;
}

/* ---- mobile disclosure: no JavaScript, so it cannot fail to initialise ---- */
.vnm-header__state { position: absolute; opacity: 0; pointer-events: none; }

.vnm-header__burger {
	display: none;
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	margin: 0;              /* a <button> since 2026-09-13: kill UA + inherited label margins so the glyph stays on the row's centre */
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	appearance: none;
	margin-inline-start: auto;
	cursor: pointer;
	position: relative;
}

.vnm-header__burger span,
.vnm-header__burger span::before,
.vnm-header__burger span::after {
	position: absolute;
	left: 10px;
	width: 24px;
	height: 2px;
	background: var(--vnm-on-dark);
	content: "";
	transition: transform .2s ease, opacity .2s ease;
}

.vnm-header__burger span { top: 21px; }
.vnm-header__burger span::before { left: 0; top: -7px; }
.vnm-header__burger span::after  { left: 0; top: 7px; }

@media (max-width: 899px) {
	.vnm-header__inner {
		flex-wrap: wrap;
		align-items: center;   /* explicit: every control (brand, actions, burger) on the row's vertical centre, as on the exam reference */
		min-height: 72px;
		gap: 12px;
		padding-block: 10px;
	}

	.vnm-header__logo { width: 56px; height: 56px; }

	.vnm-header__burger { display: block; order: 3; }

	.vnm-header__actions { order: 2; margin-inline-start: auto; }

	/* Reference at 390: 71x36, `padding: 8px 15px`, `font: 500 16px/18px`. Ours
	   was 79x35 on 20px of inline padding. */
	.vnm-header__login { padding: 8px 15px; font-size: 16px; line-height: 18px; }

	.vnm-header__nav {
		order: 4;
		flex-basis: 100%;
		display: none;
	}

	.vnm-header__state:checked ~ .vnm-header__nav { display: block; }

	.vnm-header__nav ul {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		padding-bottom: 8px;
	}

	.vnm-header__nav a {
		padding: 12px 2px;
		border-bottom: 1px solid rgba(255, 255, 255, .12);
	}

	.vnm-header__nav a.is-current {
		border-bottom-color: var(--vnm-brand);
	}

	.vnm-header__state:checked ~ .vnm-header__burger span { background: transparent; }
	.vnm-header__state:checked ~ .vnm-header__burger span::before { transform: translateY(7px) rotate(45deg); }
	.vnm-header__state:checked ~ .vnm-header__burger span::after  { transform: translateY(-7px) rotate(-45deg); }
}

/* ---- the mobile utility row (ArneIron balance / account / cart) ---------- */
.vnm-utilitybar { display: none; }

@media (max-width: 899px) {
	.vnm-utilitybar {
		display: block;
		background: var(--vnm-page-ink);
		color: var(--vnm-on-dark-2);
	}

	.vnm-utilitybar__inner {
		display: flex;
		align-items: center;
		justify-content: flex-end;
		gap: 16px;
		min-height: 40px;
		padding-inline: var(--vnm-gutter);
		font-size: 14px;
	}

	.vnm-utilitybar__inner:empty { display: none; }
	.vnm-utilitybar__inner a { color: inherit; }
}

/* =============================================================================
 * §4. PAGE-TITLE BAND
 * -----------------------------------------------------------------------------
 * Prod puts every page title in a black band under the header: 44.8px/600 white,
 * centred, ~140px tall, with the white content sheet starting below it on a
 * rounded lip. dev renders the same title as 18px black text flush against the
 * header, which is most of what "reads as stock arneiron" means in #4279.
 *
 * Full-bleed is done with box-shadow + clip-path rather than `width:100vw`,
 * because 100vw includes the scrollbar and would add a horizontal scrollbar to
 * every page on a desktop browser.
 *
 * The front page is excluded: L3's templates/front-page.html emits a
 * deliberately screen-reader-only <h1>, and giving that a 140px black band would
 * put a title bar above a hero that is designed not to have one.
 * =========================================================================== */

:root h1.wp-block-post-title:not(.screen-reader-text),
:root h1.wp-block-query-title,
:root h1.woocommerce-products-header__title,
:root h1.page-title {
	position: relative;
	margin: calc(-1 * var(--wp--preset--spacing--6)) 0 var(--wp--preset--spacing--8);
	padding: clamp(20px, 2vw, 29px) var(--vnm-gutter) calc(clamp(20px, 2vw, 29px) + var(--vnm-lip));
	background: var(--vnm-chrome-bg);
	box-shadow: 0 0 0 100vmax var(--vnm-chrome-bg);
	clip-path: inset(0 -100vmax);
	color: var(--vnm-on-dark);
	text-align: center;
	font-size: var(--vnm-fs-h1);
	font-weight: 600;
	line-height: 1.4;
}

/* The lip below is absolutely positioned 100vmax past each edge so it reaches
   the viewport. `clip-path` is a PAINT clip and does not clip scrollable
   overflow, so without this the band added 1360px of horizontal scroll to every
   page — measured: the /shop/ document went 1440px -> 2800px wide the first time
   this shipped. `overflow-x: clip` on core's site wrapper removes it. `clip`
   rather than `hidden` on purpose: `hidden` would make this element a scroll
   container and break `position: sticky` for anything inside it. */
:root .wp-site-blocks {
	overflow-x: clip;
}

/* the white sheet's rounded lip, spanning the viewport */
:root h1.wp-block-post-title:not(.screen-reader-text)::after,
:root h1.wp-block-query-title::after,
:root h1.woocommerce-products-header__title::after,
:root h1.page-title::after {
	content: "";
	position: absolute;
	left: -100vmax;
	right: -100vmax;
	bottom: 0;
	height: var(--vnm-lip);
	background: var(--wp--preset--color--bg);
	border-radius: var(--vnm-lip) var(--vnm-lip) 0 0;
}

/* A title inside a post card is not a page title. `.wp-block-post-title` is
   emitted for every product and post tile too — those are h2/h3 and are excluded
   by the h1 in the selector, but state it explicitly so a future level change
   does not silently paint a black band inside a product grid. */
:root h2.wp-block-post-title,
:root h3.wp-block-post-title {
	background: none;
	box-shadow: none;
	clip-path: none;
	padding: 0;
	color: inherit;
}

/* WooCommerce prints its breadcrumb immediately BEFORE the archive title, and
   the two then fight: the band's -24px top margin (which exists to close the
   gap `main{margin-top:var(--wp--preset--spacing--6)}` opens under the header)
   lands the band on top of the breadcrumb, and the breadcrumb's own grey renders
   on black. Reordering is not available — `main` is a constrained block layout,
   not a flex container, and turning it into one to move one line would change
   how every child of every template is sized.
   prod hides breadcrumbs outright (`pixtheme_tab_hide: hide_breadcrumbs`, and no
   breadcrumb appears on any prod page), so this follows the reference. Stated
   plainly because it is a small navigational loss, not a pure win. */
:root .woocommerce-breadcrumb,
:root .wc-block-breadcrumbs {
	display: none;
}

/* =============================================================================
 * §5. FOOTER
 * =========================================================================== */

.vnm-footer {
	background: var(--vnm-page-ink);
	color: var(--vnm-on-dark-2);
	font-family: var(--wp--preset--font-family--jost);
	padding: clamp(40px, 4vw, 64px) var(--vnm-gutter) clamp(20px, 2vw, 28px);
	margin-top: clamp(48px, 6vw, 96px);
}

.vnm-footer__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: clamp(24px, 4vw, 48px);
	max-width: 1300px;
	margin-inline: auto;
}

.vnm-footer__card {
	display: flex;
	/* Top-aligned, not centred: the mark sits level with the name rather than
	   floating 34px down beside a taller text column (measured at 1400px). This
	   is also what the reference does — solutech's `.pix-footer-horizontal-card`
	   (single.css:5970) is `align-items: start`. */
	align-items: flex-start;
	/* 25px is the reference's own `.pix-footer-horizontal-card` column-gap. */
	gap: 25px;
	flex: 1 1 380px;
	min-width: 0;
}

.vnm-footer__mark {
	width: 140px;
	height: auto;
	flex: 0 0 auto;
}

:root .vnm-footer__name {
	margin: 0 0 8px;
	color: var(--vnm-on-dark);
	font-size: 20px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: .4px;
	text-transform: none;
	/* prod ships this one at 700 while the child's theme.json sets h3 to 500;
	   the child's own note flags exactly this element as the residual. Set it
	   here rather than moving the global h3 weight for one string.
	   ⚠ 2026-08-29: §21 later added `:root h2, :root h3 { font-weight: 600 }`
	   (0-1-1), which OUTRANKS a bare `.vnm-footer__name` (0-1-0) — measured
	   600 on the deployed image while this 700 sat here looking applied. The
	   `:root` prefix above restores it at 0-2-0. §21 is the reference's value
	   for a GENERIC h3; this element is the documented exception. */
}

.vnm-footer__roles,
.vnm-footer__desc {
	margin: 0 0 6px;
	font-size: 16px;
	line-height: 1.6;
}

.vnm-footer__roles { color: var(--vnm-brand); }
.vnm-footer__desc  { color: var(--vnm-on-dark-2); }

.vnm-footer__social {
	display: flex;
	flex-wrap: wrap;
	/* the reference's `.pf-social` is `display:flex; gap:16px`. */
	gap: 16px;
	margin: 14px 0 0;
	padding: 0;
	list-style: none;
}

/* -----------------------------------------------------------------------------
 * The reference's pill, ported verbatim from `solutech` single.css:
 *
 *   .pf-social a        48x48, radius 50%, background rgba(90,40,160,.4),
 *                       colour #fff, font-size 20px, transition .3s,
 *                       box-shadow rgba(138,43,226,.2) 0 0 10px
 *   .pf-social a:hover  background rgba(138,43,226,.8),
 *                       box-shadow rgba(138,43,226,.6) 0 0 20px,
 *                       transform translateY(-2px)
 *
 * What was here before was a 38px transparent circle with a hairline border —
 * an invention, not a port, and it rendered the glyphs as bare coloured dots on
 * the starfield. Read off the reference with getComputedStyle at rest AND on
 * :hover, plus the matched CSSRule text, so both states are the reference's.
 *
 * The reference marks every declaration `!important`; those are it fighting its
 * own anchor styling and are dropped here — this sheet already loads after the
 * chrome it would need to beat, and the values measure identical without them.
 *
 * `font-size: 20px` is the reference's icon-FONT sizing (its glyph is an <i>).
 * Here the glyph is an inline <svg>, so the equivalent is an explicit 20x20 box
 * below; the anchor's font-size would not reach it.
 * -------------------------------------------------------------------------- */
.vnm-footer__social a {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background: rgba(90, 40, 160, .4);
	color: var(--vnm-on-dark);
	text-decoration: none;
	box-shadow: 0 0 10px rgba(138, 43, 226, .2);
	transition: .3s;
}

.vnm-footer__social a:hover,
.vnm-footer__social a:focus-visible {
	background: rgba(138, 43, 226, .8);
	box-shadow: 0 0 20px rgba(138, 43, 226, .6);
	transform: translateY(-2px);
	color: #fff;
}

.vnm-footer__social svg { display: block; width: 20px; height: 20px; }
.vnm-footer__social i { display: block; font-size: 20px; line-height: 1; }

.vnm-footer__cta { flex: 0 1 auto; }

.vnm-footer__lambo {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	padding: 12px 28px 12px 12px;
	border-radius: 100px;
	border: 1px solid var(--vnm-brand);
	background: rgba(136, 136, 234, .10);
	color: var(--vnm-on-dark);
	font-size: 18px;
	font-weight: 500;
	text-decoration: none;
	transition: background .15s ease, box-shadow .15s ease;
}

.vnm-footer__lambo img {
	width: 120px;
	height: auto;
	flex: 0 0 auto;
}

.vnm-footer__lambo:hover,
.vnm-footer__lambo:focus-visible {
	background: rgba(136, 136, 234, .22);
	box-shadow: 0 0 24px rgba(136, 136, 234, .35);
	color: var(--vnm-on-dark);
}

.vnm-footer__copy {
	max-width: 1300px;
	margin: clamp(28px, 3vw, 48px) auto 0;
	padding-top: 18px;
	border-top: 1px solid rgba(255, 255, 255, .10);
	/* Measured on the reference: 14px / rgba(255,255,255,.6) / uppercase /
	   letter-spacing 1px / line-height 1.8 (25.2px at 14px). The ratio is
	   stored rather than the computed 25.2px so the leading survives a size
	   change. Was 15px, rgb(201,201,221), no transform, no tracking. */
	color: rgba(255, 255, 255, .6);
	font-size: 14px;
	line-height: 1.8;
	letter-spacing: 1px;
	text-transform: uppercase;
	text-align: center;
}

@media (max-width: 720px) {
	.vnm-footer__inner { flex-direction: column; align-items: flex-start; }
	/* flex-basis is the MAIN axis, and the main axis is now vertical: leaving
	   `flex: 1 1 380px` on the card reserved 380px of height and opened ~150px of
	   dead space above the lambo button. Measured at 414px. */
	/* Mark and name/roles share the top line; desc and socials run the FULL card
	   width beneath them.
	   `.vnm-footer__desc` and `.vnm-footer__social` are nested inside
	   `.vnm-footer__text`, so they cannot span the card on their own. Grid plus
	   `display: contents` on that wrapper promotes its four children to grid
	   items of the card, which is what lets the last two take `1 / -1`. No
	   markup change and nothing moves in the DOM, so the reading order and the
	   desktop layout are untouched.
	   `flex: 0 1 auto` still has to stay even though the card is now a grid:
	   `.vnm-footer__inner` above is a COLUMN flex container here, so the card is
	   its flex ITEM and flex-basis is the vertical axis — the original
	   `1 1 380px` reserved 380px of height (see the note above). */
	.vnm-footer__card {
		flex: 0 1 auto;
		display: grid;
		grid-template-columns: auto minmax(0, 1fr);
		column-gap: 16px;
		row-gap: 10px;
		align-items: start;
	}
	.vnm-footer__text { display: contents; }
	.vnm-footer__mark  { grid-column: 1; grid-row: 1 / span 2; align-self: start; }
	.vnm-footer__name  { grid-column: 2; grid-row: 1; }
	.vnm-footer__roles { grid-column: 2; grid-row: 2; }
	.vnm-footer__desc  { grid-column: 1 / -1; }

	/* One row of six, at any phone width. 6 x 48px = 288px of icons plus five
	   gaps needs 328px; a 320px-wide screen gives the card only 280px, so with
	   fixed 48px circles and nowrap the last icon was pushed 48px past the row
	   and CLIPPED — invisibly, because `.wp-site-blocks` is `overflow-x: clip`,
	   so the page never gained a scrollbar to hint at it. Measured: overflow 8px
	   at 360px, 48px at 320px.
	   The icons therefore have to be the thing that gives. `flex: 0 1 48px` lets
	   them shrink below their basis, `max-width` stops them growing past the
	   design size on wider phones, and `aspect-ratio` keeps them circular at
	   whatever width they land on. */
	.vnm-footer__social {
		grid-column: 1 / -1;
		flex-wrap: nowrap;
		justify-content: space-between;
		gap: 8px;
	}
	.vnm-footer__social > li { flex: 0 1 48px; min-width: 0; }
	.vnm-footer__social a {
		width: 100%;
		max-width: 48px;
		height: auto;
		aspect-ratio: 1;
	}
	.vnm-footer__cta  { flex: 0 0 auto; }
	.vnm-footer__mark { width: 96px; }
	.vnm-footer__lambo { padding-right: 22px; font-size: 16px; }
	.vnm-footer__lambo img { width: 84px; }
}

/* The parent's own empty footer block is still emitted by templates that were
   not overridden; give it no height rather than 49px of blank white under the
   real footer. */
.wp-block-arneiron-footer:empty { display: none; }

/* =============================================================================
 * §9. UTILITY-ROW CHIP LABELS                            (added 2026-08-13)
 * -----------------------------------------------------------------------------
 * DEFECT: the account chip renders
 *     <a aria-label="Log in"><span …__icon>👤</span><span …__screen>Log in</span></a>
 * and the parent declares the label class as an EMPTY rule —
 *     arneiron/assets/css/ds.css:618 declares .arneiron-account-toggle__screen
 *     with no declarations at all — the braces contain only a note
 * — so "Log in" paints at full 14px beside the emoji and wraps onto two lines
 * inside the 40px utility row, colliding with the icon. Visible at 414px.
 *
 * The anchor already carries aria-label="Log in", so the visible words are
 * redundant, not informative: hide them from sight, keep them for assistive
 * tech. Chips are also pinned to a single line so a longer currency string
 * (e.g. "€ 1,234.00") cannot reintroduce the wrap.
 *
 * Fixed HERE, in the child, and not in ds.css: that file is the shared parent
 * theme used by every tenant in the estate, and this row only exists on VNM.
 * ========================================================================== */

@media (max-width: 899px) {

	.vnm-utilitybar .arneiron-account-toggle__screen {
		position: absolute;
		width: 1px;
		height: 1px;
		margin: -1px;
		padding: 0;
		border: 0;
		overflow: hidden;
		white-space: nowrap;
		clip-path: inset(50%);
	}

	.vnm-utilitybar__inner a {
		display: inline-flex;
		align-items: center;
		gap: 6px;
		white-space: nowrap;
		line-height: 1;
	}

	.vnm-utilitybar__inner .arneiron-cart-chip__total {
		white-space: nowrap;
	}
}

/* =============================================================================
 * §10. DESKTOP OVERLAY MASTHEAD                          (added 2026-08-14)
 * -----------------------------------------------------------------------------
 * Measured on live vania-novikau.me at a 1600px viewport, on the front page and
 * on /about/, via getComputedStyle:
 *
 *     .pix-header        position:absolute; top:0; z-index:3;
 *                        background:rgba(0,0,0,0.2); height:123px
 *     .pix-slide-content getBoundingClientRect().top === 0
 *
 * The reference masthead floats over the first section on EVERY page, not only
 * over the hero. dev rendered it in normal flow, so every page began 123px lower
 * than the reference and nothing ever ran under the logo.
 *
 * Scoped to >=900px, the breakpoint vnm-nav.css already uses for the nav
 * disclosure. Below it the header stays in flow: the mobile utility row sits
 * directly beneath it, and an overlaid header on a phone would cover the title.
 *
 * The 1300px reading column is NOT set here — it is `settings.layout` in the
 * child's theme.json, because arneiron/assets/css/ds.css:186 derives
 * `.site-main`'s width from `--wp--style--global--wide-size` and
 * `.wp-block-post-content`'s from `--wp--style--global--content-size`. Overriding
 * the computed widths in CSS would fight that instead of feeding it.
 * ========================================================================== */

@media (min-width: 900px) {

	/* Two jobs, both required:
	   - `position: relative` gives the absolutely positioned header a containing
	     block. `overflow-x: clip` from §4 does NOT establish one — only
	     position/transform/filter/contain do.
	   - `display: flow-root` establishes a block formatting context so that
	     `main`'s top margin stops collapsing THROUGH this wrapper and the body.
	     Without it, main's inline `style="margin-top:var(--wp--preset--spacing--6)"`
	     escapes to the top of the document and shifts the whole page down 24px,
	     leaving a pale strip above the overlaid header — measured:
	     body.getBoundingClientRect().top === 24. `overflow-x: clip` does not
	     establish a BFC either, which is why this has to be said explicitly.
	     Fixing it here rather than zeroing the margin keeps §4's compensating
	     negative margin on the title band correct: main sits 24px down inside the
	     wrapper, the band's -24px pulls it back, and the band lands at y=0. */
	:root .wp-site-blocks {
		position: relative;
		display: flow-root;
	}

	/* Positioned on the template-part WRAPPER, not on .vnm-header itself.
	   `.wp-site-blocks` is a flow layout with a block gap, and an empty-but-
	   present wrapper still consumes one gap: taking only .vnm-header out of
	   flow left a 24px band above the hero on the front page (whose own main
	   carries inline margin-top:0, so the offset could not have come from there).
	   Removing the wrapper from flow removes the gap with it. */
	:root .wp-site-blocks > header.wp-block-template-part {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		z-index: 20;
	}

	.vnm-header {
		background: var(--vnm-chrome-veil);
	}

	/* Same failure one level along: `.vnm-utilitybar` is already display:none at
	   this breakpoint (§3), but its template-part WRAPPER remains an in-flow
	   child of .wp-site-blocks and still consumes one block gap — which is the
	   last 24px sitting above the hero on the front page. Hide the wrapper, not
	   just its contents. Matched via :has so it keys on the utility row itself
	   rather than on "any div template part", which a later part would inherit
	   by accident. */
	:root .wp-site-blocks > .wp-block-template-part:has(> .vnm-utilitybar) {
		display: none;
	}

	/* arneiron/assets/css/ds.css:192 puts `padding-block: var(--space-6)` on
	   .site-main. With the header floating, that 24px of TOP padding paints as a
	   white strip above the black title band, where prod has the band flush at
	   y=0. The band supplies its own top spacing (below), so the block-start
	   padding is redundant here. Only the start edge is dropped — the bottom
	   padding still separates content from the footer. */
	:root main.site-main {
		padding-block-start: 0;
	}

	/* The band now starts at y=0 beneath the floating header, so it carries the
	   header's height itself or the h1 paints under the logo. Over the band's
	   solid black the 20% veil composites back to black, which is why the header
	   still reads as a solid bar on interior pages — as it does on prod. */
	:root h1.wp-block-post-title:not(.screen-reader-text),
	:root h1.wp-block-query-title,
	:root h1.woocommerce-products-header__title,
	:root h1.page-title {
		padding-top: calc(var(--vnm-header-h) + clamp(20px, 2vw, 29px));
	}
}

/* =============================================================================
 * §11. FULL-BLEED CAROUSEL SECTION                       (added 2026-08-14)
 * -----------------------------------------------------------------------------
 * The "Decode Philosophy" section is a full-bleed BAND with a site-width column
 * inside it. Measured on live prod at a 1600px viewport (document 1585px wide),
 * walking `.wpb-content-wrapper > .vc_row`:
 *
 *     hero row      w=1330  left=128           <- contained, NOT full-bleed
 *     carousel row  w=1585  left=0  pad=127.5  <- full viewport, inner 1300
 *     the two rows below it   w=1320
 *
 * so exactly ONE row on that page stretches, and its inner column still measures
 * 1300. dev rendered the band at 1300 (left=143 -> right=1443): the block carries
 * `alignfull`, but alignfull only fills the block's PARENT, and the parent chain
 * bottoms out at `main`'s 1300px content box. It can never reach the viewport
 * from there, which is why the gradient stopped at the text edges.
 *
 * `calc(50% - 50vw)` is measured against the containing block (1300), giving
 * -150px a side and a 1600px band. That is 7.5px wider than the 1585px document
 * on each edge because `vw` counts the scrollbar — harmless here, and ONLY
 * because §4 already puts `overflow-x: clip` on `.wp-site-blocks`, so the
 * overshoot is clipped instead of opening a horizontal scrollbar. Verified after
 * this rule: document.scrollWidth still 1585.
 *
 * The inner column needs no width rule: the block is `is-layout-constrained`, so
 * its children are already capped at `--wp--style--global--content-size` (1300)
 * and centred. The side padding is only a small-screen gutter.
 *
 * Not scoped to a breakpoint — prod's band is full-bleed at every width.
 * ========================================================================== */

:root .vnm-decode-section {
	margin-inline: calc(50% - 50vw);
	padding-inline: var(--vnm-gutter);
}

/* =============================================================================
 * §12. PAGE-HEADER BAND — parity with solutech's templates/header/bg_image.php
 *                                                          (added 2026-08-14)
 * -----------------------------------------------------------------------------
 * Measured on live prod /about/ at 1600px (getComputedStyle, not read off CSS):
 *
 *     .custom-header   full-bleed 1585, height 366, padding 140/160,
 *                      margin-bottom 11
 *     h1.pix-h1        44.8px / 56 line-height (= 1.25) / 600 / #fff / centred
 *
 * dev's band measured 270 tall, padding 152/55, margin-bottom 48, line-height
 * 62.72. This aligns it.
 *
 * TWO BLEED MECHANISMS, ON PURPOSE
 * --------------------------------
 * §4 spans the band with `box-shadow: 0 0 0 100vmax` + `clip-path`, and that is
 * KEPT for the flat-colour case, which is every VNM page today and prod too.
 *
 * It cannot carry an image: a box-shadow spreads a SOLID COLOUR only, so an
 * image would paint inside the 1300px box while the shadow painted flat colour
 * to both edges — a stripe. So the image case, and only the image case, swaps to
 * real negative-margin bleed (the §11 technique), which is safe because §4
 * already puts `overflow-x: clip` on `.wp-site-blocks`.
 *
 * That swap needs `!important`, which is not laziness: WordPress's own
 * constrained-layout CSS emits
 *     .wp-container-… > :where(:not(.alignleft):not(.alignright):not(.alignfull))
 *       { margin-left: auto !important; margin-right: auto !important }
 * — measured, 3 occurrences in the page — and an unflagged `margin-inline` loses
 * to it. §11's band escapes this because `alignfull` is excluded by that
 * selector; the title band is not aligned, so it is not excluded.
 *
 * Everything image-related is gated behind `body.vnm-band-has-image`, which
 * inc/page-parts.php adds only when a page actually names one.
 * ========================================================================== */

:root h1.wp-block-post-title:not(.screen-reader-text),
:root h1.wp-block-query-title,
:root h1.woocommerce-products-header__title,
:root h1.page-title {
	margin-bottom: 11px;
	line-height: 1.25;
}

@media (min-width: 900px) {
	:root h1.wp-block-post-title:not(.screen-reader-text),
	:root h1.wp-block-query-title,
	:root h1.woocommerce-products-header__title,
	:root h1.page-title {
		/* prod's exact figures. 140 also clears the 123px overlaid masthead
		   from §10, which is why no separate header-height term is needed. */
		padding-top: 140px;
		padding-bottom: 160px;
	}
}

/* ---- what used to be here -------------------------------------------------
 * §4's optional background image, colour overlay and breadcrumb strip — all of
 * it driven by `body.vnm-band-has-*` classes and site options — is GONE as of
 * 2026-09-01. The band is `parts/page-header.html`, a Cover block, and those
 * are its own attributes now. The h1 rules ABOVE survive on purpose: they still
 * style a level-1 title on any template that has one and does NOT include the
 * part (the child's single.html, the parent's singular.html), which is the
 * reference's own behaviour for a post — a plain heading, no band.
 *
 * `.vnm-band__crumbs` below is very much alive: `arneiron-child/breadcrumbs`
 * emits that class through `get_block_wrapper_attributes()`, so the trail keeps
 * one set of type rules whether it is rendered by the block or, historically,
 * by the band.
 * ------------------------------------------------------------------------- */

.vnm-band__crumbs {
	position: relative;
	z-index: 1;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 8px;
	margin-top: 14px;
	font-family: var(--wp--preset--font-family--jost);
	font-size: 15px;
	font-weight: 400;
	line-height: 1.4;
	color: var(--vnm-on-dark-2);
}

.vnm-band__crumbs a {
	color: inherit;
	text-decoration: none;
	border-bottom: 1px solid transparent;
}

.vnm-band__crumbs a:hover,
.vnm-band__crumbs a:focus-visible {
	border-bottom-color: currentColor;
}

.vnm-band__crumbs [aria-current="page"] {
	color: var(--vnm-on-dark);
}

.vnm-band__sep {
	opacity: 0.5;
}

/* =============================================================================
 * §13. HEADER: STICKY + BOXED/FULL-WIDTH                       (2026-08-17)
 * -----------------------------------------------------------------------------
 * Measured on the reference at 1600, /kant-main7-time-inner-sense/:
 *
 *                      reference              here (before)
 *   bar                1585 full-bleed        1585 full-bleed   (already right)
 *   CONTENT            143 → 1443 = 1300      70 → 1515 ≈ full
 *   on scroll          class `fixed`,         static — scrolled away
 *                      position: fixed, z 30
 *
 * So the reference is BOXED and STICKY, which is why those are the defaults.
 *
 * STICKY IS `fixed`, NOT `position: sticky`. §10 already takes the header's
 * template-part wrapper OUT of flow (`position: absolute`) so it overlays the
 * first section; `position: sticky` has no effect on an out-of-flow element. The
 * reference does the same thing — it starts `absolute` and its script swaps to
 * `fixed` once you scroll. Going straight to `fixed` is visually identical at the
 * top of the page and needs no scroll listener at all.
 *
 * BOXED is expressed against `--wp--style--global--content-size`, so it follows
 * Styles → Layout instead of hard-coding 1300 in a second place.
 * ========================================================================== */

@media (min-width: 900px) {

	/* ---- sticky (default; body.arneiron-header-sticky) ---- */
	body.arneiron-header-sticky .wp-site-blocks > header.wp-block-template-part {
		position: fixed;
		z-index: 30; /* the reference's scrolled z-index */
	}

	/* ---- not sticky: overlays at the top, then scrolls away (the §10 default) */
	body.arneiron-header-static .wp-site-blocks > header.wp-block-template-part {
		position: absolute;
		top: 0;   /* same double-offset reason as below */
		z-index: 20;
	}

	/* ---- boxed (default; body.arneiron-header-boxed) ----
	   The BAR keeps its full-bleed background — only the row inside it is
	   constrained, which is exactly what the reference does. */
	body.arneiron-header-boxed .vnm-header__inner {
		max-width: var(--wp--style--global--content-size, 1300px);
		margin-inline: auto;
	}

	/* ---- full-width: the row uses the whole window, minus the gutter ---- */
	body.arneiron-header-full .vnm-header__inner {
		max-width: none;
	}
}

/* =============================================================================
 * §13b. STICKY, CORRECTED — it engages ON SCROLL and SHRINKS   (2026-08-17)
 * -----------------------------------------------------------------------------
 * §13 made the header `position: fixed` permanently, on the reasoning that
 * "absolute at the top and fixed once scrolled" looks identical at y=0. That was
 * wrong, and measuring the reference at three scroll positions shows why:
 *
 *     scrollY   reference height   position
 *     0         123px              absolute      <- overlays, scrolls away
 *     200        50px              fixed         <- engages AND SHRINKS
 *     900        50px              fixed
 *
 * So the bar is full height while you are at the top, and collapses to a 50px
 * strip once it sticks. Permanently-fixed at 123px is a different component.
 *
 * The engaged state is driven by `body.arneiron-header-stuck`, set by a scroll
 * listener in inc/setup.php. CSS alone cannot do this: `position: sticky` is
 * inert here because §10 takes the header's wrapper out of flow, and no CSS
 * selector can react to scroll offset.
 * ========================================================================== */

@media (min-width: 900px) {

	/* At rest: overlay the first section and scroll away with the page. This is
	   §10's behaviour, restated because §13 had overridden it. */
	body.arneiron-header-sticky .wp-site-blocks > header.wp-block-template-part {
		position: absolute;
		/* top:0, NOT the admin-bar offset. The parent sets
		   `top: var(--arneiron-adminbar-offset)` on this same selector, which is
		   correct only while the header is FIXED — `top` then resolves against
		   the viewport and parks it under the bar. Absolute resolves against a
		   containing block WordPress has ALREADY pushed down by
		   `html { margin-top: 32px }`, so the 32px lands twice and leaves a 32px
		   band of page showing between #wpadminbar and the header. Measured
		   logged in at 1400px: adminbar 0->32, header top 64, gap 32. */
		top: 0;
		z-index: 20;
	}

	/* Engaged: pinned and collapsed. */
	body.arneiron-header-sticky.arneiron-header-stuck .wp-site-blocks > header.wp-block-template-part {
		position: fixed;
		/* Back to the admin-bar offset, and it MUST be restated here. The at-rest
		   rule above sets top:0 for absolute positioning; this rule is more
		   specific but declares no `top` of its own, so without this line it
		   inherits that 0 and — now FIXED, i.e. viewport-relative — parks the
		   header UNDERNEATH #wpadminbar instead of below it (measured: header
		   top 0, gap -32). Absolute wants 0, fixed wants the offset; the two
		   states genuinely need different values. */
		top: var(--arneiron-adminbar-offset, 0px);
		z-index: 30;              /* the reference's stuck z-index */
	}

	body.arneiron-header-sticky.arneiron-header-stuck .vnm-header__inner {
		min-height: 50px;         /* 123 -> 50, measured */
	}

	/* The logo is the tallest thing in the bar, so it has to come down with it or
	   the row cannot reach 50px. Transitioned so the collapse reads as one
	   movement rather than a jump. */
	body.arneiron-header-sticky.arneiron-header-stuck .vnm-header__logo {
		height: 34px;
		width: auto;
	}

	body.arneiron-header-sticky .vnm-header__inner,
	body.arneiron-header-sticky .vnm-header__logo {
		transition: min-height 0.25s ease, height 0.25s ease;
	}

	/* Sticky off: never engages, whatever the scroll position. */
	body.arneiron-header-static .wp-site-blocks > header.wp-block-template-part {
		position: absolute;
		top: 0;   /* same double-offset reason as above */
		z-index: 20;
	}
}

/* -----------------------------------------------------------------------------
 * §13c · boxed header = the layout width, with NO inline padding  (2026-08-17)
 *
 * §3 gives `.vnm-header__inner` `padding-inline: var(--vnm-gutter)` (up to 70px).
 * Inside the boxed max-width from §13 that padding is INSET, so the row measured
 * logo 213 → login 1373 inside a 1300 box running 143 → 1443: the content sat
 * 70px in from both edges instead of on them.
 *
 * The reference puts its header content ON the layout edges — logo starts at 143
 * and the login button ends at 1443, i.e. exactly the 1300 box. So the boxed
 * header drops the gutter entirely and the max-width alone defines it.
 *
 * Only in boxed mode, and only at >=900px: in FULL-WIDTH mode the row runs to the
 * window, where a gutter is the only thing keeping the logo off the screen edge,
 * and below the breakpoint the mobile bar needs it for the same reason.
 * -------------------------------------------------------------------------- */

@media (min-width: 900px) {
	body.arneiron-header-boxed .vnm-header__inner {
		max-width: var(--wp--style--global--content-size, 1300px);
		margin-inline: auto;
		padding-inline: 0;
	}
}

/* -----------------------------------------------------------------------------
 * §13d · the stick must not animate — that is the bounce      (2026-08-17)
 *
 * §13b collapsed the bar with `transition: min-height .25s, height .25s`. The
 * class flips the instant the threshold is crossed, so the bar spends 250ms
 * animating 123px → 50px WHILE it is pinning: that read as a bounce, and near
 * the threshold a small scroll could start the animation repeatedly.
 *
 * The reference does not animate it at all —
 *     .pix-header.fixed .container, .pix-header.fixed nav { height: 50px; }
 * — it is a straight swap, and it uses `height`, not `min-height`, so the row
 * cannot be pushed taller by its contents mid-collapse.
 *
 * NO PLACEHOLDER, deliberately. The reference has none, and adding one here
 * would be wrong: §10 already takes the header's wrapper OUT OF FLOW
 * (`position: absolute`) at rest, so pinning it changes nothing about document
 * flow and there is no gap to fill. A spacer would push the whole page down by
 * the header's height instead. Checked the reference's JS and CSS for a
 * clone/spacer/placeholder — there is none; `absolute → fixed` is the whole
 * mechanism.
 *
 * The stuck bar also takes the reference's SOLID background (#1a1a1a) rather
 * than the 20% veil: over scrolled content a translucent bar is unreadable, and
 * the reference switches to solid for exactly that reason.
 * -------------------------------------------------------------------------- */

@media (min-width: 900px) {

	/* kill the animation from §13b */
	body.arneiron-header-sticky .vnm-header__inner,
	body.arneiron-header-sticky .vnm-header__logo {
		transition: none;
	}

	body.arneiron-header-sticky.arneiron-header-stuck .vnm-header__inner {
		height: 50px;
		min-height: 0;
	}

	body.arneiron-header-sticky.arneiron-header-stuck .vnm-header {
		background: #1a1a1a;
	}
}

/* =============================================================================
 * §16. The logged-in cluster — balance + account menu   (2026-08-18, revised 08-19)
 * -----------------------------------------------------------------------------
 * Balance measurements come from the reference's header1.php inline styles: row
 * 14px/600 with a 5px gap, the count itself at 20px, the coin 40px wide nudged
 * 4px up so its optical centre lines up with the digits, 15px before the icon.
 *
 * THE DROPDOWN NOW USES THE REFERENCE'S OWN NUMBERS (single.css:831). The first
 * pass invented its own — 190px min-width, 6px radius, a heavy 30px shadow and a
 * fade transition — which read as a different component. The reference is:
 * #1a1a1a, padding 10px 15px, radius 4px, a light 0 5px 15px/0.1 shadow, a
 * 1px hairline border, width AUTO (it sizes to its longest label, it is not
 * pinned to a minimum), z-index 1000, and a FIXED height of 270px.
 *
 * The 270px is deliberate on their side and reproduced here rather than replaced
 * with `auto`: the seven items are the same seven, so the panel lands at the same
 * size, and matching it is the whole point of this pass.
 *
 * `display: none/block` like the reference, NOT an opacity fade — with a fade the
 * panel still occupies its box while invisible and swallows clicks aimed at the
 * page beneath it.
 * ========================================================================== */

.vnm-header__actions {
	display: flex;
	align-items: center;
	gap: 15px;
}

.vnm-header__balance {
	display: flex;
	align-items: center;
	gap: 5px;
	color: inherit;
	font-weight: 600;
	font-size: 14px;
	text-decoration: none;
}

.vnm-header__coin {
	position: relative;
	top: -4px;
	width: 40px;
	height: auto;
}

.vnm-header__balance .aic-live-balance {
	font-size: 20px;
}

.vnm-header__account {
	position: relative;
	display: flex;
	align-items: center;
}

.vnm-header__account-icon {
	display: flex;
	align-items: center;
	color: inherit;
	text-decoration: none;
}

/* The gap between the icon and the panel is dead space the pointer has to cross;
   without this bridge the menu closes mid-travel. The reference ships the same
   10px strip. */
.vnm-header__account::after {
	content: "";
	position: absolute;
	top: 100%;
	left: 0;
	width: 100%;
	height: 10px;
}

.vnm-header__submenu {
	display: none;
	position: absolute;
	top: 100%;
	right: 0;
	z-index: 1000;
	width: auto;
	min-width: auto;
	max-width: 100vw;
	height: 270px;
	margin: 0;
	padding: 10px 15px;
	list-style: none;
	text-align: left;
	background-color: #1a1a1a;
	border: 1px solid rgba(0, 0, 0, .1);
	border-radius: 4px;
	box-shadow: 0 5px 15px rgba(0, 0, 0, .1);
	overflow: visible;
}

/* Hover on either half, plus focus-within so the seven links are reachable by
   keyboard — the reference opens on hover only, which leaves them tab-reachable
   but invisible. */
.vnm-header__account:hover .vnm-header__submenu,
.vnm-header__account:focus-within .vnm-header__submenu,
.vnm-header__submenu:hover {
	display: block;
}

.vnm-header__submenu li {
	display: block;
	margin: 0;
	padding: 5px 0;
	list-style: none;
}

/*
 * `white-space: nowrap` REPLACES the reference's `word-break: break-word`, and it
 * is a fix rather than a deviation.
 *
 * The panel is `width: auto` and absolutely positioned, so its width is
 * shrink-to-fit: min(max(min-content, available), max-content). Its containing
 * block is the account icon — 20px wide — so `available` is 20px, and
 * break-word drives min-content down to the widest UNBREAKABLE fragment.
 * Measured result: a 43px panel with every label broken across several lines.
 *
 * Forbidding the break makes min-content equal max-content, i.e. the longest
 * label, which is the width the reference actually shows. Its own break-word is
 * a guard for labels long enough to overflow the viewport; these seven are fixed
 * strings, so nothing here can hit that case.
 */
.vnm-header__submenu a {
	display: block;
	color: #fff;
	font-size: 14px;
	text-decoration: none;
	white-space: nowrap;
}

.vnm-header__submenu a:hover,
.vnm-header__submenu a:focus-visible {
	color: var(--vnm-brand, #e5b769);
	text-decoration: none;
}

/* Exit is set apart, as in the reference. */
.vnm-header__submenu-exit {
	margin-top: 5px;
	padding-top: 5px;
	border-top: 1px solid rgba(255, 255, 255, .1);
}

/* =============================================================================
 * §17. Header search                                             (2026-08-19)
 * -----------------------------------------------------------------------------
 * The reference puts a magnifier first in the header's right-hand list and, on
 * click, swaps the NAV for a search field in place (`theme.js:87` adds `.show`
 * to `.search-container` and `.hide` to the logo and nav). It was never ported —
 * dev had no search control at all, in any state.
 *
 * Reproduced with the checkbox that the markup already carries, so the behaviour
 * needs no script: `:checked` hides the nav and reveals the panel. That also
 * means it survives with JS disabled, which the reference's version does not.
 * ========================================================================== */

.vnm-header__search-state {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.vnm-header__search,
.vnm-header__search-close {
	display: flex;
	align-items: center;
	margin: 0;              /* same global-label-margin defence as the burger */
	color: inherit;
	cursor: pointer;
}

/* The opener is an <a> since 2026-09-13 — strip the link chrome so it reads
   as an icon control, exactly as the label did. */
a.vnm-header__search {
	text-decoration: none;
}

a.vnm-header__search:hover {
	text-decoration: none;
	opacity: .85;
}

/* The FA 7 <i> conversions ( 2026-09-13 ) — glyphs size by font, the old
   inline svgs were 20x20 boxes. */
.vnm-header__search-close i,
.vnm-header__account-icon i,
.vnm-header__search i {
	font-size: 20px;
	line-height: 1;
}

/* The glyph is Font Awesome now, not a fixed-size <svg>, so it takes its size
   from the font rather than from width/height attributes — left alone it
   inherited the body's 18px and drew 23x18. The reference sets 16px on the same
   icon (measured on exam.vania-novikau.me: font-size 16px, box 20x16), which is
   also exactly the 20px width of the account SVG sitting beside it, so the row
   stays even. `line-height: 1` keeps the flex row from growing by the font's
   leading. */
.vnm-header__search .fa-search {
	font-size: 16px;
	line-height: 1;
}

.vnm-header__searchbox {
	display: none;
	flex: 1 1 auto;
	align-items: center;
	gap: 10px;
}

#vnm-search-toggle:checked ~ .vnm-header__searchbox {
	display: flex;
}

/* The nav gives up its room to the field, exactly as the reference does. */
#vnm-search-toggle:checked ~ .vnm-header__nav {
	display: none;
}

.vnm-header__searchbox form {
	flex: 1 1 auto;
	margin: 0;
}

.vnm-header__searchbox input[type="search"],
.vnm-header__searchbox .wp-block-search__input,
.vnm-header__searchbox .search-field {
	width: 100%;
	padding: 8px 12px;
	color: #fff;
	font-size: 15px;
	background: rgba(255, 255, 255, .06);
	border: 1px solid rgba(255, 255, 255, .18);
	border-radius: 4px;
}

.vnm-header__searchbox input[type="search"]::placeholder {
	color: rgba(255, 255, 255, .5);
}

/* Core's form ships a submit button; the field takes Enter, and the reference
   shows a bare field, so it is hidden rather than restyled. */
.vnm-header__searchbox input[type="submit"],
.vnm-header__searchbox .wp-block-search__button,
.vnm-header__searchbox .search-submit {
	display: none;
}

/* =============================================================================
 * §18. Front page — filter off, footer gap re-homed        (2026-08-20)
 * -----------------------------------------------------------------------------
 * SCOPED TO THE FRONT PAGE deliberately. The brief said "on the main page", and
 * two of these three would misbehave site-wide: `.vnm-footer` carries its 96px
 * top margin on EVERY template, so dropping it globally while replacing it with
 * padding on a band that only the front page has would collapse the gap above
 * the footer everywhere else. Scoping keeps the change where it was asked for.
 *
 * MEASURED before the change, front page at 1600px:
 *     .vnm-footer                          margin-top 96px
 *     .arneiron-carousel                   padding-bottom 0
 *     .arneiron-dynamic-carousel-filter    visible, 29px tall, 5 links
 * ========================================================================== */

/* a) The carousel's category filter.
 *
 * The block has NO attribute for this. `arneiron/dynamic-carousel` draws the
 * filter whenever its `categories` attribute resolves to real terms, and the
 * same attribute also builds the tax_query — so emptying it to hide the filter
 * would silently widen the query and change WHICH posts appear. Hiding the
 * element is the only change that touches the filter and nothing else. */
body.home .arneiron-dynamic-carousel-filter {
	display: none;
}

/* b) + c) The 96px moves from the footer's margin to the band's padding.
 *
 * Same total distance, but it now belongs to the carousel, so the section's
 * background extends through it instead of the gap being blank page above the
 * footer. The two values are stated as one custom property so they cannot drift
 * apart later — that is the whole point of the swap. */
body.home {
	--vnm-footer-gap: 96px;
}

body.home .vnm-footer {
	margin-top: 0;
}

body.home .arneiron-carousel {
	padding-bottom: var(--vnm-footer-gap);
}

/* -----------------------------------------------------------------------------
 * §19. Root section gap — MOVED TO THE PARENT THEME            (2026-08-21)
 *
 * `:where(.wp-site-blocks) > * { margin-block-start: 0 }` now lives in the
 * arneiron parent (assets/css/ds.css, "ROOT SECTION RHYTHM"), so every site on
 * the theme gets it rather than only this one. Nothing replaces it here: two
 * copies of the same reset is one more place to look when the spacing is wrong.
 * -------------------------------------------------------------------------- */

/* =============================================================================
 * §20. Carousel cards — no underlines                          (2026-08-25)
 * -----------------------------------------------------------------------------
 * Measured on the front page at 1600: the reference has ZERO underlined links on
 * the whole page; here there were SEVEN, all inside the carousel's post cards —
 * the image link, the category button, the title. They pick up the underline
 * from the global link styling because nothing in the card resets it, and the
 * reference's own card CSS (which does) was never ported.
 *
 * Scoped to the carousel section rather than set globally: an underline is the
 * correct default for a link in prose, and removing it site-wide to fix a card
 * would trade one mismatch for a worse one.
 * ========================================================================== */

.arneiron-carousel a {
	text-decoration: none;
}

/* The login modal's "Lost password?" trigger. The reference does not underline
   it either; it was the last underlined link on the page after §20 removed the
   carousel's. Scoped to the xoo-el form so it cannot reach page content. */
.xoo-el-fields .xoo-el-lostpw-tgr {
	text-decoration: none;
}

/* Post page: the last underlined links. The reference has ZERO on this template
   too — measured — and these three sources are the only ones left here:
   the related-post thumbnails and the comments "you must be logged in" prompt.
   Scoped to each, not set globally: a link in prose should stay underlined. */
.vnm-related__thumb,
.comment-respond .must-log-in a {
	text-decoration: none;
}

/* =============================================================================
 * §21. Type weights — the reference's values                   (2026-08-25)
 * -----------------------------------------------------------------------------
 * Root and body font SIZE already match (18px, since the --pix-font-size port).
 * What still differed across both the front page and the post template was
 * WEIGHT, consistently and in the same direction on both:
 *
 *              prod   here
 *   h2 / h3    600    700     headings a step too heavy
 *   li         500    400     list items a step too light
 *   h1         600    600     already correct
 *
 * Sizes are deliberately untouched: every measured size matched apart from
 * `h1` at 44.802 vs 44.8, which is a sub-pixel rounding artefact of the same
 * clamp() and not a real difference.
 * ========================================================================== */

:root h2,
:root h3 {
	font-weight: 600;
}

li {
	font-weight: 500;
}

/* =============================================================================
 * §22. Footer tagline — the reference's type                   (2026-08-25)
 * -----------------------------------------------------------------------------
 * "Curiosity-driven research at the intersection of Physics and AI."
 * Measured against the reference's `.pf-desc`:
 *
 *                    prod                  here (before)
 *   size             18px                  16px
 *   line-height      32.4px  (= 1.8)       25.6px  (= 1.6)
 *   colour           rgb(168,148,194)      rgb(201,201,221)
 *   margin-bottom    15px                  6px
 *
 * Weight, family, style and letter-spacing already matched and are left alone.
 *
 * line-height is set as the RATIO 1.8 rather than the computed 32.4px: the two
 * are identical at 18px, but a ratio keeps the leading correct if the size is
 * ever changed, which a pixel value would silently not.
 * ========================================================================== */

.vnm-footer__desc {
	font-size: 18px;
	line-height: 1.8;
	color: rgb(168, 148, 194);
	margin-bottom: 15px;
}

/* The roles line above the tagline — "Physicist · Researcher · AI Explorer".
   Same footer block, same kind of drift as §22:
       size    prod 18px               here 16px
       colour  prod rgb(209,196,233)   here rgb(136,136,234)
   Weight already matched. ("Buy me a lambo" was measured too and matches.) */
.vnm-footer__roles {
	font-size: 18px;
	color: rgb(209, 196, 233);
}

/* =============================================================================
 * §23 · no underline on ANY link hover                         (2026-08-26)
 *
 * Ten separate rules across the parent and the child add `text-decoration:
 * underline` on hover — blog-card terms, card titles, read-more, post titles,
 * post terms, the table of contents, the footer, the single-post prev/next nav
 * and the related list. Five of them live in the PARENT, which is shared with
 * dev.arneiron.net and by standing rule takes mechanics only, never appearance,
 * so they are overridden from here rather than edited there.
 *
 * `:root` is repeated to reach specificity (0,4,1). The strongest of those rules
 * is `.vnm-blog-cards .vnm-blog-card__terms a:hover` at (0,3,1) — a plain
 * `a:hover` would be served, would look correct in the file, and would lose.
 * No `!important`, which would also override rules that legitimately need one.
 *
 * `:focus-visible` is deliberately NOT included. Most of those rules group hover
 * and focus in one selector; killing both would strip the keyboard affordance
 * from links that have nothing else marking them out. Hover is a pointer
 * nicety; focus is accessibility.
 * ========================================================================== */

:root:root:root a:hover {
	text-decoration: none;
}


/* =============================================================================
 * §24 · the three Bootstrap utilities the chatbox markup needs  (2026-08-29)
 * -----------------------------------------------------------------------------
 * ★★★ A CLASS THAT DOES NOTHING IS INVISIBLE IN EVERY DIFF. The post body is
 * rendered by ai-chatboxes, whose markup was written against the reference's
 * theme — and that theme loads BOOTSTRAP. Three of its utility classes are
 * load-bearing in that markup and are defined NOWHERE on this plane, so they
 * were silently inert:
 *
 *   .d-lg-none   3x   the MOBILE COPY of each repeater image. Hidden on the
 *                     reference at >=1000px; here it rendered full-width on
 *                     desktop, ~800px tall, once per repeater row.
 *   .mb-3        6x   1rem  (18px at this root size)
 *   .mb-4        4x   1.5rem
 *
 * Cost of the d-lg-none half alone, measured on the same post at 1440:
 *
 *                        reference    here (before)
 *     L2 pane height        1479          3983
 *     document height       4112          6730
 *
 * The images are not "extra content" and the post is not different — the same
 * three repeater rows render on both planes. It is one duplicate <img> per row
 * that the reference hides and this plane had no rule to hide.
 *
 * WHY THIS TOOK SO LONG TO SEE, worth recording: every earlier pass compared
 * COMPUTED VALUES of elements that exist on both planes, and these elements do
 * exist on both — with a legitimate `display: block`. Nothing is missing, no
 * declaration is wrong, and no cascade fight is being lost. The defect is an
 * absent RULESET for a class the markup names, which no property-by-property
 * diff can surface. It showed up only by walking the subtree height and asking
 * where 2477px went.
 *
 * PORTED AS THE REFERENCE DECLARES THEM, read out of its own bootstrap.min.css
 * rather than from Bootstrap's documentation:
 *
 *   @media (min-width: 1000px) { .d-lg-none { display: none !important } }
 *   .mb-3, .my-3 { margin-bottom: 1rem   !important }
 *   .mb-4, .my-4 { margin-bottom: 1.5rem !important }
 *
 * Two deliberate departures, both narrowing:
 *
 *  1. `.my-3` / `.my-4` are dropped. In Bootstrap the `my-*` bottom margin is
 *     grouped into these rules and its TOP margin comes from a separate one;
 *     porting only the group would give `.my-*` a bottom margin and no top.
 *     Neither class appears in the markup, so the half-rule is omitted rather
 *     than shipped broken.
 *
 *  2. Only these three are ported, not Bootstrap's utility layer. Each was
 *     counted in the rendered markup first. If the plugin's markup later names
 *     another one, it will be just as invisible as these were — the check is
 *     to enumerate the class TOKENS in the rendered body and ask which of them
 *     no stylesheet on this plane defines.
 *
 * The `!important` IS the reference's declaration, not a specificity shortcut:
 * a utility class exists to beat component CSS, and `.pix-repeater-image` sets
 * its own display. This is the one place in this sheet where it is a port.
 *
 * ⚠ The breakpoint is 1000px, NOT Bootstrap's stock 992px. The reference ships
 * a customised build. Measured from its stylesheet; do not "correct" it.
 * ========================================================================== */

@media (min-width: 1000px) {
	.d-lg-none {
		display: none !important;
	}
}

.mb-3 {
	margin-bottom: 1rem !important;
}

.mb-4 {
	margin-bottom: 1.5rem !important;
}


/* =============================================================================
 * §25 · carousel pagination dots — the reference's owl dots  (2026-08-29)
 * -----------------------------------------------------------------------------
 * The dots were never a missing FEATURE. `dynamic-carousel/lib-render.php`
 * already emits `<div class="swiper-pagination">` whenever the block's `dots`
 * attribute is true, and frontend.js already wires Swiper's pagination module
 * to it. The front-page block instance simply had `"dots":false` saved in its
 * attributes; that is now `true` (a CONTENT edit to page 1952, not code).
 *
 * ⚠ FOR THE NEXT READER: I first reported this as a missing renderer, because I
 * grepped `render.php` for `swiper-pagination` and found nothing. The markup is
 * in `lib-render.php`. Grep the BLOCK DIRECTORY, never the file you expect.
 *
 * What DID need doing is appearance. The reference draws these with Owl
 * Carousel; here they are Swiper, whose defaults are an 8px iOS-blue circle
 * (rgb(0,122,255)) at 0.2 opacity when inactive — visibly foreign on this site.
 *
 * Measured off the reference's live `.owl-dot` / `.owl-dots`:
 *
 *     inactive   7 x 7   rgb(166,166,166)  radius 100px  opacity 1
 *     active    14 x 7   rgb(136,136,234)  radius 100px  opacity 1
 *     spacing   margin 0 5px
 *     motion    transition: background .3s, width .3s ease-in-out
 *     row       text-align center, margin-top 40px, IN FLOW below the stage
 *
 * The active dot is WIDER, not merely recoloured — an elongated pill against
 * round inactive ones. rgb(136,136,234) is #8888ea, the brand colour, so it is
 * written as the token with the measured literal as the fallback.
 *
 * Set through SWIPER'S OWN CUSTOM PROPERTIES wherever it exposes one, rather
 * than overriding its rules: that is the component's documented API and it
 * survives a Swiper upgrade that renames an internal selector. Only two things
 * have no variable — the active bullet's WIDTH and the row's position — so only
 * those are written as rules.
 *
 * The row is put back IN FLOW (`position: static`). Swiper's default absolutely
 * positions it at `bottom: 8px` INSIDE the stage, which floats the dots over
 * the bottom of the cards; the reference's sit 40px BELOW the stage. With the
 * row in flow the `.swiper`'s own `overflow: hidden` cannot clip it, because an
 * in-flow child grows the box instead of overflowing it.
 *
 * Scoped to `.arneiron-carousel` throughout: this is the appearance of THIS
 * site's carousel, and an unscoped rule would restyle any other Swiper the
 * parent theme mounts.
 * ========================================================================== */

.arneiron-carousel {
	--swiper-pagination-bullet-width: 7px;
	--swiper-pagination-bullet-height: 7px;
	--swiper-pagination-bullet-border-radius: 100px;
	--swiper-pagination-bullet-horizontal-gap: 5px;
	--swiper-pagination-bullet-inactive-color: rgb(166, 166, 166);
	--swiper-pagination-bullet-inactive-opacity: 1;
	--swiper-pagination-color: var(--pix-main-color, #8888ea);
}

.arneiron-carousel .swiper-pagination-bullets.swiper-pagination-horizontal {
	position: static;
	margin-top: 40px;
	text-align: center;
}

.arneiron-carousel .swiper-pagination-bullet {
	transition: background .3s, width .3s ease-in-out;
}

.arneiron-carousel .swiper-pagination-bullet-active {
	width: 14px;
}


/* =============================================================================
 * §26 · the page-header PART — what blocks cannot express   (rewritten 09-01)
 * -----------------------------------------------------------------------------
 * §26 used to style a `.vnm-band` wrapper that PHP wrapped around the title.
 * The band is now `parts/page-header.html` — a Cover block — so almost
 * everything this section used to set is a block attribute you can see and
 * change in the editor: background image, overlay colour, overlay opacity,
 * content position, min-height, padding, margin.
 *
 * What is left here is only what a block genuinely cannot say:
 *
 *   1. the spacing `main` opens ABOVE the band, which belongs to a sibling
 *      element and is therefore not the Cover's to remove;
 *   2. the rounded white lip where the band meets the content sheet — a
 *      decoration with no block equivalent.
 *
 * Everything the Cover owns was DELETED rather than left as a duplicate: a CSS
 * rule that silently wins over a control the editor is showing you is the worst
 * of both, because the panel then lies about what the page will do.
 * ========================================================================== */

/* The band is the first thing under the overlaid masthead, so whatever spacing
   `main` opens above it has to go. `:has()` asks the precise question — is a
   band actually on this page — so a template without one keeps its spacing.
   ⚠ !important because both values arrive as INLINE styles on <main> from the
   block templates, and inline is beaten only by an important author rule; see
   the note this replaces and vnm-single.css §P4h, which hit the same wall. */
:root .wp-site-blocks:has(.vnm-page-header) main.site-main {
	margin-top: 0 !important;
}

/* `padding-top: 0 !important` used to live here too. It is GONE, not moved.
   It existed so `main` sat flush against the band when the content below was a
   flat sheet. Every template that has a band now renders that content as a CARD
   (vnm-single.css) which wants 80px of top padding — the exact templates this
   selector matches. Keeping it meant the card's own padding had to be fought
   back with `!important` and a specificity count, which is how products ended
   up rendering `0px 80px 110px` while pages were right. The margin still goes:
   the card is placed by the band's bottom edge, and a top margin would push it
   off. */

/* THE LIP IS GONE, and the boxed container is why. It painted a rounded sheet-
   coloured strip across the bottom of the band, faking the corner where the
   band met the content below. The content sheet now IS a card — `main` carries
   its own `border-radius: 8px` and is pulled up `-110px` into the band
   (vnm-single.css) — so the real corner is right there, and the fake one sat on
   top of it in a second colour and a second radius. Removed rather than
   adjusted: there is nothing left for it to stand in for.

   `--vnm-lip` stays defined — the h1 title-bar rules above still use it for the
   templates that render a plain title bar instead of the Cover band. */

/* The trail sits above the Cover's overlay span, which covers the whole box. */
:root .vnm-page-header .vnm-band__crumbs {
	position: relative;
	z-index: 1;
}

/* The band's RESPONSIVE values moved to the PARENT theme
   ( arneiron/assets/css/page-header.css ) — the band is the parent's part, so
   the parent owns its small-screen numbers. 2026-09-13. */

/* =============================================================================
 * Section decor: scale it down on mobile
 * -----------------------------------------------------------------------------
 * `arneironDecorTop` points are authored in ABSOLUTE PIXELS (the front page's
 * band runs -4000..4000 with 20-60px teeth) and arneiron/inc/group-decor.php
 * renders the `px` unit at TRUE SIZE on purpose: a nested
 * `<svg x="50%" width="1" overflow="visible">` centred in the row, with the
 * +/-4000 closing points filling the spill. Nothing in that path scales, so a
 * phone got the desktop-sized fractal — three enormous teeth instead of a band.
 *
 * This is solutech's own fix, ported verbatim in shape from
 * themes/solutech/css/single.css:5727 (`.section-decor-wrap`), which is the
 * reference this decor was rebuilt from and which had already solved it.
 *
 * ★ Scale the WRAPPER DIV, never the SVG. Transforming the nested svg or its
 * polygon makes the browser clip to that svg's 1px-wide viewport, so the
 * +/-4000 closers stop filling the band and the decor collapses to a small blob
 * mid-row. Measured that four different ways before finding solutech's version.
 *
 * The width/left pair is what keeps it full-bleed once scaled:
 * 160% x 0.625 = 100%, and left:-30% re-centres the overflow ((160-100)/2).
 * `right: auto` is needed here because the parent sets both left and right.
 * ========================================================================== */

@media (max-width: 899.98px) {

	:root .arneiron-decor-wrap {
		width: 160%;
		left: -30%;
		right: auto;
		transform: scale(0.625);
	}

	/* Each band scales toward the edge it sits on, so it stays welded to the
	   section boundary instead of drifting off it. */
	:root .arneiron-decor-wrap.top    { transform-origin: bottom center; }
	:root .arneiron-decor-wrap.bottom { transform-origin: top center; }
}

/* =============================================================================
 * §22. The nav centres on the HEADER, not on what is left over   (2026-09-11)
 * -----------------------------------------------------------------------------
 * `.vnm-header__nav` is `flex: 1 1 auto` with `justify-content: center`, so it
 * centres the menu inside THE SLOT IT HAPPENS TO OCCUPY — the gap between the
 * brand and the actions cluster. That is only the middle of the header while
 * those two clusters are the same width, and they are not: measured at 1440,
 * brand 123 and actions 118 logged out, 128 logged in. The menu therefore sits
 * at 715 logged out and 710 logged in against a header centre of 713, and it
 * moves again whenever a chip is added to the right-hand cluster.
 *
 * The fix is the one the parent theme already uses for `.app-header`
 * (ds.css, `.has-centred-nav`): take the nav OUT OF FLOW so its box is the
 * whole header rather than the leftover space, then centre the list inside it.
 *
 * Positioned against `.vnm-header__inner` rather than the band: the inner is
 * `max-width: 1300px` with auto side margins, so it is already centred in the
 * band and the two share a centre line — but staying inside it means the menu
 * can never reach into the page gutters, which spanning the band would allow.
 *
 * THREE THINGS THIS COSTS, each learned from the parent's version:
 *
 *   1. The nav's box now lies OVER the brand and the actions, so it must not
 *      swallow their clicks — `pointer-events: none` on the nav, handed back on
 *      the links themselves. Given to the <ul> instead it would still cover the
 *      full width and the logo and Login would stop being clickable.
 *   2. `margin: 0` is restated because margins still apply to an absolutely
 *      positioned box, and `inset-block: 0` is what puts it on the band.
 *   3. The nav's flex growth was what pushed the actions to the right edge.
 *      Out of flow that absorber is gone, so `margin-inline-end: auto` moves
 *      onto the brand — it takes the free space immediately after the logo and
 *      every control packs to the end, however many chips arrive later.
 *
 * Bounded to the desktop header: below 900px the nav is the mobile drawer
 * (vnm-mobile-header.css §15), which is `position: fixed` and must stay that
 * way. The menu is 221px wide and the widest cluster 128, so it clears both
 * sides while the inner is at least ~478px — true at every width this rule
 * applies to, so no JS fit-test is needed here, unlike the parent's.
 * ========================================================================== */

@media (min-width: 900px) {

	/* The positioning context. Without this the nav would resolve against
	   whatever ancestor happens to be positioned, which is not the header. */
	.vnm-header__inner {
		position: relative;
	}

	.vnm-header__nav {
		position: absolute;
		inset-inline: 0;
		inset-block: 0;
		margin: 0;
		pointer-events: none;
	}

	.vnm-header__nav ul {
		justify-content: center;
	}

	.vnm-header__nav li,
	.vnm-header__nav a {
		pointer-events: auto;
	}

	.vnm-header__brand {
		margin-inline-end: auto;
	}
}
