/*
 * PouchPick Header — HD.1 FINAL (Human Design Lock 2026-10-16,
 * design-locks/HD1-HEADER-FINAL-LOCK.md; design authority
 * ~/Documents/PouchPick-Labs/design/header-evolution-hd1/final/):
 * Concept C Dark Premium — the navy commerce bar and nav row under the
 * chrome-navy rail, the official wordmark in Lime without a plate (larger:
 * 188 → 143px desktop, 164 → 132 tablet, 124 mobile), the white Search
 * field and Cart pill, the shopping spine left and the services cluster
 * right — and S2 Fluid Compact: ONE scroll value --p (0 full … 1 compact,
 * the first 140px of scroll, header.js) sizes the bar, the logo, the nav
 * row and the Search slot continuously. The responsive architecture
 * (>=1180 desktop / 768–1179 tablet / <=767 mobile) is preserved; the
 * header is fixed over a constant spacer at >=768 (content never moves)
 * and sticky + persistent on mobile (UI.1).
 *
 * Kept from the earlier locks: the rotating ticker (lock §20; the mobile
 * strip moves continuously since MOB-03),
 * the Search field mechanics, the Market selector + its INT.4 motion, the
 * Cart hooks, the SB.1C shipping surfaces, the nav-item grammar (Barlow 600
 * 15.5px, underline reveal, caret, the human-locked 1×16 divider) — on the
 * dark skin. Superseded locks: see the HD.1 lock's supersession table.
 */

/* Registered so the interpolations stay typed numbers (unregistered engines
   behave the same: --p is set to 0 explicitly below). */
@property --p { syntax: '<number>'; inherits: true; initial-value: 0; }
@property --ps { syntax: '<number>'; inherits: true; initial-value: 0; }

.pp-header { background: var(--pp-navy); }
.pp-header-shell { position: relative; z-index: 200; --p: 0; --ps: 0; }
/* UI.1 P2 (Human Lock §8): the header's icon controls (mobile Search / Menu,
   the tablet Menu, the drawer and search Close buttons, the ticker / strip
   controls) press with shade + scale(.985) — the 12% tint reads under a thumb
   where the 6% one did not (HIL R1 P2). Placed before the ticker rules so
   their dark-chrome white shade still wins at equal specificity. */
.pp-header-shell .pp-icon-btn:active, .pp-header-shell .pp-icon-btn.is-pressed { background: var(--pp-navy-tint-strong); transform: scale(var(--pp-press-scale)); }
/* Measurement pass (header.js): both S2 endpoints are laid out in one task
   with the three S2 rows' transitions off, so no measured box is caught
   mid-transition. Nothing else in the shell is touched: the rail's ambient
   loop, the shipping cue and the Cart drawer keep their animations and
   transitions (resetting them would show). No measured width depends on an
   animation (the settle acknowledgement only translates and fades). */
.pp-hd-measuring .pp-row2, .pp-hd-measuring .pp-row2 *,
.pp-hd-measuring .pp-navrow, .pp-hd-measuring .pp-navrow *,
.pp-hd-measuring .pp-tchips, .pp-hd-measuring .pp-tchips * { transition: none !important; }

/* ================= Row 1 — ticker (lock §20) =================
   One message at a time in a grid-stacked viewport; crossfade only on the
   ticker token; controls right; minimum ≈38px, long strings wrap and grow
   the row (never truncate). */
