/**
 * Kelvin — Technical Luxe design system.
 *
 * Tokens come from theme.json (--wp--preset--*, --wp--custom--*). This file carries
 * the component layer: header, hero, trust bar, cards, editorial sections, footer,
 * and the dark brand layer used by the Lab Archive and campaign pages.
 *
 * Conventions
 *   .k-*        component classes, applied from block templates/patterns
 *   .k-dark     brand layer — flips a section to the void palette
 *   data-k-*    hooks the JS reads; never style off them
 */

/* -------------------------------------------------------------------------- *
 * 1. Foundation
 * -------------------------------------------------------------------------- */

:root {
	--k-ink: var(--wp--preset--color--contrast);
	--k-body: var(--wp--preset--color--contrast-2);
	--k-muted: var(--wp--preset--color--contrast-3);
	--k-faint: var(--wp--preset--color--contrast-4);
	--k-accent: var(--wp--preset--color--accent);
	--k-line: var(--wp--preset--color--hairline);
	--k-surface: var(--wp--preset--color--base);
	--k-grey: var(--wp--preset--color--base-2);
	--k-radius: var(--wp--custom--radius--control);
	--k-radius-card: var(--wp--custom--radius--card);
	--k-ease: var(--wp--custom--ease);
	--k-gutter: var(--wp--preset--spacing--50);

	/* Header dock. A strong ease-out: it leaves immediately and settles slowly,
	   which is what reads as weight rather than as a slide. */
	--k-nav-dur: .34s;
	--k-nav-ease: cubic-bezier(.22, 1, .36, 1);

	/* Lucide "search" glyph as a data URI, used as a mask so it tints with
	   currentColor. Kept as a variable so the field's ::before and any future
	   consumer share one source. */
	--k-icon-search: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='8'/%3E%3Cpath%20d='m21%2021-4.3-4.3'/%3E%3C/svg%3E");
}

/* Inline icons (Lucide). They inherit colour and sit on the text baseline; the
   crisp stroke comes from being real SVG rather than a font glyph. */
.k-icon {
	flex: none;
	display: inline-block;
	vertical-align: middle;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	font-variant-numeric: tabular-nums;
}

/**
 * Bands sit flush against each other.
 *
 * Every section owns its own background and gutter, so the root layout must add
 * nothing of its own: no side padding (which would inset the full-bleed bands
 * away from the viewport edge) and no flow gap (which would show the page
 * background as a stripe between the header, each band, and the footer).
 * WordPress writes both with :where(), so a plain class selector wins.
 */
.wp-site-blocks > * {
	margin-block-start: 0;
	margin-block-end: 0;
}

/* Same reason, one level in: bands are children of <main>, whose flow layout
   would otherwise space them apart with the global block gap. Scoped to the band
   components themselves so ordinary content inside them keeps its rhythm. */
.k-header,
.k-hero,
.k-band,
.k-trustbar,
.k-shop,
.k-pdp,
.k-archive,
.k-footer,
/* A template part without an explicit tagName renders inside this wrapper, which
   picks up the gap even though the band inside it does not. */
.wp-block-template-part {
	margin-block: 0;
}

/* Data reads as a spec plate: mono, tabular, never re-flowing on update. */
.k-mono,
.woocommerce-Price-amount,
.k-price {
	font-family: var(--wp--preset--font-family--mono);
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum" 1;
}

/* The recurring uppercase mono label — "Palette", "System", "1 · Contact". */
.k-cap {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: var(--wp--custom--tracking--cap);
	text-transform: uppercase;
	color: var(--k-muted);
	margin: 0;
}

.k-cap--accent { color: var(--k-accent); }
.k-cap--ice { color: var(--wp--preset--color--ice); }

/* Image placeholder — the seamless-grey diagonal used across the design doc. */
.k-swatch {
	background: var(--wp--custom--swatch);
	border: 1px solid var(--k-line);
}

.k-dark .k-swatch,
.k-swatch--void {
	background: var(--wp--custom--swatch-void);
	border-color: var(--wp--preset--color--void-line);
}

:where(a):focus-visible,
:where(button):focus-visible,
:where(input):focus-visible,
:where(select):focus-visible,
:where(textarea):focus-visible,
:where([tabindex]):focus-visible {
	outline: 2px solid var(--k-accent);
	outline-offset: 2px;
	border-radius: 1px;
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
		scroll-behavior: auto !important;
	}
}

/* -------------------------------------------------------------------------- *
 * 1b. Motion layer
 * -------------------------------------------------------------------------- */

/* Lenis needs these to own the scroll position. */
html.lenis,
html.lenis body { height: auto; }

.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/**
 * There is deliberately no CSS "before" state for scroll reveals.
 *
 * Hiding elements in the stylesheet and relying on JavaScript to bring them back
 * means any failure — a blocked module, a stale cache, a bad MIME type — leaves
 * whole sections invisible. The module sets the hidden state itself, and only on
 * elements that are off-screen when it runs, so nothing can be hidden unless the
 * code that reveals it is already running.
 */

/* Cross-document page transitions, where the browser supports them. The header
   and footer are named so they persist instead of cross-fading with the body. */
@view-transition { navigation: auto; }

.k-header { view-transition-name: k-header; }
.k-footer { view-transition-name: k-footer; }

::view-transition-old(root) { animation-duration: .22s; }
::view-transition-new(root) { animation-duration: .32s; }

@media (prefers-reduced-motion: reduce) {
	@view-transition { navigation: none; }
}

.k-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* -------------------------------------------------------------------------- *
 * 2. Controls — 3px radius, ink-filled primary, hairline secondary
 * -------------------------------------------------------------------------- */

.k-btn,
.wp-block-button__link,
button.k-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .5rem;
	padding: 1rem 2.25rem;
	border: 1px solid var(--k-ink);
	border-radius: var(--k-radius);
	background: var(--k-ink);
	color: var(--k-surface);
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 1;
	letter-spacing: .03em;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .18s var(--k-ease), border-color .18s var(--k-ease), color .18s var(--k-ease);
}

.k-btn:hover,
.k-btn:focus-visible {
	background: var(--k-accent);
	border-color: var(--k-accent);
	color: var(--k-surface);
}

