/*
 * S6D commerce-shell components — mega menu zones/tiles, Brands panel,
 * predictive search panel, cart drawer, mobile/compact nav drawer drill-in.
 * Values translated 1:1 from the approved final lab
 * (design-lab/final/header/s6-commerce-shell-final/commerce-shell-final.css)
 * into this theme's own .pp-* namespace — HEADER-DIRECTION-LOCK.md v1.1.
 *
 * S9D-B (GLOBAL-COMMERCE-POLISH-LOCK.md §18, §21, §29 — measured from
 * design-lab/final/global-polish/ Hybrid V2): zone links with Navy hover
 * tint and 32px rows, tiles on soft surface with CONTAINED .pp-packshot art
 * (never cover-cropped), the search panel on the component
 * transition with 48px rows / loading skeleton / no-results, the mobile
 * drawer drill rows at ≥44px and the mobile search takeover on the overlay
 * transition. The Cart Drawer block below is UNCHANGED (S9D-D owns it).
 */

/* ================= Shop mega menu — zones + tiles ================= */

.pp-mm-inner, .pp-brands-inner { max-width: var(--pp-container-max); margin: 0 auto; }

.pp-mm-zones { display: grid; gap: 32px; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); margin-bottom: 24px; }

.pp-mm-zone h4, .pp-brands-inner h4 { font: 700 11px/1.3 var(--pp-font-body); letter-spacing: .06em; text-transform: uppercase; color: var(--pp-secondary-text); margin: 0 0 12px; }
.pp-mm-zone ul { list-style: none; margin: 0; padding: 0; }
.pp-mm-zone li { margin-bottom: 4px; }
.pp-mm-zone a {
	display: flex; align-items: center; gap: 8px;
	min-height: 32px; padding: 0 6px; margin-inline: -6px; border-radius: 4px;
	font: 400 13.5px/1.3 var(--pp-font-body); color: var(--pp-ink);
	transition: color var(--pp-motion-micro) var(--pp-ease-out), background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-mm-zone a:hover { color: var(--pp-navy); background: var(--pp-navy-tint); }
.pp-mm-zone a:active { background: var(--pp-navy-tint-strong); }
.pp-mm-zone a.pp-mm-seeall { color: var(--pp-navy); font-weight: 600; gap: 6px; }
.pp-mm-seeall .pp-i { color: currentColor; }

/* Flavour-family marks. UI.1F (Human, UI-HUMAN-LOCK.md "UI.1F"): every
   catalogue family carries its Tabler 3.49.0 glyph (inc/icons.php
   pp_flavour_family_mark()) at 16px, stroke 1.75, in its family colour.
   This is the one family-colour source: the header menus, Search and the
   Brand Page flavour cards all read it. Mint, Fruit, Berry and Tropical
   keep their original colours; the other eleven were added by the Human's
   flavour-icon ruling (GLOBAL-COMMERCE-POLISH-LOCK.md, FLAVOUR ICON NOTE).
   Only a future family without a colour takes the secondary text colour
   (the dot's light neutral would make a line glyph unreadable). A family
   without a mapped glyph keeps the committed dot. */
.pp-mm-swatch { display: inline-block; width: 9px; height: 9px; border-radius: 50%; flex: none; background: var(--pp-fam, var(--pp-border)); }
.pp-flavour-i { width: 16px; height: 16px; flex: none; color: var(--pp-fam, var(--pp-secondary-text)); }
:is(.pp-mm-swatch, .pp-flavour-i).mint { --pp-fam: #4FA8D8; }
:is(.pp-mm-swatch, .pp-flavour-i).fruit { --pp-fam: #F2A93B; }
:is(.pp-mm-swatch, .pp-flavour-i).berry { --pp-fam: #8A5CC2; }
:is(.pp-mm-swatch, .pp-flavour-i).tropical { --pp-fam: #E8635E; }
:is(.pp-mm-swatch, .pp-flavour-i).citrus { --pp-fam: #D2B90E; }
:is(.pp-mm-swatch, .pp-flavour-i).watermelon { --pp-fam: #CA3764; }
:is(.pp-mm-swatch, .pp-flavour-i).cola { --pp-fam: #8D3424; }
:is(.pp-mm-swatch, .pp-flavour-i).energy { --pp-fam: #416AD1; }
:is(.pp-mm-swatch, .pp-flavour-i).fizzy { --pp-fam: #27A3A0; }
:is(.pp-mm-swatch, .pp-flavour-i).candy-dessert { --pp-fam: #E681A5; }
:is(.pp-mm-swatch, .pp-flavour-i).coffee { --pp-fam: #885E3E; }
:is(.pp-mm-swatch, .pp-flavour-i).floral-exotic { --pp-fam: #C552AC; }
:is(.pp-mm-swatch, .pp-flavour-i).spicy-herbal { --pp-fam: #449854; }
:is(.pp-mm-swatch, .pp-flavour-i).licorice { --pp-fam: #3C3041; }
:is(.pp-mm-swatch, .pp-flavour-i).tobacco { --pp-fam: #A18238; }

.pp-mm-count { color: var(--pp-secondary-text); font-size: 12px; }
.pp-mm-strength-row { justify-content: space-between; }

/* Brand rows — SF.4 / BR.6 (BR.3B LOCK 1 + LOCK 11): the approved registry
   mark at the mega column's own density, never a product photo cropped to a
   circle (the lock §18 product_brand thumbnail this replaces). The mark
   carries the brand name (alt), so no name text repeats beside it; the real
   count sits on the row's end edge exactly like the strength rows beside it.
   Mark size is the registry's model, base x logo_scale x 1.03 x density
   (ruling C5) — 30 x 1.03 x .45 = 13.9px nominal in the 32px row. */
.pp-mm-zone a.pp-mm-brand-row { justify-content: space-between; }
/* Two classes on purpose: WooCommerce's `.woocommerce img, .woocommerce-page
   img { height:auto; max-width:100% }` (0,1,1) is on every Shop / PDP / Cart
   / Account page and would otherwise win, rendering the mark at its natural
   size (SF.4 review R1, B-01). max-width:none keeps the registry ratio. */
.pp-mm-zone .pp-mm-brand-logo {
	--pp-mm-mark-k: .45;
	display: block;
	flex: 0 0 auto;
	width: auto;
	max-width: none;
	height: calc(30px * var(--pp-bdx-ls, 1) * 1.03 * var(--pp-mm-mark-k));
}
/* CAT.6B — a brand without an approved mark keeps its row by NAME (Human
   decision 2026-10-21: discoverability never depends on logo availability).
   The search panel's precedent (.pp-sp-brand-name): the display face at 600,
   here at the row's own size; colour follows the row (hover included). */
.pp-mm-zone .pp-mm-brand-name {
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-family: var(--pp-font-display);
	font-weight: 600;
}

/* Tiles — soft surface, copy bottom-start, contained packshot top-end (lock §21). */
.pp-mm-tiles { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); padding-top: 24px; border-top: 1px solid var(--pp-border); }
.pp-tile {
	position: relative; display: flex; align-items: flex-end; gap: 12px;
	min-height: 128px; padding: 14px; border-radius: var(--pp-radius-lg);
	background: var(--pp-soft-surface); color: var(--pp-ink);
	border: 1px solid transparent; overflow: hidden; cursor: pointer;
	transition: border-color var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-press-out) var(--pp-ease-out);
}
.pp-tile:hover { border-color: var(--pp-navy); }
.pp-tile:active, .pp-tile.is-pressed { transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
.pp-tile-shot { position: absolute; inset-inline-end: 10px; top: 10px; width: 96px; height: 96px; }
.pp-tile-shot .pp-packshot { width: 100%; height: 100%; }
.pp-tile:hover .pp-tile-shot .pp-packshot img { transform: translateY(calc(var(--pp-lift) * -1)) scale(var(--pp-packshot-display, 1)); }
.pp-tile-copy { display: flex; flex-direction: column; gap: 4px; max-width: 60%; }
.pp-tile-eyebrow { display: inline-block; width: fit-content; background: var(--pp-navy); color: #fff; font: 700 10px/1 var(--pp-font-body); letter-spacing: .04em; text-transform: uppercase; padding: 5px 9px; border-radius: 5px; }
.pp-tile--deal .pp-tile-eyebrow { background: var(--pp-red); }
.pp-tile-head { font: 600 16px/1.2 var(--pp-font-display); }
.pp-tile-msg { font: 400 12px/1.4 var(--pp-font-body); color: var(--pp-secondary-text); }

/* ================= Brands panel — Compact Identity (SF.4 / BR.6) =================
   BR.3B LOCK 11 (HUMAN-LOCKED direction — Board K, captures 21 + 24), read
   through ruling C4: the production ~76px row and this panel's 4-up grid
   STAND (the lab's 62px row is not ported), and H1–H4 are re-derived inside
   them. Values are the lab's R1 header rules (shared/br3a-r1.css §3) unless a
   comment says otherwise:
     H1 count 12.5/500, right-aligned, tabular — one shared end edge
     H2 mark clear space max(12px, .85 x mark height), never a flat gap
     H3 a 34px contained product cue, seated on the card family's contact pool
     H4 a 3px leading tone rail (not a floor bar: under a nav row a floor edge
        reads as an underline / hover state)
   Mark size is the registry's production model (ruling C5): base x
   logo_scale x 1.03 x surface density, here 30 x 1.03 x .615 = 19px nominal —
   BR.3's header nominal height, unchanged by the taller production row; the
   extra height is air. The lab's gamma / ink normalisation is NOT ported.
   Tone = the brand's VERIFIED accent or the Navy-safe fallback (A1.2: lab
   candidate tones were never promoted) — the /brands/ rule exactly.
   Interaction stays the header's own nav affordance (Navy border on hover,
   press scale); only the product cue moves. */

.pp-brands-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; margin-bottom: 14px; }
.pp-brands-grid > *, .pp-mbrand-grid > * { min-width: 0; }

.pp-bh {
	/* per-brand values arrive inline from pp_brand_presentation(); these are
	   the fallbacks for a row that carries none. */
	--pp-bdx-tone: var(--pp-navy);
	--pp-bdx-field: 1;
	--pp-bdx-ls: 1;
	/* surface density — the panel row */
	--pp-bh-mark-k: .615;
	--pp-bh-mark-h: calc(30px * var(--pp-bdx-ls) * 1.03 * var(--pp-bh-mark-k));

	position: relative;
	display: flex;
	align-items: center;           /* R1-D3: every mark centred on one optical line */
	box-sizing: border-box;        /* R1-D4: min-height is the whole row */
	min-height: 76px;              /* C4: the production row stands */
	padding: 14px 16px 14px 18px;
	overflow: hidden;
	isolation: isolate;
	border: 1px solid #E3E8EF;
	border-radius: var(--pp-radius-lg);
	/* the R1 header ground (G1): `field` DIVIDES the tint (R1-D2) */
	background:
		radial-gradient(118% 128% at 84% 112%,
			color-mix(in srgb, var(--pp-bdx-tone) calc(10% / var(--pp-bdx-field)), transparent),
			transparent 62%),
		linear-gradient(168deg, #FFFFFF 0%, #F7F9FB 62%, #EEF2F6 100%);
	color: var(--pp-ink);
	text-decoration: none;
	transition: border-color var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-press-out) var(--pp-ease-out);
}
.pp-bh:hover { border-color: var(--pp-navy); }
.pp-bh:active, .pp-bh.is-pressed { transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }

/* H4 — the leading tone rail */
.pp-bh::before {
	content: '';
	position: absolute;
	z-index: 1;
	inset-block: 0;
	inset-inline-start: 0;
	width: 3px;
	background: var(--pp-bdx-tone);
	opacity: calc(.92 / var(--pp-bdx-field));
}

/* The registry mark + H2 clear space. Two classes: see .pp-mm-brand-logo —
   WooCommerce's `.woocommerce img` (0,1,1) must not reach the mark (B-01). */
.pp-bh .pp-bh-mark {
	display: block;
	flex: 0 0 auto;
	width: auto;
	max-width: none;
	height: var(--pp-bh-mark-h);
	margin-inline-end: max(12px, calc(.85 * var(--pp-bh-mark-h)));
}

/* CAT.6B — no approved mark: the brand's NAME stands in the mark's place, on
   the same optical line with the same clear space. The search panel's ratio
   (13px name beside a ~15px mark slot): the display face at 600, .86 x this
   surface's mark height. Never a drawn or imitated mark. */
.pp-bh .pp-bh-name {
	flex: 0 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-family: var(--pp-font-display);
	font-size: calc(.86 * var(--pp-bh-mark-h));
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: -0.01em;
	margin-inline-end: max(12px, calc(.85 * var(--pp-bh-mark-h)));
}

/* H1 — the real count on one shared end edge (all longhand: R1-D1) */
.pp-bh-count {
	flex: 0 0 auto;
	margin-inline-start: auto;
	text-align: end;
	font-family: var(--pp-font-body);
	font-size: 12.5px;
	font-weight: 500;
	line-height: 1.3;
	color: var(--pp-secondary-text);
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

/* H3 — the product cue: contained, seated, decorative */
.pp-bh-cue {
	position: relative;
	flex: 0 0 auto;
	width: 34px;
	height: 34px;
	margin-inline-start: 14px;
}
.pp-bh-cue::after {
	content: '';
	position: absolute;
	z-index: 0;
	left: 8%;
	right: 8%;
	bottom: 1px;
	height: 5px;
	border-radius: 50%;
	background: radial-gradient(closest-side, rgba(11, 29, 56, 0.26) 0%, rgba(11, 29, 56, 0.12) 52%, transparent 100%);
}
.pp-bh .pp-bh-cue img {
	position: relative;
	z-index: 1;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}
@media (prefers-reduced-motion: no-preference) {
	.pp-bh-cue img { transition: transform 180ms var(--pp-ease-out); }
	.pp-bh:hover .pp-bh-cue img,
	.pp-bh:focus-visible .pp-bh-cue img { transform: translateY(-2px); }
}

.pp-brands-seeall { padding-inline: 0; gap: 6px; }

/* ================= Predictive search panel (lock §29) =================
   Opens on the component transition (opacity + 4px); 48px result rows with
   hover tint, pressed tint-strong and the keyboard highlight; the empty-state
   groups (HD.1F); loading skeleton; no-results block; view-all row. */

.pp-search-panel {
	position: absolute; top: calc(100% + 8px); inset-inline: 0;
	background: #fff; border: 1px solid var(--pp-border); border-radius: var(--pp-radius-lg);
	box-shadow: var(--pp-shadow-popover); z-index: 160; max-height: 70vh; overflow-y: auto;
	opacity: 0; transform: translateY(-4px); 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-search-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; }
.pp-search-panel-inner { padding: 12px; }

.pp-sp-group + .pp-sp-group { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--pp-border); }
.pp-sp-group h5 { font: 700 11px/1.3 var(--pp-font-body); letter-spacing: .06em; text-transform: uppercase; color: var(--pp-secondary-text); margin: 0 6px 8px; }

.pp-sp-row {
	display: flex; align-items: center; gap: 12px; width: 100%; min-height: 48px;
	padding: 6px 8px; border-radius: var(--pp-radius-md); text-align: start; color: var(--pp-ink);
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-sp-row:hover, .pp-sp-row.is-focus { background: var(--pp-navy-tint); }
.pp-sp-row:active { background: var(--pp-navy-tint-strong); }
.pp-sp-row .pp-packshot { width: 40px; height: 40px; border-radius: 6px; flex: none; border: 1px solid var(--pp-border); }
/* SF.4 ruling 6 — the brand row's registry mark (it replaced the round
   .pp-brand-mark product photo): the Compact Identity row's 19px nominal height
   x the brand's own `logo_scale` (ruling C5). Two classes + max-width:none:
   WooCommerce's `.woocommerce img` (0,1,1) must not resize it (B-01). */
.pp-sp-row .pp-sp-brand-logo { flex: none; display: inline-flex; align-items: center; }
.pp-sp-row .pp-sp-brand-logo img { display: block; width: auto; max-width: none; height: calc(30px * var(--pp-bdx-ls, 1) * 1.03 * .615); }
.pp-sp-row .pp-mm-swatch { width: 12px; height: 12px; margin-inline: 10px; }
.pp-sp-row .body { flex: 1; min-width: 0; }
.pp-sp-row .t { display: block; font: 500 13.5px/1.3 var(--pp-font-body); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pp-sp-row .m { display: block; font: 400 11.5px/1.3 var(--pp-font-body); color: var(--pp-secondary-text); }
.pp-sp-row .p { font: 700 13px/1 var(--pp-font-body); flex: none; }
.pp-sp-row .name { font: 600 15px/1 var(--pp-font-display); }
.pp-sp-row > .pp-i { color: var(--pp-navy); flex: none; }
/* UI.1F: the family glyph keeps its family colour and the dot's 32px slot (16 + 2 × 8). */
.pp-sp-row > .pp-flavour-i { color: var(--pp-fam, var(--pp-secondary-text)); margin-inline: 8px; }

.pp-sp-viewall {
	display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; min-height: 44px;
	margin-top: 8px; border-top: 1px solid var(--pp-border); color: var(--pp-navy); font: 600 13px/1 var(--pp-font-body);
	border-radius: 0 0 var(--pp-radius-md) var(--pp-radius-md);
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-sp-viewall:hover, .pp-sp-viewall.is-focus { background: var(--pp-navy-tint); }

.pp-sp-chips { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 6px; }
/* HD.1F — the Search empty state (the HD.1 lab's panel, predictive-search.js
   renderEmpty()): Popular brands as keyline pills (the registry mark at the
   lab's 15px nominal x the brand's own `logo_scale` + the real count), Shop by
   flavour as pill chips carrying the family glyph, and the guide rows on the
   result-row grammar with a soft arrow tile and the hub name. Hover and the
   keyboard highlight (is-focus) take the rows' Navy tint. Two classes on the
   mark + max-width:none, as the brand row (B-01). */
.pp-sp-brands { display: flex; flex-wrap: wrap; gap: 8px; padding: 0 6px; }
.pp-sp-brand {
	display: inline-flex; align-items: center; gap: 8px; min-height: 38px; padding: 0 12px;
	border: 1px solid var(--pp-border); border-radius: var(--pp-radius-control);
	color: var(--pp-secondary-text); font: 600 12px/1 var(--pp-font-body);
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out), border-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-sp-brand:hover, .pp-sp-brand.is-focus { background: var(--pp-navy-tint); border-color: var(--pp-navy); }
.pp-sp-brand .pp-sp-brand-logo { display: inline-flex; align-items: center; }
.pp-sp-brand .pp-sp-brand-logo img { display: block; width: auto; max-width: none; height: calc(24px * var(--pp-bdx-ls, 1) * 1.03 * .615); }
.pp-sp-brand-name { color: var(--pp-ink); font: 600 13px/1 var(--pp-font-display); }
.pp-sp-fchip { padding-inline: 12px; border-radius: 999px; font: 500 13px/1 var(--pp-font-body); }
/* The lab's 34px chip on tablet / desktop; phones keep the design system's
   40px chip (design-system.css) and the pills match it for touch. */
@media (min-width: 768px) { .pp-sp-fchip { min-height: 34px; } }
@media (max-width: 767px) { .pp-sp-brand { min-height: 40px; } }
.pp-sp-fchip .pp-flavour-i { width: 16px; height: 16px; }
.pp-sp-row--guide .pp-sp-guide-ic { display: inline-flex; align-items: center; justify-content: center; flex: none; width: 40px; height: 28px; border-radius: 6px; background: var(--pp-soft-surface); color: var(--pp-navy); }
.pp-sp-row--guide .pp-sp-guide-m { flex: none; font: 500 12px/1 var(--pp-font-body); color: var(--pp-secondary-text); white-space: nowrap; }
.pp-sp-row--guide .t { white-space: normal; } /* a guide title wraps (the lab), never truncates as a product name does */
.pp-sp-hint { font: 500 12px/1.4 var(--pp-font-body); color: var(--pp-secondary-text); padding: 8px; margin: 0; display: flex; align-items: center; gap: 8px; }
.pp-sp-noresults { padding: 8px; }
.pp-sp-noresults .h { font: 600 14px/1.3 var(--pp-font-body); margin: 0 0 4px; }
.pp-sp-noresults .s { font: 400 12.5px/1.4 var(--pp-font-body); color: var(--pp-secondary-text); margin: 0; }
/* Gate B.1: the no-results block is a .pp-sp-group followed by the ONE shared Browse group (renderBrowse()) — the former hardcoded “try” link list is gone. */
.pp-sp-skel { height: 40px; border-radius: 6px; background: linear-gradient(90deg, var(--pp-soft-surface) 25%, var(--pp-secondary-surface) 50%, var(--pp-soft-surface) 75%); background-size: 200% 100%; animation: pp-skel 1200ms linear infinite; margin: 6px 8px; }
@keyframes pp-skel { from { background-position: 200% 0; } to { background-position: -200% 0; } }

/* ================= Cart drawer — S9D-D polish =================
   GLOBAL-COMMERCE-POLISH-LOCK.md §8 (Drawer Breath), §38 (controls),
   §16 (safe area), §26 (price hierarchy), ROUND-2-DECISIONS Cart Drawer.
   Cart authority, the REST routes and the drawer's structure are untouched
   — this block is presentation only. Values measured from the promoted lab
   design-lab/final/global-polish/ (.pp-drawer / .pp-line / .pp-stepper). */

/* Drawer Breath: overlay fades and the panel slides on the decelerate
   curve; the exit is faster on the accelerate curve. Both use the shared
   overlay motion tokens, which already carry their reduced-motion values
   (design-system.css §2 — 120/100ms fade, no transform below).
   Closed is also visibility: hidden (the .pp-fpanel-overlay pattern): iOS 26+
   Safari hit-tests the screen edges through opacity, pointer-events and inert,
   and a closed scrim inside the sticky header made it paint the header's Navy
   under its bottom toolbar (MOB-01). */
.pp-cart-overlay { position: fixed; inset: 0; background: var(--pp-overlay); z-index: 300; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity var(--pp-motion-overlay-exit) var(--pp-ease-in), visibility 0s linear var(--pp-motion-overlay-exit); }
.pp-cart-overlay.is-open { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity var(--pp-motion-overlay) var(--pp-ease-out), visibility 0s; }

.pp-cart-drawer { position: fixed; top: 0; inset-inline-end: 0; bottom: 0; width: 420px; max-width: 92vw; background: #fff; transform: translateX(100%); transition: transform var(--pp-motion-overlay-exit) var(--pp-ease-in); box-shadow: var(--pp-shadow-drawer); z-index: 301; display: flex; flex-direction: column; }
[dir="rtl"] .pp-cart-drawer { transform: translateX(-100%); }
.pp-cart-overlay.is-open .pp-cart-drawer { transform: none; transition: transform var(--pp-motion-overlay) var(--pp-ease-out); }

/* …the body content settles ~60ms behind the panel; the foot with Checkout
   is visible and interactive from the first frame (lock §8), so it is never
   part of this staggered group. */
.pp-cart-overlay:not(.is-open) .pp-cart-body > * { opacity: 0; transform: translateY(6px); transition: none; }
.pp-cart-overlay.is-open .pp-cart-body > * {
	opacity: 1; transform: none;
	transition: opacity var(--pp-motion-component) var(--pp-ease-out) var(--pp-motion-stagger),
	            transform var(--pp-motion-component) var(--pp-ease-out) var(--pp-motion-stagger);
}
@media (prefers-reduced-motion: reduce) {
	.pp-cart-overlay:not(.is-open) .pp-cart-body > * { opacity: 1; transform: none; }
	.pp-cart-overlay.is-open .pp-cart-body > * { transition: none; }
	/* S9D-D-R (MINOR 1): reduced motion is "fade only, no translate"
	   (lock §7 overlay row / §8). The panel previously still slid — the
	   reduced tokens only shortened the slide to 120/100ms. The panel now
	   never translates in either direction; the overlay's own opacity
	   transition (already on the reduced overlay tokens) is the whole
	   animation. Closed remains genuinely closed: the overlay stays
	   opacity 0 + pointer-events:none + `inert` (pp-overlay.js), so a
	   non-translated panel is neither visible nor reachable. */
	.pp-cart-drawer,
	[dir="rtl"] .pp-cart-drawer,
	.pp-cart-overlay.is-open .pp-cart-drawer { transform: none; transition: none; }
}

.pp-cart-head { display: flex; align-items: center; justify-content: space-between; gap: var(--pp-space-3); padding: 14px 12px 12px var(--pp-space-5); border-bottom: 1px solid var(--pp-border); flex: none; }
.pp-cart-head h3 { font: 600 20px/1.2 var(--pp-font-display); letter-spacing: -0.015em; margin: 0; }
/* Close: the shared ≥44px bordered icon button + shared inline-SVG glyph
   (lock §38 / §15) — the raw ✕ text glyph is gone. */
.pp-cart-close { flex: none; }

.pp-cart-body { flex: 1; overflow-y: auto; padding: 20px var(--pp-space-5); display: flex; flex-direction: column; gap: 20px; }
.pp-cart-foot { flex: none; padding: 14px var(--pp-space-5); padding-bottom: calc(20px + var(--pp-safe-bottom)); border-top: 1px solid var(--pp-border); display: flex; flex-direction: column; gap: 10px; }

.pp-cart-lines { display: flex; flex-direction: column; gap: 20px; }
.pp-cart-line { display: flex; gap: 12px; align-items: flex-start; transition: opacity var(--pp-motion-micro) var(--pp-ease-out); }
.pp-cart-line.pp-busy { opacity: .55; pointer-events: none; }
.pp-cart-line-img { flex: none; }
/* One shared packshot component (lock §24) — 1:1 box, contain, white
   ground, per-product display scale from the single adapter. */
.pp-cart-line-img .pp-cart-packshot { width: 64px; height: 64px; display: flex; }
.pp-cart-line-body { flex: 1; min-width: 0; }
.pp-cart-line-title { display: block; font: 600 14px/1.3 var(--pp-font-body); color: var(--pp-ink); }
.pp-cart-line-meta { font: 400 12px/1.3 var(--pp-font-body); color: var(--pp-secondary-text); margin: 1px 0 8px; }
.pp-cart-line-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Price hierarchy (human production-review correction, post-S6D; lock §26):
   per-can is the PRIMARY product price (same rule as the PLP/homepage
   cards) — ordinary/base per-can (struck, discounted lines only) is
   secondary, line total stays visible but tertiary. Cart footer subtotal
   remains dominant (unchanged, see .pp-cart-subtotal). The classes are now
   the shared .pp-price-* grammar (product-card.css); only the drawer's own
   density is set here. */
.pp-cart-line-price { flex: none; text-align: end; display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.pp-cart-line-percan.pp-price-primary { font-size: 14px; }
.pp-cart-line-was.pp-price-ref, .pp-cart-line-total.pp-price-total { font-size: 11.5px; text-transform: none; letter-spacing: 0; }

/* Stepper — lock §38: 40px cells (≥44px on true mobile), SVG glyphs, real
   disabled state at quantity 1, compact Press from the foundation. */
.pp-cart-stepper { display: inline-flex; align-items: center; border: 1px solid var(--pp-border); border-radius: var(--pp-radius-control); background: #fff; width: fit-content; }
.pp-cart-step {
	width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
	color: var(--pp-ink); border-radius: var(--pp-radius-control); cursor: pointer;
	-webkit-tap-highlight-color: transparent; touch-action: manipulation;
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out), transform var(--pp-motion-press-out) var(--pp-ease-out);
}
/* UI.1 P2 (Human Lock §8): hover on hover-capable input only; press = the
   12% tint + scale(.985), now also through pp-foundation.js's pointerdown
   `.is-pressed` (the stepper was `:active`-only — no press on touch). */
@media (hover: hover) { .pp-cart-step:hover { background: var(--pp-soft-surface); } }
.pp-cart-step:active, .pp-cart-step.is-pressed { background: var(--pp-navy-tint-strong); transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
.pp-cart-step:disabled { color: var(--pp-border); background: none; transform: none; cursor: not-allowed; }
.pp-cart-step .pp-i { width: 16px; height: 16px; }
.pp-cart-qty { min-width: 32px; align-self: stretch; display: inline-flex; align-items: center; justify-content: center; border-inline: 1px solid var(--pp-border); font: 600 var(--pp-text-label)/1 var(--pp-font-body); }
@media (prefers-reduced-motion: reduce) {
	.pp-cart-step:active, .pp-cart-step.is-pressed { transform: none; }
}
@media (max-width: 767px) {
	.pp-cart-step { width: var(--pp-hit-min); height: var(--pp-hit-min); }
}

/* Remove — the tertiary/text tier of the global button system (underline
   revealed on hover/focus by .pp-btn-text, never painted permanently); the
   ≥44px true-mobile floor comes from .pp-btn-text in design-system.css. */

.pp-cart-progress { background: var(--pp-soft-surface); border-radius: var(--pp-radius-lg); padding: 14px var(--pp-space-4); }
.pp-cart-progress .label { font: 600 13px/1.3 var(--pp-font-body); margin: 0 0 8px; color: var(--pp-ink); }
.pp-cart-progress-track { height: 6px; border-radius: 4px; background: var(--pp-border); overflow: hidden; }
/* Compositor-property fill so the movement survives the server-rendered
   body swap (lock §38) — assets/js/cart-drawer.js re-seeds the previous
   value on the fresh node, then sets the new one. */
.pp-cart-progress-track .fill { height: 100%; width: 100%; background: var(--pp-navy); transform-origin: left; transform: scaleX(var(--pp-progress, 0)); transition: transform calc(var(--pp-motion-feedback) * 1.8) var(--pp-ease-out), background-color var(--pp-motion-micro); }
[dir="rtl"] .pp-cart-progress-track .fill { transform-origin: right; }
.pp-cart-progress.pp-unlocked .fill { background: var(--pp-green); }
.pp-cart-progress.pp-unlocked .label { color: var(--pp-success-text); }

.pp-cart-recommend { display: flex; align-items: center; gap: 10px; border: 1px solid var(--pp-border); border-radius: var(--pp-radius-lg); padding: var(--pp-space-3); flex-wrap: wrap; /* S9E-A2-R1: lets a rejection take its own full-width row; the packshot / body / Add row itself never wraps (the body's basis is 0) */ }
/* S9E-A2-R1: a WooCommerce rejection of the recommendation add (cart-drawer.js)
   — the shared Commerce Notice error variant on its own row inside the card;
   empty = no row. Success renders nothing here: the re-rendered body is the
   confirmation. */
.pp-cart-recommend .pp-cart-recommend-notice { flex: 1 1 100%; min-width: 0; }
.pp-cart-recommend .pp-cart-packshot { width: 48px; height: 48px; flex: none; display: flex; }
.pp-cart-recommend-body { flex: 1; min-width: 0; }
.pp-cart-recommend-eyebrow { font: 700 var(--pp-text-meta-min)/1.2 var(--pp-font-body); text-transform: uppercase; letter-spacing: .04em; color: var(--pp-secondary-text); margin: 0 0 3px; }
.pp-cart-recommend-title { display: block; font: 600 13px/1.3 var(--pp-font-body); color: var(--pp-ink); }
/* S9D-D (lock §15): the recommendation title is the only link into that
   product — its packshot is a plain image, not a second link — so unlike a
   cart line's title it is NOT covered by an adjacent large target and
   takes its own ≥44px effective hit area on true mobile. The invisible
   pseudo keeps the visual type size unchanged. */
@media (max-width: 767px) {
	.pp-cart-recommend-title { position: relative; }
	.pp-cart-recommend-title::after {
		content: ""; position: absolute; top: 50%; left: 0;
		width: 100%; height: max(100%, var(--pp-hit-min));
		transform: translateY(-50%);
	}
}
.pp-cart-recommend-meta { font: 400 var(--pp-text-meta)/1.3 var(--pp-font-body); color: var(--pp-secondary-text); margin: 2px 0 0; }
.pp-cart-recommend-price { font: 500 12.5px/1.3 var(--pp-font-body); color: var(--pp-secondary-text); margin: 2px 0 0; }
/* S9D-A: an in-row button is the S tier of the global button foundation
   (36px) — not the M default the base .pp-btn now carries. S9D-A-R: the S
   min-height is scoped to >=768px so the foundation's true-mobile >=44px
   floor (design-system.css) is never outranked — lock §3 / §15, Account
   lock AK-3 principle. */
.pp-cart-recommend-add button { padding: 8px 14px; font-size: 12.5px; }
@media (min-width: 768px) { .pp-cart-recommend-add button { min-height: var(--pp-btn-h-s); } }

.pp-cart-subtotal { display: flex; align-items: center; justify-content: space-between; }
.pp-cart-subtotal .lab { font: 400 13px/1 var(--pp-font-body); color: var(--pp-secondary-text); }
.pp-cart-subtotal .amt { font: 700 18px/1 var(--pp-font-body); }

.pp-cart-empty { text-align: center; padding: 40px 12px; }
.pp-cart-empty-heading { font: 600 15px/1.3 var(--pp-font-body); margin-bottom: 6px; }
.pp-cart-empty-sub { font: 400 13px/1.4 var(--pp-font-body); color: var(--pp-secondary-text); margin-bottom: 18px; }

/* ================= Mobile / compact shared nav drawer — drill screens =================
   The drawer itself (grid-rows open/close) is in header.css. */

.pp-mdrawer-screen { display: none; }
.pp-mdrawer-screen.pp-active { display: block; }

.pp-mback {
	display: flex; align-items: center; gap: 8px; width: 100%; min-height: var(--pp-hit-min);
	text-align: start; background: var(--pp-soft-surface); border: none; padding: 0 18px;
	font: 600 14px/1.2 var(--pp-font-display); letter-spacing: 0; color: var(--pp-navy); cursor: pointer;
}
.pp-mback .pp-i { color: currentColor; }

.pp-msub { border-bottom: 1px solid var(--pp-border); }
.pp-msub a { display: flex; align-items: center; min-height: var(--pp-hit-min); padding: 0 18px; font: 400 14.5px/1.3 var(--pp-font-body); color: var(--pp-ink); }
.pp-msub a:active { background: var(--pp-navy-tint); }

.pp-mdrill-row {
	display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; min-height: var(--pp-hit-min);
	background: none; border: none; border-bottom: 1px solid var(--pp-border); padding: 0 18px;
	font: 400 14.5px/1.3 var(--pp-font-body); color: var(--pp-ink); cursor: pointer; text-align: start;
}
.pp-mdrill-row:active { background: var(--pp-navy-tint); }
.pp-mdrill-label { display: inline-flex; align-items: center; gap: 8px; }
.pp-mdrill-row .meta { color: var(--pp-secondary-text); font-size: 13px; }

/* Tablet drill brands screen — SF.4 / BR.6: the SAME Compact Identity row as
   the desktop panel, at the drill's committed 56px density (2-up, LOCK 11
   grid rule at <=1024). 56 - 2 (border) - 2 x 10 (padding) = the 34px cue. */
.pp-mbrand-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; padding: var(--pp-space-4) 18px; }
.pp-mbrand-grid .pp-bh { min-height: 56px; padding: 10px 14px 10px 16px; }

/* ================= Mobile anchored Search panel (design-locks/MOBILE-SEARCH-INTERACTION-LOCK.md) =================
   S12 human lock, Direction A — "the header expands into Search". ONE header:
   the panel is the last child of .pp-mobile-header (position:relative in
   header.css) and anchors at top:100% — a pure-CSS 0px attachment with no
   header-height constant. Supersedes the fullscreen takeover (GLOBAL-
   COMMERCE-POLISH-LOCK.md §29 mobile part). Tablet/desktop keep the
   .pp-search-panel dropdown; every selector here is display:none at ≥768.

   Wrapper  .pp-mobile-search-full — fixed, transparent, z 302. Rendered after
            the sticky header (MOB-01): inside it, iOS 26+ Safari's screen-edge
            sampling reached the header through this layer and kept its Navy
            under the bottom toolbar after Search closed. top = --pp-msf-top,
            the live bottom of .pp-mobile-header written by predictive-search.js
            (still a 0px attachment, no header-height constant). Carries opacity/visibility, the
            --pp-search-avail input and the ::before scrim: Search-scoped
            rgba(17,17,17,.12), no blur — NOT --pp-overlay (.32), which the
            Cart Drawer depends on. The scrim starts at the panel's top edge
            and runs one layout viewport downward, so it never covers the
            header; a tap on it arrives as e.target === overlay and closes
            Search through pp-overlay.js's existing backdrop path.
   Panel    .pp-msf-dialog — the white surface. Height model (lock §5; Gate B.1
            human clarification: the R1 45dvh figure was a visual reference,
            never a minimum — no min-height, no dead white space):
              empty     content-driven + 24px finishing space (.pp-msf-body padding)
              growth    content-driven with useful results / no-results
              maximum   max-height 60dvh
              capped    ≤ --pp-search-avail = visualViewport.height − header
                        bottom, written in px by predictive-search.js only
                        while Search is open (the keyboard shrinks the VISUAL
                        viewport; dvh alone does not follow it). Without
                        visualViewport the 60dvh default keeps the pure-dvh
                        geometry; engines without dvh fall back to the plain
                        60vh base (Gate D GC-2, @supports below) — Search
                        stays bounded and usable everywhere.
   Body     .pp-msf-body — the ONLY scrollable region while Search is open
            (overscroll-behavior: contain, no chaining to the locked
            document); the input row (.pp-msf-head) never scrolls away.
   Motion   component tokens (200ms enter / 140ms exit — 0ms under reduced
            motion): opacity on the wrapper, translateY(-8px → 0) on the panel. */

.pp-mobile-search-full {
	position: fixed; top: var(--pp-msf-top, 0px); inset-inline: 0;
	z-index: 302;
	background: transparent;
	--pp-search-avail: 60vh;   /* universally-valid base; the dvh enhancement is @supports-gated below (Gate D GC-2) */
	opacity: 0; visibility: hidden;
	transition: opacity var(--pp-motion-component-exit) var(--pp-ease-in), visibility 0s linear var(--pp-motion-component-exit);
}
.pp-mobile-search-full.is-open { opacity: 1; visibility: visible; transition: opacity var(--pp-motion-component) var(--pp-ease-out), visibility 0s; }
.pp-mobile-search-full::before {
	content: ""; position: absolute; top: 0; inset-inline: 0; z-index: -1;
	height: 100vh; height: 100lvh;
	background: rgba(17, 17, 17, .12);
}
.pp-msf-dialog {
	position: relative;
	display: flex; flex-direction: column;
	max-height: min(60vh, var(--pp-search-avail));
	background: #fff;
	border-top: 1px solid var(--pp-border);      /* hairline seam under the header row — the nav drawer's own convention */
	border-bottom: 1px solid var(--pp-border);   /* restrained lower boundary: no floating-card shadow, no rounded corners */
	padding-inline: var(--pp-safe-left) var(--pp-safe-right);   /* landscape notch clearance via the theme's safe-area tokens (design-system.css); the header owns the top inset — never double-applied */
	transform: translateY(-8px);
	transition: transform var(--pp-motion-component-exit) var(--pp-ease-in);
}
.pp-mobile-search-full.is-open .pp-msf-dialog { transform: none; transition: transform var(--pp-motion-component) var(--pp-ease-out); }
/* Gate D (GC-2): dvh as a progressive enhancement over the 60vh base above. The
   previous two-line ladder was DEAD on non-dvh engines — a declaration that
   contains var() is never parse-rejected, so the dvh line always won the
   cascade and then resolved (invalid at computed-value time) to
   max-height:none, not to the vh line; the panel lost its cap entirely on
   iOS ≤15.3 / Chrome <108. @supports gates the modern unit instead; the JS
   visual-viewport px write on --pp-search-avail (open-state only) overrides
   the custom property in both worlds, so the keyboard clamp is unchanged —
   and now also bounds legacy engines that still expose visualViewport. */
@supports (height: 1dvh) {
	.pp-mobile-search-full { --pp-search-avail: 60dvh; }
	.pp-msf-dialog { max-height: min(60dvh, var(--pp-search-avail)); }
}
.pp-msf-head { display: flex; align-items: center; gap: 6px; padding: 8px var(--pp-gutter-mobile) 10px; flex: none; }
.pp-msf-head .pp-search { flex: 1; min-width: 0; }
.pp-msf-close { flex: none; color: var(--pp-ink); }
.pp-msf-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; padding: 2px var(--pp-gutter-mobile) 24px; }   /* 24px finishing space after the last row (+1px boundary) — Gate B.1 */
/* Inside the panel the result grammar aligns to the field's edge; the shared
   .pp-sp-* rules keep their dropdown insets on tablet/desktop untouched. */
.pp-msf-body .pp-sp-group h5 { margin-inline: 0; }
.pp-msf-body .pp-sp-chips, .pp-msf-body .pp-sp-brands, .pp-msf-body .pp-sp-hint, .pp-msf-body .pp-sp-noresults { padding-inline: 0; }
.pp-msf-body .pp-sp-row { padding-inline: 4px; margin-inline: -4px; width: auto; }
/* Soft foot fade (lock §12) — CSS only: white over white when nothing continues, a soft cut when rows do. */
.pp-msf-dialog::after { content: ""; position: absolute; inset-inline: 0; bottom: 0; height: 24px; background: linear-gradient(to top, #fff, rgba(255, 255, 255, 0)); pointer-events: none; }
/* Browse shortcuts — the no-results state on every tier (renderBrowse(),
   predictive-search.js; HD.1F moved the empty query to the lab's groups):
   navigation over the existing URL authority, not results. ≥44px rows,
   drawer-row typography, one hairline between rows. */
.pp-sp-browse-row {
	display: flex; align-items: center; justify-content: space-between; gap: 8px;
	min-height: var(--pp-hit-min); padding-inline: 4px; margin-inline: -4px;
	color: var(--pp-ink); font: 600 14px/1.2 var(--pp-font-display);
	border-radius: var(--pp-radius-control);
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-sp-browse-row + .pp-sp-browse-row { border-top: 1px solid var(--pp-border); border-radius: 0 0 var(--pp-radius-control) var(--pp-radius-control); }
.pp-sp-browse-row .pp-i { width: 16px; height: 16px; color: var(--pp-secondary-text); flex: none; }
.pp-sp-browse-row:active, .pp-sp-browse-row.is-focus { background: var(--pp-navy-tint); }
/* Search toggle active state (lock §13): soft-surface tint driven by the
   aria-expanded state pp-overlay.js's callbacks keep in sync — never a filled
   Navy (Cart stays the primary); the control's geometry is untouched. */
.pp-mobile-header [data-pp-search-toggle][aria-expanded="true"] { background: var(--pp-soft-surface); }
@media (min-width: 768px) { .pp-mobile-search-full { display: none; } }

/* True mobile: search clear is a full 44px hit (Hybrid V2 §17 / lock §15). */
@media (max-width: 767px) {
	.pp-search-clear { width: var(--pp-hit-min); height: var(--pp-hit-min); }
	.pp-search { padding-inline-end: 0; }
}

/* ================= Reduced motion (lock §7) ================= */
@media (prefers-reduced-motion: reduce) {
	.pp-search-panel, .pp-msf-dialog { transform: none; }
	.pp-tile:active, .pp-tile.is-pressed, .pp-bh:active, .pp-bh.is-pressed { transform: none; }
	.pp-sp-skel { animation-duration: 2400ms; }
}

/* ============================================================================
   S12 HEADER COMMERCE — content surfaces (design-locks/HEADER-COMMERCE-LOCK.md).
   APPEND-ONLY SECTION: everything above this line — including the Search-owned
   anchored-panel and desktop-panel blocks — keeps its exact bytes and file
   positions. Shell geometry/state classes live in header.css.
   ============================================================================ */

/* ---------------- Campaign rail internals (rail lock) ----------------
   Pinned lead (Lime keyline tag) + ambient service track (~28s linear
   marquee, duplicated sequence aria-hidden, 20px edge fades) + static
   utility. Three locked tag treatments only. Pause: the pointer resting on
   the track or keyboard focus on it, nothing else (HD.1F: header interaction
   never pauses it) — never a :has() dependency. */
.pp-rail { gap: 12px; font-family: var(--pp-font-body); } /* A.2 lab parity: 12px lead→track (lab .cbar--rail) */
/* A.2 lab parity (human Gate B): EVERY rail message is a 24px tag — the
   lab's ONE .ctag grammar (700 10.5px/1, .05em, uppercase, 0 10px, radius 5)
   — in exactly the three locked treatments: the pinned lead = Lime keyline
   (Lime text on a Lime tint with a 45% Lime keyline), every ambient item =
   plain bordered (22% white keyline), and the white chip reserved for a
   content-keyed state. Nothing here re-authors copy. */
.pp-rail-lead,
.pp-rail-item {
	flex: none;
	display: inline-flex;
	align-items: center;
	min-height: 24px;
	padding: 0 10px;
	border: 1px solid rgba(255, 255, 255, .22);
	border-radius: 5px;
	color: rgba(255, 255, 255, .92);
	font: 700 10.5px/1 var(--pp-font-body);
	letter-spacing: .05em;
	text-transform: uppercase;
	white-space: nowrap;
}
.pp-rail-lead { color: var(--pp-lime); border-color: rgba(215, 255, 0, .45); background: rgba(215, 255, 0, .07); }
/* The other two locked tag treatments (state-keyed campaign states). */
.pp-rail-tag--bordered { border-color: rgba(255, 255, 255, .22); color: rgba(255, 255, 255, .92); background: none; }
.pp-rail-tag--chip { background: #fff; border-color: #fff; color: var(--pp-navy); }
.pp-rail-track {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	/* HC.2 initial state: the run starts AFTER the 36px entry-fade zone (the
	   fade covers this padding), so the first ambient tag is intact at rest —
	   initial render, pause and reduced motion — instead of a clipped glyph;
	   in motion the padding is just part of the fade path. Loop maths are
	   untouched (the run itself is unpadded, translateX(−50%) stays seamless). */
	padding-inline-start: 36px;
	/* A.1-7 entry polish (human Gate B): a wider 36px fade at the track's
	   start (beside the pinned lead) so entering/exiting labels read as an
	   intentional fade, never as clipped text caught mid-glyph; exit keeps a
	   tighter 24px. Same mask mechanism, motion model untouched. */
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 36px, #000 calc(100% - 24px), transparent);
	mask-image: linear-gradient(90deg, transparent, #000 36px, #000 calc(100% - 24px), transparent);
}
.pp-rail-track:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
/* HC.8 seamless loop: the run holds --pp-rail-seqs IDENTICAL sequences and
   travels exactly ONE of them (100% / count), so the frame at the end of the
   cycle is pixel-identical to the frame at the start — the seam cannot be
   seen. The count is what matters for emptiness: with N sequences the content
   left of the viewport after one sequence of travel is (N-1) sequences, so the
   rail only stays full while (N-1) x sequence width >= the visible track. Two
   sequences (the committed value, kept here as the no-JS fallback) satisfy
   that only while one sequence is at least as wide as the track — at 1440 the
   sequence was ~824px against a ~1100px track, which is exactly the dead gap
   the human saw. header.js measures the real rendered widths and raises the
   count; it also sets the duration from the travel distance so the perceived
   speed stays ~29px/s whatever the campaign copy or language produces. */
.pp-rail-run { display: flex; width: max-content; animation: pp-rail-marquee var(--pp-rail-duration, 28s) linear infinite; will-change: transform; }
.pp-rail-seq { display: flex; align-items: center; gap: 8px; padding-inline-end: 8px; } /* A.2 lab parity: 8px tag rhythm across the seam (lab .ctag margin 8 + .track-seq padding 8) — the seam gap IS one normal item gap */
@keyframes pp-rail-marquee { from { transform: translateX(0); } to { transform: translateX(calc(-100% / var(--pp-rail-seqs, 2))); } }
/* HD.1F (Human ruling 2026-10-16): the loop keeps moving through every other
   header interaction — Search, menus, Market, Account, Cart, focus on Order
   tracking. It pauses only for the moving track itself: the pointer resting
   on it, or keyboard focus on it (the track carries the full text as its
   name) — the rail's own pause mechanism. */
.pp-rail-track:hover .pp-rail-run,
.pp-rail-track:focus-visible .pp-rail-run { animation-play-state: paused; }
.pp-rail-utility { display: flex; align-items: center; gap: 14px; margin-inline-start: auto; flex: none; }
.pp-rail-link {
	display: inline-flex;
	align-items: center;
	min-height: 30px;
	color: rgba(255, 255, 255, .85);
	font: 600 11.5px/1 var(--pp-font-body);
	letter-spacing: .02em;
	white-space: nowrap;
	transition: color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-rail-link:hover { color: #fff; text-decoration: underline; text-underline-offset: 3px; }
.pp-rail-link:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 2px; }

/* ---------------- Focused single-zone panels (Flavours / Strength) ------
   Same contained shell + .pp-mm-* grammar as the Shop mega; the one zone's
   list flows into columns so 15 families stay a shallow scan, not a tower. */
.pp-mm-zones--focus { grid-template-columns: 1fr; margin-bottom: 0; }
.pp-mm-focus-cols { columns: 3; column-gap: 32px; }
.pp-mm-focus-cols li { break-inside: avoid; }
@media (min-width: 1180px) and (max-width: 1366px) { .pp-mm-focus-cols { columns: 2; } }

/* ---------------- Drawer V2 — three-tier root (drawer lock) ----------------
   Tier separation on the soft surface; PRIMARY DISCOVERY rows are inline
   accordions (hidden + aria-expanded, max one level, subset + directory
   escape); shortcuts/utility are plain rows. Mechanics (grid-rows expander,
   inert, Escape/focus) unchanged in header.js. */
.pp-mdrawer-group--shortcuts, .pp-mdrawer-group--utility { border-top: 6px solid var(--pp-soft-surface); }
.pp-macc-head { justify-content: space-between; }
.pp-macc-head .pp-macc-caret { width: 16px; height: 16px; color: var(--pp-secondary-text); transition: transform var(--pp-motion-micro) var(--pp-ease-out); }
.pp-macc-head[aria-expanded="true"] .pp-macc-caret { transform: rotate(180deg); }
.pp-macc-head[aria-expanded="true"] { background: var(--pp-soft-surface); }
.pp-macc-sub { background: var(--pp-soft-surface); border-bottom: 1px solid var(--pp-border); padding: 6px 0 10px; }
.pp-macc-sub[hidden] { display: none; }
.pp-macc-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	min-height: 44px;
	padding: 0 18px 0 26px;
	font: 500 14px/1.3 var(--pp-font-body);
	color: var(--pp-ink);
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-macc-row:active { background: var(--pp-navy-tint); }
.pp-macc-row .meta { font: 500 12px/1 var(--pp-font-body); color: var(--pp-secondary-text); }
.pp-macc-label { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.pp-macc-row--all { color: var(--pp-navy); font-weight: 600; justify-content: flex-start; gap: 6px; }
.pp-macc-row--all .pp-i { color: currentColor; }
.pp-mrow--shortcut, .pp-mrow--utility { font-weight: 600; }
/* Deals Lime dot in the drawer — A.2 lab parity (Drawer V2 .d5row): label at
   the start, the 7px keylined dot at the row's END on the row's own
   space-between (the pseudo is flex-ordered last; ::after is not used so the
   rule reads like the desktop dot). SF.4 ruling 5: only while a qualifying
   real deal exists (`is-live`). */
.pp-mobile-drawer .pp-nav-item--deals.is-live::before { content: ""; order: 1; width: 7px; height: 7px; border-radius: 50%; background: var(--pp-lime); box-shadow: 0 0 0 1px rgba(20, 47, 81, .4); flex: none; }

/* ------- SB.1C SHIPPING STATUS (design authority: SB1B-FINAL-HUMAN-LOCK) -------
   The SS.2B floating hero shipping panel is RETIRED (lock §8): the EXISTING
   announcement slot carries the shipping status sitewide — the rail lead
   chip (≥1180), the tablet ticker slot + T2 (768–1179), the mobile strip
   slot (≤767) — with P2-B in the Cart Drawer. The rail lead keeps the shared
   .pp-rail-lead/.pp-rail-item tag block above, untouched (24px, radius 5,
   padding 0 10, 1px keyline, 700 10.5px/1, .05em, uppercase, inline-flex
   centred): only its text and its state colours follow the cart. Server
   markup + state: inc/shipping-status.php; live updates: header.js
   initShippingStatus(). Nothing here sets a width, height or padding on an
   existing component. */

/* G1-C: the lead chip as the shipping slot. `position: relative` only
   anchors the cue (no box change). Unlocked = the identical keyline grammar
   in semantic green. */
.pp-rail-lead[data-pp-ship-slot] { position: relative; }
.pp-rail-lead[data-pp-ship-state="unlocked"] { color: var(--pp-green); border-color: rgba(71, 215, 88, .45); background: rgba(71, 215, 88, .07); }
.pp-ship-amt { font-variant-numeric: tabular-nums; }

/* A-LIME bottom-keyline cue: a 1px Lime segment riding ON the chip's existing
   bottom border (bottom:-1px = the border row), inset 5px past the 5px
   corners, exact progress ratio, 0px added height, absolutely positioned so
   it can never move the label; retired at unlocked (header.js removes it). */
.pp-ship-cue { position: absolute; left: 5px; right: 5px; bottom: -1px; height: 1px; pointer-events: none; }
.pp-ship-cue i { position: absolute; inset: 0; background: var(--pp-lime); transform-origin: left center; transform: scaleX(var(--pp-ship-ratio, 0)); transition: transform 260ms var(--pp-ease-out); }
[dir="rtl"] .pp-ship-cue i { transform-origin: right center; }

/* The tablet-ticker / mobile-strip slot: the same message in the idiom's own
   type (uppercase like its neighbours — the strip's own rule since MOB-03),
   semantic green at unlocked; no cue there — those idioms have no chip. */
.pp-ticker-msg[data-pp-ship-slot="ticker"] { text-transform: uppercase; }
.pp-ticker-msg[data-pp-ship-state="unlocked"],
.pp-mticker-item[data-pp-ship-state="unlocked"] { color: var(--pp-green); }
/* The strip markup still carries the near state's compact form ("$5.95 to
   free shipping", inc/shipping-status.php pp_shipping_message_html()). MOB-03:
   it stays hidden — the moving strip never runs out of width, so it shows the
   full sentence at every phone width, like P2-B, the live region and the
   screen-reader list. */
.pp-ship-compact { display: none; }
/* A slot with nothing to announce is hidden — the components' own display
   rules (inline-flex chip and strip message, grid-stacked ticker message)
   must not override [hidden]. */
.pp-rail-lead[hidden], .pp-ticker-msg[hidden], .pp-mticker-item[hidden] { display: none; }

/* T2 — compact tablet shipping persistence (768–1179 only): a 30px fixed
   service strip in the mobile strip's type (600 11.5px, sentence case) on
   the chrome Navy; rendered only while the cart progresses. UI.1 final
   decision F1 (OPTION A): header.js shows it exactly while the S1 tablet
   header is in its compact sticky state — T2 is then that state's top row,
   with the compact header directly below it and the ticker stepped out
   (header.css) — and hides it again at the top, where the normal header and
   its ticker return. Overlay — zero layout cost, no jump. */
.pp-ship-t2 { display: none; }
@media (min-width: 768px) and (max-width: 1179px) {
	.pp-ship-t2 {
		position: fixed;
		top: 0;
		inset-inline: 0;
		z-index: 150;
		display: flex;
		align-items: center;
		justify-content: center;
		height: 30px;
		padding-inline: var(--pp-gutter);
		background: var(--pp-navy-chrome);
		color: #fff;
		font: 600 11.5px/1.3 var(--pp-font-body);
		letter-spacing: 0;
		white-space: nowrap;
		pointer-events: none;
		opacity: 0;
		visibility: hidden;
		transform: translateY(-6px);
		transition: opacity 160ms var(--pp-ease-out), transform 160ms var(--pp-ease-out), visibility 0s linear 160ms;
	}
	.pp-ship-t2.is-live { opacity: 1; visibility: visible; transform: none; transition: opacity 160ms var(--pp-ease-out), transform 160ms var(--pp-ease-out); }
	/* F1: T2 is the compact header's own top row, so it takes the ticker's
	   place in the same frame the header compacts — a fade would leave the top
	   30px see-through above the moved header for ~120ms. Leaving still fades
	   (behind the header). */
	.pp-header-shell.pp-tablet-compact ~ .pp-ship-t2.is-live { transition: none; }
	.admin-bar .pp-ship-t2 { top: var(--pp-admin-bar-h, 0px); } /* WordPress's fixed admin bar (logged-in staff only; header.css) */
}
.pp-ship-t2[data-pp-ship-state="unlocked"] { color: var(--pp-green); }
.pp-ship-t2 .pp-ship-amt { font-weight: 700; }

/* P2-B — the Cart Drawer's free-shipping detail between Subtotal and
   Checkout: 13px/18px message, amount 700 tabular, a 2px × 144px hairline
   (112px at 320), Navy fill, semantic green + success text at unlocked; no
   icon, card or panel. The margins make the locked 44px footprint inside
   the foot's 10px column gap; nothing renders (zero space) without cart
   progress. The fill re-seeds across the foot re-render (cart-drawer.js). */
.pp-ship-p2 { margin: 2px 0 4px; }
.pp-ship-p2-line { margin: 0; font: 400 13px/18px var(--pp-font-body); color: var(--pp-ink); }
.pp-ship-p2 .pp-ship-amt { font-weight: 700; }
.pp-ship-p2-track { position: relative; display: block; width: 144px; height: 2px; margin-top: 8px; border-radius: 1px; background: #ECEDEC; overflow: hidden; }
.pp-ship-p2-track i { position: absolute; inset: 0; border-radius: inherit; background: var(--pp-navy); transform-origin: left center; transform: scaleX(var(--pp-ship-ratio, 0)); transition: transform 260ms var(--pp-ease-out), background-color 260ms var(--pp-ease-out); }
[dir="rtl"] .pp-ship-p2-track i { transform-origin: right center; }
.pp-ship-p2[data-pp-ship-state="unlocked"] .pp-ship-p2-line { color: var(--pp-success-text); font-weight: 500; }
.pp-ship-p2[data-pp-ship-state="unlocked"] .pp-ship-p2-track i { background: var(--pp-green); }
@media (max-width: 359px) {
	.pp-ship-p2-track { width: 112px; }
}

/* ---- unlock celebration (FINAL-CELEBRATION-LOCK: premium confetti) ----
   transform/opacity only · temporary nodes appended by header.js · every
   node removed after play · fully suppressed under prefers-reduced-motion
   (the engine checks too). aria-hidden, non-focusable, no live region.
   SB.1C re-anchor: the sweep runs along the P2-B hairline (its host track
   clips it), and the layer sits ABOVE the fixed header and the open Cart
   Drawer (both inside the header's z-index 200 stacking context), so the
   screen-wide confetti stays visible over them. */
.pp-ship-sweep {
	position: absolute;
	inset: 0 auto 0 0;
	width: 34%;
	border-radius: 999px;
	background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.65) 50%, rgba(255, 255, 255, 0) 100%);
	transform: translateX(-110%);
	animation: pp-ship-sweep 750ms var(--pp-ease-out) forwards;
	pointer-events: none;
}
@keyframes pp-ship-sweep { to { transform: translateX(320%); } }
.pp-cele-layer {
	position: absolute;
	left: 0;
	right: 0;
	top: 0;
	overflow: hidden;
	pointer-events: none;
	z-index: 320;
}
.pp-cele-p {
	position: absolute;
	top: -22px;
	will-change: transform, opacity;
	animation: pp-cele-fall var(--dur, 1400ms) cubic-bezier(0.25, 0.4, 0.6, 1) var(--delay, 0ms) forwards;
	opacity: 0;
}
@keyframes pp-cele-fall {
	0%   { opacity: 0; transform: translate3d(0, 0, 0) rotateZ(0) rotateX(0); }
	8%   { opacity: 1; }
	80%  { opacity: 1; }
	100% { opacity: 0; transform: translate3d(var(--dx, 0px), var(--dist, 320px), 0) rotateZ(var(--rot, 400deg)) rotateX(var(--flip, 300deg)); }
}
@media (prefers-reduced-motion: reduce) {
	.pp-ship-cue i, .pp-ship-p2-track i, .pp-ship-t2, .pp-ship-t2.is-live { transition: none; }
	.pp-ship-sweep, .pp-cele-p { display: none !important; animation: none !important; }
}

/* ---------------- Market selector — rail + strip variants ----------------
   Same native <details> authority and popover grammar as the ticker/drawer
   variants; renders only with ≥2 published routes (today's single-route DEV
   stays honestly silent). Rail variant lives in the rail utility cluster
   (desktop, chrome navy); strip variant is the mobile M3 chip (flag/code —
   never flag-only — a 26px chip centred in the 30px strip; A.2 note: its hit
   box is the chip itself, not 44px). */
.pp-market--rail { flex: none; }
.pp-market--rail .pp-market-summary { min-height: 28px; margin-block: -3px; } /* A.2 lab parity: 28px chip centred in the 38px rail (lab .mkt--flag) */
.pp-market--rail .pp-market-summary:focus-visible { box-shadow: 0 0 0 2px var(--pp-navy-chrome), 0 0 0 4px #fff; }
.pp-market--strip { flex: none; margin-inline-start: 4px; }
/* HC.2 GC-3: the M3 strip chip keeps the lab's 26px 700-weight VISUAL (lab
   .m5mkt) while the interactive element is a 44px target. The summary is the
   44px hit box (margin-block −7px keeps the strip at 30px — the same model as
   the Next/Pause buttons); the visible keyline chip is its ::before, inset 9px
   top/bottom (= 26px), and the focus ring is painted on that chip. */
.pp-market--strip .pp-market-summary { position: relative; min-height: 44px; margin-block: -7px; padding: 0 8px; font-size: 11px; font-weight: 700; border: 0; border-radius: 0; background: none; }
.pp-market--strip .pp-market-summary::before { content: ""; position: absolute; inset: 9px 0; border: 1px solid rgba(255, 255, 255, .28); border-radius: var(--pp-radius-sm); pointer-events: none; transition: border-color var(--pp-motion-micro) var(--pp-ease-out), background-color var(--pp-motion-press-out) var(--pp-ease-out); }
@media (hover: hover) { .pp-market--strip .pp-market-summary:hover::before { border-color: rgba(255, 255, 255, .6); } } /* UI.1 P2: hover-capable input only */
/* UI.1 P2: the press shade lands on the visible 26px chip (the ::before), never
   on the 44px hit box around it; the summary's .985 scale carries the chip. */
.pp-market--strip .pp-market-summary:is(:active, .is-pressed)::before { background-color: rgba(255, 255, 255, .2); transition-duration: var(--pp-motion-press-in); }
.pp-market--strip .pp-market-summary:focus-visible { outline: none; box-shadow: none; }
.pp-market--strip .pp-market-summary:focus-visible::before { box-shadow: 0 0 0 2px var(--pp-navy-chrome), 0 0 0 4px #fff; }
.pp-market--strip .pp-market-list { inset-inline-end: -4px; }

/* ---- HC.7 (human amendment): desktop Market is COMMERCE-ROW-OWNED. The ONE
   selector renders in .pp-row2 between Search and Account as the lab's
   commerce-row chip (.mkt--compact): 40px, 1.5px border-tone keyline, ink
   text 600 12.5px, flag + market code · currency, secondary caret. Full
   desktop tier only — the tablet tier keeps its frozen ticker pill and
   mobile its strip chip — and it never changes the Header's row height
   (40px inside the 46px control line). Popover: the shared .pp-market-list
   grammar, right-aligned under the chip. ---- */
.pp-market--row { display: none; flex: none; }
@media (min-width: 1180px) {
	.pp-market--row { display: block; }
	.pp-market--row .pp-market-summary {
		min-height: 40px;
		gap: 6px;
		padding: 0 10px;
		border: 1.5px solid var(--pp-border);
		border-radius: var(--pp-radius-md);
		color: var(--pp-ink);
		font: 600 12.5px/1 var(--pp-font-body);
		letter-spacing: 0;
	}
	.pp-market--row .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 hover-capable input the chip lifts ~2px as ONE
	   object (flag, codes and caret together) with the subtle Navy separation,
	   on top of its existing keyline hover; the separation steps aside for the
	   focus ring. P2 (§8): pressed = the 12% tint + .985, winning over the lift.
	   Final decision F2: the lift and separation apply only while the selector
	   is CLOSED — an open chip stays still (its [open] caret and popover are the
	   state; the keyline hover is unchanged). The condition sits in :where() so
	   the press rule below still wins. */
	@media (hover: hover) {
		.pp-market--row .pp-market-summary:hover { border-color: var(--pp-border-hover); }
		.pp-market--row:where(:not([open])) .pp-market-summary:hover { transform: translateY(calc(var(--pp-hover-rise) * -1)); transition-duration: var(--pp-motion-micro); }
		.pp-market--row:where(:not([open])) .pp-market-summary:hover:not(:focus-visible) { box-shadow: var(--pp-shadow-hover); }
	}
	.pp-market--row .pp-market-summary:is(:active, .is-pressed) { background-color: var(--pp-navy-tint-strong); transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
	.pp-market--row .pp-market-summary:is(:active, .is-pressed):not(:focus-visible) { box-shadow: none; }
	.pp-market--row .pp-market-summary .pp-i { opacity: 1; color: var(--pp-secondary-text); }
	.pp-market--row .pp-market-summary .pp-market-caret { width: 12px; height: 12px; }
	.pp-market--row .pp-market-summary .pp-flag { box-shadow: inset 0 0 0 1px rgba(11, 29, 56, .14); }
	.pp-market--row .pp-market-sep { color: var(--pp-secondary-text); opacity: 1; }
	/* Label C (lab §12 default): flag + market code · currency; region and
	   language stay in the popover rows. */
	.pp-market--row .pp-market-region,
	.pp-market--row .pp-market-lang,
	.pp-market--row .pp-market-sep:not(.pp-market-sep--cur) { display: none; }
}
/* 1180-class density (lab §14): the currency drops, never the target. */
@media (min-width: 1180px) and (max-width: 1279px) {
	.pp-market--row .pp-market-cur,
	.pp-market--row .pp-market-sep--cur { display: none; }
}

/* ---------------- Reduced motion (header-commerce additions) ---------------- */
@media (prefers-reduced-motion: reduce) {
	.pp-rail-run { animation: none; }
	.pp-macc-head .pp-macc-caret { transition: none; }
}

/* ============================================================================
   GATE A.1 — targeted Human Gate B corrections (appended; Search-owned blocks
   above keep their exact bytes and positions).
   ============================================================================ */

/* ---- A.1-2 tablet drawer contract — RETIRED by HD.1: the mobile and the
   tablet menu are ONE grouped drawer root (header.php); the tablet drill
   screens and their breakpoint gate are gone. ---- */

/* ---- A.1-5 market flag assets (inc/icons.php pp_flag): rect flag with the
   locked subtle keyline; decorative beside the market code. ---- */
.pp-flag { width: 20px; height: 14px; border-radius: 2.5px; flex: none; display: inline-block; box-shadow: inset 0 0 0 1px rgba(11, 29, 56, .14); }
.pp-market--strip .pp-flag { width: 16px; height: 11px; }
.pp-market-summary .pp-flag { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .28); }
.pp-market--drawer .pp-market-summary .pp-flag { box-shadow: inset 0 0 0 1px rgba(11, 29, 56, .14); }
.pp-market-opt .pp-flag { margin-inline-end: 2px; }

/* ---- A.1-1 mobile market at every width (M3 lock: the strip trigger is
   flag + market CODE — never flag-only, never code-less): the closed strip
   trigger drops the language text at ALL mobile widths, so 320 keeps a
   visible, ≥44px, collision-free market control; the popover and the drawer
   variant keep the full identity. ---- */
.pp-market--strip .pp-market-sep,
.pp-market--strip .pp-market-lang,
.pp-market--strip .pp-market-region,
.pp-market--strip .pp-market-cur { display: none; }
.pp-market--strip .pp-market-summary { gap: 5px; }

/* ---- HC.2 market presentation grammar (MARKET-LOCK): desktop rail trigger =
   flag + COUNTRY · LANGUAGE CODE · CURRENCY CODE; the market code shows in
   place of the country only when no country is known, and ≤1366 the region
   drops leaving flag + codes (lock: "region may drop ≤1366"). Popover rows =
   flag + code + country · language + currency. Fields render only when a real
   (or local launch-preview) value exists — see pp_market_presentation(). ---- */
.pp-market--rail.pp-market--has-region .pp-market-code { display: none; }
@media (max-width: 1366px) {
	.pp-market--rail.pp-market--has-region .pp-market-region { display: none; }
	.pp-market--rail.pp-market--has-region .pp-market-code { display: inline; }
}
/* Popover row body = the lab .mrow-body: region over languages, currency at the
   row end; the commerce-shell popovers widen to the lab's ~300px so a full
   country name never wraps (the frozen tablet ticker popover is untouched). */
.pp-market-opt-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.pp-market-opt-region { font: 600 13.5px/1.2 var(--pp-font-body); }
.pp-market-opt-lang { font: 400 11.5px/1.2 var(--pp-font-body); color: var(--pp-secondary-text); }
.pp-market-opt-cur { margin-inline-start: auto; font: 700 11px/1 var(--pp-font-body); letter-spacing: .04em; color: var(--pp-navy); }
.pp-market--rail .pp-market-list, .pp-market--strip .pp-market-list, .pp-market--row .pp-market-list { min-width: 300px; }
.pp-market--rail .pp-market-opt, .pp-market--strip .pp-market-opt, .pp-market--row .pp-market-opt { min-height: 46px; gap: 11px; }
/* Launch-preview layout rows (local/development only): non-interactive, no route. */
.pp-market-opt--preview { cursor: default; }
.pp-market-opt--preview:hover { background: none; }

/* ============================================================================
   HD.1 — content surfaces of the dark header (design-locks/
   HD1-HEADER-FINAL-LOCK.md; lab ~/Documents/PouchPick-Labs/design/
   header-evolution-hd1/final/). Appended; the Search-owned blocks above keep
   their exact bytes and positions. Shell geometry / S2 live in header.css.
   ============================================================================ */

/* ---- "Soon": the marker of a feature that opens its Coming Soon page.
   White on the Navy surfaces (inside the locked Lime budget — D5), Navy on
   white menus. ---- */
.pp-soon {
	display: inline-flex;
	align-items: center;
	flex: none;
	height: 18px;
	padding: 0 6px;
	margin-inline-start: 8px;
	border: 1px solid rgba(20, 47, 81, .4);
	border-radius: 5px;
	background: #fff;
	color: var(--pp-navy);
	font: 700 9.5px/1 var(--pp-font-body);
	letter-spacing: .07em;
	text-transform: uppercase;
	white-space: nowrap;
}
.pp-soon--dark { border-color: rgba(255, 255, 255, .3); background: rgba(255, 255, 255, .04); color: rgba(255, 255, 255, .82); }

/* ---- Services cluster (nav row, right): Knowledge / Help in the secondary
   weight; Subscribe & Save in the spine weight, its underline under the
   label only (the Soon tag sits outside it). ---- */
.pp-services .pp-nav-item--sec { font-weight: 500; color: rgba(255, 255, 255, .66); }
.pp-services .pp-nav-item--feature { font-weight: 600; color: rgba(255, 255, 255, .88); }
.pp-services .pp-nav-item--feature::after { content: none; }
.pp-services .pp-nav-item--feature .pp-lbl { position: relative; }
.pp-services .pp-nav-item--feature .pp-lbl::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	bottom: -9px;
	height: 2px;
	border-radius: 2px;
	background: #fff;
	transform: scaleX(0);
	transition: transform var(--pp-motion-micro) var(--pp-ease-out);
}
@media (hover: hover) { .pp-services .pp-nav-item--feature:hover .pp-lbl::after { transform: scaleX(1); } }
.pp-services .pp-nav-item--feature[aria-current="page"] { color: #fff; }
.pp-services .pp-nav-item--feature[aria-current="page"] .pp-lbl::after { transform: scaleX(1); }
.pp-nav-item[hidden] { display: none; }

/* ---- Menus (Account · Help · More): white popovers under their trigger,
   positioned by header.js; the panels' component motion. ---- */
.pp-hpops { position: absolute; top: 0; left: 0; width: 0; height: 0; z-index: 160; }
.pp-hpop {
	position: absolute;
	top: 0;
	left: 0;
	width: 300px;
	max-width: calc(100vw - 24px);
	padding: 10px;
	background: #fff;
	color: var(--pp-ink);
	border: 1px solid var(--pp-border);
	border-radius: var(--pp-radius-lg);
	box-shadow: var(--pp-shadow-popover);
	font-family: var(--pp-font-body);
	opacity: 0;
	transform: translateY(-4px);
	visibility: hidden;
	transition: opacity var(--pp-motion-micro) var(--pp-ease-in), transform var(--pp-motion-micro) var(--pp-ease-in), visibility 0s linear var(--pp-motion-micro);
}
.pp-hpop.is-open { opacity: 1; transform: none; visibility: visible; transition: opacity 180ms var(--pp-ease-out), transform 180ms var(--pp-ease-out), visibility 0s; }
.pp-hpop--account { width: 310px; }
.pp-hpop--help { width: 340px; }
.pp-hpop-h { margin: 0; padding: 8px; font: 600 11px/1.2 var(--pp-font-body); letter-spacing: .06em; text-transform: uppercase; color: var(--pp-secondary-text); }
.pp-hpop-h--sep { margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--pp-secondary-surface); }
.pp-hpop-h-link { color: inherit; }
@media (hover: hover) { .pp-hpop-h-link:hover { color: var(--pp-navy); text-decoration: underline; text-underline-offset: 3px; } }
.pp-hpop-row {
	display: flex;
	align-items: center;
	gap: 10px;
	min-height: 40px;
	padding: 0 8px;
	border-radius: 8px;
	color: var(--pp-ink);
	font: 500 14.5px/1.2 var(--pp-font-body);
	transition: background-color var(--pp-motion-micro) var(--pp-ease-out);
}
.pp-hpop-row[hidden] { display: none; }
@media (hover: hover) { .pp-hpop-row:hover { background: var(--pp-soft-surface); } }
.pp-hpop-row:active { background: var(--pp-navy-tint); }
.pp-hpop-row .pp-soon { margin-inline-start: auto; }
.pp-hpop-row .pp-fi { width: 16px; height: 16px; color: var(--pp-navy); }
.pp-hpop-row[aria-current="page"] { font-weight: 700; }
.pp-hpop-row--sm { min-height: 34px; font-size: 14px; }
.pp-hpop-list { list-style: none; margin: 0; padding: 0; }
.pp-hpop-cta {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	margin: 2px 2px 6px;
	border-radius: var(--pp-radius-md);
	background: var(--pp-navy);
	color: #fff;
	font: 600 14.5px/1 var(--pp-font-body);
	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-hpop-cta:hover { background: var(--pp-navy-hover); } }
.pp-hpop-cta:active { background: var(--pp-navy-pressed); transform: scale(var(--pp-press-scale)); }
.pp-hpop-cta:focus-visible { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--pp-navy); }

/* ---- Shop mega (HD.1): six zones at the lab's proportions; the feature
   rows; the Subscribe & Save tile. ---- */
@media (min-width: 1180px) {
	.pp-mm-zones--6 { grid-template-columns: 1.05fr 1fr 1.05fr .72fr .95fr 1.2fr; gap: 28px; }
}
.pp-mm-zone a.pp-mm-feature { justify-content: space-between; }
.pp-mm-zone a.pp-mm-feature .pp-soon { margin-inline-start: auto; }
.pp-mm-zone a[aria-current="page"] { font-weight: 700; color: var(--pp-navy); }
.pp-tile--feature { background: var(--pp-navy); color: #fff; border-color: var(--pp-navy); }
.pp-tile--feature:hover { background: var(--pp-navy-hover); border-color: var(--pp-navy-hover); }
.pp-tile--feature .pp-tile-eyebrow { background: rgba(255, 255, 255, .06); color: #fff; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .32); }
.pp-tile--feature .pp-tile-head { color: #fff; }
.pp-tile-glyph { position: absolute; inset-inline-end: 14px; top: 14px; width: 60px; height: 60px; display: inline-flex; align-items: center; justify-content: center; border-radius: 14px; background: rgba(255, 255, 255, .06); color: #fff; }
.pp-tile-glyph .pp-i { width: 30px; height: 30px; stroke-width: 1.5; }
.pp-tile--feature:focus-visible { box-shadow: 0 0 0 2px #fff, 0 0 0 4px var(--pp-navy); }

/* ---- Knowledge panel: sections in two columns + "All of Knowledge"; the
   "Start here" guides as soft cards. ---- */
.pp-mm-zones--knowledge { grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 40px; margin-bottom: 0; }
.pp-mm-focus-cols--2 { columns: 2; column-gap: 24px; }
.pp-mm-zone .pp-mm-seeall--block { display: inline-flex; margin-top: 8px; }
.pp-kguides { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.pp-kguide {
	display: grid;
	align-content: start;
	gap: 8px;
	min-height: 92px;
	padding: 16px;
	border-radius: var(--pp-radius-lg);
	background: var(--pp-soft-surface);
	color: var(--pp-ink);
	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-kguide:hover { background: var(--pp-secondary-surface); } }
.pp-kguide:active, .pp-kguide.is-pressed { transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
.pp-kguide-eb { font: 700 10px/1 var(--pp-font-body); letter-spacing: .06em; text-transform: uppercase; color: var(--pp-secondary-text); }
.pp-kguide-t { font: 600 15px/1.3 var(--pp-font-body); }

/* ---- Desktop Market chip on the Navy bar (HC.7 component; lab .hd-market-btn):
   white-keyline chip, white text; the keyline brightens on hover, white
   when open; no lift on the dark bar. ---- */
@media (min-width: 1180px) {
	.pp-market--row .pp-market-summary { border-color: rgba(255, 255, 255, .24); color: #fff; }
	.pp-market--row .pp-market-summary .pp-i { width: 16px; height: 16px; color: #fff; opacity: .85; }
	.pp-market--row .pp-market-summary .pp-market-caret { width: 20px; height: 20px; opacity: .62; }
	.pp-market--row .pp-market-sep { color: #fff; opacity: .5; }
	.pp-market--row .pp-market-cur { font-weight: 500; }
	.pp-market--row[open] .pp-market-summary { border-color: #fff; }
	@media (hover: hover) {
		.pp-market--row .pp-market-summary:hover { border-color: rgba(255, 255, 255, .5); }
		.pp-market--row:where(:not([open])) .pp-market-summary:hover { transform: none; }
		.pp-market--row:where(:not([open])) .pp-market-summary:hover:not(:focus-visible) { box-shadow: none; }
	}
	.pp-market--row .pp-market-summary:is(:active, .is-pressed) { background-color: rgba(255, 255, 255, .12); }
}

/* ---- The strip Market chip (tablet strip + mobile strip — the same
   component and 44px hit box): the lab's 16px globe and 20px caret. ---- */
.pp-market--strip .pp-market-summary .pp-i { width: 16px; height: 16px; }
.pp-market--strip .pp-market-summary .pp-market-caret { width: 20px; height: 20px; opacity: .62; }

/* ---- Tablet quick-link chips (768–1179): one scrollable row, fading at
   the end edge. ---- */
.pp-tchips-scroll {
	height: 52px;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scrollbar-width: none;
	-webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
	mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
}
.pp-tchips-scroll::-webkit-scrollbar { display: none; }
.pp-tchips-in { display: flex; align-items: center; gap: 8px; height: 100%; width: max-content; padding: 0 24px; }
.pp-tchip {
	position: relative;
	display: inline-flex;
	align-items: center;
	height: 36px;
	padding: 0 15px;
	border: 1px solid rgba(255, 255, 255, .18);
	border-radius: 999px;
	background: rgba(255, 255, 255, .06);
	color: #fff;
	font: 600 14px/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);
}
.pp-tchip::after { content: ""; position: absolute; inset: -4px -2px; } /* ≥44px effective hit inside the 36px chip */
@media (hover: hover) { .pp-tchip:hover { background: rgba(255, 255, 255, .12); } }
.pp-tchip:active, .pp-tchip.is-pressed { background: rgba(255, 255, 255, .12); transform: scale(var(--pp-press-scale)); transition-duration: var(--pp-motion-press-in); }
.pp-tchip .pp-soon { margin-inline-start: 7px; }
.pp-tchip[aria-current="page"] { font-weight: 700; background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .4); }

/* ---- Drawer (mobile + tablet): the HD.1 groups — the announced features
   (Subscribe & Save, then ONE "Coming soon" accordion), Guides & help, Your
   account — on the Drawer V2 row grammar. ---- */
.pp-mdrawer-group--future, .pp-mdrawer-group--guides { border-top: 6px solid var(--pp-soft-surface); }
.pp-mdrawer-th { margin: 0; padding: 18px 18px 6px; font: 600 11px/1.2 var(--pp-font-body); letter-spacing: .07em; text-transform: uppercase; color: var(--pp-secondary-text); }
.pp-mobile-drawer .pp-mrow.pp-mrow--feature { justify-content: flex-start; gap: 12px; }
.pp-mobile-drawer .pp-mrow--feature .pp-fi, .pp-macc-row--feature .pp-fi { width: 20px; height: 20px; color: var(--pp-navy); }
.pp-mrow--feature .pp-soon, .pp-macc-row--feature .pp-soon { margin-inline-start: auto; }
.pp-macc-row.pp-macc-row--feature { justify-content: flex-start; gap: 12px; }
.pp-mobile-drawer [aria-current="page"] { font-weight: 700; }

/* ---- SB.1C T2 on the HD.1 tablet: the strip's own 34px, so T2 takes its
   place in the compact header without moving the bar. ---- */
@media (min-width: 768px) and (max-width: 1179px) {
	.pp-ship-t2 { height: 34px; }
}

/* ---- Mobile Search toggle, active (MOBILE-SEARCH lock §13 soft-surface
   tint): on the navy row the glyph turns Navy so the open state reads. ---- */
.pp-mobile-header [data-pp-search-toggle][aria-expanded="true"] { color: var(--pp-navy); }

@media (prefers-reduced-motion: reduce) {
	.pp-hpop, .pp-hpop.is-open { transform: none; transition-duration: 0ms; }
	.pp-services .pp-nav-item--feature .pp-lbl::after { transition: none; }
	.pp-tchip:active, .pp-tchip.is-pressed, .pp-kguide:active, .pp-kguide.is-pressed, .pp-hpop-cta:active { transform: none; }
}