.pp-ticker {
	background: var(--pp-navy);
	color: #fff;
	min-height: 38px;
	display: flex;
	align-items: center;
	position: relative;
	padding-inline: var(--pp-gutter);
}
.pp-ticker-viewport { flex: 1; min-width: 0; position: relative; min-height: 38px; display: grid; align-items: center; }
.pp-ticker-msg {
	grid-area: 1 / 1;
	margin: 0;
	padding: 6px 0;
	text-align: center;
	font: 600 12.5px/1.3 var(--pp-font-body);
	letter-spacing: .02em;
	overflow-wrap: anywhere;
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--pp-motion-ticker) var(--pp-ease-out);
}
.pp-ticker-msg.is-active { opacity: 1; pointer-events: auto; }
.pp-ticker-ctl { display: flex; align-items: center; gap: 2px; flex: none; }
/* 44px effective hits inside the 38px bar (Hybrid V2 §17: margin-block −3px). */
.pp-ticker .pp-icon-btn { color: #fff; width: var(--pp-hit-min); height: var(--pp-hit-min); margin-block: -3px; }
@media (hover: hover) { .pp-ticker .pp-icon-btn:hover { background: rgba(255,255,255,.12); } } /* UI.1 P2: hover-capable input only — a tap never leaves the shade */
.pp-ticker .pp-icon-btn:active, .pp-ticker .pp-icon-btn.is-pressed { background: rgba(255,255,255,.2); }
.pp-ticker .pp-icon-btn:focus-visible { box-shadow: 0 0 0 2px var(--pp-navy), 0 0 0 4px #fff; }
.pp-ticker .pp-i { width: 16px; height: 16px; }

/* ================= Row 2 — the commerce bar: wordmark / search / Market · Account · Cart ================= */
.pp-row2 {
	display: flex;
	align-items: center;
	gap: var(--pp-space-5);
	padding: 18px var(--pp-gutter);
	flex-wrap: wrap;
}
/* The Lime plate (.pp-plate) is now the FOOTER's alone (footer.php
   .pp-plate.pp-footer-plate; the checkout / order-received shells have their
   own plate classes, checkout.css / account.css) — HD.1 retired it in this
   header. These rules keep the footer rendering exactly as before. */
.pp-plate {
	background: var(--pp-lime);
	border-radius: 4px;
	padding: 16px var(--pp-space-5);
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 232px;
}
.pp-plate img { width: 185px; display: block; }
/* The retired desktop header plate rule also gave the footer wordmark its
   natural height at >=1180 (132 × 30.53 on the artwork's ratio, not the
   132 × 29 attribute box): kept. */
@media (min-width: 1180px) { .pp-plate img { height: auto; } }

/* HD.1 wordmark — the official artwork in Lime (#D7FF00 on Navy, 11.7:1), no
   plate; width follows --p, height follows the artwork's own 869:201 ratio;
   the link keeps a 44px touch height. Two classes: WooCommerce's
   `.woocommerce img { height:auto; max-width:100% }` (0,1,1) must not reach
   it. */
.pp-logo { display: inline-flex; align-items: center; flex: none; min-height: var(--pp-hit-min); line-height: 0; border-radius: 4px; }
.pp-logo .pp-logo-img { display: block; width: calc(188px - 45px * var(--p)); height: auto; max-width: none; aspect-ratio: 869 / 201; }

/* Search field (lock §13, §29): 46px, 1.5px border, 15px input (16px on true
   mobile — design-system.css floor), Ink focus ring + the locked Lime
   underline, inline SVG glyph, clear button + indeterminate loading bar.
   HD.1: these base rules now serve the mobile Search panel (MOBILE-SEARCH
   lock, unchanged); the white field of the dark commerce bar is set below
   (".pp-row2 .pp-search"). */
.pp-search-wrap { flex: 1; min-width: 200px; max-width: 480px; margin: 0 auto; position: relative; }
.pp-search-form { display: block; }
.pp-search {
	display: flex;
	align-items: center;
	gap: 8px;
	width: 100%;
	min-height: 46px;
	padding: 0 4px 0 14px;
	background: #fff;
	border: 1.5px solid var(--pp-border);
	border-radius: var(--pp-radius-md);
	color: var(--pp-secondary-text);
	position: relative;
	cursor: text;
	transition: border-color var(--pp-motion-micro) var(--pp-ease-out), box-shadow var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-search > .pp-i { color: var(--pp-secondary-text); flex: none; }
.pp-search input[type="search"] {
	flex: 1;
	min-width: 0;
	border: 0;
	background: none;
	padding: 10px 0;
	font-family: var(--pp-font-body);
	font-size: 15px;
	font-weight: 400;
	line-height: 1.3;
	color: var(--pp-ink);
}
.pp-search input[type="search"]::placeholder { color: var(--pp-secondary-text); opacity: 1; }
.pp-search input[type="search"]::-webkit-search-decoration,
.pp-search input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }
/* The field carries the focus ring (:focus-within) — the input itself must not
   paint a second ring. Ring stays visible in forced-colours via the outline
   on the field, so the input's own outline can be dropped (S9D-A forced-colors note). */
.pp-search input[type="search"]:focus, .pp-search input[type="search"]:focus-visible { outline: none; box-shadow: none; }
@media (hover: hover) {
	.pp-search:hover { border-color: var(--pp-border-hover); }
}
.pp-search:focus-within { border-color: var(--pp-ink); box-shadow: var(--pp-focus-ring); }
@media (forced-colors: active) { .pp-search:focus-within { outline: 2px solid; outline-offset: 2px; } }
/* Lime underline — the one Lime touchpoint in the field (HEADER lock fix 3 / lock §5 budget). */
.pp-search::after {
	content: "";
	position: absolute;
	inset-inline: 6px;
	bottom: -1.5px;
	height: 2.5px;
	border-radius: 2px;
	background: var(--pp-lime);
	transform: scaleX(0);
	transform-origin: center;
	transition: transform var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-search:focus-within::after { transform: scaleX(1); }
/* Loading (lock §29): indeterminate Navy bar under the field while a request
   is pending; hidden otherwise. */
.pp-search-loading { position: absolute; inset-inline: 10px; bottom: -1.5px; height: 2.5px; overflow: hidden; border-radius: 2px; display: none; }
.pp-search.is-loading .pp-search-loading { display: block; }
.pp-search.is-loading::after { transform: scaleX(0); }
.pp-search-loading::before { content: ""; position: absolute; inset: 0; width: 40%; background: var(--pp-navy); animation: pp-indeterminate 1000ms var(--pp-ease-standard) infinite; }
@keyframes pp-indeterminate { from { transform: translateX(-120%); } to { transform: translateX(300%); } }
/* Clear — SVG icon button, shown only with a value; 36px visual desktop,
   44px effective hit on true mobile (Hybrid V2 §17). */
.pp-search-clear { display: none; width: 36px; height: 36px; flex: none; color: var(--pp-secondary-text); }
@media (hover: hover) { .pp-search-clear:hover { color: var(--pp-ink); } }
.pp-search.has-value .pp-search-clear { display: inline-flex; }

/* HD.1 — the commerce bar's Search: the white field on Navy (the brightest
   element of the dark header), 46px, radius 9, Inter 16/20 (the placeholder
   "Brand, flavour or strength…" was measured to fit every field state at
   this size), a white focus glow instead of the ink ring + Lime underline
   (both invisible / over budget on Navy). No hover lift. HD.1 RR: the glow
   is 50% white (≈ 4.5:1 against the Navy bar; the lab's 28% was ≈ 2.4:1,
   under the 3:1 non-text minimum) — same 3px geometry. */
.pp-row2 .pp-search { min-height: 46px; padding-inline: 15px 4px; gap: 10px; border: 1px solid #fff; border-radius: var(--pp-radius-md); }
.pp-row2 .pp-search input[type="search"] { padding: 0; height: 44px; font-size: 16px; line-height: 20px; text-overflow: ellipsis; }
.pp-row2 .pp-search:focus-within { border-color: #fff; box-shadow: 0 0 0 3px rgba(255, 255, 255, .5); }
.pp-row2 .pp-search::after { content: none; }
@media (hover: hover) { .pp-row2 .pp-search:hover { border-color: #fff; } }

/* Icons cluster */
.pp-icons { display: flex; align-items: center; gap: 8px; flex: none; }
/* HC.8: the commerce row's right-hand group (Market · Account · Cart) as ONE
   layout item. HD.1: one 8px rhythm between Market, Account and Cart (lab
   .hd-end). */
.pp-row2-end { display: flex; align-items: center; gap: 8px; flex: none; }

/* Account — neutral static state (lock §18): user icon + system label;
   .pp-auth-dot is the dormant Navy indicator slot (hydrated only by a
   future authenticated read — never rendered active from static HTML).
   HD.1: a button opening the Account menu; on Navy; its label collapses
   WITH the scroll value (1.5× the rate of --p, from its measured width
   --pp-acct-w), so the end group always shrinks at least as fast as the
   Search slot widens — no discrete swap. */
.pp-account-link {
	display: inline-flex;
	align-items: center;
	gap: clamp(0px, calc(7px * (1 - var(--p) * 1.5)), 7px);
	min-height: var(--pp-hit-min);
	padding: 0 8px;
	border-radius: var(--pp-radius-md);
	background: none;
	border: 0;
	font: 500 14px/1 var(--pp-font-body);
	color: #fff;
	cursor: pointer;
	position: relative;
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
@media (hover: hover) { .pp-account-link:hover { background: rgba(255, 255, 255, .08); } }
.pp-account-link[aria-expanded="true"] { background: rgba(255, 255, 255, .08); }
.pp-account-link .pp-i { color: currentColor; }
.pp-account-label { display: inline-block; overflow: hidden; white-space: nowrap; max-width: clamp(0px, calc(var(--pp-acct-w, 76px) * (1 - var(--p) * 1.5)), 200px); opacity: calc(1 - var(--p) * 2.5); }
.pp-account-link .pp-auth-dot { position: absolute; width: 8px; height: 8px; border-radius: 50%; background: var(--pp-navy); border: 2px solid #fff; inset-inline-start: 22px; top: 10px; opacity: 0; transform: scale(.6); transition: opacity var(--pp-motion-feedback) var(--pp-ease-out), transform var(--pp-motion-feedback) var(--pp-ease-out); }
.pp-account-link.is-authed .pp-auth-dot { opacity: 1; transform: none; }

/* Cart pill — HD.1: the white pill with Navy text on the dark bar (the CTA
   on a Navy surface, as the lab), "Cart · count · subtotal" kept. The
   count chip and the subtotal are visual twins of .pp-cart-count — the ONE
   value cart-drawer.js writes, kept for assistive technology (visually
   hidden, never removed) — mirrored by header.js. .pp-cart / .pp-cart-count
   / .pp-cart--empty stay the hooks cart-drawer.js updates. */
.pp-cart {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: var(--pp-hit-min);
	padding: 0 16px;
	background: #fff;
	color: var(--pp-navy);
	border-radius: var(--pp-radius-md);
	font: 600 13px/1 var(--pp-font-body);
	white-space: nowrap;
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-press-out) var(--pp-ease-out);
}
@media (hover: hover) { .pp-cart:hover { background: #EEF1F4; } }
.pp-cart:active, .pp-cart.is-pressed { background: #E3E8EE; transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
.pp-cart-pill .pp-cart-count { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.pp-cart-n { min-width: 22px; height: 20px; padding: 0 6px; border-radius: 6px; display: inline-flex; align-items: center; justify-content: center; background: var(--pp-navy); color: #fff; font: 700 12px/1 var(--pp-font-body); font-variant-numeric: tabular-nums; }
.pp-cart-sub { display: inline-block; padding-inline-start: 9px; border-inline-start: 1px solid rgba(20, 47, 81, .2); font-weight: 600; font-variant-numeric: tabular-nums; }
.pp-cart-sub:empty { display: none; }

/* Compact/tablet-tier (768-1179px) hamburger — a 44px icon button, hidden at
   full desktop, shown only by the tablet media query below. */
.pp-compact-hamburger { display: none; }
/* S12 action-group harmonisation: the 24px glyph read undersized beside the
   44px Cart pill; 28px keeps the same 44px hit box (Cart-height family)
   while the glyph gains the presence the human review asked for. */
.pp-compact-hamburger .pp-i--lg { width: 28px; height: 28px; }

/* Menu toggles render both glyphs once; aria-expanded drives which shows. */
[data-pp-menu-toggle] .pp-i--close { display: none; }
[data-pp-menu-toggle][aria-expanded="true"] .pp-i--menu { display: none; }
[data-pp-menu-toggle][aria-expanded="true"] .pp-i--close { display: inline-block; }

/* ================= Nav items (lock §18; HD.1 on Navy) =================
   Shop/Brands/Flavours/Strength are real <button>s (they open panels, not
   pages); Best sellers / New arrivals / Deals are real <a>. ONE nav-item
   grammar for the spine, the compact mini-nav and the services cluster:
   Barlow 600 15.5px (GLOBAL-COMMERCE-POLISH §11, unchanged), 88% white on
   Navy; hover = white text + a 2px white underline revealed from the centre
   (120ms), no lift, no pill — on hover-capable input only; the OPEN state
   stays the state indicator (the full 2.5px underline). */
.pp-nav { display: flex; align-items: center; justify-content: center; gap: 2px; }
.pp-nav .pp-nav-item, .pp-mini-nav .pp-nav-item, .pp-services .pp-nav-item {
	padding: 0 12px;
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	gap: 5px;
	font-family: var(--pp-font-display);
	font-weight: 600;
	font-size: 15.5px;
	line-height: 1;
	letter-spacing: 0;
	color: rgba(255, 255, 255, .88);
	white-space: nowrap;
	position: relative;
	background: none;
	border: none;
	cursor: pointer;
	transition: color var(--pp-motion-micro) var(--pp-ease-out);
}
/* The approved lab renders its carets in a 20px box (the glyph ~10px wide). */
:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item .pp-nav-caret { width: 20px; height: 20px; color: currentColor; opacity: .62; transition: transform var(--pp-motion-micro) var(--pp-ease-out); }
:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item::after {
	content: "";
	position: absolute;
	inset-inline: 12px;
	bottom: 6px;
	height: 2px;
	background: #fff;
	border-radius: 2px;
	transform: scaleX(0);
	transition: transform var(--pp-motion-micro) var(--pp-ease-out);
}
@media (hover: hover) {
	:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item:hover { color: #fff; }
	:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item:hover::after { transform: scaleX(1); }
}
:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item:is(.is-open, [aria-expanded="true"]) { color: #fff; }
:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item:is(.is-open, [aria-expanded="true"])::after { height: 2.5px; transform: scaleX(1); }
:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item:is(.is-open, [aria-expanded="true"]) .pp-nav-caret { transform: rotate(180deg); }
:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item:active { color: #fff; }

/* ================= Mega menu / Brands panel — container + open/close (lock §21)
   Component transition: opacity + 6px on the component tokens; visibility
   keeps closed panels out of the tab order. Zone/tile/brand content styling
   lives in header-commerce.css. ================= */
.pp-megamenu, .pp-brands-panel {
	position: absolute;
	inset-inline: 0;
	top: 100%;
	background: #fff;
	border-top: 1px solid var(--pp-border);
	box-shadow: 0 18px 30px rgba(0,0,0,.08);
	padding: 28px var(--pp-gutter) 32px;
	z-index: 150;
	opacity: 0;
	transform: translateY(-6px);
	visibility: hidden;
	transition:
		opacity var(--pp-motion-component-exit) var(--pp-ease-in),
		transform var(--pp-motion-component-exit) var(--pp-ease-in),
		visibility 0s linear var(--pp-motion-component-exit);
}
.pp-megamenu { max-height: 80vh; overflow-y: auto; }
.pp-megamenu.is-open, .pp-brands-panel.is-open {
	opacity: 1;
	transform: none;
	visibility: visible;
	transition:
		opacity var(--pp-motion-component) var(--pp-ease-out),
		transform var(--pp-motion-component) var(--pp-ease-out),
		visibility 0s;
}

/* Tier gates (HEADER-DIRECTION-LOCK.md v1.1 Section Q as amended; HD.1):
   >=1180 desktop (rail, commerce bar, nav row, megas, menus), 768-1179
   tablet (strip, commerce bar with Search + Cart + Menu, quick-link chips,
   the side-sheet menu — no desktop nav row), <=767 true mobile (its own
   persistent composition, header-anchored Search panel —
   MOBILE-SEARCH-INTERACTION-LOCK.md). */
@media (max-width: 767px) {
	.pp-ticker--desktop, .pp-row2, .pp-navrow, .pp-row3-desktop, .pp-tchips, .pp-megamenu, .pp-brands-panel, .pp-hpops, .pp-search-panel, .pp-compact-hamburger { display: none !important; }
}
@media (min-width: 768px) {
	.pp-mobile-header { display: none !important; }
}
@media (min-width: 768px) and (max-width: 1179px) {
	.pp-navrow, .pp-row3-desktop, .pp-megamenu, .pp-brands-panel, .pp-hpops { display: none !important; }
	.pp-compact-hamburger { display: inline-flex !important; }
	.pp-account-link { display: none !important; }
}
@media (min-width: 1180px) {
	.pp-tchips { display: none !important; }
}

/* ================= Mobile shell (<=767px) ================= */
.pp-mobile-header { background: var(--pp-navy); position: relative; } /* no z-index, so no new stacking context. The Search panel renders after the sticky header (MOB-01) and is fixed to this row's live bottom edge (predictive-search.js) */
/* MOB-03 (Human brief 2026-10-28, HEADER-COMMERCE-LOCK.md "MOB-03 NOTE"):
   Menu · Search | the wordmark | Cart. Three columns, the outer two equal, so
   the wordmark is centred on the screen however the icons are grouped; each
   outer glyph sits on the 16px gutter (its 44px box is pulled 8px outward).
   The row keeps its 56px (6 + 44 + 6, the ≤767 block below). */
.pp-mobile-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; column-gap: 8px; padding: 10px var(--pp-gutter-mobile); }
/* HD.1: the Lime wordmark without a plate — 124px (112 at ≤374), 44px touch height. */
.pp-mobile-logo { justify-self: center; display: inline-flex; align-items: center; flex: none; min-height: var(--pp-hit-min); line-height: 0; border-radius: 4px; }
.pp-mobile-logo img { display: block; width: 124px; height: auto; max-width: none; aspect-ratio: 869 / 201; }
.pp-mobile-icons { display: flex; align-items: center; flex: none; }
.pp-mobile-icons--start { justify-self: start; margin-inline-start: -8px; }
.pp-mobile-icons--end { justify-self: end; margin-inline-end: -8px; }
.pp-mobile-icons .pp-icon-btn { color: #fff; }
@media (hover: hover) { .pp-mobile-icons .pp-icon-btn:hover { background: rgba(255, 255, 255, .08); } }
.pp-header-shell .pp-mobile-icons .pp-icon-btn:is(:active, .is-pressed) { background: rgba(255, 255, 255, .12); }
/* S12 action-group harmonisation: every glyph of the row is 28px inside the
   unchanged 44px hit box — one height family (MOB-03: the Cart included). */
.pp-mobile-icons .pp-i--lg { width: 28px; height: 28px; }
/* MOB-03: the unboxed Cart — the white glyph in a 44px target (no visible box;
   the icon buttons' shade on hover and press), the count a Lime badge at the
   glyph's upper right on a 2px Navy ring. The badge grows leftward from its
   right edge (two and three digits stay on screen) and is transparent while
   the cart is empty (`--empty`, header.js), so the accessible name keeps the
   count cart-drawer.js writes. */
.pp-mobile-cart {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--pp-hit-min);
	height: var(--pp-hit-min);
	color: #fff;
	border-radius: var(--pp-radius-control);
	-webkit-tap-highlight-color: transparent;
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-press-out) var(--pp-ease-out);
}
@media (hover: hover) { .pp-mobile-cart:hover { background: rgba(255, 255, 255, .08); } }
.pp-mobile-cart .pp-cart-count {
	position: absolute;
	top: 3px;
	inset-inline-end: 1px;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 9px;
	background: var(--pp-lime);
	color: var(--pp-navy);
	box-shadow: 0 0 0 2px var(--pp-navy);
	font: 700 11px/18px var(--pp-font-body);
	font-variant-numeric: tabular-nums;
	letter-spacing: 0;
	text-align: center;
	pointer-events: none;
	transition: opacity var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-mobile-cart--empty .pp-cart-count { opacity: 0; animation: none; }
/* UI.1 P2: `.is-pressed` (pp-foundation.js pointerdown) backs `:active`, which
   touch browsers did not paint (HIL R1 / IC.2 finding). */
.pp-mobile-cart:active, .pp-mobile-cart.is-pressed { background: rgba(255, 255, 255, .12); transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
@media (max-width: 374px) {
	.pp-mobile-logo img { width: 112px; }
}
/* MOB-03 compact fallback below 320px (zoomed or very narrow screens), where
   the equal side columns no longer leave the wordmark room: it follows
   Search instead of centring, and nothing overlaps or overflows. */
@media (max-width: 319px) {
	.pp-mobile-row { grid-template-columns: auto auto 1fr; }
	.pp-mobile-logo { justify-self: start; }
}

/* MOB-03: the strip's announcements move continuously right to left — the
   campaign rail's seamless loop (.pp-rail-run / .pp-rail-seq and their
   reduced-motion rule, header-commerce.css; header.js measures the loop)
   inside a clipped track from the screen edge to the Market chip, so the
   moving copy never runs under it. The first message starts on the 16px
   gutter, intact at rest; the copy fades in and out at the ends. No Pause
   control (the Human, 2026-10-29): the region stops 8px short of the Market
   chip (the strip's own end padding; the chip keeps its 4px lead), so the
   fade finishes clear of it. */
.pp-mticker { position: relative; flex: 1; min-width: 0; align-self: stretch; display: flex; align-items: center; margin-inline-end: 8px; }
/* The track's box reaches 7px above and below the 30px band (margin-block −7px,
   as the Market chip): the clip that holds a linked message's 44px target.
   Its copy stays centred in the band. */
.pp-mticker-track {
	flex: 1;
	min-width: 0;
	align-self: stretch;
	display: flex;
	align-items: center;
	margin-block: -7px;
	overflow: hidden;
	padding-inline-start: var(--pp-gutter-mobile);
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 var(--pp-gutter-mobile), #000 calc(100% - 20px), transparent);
	mask-image: linear-gradient(90deg, transparent, #000 var(--pp-gutter-mobile), #000 calc(100% - 20px), transparent);
}
.pp-mticker .pp-rail-seq { gap: 0; padding-inline-end: 0; }
.pp-mticker-item {
	flex: none;
	display: inline-flex;
	align-items: center;
	color: rgba(255, 255, 255, .92);
	font: 700 11px/1 var(--pp-font-body);
	letter-spacing: .04em;
	text-transform: uppercase;
	white-space: nowrap;
}
/* The separator rides after EVERY message, the last one included: the gap
   across the seam is an ordinary one, and a hidden shipping slot takes its
   separator with it. */
.pp-mticker-item::after { content: ""; flex: none; width: 4px; height: 4px; margin-inline: 14px; border-radius: 50%; background: var(--pp-lime); }
/* The preferred brand message: the rail lead's Lime keyline tag at strip density. */
.pp-mticker-tag { display: inline-flex; align-items: center; min-height: 20px; padding: 0 7px; border: 1px solid rgba(215, 255, 0, .45); border-radius: 4px; background: rgba(215, 255, 0, .07); color: var(--pp-lime); }
/* A linked message (Same-day dispatch → the full delivery terms, Discover new
   arrivals → the newest products): a Lime underline marks it, and its 44px
   target fills the track's box without moving the line (padding-block 16.5px,
   margin-block −16.5px). In the moving copy it serves pointer and touch only:
   keyboard and screen readers use its twin in the message list below. */
.pp-mticker-link {
	padding-block: 16.5px;
	margin-block: -16.5px;
	color: inherit;
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: rgba(215, 255, 0, .55);
	text-underline-offset: 3px;
	-webkit-tap-highlight-color: transparent;
}
@media (hover: hover) { .pp-mticker-link:hover { text-decoration-color: var(--pp-lime); } }
.pp-mticker-link:is(:active, .is-pressed) { color: var(--pp-lime); }
@media (hover: hover) { .pp-mticker-track:hover .pp-rail-run { animation-play-state: paused; } } /* HD.1F: only the pointer resting on the moving copy itself */
/* The message list (visually hidden, role=list) is the keyboard path to the
   links: while one of them holds focus, that message alone shows in place of
   the moving copy, on the strip's chrome, and the loop holds still behind it
   until focus moves on to the Market chip. */
.pp-mticker-sr { list-style: none; }
.pp-mticker .pp-mticker-sr:focus-within {
	inset: 0;
	z-index: 1;
	display: flex;
	align-items: center;
	width: auto;
	height: auto;
	margin: 0;
	padding-inline-start: var(--pp-gutter-mobile);
	clip: auto;
	background: var(--pp-navy-chrome);
}
.pp-mticker .pp-mticker-sr:focus-within li:not(:focus-within) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); }
.pp-mticker-sr a {
	color: rgba(255, 255, 255, .92);
	font: 700 11px/1 var(--pp-font-body);
	letter-spacing: .04em;
	text-transform: uppercase;
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
	text-decoration-color: rgba(215, 255, 0, .55);
	text-underline-offset: 3px;
}
.pp-mticker-sr a:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 2px; }
.pp-mticker:has(.pp-mticker-sr:focus-within) .pp-rail-run { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
	/* No loop: one sequence, and the track scrolls under a swipe instead, so
	   every message stays reachable. */
	.pp-mticker-track { overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none; }
	.pp-mticker-track::-webkit-scrollbar { display: none; }
	.pp-mticker .pp-rail-seq + .pp-rail-seq { display: none; }
}

/* Shared mobile nav drawer — in-flow expanding panel (non-modal, per the S6
   lab) opened on the component token via grid-template-rows (<=767; the
   tablet side sheet is set in the tablet block below). Row content styling
   lives in header-commerce.css. */
.pp-mobile-drawer {
	background: #fff;
	border-top: 1px solid var(--pp-border);
	display: grid;
	grid-template-rows: 0fr;
	visibility: hidden;
	transition: grid-template-rows var(--pp-motion-component) var(--pp-ease-out), visibility 0s linear var(--pp-motion-component);
}
/* The drawer box itself is hidden once the collapse ends (MOB-01): iOS 26+
   Safari keeps the last screen-edge element while it stays visible, and the
   open drawer is one (see the <=767 block). */
.pp-mobile-drawer.is-open { grid-template-rows: 1fr; visibility: visible; transition: grid-template-rows var(--pp-motion-component) var(--pp-ease-out), visibility 0s; }
/* Closed drawer content is out of the focus order even where `inert` is not
   supported: visibility flips hidden once the collapse transition ends and
   back to visible the instant the drawer opens (S9D-B-R M2). */
.pp-mobile-drawer-inner { overflow: hidden; min-height: 0; visibility: hidden; transition: visibility 0s linear var(--pp-motion-component); }
.pp-mobile-drawer.is-open .pp-mobile-drawer-inner { visibility: visible; transition: visibility 0s; }
.pp-mobile-drawer:not(.is-open) { border-top-color: transparent; }
.pp-mobile-drawer .pp-mrow {
	display: flex;
	justify-content: space-between;
	align-items: center;
	width: 100%;
	min-height: 52px;
	padding: 0 18px;
	font-family: var(--pp-font-display);
	font-weight: 600;
	font-size: 15px;
	line-height: 1.2;
	letter-spacing: 0;
	color: var(--pp-ink);
	border-bottom: 1px solid var(--pp-border);
	background: none;
	cursor: pointer;
	text-align: start;
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-mobile-drawer .pp-mrow:active, .pp-mobile-drawer .pp-mrow.is-pressed { background: var(--pp-navy-tint); }
.pp-mobile-drawer .pp-mrow .pp-i { color: var(--pp-secondary-text); width: 16px; height: 16px; }
@media (min-width: 1180px) { .pp-mobile-drawer { display: none; } } /* the desktop tier has no drawer — and so no 1px seam under the header */

/* ================= Reduced motion (lock §7) ================= */
@media (prefers-reduced-motion: reduce) {
	.pp-megamenu, .pp-brands-panel { transform: none; }
	.pp-search-loading::before { animation-duration: 2000ms; }
	.pp-cart:is(:active, .is-pressed), .pp-mobile-cart:is(:active, .is-pressed), .pp-market-summary:is(:active, .is-pressed) { transform: none; }
	/* UI.1 N2: the underline appears at full width (no scale reveal). */
	:is(.pp-nav, .pp-mini-nav, .pp-services) .pp-nav-item::after { transition: none; }
}

/* ---------- S11-B3: Market / Locale selector (native disclosure) ----------
   Renders only while ≥ 2 routes are published (inc/header-commerce.php).
   Ticker variant sits at the end of the Navy announcement row; the drawer
   variant is a navigation row; the footer variant lives in the legal band. */
.pp-ticker--desktop { display: flex; align-items: center; }
.pp-market { position: relative; }
.pp-market-summary {
	display: inline-flex; align-items: center; gap: 6px; list-style: none; cursor: pointer;
	min-height: 30px; padding: 0 10px; border: 1px solid rgba(255,255,255,.28); border-radius: var(--pp-radius-sm);
	color: #fff; font: 600 11.5px/1 var(--pp-font-body); letter-spacing: .02em; white-space: nowrap;
	transition: border-color var(--pp-motion-micro) var(--pp-ease-out), background-color var(--pp-motion-micro) var(--pp-ease-out), box-shadow var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-press-out) var(--pp-ease-out);
}
.pp-market-summary::-webkit-details-marker { display: none; }
@media (hover: hover) { .pp-market-summary:hover { border-color: rgba(255,255,255,.6); } } /* UI.1 P2: hover-capable input only */
/* UI.1 P2 (Human Lock §8): the selector's summary is on pp-foundation.js's
   press path — shade + scale(.985); on the dark chrome the shade is the
   ticker controls' own white 20%. The light commerce-row chip and the strip
   chip (whose visible keyline is a ::before) set their own shade in
   header-commerce.css. */
.pp-market-summary:active, .pp-market-summary.is-pressed { background-color: rgba(255,255,255,.2); transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
.pp-market-summary .pp-i { width: 14px; height: 14px; opacity: .85; }
.pp-market-caret { transition: transform var(--pp-motion-component) var(--pp-ease-out); }
.pp-market[open] .pp-market-caret { transform: rotate(180deg); }
.pp-market-code { font-weight: 700; }
.pp-market-sep { opacity: .5; }
.pp-market-list {
	position: absolute; inset-inline-end: 0; top: calc(100% + 6px); z-index: 60;
	min-width: 220px; margin: 0; padding: 6px; list-style: none;
	background: #fff; color: var(--pp-ink); border: 1px solid var(--pp-border); border-radius: var(--pp-radius-md); box-shadow: var(--pp-shadow-popover);
}
.pp-market-opt { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 0 10px; border-radius: var(--pp-radius-sm); font: 500 14px/1.2 var(--pp-font-body); color: var(--pp-ink); text-decoration: none; }
.pp-market-opt b { font: 700 11px/1 var(--pp-font-body); letter-spacing: .04em; color: var(--pp-navy); min-width: 26px; }
.pp-market-opt:hover { background: var(--pp-soft-surface); }
.pp-market-opt.is-current { background: var(--pp-navy-tint); }
.pp-market--ticker { margin-inline-start: auto; margin-inline-end: 8px; flex: none; }
.pp-market--ticker .pp-market-summary:focus-visible { box-shadow: 0 0 0 2px var(--pp-navy), 0 0 0 4px #fff; }
/* UI.1 H2 (Human Lock §5) on the tablet ticker chip: the whole chip lifts ~2px
   as one object with its existing keyline brightening; a Navy separation
   would be invisible on the Navy ticker, so none is painted. Press wins.
   Final decision F2: only while the selector is CLOSED — an open chip stays
   still under the pointer (its [open] caret and popover are the state). The
   condition sits in :where() so the press rule below still wins. */
@media (hover: hover) { .pp-market--ticker:where(:not([open])) .pp-market-summary:hover { transform: translateY(calc(var(--pp-hover-rise) * -1)); transition-duration: var(--pp-motion-micro); } }
.pp-market--ticker .pp-market-summary:is(:active, .is-pressed) { transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
/* Drawer variant: a full-width navigation row with the list in flow (no popover on a phone). */
.pp-mrow--market { padding: 0; }
.pp-market--drawer { width: 100%; }
.pp-market--drawer .pp-market-summary { width: 100%; min-height: 52px; border: 0; border-radius: 0; padding: 0 var(--pp-gutter-mobile); color: var(--pp-ink); font: 600 15px/1.2 var(--pp-font-body); justify-content: flex-start; }
.pp-market--drawer .pp-market-summary .pp-market-caret { margin-inline-start: auto; }
/* UI.1 P2: as a drawer row it presses like the drawer rows — Navy tint, no scale. */
.pp-market--drawer .pp-market-summary:is(:active, .is-pressed) { background-color: var(--pp-navy-tint); transform: none; }
.pp-market--drawer .pp-market-list { position: static; box-shadow: none; border: 0; border-top: 1px solid var(--pp-border); border-radius: 0; padding: 6px var(--pp-gutter-mobile) 10px; background: var(--pp-soft-surface); }
.pp-market--drawer .pp-market-opt { min-height: var(--pp-hit-min); }
@media (max-width: 1024px) { .pp-market--ticker { display: none; } }

/* ---------- INT.4: Market selector motion — M2.55-B "Velvet Cascade" -------
   (INT.3 lab, human-selected). PRESENTATION ONLY: every selector below reads
   state ([open], set by the platform / the INT.2 controller) or one of two
   presentation classes (.pp-mkt-exit / .pp-mkt-settled) whose whole lifecycle
   is fixed timers in initMarketMotion() (header.js) — never interaction
   authority. Opens are keyframes on [open] and replay on every real open;
   the exit runs AFTER [open] has already dropped (state, light-dismiss, the
   HC.8 pin and the caret all see the close instantly), with ::details-content
   held rendered for the 100ms fade. Engines without ::details-content skip
   that one rule and close instantly — today's behaviour. A close cancelled
   by a reopen becomes .pp-mkt-settled: visible at once, no entrance replay.
   ONE continuous top→bottom wave: rows hold a .21 opacity floor through
   their 10ms stagger (visual presence from frame one — opacity never gates
   hit-testing), 1.5px travel, ~178ms life inside the 210ms E3 surface.
   The drawer variant is an in-flow accordion, not a popover — excluded.
   Direction is one token: --pp-mkt-dir -1 opens downward (header), 1 opens
   upward (footer desktop rise, footer.css). Touch and reduced-motion
   re-tune ONLY the custom properties. */
details.pp-market:not(.pp-market--drawer) {
	--pp-mkt-dir: -1;                              /* -1 = hangs below the trigger */
	--pp-mkt-open-ms: 210ms;
	--pp-mkt-ease: cubic-bezier(.16, 1, .3, 1);    /* E3 — locked */
	--pp-mkt-origin: 50% 0;
	--pp-mkt-surface-from: translateY(calc(var(--pp-mkt-dir) * 6px)) scale(.987);
	--pp-mkt-row-anim: pp-mkt-row-in;
	--pp-mkt-row-from: translateY(calc(var(--pp-mkt-dir) * 1.5px));
	--pp-mkt-row-floor: .21;
	--pp-mkt-row-ms: 178ms;                        /* ≈ open × .85 */
	--pp-mkt-row-base: 20ms;
	--pp-mkt-stagger: 10ms;
	--pp-mkt-close-ms: 100ms;
	--pp-mkt-exit-to: translateY(calc(var(--pp-mkt-dir) * 3px));
}
@keyframes pp-mkt-surface-in { from { opacity: 0; transform: var(--pp-mkt-surface-from); } }
@keyframes pp-mkt-row-in { from { opacity: var(--pp-mkt-row-floor); transform: var(--pp-mkt-row-from); } }
@keyframes pp-mkt-surface-out { to { opacity: 0; transform: var(--pp-mkt-exit-to); } }

details.pp-market:not(.pp-market--drawer)[open]:not(.pp-mkt-settled) .pp-market-list {
	animation: pp-mkt-surface-in var(--pp-mkt-open-ms) var(--pp-mkt-ease) both;
	transform-origin: var(--pp-mkt-origin);
}
details.pp-market:not(.pp-market--drawer)[open]:not(.pp-mkt-settled) .pp-market-list > li {
	animation: var(--pp-mkt-row-anim) var(--pp-mkt-row-ms) var(--pp-mkt-ease) both;
	animation-delay: calc(var(--pp-mkt-row-base) + var(--pp-mkt-i, 10) * var(--pp-mkt-stagger));
}
/* Reveal order = document order; spare slots inherit the var fallback (10),
   so a grown list caps at base + 10 staggers rather than drifting late.
   The footer's desktop rise re-indexes trigger-first (footer.css). */
details.pp-market .pp-market-list > li:nth-child(1) { --pp-mkt-i: 0; }
details.pp-market .pp-market-list > li:nth-child(2) { --pp-mkt-i: 1; }
details.pp-market .pp-market-list > li:nth-child(3) { --pp-mkt-i: 2; }
details.pp-market .pp-market-list > li:nth-child(4) { --pp-mkt-i: 3; }
details.pp-market .pp-market-list > li:nth-child(5) { --pp-mkt-i: 4; }
details.pp-market .pp-market-list > li:nth-child(6) { --pp-mkt-i: 5; }
details.pp-market .pp-market-list > li:nth-child(7) { --pp-mkt-i: 6; }
details.pp-market .pp-market-list > li:nth-child(8) { --pp-mkt-i: 7; }
details.pp-market .pp-market-list > li:nth-child(9) { --pp-mkt-i: 8; }
details.pp-market .pp-market-list > li:nth-child(10) { --pp-mkt-i: 9; }

/* Caret joins the surface on open (×.85, no overshoot) and returns with the
   exit; overrides the generic component timing above for popover variants. */
details.pp-market:not(.pp-market--drawer) .pp-market-caret {
	transition: transform var(--pp-mkt-close-ms) var(--pp-ease-in);
}
details.pp-market:not(.pp-market--drawer)[open] .pp-market-caret {
	transition: transform calc(var(--pp-mkt-open-ms) * .85) var(--pp-mkt-ease);
}

/* EXIT — [open] is already gone; this class only keeps the fade visible.
   Standalone rule: engines without ::details-content drop it (instant
   close), everything else is unaffected. */
details.pp-market.pp-mkt-exit::details-content { content-visibility: visible; }
details.pp-market.pp-mkt-exit:not([open]) .pp-market-list {
	animation: pp-mkt-surface-out var(--pp-mkt-close-ms) var(--pp-ease-in) both;
	pointer-events: none; /* a dismissed surface must not swallow the next click */
}

/* Touch / coarse pointer: one fast surface, 3px, no scale, no stagger —
   the same gate the INT.2 controller complements (hover+fine installs JS). */
@media (hover: none), (pointer: coarse) {
	details.pp-market:not(.pp-market--drawer) {
		--pp-mkt-open-ms: 140ms;
		--pp-mkt-surface-from: translateY(calc(var(--pp-mkt-dir) * 3px));
		--pp-mkt-row-anim: none;
	}
}

/* Reduced motion (lock §7): opacity only — no travel, no scale, no stagger;
   close near-instant; caret static (matches the 0ms component token). */
@media (prefers-reduced-motion: reduce) {
	details.pp-market:not(.pp-market--drawer) {
		--pp-mkt-open-ms: 80ms;
		--pp-mkt-ease: linear;
		--pp-mkt-surface-from: none;
		--pp-mkt-row-anim: none;
		--pp-mkt-close-ms: 0ms;
	}
	details.pp-market:not(.pp-market--drawer) .pp-market-caret,
	details.pp-market:not(.pp-market--drawer)[open] .pp-market-caret { transition: none; }
}


/* ============================================================================
   HD.1 — SHELL GEOMETRY + S2 FLUID COMPACT (design-locks/HD1-HEADER-FINAL-LOCK.md;
   supersedes the R5-C / R5.2-C shell geometry and the discrete Full /
   Scrolled State Contract of HEADER-COMMERCE-LOCK.md). Shell geometry and
   state ONLY — content surfaces (rail internals, drawer rows, menus, the
   shipping surfaces, Market variants) live in header-commerce.css.

   State, written by header.js only:
     --p / --ps   the scroll value (0 full … 1 compact over the first 140px)
                  and the Search-slot value (min(1, p / .85)), written on the
                  three subtrees that read them — .pp-row2, .pp-navrow,
                  .pp-tchips — never on the header root (a root write
                  restyles every panel each frame).
     .pp-compact  the compact layer (hysteresis: on at p ≥ .97, off at ≤ .90;
                  reduced motion: the discrete rule); .pp-tablet-compact is
                  its tablet alias (T2 and the tablet rules read it).
     .pp-scrolled "not at top" (> 8px) — the shadow, every tier.
     .pp-geo      desktop measured geometry is live (--pp-L0/R0/L1/R1, the
                  mini-nav position and the bar padding, px, on the shell).
     .pp-nav-ghost / .pp-mini-on   pointer state of the fading nav row and
                  the appearing mini-nav.
   Without JavaScript the header renders its full state and never compacts.
   ============================================================================ */

/* Tier gates: the campaign rail exists only on full desktop; the compact
   mini-nav only in the desktop compact layer; the fixed-header spacer only
   where the header actually leaves flow (>=768). */
.pp-rail { display: none; }
.pp-mini-nav { display: none; }
.pp-navrow { display: none; }
.pp-header-spacer { height: 0; }
.pp-header-scrim { display: none; }

/* "Not at top" shadow — every tier (HD.1: deeper, it sits under a Navy bar). */
.pp-header-shell { transition: box-shadow 220ms var(--pp-ease-out); }
.pp-header-shell.pp-scrolled { box-shadow: 0 10px 24px rgba(11, 29, 56, .22); }

@media (min-width: 1180px) {
	/* ---- Asymmetric 1840 chrome grid: ONE padding formula — the 32px cart
	   gutter through 1728 and the 72px optical gutter at 1920
	   ((1920 − 1840)/2 + 32 = 72); rail, commerce bar and nav row. ---- */
	.pp-header-shell { --pp-hdr-max: 1840px; --pp-chrome-pad: max(32px, calc((100% - var(--pp-hdr-max)) / 2 + 32px)); }

	/* Rail replaces the ticker row on full desktop. HD.1: a 34px band on the
	   chrome Navy (was 38); rail content styling lives in header-commerce.css. */
	.pp-ticker--desktop { display: none; }
	.pp-rail {
		display: flex;
		align-items: center;
		height: 34px;
		position: relative;
		z-index: 3;
		background: var(--pp-navy-chrome);
		color: #fff;
		padding-inline: var(--pp-chrome-pad);
		box-shadow: inset 0 -1px 0 rgba(255, 255, 255, .05);
	}

	/* ---- Fixed header + CONSTANT spacer: the spacer holds the FULL height
	   (header.js measures it once per load / width change into
	   --pp-header-full-h; 150 = rail 34 + bar 72 + nav row 44), so the S2
	   compaction never moves page content. ---- */
	.pp-header-shell { position: fixed; top: 0; inset-inline: 0; }
	.admin-bar .pp-header-shell { top: 32px; }
	.pp-header-spacer { height: var(--pp-header-full-h, 150px); }

	/* ---- Commerce bar: 72 → 60px with --p; wordmark 188 → 143. ---- */
	.pp-row2 {
		position: relative;
		z-index: 2;
		height: calc(72px - 12px * var(--p));
		padding: 0 var(--pp-chrome-pad);
		flex-wrap: nowrap;
		background: var(--pp-navy);
	}
	.pp-row2 .pp-search-wrap { max-width: none; margin-inline: 0; }

	/* Before measurement (or without JavaScript): the plain grid endpoints.
	   Full — the HC.8 three-track axis grid: Search centred on the viewport
	   while the middle track leaves both sides room for the wider side group
	   (--pp-row2-end-reserve; header.js replaces this with measured geometry).
	   Compact (measurement pass only) — logo · mini-nav · Search · end. */
	.pp-header-shell:not(.pp-geo) .pp-row2 {
		--pp-row2-end-reserve: 384px; /* Market chip "GLOBAL · USD" + Account + Cart */
		display: grid;
		grid-template-columns:
			minmax(max-content, 1fr)
			minmax(0, min(600px, calc(100% - 2 * 16px - 2 * var(--pp-row2-end-reserve))))
			minmax(max-content, 1fr);
		column-gap: 16px;
		align-items: center;
	}
	.pp-header-shell:not(.pp-geo) .pp-row2 > .pp-logo { grid-column: 1; justify-self: start; }
	.pp-header-shell:not(.pp-geo) .pp-row2 > .pp-search-wrap { grid-column: 2; width: 100%; }
	.pp-header-shell:not(.pp-geo) .pp-row2 > .pp-row2-end { grid-column: 3; justify-self: end; }
	.pp-header-shell.pp-compact:not(.pp-geo) .pp-row2 { grid-template-columns: auto auto minmax(160px, 1fr) auto; column-gap: 14px; }
	.pp-header-shell.pp-compact:not(.pp-geo) .pp-row2 > .pp-mini-nav { display: flex; grid-column: 2; }
	.pp-header-shell.pp-compact:not(.pp-geo) .pp-row2 > .pp-search-wrap { grid-column: 3; }
	.pp-header-shell.pp-compact:not(.pp-geo) .pp-row2 > .pp-row2-end { grid-column: 4; }

	/* S2 measured geometry: the Search slot interpolates continuously between
	   the centred full slot (--pp-L0/--pp-R0) and the compact slot
	   (--pp-L1/--pp-R1) — it completes at p = .85 (--ps); logo and end group
	   are pinned to the bar's content edges; the mini-nav's opacity is a pure
	   function of the scroll value (0 at p ≤ .88, 1 at p ≥ .963 — never a
	   timed fade, so at no scroll speed does it overlap the moving Search);
	   it takes pointer input only in the compact layer (.pp-mini-on; `inert`
	   otherwise — header.js). No discrete re-flow anywhere in the S2 path. */
	.pp-geo .pp-row2 { display: block; }
	.pp-geo .pp-row2 > .pp-logo { position: absolute; left: var(--pp-pad-px); top: 50%; transform: translateY(-50%); }
	.pp-geo .pp-row2 > .pp-row2-end { position: absolute; right: var(--pp-pad-px); top: 50%; transform: translateY(-50%); }
	.pp-geo .pp-row2 > .pp-search-wrap {
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
		width: auto;
		min-width: 0;
		left: calc(var(--pp-L0) + (var(--pp-L1) - var(--pp-L0)) * var(--ps));
		right: calc(var(--pp-R0) + (var(--pp-R1) - var(--pp-R0)) * var(--ps));
	}
	.pp-geo .pp-row2 > .pp-mini-nav {
		display: flex;
		position: absolute;
		left: var(--pp-mini-left);
		top: 50%;
		transform: translateY(-50%);
		opacity: clamp(0, calc((var(--p) - 0.88) * 12), 1);
		pointer-events: none;
	}
	.pp-geo.pp-mini-on .pp-row2 > .pp-mini-nav { pointer-events: auto; }
	/* MK.7L resilience: a placeholder that no longer fits ends in an ellipsis;
	   the predictive panel keeps its own legible floor under a narrow field. */
	.pp-compact .pp-search-panel { min-width: 240px; }

	/* Commerce controls (lab .hd-end): Search 46 · Market 40 · Account 44 ·
	   Cart 46 (the Search line). */
	.pp-row2 .pp-cart { min-height: 46px; }

	/* ---- Nav row: 44 → 0px with --p, its background opaque while it
	   collapses; only its content fades (1 − 2.5p, gone by p .4) and lifts
	   (−10p px). Above p .19 it no longer takes the pointer; in the compact
	   layer it is hidden and `inert` (header.js) — the mini-nav carries the
	   navigation, so exactly ONE Primary navigation is exposed at a time.
	   Keyboard focus entering the row pins the header full (header.js). ---- */
	.pp-navrow {
		display: block;
		position: relative;
		z-index: 1;
		height: calc(44px * (1 - var(--p)));
		overflow: hidden;
		background: var(--pp-navy);
		box-shadow: inset 0 1px 0 rgba(255, 255, 255, .09);
	}
	.pp-compact .pp-navrow { visibility: hidden; }
	.pp-nav-ghost .pp-navrow-in { pointer-events: none; }
	.pp-navrow-in {
		height: 44px;
		display: grid;
		grid-template-columns: auto minmax(0, 1fr) auto;
		align-items: center;
		padding: 0 var(--pp-chrome-pad);
		opacity: calc(1 - var(--p) * 2.5);
		transform: translateY(calc(var(--p) * -10px));
	}

	/* The shopping spine LEFT (first label on the content edge) and the
	   services cluster RIGHT (HD.1 D1 — supersedes R5.2-C's centred spine). */
	.pp-row3-desktop { grid-column: 1; justify-content: flex-start; gap: 0; margin-inline-start: -12px; }
	.pp-row3-desktop .pp-nav-group { display: flex; align-items: center; gap: 2px; }
	.pp-services { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 4px; }
	/* THE HUMAN-LOCKED SEMANTIC DIVIDER — 1×16px, vertically centred,
	   presentation-only (no DOM item, invisible to AT). On Navy: white 22%.
	   NEVER remove it as "decoration". HD.1: 40px from each label. */
	.pp-nav-group--merch { position: relative; margin-inline-start: 28px; padding-inline-start: 28px; }
	.pp-nav-group--merch::before {
		content: "";
		position: absolute;
		inset-inline-start: 0;
		top: 50%;
		width: 1px;
		height: 16px;
		margin-top: -8px;
		background: rgba(255, 255, 255, .22);
	}

	/* Deals — the restrained Lime dot (nav lock: never a permanent NEW
	   badge, never red), AFTER the label in the item's reserved end padding
	   (HD.1 lab: the item keeps one width whether or not the dot shows; ::after
	   is the underline). SF.4 ruling 5: the LINK is permanent, the DOT renders
	   only while a qualifying real deal exists (`is-live`). */
	.pp-navrow .pp-nav-item.pp-nav-item--deals { padding-inline-end: 20px; }
	.pp-mini-nav .pp-nav-item.pp-nav-item--deals { padding-inline-end: 18px; }
	:is(.pp-navrow, .pp-mini-nav) .pp-nav-item--deals.is-live::before {
		content: "";
		position: absolute;
		inset-inline-end: 9px;
		top: 50%;
		width: 6px;
		height: 6px;
		margin-top: -3px;
		border-radius: 50%;
		background: var(--pp-lime);
	}

	/* Compact mini-nav items (lab .hd-ni--mini): 40px, 8px sides. */
	.pp-mini-nav { align-items: center; gap: 0; }
	.pp-mini-nav .pp-nav-item { min-height: 40px; padding: 0 8px; }
	.pp-mini-nav .pp-nav-item::after { inset-inline: 8px; bottom: 3px; }
}

/* Desktop density (RESPONSIVE-CONTRACT): paddings compress ≤1366, the
   currency drops at 1180–1279 (HC.8.1, header-commerce.css) — typography
   never shrinks. */
@media (min-width: 1180px) and (max-width: 1366px) {
	.pp-nav .pp-nav-item:not(.pp-nav-item--deals), .pp-services .pp-nav-item, .pp-mini-nav .pp-nav-item:not(.pp-nav-item--deals) { padding: 0 10px; }
	:is(.pp-nav, .pp-mini-nav) .pp-nav-item--deals { padding-inline-start: 10px; }
	:is(.pp-nav, .pp-services) .pp-nav-item::after { inset-inline: 10px; }
	.pp-nav-group--merch { margin-inline-start: 20px; padding-inline-start: 20px; }
}
@media (min-width: 1180px) and (max-width: 1279px) {
	.pp-mini-nav .pp-nav-item:not(.pp-nav-item--deals) { padding: 0 7px; }
	.pp-mini-nav .pp-nav-item--deals { padding-inline-start: 7px; }
	.pp-mini-nav .pp-nav-item::after { inset-inline: 7px; }
	.pp-header-shell:not(.pp-geo) .pp-row2 { --pp-row2-end-reserve: 344px; } /* the chip without its currency */
}

/* ===================== TABLET (768–1179) — S2 + quick-link chips =====================
   The desktop technique: the header is FIXED over a CONSTANT spacer
   (--pp-header-full-h, measured; 162 = strip 34 + bar 76 + chips 52), so
   content never moves. S2 sizes the bar 76 → 62 and the wordmark 164 → 132,
   and collapses the chips row 52 → 0 (its content fades by p .4); the strip
   persists. The compact layer (.pp-compact + .pp-tablet-compact) is where
   SB.1C T2 takes the strip's place while the cart progresses (OPTION A,
   UI.1 F1): T2 is the same 34px, so the bar never moves when it does. The
   menu is a right-hand side sheet over a scrim. Screen only: a printed page
   keeps the header in flow, once. */
@media screen and (min-width: 768px) and (max-width: 1179px) {
	.pp-header-shell { position: fixed; top: var(--pp-admin-bar-h, 0px); inset-inline: 0; }
	.pp-header-spacer { height: var(--pp-header-full-h, 162px); }

	/* The strip: the tablet ticker on the chrome Navy — one centred message in
	   the strip's own type, Next (MOB-03: no Pause), the Market chip last. */
	.pp-ticker--desktop { min-height: 34px; padding-inline: 24px 8px; background: var(--pp-navy-chrome); }
	.pp-ticker--desktop .pp-ticker-viewport { min-height: 34px; }
	.pp-ticker--desktop .pp-ticker-msg { padding: 4px 0; font: 700 11.5px/1.3 var(--pp-font-body); letter-spacing: .04em; text-transform: uppercase; }
	.pp-ticker--desktop .pp-icon-btn { margin-block: -5px; }

	.pp-row2 {
		position: relative;
		z-index: 2;
		height: calc(76px - 14px * var(--p));
		padding: 0 24px;
		gap: 18px;
		flex-wrap: nowrap;
		background: var(--pp-navy);
	}
	.pp-logo .pp-logo-img { width: calc(164px - 32px * var(--p)); }
	.pp-row2 .pp-search-wrap { flex: 1; min-width: 0; max-width: 520px; margin-inline: auto 0; }
	.pp-row2-end, .pp-icons { gap: 10px; }
	.pp-row2 .pp-cart { min-height: 46px; }
	/* The tablet Cart is glyph + count (lab .hdt-end); "Cart" stays the
	   accessible name (visually hidden, never removed). */
	.pp-row2 .pp-cart-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
	.pp-row2 .pp-cart-sub { display: none; }
	.pp-compact-hamburger { color: #fff; width: var(--pp-hit-min); height: var(--pp-hit-min); }
	@media (hover: hover) { .pp-compact-hamburger:hover { background: rgba(255, 255, 255, .08); } }
	.pp-header-shell .pp-compact-hamburger:is(:active, .is-pressed) { background: rgba(255, 255, 255, .12); }

	/* Quick-link chips: 52 → 0px with --p; hidden in the compact layer. */
	.pp-tchips {
		display: block;
		position: relative;
		z-index: 1;
		height: calc(52px * (1 - var(--p)));
		overflow: hidden;
		background: var(--pp-navy);
		box-shadow: inset 0 1px 0 rgba(255, 255, 255, .09);
	}
	.pp-tchips-scroll { opacity: calc(1 - var(--p) * 2.5); }
	.pp-compact .pp-tchips { visibility: hidden; }
	.pp-nav-ghost .pp-tchips-scroll { pointer-events: none; }

	/* SB.1C T2 (OPTION A): while compact with the cart progressing, T2 is the
	   top row and the strip's visible parts step out (its screen-reader list
	   stays). */
	.pp-tablet-compact.pp-has-t2 { top: calc(var(--pp-admin-bar-h, 0px) + 34px); }
	.pp-tablet-compact.pp-has-t2 .pp-ticker--desktop { min-height: 0; padding: 0; }
	.pp-tablet-compact.pp-has-t2 .pp-ticker--desktop > :not(.pp-visually-hidden) { display: none; }

	/* The menu: a right-hand side sheet under the header's live bottom edge
	   (--pp-drawer-top, header.js), over the scrim; its content scrolls. */
	.pp-mobile-drawer {
		position: fixed;
		z-index: 5;
		top: var(--pp-drawer-top, 96px);
		inset-inline-end: 0;
		bottom: 0;
		width: min(420px, 100%);
		display: block;
		border-top: 0;
		box-shadow: -12px 0 30px rgba(0, 0, 0, .14);
		overflow-y: auto;
		overscroll-behavior: contain;
		opacity: 0;
		visibility: hidden;
		transition: opacity 140ms var(--pp-ease-in), visibility 0s linear 140ms;
	}
	.pp-mobile-drawer.is-open { opacity: 1; visibility: visible; transition: opacity 180ms var(--pp-ease-out), visibility 0s; }
	.pp-mobile-drawer-inner { overflow: visible; }
	.pp-header-scrim { display: block; position: fixed; inset: 0; z-index: 150; background: rgba(17, 17, 17, .32); }
	.pp-header-scrim[hidden] { display: none; }
}

/* ===================== MOBILE (≤767) — PERSISTENT COMPACT =====================
   The header ELEMENT is sticky (never a child — the zero-sticky-range
   gotcha) and the service strip persists in every state. UI.1 (Human Lock
   §4): the compact composition is the persistent mobile header — it never
   expands or collapses, so its height is constant (strip 30 + row 56 = 86).
   header.js only toggles the "not at top" shadow (.pp-scrolled) here. HD.1:
   the navy row with the Lime wordmark (124 / 112); MOB-03: centred, between
   Menu · Search and the unboxed Cart. */
@media (max-width: 767px) {
	.pp-header-shell { position: sticky; top: 0; }
	/* MOB-01: an offset-less sticky box lays out exactly like the in-flow
	   drawer, but iOS 26+ Safari's screen-edge sampling stops at it instead of
	   reaching the sticky header, so the header is never kept as the bottom
	   edge (painting its Navy under the toolbar) after the menu closes. */
	.pp-mobile-drawer { position: sticky; }
	/* MOB-02: the open menu scrolls its own content. The drawer still opens in
	   flow on the grid-rows expander, but its content box ends at the live
	   viewport bottom (from its measured top edge, --pp-mdrawer-top, header.js),
	   so every row is reachable at once while the page behind holds its scroll
	   (the shared overlay lock) and no gesture chains to it. The last row
	   clears Safari's floating bottom toolbar: iOS 26 reports it as the bottom
	   safe-area inset (98 / 58px expanded / compact on the Human's iPhone). */
	.pp-mobile-drawer-inner {
		max-height: calc(100vh - var(--pp-mdrawer-top, 87px));
		max-height: calc(100dvh - var(--pp-mdrawer-top, 87px));
		overflow-y: auto;
		overscroll-behavior: contain;
	}
	.pp-mobile-drawer-inner > .pp-mdrawer-screen { padding-bottom: var(--pp-safe-bottom); }

	/* Strip: 30px darker-chrome service band. MOB-03: the moving ticker (the
	   track supplies the 16px gutter; it never wraps, so the strip is 30px at
	   every width) and the strip-right Market chip, 8px end inset — its
	   styling lives with the other market variants in header-commerce.css. */
	.pp-mstrip { display: flex; align-items: center; background: var(--pp-navy-chrome); min-height: 30px; padding-inline: 0 8px; }

	.pp-mobile-row { padding-block: 6px; }
}

/* Reduced motion: no interpolation (header.js applies the discrete rule —
   p is 0 or 1) and every state change is instant. */
@media (prefers-reduced-motion: reduce) {
	.pp-header-shell, .pp-row2, .pp-row2 *, .pp-navrow, .pp-navrow *, .pp-tchips, .pp-tchips *, .pp-mobile-drawer { transition-duration: 0ms !important; }
}

/* ===================== Focus on Navy (HD.1) =====================
   The controls that sit on the dark chrome take a 2px white outline (the
   design-system ink / white-gap rings disappear on Navy); everything inside
   the white surfaces (panels, menus, drawer, Search results) keeps the
   design-system ring. */
.pp-header-shell :is(.pp-logo, .pp-mobile-logo, .pp-nav-item, .pp-account-link, .pp-cart, .pp-mobile-cart, .pp-compact-hamburger, .pp-tchip):focus-visible,
.pp-header-shell .pp-mobile-icons .pp-icon-btn:focus-visible {
	outline: 2px solid #fff;
	outline-offset: 2px;
	box-shadow: none;
}

/* ======================= HD.1 STICKY-OFFSET AUTHORITY =======================
   (UI.1 Human Lock §11, as amended by HD.1.) THE ONE responsive value
   every page-level sticky surface positions itself against. Consumers use
     top: calc(var(--pp-sticky-top) + <their own gap> + var(--pp-admin-bar-h, 0px))
   and never a header height of their own.

   A root custom property restyles the WHOLE document when it changes, so
   the root value is STATIC per tier — the FULL header's line (its bottom
   edge − 1px, the edge tucked under the header): 149 desktop · 161 tablet ·
   85 mobile here before measurement, the measured value from header.js
   after — and never written while scrolling. Sticky surfaces under the
   header opt in with `data-pp-sticky-follow`; header.js gives each the LIVE
   line inline (149 → 93 desktop, 161 → 95 tablet, 85 mobile), one element
   restyle per pixel of compaction. A surface that has not opted in is
   fail-safe: it sits under the full header's line — a gap under the compact
   header, never underneath it.
   --pp-header-compact-h: the compact header height per tier (94 desktop,
   96 tablet); in-page anchors clear it (scroll-padding-top), as before. */
html { --pp-sticky-top: 0px; }
@media (min-width: 1180px) { html { --pp-header-compact-h: 94px; --pp-sticky-top: 149px; scroll-padding-top: calc(var(--pp-header-compact-h) + 8px); } }
@media (min-width: 768px) and (max-width: 1179px) { html { --pp-header-compact-h: 96px; --pp-sticky-top: 161px; scroll-padding-top: calc(var(--pp-header-compact-h) + 8px); } }
@media (max-width: 767px) { html { --pp-sticky-top: 85px; } }
/* WordPress's admin bar (logged-in staff only) is fixed at 32px from 783px —
   and at 46px below that, which reaches the fixed tablet header at 768–782. */
@media (min-width: 783px) { .admin-bar { --pp-admin-bar-h: 32px; } }
@media (min-width: 768px) and (max-width: 782px) { .admin-bar { --pp-admin-bar-h: 46px; } }