/**
 * Variants are written as `.k-btn.k-btn--x`, not `.k-btn--x`.
 *
 * The base rule above qualifies one of its selectors with an element
 * (`button.k-btn`, needed to outrank WordPress's own button styles). That scores
 * (0,1,1), which beats a lone `.k-btn--ghost` at (0,1,0) — so a <button> carrying
 * the ghost class kept rendering solid ink while an <a> with the same class went
 * outlined. Doubling the class takes each variant to (0,2,0), which wins on class
 * count regardless of the tag, so ghost looks the same on a link and a button.
 */
.k-btn.k-btn--ghost {
	background: transparent;
	color: var(--k-ink);
	border-color: rgba(14, 17, 19, .2);
	padding-inline: 1.625rem;
}

.k-btn.k-btn--ghost:hover,
.k-btn.k-btn--ghost:focus-visible {
	background: transparent;
	color: var(--k-accent);
	border-color: var(--k-accent);
}

.k-btn.k-btn--small {
	padding: .4375rem .8125rem;
	font-size: .71875rem;
	letter-spacing: 0;
}

.k-btn.k-btn--block { width: 100%; }

.k-dark .k-btn,
.k-btn.k-btn--onvoid {
	background: var(--wp--preset--color--on-void);
	border-color: var(--wp--preset--color--on-void);
	color: var(--wp--preset--color--void);
}

.k-dark .k-btn:hover,
.k-btn.k-btn--onvoid:hover {
	background: var(--wp--preset--color--ice);
	border-color: var(--wp--preset--color--ice);
	color: var(--wp--preset--color--void);
}

.k-dark .k-btn.k-btn--ghost {
	background: transparent;
	color: var(--wp--preset--color--on-void);
	border-color: rgba(238, 242, 244, .26);
}

.k-dark .k-btn.k-btn--ghost:hover {
	color: var(--wp--preset--color--ice);
	border-color: var(--wp--preset--color--ice);
}

/* Text inputs read as instrument fields: mono, hairline, 3px. */
.k-input,
input[type="text"],
input[type="email"],
input[type="search"],
input[type="tel"],
input[type="number"],
input[type="password"],
input[type="url"],
select,
textarea {
	width: 100%;
	padding: .75rem .8125rem;
	border: 1px solid var(--k-line);
	border-radius: var(--k-radius);
	background: var(--k-surface);
	color: var(--k-ink);
	font-family: var(--wp--preset--font-family--mono);
	font-size: .75rem;
	line-height: 1.4;
	transition: border-color .18s var(--k-ease);
}

.k-input::placeholder,
input::placeholder,
textarea::placeholder { color: var(--k-faint); opacity: 1; }

.k-input:focus,
input:focus,
select:focus,
textarea:focus { border-color: var(--k-accent); }

.k-dark .k-input,
.k-dark input[type="text"],
.k-dark input[type="email"],
.k-dark input[type="search"] {
	background: transparent;
	border-color: rgba(238, 242, 244, .24);
	color: var(--wp--preset--color--on-void);
}

.k-dark .k-input::placeholder { color: var(--wp--preset--color--on-void-4); }

/* The one-line "– 1 +" stepper on the PDP and in the cart drawer. */
.k-qty {
	display: inline-flex;
	align-items: center;
	border: 1px solid rgba(14, 17, 19, .2);
	border-radius: var(--k-radius);
	overflow: hidden;
}

.k-qty button {
	width: 2.5rem;
	align-self: stretch;
	border: 0;
	background: transparent;
	color: var(--k-ink);
	font-family: var(--wp--preset--font-family--mono);
	font-size: .9375rem;
	line-height: 1;
	cursor: pointer;
	transition: color .18s var(--k-ease);
}

.k-qty button:hover { color: var(--k-accent); }

.k-qty input {
	width: 2.75rem;
	padding: .875rem 0;
	border: 0;
	border-radius: 0;
	text-align: center;
	font-family: var(--wp--preset--font-family--mono);
	font-size: .8125rem;
	-moz-appearance: textfield;
	appearance: textfield;
}

.k-qty input::-webkit-outer-spin-button,
.k-qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* -------------------------------------------------------------------------- *
 * 3. Header — wordmark, nav, lot search, cart count
 * -------------------------------------------------------------------------- */

/**
 * Sticky positioning lives on the template-part wrapper, not on .k-header.
 *
 * WordPress renders a template part with tagName "header" as
 * `<header class="wp-block-template-part"><header class="k-header">…</header></header>`
 * — two nested <header> elements. A sticky element is confined to its immediate
 * containing block, and that wrapper is exactly as tall as .k-header itself (it
 * has no other content), so a `position: sticky` on .k-header had nowhere to
 * stick: the moment the page scrolled past the header's own height, the wrapper
 * scrolled fully out of view and dragged the "stuck" header with it. Moving
 * `sticky` up to the wrapper — whose own containing block is `.wp-site-blocks`,
 * i.e. the full page — is what actually keeps it pinned for the whole scroll.
 * `display: flow-root` on the wrapper stops the inner pill's margin-top (used
 * for the "floats down from the edge" scrolled state) from collapsing through
 * it and dragging the sticky wrapper down with it.
 */
header.wp-block-template-part:first-child {
	position: sticky;
	top: 0;
	z-index: 60;
	display: flow-root;
}

.admin-bar header.wp-block-template-part:first-child { top: var(--wp-admin--admin-bar--height, 32px); }

/**
 * The dock animation, and why it is built this way.
 *
 * The obvious way to inset a full-bleed bar into a floating pill is to animate
 * `max-width` and `margin-inline` on the bar itself. It does not work: the bar
 * starts at `max-width: none` and `margin-inline: 0`, and neither `none` nor
 * `auto` is an interpolatable value. The browser cannot tween them, so the bar
 * jumps sideways in a single frame while the radius eases — which is exactly
 * what made the first version look broken.
 *
 * So the inset is done with padding on the outer element instead. Every animated
 * value here is a length or a colour, so all of it actually tweens:
 *
 *   .k-header       padding — opens the gap at the top and both sides
 *   .k-header__bar  radius, background, border, shadow — the chrome
 *   .k-header__inner  padding-block — the height shrink
 */
.k-header {
	position: relative;
	padding: 0;
	transition: padding var(--k-nav-dur) var(--k-nav-ease);
}

/**
 * Docked, the bar pulls in to the content column — the same 1180px the hero,
 * the catalog and the footer align to — so the pill reads as part of the grid
 * rather than as an arbitrary floating strip. `max()` keeps a minimum breathing
 * gap on viewports narrower than that column. Both branches resolve to lengths,
 * so the whole thing still tweens.
 */
.k-header.is-scrolled {
	padding:
		.625rem
		max(clamp(.75rem, 2vw, 2rem), calc((100% - var(--wp--style--global--wide-size)) / 2))
		0;
}

/* The visible bar. Chrome lives here so the outer element is free to animate
   the inset without the background moving with it. */
.k-header__bar {
	padding-inline: var(--k-gutter);
	background: rgba(255, 255, 255, .94);
	backdrop-filter: saturate(180%) blur(12px);
	/* A full transparent border from the start: the scrolled state only changes
	   its colour, so the bar never changes size and nothing shifts. */
	border: 1px solid transparent;
	border-bottom-color: var(--k-line);
	border-radius: 0;
	box-shadow: 0 0 0 0 rgba(14, 17, 19, 0);
	transition:
		background-color var(--k-nav-dur) var(--k-nav-ease),
		border-color var(--k-nav-dur) var(--k-nav-ease),
		border-radius var(--k-nav-dur) var(--k-nav-ease),
		box-shadow var(--k-nav-dur) var(--k-nav-ease),
		padding-inline var(--k-nav-dur) var(--k-nav-ease);
}

.k-header.is-scrolled .k-header__bar {
	padding-inline: clamp(1rem, 2vw, 1.75rem);
	/* Denser than at rest, not lighter. At rest the bar sits on the page's own
	   background; docked it floats over whatever is scrolling past, so the type
	   inside has to stay readable even where backdrop-filter is unsupported. */
	background: rgba(255, 255, 255, .92);
	backdrop-filter: saturate(200%) blur(20px);
	border-color: rgba(14, 17, 19, .07);
	border-radius: var(--wp--custom--radius--pill);
	/* Two shadows: a wide soft one for lift, a tight one to seat the edge. */
	box-shadow:
		0 12px 32px -14px rgba(14, 17, 19, .26),
		0 2px 6px -3px rgba(14, 17, 19, .10);
}

.k-header__inner {
	display: flex;
	align-items: center;
	gap: 1.625rem;
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	padding-block: .875rem;
	transition: padding-block var(--k-nav-dur) var(--k-nav-ease);
}

/* The shrink. A gentle tightening, not a collapse: the docked pill keeps enough
   vertical body that it still reads as a proper bar, not a thin strip. */
.k-header.is-scrolled .k-header__inner { padding-block: .6875rem; }

/* The wordmark's square scales with a transform rather than width/height: it is
   a solid block, so it stays crisp, and the compositor handles it. The wordmark
   text is deliberately left at its own size — animating font-size reflows the
   row and renders the type soft mid-tween, which cheapens the whole effect. */
.k-wordmark::before {
	transition: transform var(--k-nav-dur) var(--k-nav-ease);
}

.k-header.is-scrolled .k-wordmark::before { transform: scale(.9); }

/**
 * Phones dock too.
 *
 * The inset resolves on its own: `max()` picks the clamp branch once the viewport
 * is narrower than the content column, so no separate padding rule is needed.
 * The radius is the full stadium here, same as desktop — that only looked wrong
 * while the bar was two rows tall and the curve bowed away from the content. On
 * a single row it is simply a capsule.
 */
@media (max-width: 900px) {
	.k-header.is-scrolled .k-header__bar { border-radius: var(--wp--custom--radius--pill); }

	/**
	 * Open, the capsule stops being a capsule.
	 *
	 * A 999px radius is right for a 52px bar on its own, but once the panel hangs
	 * off its bottom edge the bar is just the head of a tall card — and that same
	 * curve then reads as an odd bulge that does not answer the 1.25rem corners at
	 * the foot. Both ends take the same radius so the open menu is one coherent
	 * rounded rectangle, and the shared seam squares off.
	 */
	.k-header.is-scrolled.is-open .k-header__bar {
		border-radius: 1.25rem 1.25rem 0 0;
	}

	.k-header.is-scrolled .k-header__panel {
		border-bottom-left-radius: 1.25rem;
		border-bottom-right-radius: 1.25rem;
	}

	/* Opaque while open: the bar is normally translucent over the page, but the
	   panel below it is solid, and the two finishes meeting mid-card showed the
	   join as a grey band across the top. */
	.k-header.is-open .k-header__bar {
		background: var(--k-surface);
		border-bottom-color: var(--k-line);
	}
}

/* Wordmark: solid square + tight grotesk. The square doubles as the lot stamp. */
.k-wordmark {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	text-decoration: none;
	flex: none;
}

.k-wordmark::before {
	content: "";
	width: 10px;
	height: 10px;
	background: var(--k-ink);
	flex: none;
}

.k-wordmark__text {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.0625rem;
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--display);
	line-height: 1;
	color: var(--k-ink);
	text-transform: uppercase;
}

.k-wordmark__descriptor {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .65625rem;
	letter-spacing: .1em;
	color: var(--k-muted);
}

.k-dark .k-wordmark::before { background: var(--wp--preset--color--ice); }
.k-dark .k-wordmark__text { color: var(--wp--preset--color--on-void); }

.k-nav ul {
	display: flex;
	gap: 1.375rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.k-nav a {
	font-size: .78125rem;
	color: var(--k-ink);
	text-decoration: none;
	padding-bottom: 2px;
	border-bottom: 2px solid transparent;
	transition: border-color .18s var(--k-ease), color .18s var(--k-ease);
}

.k-nav a:hover,
.k-nav .current-menu-item > a,
.k-nav [aria-current="page"] {
	border-bottom-color: var(--k-accent);
	color: var(--k-ink);
}

.k-dark .k-nav a { color: var(--wp--preset--color--on-void-2); }
.k-dark .k-nav a:hover,
.k-dark .k-nav [aria-current="page"] { border-bottom-color: var(--wp--preset--color--ice); color: var(--wp--preset--color--on-void); }

/* Deliberately not `flex: 1`. The search carries `margin-left: auto` to push
   itself and everything after it to the right; if this group grew instead, it
   would swallow the free space and strand the search mid-row. */
.k-header__end {
	flex: none;
	display: flex;
	justify-content: flex-end;
	align-items: center;
	gap: 1rem;
}

/* Search takes a peptide name or a lot number — same field, two jobs. */
.k-search {
	position: relative;
	min-width: 230px;
}

.k-search input[type="search"] {
	padding: .4375rem .75rem .4375rem 1.875rem;
	font-size: .6875rem;
}

/* Lucide "search" as a mask, so it tints with the field's own muted grey and
   sharpens the focus colour for free. A real magnifier — ring plus handle —
   instead of the bare ring the old border-circle drew. */
.k-search::before {
	content: "";
	position: absolute;
	left: .625rem;
	top: 50%;
	width: 15px;
	height: 15px;
	transform: translateY(-50%);
	background-color: var(--k-muted);
	-webkit-mask: var(--k-icon-search) center / contain no-repeat;
	        mask: var(--k-icon-search) center / contain no-repeat;
	transition: background-color .18s var(--k-ease);
	pointer-events: none;
}

/* The field turns its icon to the accent while focused — a small, cheap cue that
   the search is live. */
.k-search:focus-within::before { background-color: var(--k-accent); }

.k-search button[type="submit"] { display: none; }

.k-cart-link {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	font-size: .75rem;
	color: var(--k-ink);
	text-decoration: none;
	white-space: nowrap;
	background: none;
	border: 0;
	cursor: pointer;
	font-family: inherit;
}

.k-cart-link:hover { color: var(--k-accent); }
.k-dark .k-cart-link { color: var(--wp--preset--color--on-void); }

/* The icon leads; the count nudges toward it so the trio reads as one unit. */
.k-cart-link__icon { margin-right: -.125rem; }
.k-cart-link__count { font-family: var(--wp--preset--font-family--mono); }

/* On desktop the panel wrapper is not a box at all — `display: contents` drops it
   out of the layout so the nav inside becomes a direct flex item of the header
   row, exactly as it was before the wrapper existed. Its foot is mobile-only. */
.k-header__panel,
.k-header__panel-inner { display: contents; }
.k-header__panel-foot { display: none; }

/* On desktop the search sits at the far right of the row, ahead of the cart.
   Scoped through the parent because WordPress's flex layout ships
   `.is-layout-flex > :is(*, div) { margin: 0 }` at (0,1,1), which outranks a
   bare `.k-search` and would zero this out. */
.k-header__inner > .k-search { margin-left: auto; }

/* -------------------------------------------------------------------------- *
 * 3b. Hamburger
 * -------------------------------------------------------------------------- */

.k-header__toggle {
	display: none;
	position: relative;
	/* 44px is the minimum comfortable touch target; the icon inside is 18px. */
	width: 44px;
	height: 44px;
	margin-right: -.625rem;
	background: none;
	border: 0;
	padding: 0;
	color: var(--k-ink);
	cursor: pointer;
}

/* Three rules from two elements: the span is the middle bar, its pseudo-elements
   are the outer two. On open the middle fades and the outer two cross. */
.k-burger,
.k-burger::before,
.k-burger::after {
	position: absolute;
	left: 50%;
	width: 20px;
	height: 2px;
	background: currentColor;
	transition:
		transform var(--k-nav-dur) var(--k-nav-ease),
		background-color .18s var(--k-ease);
}

.k-burger {
	top: 50%;
	margin-left: -10px;
	transform: translateY(-50%);
}

.k-burger::before,
.k-burger::after {
	content: "";
	left: 0;
	margin-left: 0;
}

.k-burger::before { top: -6px; }
.k-burger::after { top: 6px; }

/* Hide the middle bar by clearing its own background, not with opacity: opacity
   applies to the element *and* its pseudo-elements, so fading the span took the
   two bars that form the X with it and the icon vanished entirely when open. */
.k-header.is-open .k-burger { background-color: transparent; }
.k-header.is-open .k-burger::before { transform: translateY(6px) rotate(45deg); }
.k-header.is-open .k-burger::after { transform: translateY(-6px) rotate(-45deg); }

/* -------------------------------------------------------------------------- *
 * 3c. Mobile header — search on its own row, nav in a drop panel
 * -------------------------------------------------------------------------- */

/**
 * One row, not two.
 *
 * The search had its own full-width row, which is what made the bar read as a
 * thick slab: two stacked rows plus the gap between them, and a large empty
 * field carrying half of it. Inlining the field puts the whole header on a
 * single line and roughly halves its height, while still keeping the lookup
 * permanently visible — which is the part that actually mattered.
 */
@media (max-width: 900px) {
	.k-header__inner {
		flex-wrap: nowrap;
		gap: .5rem;
		padding-block: .4375rem;
	}

	/* 40px stays a comfortable target; the negative margin keeps it from setting
	   the row height, so the button does not inflate the bar around it. */
	.k-header__toggle {
		display: block;
		width: 40px;
		height: 40px;
		margin-right: -.5rem;
		flex: none;
	}

	.k-header__end {
		flex: none;
		gap: .5rem;
	}

	.k-wordmark { flex: none; }
	.k-wordmark__text { font-size: .9375rem; }

	/* The field takes whatever the fixed elements leave. */
	.k-header__inner > .k-search {
		order: 0;
		flex: 1 1 auto;
		flex-basis: auto;
		min-width: 0;
		margin-left: 0;
	}

	/* A tinted capsule rather than a bordered box: a hard-edged rectangle sitting
	   inside the rounded bar read as a box within a box. Filled and pill-shaped,
	   the field belongs to the bar instead of interrupting it. */
	.k-search input[type="search"] {
		padding-block: .4375rem;
		padding-left: 1.75rem;
		font-size: .6875rem;
		text-overflow: ellipsis;
		background: rgba(14, 17, 19, .045);
		border-color: transparent;
		border-radius: var(--wp--custom--radius--pill);
		transition:
			padding-block var(--k-nav-dur) var(--k-nav-ease),
			background-color .18s var(--k-ease),
			border-color .18s var(--k-ease);
	}

	.k-search input[type="search"]:focus {
		background: var(--k-surface);
		border-color: var(--k-accent);
	}

	.k-search::before { left: .6875rem; }

	/* Icon + count only on phones: the search field wants the width, and the bag
	   glyph already says "cart" without the word. */
	.k-cart-link { font-size: .6875rem; gap: .25rem; }
	.k-cart-link__label { display: none; }
	.k-cart-link__icon { margin-right: 0; }

	/* Docked, the single row tightens a little — but keeps enough height that the
	   capsule still feels like a bar you can tap into, not a sliver. */
	.k-header.is-scrolled .k-header__inner { padding-block: .5rem; }
	.k-header.is-scrolled .k-search input[type="search"] { padding-block: .375rem; }

	/**
	 * The nav becomes a drop panel.
	 *
	 * `nav.k-nav` rather than `.k-nav`: WordPress copies the block's className
	 * onto both the <nav> and its inner <ul>, so a bare `.k-nav` would position
	 * the list as a second panel. The element qualifier also lifts specificity
	 * above the `.wp-container-*` layout class WordPress prints inline, which is
	 * what stopped the old `display: none` from ever applying.
	 */
	/**
	 * The card grows; the panel does not arrive.
	 *
	 * This used to fade and slide in as its own layer while the bar above it
	 * morphed its corners — two different kinds of motion on what the eye reads
	 * as one object, which is exactly why it looked wrong. Animating the height
	 * instead makes the bar and the menu a single shape that unfolds downward,
	 * and the corner morph then belongs to that same movement.
	 *
	 * `grid-template-rows: 0fr → 1fr` is what makes an auto height animatable at
	 * all: the row resolves against the content, so nothing has to be measured in
	 * JavaScript and the menu can change length freely.
	 */
	.k-header__panel {
		display: grid;
		grid-template-rows: 0fr;
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		z-index: 5;
		/* Inline padding only — vertical padding would survive the collapse and
		   leave a strip of bar hanging below the capsule. The foot carries the
		   bottom spacing instead, inside the part that actually collapses. */
		padding: 0 var(--k-gutter);
		background: var(--k-surface);
		/* No border-top: the bar directly above already draws a bottom edge, and
		   two hairlines meeting at the seam read as a seam. */
		box-shadow: 0 18px 30px -20px rgba(14, 17, 19, .35);
		visibility: hidden;
		transition:
			grid-template-rows var(--k-nav-dur) var(--k-nav-ease),
			visibility var(--k-nav-dur);
	}

	/* A real box again — on desktop this is `display: contents`, and left that way
	   the nav and the foot become two separate grid rows, so the single
	   `0fr` track only ever collapsed the first one and the panel never closed. */
	.k-header__panel-inner {
		display: block;
		min-height: 0;
		max-height: calc(100dvh - 8rem);
		overflow: hidden auto;
		overscroll-behavior: contain;
	}

	.k-header.is-open .k-header__panel {
		grid-template-rows: 1fr;
		visibility: visible;
	}

	/* The nav is now just content inside the panel. */
	nav.k-nav {
		display: block;
		position: static;
		width: 100%;
	}

	/**
	 * Generous stacked rows on hairlines — the same spec-sheet language as the
	 * product page's disclosure rows.
	 *
	 * The Navigation block nests a second list, `ul.wp-block-page-list`, and that
	 * is where the items actually live. WordPress styles it with
	 * `.wp-block-navigation .wp-block-page-list` at (0,2,0), which outranks a
	 * `.k-nav ul` rule — so the items stayed in a row and ran together on one
	 * line. Naming the inner list explicitly, with the element qualifier, wins.
	 * The custom properties are set too, since that is the knob WordPress's own
	 * rule reads from.
	 */
	nav.k-nav {
		--navigation-layout-direction: column;
		--navigation-layout-justify: flex-start;
		--navigation-layout-align: stretch;
		--navigation-layout-wrap: nowrap;
	}

	nav.k-nav ul,
	nav.k-nav .wp-block-page-list {
		display: flex;
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		width: 100%;
	}

	nav.k-nav li {
		border-bottom: 1px solid var(--k-line);
		width: 100%;
	}

	nav.k-nav li:last-child { border-bottom: 0; }

	/**
	 * Rows are sized by their touch target, not by padding for its own sake.
	 * 48px clears the 44px minimum comfortably, where the previous 61px was just
	 * air — across five items that alone reclaimed most of a screenful. The arrow
	 * anchors the right edge, which was dead width before.
	 */
	nav.k-nav a,
	nav.k-nav .wp-block-navigation-item__content {
		/* Both selectors, and the second one qualified: WordPress styles the link
		   through `.wp-block-navigation .wp-block-navigation-item__content` at
		   (0,2,0), which outranks `nav.k-nav a` and kept the row `display: block`.
		   border-box so min-height is the row height, not the height on top of
		   the padding — that alone was adding 16px to every row. */
		box-sizing: border-box;
		display: flex;
		align-items: center;
		width: 100%;
		min-height: 46px;
		padding: .375rem .125rem;
		font-size: 1rem;
		font-weight: 500;
		letter-spacing: var(--wp--custom--tracking--tight);
		line-height: 1.3;
		border-bottom: 0;
	}

	/* A mono index down the left edge. The column was empty, and a numbered
	   register is the same language the lot stamps and spec tables already
	   speak — it reads as deliberate rather than as margin. */
	nav.k-nav ul { counter-reset: k-nav-item; }
	nav.k-nav li { counter-increment: k-nav-item; }

	nav.k-nav a::before {
		content: counter(k-nav-item, decimal-leading-zero);
		margin-right: .875rem;
		font-family: var(--wp--preset--font-family--mono);
		font-size: .625rem;
		font-weight: 400;
		letter-spacing: .06em;
		color: var(--k-faint);
	}

	nav.k-nav a::after {
		content: "→";
		margin-left: auto;
		font-family: var(--wp--preset--font-family--mono);
		font-size: .8125rem;
		color: var(--k-faint);
		transition: transform .18s var(--k-ease), color .18s var(--k-ease);
	}

	nav.k-nav a:hover::before { color: var(--k-accent); }

	.k-nav a:hover,
	.k-nav [aria-current="page"] { color: var(--k-accent); border-bottom: 0; }

	nav.k-nav a:hover::after { color: var(--k-accent); transform: translateX(3px); }

	/**
	 * The foot of the panel.
	 *
	 * What was blank space below the last link now carries the three standing
	 * claims and the support promise — the same copy the trust bar and the footer
	 * already run. It answers the two questions a first-time buyer actually has
	 * while the menu is open, instead of padding the panel out to nothing.
	 */
	.k-header__panel-foot {
		display: block;
		margin-top: .625rem;
		padding-top: .875rem;
		/* The panel's bottom spacing lives here so it collapses with the content
		   rather than propping the closed panel open. */
		padding-bottom: 1rem;
		border-top: 1px solid var(--k-line);
	}

	.k-header__claim {
		display: flex;
		align-items: center;
		gap: .5rem;
		margin: 0 0 .4375rem;
		font-family: var(--wp--preset--font-family--mono);
		font-size: .625rem;
		letter-spacing: .08em;
		text-transform: uppercase;
		color: var(--k-muted);
	}

	.k-header__claim::before {
		content: "";
		width: 5px;
		height: 5px;
		background: var(--k-accent);
		flex: none;
	}

	.k-header__support {
		margin: .875rem 0 0;
		font-family: var(--wp--preset--font-family--mono);
		font-size: .625rem;
		line-height: 1.7;
		color: var(--k-faint);
	}

	/**
	 * A scrim so the panel reads as a layer over the page, not part of it.
	 *
	 * `z-index: 1`, never a negative value: at -1 it paints behind the page's own
	 * content and dims nothing at all. The bar above it is lifted to 2 so both it
	 * and the panel it contains stay clear of the scrim.
	 */
	.k-header__bar { position: relative; z-index: 2; }

	.k-header::after {
		content: "";
		position: fixed;
		inset: 0;
		z-index: 1;
		background: rgba(14, 17, 19, .28);
		opacity: 0;
		visibility: hidden;
		transition: opacity var(--k-nav-dur) var(--k-nav-ease), visibility var(--k-nav-dur);
	}

	.k-header.is-open::after { opacity: 1; visibility: visible; }

	body.k-menu-open { overflow: hidden; }
}

/**
 * Below roughly a 420px screen the wordmark's text is what has to give, not the
 * search. The solid square is the mark in its own right — the design doc has it
 * doubling as the lot stamp and the favicon — so dropping the lettering keeps
 * the brand present and hands the width to the field.
 */
@media (max-width: 420px) {
	.k-wordmark__text { display: none; }
	.k-wordmark::before { width: 12px; height: 12px; }
}

/* -------------------------------------------------------------------------- *
 * 4. Layout bands
 * -------------------------------------------------------------------------- */

.k-band {
	padding-block: var(--wp--preset--spacing--70);
	padding-inline: var(--k-gutter);
}

.k-band--grey { background: var(--k-grey); }
.k-band--surface { background: var(--k-surface); border-top: 1px solid var(--k-line); }
.k-band--tight { padding-block: var(--wp--preset--spacing--60); }

.k-band__inner {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

.k-band__inner--narrow { max-width: var(--wp--style--global--content-size); }

/* Section head: title left, "Full catalog →" right, baseline-aligned. */
.k-sectionhead {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.5rem;
	flex-wrap: wrap;
	margin-bottom: var(--wp--preset--spacing--40);
}

.k-sectionhead__title {
	font-size: var(--wp--preset--font-size--display-s);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--display);
	line-height: 1.1;
	margin: 0;
}

.k-sectionhead__sub {
	font-size: var(--wp--preset--font-size--small);
	color: var(--k-muted);
	margin: .5rem 0 0;
}

.k-link-arrow {
	font-size: .8125rem;
	font-weight: 500;
	color: var(--k-ink);
	text-decoration: none;
	border-bottom: 1px solid var(--k-accent);
	padding-bottom: 2px;
	white-space: nowrap;
}

.k-link-arrow:hover { color: var(--k-accent); }

.k-grid-3 {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--40);
}

@media (max-width: 900px) { .k-grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .k-grid-3 { grid-template-columns: 1fr; } }

/* -------------------------------------------------------------------------- *
 * 5. Hero
 * -------------------------------------------------------------------------- */

.k-hero {
	background: var(--k-grey);
	padding-inline: var(--k-gutter);
	padding-block: var(--wp--preset--spacing--80) calc(var(--wp--preset--spacing--80) * 1.3);
}

.k-hero__inner {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	display: grid;
	grid-template-columns: 1.06fr .94fr;
	gap: clamp(1.5rem, 1rem + 2.6vw, 3.375rem);
	align-items: center;
}

.k-hero__eyebrow {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--k-accent);
	margin: 0;
}

.k-hero__title {
	font-size: var(--wp--preset--font-size--display-l);
	font-weight: 600;
	line-height: 1;
	letter-spacing: -.04em;
	max-width: 11em;
	margin: 1.5rem 0 1.375rem;
}

.k-hero__lede {
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.65;
	color: var(--k-body);
	max-width: 33em;
	margin: 0 0 2.125rem;
}

.k-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: .75rem;
	align-items: center;
}

.k-hero__note {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .6875rem;
	color: var(--k-muted);
	margin: 1.375rem 0 0;
}

.k-hero__media {
	aspect-ratio: 4 / 5;
	overflow: hidden;
}

.k-hero__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.k-dark.k-hero { background: var(--wp--preset--color--void); }
.k-dark .k-hero__eyebrow { color: var(--wp--preset--color--ice); }
.k-dark .k-hero__title { color: var(--wp--preset--color--on-void); }
.k-dark .k-hero__lede { color: var(--wp--preset--color--on-void-3); }
.k-dark .k-hero__note { color: var(--wp--preset--color--on-void-4); }

@media (max-width: 782px) {
	.k-hero__inner { grid-template-columns: 1fr; }
	.k-hero__media { aspect-ratio: 4 / 3; order: 2; }
	.k-hero__actions .k-btn { width: 100%; }
}

/* -------------------------------------------------------------------------- *
 * 6. Trust bar
 * -------------------------------------------------------------------------- */

.k-trustbar {
	background: var(--k-ink);
	padding: 1.375rem var(--k-gutter);
}

.k-trustbar__inner {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	display: flex;
	justify-content: center;
	flex-wrap: wrap;
	gap: 1rem clamp(1.5rem, .5rem + 4vw, 4.5rem);
}

.k-trustbar__item {
	display: flex;
	align-items: center;
	gap: .625rem;
	font-family: var(--wp--preset--font-family--mono);
	font-size: .75rem;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--on-void);
}

.k-trustbar__item::before {
	content: "";
	width: 7px;
	height: 7px;
	background: var(--wp--preset--color--ice);
	flex: none;
}

@media (max-width: 600px) {
	.k-trustbar__inner { flex-direction: column; justify-content: flex-start; gap: .5625rem; }
}

/* -------------------------------------------------------------------------- *
 * 7. System strip — the traceability claim plus three figures
 * -------------------------------------------------------------------------- */

.k-system {
	display: grid;
	grid-template-columns: .85fr 1.15fr;
	gap: clamp(1.5rem, 1rem + 3vw, 3.75rem);
	max-width: var(--wp--style--global--content-size);
	margin-inline: auto;
}

.k-system__title {
	font-size: var(--wp--preset--font-size--display-s);
	line-height: 1.1;
	letter-spacing: var(--wp--custom--tracking--display);
	margin: .875rem 0 0;
}

.k-system__body {
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.7;
	color: var(--k-body);
	margin: 0 0 1.875rem;
	text-wrap: pretty;
}

.k-figures {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1.5rem;
	border-top: 1px solid var(--k-line);
	padding-top: 1.5rem;
}

.k-figure__value {
	font-size: var(--wp--preset--font-size--heading-m);
	font-weight: 600;
	letter-spacing: var(--wp--custom--tracking--display);
	line-height: 1.1;
}

.k-figure__label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .6875rem;
	line-height: 1.5;
	color: var(--k-muted);
	margin-top: .3125rem;
}

.k-dark .k-system__title { color: var(--wp--preset--color--on-void); }
.k-dark .k-system__body { color: var(--wp--preset--color--on-void-3); }
.k-dark .k-figures { border-top-color: var(--wp--preset--color--void-line); }
.k-dark .k-figure__value { color: var(--wp--preset--color--on-void); }
.k-dark .k-figure__label { color: var(--wp--preset--color--on-void-4); }

@media (max-width: 782px) { .k-system { grid-template-columns: 1fr; } }
@media (max-width: 480px) { .k-figures { grid-template-columns: 1fr; gap: 1rem; } }

/* -------------------------------------------------------------------------- *
 * 8. Reviews — initials, lab type, verified purchase. No star inflation.
 * -------------------------------------------------------------------------- */

.k-review {
	border-top: 2px solid var(--k-accent);
	padding-top: 1.25rem;
}

.k-review__quote {
	font-size: var(--wp--preset--font-size--heading-s);
	line-height: 1.55;
	color: var(--k-ink);
	margin: 0 0 1.125rem;
}

.k-review__meta {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	line-height: 1.6;
	color: var(--k-muted);
}

.k-review__verified { color: var(--k-accent); display: block; }

.k-dark .k-review { border-top-color: var(--wp--preset--color--ice); }
.k-dark .k-review__quote { color: var(--wp--preset--color--on-void); }
.k-dark .k-review__meta { color: var(--wp--preset--color--on-void-4); }
.k-dark .k-review__verified { color: var(--wp--preset--color--ice); }

/* -------------------------------------------------------------------------- *
 * 9. Field Notes — editorial cards
 * -------------------------------------------------------------------------- */

.k-note__media {
	aspect-ratio: 16 / 10;
	overflow: hidden;
	display: block;
}

.k-note__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

.k-note__kicker {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .625rem;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--k-accent);
	margin: .875rem 0 .4375rem;
}

/* Post Terms renders the categories as links, which would otherwise pick up the
   global link colour instead of the kicker's accent. */
.k-note__kicker a {
	color: inherit;
	text-decoration: none;
}

.k-note__kicker a:hover { text-decoration: underline; }

.k-note__title {
	font-size: var(--wp--preset--font-size--heading-s);
	font-weight: 500;
	line-height: 1.35;
	letter-spacing: var(--wp--custom--tracking--tight);
	margin: 0;
}

.k-note__title a { text-decoration: none; color: inherit; }
.k-note__title a:hover { color: var(--k-accent); }

/* -------------------------------------------------------------------------- *
 * 10. Footer
 * -------------------------------------------------------------------------- */

.k-footer {
	background: var(--k-ink);
	color: var(--wp--preset--color--on-void-2);
	padding: var(--wp--preset--spacing--70) var(--k-gutter) 1.875rem;
}

.k-footer__inner { max-width: var(--wp--style--global--wide-size); margin-inline: auto; }

.k-footer__cols {
	display: grid;
	grid-template-columns: 1.4fr 1fr 1fr 1fr;
	gap: 2.5rem;
	padding-bottom: 2.75rem;
	border-bottom: 1px solid rgba(238, 242, 244, .14);
}

.k-footer__blurb {
	font-size: .8125rem;
	line-height: 1.65;
	color: var(--wp--preset--color--on-void-3);
	margin: 0 0 1.125rem;
	max-width: 26em;
}

.k-footer__heading {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--ice);
	margin: 0 0 .875rem;
}

.k-footer__list { list-style: none; margin: 0; padding: 0; }
.k-footer__list li { line-height: 2; }

.k-footer__list a,
.k-footer a {
	font-size: .8125rem;
	color: var(--wp--preset--color--on-void-2);
	text-decoration: none;
}

.k-footer__list a:hover,
.k-footer a:hover { color: var(--wp--preset--color--ice); }

.k-footer__signup { display: flex; gap: .5rem; max-width: 320px; }
.k-footer__signup input { flex: 1; }

.k-footer__support {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	line-height: 1.7;
	color: var(--wp--preset--color--on-void-3);
	margin-top: 1.125rem;
}

.k-footer__legal {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 1rem;
	flex-wrap: wrap;
	padding-top: 1.375rem;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	line-height: 1.7;
	color: #7D858B;
}

.k-footer__legal a { font-size: inherit; color: inherit; }

@media (max-width: 900px) { .k-footer__cols { grid-template-columns: 1fr 1fr; gap: 2rem; } }
@media (max-width: 600px) { .k-footer__cols { grid-template-columns: 1fr; } }

/* -------------------------------------------------------------------------- *
 * 11. Lab Archive — the trust engine, dark by default
 * -------------------------------------------------------------------------- */

.k-dark,
.k-archive {
	background: var(--wp--preset--color--void);
	color: var(--wp--preset--color--on-void-2);
}

.k-dark :where(h1, h2, h3, h4, h5) { color: var(--wp--preset--color--on-void); }

.k-archive__hero {
	padding: var(--wp--preset--spacing--70) var(--k-gutter) var(--wp--preset--spacing--60);
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}

.k-archive__title {
	font-size: var(--wp--preset--font-size--display-m);
	line-height: 1.02;
	letter-spacing: -.04em;
	color: var(--wp--preset--color--on-void);
	max-width: 16em;
	margin: 1rem 0 .875rem;
}

.k-archive__lede {
	font-size: .9375rem;
	line-height: 1.65;
	color: var(--wp--preset--color--on-void-3);
	max-width: 38em;
	margin: 0 0 1.625rem;
}

.k-lot-lookup {
	display: flex;
	gap: .625rem;
	max-width: 34rem;
}

.k-lot-lookup input { flex: 1; padding: .9375rem 1rem; font-size: .78125rem; }
.k-lot-lookup .k-btn { padding-inline: 1.75rem; flex: none; }

.k-archive__result {
	background: var(--wp--preset--color--void-2);
	border-top: 1px solid var(--wp--preset--color--void-line);
	padding: var(--wp--preset--spacing--40) var(--k-gutter);
}

.k-archive__result-inner { max-width: var(--wp--style--global--wide-size); margin-inline: auto; }

.k-archive__lot {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 1rem;
	flex-wrap: wrap;
	margin-bottom: 1.25rem;
}

.k-archive__lot-name {
	font-size: 1.0625rem;
	font-weight: 500;
	letter-spacing: var(--wp--custom--tracking--tight);
	color: var(--wp--preset--color--on-void);
}

.k-archive__verdict {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	letter-spacing: .08em;
	color: var(--wp--preset--color--ice);
}

.k-archive__verdict--fail { color: #E8887F; }

/* 1px gaps on a hairline background give the grid its instrument-panel look. */
.k-metrics {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 1px;
	background: var(--wp--preset--color--void-line);
	border: 1px solid var(--wp--preset--color--void-line);
}

.k-metric { background: var(--wp--preset--color--void-3); padding: 1rem; }

.k-metric__label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .625rem;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--on-void-4);
}

.k-metric__value {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 1.375rem;
	font-weight: 500;
	color: var(--wp--preset--color--on-void);
	margin-top: .375rem;
}

.k-archive__detail {
	display: flex;
	gap: 1.375rem;
	margin-top: 1.375rem;
	align-items: stretch;
}

.k-archive__chart { flex: 1; aspect-ratio: 16 / 7; overflow: hidden; }
.k-archive__chart img { width: 100%; height: 100%; object-fit: cover; display: block; }

.k-archive__actions {
	width: 220px;
	flex: none;
	display: grid;
	gap: .5625rem;
	align-content: start;
}

.k-archive__source {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .625rem;
	line-height: 1.7;
	color: var(--wp--preset--color--on-void-4);
	margin-top: .25rem;
}

.k-archive__foot {
	background: var(--wp--preset--color--void-4);
	padding: 1.25rem var(--k-gutter);
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	line-height: 1.7;
	color: #6B7379;
}

.k-archive__empty {
	font-family: var(--wp--preset--font-family--mono);
	font-size: .78125rem;
	line-height: 1.8;
	color: var(--wp--preset--color--on-void-3);
}

@media (max-width: 900px) { .k-metrics { grid-template-columns: repeat(2, 1fr); } }

@media (max-width: 782px) {
	.k-archive__detail { flex-direction: column; }
	.k-archive__actions { width: 100%; }
	.k-lot-lookup { flex-direction: column; }
}

/* -------------------------------------------------------------------------- *
 * 12. Editorial content (Field Notes posts, policy pages)
 * -------------------------------------------------------------------------- */

.k-prose { max-width: 40rem; }
.k-prose > * + * { margin-top: 1.375rem; }
.k-prose p { line-height: 1.75; color: var(--k-body); }
.k-prose h2 { font-size: var(--wp--preset--font-size--heading-l); margin-top: 2.75rem; }
.k-prose h3 { font-size: var(--wp--preset--font-size--heading-m); margin-top: 2.25rem; }
.k-prose a { color: var(--k-accent); text-decoration: underline; text-underline-offset: .2em; }
.k-prose blockquote {
	border-top: 2px solid var(--k-accent);
	border-left: 0;
	padding: 1.125rem 0 0;
	margin-inline: 0;
	font-size: var(--wp--preset--font-size--heading-s);
	line-height: 1.55;
}
.k-prose figcaption {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	color: var(--k-muted);
}

/* -------------------------------------------------------------------------- *
 * 13. Compliance notice — footer, cart, checkout confirmation
 * -------------------------------------------------------------------------- */

.k-compliance {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--cap);
	line-height: 1.7;
	color: var(--k-faint);
}

.k-compliance--panel {
	border: 1px solid var(--k-line);
	border-radius: var(--k-radius);
	padding: .875rem 1rem;
	background: var(--k-grey);
	color: var(--k-muted);
}

.k-dark .k-compliance { color: var(--wp--preset--color--on-void-4); }
