/**
 * H4YF Skin — component layer (header, drawer, shop grid, PDP).
 * Loaded AFTER Astra so tokens + layout win by cascade order.
 */

/* ------------------------------------------------------------------ */
/* Kill Astra header leakage (red-bar safety — our markup replaces it) */
/* ------------------------------------------------------------------ */
#masthead,
.ast-mobile-header-wrap,
.ast-primary-header-bar,
.ast-builder-grid-row,
.main-header-bar,
.main-header-menu-toggle,
.ast-menu-toggle,
.ast-header-break-point .main-header-bar-wrap,
.ast-mobile-popup-drawer,
#astra-mobile-cart-drawer,
.astra-mobile-cart-overlay {
	display: none !important;
	visibility: hidden !important;
	height: 0 !important;
	overflow: hidden !important;
}

/* Site-wide charcoal + crimson-gradient wash (Josh punch list 2026-08-05:
   full site wallpaper, not just the homepage — moved here from `.h4yf-home`
   below, which carried it alone before). Same D16 formula, still fixed
   attachment so it reads as one continuous surface behind every template.
   Alphas raised ~2.7x 2026-08-30 (#746): the 0.09-0.12 originals rendered as
   flat near-black live — every product image container already sits on its
   own opaque charcoal card (grid tiles, PDP gallery), so the wash only ever
   touches page chrome/margins and can run stronger without competing with
   photography. Text contrast is unaffected — --h4yf-ink stays near-white
   regardless of how saturated the dark-red wash beneath it gets. */
body.h4yf-skin {
	background:
		radial-gradient(120% 60% at 50% 0%,   rgba(168, 18, 58, 0.25), transparent 52%),
		radial-gradient(100% 55% at 85% 55%,  rgba(168, 18, 58, 0.20), transparent 54%),
		radial-gradient(140% 70% at 50% 115%, rgba(168, 18, 58, 0.27), transparent 52%),
		linear-gradient(180deg, var(--h4yf-charcoal) 0%, var(--h4yf-charcoal-2) 50%, var(--h4yf-charcoal) 100%);
	background-attachment: fixed;
	color: var(--h4yf-ink);
}

/* ------------------------------------------------------------------ */
/* Headings on charcoal (Sprint 6.6 RC1)                              */
/* ------------------------------------------------------------------ */
/* Astra's global palette sets h1-h6 to --ast-global-color-2 (#1E293B,
   a light-background value) at specificity (0,0,1). On charcoal that is
   1.16:1 — invisible. Its inline customizer CSS prints after our
   stylesheet, so an equal-specificity rule loses on source order:
   :root lifts us to (0,1,0) and wins without !important. Kept first in
   this file so component rules (also (0,1,0)) still win their ties.
   Written out longhand on purpose — LiteSpeed's UCSS pass drops every
   rule whose selector uses :is()/:where(), so the grouped form silently
   never reaches the browser on this site. */
:root h1,
:root h2,
:root h3,
:root h4,
:root h5,
:root h6 {
	color: var(--h4yf-ink);
}

/* ------------------------------------------------------------------ */
/* Sticky header                                                      */
/* ------------------------------------------------------------------ */
.h4yf-header {
	position: sticky;
	top: 0;
	z-index: var(--h4yf-z-sticky);
	background: var(--h4yf-charcoal);
	border-bottom: 1px solid var(--h4yf-charcoal-2);
}

.h4yf-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	max-width: 1280px;
	margin: 0 auto;
	padding: 12px 16px;
	min-height: 56px;
}

.h4yf-logo {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-decoration: none;
	line-height: 0;
	/* Mobile audit 2026-07-31: measured 40x40, under the 44px floor. */
	min-width: var(--h4yf-tap-floor, 44px);
	min-height: var(--h4yf-tap-floor, 44px);
}

.h4yf-logo img {
	display: block;
	height: 40px;
	width: auto;
	max-width: 160px;
	object-fit: contain;
}

.h4yf-logo--text {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: 18px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	line-height: 1;
}

.h4yf-header__nav {
	flex: 1;
	display: none;
	justify-content: center;
}

@media (min-width: 921px) {
	.h4yf-header__nav {
		display: flex;
	}

	/* `!important`, not a descendant scope — and that is deliberate.
	   Bare `.h4yf-nav-toggle` is (0,1,0) and ties `.h4yf-icon-btn
	   { display: inline-flex }` at line ~163; a media query adds no
	   specificity, so the tie went to source order and the LATER rule won —
	   the hamburger rendered 48x48 beside the full inline nav at every
	   desktop width (6.6 punch-list P2-11).
	   The obvious fix, `.h4yf-header .h4yf-nav-toggle` at (0,2,0), SHIPPED
	   AND FAILED on 0.9.37: **LiteSpeed UCSS rewrites selectors and dropped
	   the `.h4yf-header ` ancestor**, collapsing it straight back to (0,1,0)
	   and re-creating the tie. Verified in the served bundle — the hide sat
	   at char 20,412 and `.h4yf-icon-btn` at 21,043, so order decided it
	   again. `!important` is the only form here that survives a selector
	   rewrite, because it does not depend on the selector at all. */
	.h4yf-nav-toggle {
		display: none !important;
	}
}

.h4yf-nav,
.h4yf-drawer-nav {
	list-style: none;
	margin: 0;
	padding: 0;
}

.h4yf-nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 4px 20px;
}

.h4yf-nav a,
.h4yf-drawer-nav a {
	color: var(--h4yf-ink);
	text-decoration: none;
	font-family: var(--h4yf-body);
	font-weight: 700;
	/* 15px = the legacy canon nav floor (h4yf_custom_css 2026-06-30
	   "PRIMARY NAV 5-PILLAR LEGIBILITY FIX") — was 13px, below floor.
	   Ported sprint 7.2-r2. */
	font-size: 15px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	transition: opacity 0.2s ease, color 0.2s ease;
}

.h4yf-nav a:hover,
.h4yf-nav a:focus-visible,
.h4yf-drawer-nav a:hover,
.h4yf-drawer-nav a:focus-visible {
	color: var(--h4yf-hover);
	opacity: 1;
}

/* ---------------------- desktop dropdowns (#369) ----------------------
   Astra injects an arrow span into EVERY item, childless or not, and its own
   dropdown CSS/JS keys off `.main-header-menu` — which this markup is not. The
   skin owns the submenu outright.
   `!important` on both states, not a cleverer selector: UCSS rewrites
   selectors on this site (see the .h4yf-nav-toggle note above), and a media
   query adds no specificity. The open rule still carries a full class more
   than the closed rule, so it survives a dropped ancestor. */
.h4yf-nav > li {
	position: relative;
}

/* Astra stamps an `.ast-icon.icon-arrow` chevron into EVERY `.menu-link`,
   including leaf items with no children, plus a `.dropdown-menu-toggle` span on
   each parent. The desktop bar has hidden them since Sprint 1.2 — the DRAWER
   never was, so 34 chevrons rendered down the mobile menu (measured on slate
   2026-08-04). They were noise in every case: the drawer does not accordion,
   `.h4yf-drawer-nav .sub-menu` is an always-expanded indented list, so nothing
   was ever behind a toggle. Josh 2026-08-04: "Remove carrots from mobile
   hamburger menu". `.ast-menu-toggle` is already killed globally at the top of
   this file. */
.h4yf-nav .ast-icon,
.h4yf-nav .dropdown-menu-toggle,
.h4yf-drawer-nav .ast-icon,
.h4yf-drawer-nav .dropdown-menu-toggle {
	display: none !important;
}

.h4yf-nav > li > a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: var(--h4yf-tap-floor, 44px);
}

.h4yf-nav .menu-item-has-children > a::after {
	content: '';
	width: 6px;
	height: 6px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateY(-2px) rotate(45deg);
}

.h4yf-nav .sub-menu {
	display: none !important;
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 1;
	min-width: 220px;
	margin: 0;
	padding: 6px 0;
	list-style: none;
	background: var(--h4yf-charcoal);
	border: 1px solid var(--h4yf-charcoal-2);
	box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}

.h4yf-nav .menu-item-has-children:hover > .sub-menu,
.h4yf-nav .menu-item-has-children:focus-within > .sub-menu {
	display: block !important;
}

/* Escape has to beat :hover, which CSS alone cannot undo while the pointer is
   still over the item. skin.js sets this class and clears it on the next
   pointerenter/focusin. Same specificity as the open rule, so it must stay
   AFTER it. */
.h4yf-nav.is-suppressed .menu-item-has-children > .sub-menu {
	display: none !important;
}

.h4yf-nav .sub-menu a {
	display: flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	padding: 8px 16px;
	font-size: 14.5px;
	font-weight: 500;
	letter-spacing: 0.04em;
	white-space: nowrap;
}

.h4yf-header__actions {
	display: flex;
	align-items: center;
	gap: 4px;
}

.h4yf-icon-btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	border-radius: 6px;
	background: transparent;
	color: var(--h4yf-ink);
	cursor: pointer;
	transition: background 0.2s ease;
}

.h4yf-icon-btn:hover,
.h4yf-icon-btn:focus-visible {
	background: var(--h4yf-charcoal-2);
}

/* `outline: none` used to sit in the rule above, i.e. on `:focus-visible` too —
   it stripped the keyboard ring off every icon button and only looked fine
   because premier.css re-added an outline further down the cascade. That
   premier block is gone (2026-08-02), so the suppression goes with it: the
   background fill is the HOVER feedback, and the sitewide focus blanket
   supplies the #EE6730 ring + glow for keyboard users. */
.h4yf-icon-btn:hover {
	outline: none;
}

/* Chromium collapses an inline <svg> flex child to 0 width when it's only
   sized via width/height attributes (no CSS width) — explicit CSS is required. */
.h4yf-icon-btn svg {
	width: 22px;
	height: 22px;
	flex-shrink: 0;
}

.h4yf-cart-count {
	position: absolute;
	top: 6px;
	right: 4px;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: 999px;
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 10px;
	line-height: 18px;
	text-align: center;
}

.h4yf-cart-count:empty,
.h4yf-cart-count[data-count="0"] {
	display: none;
}

/* ------------------------------------------------------------------ */
/* Off-canvas drawers — rebuilt 2026-07-31 (Josh: elevated aesthetic +  */
/* quantified thumb-zone canon + custom lazy cart, no wc-cart-fragments)*/
/*                                                                     */
/* THUMB ZONE (canon: docs/brand/H4YF_THUMB_ZONE.md). Reference device  */
/* 390x844. Measured from the BOTTOM edge:                             */
/*   natural 0-280px | stretch 280-560px | hard 560-844px              */
/* Everything a user taps repeatedly lives in the bottom third. That is */
/* why the nav list is bottom-weighted (margin-top:auto) and the CTAs   */
/* sit in a footer above the home indicator, not at the top of the      */
/* panel where a right-thumb reach has to cross the whole screen.       */
/* ------------------------------------------------------------------ */

/* Semantic z-index scale. Replaces the old 9998/9999 pair — arbitrary
   four-digit values are how stacking wars start. Anything overlaying the
   page picks a rung here rather than inventing a bigger number. */
:root {
	--h4yf-z-sticky: 500;

	/* Product image plate — ONE aspect for every product photo on the site.

	   Every catalogue photo comes out of sneaker-suite's `square()` on a SQUARE
	   transparent canvas with the shoe centered. A sneaker is a wide, short
	   subject, so live-measured across a 61-image sample the shoe fills ~85% of
	   that canvas horizontally but only ~40-55% of it vertically. Rendered in a
	   1:1 tile, that dead space is half the tile and the product reads tiny
	   (Josh 2026-08-29: "essentially shrank to where the shoe image was
	   rendered drastically smaller, unreadable").

	   4:3 + `cover` crops the middle 75% of the source's HEIGHT, which is
	   transparent padding on every pipeline image — the tallest content in that
	   sample was 57.2% of canvas height (spanning 21.4%-78.6%), so the crop has
	   ~4.7% clearance and never reaches the shoe. Net: the shoe renders ~1.35x
	   larger in the same tile footprint.

	   This REPLACES the 4:5 plate the drops/radar/heat/grail cards carried. 4:5
	   is TALLER than the square source, so `cover` there cropped ~20% off the
	   WIDTH — straight through the toe and heel of a shoe occupying 85% of it.
	   That is the zoomed-in/cut-off rendering Josh flagged on /drops/.

	   The PDP hero is deliberately NOT on this plate: a detail page must never
	   crop the product. See the `contain` block on the gallery below. */
	--h4yf-plate: 4 / 3;
	--h4yf-z-bottombar: 600;
	--h4yf-z-overlay: 700;
	--h4yf-z-drawer: 710;
	--h4yf-z-toast: 800;
	--h4yf-z-sheet: 810;

	/* Ease-out only — nothing on this surface eases IN. A panel that
	   accelerates away from the finger reads as lag. */
	--h4yf-ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
	--h4yf-drawer-dur: 380ms;

	/* Tap-target floor (WCAG 2.5.5 AAA / Apple HIG 44pt) and the
	   comfortable target (Material 48dp). Never ship below the floor. */
	--h4yf-tap-floor: 44px;
	--h4yf-tap: 48px;

	/* Basketball orange — the focus / selection / highlight signal
	   (Josh 2026-08-01).
	   [AMENDED 2026-08-04, Josh: "I mean sitewide; crimson is the brand color to
	   use." `--h4yf-orange` (#D4571A, the hover carve-out) is RETIRED and all 20
	   of its declarations are now crimson. This token is the ONE orange left,
	   and it is deliberately NOT swapped: it is not a brand colour, it is a WCAG
	   1.4.11 non-text indicator, and it is the only thing telling a keyboard
	   user where they are. Crimson measures 2.88:1 on the charcoal floor —
	   BELOW the 3:1 that a focus indicator has to clear — so swapping it would
	   trade a visible focus ring for an invisible one and turn
	   `scripts/a11y/a11y_check.py` red on two committed pairs. Flagged to Josh
	   2026-08-04; swap it only if he confirms after seeing that number.]
	   Crimson stays the brand accent and CTA fill.
	   Brighter than #D4571A on purpose — a focus ring has to read instantly
	   against charcoal, and it measures 4.94:1 on the #232326 floor and 4.39:1
	   on the #2C2C2E card (re-derived 2026-08-02 when the floor lifted from
	   #1C1C1E, where it had been 5.36:1 — still far past the 3:1 floor) (WCAG 1.4.11 needs 3:1 for a non-text indicator; all
	   three pairs, selection included, are checked by a11y_check.py). Never use it as a fill or a text colour;
	   it means "this is the thing you're on", nothing else. */
	--h4yf-bball: #ee6730;
	--h4yf-bball-glow: rgba(238, 103, 48, 0.42);
	--h4yf-bball-halo: rgba(238, 103, 48, 0.22);
}

/* Text selection carries the same signal. */
body.h4yf-skin ::selection {
	background: var(--h4yf-bball);
	color: #1c1c1e;
}

.h4yf-drawer-overlay {
	position: fixed;
	inset: 0;
	z-index: var(--h4yf-z-overlay);
	background: rgba(10, 10, 11, 0.62);
	opacity: 0;
	transition: opacity var(--h4yf-drawer-dur) var(--h4yf-ease-out-expo);
	/* Blur is earned here: it separates an overlaid surface from the page
	   beneath it. Not decorative glass — the drawer is the one truly
	   overlaid surface in the system (DESIGN.md elevation rule). */
	backdrop-filter: blur(2px);
	-webkit-backdrop-filter: blur(2px);
}

.h4yf-drawer-overlay.is-open {
	opacity: 1;
}

.h4yf-drawer {
	position: fixed;
	top: 0;
	right: 0;
	z-index: var(--h4yf-z-drawer);
	display: flex;
	flex-direction: column;
	width: min(92vw, 400px);
	max-width: 100%;
	/* top/bottom inset rather than `height: 100dvh` — measured 2026-07-31, dvh
	   resolved to 1087px against an 844px visible viewport, which pushes
	   bottom-anchored content below the fold. Insets are always exactly the
	   visual viewport. */
	bottom: 0;
	background: var(--h4yf-charcoal);
	border-left: 1px solid var(--h4yf-border);
	transform: translateX(100%);
	transition: transform var(--h4yf-drawer-dur) var(--h4yf-ease-out-expo);
	/* The system's only real shadow (DESIGN.md): two layers, tight contact
	   + wide ambient, so the panel reads as lifted rather than outlined. */
	box-shadow: -1px 0 0 rgba(255, 255, 255, 0.04), -24px 0 60px rgba(0, 0, 0, 0.55);
	will-change: transform;
}

.h4yf-drawer.is-open {
	transform: translateX(0);
}

/* A closed drawer parks at translateX(100%) — flush with the right edge — so
   its 60px ambient shadow painted a dark band down the right side of every
   page at every width (2026-09-30 audit). The shadow belongs to the open
   state only. `:not(.is-open)` rather than a rule on `.is-open`, because the
   :not() form matches at UCSS crawl time and survives the shredder (see
   paintOpen() in assets/skin.js). */
.h4yf-drawer:not(.is-open) {
	box-shadow: none;
}

/* Head sits in the HARD zone by construction (top of a 844px panel), so it
   carries identity and the close affordance — never a primary action. */
.h4yf-drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: max(18px, env(safe-area-inset-top)) 18px 14px;
	border-bottom: 1px solid var(--h4yf-charcoal-2);
}

.h4yf-drawer__title {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: 22px;
	line-height: 1;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.h4yf-drawer__body {
	flex: 1;
	display: flex;
	flex-direction: column;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 18px;
	-webkit-overflow-scrolling: touch;
}

/* THUMB ZONE, load-bearing: push a SHORT nav list to the bottom of the panel so
   the items land in the natural arc.
   `margin-top: auto` on the LIST — never `justify-content: flex-end` on the
   scroll container. Measured 2026-07-31 on the live menu (5 top-level + 19
   sub-items = 1139px of list in a 767px box): flex-end put the list 390px ABOVE
   the scroll box, `scrollHeight` didn't count it, and the top items were
   permanently unreachable — you cannot scroll to content that overflows the
   START of a flex container. `margin-top: auto` collapses to 0 once the content
   is taller than the box, so a long menu scrolls normally. */
.h4yf-drawer__body--nav > .h4yf-drawer-nav,
.h4yf-drawer__body--nav > div > .h4yf-drawer-nav {
	margin-top: auto;
}

.h4yf-drawer-nav {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.h4yf-drawer-nav a {
	display: flex;
	align-items: center;
	min-height: var(--h4yf-tap);
	padding: 12px 2px;
	font-family: var(--h4yf-body);
	font-size: 16px;
	font-weight: 600;
	letter-spacing: 0.01em;
	border-bottom: 1px solid var(--h4yf-charcoal-2);
	position: relative;
	transition: color 160ms var(--h4yf-ease-out-expo),
		padding-left 220ms var(--h4yf-ease-out-expo);
}

/* Crimson as a scalpel: a 2px rule that grows from the leading edge on
   hover/focus. Not a fill, not a side-stripe at rest — it only exists
   while the item is engaged. */
.h4yf-drawer-nav a::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 0;
	height: 2px;
	background: var(--h4yf-crimson);
	transform: translateY(-50%);
	transition: width 220ms var(--h4yf-ease-out-expo);
}

.h4yf-drawer-nav a:hover,
.h4yf-drawer-nav a:focus-visible {
	color: var(--h4yf-ink);
	padding-left: 18px;
}

.h4yf-drawer-nav a:hover::before,
.h4yf-drawer-nav a:focus-visible::before {
	width: 12px;
}

/* Top-level only (`>` on the outer list) — Bug found 2026-08-09 live on
   /shop/: "Shop Sneakers" and its child "Heat (All)" both link to /shop/,
   so WordPress's own current-menu-item detection (URL match, not depth)
   marks BOTH current, and this rule used to fire on `.current-menu-item`
   at any depth — the dash rendered on the top-level title AND bled onto
   the sub-item directly beneath it, colliding with its label. Menu titles
   get the indicator; sub-items never do, regardless of how many share a
   URL with their parent. */
.h4yf-drawer-nav > .current-menu-item > a {
	color: var(--h4yf-ink);
	padding-left: 18px;
}

.h4yf-drawer-nav > .current-menu-item > a::before {
	width: 12px;
}

.h4yf-drawer-nav .sub-menu {
	list-style: none;
	margin: 0;
	padding: 0 0 0 14px;
}

/* Sub-links: >=46px tap height per legacy canon (h4yf_custom_css
   2026-06-30 "MOBILE NAV LEGIBILITY + TAP TARGETS spec 1.2/1.3") — was
   13px/41px, below floor. Ported sprint 7.2-r2, kept above the 44px floor. */
.h4yf-drawer-nav .sub-menu a {
	display: flex;
	align-items: center;
	min-height: 46px;
	font-size: 14.5px;
	font-weight: 500;
	color: var(--h4yf-body-color, var(--h4yf-ink));
	opacity: 0.82;
	border-bottom: 0;
	padding: 8px 2px;
}

/* Staggered entrance — one list, items arriving in sequence. Legitimate
   stagger (a single list), not a uniform reflex applied to every section.
   Default state is VISIBLE: the transform only applies while the drawer is
   closed, so a headless render or a paused tab can never ship it blank. */
.h4yf-drawer:not(.is-open) .h4yf-drawer-nav > li {
	opacity: 0;
	transform: translateX(12px);
}

.h4yf-drawer-nav > li {
	opacity: 1;
	transform: none;
	transition: opacity 260ms var(--h4yf-ease-out-expo) var(--h4yf-stagger, 0ms),
		transform 260ms var(--h4yf-ease-out-expo) var(--h4yf-stagger, 0ms);
}

/* --------------------------- cart drawer --------------------------- */
.h4yf-cart-lines {
	list-style: none;
	margin: 0;
	padding: 0;
}

.h4yf-cart-line {
	display: grid;
	grid-template-columns: 56px 1fr auto;
	align-items: center;
	gap: 12px;
	padding: 14px 0;
	border-bottom: 1px solid var(--h4yf-charcoal-2);
}

.h4yf-cart-line img {
	width: 56px;
	height: 56px;
	object-fit: cover;
	border-radius: 4px;
	background: var(--h4yf-charcoal-2);
}

.h4yf-cart-line__name {
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--h4yf-ink);
}

.h4yf-cart-line__meta {
	font-size: 12.5px;
	color: var(--h4yf-gray);
	margin-top: 2px;
}

/* Quiet at rest, crimson when engaged — the same treatment the cart page's
   remove control gets, so the two surfaces read as one action. Muted, not ink:
   nothing in a cart should compete with Checkout, and a destructive control
   least of all. Inline-flex with the 44px floor because this is a real tap
   target on the surface most of the traffic uses. */
.h4yf-cart-line__remove {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	margin-top: 2px;
	padding: 0;
	background: none;
	border: 0;
	color: var(--h4yf-muted);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 11.5px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
	transition: color 160ms var(--h4yf-ease-out-expo);
}

.h4yf-cart-line__remove:hover,
.h4yf-cart-line__remove:focus-visible {
	color: var(--h4yf-hover);
}

.h4yf-cart-line__remove[disabled] {
	opacity: 0.55;
	cursor: default;
	text-decoration: none;
}

.h4yf-cart-line__price {
	font-family: var(--h4yf-display);
	font-size: 17px;
	letter-spacing: 0.04em;
	color: var(--h4yf-ink);
	white-space: nowrap;
	align-self: start;
}

/* Empty + loading states are real states, not afterthoughts. */
.h4yf-cart-state {
	margin: auto 0;
	text-align: center;
	padding: 32px 8px;
	color: var(--h4yf-gray);
	font-size: 14px;
}

.h4yf-cart-state__title {
	font-family: var(--h4yf-display);
	font-size: 20px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	margin-bottom: 6px;
}

.h4yf-cart-skeleton {
	height: 56px;
	border-radius: 4px;
	background: linear-gradient(90deg, var(--h4yf-charcoal-2) 25%, #34343a 50%, var(--h4yf-charcoal-2) 75%);
	background-size: 200% 100%;
	animation: h4yf-shimmer 1.4s ease-in-out infinite;
	margin-bottom: 10px;
}

@keyframes h4yf-shimmer {
	to { background-position: -200% 0; }
}

.h4yf-cart-subtotal {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 14px 0 2px;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
}

.h4yf-cart-subtotal strong {
	font-family: var(--h4yf-display);
	font-size: 22px;
	letter-spacing: 0.04em;
	color: var(--h4yf-ink);
}

/* THUMB ZONE: the foot is the natural-arc band. Primary action (Checkout)
   goes on the RIGHT because ~90% of one-handed use is right-thumb, and the
   safe-area pad keeps it clear of the home indicator. */
.h4yf-drawer__foot {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 10px;
	padding: 16px 18px calc(16px + env(safe-area-inset-bottom));
	border-top: 1px solid var(--h4yf-charcoal-2);
	background: var(--h4yf-charcoal);
}

.h4yf-drawer__foot .h4yf-btn {
	min-height: var(--h4yf-tap);
}

/* Reduced motion: the panel still needs to arrive, but it crossfades in
   place instead of sliding, and the stagger is dropped entirely. */
@media (prefers-reduced-motion: reduce) {
	.h4yf-drawer {
		transition: opacity 120ms linear;
		transform: none;
		opacity: 0;
		pointer-events: none;
	}

	.h4yf-drawer.is-open {
		opacity: 1;
		pointer-events: auto;
	}

	.h4yf-drawer:not(.is-open) .h4yf-drawer-nav > li,
	.h4yf-drawer-nav > li {
		opacity: 1;
		transform: none;
		transition: none;
	}

	.h4yf-drawer-nav a,
	.h4yf-drawer-nav a::before {
		transition: none;
	}

	.h4yf-cart-skeleton {
		animation: none;
	}
}

.h4yf-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 0 16px;
	border-radius: 6px;
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
	text-decoration: none;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	text-align: center;
	border: 0;
	cursor: pointer;
	transition: opacity 0.2s ease, color 160ms var(--h4yf-ease-out-expo, ease-out),
		box-shadow 160ms var(--h4yf-ease-out-expo, ease-out);
}

/* HOVER TEXT GOES ORANGE, and the button picks up the same glow focus already
   uses (Josh 2026-08-20: "all hover/focus color is the basketball orange glow,
   including text on buttons when hovering").

   The old rule was `opacity: 0.9` and nothing else, which on a crimson fill is
   a change you have to look for — the button got very slightly darker and the
   ink label did not move at all. On the ghost variant it did even less, because
   fading a transparent background is fading nothing.

   Orange-on-crimson measures 3.3:1, which clears the 3:1 large-text floor the
   CTA type sits above (Bebas at `--h4yf-fs-cta`, 16px+ and heavy). The glow is
   what carries the state at a glance; the colour shift is what confirms it once
   you look. Both are the same pair of tokens the focus ring uses, so pointing at
   a button and tabbing to it now say the same thing in the same language. */
.h4yf-btn:hover {
	opacity: 1;
	color: var(--h4yf-hover);
	box-shadow: 0 0 0 3px var(--h4yf-bball-halo), 0 0 16px 1px var(--h4yf-bball-glow);
}

/* A glow is an appearance change, not motion, but it still must not animate for
   anyone who asked for less — same treatment the focus ring already gets. */
@media (prefers-reduced-motion: reduce) {
	.h4yf-btn,
	.h4yf-btn:hover {
		transition: none;
	}
}

/* [FIXED 2026-08-04, impeccable polish pass] The border was
   `--h4yf-charcoal-2` (#2C2C2E) — nine steps off the `--h4yf-charcoal`
   (#232326) page it sits on, i.e. an outline you effectively cannot see. Live
   at 390px the hero's secondary CTA ("Watch the Channel — 194 Videos") read as
   loose floating text rather than a button; the token block's own comment says
   `--h4yf-border` (#3A3A3C) exists because it "reads on BOTH charcoal and
   charcoal-2 surfaces", which is exactly this case. */
.h4yf-btn--ghost {
	background: transparent;
	border: 1px solid var(--h4yf-border);
}

/* AFTER the base rule on purpose: `.h4yf-btn--ghost` sets the `border`
   SHORTHAND, which resets border-color. Declared above it, this rule loses to a
   later shorthand at equal specificity and the ghost button's only hover change
   would be its label. */
.h4yf-btn--ghost:hover,
.h4yf-btn--ghost:focus-visible {
	border-color: var(--h4yf-hover);
}

/* YouTube-branded ghost buttons (Josh punch list: match the real YouTube
   icon/color) — red border instead of the generic --h4yf-border gray, paired
   with h4yf_youtube_glyph_brand()'s hardcoded red/white icon in front-page.php. */
.h4yf-btn--yt.h4yf-btn--ghost {
	border-color: #FF0000;
}

/* Shop-loop pagination fallback (sprint 6.6-fix P1-5) — canon CTA,
   not the WooCommerce/Astra default blue button. */
.h4yf-load-more {
	display: block;
	margin: 16px auto;
	padding: 0 16px;
	min-height: 48px;
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
	border: 0;
	border-radius: 6px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
	transition: opacity 0.2s ease;
}

.h4yf-load-more:hover {
	opacity: 0.9;
}

body.h4yf-drawer-open {
	overflow: hidden;
}

/* ------------------------------------------------------------------ */
/* Shop archive — edge-to-edge 2-col mobile grid                      */
/* ------------------------------------------------------------------ */
@media (max-width: 768px) {
	.post-type-archive-product .site-content > .ast-container,
	.tax-product_cat .site-content > .ast-container,
	.tax-product_tag .site-content > .ast-container {
		padding-left: 0 !important;
		padding-right: 0 !important;
		max-width: 100% !important;
	}

	.woocommerce ul.products {
		display: flex !important;
		flex-wrap: wrap !important;
		margin: 0 !important;
		padding: 0 !important;
		gap: 2px !important;
	}

	/* De-framed cards: transparent surface + crimson hairline only —
	   continuous charcoal scroll, no boxed frames. Ported from
	   h4yf_custom_css 2026-06-30 de-frame block ("PREMIER MOBILE STORE"),
	   sprint 7.2-r2. */
	.woocommerce ul.products li.product {
		width: calc(50% - 1px) !important;
		margin: 0 !important;
		padding: 0 0 14px !important;
		background: transparent !important;
		border: none !important;
		border-bottom: 2px solid rgba(196, 30, 30, 0.16) !important;
		border-radius: 0 !important;
	}

	/* [REVERSED 2026-08-20, Josh: "ensure the crimson 'add to cart' button needs
	   to be uniform across site inventory."] This block used to read "Grid
	   add-to-cart hidden — drive to PDP (Bill)" and hid the button below 768px,
	   which removed the primary buying action from the surface carrying ~85% of
	   the traffic. Bill's original call is preserved here rather than deleted,
	   because it was a deliberate decision and this is a deliberate reversal of
	   it, not a bug fix.

	   `.added_to_cart` (the "View cart →" link WooCommerce appends after an AJAX
	   add) stays hidden: the header badge and the cart drawer already report the
	   add, and a third confirmation inside a 2-up mobile grid pushes the next
	   card off the fold. */
	.woocommerce ul.products li.product .added_to_cart {
		display: none !important;
	}
}

/* ---- The shop-loop CTA (2026-08-20) --------------------------------------
   ONE button, one look, both stages, every viewport — Josh: "ensure the crimson
   'add to cart' button needs to be uniform across site inventory."

   `inc/inventory-lifecycle.php` renders it and decides which it is: Add to Cart
   on a live pair, Request This Pair on an upcoming or placed one. Both carry
   `.h4yf-btn`, so they inherit the site's button — including the new orange
   hover glow — instead of being a fourth thing that looks nearly like a button.

   The old rule sized Astra's `.ast-on-card-button` and applied on desktop only,
   because the button was hidden on mobile. Both of those are gone. Astra's
   selectors are kept in the list: its markup still renders on any loop this
   theme has not taken over (a shortcode grid, a block), and the point of this
   pass is that they all look the same. */
.woocommerce ul.products li.product .h4yf-loop-cta,
.woocommerce ul.products li.product .ast-on-card-button,
.woocommerce ul.products li.product a[class*="add_to_cart_button"] {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: var(--h4yf-tap-floor, 44px);
	margin-top: 10px;
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
	border: 0;
	border-radius: 6px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
	text-decoration: none;
}

/* Request This Pair is the same button, not a lesser one. A placed pair is
   still the strongest lead on the page — somebody wanted exactly that shoe —
   so demoting its CTA to a ghost would be optimising the wrong way. */
.woocommerce ul.products li.product .h4yf-loop-cta--request {
	background: var(--h4yf-crimson);
}

/* The 2-up mobile grid is edge-to-edge with a 2px gutter, so the button needs
   the card's own inset rather than the full cell width. */
@media (max-width: 768px) {
	.woocommerce ul.products li.product .h4yf-loop-cta {
		width: calc(100% - 16px);
		margin-inline: 8px;
		font-size: 13px;
		letter-spacing: 0.04em;
	}
}

.woocommerce ul.products li.product .price,
.woocommerce ul.products li.product .price span {
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.woocommerce ul.products li.product .woocommerce-loop-product__title {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	/* [RAISED 2026-08-02, Josh directive: the title should read as the card's
	   HEADER.] Was a flat 15px — a legibility floor ported from
	   h4yf_custom_css 2026-06-30, which is a floor, not a design decision, and
	   it left the strongest thing on the card (the shoe's name) smaller than
	   the price beneath it. Bebas is condensed, so 20px here occupies roughly
	   the width of 15px in a normal-width sans: the card gains hierarchy
	   without gaining rows.

	   Still px, not rem — Astra shrinks the mobile root (see style.css), and a
	   card title is exactly the kind of thing that must not silently shrink
	   8.8% on phones. The vw term is safe; it never depended on the root. */
	font-size: clamp(18px, 0.5vw + 16px, 21px);
	letter-spacing: 0.035em;
	text-transform: uppercase;
}

/* Infinite scroll sentinel — pagination stays in DOM for crawlers */
.h4yf-infinite-sentinel {
	height: 1px;
	width: 100%;
	pointer-events: none;
}

.woocommerce-pagination.h4yf-infinite-active {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.h4yf-infinite-status {
	text-align: center;
	padding: 20px 16px;
	color: #9a9a9a;
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-size: 13px;
}

/* ------------------------------------------------------------------ */
/* PDP — dark summary, white price, crimson CTAs only                 */
/* ------------------------------------------------------------------ */
/* [FIXED 2026-07-23, Sprint 6.3: same wrong `.woocommerce`-ancestor
   assumption as the ATC button below — these 2 rules never matched live
   either. Price rendered dark-slate-on-charcoal (rgb(51,65,85), ~22px)
   instead of white/28px; summary panel never got its charcoal-2 background.
   Live-confirmed via getComputedStyle before AND after this fix.] */
.single-product .summary.entry-summary {
	background: var(--h4yf-charcoal) !important;
	color: var(--h4yf-ink) !important;
	padding: 16px;
}

.single-product p.price,
.single-product span.price {
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-body) !important;
	font-weight: 700 !important;
	font-size: 28px !important;
	font-variant-numeric: tabular-nums;
}

/* ---- Sale price: struck regular vs live sale (#746) --------------------
   WooCommerce renders a discounted price as `<del>` + `<ins>` inside the same
   `.price` container. Until now the file had NO `del`/`ins` rule at all, so a
   marked-down pair rendered both numbers identically — same ink, same 700
   weight — and the discount, the strongest conversion signal on a resale
   catalog, was invisible.

   `!important` is required, not decorative: the loop rule at :1015 and the PDP
   rule at :1107 both paint `.price span` with `color: var(--h4yf-ink)
   !important`, and Woo nests the amount in a `<span>` inside the `<del>`, so
   an unflagged rule here loses to them. Selectors are also written long enough
   to out-specify those two — `.woocommerce ul.products li.product .price span`
   is (0,4,3), so the loop pair below must match or beat it.

   Crimson is deliberately NOT used: it is 2.88:1 on charcoal (style.css:18),
   below the 4.5:1 AA floor for text, and it is already the CTA fill — a second
   crimson number next to a crimson Add-to-Cart competes with the click.
   `--h4yf-gray` (#8C8C8C, 5.1:1) recedes the old price instead, which is what
   makes the new one read as the discount.
   No `:is()`/`:where()` — LiteSpeed's UCSS pass silently drops those on this
   site (see the note at the top of this file). ------------------------------ */
.woocommerce ul.products li.product .price del,
.woocommerce ul.products li.product .price del span,
.single-product .entry-summary .price del,
.single-product .entry-summary .price del span,
.single-product p.price del,
.single-product p.price del span {
	color: var(--h4yf-gray) !important;
	font-weight: 400 !important;
	text-decoration: line-through;
	text-decoration-thickness: 1px;
}

.woocommerce ul.products li.product .price ins,
.woocommerce ul.products li.product .price ins span,
.single-product .entry-summary .price ins,
.single-product .entry-summary .price ins span,
.single-product p.price ins,
.single-product p.price ins span {
	color: var(--h4yf-ink) !important;
	font-weight: 700 !important;
	/* Browsers underline `<ins>` by default — on a price that reads as a typo. */
	text-decoration: none;
	background: transparent;
}

/* [FIXED 2026-07-23, Sprint 6.3: same wrong `.woocommerce`-ancestor bug —
   `.woocommerce` is a body class here, not a wrapper div, so a descendant
   selector requiring it as an ancestor of `.quantity` can never match
   (both live on/under the same body element). Live-confirmed broken:
   transparent bg, rgb(128,130,133) gray text instead of charcoal-2/ink.] */
.single-product .quantity .qty {
	background: var(--h4yf-charcoal-2) !important;
	color: var(--h4yf-ink) !important;
	border: 1px solid var(--h4yf-charcoal-2) !important;
	height: 52px !important;
	width: 60px !important;
}

/* [FIXED 2026-07-23, Sprint 6.3: prior selector required a `.woocommerce`
   ancestor div that doesn't exist in this theme's actual single-product DOM
   (Astra renders the product wrapper directly under .content-area, no
   .woocommerce class anywhere in the chain) — rule never matched live,
   button rendered stock WooCommerce blue this whole time. body.single-product
   scoping is enough; no other button on this template shares these classes.] */
body.single-product .button.single_add_to_cart_button,
body.single-product .h4yf-btn,
.h4yf-vault-alert-btn {
	background: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border-radius: 6px;
}

/* Zero default blue: neither rule above sets `border-color`, so it fell
   through to the initial `currentcolor` at (0,1,0) — Astra's own giant
   button-reset selector list carries `.woocommerce-js a.button` at (0,2,1),
   which does win a border-color fight and pins it to
   var(--ast-global-color-0). Live-measured 2026-08-17 on a PDP with an
   in-stock item (add-to-cart) and one showing the vault-alert swap-in (out
   of stock): both borders were default blue.

   [ROUND 2 FIX, same day] The first pass wrote `a.single_add_to_cart_button`
   on the assumption both buttons were anchors, matching `h4yf-vault-alert-btn`
   — checked live afterward and WooCommerce actually renders the real
   add-to-cart control as `<button type="submit" class="single_add_to_cart_button
   button alt">`, never an `<a>`, so that selector never matched anything and
   the border stayed blue straight through the "fixed" deploy. Corrected to
   the class alone (tag-agnostic).

   [ROUND 3 FIX, same day] That correction still didn't render live: the
   `.woocommerce` token in `body.h4yf-skin .woocommerce .single_add_to_cart_button`
   is a separate compound requiring `.woocommerce` to be a DESCENDANT of
   `body.h4yf-skin` — but `.woocommerce` is a class Astra puts on `<body>`
   itself on every WooCommerce-templated page, the same node as
   `body.h4yf-skin`. A node can't be its own descendant, so that half of the
   selector could never match anything, full stop — confirmed live via
   `el.matches('body.h4yf-skin .woocommerce .single_add_to_cart_button')`
   returning `false` even on the element the rule was meant to hit.
   `body.h4yf-skin button.single_add_to_cart_button` (element instead of the
   stray ancestor) gets the same (0,2,2) specificity margin correctly. */
body.h4yf-skin button.single_add_to_cart_button,
body.h4yf-skin a.h4yf-vault-alert-btn {
	border-color: currentcolor;
}

/* PDP's mobile sticky Add-to-Cart bar (`.h4yf-sticky-atc`, referenced in §8)
   renders its own plain `<button class="button">` with no other identifying
   class — same gap, same fix. */
body.h4yf-skin .h4yf-sticky-atc button.button {
	border-color: currentcolor;
	background-color: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

/* VAULT ALERT swap-in (mu-plugins/h4yf-upcoming-guard.php) — bare .button
   class picked up Astra's default blue, never themed (sprint 6.6-fix P1-6). */
.h4yf-vault-alert-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 0 16px;
	text-decoration: none;
	border: 0;
}

.h4yf-vault-alert-btn:hover {
	opacity: 0.9;
	color: var(--h4yf-ink);
}

/* Home credibility strip links + skip-link — bare <a>s picked up the
   browser/theme default blue, never themed (sprint 6.6-fix P1-6).

   [FIXED 2026-08-04, impeccable polish pass] These were `--h4yf-gray`
   (#8C8C8C, 4.66:1) sitting immediately after `--h4yf-ink` (#FAFAFA, 15:1)
   statement text on the same line — so on every row of the trust strip the
   only CLICKABLE thing was the dimmest thing: "650+ Pairs Placed with
   Collectors **See the Proof ->**". An inverted affordance, and it read as
   disabled rather than as the next step.
   Ink plus an underline instead. The underline is what says "link" — colour
   alone was doing that job badly. Not crimson: the ban on crimson-as-text was
   lifted 2026-07-26 (so the old note above is stale), but D22 records crimson
   text at 2.65:1 as a NAMED, already-failing exception, and adding new
   instances of it would widen a hole the project deliberately fenced off.
   `!important` retained — it is what beats the theme's default blue anchor. */
.h4yf-trust-stat__link,
.skip-link {
	color: var(--h4yf-ink) !important;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
	text-decoration-color: var(--h4yf-border);
}

/* Sprint 6.6-fix P1-9: text link was ~15px tall (line-height only, no
   dedicated container CSS existed) — pad the tap area without shifting
   surrounding layout (negative margin cancels the added padding box). */
.h4yf-trust-stat__link {
	/* Mobile audit 2026-07-31: measured 41.2px tall, under the 44px floor.
	   Negative margins keep the visual position identical while the tap box grows. */
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	margin: -12px -6px;
	padding: 12px 6px;
}

.h4yf-trust-stat__link:hover,
.h4yf-trust-stat__link:focus-visible {
	color: var(--h4yf-ink) !important;
	text-decoration-color: var(--h4yf-bball);
}

.skip-link:focus {
	color: var(--h4yf-charcoal) !important;
}

body.single-product .button.single_add_to_cart_button {
	width: calc(100% - 72px) !important;
	height: 52px !important;
}

/* ---- Sprint 6.3: cart-page "Proceed to Checkout" (WC Blocks) never had a
   crimson/height rule at all — checkout's own Place Order button already
   does (line ~2121); this closes the matching gap one step earlier in the
   funnel. ------------------------------------------------------------- */
body.h4yf-skin .wc-block-cart__submit-button {
	background: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border: 0;
	border-radius: 6px;
	min-height: 48px !important;
}

.single-product .product_title.entry-title {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	/* [SIZED 2026-08-02, Josh directive.] The PDP title had no size of its own —
	   it inherited Astra's h1 and landed at 34.2px on a phone and 59.3px on
	   desktop, i.e. the single most important line on the page was whatever the
	   parent theme happened to do. It now takes the skin's own display token,
	   which is both larger (36 / 72) and, more to the point, ours: the product
	   name is this page's hero and should move with the type scale, not with
	   Astra's defaults.
	   `balance` matters at this size — a two-word orphan on line three is the
	   usual failure of big condensed display type in a ~415px column. */
	font-size: var(--h4yf-fs-h1);
	line-height: 1.02;
	letter-spacing: 0.01em;
	text-wrap: balance;
	margin-bottom: 0.24em;
}

/* The rest of the summary column, scaled against that title so the block reads
   as a fashion-house spec panel rather than default WooCommerce rows. Price is
   the second-strongest thing on the page and stays Montserrat — Bebas is for
   the name, not for a number the shopper has to read precisely. */
.single-product .entry-summary .price,
.single-product .entry-summary .price span {
	font-size: clamp(26px, 0.9vw + 22px, 34px);
	letter-spacing: 0.005em;
	line-height: 1.15;
}

/* Short description: this is the one run of real prose in the column, so it
   gets a reading measure and slightly open leading rather than the tight UI
   line-height everything around it uses. */
.single-product .woocommerce-product-details__short-description p {
	font-size: var(--h4yf-fs-body);
	line-height: 1.6;
	max-width: 62ch;
	color: #E2E2E2;
	text-wrap: pretty;
}

/* PDP score section — standalone, above condition/size/scarcity (Issue #218
   reorder, 2026-07-27: gallery -> score -> condition/size/scarcity ->
   abbreviated description -> ATC). Was paired side-by-side with the short
   description inside a shared .h4yf-pdp-detail flex row on desktop (240px
   fixed column); decoupled so DOM order alone drives layout at every viewport
   width, no desktop/mobile split needed.
   [CORRECTED 2026-08-01, CU-2: said "hook-priority DOM order". Hook priority
   never produced that order on the live Astra site — see inc/flames.php for
   the mechanism. The blocks are anchored on `astra_woo_single_price_after`;
   these rules assume nothing about the hook, only that the three blocks are
   block-level siblings in the summary column.] */
.single-product .h4yf-pdp-score-section {
	margin: 0 0 16px;
	padding: 12px;
	background: var(--h4yf-charcoal-2);
	border-radius: 6px;
}

.single-product .h4yf-pdp-score-section .h4yf-score-block {
	margin: 0;
}

.single-product .woocommerce-product-details__short-description {
	margin: 0 0 16px;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	line-height: 1.6;
}

/* ================================================================== */
/* §PDP-CONVERSION — Sprint 6.8 (inc/pdp-conversion.php)               */
/* ================================================================== */
.h4yf-pdp-meta {
	display: flex;
	gap: 16px;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	color: var(--h4yf-ink);
	margin: 4px 0;
}

.h4yf-pdp-scarcity {
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-size: var(--h4yf-fs-body);
	/* Sprint 6.6-fix P1-8: crimson is fill-only per style.css:18 (2.9:1 on
	   charcoal) — never foreground text. */
	color: var(--h4yf-ink);
	margin: 4px 0 12px;
}

/* Nests inside .h4yf-pdp-checklist now (merged 2026-07-27, was two separate
   proof boxes saying "12-point" twice). */
.h4yf-pdp-trust {
	list-style: none;
	margin: 8px 0;
	padding: 12px;
	background: var(--h4yf-charcoal-2);
	border-radius: 6px;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.h4yf-pdp-trust a {
	color: var(--h4yf-ink);
	text-decoration: underline;
}

.h4yf-pdp-checklist {
	display: flex;
	flex-direction: column;
	gap: 2px;
	margin: 8px 0;
	padding: 10px 12px;
	border: 1px solid var(--h4yf-crimson);
	border-radius: 6px;
}

.h4yf-pdp-checklist__badge {
	font-family: var(--h4yf-display);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	/* Sprint 6.6-fix P1-8: crimson is fill-only (style.css:18) — the
	   crimson border on .h4yf-pdp-checklist already carries the accent. */
	color: var(--h4yf-ink);
}

.h4yf-pdp-checklist__final-sale {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	color: var(--h4yf-ink);
	margin: 4px 0 0;
}

.h4yf-pdp-checklist__final-sale a {
	color: var(--h4yf-ink);
	text-decoration: underline;
}

/* PDP hero placeholder (2026-07-27) — branded card replacing WC's gray
   "pics coming soon" gallery on UPCOMING-phase shells with no real photo
   yet. inc/pdp-hero-placeholder.php. No buy box exists on these (Vault
   Alert only) — the DROPPING banner is the CTA the rest of the page builds
   toward, styled to read as one, not a caption. */
.h4yf-pdp-hero-placeholder {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 10px;
	padding: 32px 20px;
	background: var(--h4yf-charcoal-2);
	border-radius: 8px;
}

.h4yf-pdp-hero-placeholder__mark {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
}

/* Same crimson-fill mask technique as §FLAMES' .h4yf-f (score-row flame
   glyphs), scaled way up and sat behind the raster hero logo as a brand
   accent rather than a 5th flame icon. Path is the real brand flame
   (Drive 07 — BRAND ASSETS/Logos/h4yf_flame.png), potrace-traced to a
   single subpath, verified 0.9924 IoU against the source alpha mask. */
.h4yf-pdp-hero-placeholder__flame {
	position: absolute;
	width: 260px;
	height: 260px;
	background: var(--h4yf-crimson);
	opacity: 0.18;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.5 23.93C12.12 23.77 12.04 23.0 12.38 22.78C12.49 22.71 12.76 22.47 12.99 22.24C13.22 22.02 13.52 21.74 13.66 21.61C13.97 21.31 14.47 20.34 14.41 20.16C14.35 20.02 14.25 20.03 13.39 20.22C12.46 20.44 11.97 20.24 11.97 19.65C11.97 19.29 12.23 18.84 12.87 18.15C12.99 18.02 13.45 16.92 13.57 16.5C13.96 15.1 13.57 13.44 13.15 14.7C12.77 15.81 11.42 17.22 10.53 17.42C10.07 17.52 9.92 17.37 9.7 16.64C9.56 16.16 9.4 15.88 9.4 16.09C9.4 16.13 9.32 16.19 9.23 16.21C8.83 16.31 8.44 17.04 8.13 18.28C7.86 19.34 7.81 19.41 7.26 19.38L6.82 19.35L6.75 19.61C6.64 20.02 6.72 20.65 6.9 20.89C6.99 21.0 7.06 21.14 7.06 21.2C7.06 21.25 7.13 21.45 7.21 21.62C7.54 22.36 7.45 22.9 6.99 22.9C6.7 22.9 6.09 22.68 5.98 22.53C5.94 22.47 5.79 22.39 5.66 22.36C5.37 22.3 5.11 22.07 4.97 21.75C4.92 21.62 4.83 21.51 4.77 21.51C4.37 21.51 3.4 20.02 3.15 19.02C3.08 18.76 2.96 18.37 2.88 18.15C2.46 17.02 2.71 14.4 3.33 13.35C3.4 13.23 3.52 12.99 3.59 12.8C3.8 12.28 4.2 11.67 4.39 11.56C4.49 11.51 4.67 11.31 4.8 11.11C4.92 10.92 5.13 10.7 5.26 10.62C5.39 10.55 5.59 10.33 5.71 10.15C5.85 9.93 5.99 9.8 6.11 9.78C6.21 9.76 6.46 9.63 6.66 9.49C7.32 9.04 7.57 9.02 7.87 9.39C8.05 9.61 8.28 9.44 8.65 8.81C9.11 8.03 9.18 7.42 9.0 5.58C8.87 4.34 9.9 4.44 11.17 5.78C11.89 6.55 12.05 6.63 12.21 6.33C12.25 6.25 12.38 6.03 12.5 5.84C13.0 5.0 13.26 2.23 12.9 1.44C12.48 0.52 12.79 -0.09 13.55 0.11C14.22 0.29 15.78 1.81 16.04 2.52C16.09 2.69 16.23 2.95 16.34 3.11C16.54 3.41 16.65 3.66 16.84 4.27C16.9 4.46 17.02 4.74 17.1 4.89C17.27 5.19 17.34 5.57 17.49 6.86C17.61 7.99 17.7 8.15 18.03 7.83C18.15 7.7 18.26 7.53 18.26 7.45C18.26 6.59 18.75 5.85 19.34 5.85C20.32 5.85 20.69 8.85 19.97 10.95C19.67 11.82 19.76 11.98 20.38 11.76C21.35 11.41 21.62 11.98 21.02 13.08C20.61 13.8 20.52 14.3 20.52 15.78C20.52 17.12 20.38 17.98 20.03 18.73C19.91 18.99 19.77 19.32 19.71 19.46C19.66 19.6 19.45 19.92 19.24 20.16C19.04 20.4 18.78 20.73 18.66 20.89C18.54 21.05 18.31 21.29 18.15 21.44C17.99 21.58 17.79 21.76 17.7 21.85C17.61 21.93 17.43 22.07 17.29 22.16C17.15 22.24 16.92 22.41 16.77 22.52C15.78 23.31 13.11 24.19 12.5 23.93Z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.5 23.93C12.12 23.77 12.04 23.0 12.38 22.78C12.49 22.71 12.76 22.47 12.99 22.24C13.22 22.02 13.52 21.74 13.66 21.61C13.97 21.31 14.47 20.34 14.41 20.16C14.35 20.02 14.25 20.03 13.39 20.22C12.46 20.44 11.97 20.24 11.97 19.65C11.97 19.29 12.23 18.84 12.87 18.15C12.99 18.02 13.45 16.92 13.57 16.5C13.96 15.1 13.57 13.44 13.15 14.7C12.77 15.81 11.42 17.22 10.53 17.42C10.07 17.52 9.92 17.37 9.7 16.64C9.56 16.16 9.4 15.88 9.4 16.09C9.4 16.13 9.32 16.19 9.23 16.21C8.83 16.31 8.44 17.04 8.13 18.28C7.86 19.34 7.81 19.41 7.26 19.38L6.82 19.35L6.75 19.61C6.64 20.02 6.72 20.65 6.9 20.89C6.99 21.0 7.06 21.14 7.06 21.2C7.06 21.25 7.13 21.45 7.21 21.62C7.54 22.36 7.45 22.9 6.99 22.9C6.7 22.9 6.09 22.68 5.98 22.53C5.94 22.47 5.79 22.39 5.66 22.36C5.37 22.3 5.11 22.07 4.97 21.75C4.92 21.62 4.83 21.51 4.77 21.51C4.37 21.51 3.4 20.02 3.15 19.02C3.08 18.76 2.96 18.37 2.88 18.15C2.46 17.02 2.71 14.4 3.33 13.35C3.4 13.23 3.52 12.99 3.59 12.8C3.8 12.28 4.2 11.67 4.39 11.56C4.49 11.51 4.67 11.31 4.8 11.11C4.92 10.92 5.13 10.7 5.26 10.62C5.39 10.55 5.59 10.33 5.71 10.15C5.85 9.93 5.99 9.8 6.11 9.78C6.21 9.76 6.46 9.63 6.66 9.49C7.32 9.04 7.57 9.02 7.87 9.39C8.05 9.61 8.28 9.44 8.65 8.81C9.11 8.03 9.18 7.42 9.0 5.58C8.87 4.34 9.9 4.44 11.17 5.78C11.89 6.55 12.05 6.63 12.21 6.33C12.25 6.25 12.38 6.03 12.5 5.84C13.0 5.0 13.26 2.23 12.9 1.44C12.48 0.52 12.79 -0.09 13.55 0.11C14.22 0.29 15.78 1.81 16.04 2.52C16.09 2.69 16.23 2.95 16.34 3.11C16.54 3.41 16.65 3.66 16.84 4.27C16.9 4.46 17.02 4.74 17.1 4.89C17.27 5.19 17.34 5.57 17.49 6.86C17.61 7.99 17.7 8.15 18.03 7.83C18.15 7.7 18.26 7.53 18.26 7.45C18.26 6.59 18.75 5.85 19.34 5.85C20.32 5.85 20.69 8.85 19.97 10.95C19.67 11.82 19.76 11.98 20.38 11.76C21.35 11.41 21.62 11.98 21.02 13.08C20.61 13.8 20.52 14.3 20.52 15.78C20.52 17.12 20.38 17.98 20.03 18.73C19.91 18.99 19.77 19.32 19.71 19.46C19.66 19.6 19.45 19.92 19.24 20.16C19.04 20.4 18.78 20.73 18.66 20.89C18.54 21.05 18.31 21.29 18.15 21.44C17.99 21.58 17.79 21.76 17.7 21.85C17.61 21.93 17.43 22.07 17.29 22.16C17.15 22.24 16.92 22.41 16.77 22.52C15.78 23.31 13.11 24.19 12.5 23.93Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

.h4yf-pdp-hero-placeholder__logo {
	position: relative;
	max-width: 220px;
	height: auto;
}

.h4yf-pdp-hero-placeholder__title {
	font-family: var(--h4yf-display);
	font-weight: 400;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	font-size: var(--h4yf-fs-h2);
	margin: 8px 0 0;
}

.h4yf-pdp-hero-placeholder__colorway {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-h3);
	color: #9a9a9a;
	margin: 0;
}

.h4yf-pdp-hero-placeholder__banner {
	font-family: var(--h4yf-display);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: #fff;
	background: var(--h4yf-crimson);
	width: 100%;
	padding: 12px 20px;
	border-radius: 6px;
	font-size: var(--h4yf-fs-h3);
	margin: 12px 0 0;
}

.h4yf-pdp-hero-placeholder__footer {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	letter-spacing: 0.04em;
	color: #9a9a9a;
	display: flex;
	gap: 16px;
	margin: 4px 0 0;
}

/* PDP video proof (2026-07-27) — real per-product YouTube embed, feed-gated
   server-side in inc/pdp-conversion.php; iframe injected client-side by
   assets/js/proof-render.js. Reserve the 16:9 box before JS runs (CLS). */
.h4yf-pdp-video-proof {
	margin: 32px 0;
}

.h4yf-pdp-video-proof__title {
	font-family: var(--h4yf-display);
	font-weight: 400;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	font-size: var(--h4yf-fs-h3);
	margin: 0 0 12px;
}

.h4yf-video-proof-wrapper {
	position: relative;
	padding-bottom: 56.25%;
	height: 0;
	overflow: hidden;
	max-width: 100%;
	border-radius: 6px;
	background: var(--h4yf-charcoal-2);
}

/* PDP Curator's Take (#273) — the payoff for every tile teaser across the
   Drops Engine. Flat tonal box, not a side-stripe blockquote (DESIGN.md
   Elevation: depth is a tonal step + hairline, never a colored border). */
.h4yf-pdp-curators-take {
	margin: 32px 0;
	background: var(--h4yf-charcoal-2);
	border-radius: 6px;
	padding: 20px 22px;
}

.h4yf-pdp-curators-take__title {
	font-family: var(--h4yf-display);
	font-weight: 400;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	font-size: var(--h4yf-fs-h3);
	margin: 0 0 10px;
}

/* Editorial copy, so it gets editorial measure: ~66 characters is the readable
   line, and at 1.5 a 700-character single paragraph was a grey wall (Josh
   2026-08-02). The paragraphs come from h4yf_ct_paragraphs(). */
.h4yf-pdp-curators-take__body {
	margin: 0;
	max-width: 66ch;
	color: #e2e2e2;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	font-weight: 500;
	line-height: 1.65;
}

.h4yf-pdp-curators-take__body p {
	margin: 0 0 0.9em;
}

.h4yf-pdp-curators-take__body p:last-child {
	margin-bottom: 0;
}

/* The attribution is a sibling of the quote, not a line inside it — it kept
   running on from the last sentence as though Billy had said his own name. */
.h4yf-pdp-curators-take__cite {
	margin: 14px 0 0;
	padding-top: 12px;
	border-top: 1px solid var(--h4yf-border);
	color: #9a9a9a;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	font-weight: 600;
	letter-spacing: 0.02em;
}

.h4yf-pdp-crosssell {
	margin: 32px 0;
}

/* Section title, sized like every other section title on the site rather than
   left at Astra's default h2 — this rail sits directly under the PDP and used
   to read as a smaller, weaker heading than the shop archive's. */
.h4yf-pdp-crosssell h2 {
	font-family: var(--h4yf-display);
	color: var(--h4yf-ink);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	margin: 0 0 16px;
}

/* [DELETED 2026-08-02] `.h4yf-pdp-crosssell__grid` and its `li a` type rules
   lived here — a bespoke 2-up/4-up grid with 13px Montserrat titles. The rail
   now renders through WooCommerce's own loop template (inc/pdp-conversion.php),
   so it inherits the real card system: Bebas title, HEAT row, condition badge,
   hover ring, identical padding. Deleting the override IS the fix — a second
   copy of card styling is the thing that drifted in the first place. */


/* ================================================================== */
/* §FLAMES — HEAT / GRAIL / COP player-stat display (inc/flames.php)   */
/* Fresh on-brand styling — replaces the red snippet-902 §F.          */
/* ================================================================== */
.h4yf-score-block {
	display: flex;
	flex-direction: column;
	gap: 5px;
	margin: 10px 0;
	container-type: inline-size;
}

.h4yf-score-block--compact {
	gap: 2px;
	margin: 6px 0 2px;
}

.h4yf-score-row {
	display: flex;
	align-items: center;
	gap: 8px;
}

/* Expanded (PDP) row: label | flames | score | definition, one line, all
   three rows inside the single score box. Label, flame run and score are
   fixed-width so every row's definition starts on the same x — the block
   reads as an aligned stat sheet, not three ragged lines. None of this
   touches the compact card variant, which renders no score or definition. */
.h4yf-score-row:has(.h4yf-score-explain) {
	gap: 10px;
	padding: 3px 0;
}

.h4yf-score-row:has(.h4yf-score-explain) .h4yf-flames {
	flex: 0 0 auto;
	min-width: 88px;
}

/* One-word gloss (Rarity / Prestige / Deal). The full sentence lives on the
   Additional Information tab, so this never needs to wrap — no breakpoint. */
.h4yf-score-explain {
	flex: 0 1 auto;
	min-width: 0;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	line-height: 1.4;
	color: #9a9a9a;
}

.h4yf-score-label {
	flex: 0 0 auto;
	min-width: 46px;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-meta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #9a9a9a;
}

.h4yf-score-block--compact .h4yf-score-label {
	min-width: 40px;
	font-size: 9px;
}

.h4yf-score-row--link {
	color: inherit;
	text-decoration: none;
	cursor: pointer;
	margin-block: -4px;
	padding-block: 4px;
}

.h4yf-score-row--link:hover,
.h4yf-score-row--link:focus-visible {
	color: var(--h4yf-ink);
}

.h4yf-score-row--link:hover .h4yf-score-label,
.h4yf-score-row--link:focus-visible .h4yf-score-label {
	color: var(--h4yf-ink);
}

.h4yf-flames {
	display: inline-flex;
	gap: 2px;
}

/* Flame glyph: a mask lets the background (solid / split-gradient / dim)
   show through for full / half / empty without separate icon assets.
   Path is the real H4YF brand flame (Drive 07 — BRAND ASSETS/Logos/
   h4yf_flame.png), potrace-traced to a single subpath normalized into the
   24x24 box (2026-07-27) — replaces the generic flame that shipped before.
   Verified 0.9924 IoU against the source alpha mask. Fill logic unchanged:
   an empty flame filled 50% or 100% with crimson, 1-4 flames by half step. */
.h4yf-f {
	width: 20px;
	height: 20px;
	background: var(--h4yf-charcoal-2);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.5 23.93C12.12 23.77 12.04 23.0 12.38 22.78C12.49 22.71 12.76 22.47 12.99 22.24C13.22 22.02 13.52 21.74 13.66 21.61C13.97 21.31 14.47 20.34 14.41 20.16C14.35 20.02 14.25 20.03 13.39 20.22C12.46 20.44 11.97 20.24 11.97 19.65C11.97 19.29 12.23 18.84 12.87 18.15C12.99 18.02 13.45 16.92 13.57 16.5C13.96 15.1 13.57 13.44 13.15 14.7C12.77 15.81 11.42 17.22 10.53 17.42C10.07 17.52 9.92 17.37 9.7 16.64C9.56 16.16 9.4 15.88 9.4 16.09C9.4 16.13 9.32 16.19 9.23 16.21C8.83 16.31 8.44 17.04 8.13 18.28C7.86 19.34 7.81 19.41 7.26 19.38L6.82 19.35L6.75 19.61C6.64 20.02 6.72 20.65 6.9 20.89C6.99 21.0 7.06 21.14 7.06 21.2C7.06 21.25 7.13 21.45 7.21 21.62C7.54 22.36 7.45 22.9 6.99 22.9C6.7 22.9 6.09 22.68 5.98 22.53C5.94 22.47 5.79 22.39 5.66 22.36C5.37 22.3 5.11 22.07 4.97 21.75C4.92 21.62 4.83 21.51 4.77 21.51C4.37 21.51 3.4 20.02 3.15 19.02C3.08 18.76 2.96 18.37 2.88 18.15C2.46 17.02 2.71 14.4 3.33 13.35C3.4 13.23 3.52 12.99 3.59 12.8C3.8 12.28 4.2 11.67 4.39 11.56C4.49 11.51 4.67 11.31 4.8 11.11C4.92 10.92 5.13 10.7 5.26 10.62C5.39 10.55 5.59 10.33 5.71 10.15C5.85 9.93 5.99 9.8 6.11 9.78C6.21 9.76 6.46 9.63 6.66 9.49C7.32 9.04 7.57 9.02 7.87 9.39C8.05 9.61 8.28 9.44 8.65 8.81C9.11 8.03 9.18 7.42 9.0 5.58C8.87 4.34 9.9 4.44 11.17 5.78C11.89 6.55 12.05 6.63 12.21 6.33C12.25 6.25 12.38 6.03 12.5 5.84C13.0 5.0 13.26 2.23 12.9 1.44C12.48 0.52 12.79 -0.09 13.55 0.11C14.22 0.29 15.78 1.81 16.04 2.52C16.09 2.69 16.23 2.95 16.34 3.11C16.54 3.41 16.65 3.66 16.84 4.27C16.9 4.46 17.02 4.74 17.1 4.89C17.27 5.19 17.34 5.57 17.49 6.86C17.61 7.99 17.7 8.15 18.03 7.83C18.15 7.7 18.26 7.53 18.26 7.45C18.26 6.59 18.75 5.85 19.34 5.85C20.32 5.85 20.69 8.85 19.97 10.95C19.67 11.82 19.76 11.98 20.38 11.76C21.35 11.41 21.62 11.98 21.02 13.08C20.61 13.8 20.52 14.3 20.52 15.78C20.52 17.12 20.38 17.98 20.03 18.73C19.91 18.99 19.77 19.32 19.71 19.46C19.66 19.6 19.45 19.92 19.24 20.16C19.04 20.4 18.78 20.73 18.66 20.89C18.54 21.05 18.31 21.29 18.15 21.44C17.99 21.58 17.79 21.76 17.7 21.85C17.61 21.93 17.43 22.07 17.29 22.16C17.15 22.24 16.92 22.41 16.77 22.52C15.78 23.31 13.11 24.19 12.5 23.93Z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12.5 23.93C12.12 23.77 12.04 23.0 12.38 22.78C12.49 22.71 12.76 22.47 12.99 22.24C13.22 22.02 13.52 21.74 13.66 21.61C13.97 21.31 14.47 20.34 14.41 20.16C14.35 20.02 14.25 20.03 13.39 20.22C12.46 20.44 11.97 20.24 11.97 19.65C11.97 19.29 12.23 18.84 12.87 18.15C12.99 18.02 13.45 16.92 13.57 16.5C13.96 15.1 13.57 13.44 13.15 14.7C12.77 15.81 11.42 17.22 10.53 17.42C10.07 17.52 9.92 17.37 9.7 16.64C9.56 16.16 9.4 15.88 9.4 16.09C9.4 16.13 9.32 16.19 9.23 16.21C8.83 16.31 8.44 17.04 8.13 18.28C7.86 19.34 7.81 19.41 7.26 19.38L6.82 19.35L6.75 19.61C6.64 20.02 6.72 20.65 6.9 20.89C6.99 21.0 7.06 21.14 7.06 21.2C7.06 21.25 7.13 21.45 7.21 21.62C7.54 22.36 7.45 22.9 6.99 22.9C6.7 22.9 6.09 22.68 5.98 22.53C5.94 22.47 5.79 22.39 5.66 22.36C5.37 22.3 5.11 22.07 4.97 21.75C4.92 21.62 4.83 21.51 4.77 21.51C4.37 21.51 3.4 20.02 3.15 19.02C3.08 18.76 2.96 18.37 2.88 18.15C2.46 17.02 2.71 14.4 3.33 13.35C3.4 13.23 3.52 12.99 3.59 12.8C3.8 12.28 4.2 11.67 4.39 11.56C4.49 11.51 4.67 11.31 4.8 11.11C4.92 10.92 5.13 10.7 5.26 10.62C5.39 10.55 5.59 10.33 5.71 10.15C5.85 9.93 5.99 9.8 6.11 9.78C6.21 9.76 6.46 9.63 6.66 9.49C7.32 9.04 7.57 9.02 7.87 9.39C8.05 9.61 8.28 9.44 8.65 8.81C9.11 8.03 9.18 7.42 9.0 5.58C8.87 4.34 9.9 4.44 11.17 5.78C11.89 6.55 12.05 6.63 12.21 6.33C12.25 6.25 12.38 6.03 12.5 5.84C13.0 5.0 13.26 2.23 12.9 1.44C12.48 0.52 12.79 -0.09 13.55 0.11C14.22 0.29 15.78 1.81 16.04 2.52C16.09 2.69 16.23 2.95 16.34 3.11C16.54 3.41 16.65 3.66 16.84 4.27C16.9 4.46 17.02 4.74 17.1 4.89C17.27 5.19 17.34 5.57 17.49 6.86C17.61 7.99 17.7 8.15 18.03 7.83C18.15 7.7 18.26 7.53 18.26 7.45C18.26 6.59 18.75 5.85 19.34 5.85C20.32 5.85 20.69 8.85 19.97 10.95C19.67 11.82 19.76 11.98 20.38 11.76C21.35 11.41 21.62 11.98 21.02 13.08C20.61 13.8 20.52 14.3 20.52 15.78C20.52 17.12 20.38 17.98 20.03 18.73C19.91 18.99 19.77 19.32 19.71 19.46C19.66 19.6 19.45 19.92 19.24 20.16C19.04 20.4 18.78 20.73 18.66 20.89C18.54 21.05 18.31 21.29 18.15 21.44C17.99 21.58 17.79 21.76 17.7 21.85C17.61 21.93 17.43 22.07 17.29 22.16C17.15 22.24 16.92 22.41 16.77 22.52C15.78 23.31 13.11 24.19 12.5 23.93Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

.h4yf-score-block--compact .h4yf-f {
	width: 13px;
	height: 13px;
}

.h4yf-f--full {
	background: var(--h4yf-crimson);
}

.h4yf-f--half {
	background: linear-gradient(90deg, var(--h4yf-crimson) 0 50%, var(--h4yf-charcoal-2) 50% 100%);
}

.h4yf-f--empty {
	background: var(--h4yf-charcoal-2);
}

/* Score legend on the Additional Information tab — long-form half of the
   split the in-row one-word glosses come from (inc/flames.php). */
.h4yf-score-legend {
	margin: 24px 0 0;
}

.h4yf-score-legend__title {
	font-family: var(--h4yf-display);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--h4yf-ink);
	font-size: var(--h4yf-fs-h3);
	margin: 0 0 6px;
}

.h4yf-score-legend__intro {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	color: #9a9a9a;
	margin: 0 0 12px;
}

.h4yf-score-legend__list {
	margin: 0;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	color: var(--h4yf-ink);
}

.h4yf-score-legend__list div {
	display: flex;
	gap: 12px;
	padding: 6px 0;
	border-top: 1px solid var(--h4yf-charcoal-2);
}

.h4yf-score-legend__list dt {
	flex: 0 0 auto;
	min-width: 64px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-size: var(--h4yf-fs-meta);
	color: #9a9a9a;
}

.h4yf-score-legend__list dd {
	margin: 0;
	flex: 1 1 auto;
	min-width: 0;
}

/* Flame/HEAT-COP-GRAIL score badge — the signature-mechanic component
   (H4YF_TYPOGRAPHY_PLAN.md §3): ink text on solid crimson fill (5.7:1, never
   crimson-as-text). Sized in container-query units — it lives in a
   variable-width card (.h4yf-score-block sets container-type above), not the
   viewport, so a vw-based clamp would size it wrong across grid columns. */
.h4yf-score-badge {
	/* Trails the gloss (inc/flames.php) — must not shrink, or the one row that
	   scored 4.0 would compress its own badge to keep the gloss on one line. */
	flex: 0 0 auto;
	margin-left: 8px;
	padding: 2px 6px;
	background: var(--h4yf-crimson);
	border: none;
	border-radius: 3px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(8px, 3.4cqi, 11px);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	white-space: nowrap;
}

.h4yf-score-block--compact .h4yf-score-badge {
	display: none; /* keep cards clean; the badge lives on the PDP */
}

/* ================================================================== */
/* §CARDS — desktop product surface + drops badge restyle             */
/* (mobile 2-col grid handled above; crimson stays CTA-only)          */
/* ================================================================== */
@media (min-width: 769px) {
	.woocommerce ul.products li.product {
		background: var(--h4yf-charcoal-2);
		border: 1px solid var(--h4yf-charcoal-2);
		border-radius: 8px;
		overflow: hidden;
		padding-bottom: 14px;
		transition: border-color 0.15s ease;
	}

	.woocommerce ul.products li.product:hover {
		border-color: #3a3a3e;
	}

	.woocommerce ul.products li.product > a img {
		margin-bottom: 12px;
	}

	.woocommerce ul.products li.product .woocommerce-loop-product__title,
	.woocommerce ul.products li.product .price {
		padding-left: 12px;
		padding-right: 12px;
	}

}

/* Duplicate CTA fix (2026-08-20): `h4yf_swap_loop_cta()` (inc/inventory-
   lifecycle.php) removes core's `woocommerce_template_loop_add_to_cart` off
   `woocommerce_after_shop_loop_item` and re-adds it as `.h4yf-loop-cta`, but
   Astra's on-card quick-add anchor (`.ast-on-card-button`, thumbnail-wrap) is
   a separate Astra feature on its own hook — untouched by that swap. Both
   matched `a[class*="add_to_cart_button"]` below and got styled identically,
   so every live card rendered two visually indistinguishable crimson
   buttons stacked. Hide anything matching that isn't the canonical one. */
.woocommerce ul.products li.product a[class*="add_to_cart_button"]:not(.h4yf-loop-cta) {
	display: none !important;
}

/* Loop add-to-cart — crimson CTA, not the stock blue WC/Astra default
   (desktop only; the mobile grid hides it, see the 768px block above).
   Attribute selector catches Astra's on-card anchor (ast-on-card-button ...
   add_to_cart_button, no .button class) — same defect class as the
   mobile hide-rule above (sprint 6.6-fix P1-5). */
.woocommerce ul.products li.product a[class*="add_to_cart_button"],
.woocommerce ul.products li.product .added_to_cart {
	background: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border: 0;
	border-radius: 6px;
	margin: 6px 12px 0;
	display: inline-block;
	text-decoration: none;
}

/* WooCommerce blocks render .wc-block-grid markup, not the classic
   ul.products loop — same card tokens so both surfaces match the skin. */
.wc-block-grid__products {
	margin: 0;
	padding: 0;
}

.wc-block-grid__product {
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-charcoal-2);
	border-radius: 8px;
	overflow: hidden;
	padding-bottom: 14px;
	transition: border-color 0.15s ease;
}

.wc-block-grid__product:hover {
	border-color: #3a3a3e;
}

.wc-block-grid__product .wc-block-grid__product-image img {
	margin-bottom: 12px;
}

.wc-block-grid__product .wc-block-grid__product-title {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: 14px;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	padding-left: 12px;
	padding-right: 12px;
}

.wc-block-grid__product .wc-block-grid__product-price,
.wc-block-grid__product .wc-block-grid__product-price span {
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	padding-left: 12px;
	padding-right: 12px;
}

.wc-block-grid__product .wp-block-button__link,
.wc-block-grid__product .add_to_cart_button {
	background: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border: 0;
	border-radius: 6px;
}

/* ---- Standalone Gutenberg block buttons (#746) -------------------------
   The rule above only reaches a `.wp-block-button__link` inside a
   `.wc-block-grid__product`. A block button placed anywhere else — the empty
   cart's "Browse Sneakers", any button dropped into page content — fell
   through to Astra's `--ast-global-color-0`, which is stock #046bd2.
   Live-confirmed 2026-08-30 on /cart/: `a.wp-block-button__link` rendered
   `rgb(4, 107, 210)`. That page is never page-cached (WooCommerce excludes
   it), so it was not a stale-cache artifact — it is what every shopper with
   an empty cart saw, on the one CTA whose whole job is to send them back to
   the catalog.

   Same crimson/ink/Bebas treatment the rest of the CTAs carry, so a block
   button is not a second visual language for "click me". `!important` matches
   the grid rule directly above for the same reason it needs it there: Astra's
   generated `.wp-element-button` rules print after this stylesheet.

   Scoped to `.wp-block-button__link` on purpose, NOT the broader
   `.wp-element-button`: WordPress stamps that second class onto WooCommerce's
   secondary controls too ("Apply coupon", "Update cart"), which are deliberately
   not crimson — crimson is the primary-action fill, and spending it on a coupon
   button is what makes it stop meaning anything on the Add to Cart.
   ------------------------------------------------------------------------- */
body.h4yf-skin .wp-block-button__link {
	background: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border: 0;
	border-radius: 6px;
}

body.h4yf-skin .wp-block-button__link:hover {
	color: var(--h4yf-hover) !important;
	box-shadow: 0 0 0 3px var(--h4yf-bball-halo), 0 0 16px 1px var(--h4yf-bball-glow);
}

@media (max-width: 768px) {
	/* Match the classic loop: no add-to-cart on mobile cards. */
	.wc-block-grid__product .wp-block-button,
	.wc-block-grid__product .add_to_cart_button {
		display: none !important;
	}
}

/* PRE-OWNED / AUTHENTICATED condition badge (from h4yf-core-drops):
   charcoal/outline, never red — crimson is reserved for CTAs. */
/* Archive title (Shop / category) — white display type, flex-aligned with header filter button. */
.woocommerce-products-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	max-width: 1200px;
	margin: 0 auto 16px;
	padding: 0 24px;
	gap: 16px;
}

.woocommerce-products-header__title,
.ast-archive-title,
.woocommerce-products-header .page-title {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	margin-bottom: 0;
}

.woocommerce-products-header .astra-shop-filter-button.ast-flyout-filter {
	margin-left: auto;
	flex-shrink: 0;
}

/* Condition/authentication trust badge (H4YF_TYPOGRAPHY_PLAN.md §3): a trust/
   verification element, deliberately Montserrat not Bebas Neue even though
   it's short and caps-like — it follows the body/utility rule. */
.h4yf-condition-badge,
.h4yf-auth-badge,
.woocommerce ul.products li.product .h4yf-cond {
	display: inline-block;
	margin: 0 12px 6px;
	padding: 3px 8px;
	background: transparent;
	border: 1px solid #5a5a5e;
	border-radius: 3px;
	color: #cfcfcf;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-meta);
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

/* peru: legacy WPCode ribbon ("AUTHENTICATED", top:10px;left:0) and the
   condition badge ("DS"/"VNDS"/"BEATER", top:10px;left:10px) both anchor the
   same corner of the product-card image and render as garbled overlapping
   text. Push the condition badge below the ribbon so both stay legible. */
.woocommerce ul.products li.product .h4yf-cond-badge {
	top: 34px !important;
	left: 10px !important;
}

/* ================================================================== */
/* §HOME — curated front-page.php (skin-owned homepage)               */
/* ================================================================== */
.h4yf-home {
	display: block;
	/* D16 CONTINUOUS WASH — moved to `body.h4yf-skin` above (Josh punch list
	   2026-08-05: the wash is now site-wide, not homepage-only). No own
	   background here any more; `body`'s shows through. */
	color: var(--h4yf-ink);
}

.h4yf-btn--lg {
	min-height: 54px;
	padding: 0 28px;
	/* [FIXED 2026-08-04, impeccable polish pass] This was a hard `14px`, which
	   overrode `.h4yf-btn`'s `font-size: var(--h4yf-fs-cta)` — so the LARGE
	   variant rendered SMALLER than the base button (14px vs 16-20px), and the
	   hero's two CTAs measured 14px under a 72px Bebas headline. Straight token
	   drift against DESIGN.md's `cta` role (16-20px).
	   Re-declared rather than deleted on purpose: slate inlines a stale per-URL
	   `<style id="litespeed-ccss">` block that keeps supplying any declaration
	   merely REMOVED from the bundle (GOTCHAS "Data sourcing"). A deletion here
	   would have shipped as a no-op. `--lg` now differs from the base button by
	   hit area (54px / 28px padding), which is what "large" meant on this site
	   anyway — no new token invented for a one-off size. */
	font-size: var(--h4yf-fs-cta);
}

/* ---- Hero (text-forward = fast LCP) ---- */
.h4yf-home-hero {
	padding: clamp(48px, 11vw, 104px) 16px clamp(24px, 5vw, 40px);
	text-align: center;
	/* D16: no own background — the .h4yf-home continuous wash shows through. */
}

/* D16 wordmark red "4" — brand mark styling (signed-off it7), not body text. */
.h4yf-wordmark-four {
	color: var(--h4yf-crimson-accent);
}

.h4yf-home-hero__inner {
	max-width: 760px;
	margin: 0 auto;
}

.h4yf-home-hero__logo {
	display: block;
	height: 56px;
	width: auto;
	max-width: 280px;
	margin: 0 auto 22px;
	object-fit: contain;
}

.h4yf-home-hero__wordmark {
	display: block;
	margin: 0 0 18px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(28px, 8vw, 44px);
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/* The hero mark. Restored 2026-08-04 (Josh: "Put the main hero logo
   w/basketball background back"), which also closes issue #453 — "hero ships
   zero imagery on a sneaker brand". The D16 text-forward hero was chosen for
   LCP; a 520px PNG with `fetchpriority=high` and reserved dimensions is a
   decodable LCP element, not a regression, and the section it replaced was
   costing the page its only above-the-fold image on a visual product. */
.h4yf-home-hero__mark {
	display: block;
	/* 180px floor was 48-56% of a 320-375px viewport (Josh punch list:
	   mobile-first right-size). 130px still reads at a glance, scales up
	   past the smallest phones via vw before hitting the 300px desktop cap. */
	width: clamp(130px, 40vw, 300px);
	height: auto;
	margin: 0 auto clamp(18px, 4vw, 30px);
}

.h4yf-home-hero__eyebrow {
	margin: 0 0 14px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	line-height: 1.1;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	text-wrap: balance;
}

/* Crimson TEXT is a named, deliberate AA exception — D22, Josh 2026-08-02.
   `--h4yf-crimson` measures 2.88:1 on the charcoal floor, under both the 4.5:1
   body and 3:1 large-text floors. The call was to accept it by name rather than
   introduce a second lighter crimson for text; it is recorded as a known
   failure in docs/a11y/a11y.json and printed by a11y_check.py on every run, so
   it is tracked rather than silently passing. Do not "fix" this by swapping the
   token. [SUPERSEDES the 2026-07 note that stood here claiming crimson could
   never be a heading colour — that predated D22 and the 2026-07-26 token
   directive, and style.css:40 has said "CTAs + accents + text" since.]

   Scoped under `.h4yf-skin` for a specificity reason, not a stylistic one:
   this file opens with `:root h1 … {color: var(--h4yf-ink)}` at (0,1,1) — the
   rule that beats Astra's light-background palette. Measured in the render
   harness before deploy. `.h4yf-skin .h4yf-home-hero__tagline` is (0,2,0) and
   wins without an `!important`.

   The H1 title is deliberately NOT in this list (Josh punch list: "ALL THINGS
   SNEAKERS" font color to white) — it falls through to the `:root h1` ink
   rule above instead. */
.h4yf-skin .h4yf-home-hero__eyebrow .h4yf-accent,
.h4yf-skin .h4yf-home-hero__tagline {
	color: var(--h4yf-crimson);
}

.h4yf-home-hero__title {
	margin: 0 0 10px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h1);
	line-height: 1.04;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	text-wrap: balance;
}

.h4yf-home-hero__tagline {
	margin: 0 0 28px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(20px, 5.2vw, 30px);
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.h4yf-home-hero__cta {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 12px;
	margin: 0 0 36px;
}

.h4yf-home-hero__proof {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 14px 30px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.h4yf-home-hero__proof li {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.h4yf-home-hero__proof b {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-trust-stat);
	color: var(--h4yf-ink);
	line-height: 1;
}

.h4yf-home-hero__proof span {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-trust-label);
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: #9a9a9a;
}

/* ---- Proof / authority strip ---- */
.h4yf-home-strip {
	background: var(--h4yf-charcoal-2);
	border-top: 1px solid #3a3a3e;
	border-bottom: 1px solid #3a3a3e;
}

.h4yf-home-strip__inner {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1px;
	max-width: 1100px;
	margin: 0 auto;
}

@media (min-width: 769px) {
	.h4yf-home-strip__inner {
		grid-template-columns: repeat(4, 1fr);
	}
}

.h4yf-home-strip__item {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 22px 18px;
	text-align: center;
	background: var(--h4yf-charcoal);
}

.h4yf-home-strip__item b {
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-subhead);
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
}

.h4yf-home-strip__item span {
	font-size: 12px;
	color: #9a9a9a;
}

/* ---- Trust strip: cart/checkout $45 auth-service CTA item (Sprint 4.1) ---- */
.h4yf-trust-strip__cta-item {
	justify-content: center;
}

.h4yf-trust-strip__cta {
	/* Was `nowrap`: the $45 label is 258px and a phone cell is ~170px, so the
	   cart and checkout pages scrolled sideways at 375px (2026-09-30 audit). */
	white-space: normal;
	text-wrap: balance;
}

/* ---- Generic section frame ---- */
.h4yf-home-section {
	max-width: 1180px;
	margin: 0 auto;
	padding: clamp(36px, 7vw, 64px) 16px 0;
}

.h4yf-home-section__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	margin: 0 0 18px;
}

.h4yf-home-section__title {
	margin: 0;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.h4yf-home-section__link {
	flex: 0 0 auto;
	/* Mobile audit 2026-07-31: measured 43.8px tall — 0.2px under floor, which
	   still fails an audit and still misses thumbs. */
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	color: var(--h4yf-ink);
	text-decoration: none;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	transition: color 0.2s ease;
	/* Sprint 6.6-fix P1-9: ~15-20px tap height on a 12px label — pad the hit
	   area, negative margin keeps the visual row height/baseline unchanged. */
	margin: -12px -6px -12px;
	padding: 12px 6px;
}

.h4yf-home-section__link:hover,
.h4yf-home-section__link:focus-visible {
	color: var(--h4yf-hover);
}

/* ---- Guarantee banner (D18) — markup shipped in front-page.php with no CSS
   anywhere until Sprint 6.6 RC3; title rendered Astra slate on charcoal. ---- */
.h4yf-home-guarantee {
	margin: clamp(28px, 5vw, 48px) 0 0;
	padding: clamp(28px, 5vw, 44px) 16px;
	text-align: center;
	/* Accent hairlines, not a filled band — crimson is fill-only for CTAs (style.css :root). */
	border-top: 1px solid var(--h4yf-crimson-accent);
	border-bottom: 1px solid var(--h4yf-crimson-accent);
}

.h4yf-home-guarantee__inner {
	max-width: 620px;
	margin: 0 auto;
}

.h4yf-home-guarantee__title {
	margin: 0 0 10px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.h4yf-home-guarantee__text {
	margin: 0 0 14px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	line-height: 1.6;
}

.h4yf-home-guarantee .h4yf-home-section__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 0 8px;
}

/* ---- Shop by category ---- */
.h4yf-home-cats__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 8px;
}

/* `repeat(5, 1fr)` stood here and the set has SIX silhouettes — measured at
   1440 it laid out 5 + an orphan row of 1. It was survivable while the tiles
   were text boxes; with photos the orphan reads as a broken grid. auto-fit
   rather than `repeat(6, …)` so the row still resolves if `h4yf_silhouettes`
   is ever filtered to a different count. */
@media (min-width: 769px) {
	.h4yf-home-cats__grid {
		grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
	}
}

/* Photo tiles, not text boxes (Josh 2026-08-04). The image is the newest
   in-catalog listing for that silhouette, resolved live in
   inc/silhouette-tiles.php — a shopper picking a silhouette is making a
   visual decision, and six charcoal boxes containing only a name gave them
   nothing to decide on. */
.h4yf-home-cat {
	display: flex;
	flex-direction: column;
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
	overflow: hidden;
	color: var(--h4yf-ink);
	text-decoration: none;
	transition: border-color 0.15s ease, color 0.15s ease;
}

.h4yf-home-cat__img {
	display: block;
	aspect-ratio: 1 / 1;
	background: var(--h4yf-charcoal);
	overflow: hidden;
}

.h4yf-home-cat__img img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 380ms var(--h4yf-ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
}

.h4yf-home-cat__name {
	display: flex;
	align-items: center;
	justify-content: center;
	/* Keeps the whole tile over the 44px tap floor even when the image slot is
	   absent, and keeps the six names on one optical baseline. */
	min-height: 48px;
	padding: 10px 8px;
	text-align: center;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(15px, 1vw + 12px, 19px);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	line-height: 1.15;
}

/* A category with no resolvable photo keeps the old name-only treatment rather
   than rendering an empty frame. */
.h4yf-home-cat--noimg .h4yf-home-cat__name {
	min-height: 72px;
}

.h4yf-home-cat:hover,
.h4yf-home-cat:focus-visible {
	border-color: var(--h4yf-hover);
	color: var(--h4yf-ink);
}

.h4yf-home-cat:hover .h4yf-home-cat__img img {
	transform: scale(1.04);
}

@media (prefers-reduced-motion: reduce) {
	.h4yf-home-cat__img img,
	.h4yf-home-cat:hover .h4yf-home-cat__img img {
		transition: none;
		transform: none;
	}
}

/* ---- Vault CTA band (objective #2) — accent line, NOT a red bar ---- */
.h4yf-home-vault {
	margin: clamp(48px, 9vw, 88px) 0 0;
	padding: clamp(40px, 8vw, 72px) 16px;
	text-align: center;
	/* D16: continuous wash shows through — accent hairline only, no boxed bg. */
	background: transparent;
	border-top: 2px solid var(--h4yf-crimson);
}

.h4yf-home-vault__inner {
	max-width: 620px;
	margin: 0 auto;
}

/* [FIXED 2026-08-05, Josh: crimson side eyebrow, consistent throughout.] Same
   ink-text + crimson-dash device as .h4yf-pw-hero__kicker. */
.h4yf-home-vault__kicker {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	margin: 0 0 8px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.h4yf-home-vault__kicker::before {
	content: "";
	flex: 0 0 auto;
	width: 20px;
	height: 3px;
	background: var(--h4yf-crimson);
}

.h4yf-home-vault__title {
	margin: 0 0 10px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.h4yf-home-vault__sub {
	margin: 0 0 24px;
	color: #cfcfcf;
	font-family: var(--h4yf-body);
	font-size: clamp(14px, 3.4vw, 16px);
}

/* ---- Watch the breakdowns (lightweight; no slow server-side feed) ---- */
.h4yf-home-watch__copy {
	margin: 0 0 18px;
	color: #cfcfcf;
	font-family: var(--h4yf-body);
	font-size: clamp(14px, 3.4vw, 16px);
	max-width: 640px;
}

/* ---- Reviews band ---- */
/* [REBUILT 2026-08-20, Josh: "as prominent as other content elements on site,
   is uniform in text size/color/style".]

   The section used to opt OUT of the homepage's own frame: its own padding, its
   own centred text, its own hairline top border, and a 12px tracked kicker
   where every neighbouring section has an `h2.h4yf-home-section__title`. The
   page's strongest trust asset was the smallest heading on it. It is a
   `.h4yf-home-section` now and inherits the frame — max-width, rhythm, head
   layout — so "uniform" is structural rather than a set of matched values that
   drift apart on the next edit.

   The crimson hairline above it stays: it is the one thing the old treatment
   got right, separating buyer voice from the Guarantee panel above. */
.h4yf-home-reviews {
	margin-top: clamp(40px, 8vw, 72px);
	border-top: 1px solid rgba(196, 30, 30, 0.18);
	padding-bottom: clamp(8px, 2vw, 16px);
}

/* Shared by every section that carries one — Featured Sneakers had this class
   in its markup since D18 with no rule behind it, so its subhead rendered at
   Astra's paragraph default. One rule, both sections, and the next one too. */
.h4yf-home-section__subhead {
	margin: 6px 0 0;
	color: var(--h4yf-body-color, #e2e2e2);
	font-family: var(--h4yf-body);
	font-weight: 500;
	font-size: clamp(13px, 0.9vw, 15px);
	line-height: 1.45;
	max-width: 46ch;
}

/* New Drops rail: WooCommerce [products] inherits the §CARDS + §FLAMES styling.
   Just give the shortcode grid a little breathing room inside the section. */
.h4yf-home-drops .woocommerce {
	margin: 0;
}

/* ==================================================================
   DROPS CENTER + PICKUP WALL (canon structure, 0.4.0)
   Charcoal surfaces, crimson = CTAs/accents only.
   ================================================================== */

/* --- shared page hero --- */
.h4yf-skin .h4yf-pw-hero { background: var(--h4yf-charcoal); text-align: center; padding: 72px 24px 40px; }
/* [FIXED 2026-08-05, Josh: "crimson side eyebrow ... consistent throughout."]
   Was plain ink, no crimson mark at all — every other kicker on the site
   either has crimson text or the `::before` dash device below (matches
   `.h4yf-mosaic .h4yf-tile__kicker`, same "crimson side eyebrow" directive).
   Ink text kept (not crimson) — D22 already names crimson-as-text a failing
   AA exception; the dash is the accessible way to add the mark. */
.h4yf-skin .h4yf-pw-hero__kicker { display: inline-flex; align-items: center; gap: 9px; color: var(--h4yf-ink); font-family: var(--h4yf-body); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; font-size: 14px; margin: 0 0 10px; }
.h4yf-skin .h4yf-pw-hero__kicker::before { content: ""; flex: 0 0 auto; width: 20px; height: 3px; background: var(--h4yf-crimson); }
.h4yf-skin .h4yf-pw-hero__title { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 400; font-size: var(--h4yf-fs-h1); line-height: 1.05; margin: 0 0 12px; text-transform: uppercase; }
.h4yf-skin .h4yf-pw-hero__sub { color: #9a9a9a; font-family: var(--h4yf-body); font-weight: 600; font-size: 17px; margin: 0; }

/* --- proof stats ---
   [ALIGNED 2026-08-11, Josh: "match the style/header-sub-text body alignment
   with the rest of the site".] Was a centre-justified flex row with no
   max-width: the four tiles clumped ~700px wide in the middle of a 1235px
   viewport while every section below them starts at the 1180 grid's left edge,
   so the page had two competing left margins. Now it IS the 1180 grid — same
   max-width, same 16px gutter, same left edge as .h4yf-home-section, and the
   tiles divide it evenly instead of sizing to their own text. Background stays
   charcoal, which is also the body background, so losing the full-bleed band
   changes nothing visually. --- */
.h4yf-skin .h4yf-pw-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 16px; max-width: 1180px; margin: 0 auto; background: var(--h4yf-charcoal); padding: 8px 16px 44px; }
.h4yf-skin .h4yf-pw-stat { background: var(--h4yf-charcoal-2); border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); padding: 18px 26px; min-width: 0; }
.h4yf-skin .h4yf-pw-stat b { display: block; font-family: var(--h4yf-display); font-weight: 400; font-size: var(--h4yf-fs-trust-stat); color: var(--h4yf-ink); line-height: 1; }
.h4yf-skin .h4yf-pw-stat span { display: block; font-family: var(--h4yf-body); color: #e2e2e2; font-weight: 600; font-size: var(--h4yf-fs-trust-label); margin-top: 6px; text-transform: uppercase; letter-spacing: .06em; }

/* --- drops center sub-nav (0.9.5) — Secured Heat is not in the WP menu, so
   this strip is the only in-page path to it. Tap floor matches
   .h4yf-home-section__link's (Sprint 6.6-fix P1-9): a 12px uppercase label is
   ~15-20px tall on its own and misses thumbs. --- */
.h4yf-skin .h4yf-dropsnav { display: flex; flex-wrap: wrap; gap: 8px; max-width: 1180px; margin: 0 auto; padding: 28px 16px 0; }
.h4yf-skin .h4yf-dropsnav__link { display: inline-flex; align-items: center; min-height: var(--h4yf-tap-floor, 44px); color: #9a9a9a; font-family: var(--h4yf-body); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .1em; text-decoration: none; border: 1px solid #3a3a3c; border-radius: 999px; padding: 0 18px; transition: border-color .2s ease, color .2s ease; }
.h4yf-skin .h4yf-dropsnav__link:hover,
.h4yf-skin .h4yf-dropsnav__link:focus-visible { color: var(--h4yf-ink); border-color: var(--h4yf-hover); }
.h4yf-skin .h4yf-dropsnav__link.is-current { color: var(--h4yf-ink); border-color: var(--h4yf-ink); }

/* --- radar (image quilt, #273) --- */
.h4yf-skin .h4yf-radar__tag { color: #9a9a9a; font-family: var(--h4yf-body); font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .1em; border: 1px solid #3a3a3c; border-radius: 999px; padding: 4px 12px; }
.h4yf-skin .h4yf-radar__tag--live { color: var(--h4yf-ink); border-color: var(--h4yf-crimson); }
.h4yf-skin .h4yf-radar__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }
.h4yf-skin .h4yf-radar-card { background: var(--h4yf-charcoal-2); border-radius: var(--pm-radius, 4px); padding: 22px; animation: pm-appear-down var(--pm-slow, 500ms) var(--pm-ease-enter, ease) backwards; overflow: hidden; }
/* Photo-led tiles (product attached): image is the tile, text is the caption —
   the 90%+ live-measured case (#273 pre-flight: drops-cat 21/21, catalog 99.8%
   carry a featured image). Padding moves off the outer card onto __body so the
   image runs full-bleed to the tile edge. */
.h4yf-skin .h4yf-radar-card--has-img { padding: 0; transition: box-shadow 200ms ease; }
.h4yf-skin .h4yf-radar-card--has-img:hover { box-shadow: var(--pm-ring, 0 0 0 .1rem rgba(250, 250, 250, .2)); }
.h4yf-skin .h4yf-radar-card__img { position: relative; display: block; aspect-ratio: var(--h4yf-plate); overflow: hidden; background: var(--h4yf-charcoal); }
.h4yf-skin .h4yf-radar-card__img img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--pm-med, 300ms) var(--pm-ease, ease); }
.h4yf-skin .h4yf-radar-card--has-img:hover .h4yf-radar-card__img img { transform: scale(1.05); }
.h4yf-skin .h4yf-radar-card__badge--onimg { position: absolute; top: 12px; left: 12px; margin-bottom: 0; }
.h4yf-skin .h4yf-radar-card--has-img .h4yf-radar-card__body { padding: 16px 18px 20px; }
/* The title link is a SECOND route to the same PDP the photo already links to,
   and as a bare inline <a> it measured 21.5px tall at 390px — under the 44px
   floor this project treats as binding (docs/brand/H4YF_THUMB_ZONE.md). Making
   it a flex block gives it the floor without changing the type or adding a
   visible box. Measured after: 44px on one-line titles, unchanged on two-line. */
.h4yf-skin .h4yf-radar-card__title a { display: flex; align-items: center; min-height: var(--h4yf-tap-floor, 44px); color: inherit; text-decoration: none; }
.h4yf-skin .h4yf-radar-card__title a:hover,
.h4yf-skin .h4yf-radar-card__title a:focus-visible { text-decoration: underline; }
/* No product yet (KicksDB shell, option-only row) — stays the original flat
   text card, no forced placeholder image (#273 constraint: unknown != missing). */
.h4yf-skin .h4yf-radar-card__badge { display: inline-block; background: var(--h4yf-crimson); color: var(--h4yf-ink); border: none; border-radius: var(--pm-radius, 4px); font-family: var(--h4yf-body); font-weight: 700; font-size: 11px; letter-spacing: .06em; padding: 4px 10px; text-transform: uppercase; margin-bottom: 12px; }
/* Drop type ("parking space") — sits beside the DROPPING SOON badge. Outlined,
   never a second crimson fill: canon reserves the fill for one badge per card. */
.h4yf-skin .h4yf-radar-card__type { display: inline-block; margin: 0 0 12px 8px; padding: 4px 10px; border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); color: #9a9a9a; font-family: var(--h4yf-body); font-weight: 700; font-size: 11px; letter-spacing: .06em; text-transform: uppercase; }
.h4yf-skin .h4yf-radar-card__title { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 800; font-size: 18px; margin: 0 0 6px; }
.h4yf-skin .h4yf-radar-card__meta { color: #9a9a9a; font-size: 14px; margin: 0 0 8px; }
.h4yf-skin .h4yf-radar-card__hype { color: #f0f0f0; font-size: 14px; font-weight: 500; line-height: 1.5; margin: 0 0 10px; }
.h4yf-skin .h4yf-radar-card__grade { color: #e2e2e2; font-size: 13px; margin: 0 0 14px; text-transform: uppercase; letter-spacing: .05em; }
.h4yf-skin .h4yf-radar-card .h4yf-btn { width: 100%; text-align: center; min-height: var(--h4yf-tap-floor, 44px); }

/* --- secured heat (quilt sizing pass over WC's own product-loop markup,
   scoped to the Drops Center routes only — never touches /shop/) --- */
.h4yf-skin .h4yf-dropsctr .products.columns-4 li.product { background: var(--h4yf-charcoal-2); border-radius: var(--pm-radius, 4px); overflow: hidden; transition: box-shadow 200ms ease; }
.h4yf-skin .h4yf-dropsctr .products.columns-4 li.product:hover { box-shadow: var(--pm-ring, 0 0 0 .1rem rgba(250, 250, 250, .2)); }
.h4yf-skin .h4yf-dropsctr .products.columns-4 li.product a img { aspect-ratio: var(--h4yf-plate); object-fit: cover; transition: transform var(--pm-med, 300ms) var(--pm-ease, ease); }
.h4yf-skin .h4yf-dropsctr .products.columns-4 li.product:hover img { transform: scale(1.05); }
.h4yf-skin .h4yf-dropsctr .products.columns-4 li.product .h4yf-score-block--compact { padding: 0 12px; }

/* --- archive (image quilt, #273; MONTH buckets not weekly ones, Josh
   2026-08-01 — 16 weekly headings held 28 products live, nine of them over
   one or two cards, which is a list wearing a grid's clothes) --- */
.h4yf-skin .h4yf-archive__month { margin-bottom: 36px; }
.h4yf-skin .h4yf-archive__date { display: flex; align-items: baseline; gap: 10px; color: #9a9a9a; font-weight: 700; font-size: 13px; text-transform: uppercase; letter-spacing: .12em; border-bottom: 1px solid #3a3a3c; padding-bottom: 8px; margin: 0 0 16px; }
/* Pair count — tells you how heavy the month was before you scroll it. */
.h4yf-skin .h4yf-archive__count { color: #6e6e73; font-weight: 700; font-size: 12px; letter-spacing: .08em; }
.h4yf-skin .h4yf-archive__count::before { content: "\00b7 "; }
.h4yf-skin .h4yf-archive__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; }
.h4yf-skin .h4yf-drop-card { background: var(--h4yf-charcoal-2); border-radius: var(--pm-radius, 4px); overflow: hidden; transition: box-shadow 200ms ease; }
.h4yf-skin .h4yf-drop-card:hover { box-shadow: var(--pm-ring, 0 0 0 .1rem rgba(250, 250, 250, .2)); }
.h4yf-skin .h4yf-drop-card__link { display: block; color: inherit; text-decoration: none; }
.h4yf-skin .h4yf-drop-card__img { position: relative; aspect-ratio: var(--h4yf-plate); overflow: hidden; background: var(--h4yf-charcoal); }
.h4yf-skin .h4yf-drop-card__img img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--pm-med, 300ms) var(--pm-ease, ease); }
/* HEAT row sits under the title, never on the photo (Josh QA 2026-10-01 —
   the #273 scrim overlay covered the shoe). No-photo cards simply omit the
   image frame (h4yf_render_drop_card()). */
.h4yf-skin .h4yf-drop-card .h4yf-score-block--compact { padding: 0 14px 4px; }
.h4yf-skin .h4yf-drop-card:hover .h4yf-drop-card__img img { transform: scale(1.05); }
.h4yf-skin .h4yf-drop-card__title { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 700; font-size: 14px; line-height: 1.35; margin: 0; padding: 12px 14px 4px; }
.h4yf-skin .h4yf-drop-card__meta { display: flex; justify-content: space-between; align-items: center; padding: 4px 14px 14px; margin: 0; }
.h4yf-skin .h4yf-drop-card__status { color: #9a9a9a; font-weight: 700; font-size: 11px; text-transform: uppercase; letter-spacing: .08em; }
.h4yf-skin .h4yf-drop-card__price { color: var(--h4yf-ink); font-weight: 800; font-size: 14px; }
/* Teaser only now (#273 — full Curator's Take moved to the PDP,
   h4yf_render_pdp_curators_take()). Plain paragraph, not a blockquote/cite:
   a tease isn't a quoted payoff.
   The crimson side-stripe is BRAND CANON and deliberate (Josh 2026-08-01) —
   it marks Billy's voice wherever it appears, which is exactly the kind of
   meaning a generic "no side-stripe borders" design rule can't see. Do not
   remove it as a design-system violation; it is the system here. */
.h4yf-skin .h4yf-drop-card__take { color: #b8b8b8; font-size: 13px; font-weight: 500; line-height: 1.4; margin: 0 14px 14px; padding: 2px 0 2px 10px; border-left: 2px solid var(--h4yf-crimson); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

/* --- drops center: secured heat rail (owned tile, #289 — replaces Astra's
   raw shop-loop wrap markup; same shape as the Archive quilt card above.
   No sizing needed for the CTA: it always renders as .h4yf-vault-alert-btn
   (mu-plugins/h4yf-upcoming-guard.php swaps every drops-tagged product's
   add-to-cart link), which already carries min-height:48px site-wide. */
.h4yf-skin .h4yf-heat__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; }
.h4yf-skin .h4yf-heat-card { background: var(--h4yf-charcoal-2); border-radius: var(--pm-radius, 4px); overflow: hidden; transition: box-shadow 200ms ease; }
.h4yf-skin .h4yf-heat-card:hover { box-shadow: var(--pm-ring, 0 0 0 .1rem rgba(250, 250, 250, .2)); }
.h4yf-skin .h4yf-heat-card__link { display: block; color: inherit; text-decoration: none; }
.h4yf-skin .h4yf-heat-card__img { aspect-ratio: var(--h4yf-plate); overflow: hidden; background: var(--h4yf-charcoal); }
.h4yf-skin .h4yf-heat-card__img img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--pm-med, 300ms) var(--pm-ease, ease); }
.h4yf-skin .h4yf-heat-card:hover .h4yf-heat-card__img img { transform: scale(1.05); }
.h4yf-skin .h4yf-heat-card__title { color: var(--h4yf-ink); font-weight: 700; font-size: 14px; line-height: 1.35; margin: 0; padding: 12px 14px 4px; }
.h4yf-skin .h4yf-heat-card__meta { padding: 0 14px; margin: 0; }
.h4yf-skin .h4yf-heat-card__price { color: var(--h4yf-ink); font-weight: 800; font-size: 14px; }
.h4yf-skin .h4yf-heat-card .h4yf-vault-alert-btn { width: calc(100% - 28px); margin: 8px 14px 14px; }

/* --- pickup wall: grails rail — side-swipe carousel over the FULL ledger
   (Josh 2026-08-11). Horizontal scroll-snap, not a grid: the rail is ordered
   by price and now runs 140 rows deep, which as a wrapping grid would bury
   every other section on the page.

   Photo-less is the majority case here and always will be — the rail is
   sorted by price, the priciest sales are the oldest, and eBay's GetItem
   refuses deleted listings (measured 2026-08-11: 0 of the top 12 have a
   photo). So the type IS the image: the price is what "Verified Grails"
   actually claims, set at display scale. --- */
.h4yf-skin .h4yf-pw-grails__hint { color: #9a9a9a; font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .1em; }
.h4yf-skin .h4yf-pw-grails__rail { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(240px, 260px); gap: 20px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-left: 0; padding-bottom: 14px; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
.h4yf-skin .h4yf-grail-card { position: relative; scroll-snap-align: start; display: flex; flex-direction: column; background: var(--h4yf-charcoal-2); border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); overflow: hidden; animation: pm-appear-down var(--pm-slow, 500ms) var(--pm-ease-enter, ease) backwards; }
/* One height for every card in the rail whether or not it has a photo —
   grid-auto-flow stretches them anyway, and a mixed-height rail reads as
   breakage on a horizontal scroller far harder than it does in a grid. */
.h4yf-skin .h4yf-grail-card__img { aspect-ratio: var(--h4yf-plate); overflow: hidden; background: var(--h4yf-charcoal); }
.h4yf-skin .h4yf-grail-card__img img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--pm-med, 300ms) var(--pm-ease, ease); }
.h4yf-skin .h4yf-grail-card--has-img:hover .h4yf-grail-card__img img { transform: scale(1.05); }
.h4yf-skin .h4yf-grail-card__body { display: flex; flex-direction: column; flex: 1 1 auto; padding: 16px 18px 18px; }
.h4yf-skin .h4yf-grail-card--no-img .h4yf-grail-card__body { padding-top: 22px; }
.h4yf-skin .h4yf-shield { position: absolute; top: 14px; right: 14px; background: var(--h4yf-crimson); color: #fff; font-weight: 800; font-size: 11px; letter-spacing: .05em; border-radius: 999px; padding: 5px 10px; z-index: 1; }
.h4yf-skin .h4yf-grail-card__title { color: var(--h4yf-ink); font-weight: 800; font-size: 16px; line-height: 1.3; margin: 0 0 10px; }
.h4yf-skin .h4yf-grail-card--no-img .h4yf-grail-card__title { padding-right: 64px; }
/* Oversized on every card now, not just the photo-less ones (Josh 2026-08-11) —
   the price is the proof, so it carries the same weight beside a photo as it
   does standing in for one. `margin-top: auto` bottom-anchors it so the rail
   reads as one baseline across cards with and without images. */
.h4yf-skin .h4yf-grail-card__price { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 400; font-size: clamp(38px, 5vw, 60px); line-height: 1; letter-spacing: -.02em; margin: auto 0 8px; }
.h4yf-skin .h4yf-grail-card__meta { color: #9a9a9a; font-size: 13px; margin: 0; }

/* --- pickup wall: rotation feed — 3-up grid of every placed sale
   (Josh 2026-08-11, was a 72vh vertical scroll-snap column of 12 rows).
   Card geometry matches the drops/shop quilt: 4/5 image, charcoal-2 surface,
   1180 grid. Photo-less rows keep the same footprint on a typographic tile
   rather than collapsing, so rows stay flush across the grid. --- */
.h4yf-skin .h4yf-pw-feed__hint { color: #9a9a9a; font-weight: 700; font-size: 12px; text-transform: uppercase; letter-spacing: .1em; }
.h4yf-skin .h4yf-pw-feed__grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.h4yf-skin .h4yf-pw-card { display: flex; flex-direction: column; background: var(--h4yf-charcoal-2); border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); overflow: hidden; }
.h4yf-skin .h4yf-pw-card__visual { aspect-ratio: var(--h4yf-plate); overflow: hidden; background: linear-gradient(145deg, #232325, #151517); }
.h4yf-skin .h4yf-pw-card__visual img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform var(--pm-med, 300ms) var(--pm-ease, ease); }
.h4yf-skin .h4yf-pw-card--has-img:hover .h4yf-pw-card__visual img { transform: scale(1.05); }
.h4yf-skin .h4yf-pw-card__body { display: flex; flex-direction: column; flex: 1 1 auto; padding: 16px 18px 18px; }
.h4yf-skin .h4yf-pw-card--no-img .h4yf-pw-card__body { padding-top: 22px; }
.h4yf-skin .h4yf-pw-card__title { color: var(--h4yf-ink); font-weight: 700; font-size: 15px; line-height: 1.3; margin: 0 0 10px; }
.h4yf-skin .h4yf-pw-card__meta { display: flex; gap: 14px; align-items: baseline; margin: auto 0 10px; }
.h4yf-skin .h4yf-pw-card__price { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 400; font-size: clamp(30px, 3.4vw, 40px); line-height: 1; letter-spacing: -.02em; }
.h4yf-skin .h4yf-pw-card__auth { display: inline-block; align-self: flex-start; background: var(--h4yf-crimson); color: var(--h4yf-ink); border: none; border-radius: var(--pm-radius, 4px); font-family: var(--h4yf-body); font-weight: 700; font-size: 11px; letter-spacing: .04em; padding: 4px 9px; text-transform: uppercase; }
.h4yf-skin .h4yf-pw-card__auth--house { background: rgba(255, 255, 255, .06); color: #e2e2e2; border: 1px solid #3a3a3c; }

@media (max-width: 900px) {
	.h4yf-skin .h4yf-pw-feed__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
	.h4yf-skin .h4yf-pw-feed__grid { grid-template-columns: minmax(0, 1fr); }
	.h4yf-skin .h4yf-pw-grails__rail { grid-auto-columns: minmax(200px, 78vw); }
}

/* --- pickup wall: flex your cop portal --- */
.h4yf-skin .h4yf-pw-cop { background: var(--h4yf-charcoal); padding: 56px 24px 72px; }
.h4yf-skin .h4yf-pw-cop__inner { max-width: 640px; margin: 0 auto; text-align: center; }
/* [FIXED 2026-08-05, Josh: crimson side eyebrow, consistent throughout.] Same
   ink-text + crimson-dash device as .h4yf-pw-hero__kicker above. */
.h4yf-skin .h4yf-pw-cop__kicker { display: inline-flex; align-items: center; gap: 9px; color: var(--h4yf-ink); font-family: var(--h4yf-body); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; font-size: 13px; margin: 0 0 8px; }
.h4yf-skin .h4yf-pw-cop__kicker::before { content: ""; flex: 0 0 auto; width: 20px; height: 3px; background: var(--h4yf-crimson); }
.h4yf-skin .h4yf-pw-cop__title { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 400; font-size: var(--h4yf-fs-h2); text-transform: uppercase; margin: 0 0 10px; }
.h4yf-skin .h4yf-pw-cop__sub { color: #9a9a9a; font-family: var(--h4yf-body); font-size: 15px; margin: 0 0 24px; }
.h4yf-skin .h4yf-cop-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
@media (max-width: 560px) { .h4yf-skin .h4yf-cop-form__row { grid-template-columns: 1fr; } }
.h4yf-skin .h4yf-cop-form label { display: block; text-align: left; color: #e2e2e2; font-family: var(--h4yf-body); font-weight: 600; font-size: 13px; }
.h4yf-skin .h4yf-cop-form input { width: 100%; margin-top: 4px; background: var(--h4yf-charcoal-2); border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); color: var(--h4yf-ink); font-family: var(--h4yf-body); padding: 10px 12px; font-size: 14px; }
.h4yf-skin .h4yf-cop-form input:focus { outline: none; border-color: var(--h4yf-bball); }
.h4yf-skin .h4yf-cop-form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; }
.h4yf-skin .h4yf-cop-form .h4yf-btn { margin-top: 8px; }
.h4yf-skin .h4yf-pw-cop__done { color: #e2e2e2; font-weight: 700; margin-top: 16px; }

/* Portal additions (2026-08-01): drop picker + the proof-required note. Select is
   styled off the same rule set as the inputs so the row reads as one control
   group rather than a stock browser dropdown dropped into a dark form. */
.h4yf-skin .h4yf-cop-form__row--single { grid-template-columns: 1fr; }
.h4yf-skin .h4yf-cop-form select { width: 100%; margin-top: 4px; background: var(--h4yf-charcoal-2); border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); color: var(--h4yf-ink); font-family: var(--h4yf-body); padding: 10px 12px; font-size: 14px; }
.h4yf-skin .h4yf-cop-form select:focus { outline: none; border-color: var(--h4yf-bball); }
.h4yf-skin .h4yf-cop-form__note { color: #9a9a9a; font-family: var(--h4yf-body); font-size: 13px; margin: 4px 0 0; }

/* --- secured heat: empty state + "request a pair" (2026-08-03) ---
   Secured Heat is a manually-converted subset of Drops, so empty is a normal
   recurring state, not an error — it gets real copy and a way forward instead
   of the section silently disappearing. */
.h4yf-skin .h4yf-heat-empty { background: var(--h4yf-charcoal-2); border: 1px dashed #3a3a3c; border-radius: var(--pm-radius, 4px); padding: 40px 24px; text-align: center; }
.h4yf-skin .h4yf-heat-empty__title { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 400; font-size: var(--h4yf-fs-h3, 22px); text-transform: uppercase; margin: 0 0 8px; }
.h4yf-skin .h4yf-heat-empty__sub { color: #9a9a9a; font-family: var(--h4yf-body); font-size: 15px; line-height: 1.5; max-width: 52ch; margin: 0 auto 20px; }

/* Request form reuses the cop-portal form's control styling wholesale — same
   dark-field treatment, same 2-up rows collapsing at 560px. Only the shell
   differs, so only the shell is redeclared here. */
.h4yf-skin .h4yf-req { background: var(--h4yf-charcoal); padding: 56px 24px 72px; }
.h4yf-skin .h4yf-req__inner { max-width: 640px; margin: 0 auto; text-align: center; }
/* [FIXED 2026-08-05, Josh: crimson side eyebrow, consistent throughout.] Same
   ink-text + crimson-dash device as .h4yf-pw-hero__kicker above. */
.h4yf-skin .h4yf-req__kicker { display: inline-flex; align-items: center; gap: 9px; color: var(--h4yf-ink); font-family: var(--h4yf-body); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; font-size: 13px; margin: 0 0 8px; }
.h4yf-skin .h4yf-req__kicker::before { content: ""; flex: 0 0 auto; width: 20px; height: 3px; background: var(--h4yf-crimson); }
.h4yf-skin .h4yf-req__title { color: var(--h4yf-ink); font-family: var(--h4yf-display); font-weight: 400; font-size: var(--h4yf-fs-h2); text-transform: uppercase; margin: 0 0 10px; }
.h4yf-skin .h4yf-req__sub { color: #9a9a9a; font-family: var(--h4yf-body); font-size: 15px; margin: 0 0 24px; }
.h4yf-skin .h4yf-req-form__row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 12px; }
@media (max-width: 560px) { .h4yf-skin .h4yf-req-form__row { grid-template-columns: 1fr; } }
.h4yf-skin .h4yf-req-form__row--single { grid-template-columns: 1fr; }
.h4yf-skin .h4yf-req-form label { display: block; text-align: left; color: #e2e2e2; font-family: var(--h4yf-body); font-weight: 600; font-size: 13px; }
/* min-height, not just padding: 14px type + 10px padding + 1px border measures
   ~40px, under the binding 44px floor (docs/brand/H4YF_THUMB_ZONE.md). */
.h4yf-skin .h4yf-req-form input,
.h4yf-skin .h4yf-req-form select,
.h4yf-skin .h4yf-req-form textarea { width: 100%; margin-top: 4px; background: var(--h4yf-charcoal-2); border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); color: var(--h4yf-ink); font-family: var(--h4yf-body); padding: 10px 12px; font-size: 14px; min-height: var(--h4yf-tap-floor, 44px); }
.h4yf-skin .h4yf-req-form textarea { resize: vertical; }
.h4yf-skin .h4yf-req-form input:focus,
.h4yf-skin .h4yf-req-form select:focus,
.h4yf-skin .h4yf-req-form textarea:focus { outline: none; border-color: var(--h4yf-bball); }
.h4yf-skin .h4yf-req-form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; }
/* TEAM opt-in (#419). Overrides the form's blanket `label { display: block }` so the
   box sits beside its text, and carries the 44px tap floor itself — a bare checkbox
   renders ~13-16px and the label is the whole hit area. */
.h4yf-skin .h4yf-req-form__optin { display: flex; align-items: center; gap: 10px; min-height: 44px; font-weight: 400; cursor: pointer; }
.h4yf-skin .h4yf-req-form__optin input[type="checkbox"] { width: 20px; height: 20px; flex: 0 0 auto; margin: 0; accent-color: var(--h4yf-crimson); cursor: pointer; }
.h4yf-skin .h4yf-req-form__note { color: #9a9a9a; font-family: var(--h4yf-body); font-size: 13px; margin: 4px 0 0; }
.h4yf-skin .h4yf-req-form .h4yf-btn { margin-top: 8px; }
.h4yf-skin .h4yf-req__done { color: #e2e2e2; font-weight: 700; margin-top: 16px; }

/* Shop archive tabs (#563) — "Shop The Heat" (the product grid) vs "Plug
   Finds Your Pair" (the request form). No-JS fallback: both panels just
   stack in document order, tab buttons become inert-looking but harmless. */
/* Two tab labels ("Shop The Heat" / "Plug Finds Your Pair") measure 384px of
   flex: 0 0 auto buttons in a 375px viewport with no wrap (#750 P1-6) — scroll
   the row instead of letting it overflow the frame, with a right-edge fade so
   the cut-off is legible as "more" rather than a clipped button. */
.h4yf-skin .h4yf-shop-tabs { display: flex; gap: 8px; max-width: 1200px; margin: 0 auto 24px; padding: 0 24px; overflow-x: auto; scrollbar-width: none; -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 24px), transparent); }
.h4yf-skin .h4yf-shop-tabs::-webkit-scrollbar { display: none; }
.h4yf-skin .h4yf-shop-tabs__btn { flex: 0 0 auto; min-height: var(--h4yf-tap-floor, 44px); padding: 0 20px; background: transparent; border: 1px solid #3a3a3c; border-radius: var(--pm-radius, 4px); color: #9a9a9a; font-family: var(--h4yf-body); font-weight: 700; letter-spacing: .04em; text-transform: uppercase; font-size: 13px; cursor: pointer; }
.h4yf-skin .h4yf-shop-tabs__btn.is-active { color: var(--h4yf-ink); border-color: var(--h4yf-bball); }
.h4yf-skin .h4yf-shop-tabs__btn:focus-visible { outline: 2px solid var(--h4yf-bball); outline-offset: 2px; }
/* BOTH panels are gated, not just the hunt one. Hiding only the hunt panel
   left the product grid on screen underneath it — the tab button lit up and
   nothing swapped (live 2026-08-25).
   No-JS still works: the server renders `is-active` on the heat panel, so
   the grid — the primary path — shows even if skin.js never runs. `.is-active`
   is on the UCSS allowlist (inc/ucss-guard.php), without which LiteSpeed
   strips the rule that SHOWS a panel and keeps the one that hides it. */
.h4yf-skin .h4yf-shop-panel { display: none; }
.h4yf-skin .h4yf-shop-panel.is-active { display: block; }
.h4yf-skin .h4yf-shop-panel--hunt { max-width: 1200px; margin: 0 auto; padding: 0 24px 56px; }
/* LEFT-ALIGNED, not centred: the section title carries `.h4yf-rule`, the
   crimson side stripe Josh asked for on main section headings, and that rule
   only reads as a mark on the heading when the block is left-aligned (see the
   §CRIMSON SIDE RULE note — "a centred section never gets a left rule it
   cannot align to"). Same head/subhead shape as Featured Sneakers on the
   homepage, so the two sections read as one system. */
.h4yf-skin .h4yf-hunt__intro { max-width: 760px; margin: 0 0 40px; }
.h4yf-skin .h4yf-hunt__lede { color: #9a9a9a; font-family: var(--h4yf-body); font-size: 15px; line-height: 1.6; margin: 10px 0 32px; }

/* --- cops of drops: a DESIGNATION inside The Rotation, not its own wall
   (Josh 2026-08-01). Community rows sit in the same scroll-snap feed as
   Billy's placements and are marked; only the marks are styled here. --- */
.h4yf-skin .h4yf-pw-card__auth--cop { background: rgba(255, 255, 255, .06); color: var(--h4yf-ink); border: 1px solid var(--h4yf-crimson); }
.h4yf-skin .h4yf-pw-card--cop .h4yf-pw-card__visual { background: linear-gradient(145deg, #2a2118, #151517); }
.h4yf-skin .h4yf-pw-card__by { display: inline-block; margin-left: 8px; color: #9a9a9a; font-family: var(--h4yf-body); font-size: 12px; font-weight: 600; }
/* Tap floor (Sprint 6.6-fix P1-9): a 12px inline link is ~15px tall on its own. */
/* Receipt links sat at 15.5px — a 12px inline <a> is its own text box and
   nothing else. Same treatment the __clip link already got in #280; this
   variant was simply missed. The --badge sibling is a <span>, not
   interactive, so it deliberately gets no floor. Live-measured 15.5 -> 44
   at 390px (#273). */
.h4yf-skin .h4yf-pw-card__receipt--link { display: inline-flex; align-items: center; min-height: var(--h4yf-tap-floor, 44px); }
.h4yf-skin .h4yf-pw-card__clip { display: inline-flex; align-items: center; min-height: var(--h4yf-tap-floor, 44px); margin-left: 10px; color: var(--h4yf-ink); font-family: var(--h4yf-body); font-weight: 700; font-size: 12px; letter-spacing: .06em; text-transform: uppercase; text-decoration: none; }
.h4yf-skin .h4yf-pw-card__clip:hover,
.h4yf-skin .h4yf-pw-card__clip:focus-visible { color: var(--h4yf-hover); text-decoration: underline; }

/* ------------------------------------------------------------------
   HEADING DISPLAY (0.6.0, Sprint 1.2) — D1 resolved 2026-07-08: Bebas Neue
   (display: H1/H2/H3, product titles, CTAs, stat callouts, uppercase-only)
   supersedes 0.4.1's Playfair Display. Single self-hosted weight (400) —
   never declare 600/700/900 on this family, the browser has nothing to
   match and would synth-bold a condensed face. text-transform: uppercase
   is CSS-driven per H4YF_TYPOGRAPHY_PLAN.md §5 (never author literal caps
   in the CMS — breaks screen-reader pronunciation of mixed-case content).
   ------------------------------------------------------------------ */
body.h4yf-skin h1,
body.h4yf-skin .site-title {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h1);
	line-height: 1.05;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

body.h4yf-skin h2 {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	line-height: 1.1;
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

body.h4yf-skin h3 {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	line-height: 1.2;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/* D1 scope is H1-H3 only — h4-h6 stay Montserrat (body/utility). */
body.h4yf-skin h4,
body.h4yf-skin h5,
body.h4yf-skin h6 {
	font-family: var(--h4yf-body);
	font-weight: 700;
}

/* Mobile menu button — crimson so it reads as a button (was transparent,
   invisible against charcoal header; users tapped the logo instead). */
/* [CHANGED 2026-08-04, impeccable polish pass — VISIBLE BRAND CHANGE, easy to
   revert if Josh disagrees: restore `background: var(--h4yf-crimson)` and the
   `#A51919` hover.]
   This was a solid crimson 48x48 fill. PRODUCT.md's design principles say
   "crimson is a scalpel, not a paint bucket — reserved strictly for CTAs/
   accents", and a menu toggle is chrome, not a call to action. The cost was
   measurable rather than theoretical: at 390x844 the first fold carried TWO
   crimson fills — this toggle and `SHOP THE HEAT` — so the page's one real CTA
   competed with a navigation affordance for the same signal.
   Ghost instead, matching `.h4yf-btn--ghost` and the gallery zoom trigger: the
   hairline reads as chrome, the ink bars stay legible on charcoal, and hover/
   focus goes basketball orange per D3 rather than a second red. Tap area is
   unchanged at 48x48, above the 44px floor. */
.h4yf-nav-toggle {
	background: transparent;
	color: var(--h4yf-ink);
	min-width: 48px;
	min-height: 48px;
	border: 1px solid var(--h4yf-border);
	transition: border-color 150ms ease, background 150ms ease;
}

.h4yf-nav-toggle:hover,
.h4yf-nav-toggle:focus-visible {
	background: var(--h4yf-charcoal-2);
	border-color: var(--h4yf-bball);
}

/* 0.6.0 — Montserrat is the body/utility sans; Bebas Neue (display) is
   scoped to headings/CTAs/stat callouts only, never body text (D1). */
body.h4yf-skin {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
}

/* 0.4.3 — kill the admin-bar search (snippet 902's global submit-button
   rules paint it as a floating red SEARCH pill in every admin screenshot). */
#wpadminbar #adminbarsearch {
	display: none !important;
}

/* ================================================================== */
/* §REVIEWS — page-reviews.php + homepage featured quote              */
/* ================================================================== */

/* Reviews page header */
.h4yf-reviews-header {
	padding: clamp(48px, 11vw, 104px) 16px clamp(40px, 8vw, 72px);
	text-align: center;
	background: var(--h4yf-charcoal);
}

.h4yf-reviews-header__inner {
	max-width: 760px;
	margin: 0 auto;
}

.h4yf-reviews-header__kicker {
	margin: 0 0 8px;
	color: var(--h4yf-crimson);
	font-family: var(--h4yf-display);
	font-weight: 800;
	font-size: 14px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.h4yf-reviews-header__title {
	margin: 0 0 14px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 900;
	font-size: clamp(2rem, 7.5vw, 3.6rem);
	line-height: 1.04;
	letter-spacing: 0.01em;
	text-transform: uppercase;
}

.h4yf-reviews-header__sub {
	margin: 0;
	color: var(--h4yf-gray);
	font-size: clamp(14px, 3.4vw, 16px);
	line-height: 1.6;
	max-width: 640px;
	margin-left: auto;
	margin-right: auto;
}

/* Reviews metrics (eBay / StockX / Authentication) */
.h4yf-reviews-metrics {
	background: var(--h4yf-charcoal-2);
	border-top: 1px solid var(--h4yf-border);
	border-bottom: 1px solid var(--h4yf-border);
	padding: clamp(24px, 5vw, 48px) 16px;
}

.h4yf-reviews-metrics__inner {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: clamp(20px, 4vw, 40px);
	max-width: 1100px;
	margin: 0 auto;
}

.h4yf-reviews-metric {
	flex: 0 1 auto;
	min-width: 210px;
	text-align: center;
	padding: 20px;
	background: var(--h4yf-charcoal);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
}

.h4yf-reviews-metric__name {
	color: var(--h4yf-gray);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	font-size: 12px;
	margin-bottom: 8px;
}

.h4yf-reviews-metric__score {
	color: var(--h4yf-crimson);
	font-weight: 800;
	font-size: 40px;
	line-height: 1;
	margin-bottom: 4px;
}

.h4yf-reviews-metric__badge {
	color: var(--h4yf-ink);
	font-weight: 800;
	font-size: 22px;
	line-height: 1.1;
	margin-bottom: 6px;
}

.h4yf-reviews-metric__label {
	color: var(--h4yf-ink);
	font-weight: 800;
	font-size: 14px;
	margin-bottom: 6px;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.h4yf-reviews-metric__sub {
	color: var(--h4yf-gray);
	font-weight: 600;
	font-size: 12px;
	line-height: 1.4;
	margin-bottom: 12px;
}

.h4yf-reviews-metric__link {
	display: inline-block;
	color: var(--h4yf-crimson);
	font-weight: 700;
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	text-decoration: none;
	border-bottom: 2px solid var(--h4yf-crimson);
	padding-bottom: 2px;
	margin-top: 12px;
	transition: opacity 0.2s ease;
}

.h4yf-reviews-metric__link:hover {
	opacity: 0.8;
}

/* Reviews grid section */
.h4yf-reviews-grid-wrapper {
	max-width: 1180px;
	margin: 0 auto;
	padding: clamp(48px, 8vw, 72px) 16px;
}

.h4yf-reviews-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: 16px;
	margin-bottom: 40px;
}

@media (max-width: 768px) {
	.h4yf-reviews-grid {
		grid-template-columns: 1fr;
	}
}

.h4yf-reviews-card {
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
	padding: 20px;
	margin: 0;
	display: flex;
	flex-direction: column;
}

.h4yf-reviews-stars {
	color: var(--h4yf-crimson);
	font-size: 16px;
	letter-spacing: 2px;
	margin-bottom: 10px;
	line-height: 1;
}

.h4yf-reviews-quote {
	color: var(--h4yf-ink);
	font-weight: 600;
	font-size: 15px;
	line-height: 1.5;
	margin: 0 0 14px;
	flex: 1;
}

.h4yf-reviews-by {
	color: var(--h4yf-ink);
	font-weight: 700;
	font-size: 13px;
}

.h4yf-reviews-by span {
	color: var(--h4yf-gray);
	font-weight: 600;
}

.h4yf-reviews-item {
	color: var(--h4yf-gray);
	font-weight: 600;
	font-size: 12px;
	margin-top: 4px;
}

/* Reviews footer CTA */
.h4yf-reviews-footer {
	text-align: center;
	padding: 0 16px 64px;
	background: var(--h4yf-charcoal);
}

/* The independent-verification link (2026-08-20). Quiet by construction: it is
   a footnote on a claim, not the page's call to action — the button above it is
   now the on-site route, per Josh's "don't drive traffic away from site to
   ebay". Kept legible rather than hidden; a verification link nobody can find
   is not verification. */
.h4yf-reviews-footer__verify {
	margin: 14px 0 0;
	font-family: var(--h4yf-body);
	font-size: 12.5px;
}

.h4yf-reviews-footer__verify a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	min-height: var(--h4yf-tap-floor, 44px);
	color: var(--h4yf-gray);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.h4yf-reviews-footer__verify a:hover,
.h4yf-reviews-footer__verify a:focus-visible {
	color: var(--h4yf-ink);
}

/* Reviews mosaic tile */
.h4yf-tile--reviews {
	background: linear-gradient(135deg, var(--h4yf-charcoal-2) 0%, var(--h4yf-charcoal) 100%);
	border: 1px solid var(--h4yf-border);
}

/* Homepage featured reviews — three quotes read as a ROW, not a column.

   [ADDED 2026-08-04, impeccable polish pass] `.h4yf-home-reviews__strip` had no
   rule at all, so three `<blockquote>`s stacked full-width on Astra's default
   23.1px margin. Live-measured at 1440: the section was 726px tall to carry
   three one-line quotes, with ~160px of empty charcoal between each. As a grid
   it is 325px — a 401px cut, and the quotes finally compare against each other
   the way three testimonials are supposed to.
   `auto-fit`/`minmax` rather than breakpoints: 3-up on desktop, 1-up at 390px,
   nothing to maintain in between. */
.h4yf-home-reviews__strip {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: clamp(24px, 3vw, 40px);
	align-items: start;
	text-align: left;
	margin: 12px 0 32px;
}

/* The hairline is the container — no card. DESIGN.md's Flat-Floor rule puts the
   separation in hairlines rather than raised surfaces, and three bordered boxes
   here would be the one place on the page that disagrees with it. */
.h4yf-home-reviews__item {
	margin: 0;
	padding-top: 18px;
	border-top: 1px solid var(--h4yf-border);
	/* Astra ships a bare `blockquote { font-style: italic }`. EVERY self-hosted
	   face in assets/fonts.css is `font-style: normal` — there is no italic on
	   this site — so that rule was synthesizing an oblique on the quote AND its
	   attribution: 9 faux-italic elements on the homepage, all from this one
	   inherited declaration. Zeroed here at the root rather than patched per
	   child, and declared explicitly (not deleted) because slate's stale inline
	   CCSS block keeps supplying removed declarations. */
	font-style: normal;
}

.h4yf-home-reviews__quote {
	margin: 0 0 12px;
	color: var(--h4yf-ink);
	/* Was Bebas Neue at weight 600 in italic — a DOUBLE synthesis, since Bebas
	   self-hosts one face (400, normal): the browser faked both the bold and the
	   slant on a condensed display face, which is the ugliest form this defect
	   takes. Montserrat is also what this file's own comment 550 lines up
	   already requires ("Bebas Neue is banned from continuous text,
	   H4YF_TYPOGRAPHY_SPEC.md §1") — a testimonial is continuous text. 600 is a
	   real montserrat-600.woff2 face. The curly quotes carry the quote voice
	   that the fake italic was reaching for. */
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-style: normal;
	font-size: clamp(15px, 1.1vw, 17px);
	line-height: 1.55;
}

/* ATTRIBUTION (rebuilt 2026-08-20 — Josh: "adjust the appended usernames of the
   review quotes to not be as long, and to follow to the right or under the
   actual quote").

   Two facts, laid out as two facts. It was one 56-character run —
   "s****5, Verified Buyer. Air Griffey Max "Freshwater" Sz 12" — where the
   handle, a phrase repeated verbatim under all three quotes, and an eBay
   listing title with a stranger's shoe size on the end all shared a line and
   one colour. On a 390px screen that wrapped to three lines under a two-line
   quote.

   Now: a handle, and the pair, on one row that wraps to two only if it must.
   "Verified buyer" is gone from the row entirely — it was on every quote, which
   makes it wallpaper rather than a claim, and the section head above says it
   once where it counts. The size is stripped upstream in
   `h4yf_review_item_short()`.

   Baseline-aligned rather than stacked so the row reads as one line of credit
   under the quote — Josh's "to the right or under" — with the separator drawn
   in CSS so it disappears cleanly when a row has no pair to name. */
.h4yf-home-reviews__by {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0 8px;
	font-family: var(--h4yf-body);
	font-size: 12px;
	line-height: 1.5;
}

.h4yf-home-reviews__handle {
	color: var(--h4yf-ink);
	font-weight: 700;
	font-style: normal;
	letter-spacing: 0.04em;
}

/* The pair reads quieter than the person who bought it — the buyer is the
   proof, the shoe is the context. Muted also carries the separator, so the
   two never look like one string again. */
.h4yf-home-reviews__item-name {
	position: relative;
	color: var(--h4yf-gray);
	font-weight: 500;
	font-style: normal;
	padding-left: 9px;
}

.h4yf-home-reviews__item-name::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.15em;
	bottom: 0.15em;
	width: 1px;
	background: var(--h4yf-border);
}

/* When the row wraps, the divider would hang at the start of a new line. */
@media (max-width: 420px) {
	.h4yf-home-reviews__by {
		display: block;
	}

	.h4yf-home-reviews__item-name {
		display: block;
		margin-top: 2px;
		padding-left: 0;
	}

	.h4yf-home-reviews__item-name::before {
		display: none;
	}
}

/* ================================================================== */
/* §LEGACY PORT — Sprint 7.2-r2                                       */
/* Load-bearing rules carried over from the retiring legacy stack     */
/* (WPCode snippet 902 "Design System v8" + the h4yf_custom_css WP    */
/* option) before it is emptied at r3. Every block cites its origin.  */
/* Re-tokened to git-skin canon: crimson = CTAs/accents/hairlines     */
/* ONLY, orange (#D4571A) = hover/focus states only (D3), charcoal    */
/* base. !important kept only where Astra Customizer / WC core CSS    */
/* still loads and out-specifies us.                                  */
/* ================================================================== */

/* ---- Base + browser chrome (snippet 902 §2 / §22 / §T2) ---------- */
html {
	scroll-behavior: smooth;
	/* Anchor jumps clear the sticky .h4yf-header (56px + breathing room). */
	scroll-padding-top: 72px;
}

::-webkit-scrollbar { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: var(--h4yf-charcoal); }
::-webkit-scrollbar-thumb { background: #3a3a3c; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #5a5a5e; }

::selection {
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

/* ---- Charcoal canvas stack (902 §S + h4yf_custom_css iPhone-review
   "kill white bars" 2026-06-19pm). Astra Customizer paints html/body
   and the content wrappers light; without legacy CSS every uncovered
   strip + iOS overscroll flashes white. !important required — Astra's
   generated rules carry it.

   [FIXED 2026-08-30, #746.] This block used to paint the WRAPPERS charcoal
   too, and that is why the site read as flat no matter what the crimson wash
   at the top of this file was set to. Measured live on slate before the fix:
   `#page` is 1275 x 5630 and was `rgb(35, 35, 38)` opaque, sitting directly on
   top of `body`. The wash rendered correctly underneath it and was covered by
   a solid rectangle the size of the document — so PR #756's 2.7x alpha raise
   changed a number nobody could see, and every "make the gradient stronger"
   pass before it was working on the wrong layer.

   `html` keeps the opaque charcoal. That is the layer the white-bar fix
   actually needs: it is what paints the iOS overscroll gutter and any strip
   the document does not cover. The wrappers only need to stop being white,
   which `transparent !important` does just as well as charcoal — it still
   out-specifies Astra's generated light backgrounds, and what shows through
   is `body`'s charcoal-plus-crimson stack rather than a flat fill.

   Do not "simplify" the wrappers back to a colour. Charcoal there is
   indistinguishable from transparent on a charcoal page right up until the
   moment someone adds a wash to the body, at which point it silently
   deletes it. ------------------------------------------------------------ */
html,
body.h4yf-skin {
	background-color: var(--h4yf-charcoal) !important;
}

body.h4yf-skin #page,
body.h4yf-skin #content,
body.h4yf-skin .site-content,
body.h4yf-skin .ast-container,
body.h4yf-skin main.site-main,
body.h4yf-skin .ast-primary-content-area {
	background-color: transparent !important;
}

/* ---- Footer (902 §17) — Astra's footer markup still renders (only the
   header is takeover'd), so these selectors stay live. Crimson kept to a
   hairline accent, never a fill. --------------------------------------- */
body.h4yf-skin .site-footer,
body.h4yf-skin #colophon {
	background: var(--h4yf-charcoal) !important;
	border-top: 2px solid var(--h4yf-crimson);
	color: #9a9a9a;
}

body.h4yf-skin .footer-widget-area .widget-title,
body.h4yf-skin .ast-footer-widget-area .widget-title {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: 16px;
	color: var(--h4yf-ink);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	border-bottom: 1px solid #3a3a3c;
	padding-bottom: 8px;
}

body.h4yf-skin .footer-widget-area p,
body.h4yf-skin .footer-widget-area li,
body.h4yf-skin .ast-footer-widget-area p,
body.h4yf-skin .ast-footer-widget-area li,
body.h4yf-skin .ast-footer-copyright {
	color: #9a9a9a;
	font-size: 13px;
}

body.h4yf-skin .site-footer a,
body.h4yf-skin .ast-footer-widget-area a {
	color: #cfcfcf;
	transition: color 0.2s ease;
}

body.h4yf-skin .site-footer a:hover,
body.h4yf-skin .site-footer a:focus-visible {
	color: var(--h4yf-hover);
}

/* Footer verified-trust strip — text-only stopgap ported verbatim from
   h4yf_custom_css "PDP + FOOTER VERIFIED-TRUST STRIP" (DOM-real mu-plugin
   version remains the staged upgrade). */
body.h4yf-skin footer.site-footer::before {
	content: '\2713  TRUSTED SELLER SINCE 2016  \00b7  99.1% eBay POSITIVE  \00b7  650+ PAIRS PLACED  \00b7  EVERY PAIR 12-POINT AUTHENTICATED';
	display: block;
	text-align: center;
	background: var(--h4yf-charcoal);
	color: #e2e2e2;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.05em;
	line-height: 1.5;
	padding: 16px 20px;
}

/* ---- Global form fields (902 §14) — dark inputs sitewide (checkout,
   my-account, comments, coupon). Focus ring orange per D3. ------------- */
body.h4yf-skin input[type="text"],
body.h4yf-skin input[type="email"],
body.h4yf-skin input[type="tel"],
body.h4yf-skin input[type="password"],
body.h4yf-skin input[type="number"],
body.h4yf-skin input[type="search"],
body.h4yf-skin textarea,
body.h4yf-skin select {
	background: var(--h4yf-charcoal-2) !important;
	border: 1px solid #3a3a3c !important;
	border-radius: 4px;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-body);
	padding: 10px 14px;
	min-height: 44px;
}

/* A focused field's border IS its focus indicator, so it takes the basketball
   orange, not the hover carve-out (Josh 2026-08-01). The `outline: none` here
   only suppresses the pointer-focus ring; the `:focus-visible` blanket below
   is later in the cascade at equal specificity, so keyboard focus still gets
   the full outline + glow. */
body.h4yf-skin input:focus,
body.h4yf-skin textarea:focus,
body.h4yf-skin select:focus {
	border-color: var(--h4yf-bball) !important;
	outline: none;
}

body.h4yf-skin input::placeholder,
body.h4yf-skin textarea::placeholder {
	color: #9a9a9a;
	opacity: 1;
}

body.h4yf-skin form label {
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-size: 13px;
	color: #e2e2e2;
}

/* iOS focus-zoom fix (h4yf_custom_css 2026-06-27): Safari zooms the
   viewport when a focused input is <16px. Floor all inputs on phones. */
@media (max-width: 767px) {
	body.h4yf-skin input[type="text"],
	body.h4yf-skin input[type="email"],
	body.h4yf-skin input[type="tel"],
	body.h4yf-skin input[type="password"],
	body.h4yf-skin input[type="number"],
	body.h4yf-skin input[type="search"],
	body.h4yf-skin input[type="url"],
	body.h4yf-skin textarea,
	body.h4yf-skin select,
	body.h4yf-skin .wc-block-components-text-input input,
	body.h4yf-skin .wc-block-components-address-form input,
	body.h4yf-skin .h4yf-cop-form input {
		font-size: 16px !important;
	}
}

/* ---- Focus indicators (902 addendum §E — WCAG 2.1 AA) — sitewide
   keyboard-focus blanket beyond git-skin's per-component rules.
   Basketball-orange GLOW, not a flat hairline (Josh 2026-08-01): the ring
   is the accessible indicator and the halo is what makes it findable on a
   dark charcoal surface without hunting for a 2px line. The `outline` stays
   a real outline — box-shadow alone disappears under Windows High Contrast
   / forced-colors, where outlines are preserved. ------------------------ */
/* `[tabindex]` is here because Astra's accessibility block is now filtered off
   in functions.php, and three of the things it used to cover are not natively
   focusable — `.ast-woocommerce-product-gallery__image`, `.ast-single-variation`
   and `.ast-orders-table__cell` are divs that get a tabindex. Without this they
   would be the one class of control that came out of that change with NO focus
   indicator at all. */
body.h4yf-skin a:focus-visible,
body.h4yf-skin button:focus-visible,
body.h4yf-skin [role="button"]:focus-visible,
body.h4yf-skin [tabindex]:focus-visible,
body.h4yf-skin summary:focus-visible {
	outline: 2px solid var(--h4yf-bball);
	outline-offset: 3px;
	box-shadow: 0 0 0 5px var(--h4yf-bball-halo), 0 0 18px 2px var(--h4yf-bball-glow);
	border-radius: inherit;
	transition: box-shadow 160ms var(--h4yf-ease-out-expo, ease-out);
}

body.h4yf-skin input:focus-visible,
body.h4yf-skin select:focus-visible,
body.h4yf-skin textarea:focus-visible {
	outline: 2px solid var(--h4yf-bball);
	outline-offset: 1px;
	box-shadow: 0 0 0 4px var(--h4yf-bball-halo), 0 0 14px 1px var(--h4yf-bball-glow);
	transition: box-shadow 160ms var(--h4yf-ease-out-expo, ease-out);
}

/* The glow is an appearance change, not motion — it still must not animate
   for anyone who asked for less of it. */
@media (prefers-reduced-motion: reduce) {
	body.h4yf-skin a:focus-visible,
	body.h4yf-skin button:focus-visible,
	body.h4yf-skin [role="button"]:focus-visible,
	body.h4yf-skin summary:focus-visible,
	body.h4yf-skin input:focus-visible,
	body.h4yf-skin select:focus-visible,
	body.h4yf-skin textarea:focus-visible {
		transition: none;
	}
}

/* Forced-colors mode supplies its own system focus colour; a brand glow there
   is noise at best and an accessibility regression at worst. */
@media (forced-colors: active) {
	body.h4yf-skin a:focus-visible,
	body.h4yf-skin button:focus-visible,
	body.h4yf-skin [role="button"]:focus-visible,
	body.h4yf-skin summary:focus-visible,
	body.h4yf-skin input:focus-visible,
	body.h4yf-skin select:focus-visible,
	body.h4yf-skin textarea:focus-visible {
		box-shadow: none;
		outline: 2px solid CanvasText;
	}
}

/* ---- WC notices (902 §15) — left-border accent cards. --------------- */
body.h4yf-skin .woocommerce-message,
body.h4yf-skin .woocommerce-info,
body.h4yf-skin .woocommerce-notice--success {
	background: var(--h4yf-charcoal-2) !important;
	border-left: 4px solid var(--h4yf-crimson);
	border-top: 0;
	color: var(--h4yf-ink) !important;
	border-radius: 0 6px 6px 0;
}

body.h4yf-skin .woocommerce-error,
body.h4yf-skin .woocommerce-notice--error {
	background: rgba(196, 30, 30, 0.12) !important;
	border-left: 4px solid var(--h4yf-crimson);
	border-top: 0;
	color: var(--h4yf-ink) !important;
	border-radius: 0 6px 6px 0;
}

/* ---- Store notice (902 §4, re-designed) — legacy was a crimson
   full-width bar, which the canon now forbids (style.css: "Never a
   full-width bar"). Charcoal bar, crimson hairline accent instead. ----- */
body.h4yf-skin .woocommerce-store-notice,
body.h4yf-skin p.demo_store {
	background: var(--h4yf-charcoal-2) !important;
	color: var(--h4yf-ink) !important;
	border-bottom: 2px solid var(--h4yf-crimson);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
}

/* ---- My Account (902 §16) — dark account nav sidebar. --------------- */
body.h4yf-skin .woocommerce-MyAccount-navigation {
	background: var(--h4yf-charcoal-2);
	border: 1px solid #3a3a3c;
	border-radius: 6px;
	overflow: hidden;
}

body.h4yf-skin .woocommerce-MyAccount-navigation ul {
	list-style: none;
	padding: 0;
	margin: 0;
}

body.h4yf-skin .woocommerce-MyAccount-navigation ul li {
	border-bottom: 1px solid #3a3a3c;
}

body.h4yf-skin .woocommerce-MyAccount-navigation ul li a {
	display: block;
	padding: 12px 16px;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: #cfcfcf;
	text-decoration: none;
}

body.h4yf-skin .woocommerce-MyAccount-navigation ul li a:hover,
body.h4yf-skin .woocommerce-MyAccount-navigation ul li.is-active a {
	background: var(--h4yf-charcoal);
	color: var(--h4yf-ink);
}

/* [ADDED 2026-08-05, Josh punch list: confirm no default-blue text remains.]
   My Account order-detail / downloadable-product / address-edit links and
   every checkout-page link (return-to-cart, coupon toggle, terms/privacy)
   had no scoped rule anywhere — falling through to Astra's default
   `#046bd2` blue same as the already-fixed instances above. Ink + underline,
   matching `.h4yf-trust-stat__link`'s established pattern — not crimson
   (D22 already names crimson-as-text a failing AA exception; no new
   instances). `!important` for the same reason as that rule: it's what
   beats Astra's default anchor colour. */
body.h4yf-skin .woocommerce-MyAccount-content a,
body.h4yf-skin .woocommerce-checkout a {
	color: var(--h4yf-ink) !important;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
	text-decoration-color: var(--h4yf-border);
}

body.h4yf-skin .woocommerce-MyAccount-content a:hover,
body.h4yf-skin .woocommerce-MyAccount-content a:focus-visible,
body.h4yf-skin .woocommerce-checkout a:hover,
body.h4yf-skin .woocommerce-checkout a:focus-visible {
	color: var(--h4yf-ink) !important;
	text-decoration-color: var(--h4yf-bball);
}

/* ---- Classic cart/checkout/orders table (902 §13) — dark shop_table
   (also renders on my-account orders). Zebra-strip kill lives in
   premier.css. --------------------------------------------------------- */
body.h4yf-skin table.shop_table {
	background: var(--h4yf-charcoal-2) !important;
	border: 1px solid #3a3a3c;
	border-radius: 6px;
	color: var(--h4yf-ink);
}

body.h4yf-skin table.shop_table th {
	background: var(--h4yf-charcoal) !important;
	color: #cfcfcf;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

body.h4yf-skin table.shop_table td,
body.h4yf-skin table.cart .product-name a {
	color: var(--h4yf-ink);
}

body.h4yf-skin .cart_totals {
	background: var(--h4yf-charcoal-2);
	border: 1px solid #3a3a3c;
	border-radius: 6px;
	padding: 24px;
}

/* ---- WC Blocks cart + checkout dark theming (902 §11 / §12 / §20) —
   without this the blocks render light-mode on the charcoal site.
   Condensed from the legacy blocks; crimson only on the place-order CTA
   fill (a CTA) — everything else charcoal surfaces + ink text. --------- */
body.h4yf-skin .wp-block-woocommerce-cart,
body.h4yf-skin .wp-block-woocommerce-checkout {
	--wp--preset--color--contrast: var(--h4yf-ink);
	--wp--preset--color--base: var(--h4yf-charcoal);
	background: var(--h4yf-charcoal) !important;
	color: var(--h4yf-ink) !important;
}

body.h4yf-skin .wc-block-cart-item,
body.h4yf-skin .wc-block-cart__totals,
body.h4yf-skin .wc-block-components-totals-wrapper,
body.h4yf-skin .wc-block-components-order-summary,
body.h4yf-skin .wc-block-components-radio-control__option,
body.h4yf-skin .wc-block-components-sidebar {
	background: var(--h4yf-charcoal-2) !important;
	border-color: #3a3a3c !important;
	color: var(--h4yf-ink) !important;
}

body.h4yf-skin .wc-block-components-product-name,
body.h4yf-skin .wc-block-components-product-metadata,
body.h4yf-skin .wc-block-components-totals-item__label,
body.h4yf-skin .wc-block-components-totals-item__value,
body.h4yf-skin .wc-block-components-title,
body.h4yf-skin .wc-block-checkout__step-heading,
body.h4yf-skin .wc-block-components-checkout-step__heading,
body.h4yf-skin .wc-block-components-checkout-step__title,
body.h4yf-skin .wc-block-components-form label,
body.h4yf-skin .wc-block-components-radio-control__label {
	color: var(--h4yf-ink) !important;
}

body.h4yf-skin .wc-block-components-text-input input,
body.h4yf-skin .wc-block-components-address-form input,
body.h4yf-skin .wc-block-components-country-input select,
body.h4yf-skin .wc-block-components-state-input select,
body.h4yf-skin .wc-block-components-select select {
	background: var(--h4yf-charcoal) !important;
	border: 1px solid #3a3a3c !important;
	color: var(--h4yf-ink) !important;
}

/* THE WHITE BOX WITH WHITE TEXT (Josh 2026-08-20, live-measured on
   /checkout/ the same day: `#FAFAFA` on `#FFFFFF`, contrast ratio 1.04 — the
   Country/Region and State labels were literally invisible).

   ROOT CAUSE IS ONE MISSING LETTER. WooCommerce ships two class prefixes that
   differ by a single `s`: `wc-block-components-*` (everything above) and
   `wc-blocks-components-*` (the newer select control). Every dark-theming rule
   in this file was written against the singular, so the plural select kept
   WooCommerce's own light-mode `background: #fff` on its container — while the
   label inside it was being painted ink-white by
   `.wc-block-components-form label` two rules up, which matches any descendant
   `label` regardless of prefix. One rule reached the label, none reached the
   box behind it.

   Fixed at the container, not by darkening the label: the label is correct at
   ink, and the white field is the thing that does not belong on a charcoal
   checkout. Scanned the rest of the site for the same pattern the same day —
   /, /shop/, /culture/, /cart/, /my-account/, a PDP and a blog post — and this
   control was the only white-on-white left. */
body.h4yf-skin .wc-blocks-components-select,
body.h4yf-skin .wc-blocks-components-select__container {
	background: var(--h4yf-charcoal) !important;
	border-color: #3a3a3c !important;
	color: var(--h4yf-ink) !important;
}

body.h4yf-skin .wc-blocks-components-select__label,
body.h4yf-skin .wc-blocks-components-select__select {
	color: var(--h4yf-ink) !important;
}

body.h4yf-skin .wc-blocks-components-select__container:focus-within {
	border-color: var(--h4yf-bball) !important;
}

body.h4yf-skin .wc-block-components-radio-control__option:hover,
body.h4yf-skin .wc-block-components-radio-control__option--checked {
	border-color: var(--h4yf-hover) !important;
}

/* ---- Removing a line, cart + checkout (Josh 2026-08-20) --------------
   The control was already there and nobody could find it: WooCommerce's cart
   block renders remove as a bare 24x24 trash glyph with an aria-label and no
   visible text, tucked under the quantity stepper. It measured 24x24 live —
   below the 44px floor this file enforces everywhere else — and read as
   decoration rather than an action.

   `::after` carries the word because the button has NO text node at all, only
   the icon and an `aria-label`. Generated content is not announced over an
   aria-label, so a screen reader still hears "Remove {product} from cart"
   rather than a duplicate. */
body.h4yf-skin .wc-block-cart-item__remove-link {
	display: inline-flex !important;
	align-items: center;
	gap: 6px;
	min-height: var(--h4yf-tap-floor, 44px);
	padding: 4px 6px;
	color: var(--h4yf-muted) !important;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: none !important;
	background: transparent;
	border: 0;
	border-radius: 6px;
	transition: color 160ms var(--h4yf-ease-out-expo), background 160ms var(--h4yf-ease-out-expo);
}

body.h4yf-skin .wc-block-cart-item__remove-link::after {
	content: "Remove";
}

body.h4yf-skin .wc-block-cart-item__remove-link svg {
	width: 18px;
	height: 18px;
	fill: currentColor;
	flex: 0 0 auto;
}

/* Crimson on hover/focus: this is a destructive action and the one place in
   the cart where the alarm-light reading is the correct one. */
body.h4yf-skin .wc-block-cart-item__remove-link:hover,
body.h4yf-skin .wc-block-cart-item__remove-link:focus-visible {
	color: var(--h4yf-hover) !important;
	background: var(--h4yf-charcoal);
}

/* The checkout order summary is read-only by design — WooCommerce's block
   renders no per-line control there. Rather than rebuild that block, the
   summary heading carries a route back to the cart, which is where lines can
   be removed. Styled as a quiet text link, not a CTA: it must be findable
   without competing with Place Order. See inc/trust-strip.php for the markup. */
body.h4yf-skin .h4yf-checkout-editcart {
	display: flex;
	justify-content: flex-end;
	margin: 0 0 12px;
}

body.h4yf-skin .h4yf-checkout-editcart a {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: var(--h4yf-tap-floor, 44px);
	color: var(--h4yf-body-color, #e2e2e2);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 3px;
}

body.h4yf-skin .h4yf-checkout-editcart a:hover,
body.h4yf-skin .h4yf-checkout-editcart a:focus-visible {
	color: var(--h4yf-hover);
}

body.h4yf-skin .wc-block-components-radio-control input[type="radio"],
body.h4yf-skin .wc-block-components-checkbox input[type="checkbox"] {
	accent-color: var(--h4yf-crimson);
}

body.h4yf-skin .wc-block-components-checkout-place-order-button {
	background: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border: 0;
	border-radius: 6px;
	min-height: 56px;
	width: 100%;
}

body.h4yf-skin .wc-block-components-spinner {
	border-color: var(--h4yf-crimson) !important;
	border-top-color: transparent !important;
}

/* CLS reserve for WooPayments express-checkout buttons (h4yf_custom_css
   2026-06-27 Phase 5) — summary shifted ~60px when Apple/Google Pay
   injected. */
body.h4yf-skin .wc-block-components-express-payment,
#express-payment-method-woopayments,
.wc_payment_method_woopayments_express_checkout {
	min-height: 62px;
}

/* ---- PDP gaps (902 §9 + h4yf_custom_css Phase 5 contrast fixes) ----- */
body.h4yf-skin .woocommerce-product-gallery {
	background: var(--h4yf-charcoal-2);
	border-radius: 6px;
	overflow: hidden;
}

/* Astra's gallery navigation arrows (flex-prev/flex-next) are hardcoded to 0px height
   and flex-disabled; thumbnails provide sufficient navigation. Hide them. (#355) */
body.h4yf-skin .woocommerce-product-gallery .flex-prev,
body.h4yf-skin .woocommerce-product-gallery .flex-next {
	display: none !important;
}

body.h4yf-skin table.variations select,
body.h4yf-skin .variations select {
	background: var(--h4yf-charcoal-2) !important;
	border: 1px solid #3a3a3c !important;
	color: var(--h4yf-ink) !important;
	min-height: 48px;
	width: 100%;
}

/* WC tabs: white text; crimson bottom-border = active indicator only
   (crimson-as-text fails 4.5:1 — Phase 5 contrast batch). */
body.h4yf-skin .woocommerce-tabs .tabs {
	border-bottom: 1px solid #3a3a3c;
}

body.h4yf-skin .woocommerce-tabs .tabs li,
body.h4yf-skin .woocommerce-tabs .tabs li a {
	background: transparent !important;
	border: none !important;
	color: var(--h4yf-ink) !important;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

body.h4yf-skin .woocommerce-tabs .tabs li.active a {
	border-bottom: 3px solid var(--h4yf-crimson) !important;
}

body.h4yf-skin .woocommerce-tabs .woocommerce-Tabs-panel {
	background: transparent !important;
	border: none !important;
	color: #e2e2e2;
}

/* PDP category/tag meta links: white + crimson underline accent
   (h4yf_custom_css Phase 5 contrast batch — never crimson text). */
body.h4yf-skin .product_meta .posted_in a,
body.h4yf-skin .product_meta .tagged_as a,
body.h4yf-skin .single-product-category a {
	color: var(--h4yf-ink) !important;
	text-decoration: underline;
	text-decoration-color: var(--h4yf-crimson);
}

body.h4yf-skin .product_meta .posted_in a:hover,
body.h4yf-skin .product_meta .tagged_as a:hover {
	color: var(--h4yf-hover) !important;
}

/* [REMOVED 2026-07-31, .impeccable critique P2 "form.cart::before/::after
   trust strip — DROP": CSS `content:` for trust claims — unselectable,
   untranslatable, invisible to schema.org/AT, and stale ("350+" vs canon
   352). Payload already exists as real DOM in .h4yf-pdp-checklist
   (inc/pdp-conversion.php's before_add_to_cart_button block) — same
   eBay-stat + free-shipping lines, rendered as actual markup. */

/* WC star rating recolor (902 §F10) — crimson accent instead of WC gold. */
body.h4yf-skin .star-rating span::before,
body.h4yf-skin #respond p.stars a:hover,
body.h4yf-skin #respond p.stars a.active {
	color: var(--h4yf-hover) !important;
}

body.h4yf-skin .star-rating,
body.h4yf-skin #respond p.stars a {
	color: #46474c !important;
}

/* ---- Breadcrumbs (902 addendum §D + h4yf_custom_css Phase 5 contrast) */
body.h4yf-skin .rank-math-breadcrumb p,
body.h4yf-skin .rank-math-breadcrumb p a,
body.h4yf-skin .woocommerce-breadcrumb,
body.h4yf-skin .woocommerce-breadcrumb a {
	color: #9a9a9a !important;
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	text-decoration: none;
}

body.h4yf-skin .rank-math-breadcrumb p a:hover,
body.h4yf-skin .woocommerce-breadcrumb a:hover,
body.h4yf-skin .woocommerce-breadcrumb a:focus-visible {
	color: var(--h4yf-ink) !important;
	text-decoration: underline;
}

body.h4yf-skin .rank-math-breadcrumb p span:last-child:not(.separator) {
	color: var(--h4yf-ink) !important;
}

/* ---- Blog / content hub (902 §21) — archive + post styling on the dark
   canvas; heading rescue included (Astra's light-theme heading color is
   invisible on charcoal). Body links white + crimson underline, never
   crimson text (canon). ------------------------------------------------ */
body.h4yf-skin .entry-title,
body.h4yf-skin .entry-title a,
body.h4yf-skin .entry-content h1,
body.h4yf-skin .entry-content h2,
body.h4yf-skin .entry-content h3,
body.h4yf-skin .entry-content h4,
body.h4yf-skin .entry-content h5,
body.h4yf-skin .entry-content h6 {
	color: var(--h4yf-ink);
}

/* Gutenberg's own h2 default (`.wp-block-heading`) is a flat 42px, never
   themed by the rule above — only color was set. Measured live on /about/
   at 1121px: the site's OWN h2 token fluid-scales to 39.47px there
   (clamp math checks out against --h4yf-fs-h2), while the untouched
   Gutenberg block heading sits rigidly at 42px regardless of viewport —
   so the two H2 styles on the same page not only mismatch today, the gap
   widens further on mobile as the themed one keeps shrinking and this one
   doesn't. Also carried the theme's weight (400, not Gutenberg's 800 —
   Bebas Neue only ships one weight, so 800 was a synthesized fake-bold)
   and letter-spacing, matching every other themed h2 on the site
   (.h4yf-home-section__title etc). h3 was already correct at 400/26.589px
   — not touched. */
body.h4yf-skin .entry-content h2 {
	font-size: var(--h4yf-fs-h2);
	font-weight: 400;
	letter-spacing: 0.05em;
}

body.h4yf-skin .entry-title a:hover {
	color: var(--h4yf-hover);
}

body.h4yf-skin .entry-meta,
body.h4yf-skin .ast-post-meta,
body.h4yf-skin .posted-on,
body.h4yf-skin .byline {
	color: #9a9a9a !important;
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

body.h4yf-skin .entry-content,
body.h4yf-skin .single-content {
	color: #e2e2e2;
}

body.h4yf-skin .entry-content a:not(.wp-block-button__link):not(.button):not(.wp-element-button):not(.h4yf-btn) {
	color: var(--h4yf-ink);
	text-decoration: underline;
	text-decoration-color: var(--h4yf-crimson);
}

body.h4yf-skin .entry-content a:not(.wp-block-button__link):not(.button):not(.wp-element-button):not(.h4yf-btn):hover {
	color: var(--h4yf-hover);
}

/* ---- Imageless-card shimmer placeholder (902 addendum §A) — hundreds of
   products still ship WC's placeholder image; shimmer reads "loading",
   not "broken". Remove once eBay images are populated. ----------------- */
@keyframes h4yf-shimmer {
	0% { background-position: -200% 0; }
	100% { background-position: 200% 0; }
}

body.h4yf-skin ul.products li.product img.woocommerce-placeholder,
body.h4yf-skin ul.products li.product .woocommerce-placeholder {
	background: linear-gradient(90deg, var(--h4yf-charcoal-2) 25%, #34343a 50%, var(--h4yf-charcoal-2) 75%) !important;
	background-size: 200% 100% !important;
	animation: h4yf-shimmer 1.8s ease-in-out infinite;
	opacity: 0.8;
}

/* ---- CMS content components (902 addendum §B kicker/FAQ/definition/
   callout, §C drop-alert, h4yf_custom_css trust-block) — these classes
   live in page/post content, so their styling must survive r3.
   Condensed; crimson demoted to hairline accents. ---------------------- */
.h4yf-kicker {
	display: block;
	font-family: var(--h4yf-body);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: #9a9a9a;
	margin-bottom: 8px;
}

.h4yf-faq {
	margin: 24px 0;
	border-left: 3px solid var(--h4yf-crimson);
	padding-left: 20px;
}

.h4yf-faq-q {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	color: var(--h4yf-ink);
	text-transform: uppercase;
	margin: 0 0 8px;
}

.h4yf-faq-a {
	color: #e2e2e2;
	margin: 0;
}

.h4yf-definition,
.h4yf-callout,
.h4yf-drop-alert,
.h4yf-trust-block {
	background: var(--h4yf-charcoal-2);
	border: 1px solid #3a3a3c;
	border-top: 3px solid var(--h4yf-crimson);
	border-radius: 6px;
	padding: 16px 20px;
	margin: 24px 0;
}

.h4yf-definition-term {
	display: block;
	font-family: var(--h4yf-body);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	margin-bottom: 4px;
}

.h4yf-definition p,
.h4yf-callout p,
.h4yf-trust-block p {
	margin: 0;
	color: #e2e2e2;
}

.h4yf-callout::before {
	content: 'KEY TAKEAWAY';
	display: block;
	font-family: var(--h4yf-body);
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.22em;
	color: #9a9a9a;
	margin-bottom: 8px;
}

.h4yf-trust-block {
	text-align: center;
}

.h4yf-trust-block h4,
.h4yf-trust-block h2 {
	color: var(--h4yf-ink);
	margin: 0 0 8px;
}

.h4yf-drop-alert {
	text-align: center;
	padding: 32px 24px;
}

.h4yf-drop-alert__headline {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	color: var(--h4yf-ink);
	text-transform: uppercase;
	margin: 0 0 8px;
}

.h4yf-drop-alert__sub {
	color: #9a9a9a;
	font-size: 13px;
	margin: 0 0 20px;
}

.h4yf-drop-alert input[type="email"] {
	background: var(--h4yf-charcoal) !important;
	border: 1px solid #46474c !important;
	color: var(--h4yf-ink) !important;
}

/* ---- Astra scroll-to-top (h4yf_custom_css iPhone review pass D) — the
   Astra footer piece still renders; recolor from theme blue to crimson. */
body.h4yf-skin #ast-scroll-top {
	background-color: var(--h4yf-crimson) !important;
	color: var(--h4yf-ink) !important;
}

body.h4yf-skin #ast-scroll-top .ast-arrow-svg {
	fill: var(--h4yf-ink) !important;
}

/* ---- Sprint 6.3: sticky mobile Add-to-Cart. Fixed (not sticky) — the
   button lives high in the DOM on a long PDP, so `position:sticky` relative
   to its own ancestor would never reach the viewport's bottom edge as the
   page scrolls. z-index 500: below the drawer/overlay (700/710 — [CORRECTED
   2026-08-02: this comment still named the retired 9998/9999 pair the
   semantic scale replaced]) so
   opening the cart drawer still covers it, above normal content. Removing
   the button from flow leaves a gap where it used to sit — harmless, the
   trust-strip/shipping-line pseudo-content above it (::before/::after,
   line ~2233) closes up naturally. body padding-bottom stops the fixed bar
   from covering the last bit of page content (footer/description tail). */
@media (max-width: 768px) {
	body.single-product .button.single_add_to_cart_button {
		position: fixed;
		bottom: 0;
		left: 0;
		right: 0;
		z-index: var(--h4yf-z-sticky);
		width: 100% !important;
		border-radius: 0;
		height: 56px !important;
	}

	body.single-product {
		padding-bottom: 56px;
	}
}

/* ---- Reduced motion (902 §T5) — kill shimmer + smooth scroll for
   prefers-reduced-motion (premier.css guards its own animations). ------ */
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	body.h4yf-skin ul.products li.product .woocommerce-placeholder,
	body.h4yf-skin ul.products li.product img.woocommerce-placeholder {
		animation: none;
	}
}

/* ---- Mobile bottom bar (Home/Shop/Drops/Vault/Cart), found live but
   never ported (2026-07-26, Sprint 6.6-fix P1-9). The nav's HTML/JS is
   NOT Astra Addon and NOT in this repo — it's injected at wp_footer by
   the mu-plugin `h4yf_control_api.php` from the `h4yf_custom_footer` DB
   option (served via its own `h4yf/v1/footer` REST channel, separate
   from `h4yf/v1/css`). The 7.2-r3 legacy-CSS retirement (2026-07-16)
   emptied `h4yf_custom_css` — which is where this bar's ONLY layout CSS
   used to live — but never touched `h4yf_custom_footer`, so the markup
   kept rendering with zero styling: bare inline <a> elements collapsed
   to text-baseline height (~68x15px), the touch-target hole the P1-9
   audit measured. Ported verbatim from the pre-retirement option backup
   (`docs/audits/legacy-backups/h4yf_custom_css_option_2026-07-16.css`
   lines 255-288 + the a11y5 active-state contrast fix, lines 925-949)
   — already had the 44px floor baked in. See docs/GOTCHAS.md. --------- */
.h4yf-bottom-bar {
	display: none;
}
@media (max-width: 768px) {
	.h4yf-bottombar-on .h4yf-bottom-bar {
		display: flex;
		position: fixed;
		bottom: 0;
		left: 0;
		width: 100%;
		background-color: var(--h4yf-charcoal);
		border-top: 1px solid var(--h4yf-charcoal-2);
		justify-content: space-around;
		align-items: center;
		padding: 8px 0 calc(6px + env(safe-area-inset-bottom)) 0;
		z-index: var(--h4yf-z-bottombar);
		box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.5);
	}
	/* TYPE: Montserrat, not Bebas (Josh 2026-08-20 "fix that menu's text
	   sizing/font/color"). This is the `label` role in DESIGN.md §3 — nav
	   labels, tracked uppercase Montserrat — and the bar was the one nav
	   surface still setting `--h4yf-display`. Bebas is a condensed all-caps
	   display face; at 12px in a 55px-wide cell it was doing the job it is
	   worst at, and it disagreed with the drawer and header nav one swipe away.

	   SIZE: fluid, because the bar went from five items to seven on 2026-08-20
	   and "Authority" is the longest label in the set. A fixed size either
	   clips at 375px or wastes the room a 430px phone has. The clamp is read
	   against the viewport, which is exactly what decides the cell width.

	   COLOR: muted at rest, ink when active. Every label used to be full ink,
	   so the active state was carried by the crimson rule and icon alone and
	   seven equally-bright labels read as a wall. Muted `#9A9A9A` measures
	   4.66:1 on the charcoal floor — AA for the size, with the active item
	   brightening to 15:1 against it. */
	.h4yf-bottombar-on .h4yf-bottom-bar a {
		color: var(--h4yf-muted);
		text-decoration: none;
		font-family: var(--h4yf-body);
		font-weight: 700;
		/* 2.55vw puts a 390px phone at ~9.9px, which is the size the labels
		   were measured against (see inc/footer.php). Ceiling 11px so a large
		   phone doesn't shout.

		   FLOOR LOWERED TO 8px, 2026-09-06, with AUTHORITY back in the bar.
		   Measured in the browser against this exact face (Montserrat 700,
		   uppercase, 0.02em) at six cells:

		     390px  cell 65.0   AUTHORITY 62.6 @ 9.95px   fits
		     375px  cell 62.5   AUTHORITY 60.2 @ 9.56px   fits
		     320px  cell 53.3   AUTHORITY 56.7 @ 9px      OVER by 3.4
		                        AUTHORITY 50.4 @ 8px      fits

		   The floor only binds below ~353px, so every phone in normal use is
		   unaffected; an SE-class screen takes 8px on ALL six labels rather
		   than one label two points smaller than its neighbours, which is the
		   thing the note above rules out. The bar staying one row matters more
		   than the last point of size. */
		font-size: clamp(8px, 2.55vw, 11px);
		letter-spacing: 0.02em;
		text-transform: uppercase;
		line-height: 1;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 5px;
		flex: 1 1 0;
		min-width: 0;
		min-height: 44px;
		/* No horizontal padding: at seven cells every pixel of it comes off the
		   label, and the cells are already separated by their own width. The
		   44px tap floor is met by the cell (55.7px at 390, 45.7px at 320), not
		   by padding. */
		padding: 7px 0;
		text-align: center;
		transition: color 160ms var(--h4yf-ease-out-expo);
	}
	/* One line, always. Six cells on a 390px screen is 65px each; a label
	   that wraps makes its cell taller than its neighbours and the whole bar
	   grows a second row. `min-width: 0` above is what lets a flex item shrink
	   below its content width at all. */
	.h4yf-bottombar-on .h4yf-bottom-bar a span {
		white-space: nowrap;
	}
	.h4yf-bottombar-on .h4yf-bottom-bar a svg {
		display: block;
		width: 20px;
		height: 20px;
	}
	/* a11y5 contrast fix: crimson-on-charcoal text is 2.87:1 (fails AA) —
	   white label + crimson top-border/icon carries the active state instead. */
	.h4yf-bottombar-on .h4yf-bottom-bar a.active,
	.h4yf-bottombar-on .h4yf-bottom-bar a:active {
		color: var(--h4yf-ink) !important;
		border-top: 2px solid var(--h4yf-crimson);
	}
	.h4yf-bottombar-on .h4yf-bottom-bar a.active svg {
		stroke: var(--h4yf-crimson) !important;
	}
	.h4yf-bottombar-on .h4yf-bottom-bar a.active span {
		color: var(--h4yf-ink) !important;
	}

	/* Single source of truth for bottom clearance on non-PDP pages.
	   2026-07-27: was `.h4yf-bottombar-on body` (a descendant selector assuming
	   the class lands on <html>, from the legacy JS's `doc.classList.add(...)`
	   where doc = documentElement). The class is now server-rendered onto
	   <body> itself via the `body_class` filter (inc/footer.php) — a selector
	   can't be its own ancestor, so the old form silently never matched and
	   the fixed bar clipped page content on every non-PDP page. */
	body.h4yf-bottombar-on:not(.single-product) {
		padding-bottom: calc(64px + env(safe-area-inset-bottom)) !important;
	}
	/* PDP owns bottom:0 with the sticky Add-to-Cart bar (line ~2658) — hide the nav bar there. */
	body.single-product .h4yf-bottom-bar {
		display: none !important;
	}

	.h4yf-bottombar-on #cookie-law-info-bar,
	.h4yf-bottombar-on .cli-bar-container,
	.h4yf-bottombar-on .cc-window.cc-bottom {
		bottom: 56px !important;
	}

	/* Shop toolbar merge into bottom bar retired — standard 5-pillar bottom bar restored. */
}

/* ================================================================== */
/* §D16 — crimson-gradient homepage build (it7 mock = visual contract) */
/* ================================================================== */

/* ---- Credibility strip (directly under hero; it6 font style: 22px ink) ---- */
.h4yf-home-cred {
	padding: 8px 20px clamp(36px, 7vw, 52px);
	text-align: center;
}

.h4yf-home-cred__inner {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 14px 28px;
}

.h4yf-home-cred__inner > div {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.h4yf-home-cred b {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: 22px; /* it6 style per Josh sign-off — NOT the fluid trust-stat clamp */
	color: var(--h4yf-ink);
	line-height: 1;
}

.h4yf-home-cred span {
	font-family: var(--h4yf-body);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
}

/* ---- Culture mosaic: photo tiles + scrim (overrides premier.css gradients) ---- */
.h4yf-mosaic {
	gap: 2px;
	padding: 0;
}

.h4yf-mosaic .h4yf-tile {
	border-radius: 0;
	border-bottom: 2px solid rgba(168, 18, 58, 0.16);
}

@media (min-width: 750px) {
	.h4yf-mosaic .h4yf-tile {
		border-bottom: none;
		border-right: 2px solid rgba(168, 18, 58, 0.16);
	}
	.h4yf-mosaic .h4yf-tile:last-child {
		border-right: none;
	}
}

.h4yf-mosaic .h4yf-tile::before {
	background-size: cover;
	background-position: center;
	filter: saturate(0.85) brightness(0.9);
}

.h4yf-mosaic .h4yf-tile--drops::before   { background-image: url('img/maniere.jpg'); }
.h4yf-mosaic .h4yf-tile--pickups::before { background-image: url('img/mocha1.jpg'); }
.h4yf-mosaic .h4yf-tile--reviews::before { background-image: url('img/store.jpg'); }

/* Earlier reviews-tile block (§reviews) gave the element itself a gradient +
   border — the D16 photo/scrim lives on ::before/::after, so clear those. */
.h4yf-mosaic .h4yf-tile--reviews {
	background: none;
	border-top: 0;
	border-left: 0;
}

/* Legibility + brand scrim OVER the photo — the wash stays the identity layer. */
.h4yf-mosaic .h4yf-tile::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(35, 35, 38, 0.35) 0%, rgba(35, 35, 38, 0.65) 55%, rgba(35, 35, 38, 0.92) 100%);
}

.h4yf-mosaic .h4yf-tile--drops::after {
	background:
		radial-gradient(circle at 60% 40%, rgba(168, 18, 58, 0.27) 0%, transparent 60%),
		linear-gradient(180deg, rgba(35, 35, 38, 0.25) 0%, rgba(35, 35, 38, 0.60) 55%, rgba(35, 35, 38, 0.90) 100%);
}

.h4yf-mosaic .h4yf-tile__body {
	z-index: 1;
}

.h4yf-mosaic .h4yf-tile__kicker,
.h4yf-mosaic .h4yf-tile__title {
	text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
}

.h4yf-mosaic .h4yf-tile__kicker {
	color: rgba(250, 250, 250, 0.82);
}

/* ---- From the Channel — YouTube swipe rail (scroll-snap) ---- */
.h4yf-home-watch--rail {
	padding-left: 0;
	padding-right: 0;
}

.h4yf-home-watch--rail .h4yf-home-section__head {
	padding: 0 16px;
}

.h4yf-yt-rail {
	display: flex;
	gap: 10px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	-webkit-overflow-scrolling: touch;
	padding: 4px 16px 12px;
	scrollbar-width: none;
}

.h4yf-yt-rail::-webkit-scrollbar {
	display: none;
}

.h4yf-yt-card {
	flex: 0 0 78%;
	max-width: 340px;
	scroll-snap-align: start;
	text-decoration: none;
	color: var(--h4yf-ink);
}

@media (min-width: 750px) {
	.h4yf-yt-card {
		flex-basis: 31%;
	}
}

.h4yf-yt-thumb {
	display: block;
	aspect-ratio: 16 / 9;
	border-radius: 6px;
	background-size: cover;
	background-position: center;
	position: relative;
	overflow: hidden;
}

.h4yf-yt-thumb::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 55%, rgba(28, 28, 30, 0.65) 100%);
}

.h4yf-yt-play {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 44px;
	height: 32px;
	background: var(--h4yf-crimson);
	border-radius: 8px;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
}

.h4yf-yt-play::after {
	content: '';
	border-style: solid;
	border-width: 7px 0 7px 12px;
	border-color: transparent transparent transparent var(--h4yf-ink);
}

/* Video titles carry the CARD-TITLE role, same as a product card (Josh
   2026-08-20: "enhance the titles' font size/type/color under YouTube videos
   is uniform with other content blocks on site").

   They were 13px Montserrat 700 with no family and no colour declared — the
   only card title on the site not set in Bebas, sitting in a rail directly
   below Featured Sneakers where the identical layout uses the display face at
   ~20px. DESIGN.md §3 puts card titles in the `title` role, and this size
   matches `.woocommerce-loop-product__title`'s clamp so the two rails read as
   one system when they are three sections apart on the same scroll.

   Two lines, clamped, with the same headroom the product grid needed: Bebas
   caps overshoot their line box, and a hard two-line box slices the second
   line through the glyphs. The height is what keeps a rail of cards even. */
.h4yf-yt-title {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	overflow: hidden;
	margin: 10px 2px 0;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(17px, 0.5vw + 15px, 20px);
	line-height: 1.14;
	max-height: 2.4em;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

.h4yf-yt-card:hover .h4yf-yt-title,
.h4yf-yt-card:focus-visible .h4yf-yt-title {
	color: var(--h4yf-hover);
}

/* The rail is deliberately edge-to-edge, and the section-length crimson rule
   indents its whole section — so the rail's own left padding is dropped when
   the two combine, or the first thumbnail starts 38px in while the right edge
   still bleeds. */
.h4yf-home-watch--rail.h4yf-rule-section .h4yf-yt-rail,
.h4yf-skin .h4yf-home-watch--rail.h4yf-rule-section .h4yf-yt-rail {
	padding-left: 0;
}

.h4yf-home-watch--rail.h4yf-rule-section .h4yf-home-section__head {
	padding-left: 0;
}

/* ---- Vault-Alert AJAX submit — button states (skin.js progressive enhancement) ---- */
.h4yf-vault-form-busy button[type="submit"],
.h4yf-vault-form-busy input[type="submit"] {
	opacity: 0.6;
	pointer-events: none;
}

.h4yf-vault-form-msg {
	display: block;
	margin-top: 10px;
	font-family: var(--h4yf-body);
	font-size: 13px;
	font-weight: 600;
	color: var(--h4yf-ink);
}

.h4yf-vault-form-msg.is-error {
	color: #e6a3a3;
}

/* ---- Footer (Sprint 6.9) ---- */
.h4yf-footer {
	background: var(--h4yf-charcoal);
	border-top: 1px solid var(--h4yf-charcoal-2);
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
}

.h4yf-footer__inner {
	max-width: 1200px;
	margin: 0 auto;
	padding: 40px 20px 24px;
	display: grid;
	/* [FIXED 2026-08-04, impeccable polish pass] A `display: grid` with no
	   `grid-template-columns` gets ONE implicit `auto` column, and an `auto`
	   column sizes to its widest child's MIN-CONTENT width. `.h4yf-footer__social`
	   below had no `flex-wrap`, so its min-content width was the whole unwrapped
	   social row — live-measured 562px. That forced this column to 562px inside a
	   390px viewport, every child inherited it, and `body { overflow-x: hidden }`
	   then CLIPPED the excess rather than letting it scroll: "…no membership
	   needed", FAQ, FACEBOOK, X and WHATNOT were simply not reachable on mobile,
	   on every page of the site.
	   `minmax(0, 1fr)` is the load-bearing half — `1fr` alone still floors at
	   min-content, so a future non-wrapping child would reintroduce this. The
	   `flex-wrap` below fixes today's offender; the `minmax(0, …)` fixes the class. */
	grid-template-columns: minmax(0, 1fr);
	gap: 28px;
}

.h4yf-footer__capture-title {
	font-family: var(--h4yf-display);
	font-size: var(--h4yf-fs-h3);
	letter-spacing: 0.04em;
	margin: 0 0 4px;
}

.h4yf-footer__capture-sub {
	color: var(--h4yf-gray);
	font-size: var(--h4yf-fs-body);
	margin: 0 0 12px;
}

.h4yf-footer__nav {
	display: flex;
	flex-wrap: wrap;
	gap: 32px;
}

.h4yf-footer__links {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 8px 20px;
}

.h4yf-footer__links a {
	color: var(--h4yf-ink);
	text-decoration: none;
	font-size: var(--h4yf-fs-body);
	/* Sprint 6.6-fix P1-9: was ~14px line-height only, no padding — footer
	   has room, so just grow the tap area instead of fighting for it. */
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding-inline: 2px;
}

.h4yf-footer__links a:hover,
.h4yf-footer__links a:focus-visible {
	color: var(--h4yf-hover);
}

.h4yf-footer__links--legal a {
	color: var(--h4yf-gray);
}

.h4yf-footer__social {
	display: flex;
	/* Was the sole cause of the footer's 562px min-content width — see the note
	   on .h4yf-footer__inner. Seven social links at 44px min-height do not fit on
	   one 390px row and never did; they were overflowing into clipped space
	   instead of wrapping. */
	flex-wrap: wrap;
	/* Raised 16 -> 18 with the marks (Josh 2026-08-20: "make larger"). Bigger
	   glyphs need more air between them or the row reads as one busy band. */
	gap: 10px 18px;
	align-items: center;
}

/* LARGER, and stacked (Josh 2026-08-20: "For the social media callouts, make
   larger, use color versions of platform logos").

   The row was a 18px mark beside a 12px caps label on one baseline — at that
   size the mark is decoration on a text link. Mark over label puts the
   recognisable thing first at 26px and makes the label a caption, which is the
   right hierarchy for a row whose whole job is "you already know these". */
.h4yf-footer__social a {
	color: var(--h4yf-gray);
	text-decoration: none;
	font-size: var(--h4yf-fs-meta);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	/* Sprint 6.6-fix P1-9: same tap-area treatment as .h4yf-footer__links a. */
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 6px;
	min-height: 56px;
	/* Mobile audit 2026-07-31: height was fine but width was not — the "X" social
	   link measured 12.1px wide. WCAG 2.5.5 is 44x44, both axes. */
	min-width: var(--h4yf-tap-floor, 44px);
	padding-inline: 6px;
	transition: color 160ms var(--h4yf-ease-out-expo), opacity 160ms var(--h4yf-ease-out-expo);
}

/* A wordmark link is only the mark (eBay, X — the glyph spells the name), so it
   has no caption to align to and doesn't need the column. */
.h4yf-footer__social-link--wordmark {
	flex-direction: row;
}

/* Hover moves the LABEL to crimson and lifts the mark's opacity — it cannot
   recolour the mark itself any more, because the marks now carry their own
   brand colours and repainting YouTube crimson would make it a different
   logo. */
.h4yf-footer__social a:hover,
.h4yf-footer__social a:focus-visible {
	color: var(--h4yf-hover);
}

.h4yf-footer__social a .h4yf-brand-glyph {
	opacity: 0.88;
}

.h4yf-footer__social a:hover .h4yf-brand-glyph,
.h4yf-footer__social a:focus-visible .h4yf-brand-glyph {
	opacity: 1;
}

.h4yf-footer__copy {
	color: var(--h4yf-gray);
	font-size: var(--h4yf-fs-meta);
	margin: 0;
	border-top: 1px solid var(--h4yf-charcoal-2);
	padding-top: 16px;
}

/* ---- PDP capture / restock alert (Sprint 6.9) ---- */
.h4yf-pdp-capture {
	max-width: 640px;
	margin: 32px auto;
	padding: 24px;
	background: var(--h4yf-charcoal);
	border: 1px solid var(--h4yf-charcoal-2);
	border-radius: 10px;
	text-align: center;
}

.h4yf-pdp-capture__title {
	font-family: var(--h4yf-display);
	font-size: var(--h4yf-fs-h3);
	letter-spacing: 0.04em;
	color: var(--h4yf-ink);
	margin: 0 0 4px;
}

.h4yf-pdp-capture__sub {
	color: var(--h4yf-gray);
	font-size: var(--h4yf-fs-body);
	margin: 0 0 14px;
}

/* ------------------------------------------------------------------ */
/* Tap-target floor on WooCommerce/Astra-generated shop markup         */
/* (mobile audit 2026-07-31, measured at 390x844 — see                 */
/*  docs/brand/H4YF_THUMB_ZONE.md; floor is 44x44, WCAG 2.5.5 / HIG)   */
/*                                                                     */
/* These elements are printed by WooCommerce/Astra, not by this theme, */
/* so they never went through the skin's own 44px rules. The grid's    */
/* add-to-cart is the single most conversion-critical control on       */
/* /shop/ and it measured 38.6px tall.                                 */
/* ------------------------------------------------------------------ */
.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product .added_to_cart,
.woocommerce a.button.wc-forward,
.woocommerce .return-to-shop .button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: var(--h4yf-tap-floor, 44px);
}

/* Product title link: 40px measured. Grown with padding rather than a bare
   min-height so the card's vertical rhythm shifts by 4px, not by a jump. */
.woocommerce ul.products li.product .ast-loop-product__link,
.woocommerce ul.products li.product .woocommerce-loop-product__title a {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
}

/* Mobile bottom bar + footer text links: heights were already fine, WIDTHS
   were 22-40px. WCAG 2.5.5 is both axes. */
.h4yf-bottom-bar a,
.h4yf-footer__links a {
	min-width: var(--h4yf-tap-floor, 44px);
	justify-content: center;
}

/* PDP tap targets (mobile audit 2026-07-31, 390x844). The ATC button itself
   measured 56px and was already fine — these are the controls around it. */

/* Flame score rows: THE known canon breach named in docs/brand/H4YF_THUMB_ZONE.md
   (the Sprint 7.3 audit logged 22.6x11 / 32.4x11 / 35x21.1; measured 318x20 on the
   PDP today — width is fine now, height never was). These are category links into
   filtered shop views, i.e. real navigation, so they get the full floor. */
.h4yf-score-block .h4yf-score-row {
	min-height: var(--h4yf-tap-floor, 44px);
	align-items: center;
}

/* WooCommerce tab links: 24.2px / 21.2px measured. */
.woocommerce-tabs ul.tabs li a,
.woocommerce div.product .woocommerce-tabs ul.tabs li a {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
}

/* PDP tabs: Astra draws the active tab's indicator as a 3px
   `li.active::before` bar in its default blue (rgb(4,107,210)), plus a
   light-grey `ul.tabs::before` rule across the top. Both sat above our crimson
   underline on the tab link, so "Additional Information" wore two indicators,
   one of them off-brand (#1053, 2026-09-30). The crimson `border-bottom` on the
   link is the indicator; the list's hairline `border-bottom` is the rule.
   `body.h4yf-skin` prefix: the pattern that survives UCSS (see the gallery
   trigger note below). */
body.h4yf-skin .woocommerce-tabs ul.tabs li::before,
body.h4yf-skin .woocommerce-tabs ul.tabs li::after {
	display: none;
}

/* `ul.tabs::before` is also WooCommerce's clearfix (display: table, set at
   four-class specificity), so keep the box and drop only its paint. */
body.h4yf-skin div.product .woocommerce-tabs ul.tabs::before {
	background: transparent;
}

/* Gallery zoom trigger.

   [REWRITTEN 2026-08-04, impeccable polish pass] The rule that stood here was
   `.woocommerce div.product .woocommerce-product-gallery__trigger` and it was
   NEVER REACHING THE BROWSER — live-measured on the PDP, the element matches
   that selector (`closest('.woocommerce div.product')` is truthy) yet a CSSOM
   walk of every loaded sheet returned only generic `a` rules for it. Classic
   UCSS: correct in git, deployed, md5-verified, absent from the served bundle
   (GOTCHAS "Data sourcing"). The `body.h4yf-skin`-prefixed gallery rules ~800
   lines up DO survive the same pass — verified live, gallery background reads
   rgb(44,44,46) — so this is re-keyed onto the pattern that demonstrably
   survives rather than left as a rule nobody can see.

   What shipped in its place, unstyled: WooCommerce's default markup is a bare
   `<a>🔍</a>`, and with the tap-floor rule gone it laid out as a 698x26
   transparent full-width strip with a raw magnifying-glass EMOJI in Montserrat
   sitting at the gallery's top-left. A system-font emoji is the cheapest glyph
   available and it was on the highest-intent page on the site.
   Now a real 44px icon button in the gallery's top-right: masked stroke icon in
   `--h4yf-ink`, charcoal scrim so it holds over any product photo, hairline
   border, and basketball orange on hover/focus (DESIGN.md D3 — orange owns
   hover/focus/selection, crimson stays the CTA). `font-size: 0` suppresses the
   emoji text node without touching the markup. */
body.h4yf-skin .woocommerce-product-gallery {
	position: relative;
}

body.h4yf-skin .woocommerce-product-gallery__trigger {
	position: absolute;
	top: 12px;
	right: 12px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--h4yf-tap-floor, 44px);
	height: var(--h4yf-tap-floor, 44px);
	border-radius: 999px;
	background: rgba(35, 35, 38, 0.82);
	border: 1px solid var(--h4yf-border);
	font-size: 0;
	line-height: 0;
	color: transparent;
	transition: border-color 150ms ease, background 150ms ease;
}

body.h4yf-skin .woocommerce-product-gallery__trigger::before {
	content: "";
	width: 20px;
	height: 20px;
	background: var(--h4yf-ink);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.3-4.3'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-4.3-4.3'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Grouped longhand, not `:is()` — UCSS drops any selector using `:is()`/`:where()`
   from its keep-list (GOTCHAS "Data sourcing"), which is how the rule above died. */
body.h4yf-skin .woocommerce-product-gallery__trigger:hover,
body.h4yf-skin .woocommerce-product-gallery__trigger:focus-visible {
	border-color: var(--h4yf-bball);
	background: rgba(35, 35, 38, 0.95);
}

/* NOT changed, deliberately: PDP breadcrumb links measure ~15px tall. WCAG 2.5.5
   exempts targets that are inline within a block of text, and forcing 44px here
   would triple the height of a single supplementary nav row whose destinations are
   all reachable from the main nav. Recorded in H4YF_THUMB_ZONE.md as an accepted
   exception rather than silently skipped. */

/* ---- Shop filter flyout (#311) — Astra's off-canvas panel ships unstyled, so
   none of the skin's per-component tap-floor rules reach it. Astra renders a bare
   `<li><a>Term</a> <span class="count">` per row with no class on the anchor, so
   these selectors key off the widget list containers instead. Live-measured
   2026-08-01: 41 controls at 16-19px before, 0 under 44px after, at 390 and 1191. */
.astra-shop-filter-button {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: var(--h4yf-tap-floor, 44px);
	/* Astra ships this trigger as a stock-blue link (#046bd2) on charcoal — ~2.5:1,
	   and blue text is off-canon site-wide regardless of contrast. */
	color: var(--h4yf-ink);
}

.astra-shop-filter-button:hover {
	color: var(--h4yf-hover);
}

/* The row is the flex container, not the anchor: `.count` and `ul.children` are
   SIBLINGS of the anchor, so flexing the anchor alone would drop the count to its
   own line. */
.astra-off-canvas-sidebar li.cat-item,
.astra-off-canvas-sidebar li.wc-layered-nav-term {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	column-gap: 6px;
}

.astra-off-canvas-sidebar li.cat-item > a,
.astra-off-canvas-sidebar li.wc-layered-nav-term > a {
	flex: 1 1 auto;
	display: flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
}

.astra-off-canvas-sidebar li.cat-item > ul.children {
	flex: 1 0 100%;
	padding-left: 14px;
}

.astra-off-canvas-sidebar .ast-shop-filter-close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: var(--h4yf-tap-floor, 44px);
	min-height: var(--h4yf-tap-floor, 44px);
}

.astra-off-canvas-sidebar .price_slider_amount .button {
	min-height: var(--h4yf-tap-floor, 44px);
	padding: 0 18px;
}

/* [REMOVED 2026-08-02] `.ui-slider-handle::after` grew a 44px tap area around
   jQuery UI's 14px handles. Both handles — the only two sub-44px controls left
   in this panel, live-measured — are gone with the slider chain itself; a native
   `<input type="range">` is a 44px tap target along its whole rail. */

/* ---- Flyout PANEL SURFACE (2026-08-02).
   The panel could not be looked at until 0.9.19 made it open, so it had never
   been styled: Astra ships it as `background: var(--ast-global-color-primary)`
   = #FFFFFF, a white sheet on a charcoal site, with category links at Astra
   blue #046bd2 and `.count` spans inheriting the skin's #FAFAFA — measured
   1.04:1 on white, i.e. invisible.

   This is the second off-canvas surface in the system, so it is built as the
   sibling of `.h4yf-drawer` rather than as its own idiom: same charcoal floor,
   same hairline seam, same two-layer shadow (mirrored, because this panel
   enters from the LEFT), same scrim. DESIGN.md's Flat-Floor rule reserves real
   shadow for genuinely overlaid surfaces — a drawer is exactly that, and this
   is one.

   Specificity, not `!important`: Astra's own rule is
   `.woocommerce .astra-off-canvas-sidebar-wrapper .astra-off-canvas-sidebar`
   (0,3,0), so prefixing with `body.h4yf-skin` lands at (0,3,1) and wins
   cleanly. Nothing here needs a bang. ---------------------------------- */
body.h4yf-skin .astra-off-canvas-sidebar-wrapper .astra-off-canvas-sidebar {
	background: var(--h4yf-charcoal);
	border-right: 1px solid var(--h4yf-border);
	box-shadow: 1px 0 0 rgba(255, 255, 255, 0.04), 24px 0 60px rgba(0, 0, 0, 0.55);
	color: var(--h4yf-ink);
}

/* Astra's scrim is rgba(0,0,0,.4); the nav/cart drawer's is rgba(10,10,11,.62)
   with a 2px blur. One overlay treatment, not two.

   z-index: Astra ships this wrapper at 99, which is BELOW the skin's sticky
   header (`--h4yf-z-sticky`, 500). DESKTOP ONLY — live-measured 2026-08-02,
   both widths: at 1280px the header's top 75px covered the panel's top 75px
   and `elementFromPoint` over the applied-filter chips returned
   `.h4yf-header__inner`, so 41 of the chip bar's 59px were not merely hidden
   but CLICK-BLOCKED and a chip could never remove its filter; at 390px the
   same chip measured 0px blocked at either z-index, so mobile was never
   affected and this is not a regression there. A DOM-only check cannot see
   the desktop case: the chips are present, styled and correctly sized, and
   only hit-testing shows the header eating them — which is why the panel
   passed its earlier 390px-only verification. The panel is a drawer (this
   file already says so, above) so it takes the drawer tier, which also
   clears the bottom bar (600) while it is open. */
body.h4yf-skin .astra-off-canvas-sidebar-wrapper {
	background: rgba(10, 10, 11, 0.62);
	backdrop-filter: blur(2px);
	-webkit-backdrop-filter: blur(2px);
	z-index: var(--h4yf-z-drawer);
}

/* THE RULE THAT ACTUALLY OPENS IT (2026-09-06). ------------------------------
   Josh: "ensure the filter hamburger menu is operational and correct." It was
   not: measured live on /shop/, clicking Filters ran Astra's handler correctly
   — `<html>` gained `ast-off-canvas-overlay`, the button gained `.active`,
   focus moved to the close button — and the panel stayed at
   `visibility:hidden; opacity:0`, because the rule that reverses those two
   properties WAS NOT ON THE PAGE. Counted in the browser: 13 rules matching
   `.astra-off-canvas-sidebar-wrapper` present, 0 matching
   `ast-off-canvas-overlay`.

   That asymmetry is the LiteSpeed UCSS defect this repo has already been bitten
   by once — see the measurements in `inc/ucss-guard.php`, where the drawer's
   closed-state rule shipped and its open-state rule did not, for exactly the
   same reason: a class that only exists after a click is never in the crawled
   DOM, so the pass reads the rule as dead. `.ast-off-canvas-overlay` is now on
   that allowlist, which is the systemic half.

   This is the other half, and it is not redundancy: the allowlist only takes
   effect when UCSS next regenerates for the URL (a queue + cron on the live
   host), so on its own it fixes nothing today, and nothing at all if the plugin
   is swapped. Written against `html`, matching Astra's own scope — the class is
   added to the document element, not the body. */
html.ast-off-canvas-overlay .astra-off-canvas-sidebar-wrapper {
	visibility: visible;
	opacity: 1;
}

html.ast-off-canvas-overlay .astra-off-canvas-sidebar-wrapper .astra-off-canvas-sidebar {
	left: 0;
}

/* Widget headings ("Silhouette" / "Condition" / "Price") are section titles,
   so they take Bebas like every other section title on the site. */
body.h4yf-skin .astra-off-canvas-sidebar .widget-title,
body.h4yf-skin .astra-off-canvas-sidebar h2,
body.h4yf-skin .astra-off-canvas-sidebar h3 {
	margin-bottom: 10px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

/* Each widget is a group; a hairline between them does the separating work
   that a card would otherwise be reached for. */
body.h4yf-skin .astra-off-canvas-sidebar .widget + .widget {
	margin-top: 24px;
	padding-top: 24px;
	border-top: 1px solid var(--h4yf-charcoal-2);
}

/* No blue text anywhere (DESIGN.md). Astra's bare `a { color: var(
   --ast-global-color-0) }` is (0,0,1), so this needs no weight to beat — the
   rows are already flexed by the tap-floor rules above. */
body.h4yf-skin .astra-off-canvas-sidebar li.cat-item > a,
body.h4yf-skin .astra-off-canvas-sidebar li.wc-layered-nav-term > a {
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	text-decoration: none;
}

body.h4yf-skin .astra-off-canvas-sidebar li.cat-item > a:hover,
body.h4yf-skin .astra-off-canvas-sidebar li.wc-layered-nav-term > a:hover {
	color: var(--h4yf-hover);
}

/* An applied facet is a SELECTION, so it takes #EE6730, not the hover orange
   (D3). Woo marks the term's <li>, not the anchor. */
body.h4yf-skin .astra-off-canvas-sidebar li.wc-layered-nav-term.chosen > a,
body.h4yf-skin .astra-off-canvas-sidebar li.cat-item.current-cat > a {
	color: var(--h4yf-bball);
	font-weight: 700;
}

/* The counts were the invisible half of this bug (#FAFAFA on #FFFFFF, 1.04:1).
   They are metadata, so they take the muted token — #8C8C8C computes 4.66:1 on
   the charcoal floor [CORRECTED 2026-08-02: the 5.06:1 first written here was
   measured against #1C1C1E; this panel's floor is `--h4yf-charcoal` = #232326,
   and 4.66:1 is the live-measured number at both 390px and desktop. Still over
   the 4.5:1 body threshold, so the conclusion is unchanged] — and they get
   pushed to the panel's right edge so it reads as
   a stat sheet rather than a ragged run of parentheses. */
body.h4yf-skin .astra-off-canvas-sidebar .count {
	margin-left: auto;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	font-variant-numeric: tabular-nums;
}

body.h4yf-skin .astra-off-canvas-sidebar .ast-shop-filter-close {
	color: var(--h4yf-ink);
}

/* ---- Silhouette accordion (Josh 2026-08-02). The toggle is injected by
   `catAccordion()` in skin.js; the parent row is already a flex container from
   the tap-floor rules above, so the button just becomes its last item. The
   chevron is drawn with a border rather than shipped as an icon — one glyph is
   not worth a request or a base64 payload. */
body.h4yf-skin .astra-off-canvas-sidebar .h4yf-cat-toggle {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--h4yf-tap-floor, 44px);
	min-height: var(--h4yf-tap-floor, 44px);
	margin-left: 6px;
	padding: 0;
	background: none;
	border: 0;
	color: var(--h4yf-gray);
	cursor: pointer;
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-cat-toggle::before {
	content: "";
	width: 8px;
	height: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	/* Points DOWN when collapsed — the affordance is "there is more below". */
	transform: translateY(-2px) rotate(45deg);
	transition: transform 160ms var(--h4yf-ease-out-expo, ease-out);
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-cat-toggle[aria-expanded="true"]::before {
	transform: translateY(2px) rotate(-135deg);
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-cat-toggle:hover {
	color: var(--h4yf-hover);
}

@media (prefers-reduced-motion: reduce) {
	body.h4yf-skin .astra-off-canvas-sidebar .h4yf-cat-toggle::before {
		transition: none;
	}
}

/* A collapsed parent is a group header, so it carries a little more weight than
   the leaf rows underneath it. */
body.h4yf-skin .astra-off-canvas-sidebar li.cat-item.cat-parent > a {
	font-weight: 600;
}

/* ---- Price: native range (2026-08-02, Josh).
   The jQuery UI rules that stood here are gone with the chain they styled —
   42,391B of core/mouse/slider/touch-punch/accounting/price-slider, dequeued in
   `inc/shop-filter-panel.php`, which is the whole /shop/ JS budget overage.
   `skin.js` retypes WooCommerce's own `#min_price`/`#max_price` to
   `type="range"`; these style what the browser then draws.

   TWO STACKED RAILS, not an overlapped dual-thumb pair — see the `ponytail:`
   note in skin.js. `.price_slider` is WooCommerce's now-permanently-empty
   track div; it ships `display: none` inline, so it is left alone. */
body.h4yf-skin .astra-off-canvas-sidebar input[type="range"] {
	-webkit-appearance: none;
	appearance: none;
	display: block;
	width: 100%;
	/* The rail IS the tap target — full floor height, transparent above and
	   below the visible 4px track. */
	height: var(--h4yf-tap-floor, 44px);
	margin: 0;
	padding: 0;
	background: none;
	cursor: pointer;
}

body.h4yf-skin .astra-off-canvas-sidebar input[type="range"]::-webkit-slider-runnable-track {
	height: 4px;
	border-radius: 2px;
	background: var(--h4yf-charcoal-2);
}

body.h4yf-skin .astra-off-canvas-sidebar input[type="range"]::-moz-range-track {
	height: 4px;
	border-radius: 2px;
	background: var(--h4yf-charcoal-2);
}

body.h4yf-skin .astra-off-canvas-sidebar input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	width: 22px;
	height: 22px;
	/* WebKit centres the Firefox thumb for us but not this one: half the thumb
	   minus half the 4px track. */
	margin-top: -9px;
	border: 2px solid var(--h4yf-crimson);
	border-radius: 50%;
	background: var(--h4yf-ink);
}

body.h4yf-skin .astra-off-canvas-sidebar input[type="range"]::-moz-range-thumb {
	width: 22px;
	height: 22px;
	border: 2px solid var(--h4yf-crimson);
	border-radius: 50%;
	background: var(--h4yf-ink);
}

/* The rail is taller than its visible track, so the skin's default focus ring
   would float 44px clear of anything the eye reads as the control. Pulled in to
   the track with a negative offset.

   `--h4yf-bball` (#EE6730) and NOT `--h4yf-orange` (#D4571A): focus/selection is
   basketball orange, hover is the darker one. Caught by live-measuring the
   deployed rail under a real arrow-key press — it rendered `rgb(212,87,26)`,
   the hover colour, which is the wrong half of that rule.

   Deliberately declares ONLY the outline. The skin blanket's
   `body.h4yf-skin input:focus-visible` already supplies the halo and glow, so
   overriding `box-shadow` here just re-states it — and the `inset` variant this
   rule first shipped with computed to `rgba(0,0,0,0) 0 0 0 0 inset`, i.e. no
   halo at all, while the token itself resolved correctly (measured). Letting
   the blanket own the halo is both less CSS and the only version that renders. */
body.h4yf-skin .astra-off-canvas-sidebar input[type="range"]:focus-visible {
	outline: 2px solid var(--h4yf-bball);
	outline-offset: -18px;
}

/* WooCommerce hides this label and repopulates it from `accounting.js`. That
   script is gone, so the chips carry the readout instead and the rails get
   their own always-visible min/max labels. */
body.h4yf-skin .astra-off-canvas-sidebar .price_slider_amount .price_label {
	display: none;
}

/* Woo ships these as visually-hidden labels for what used to be two text
   inputs. With two identical rails and no numeric field, "Min price" / "Max
   price" is the only thing telling a sighted user which rail is which.

   `!important` is load-bearing here and is NOT an arms race: the visually-hidden
   utility is a bare `.screen-reader-text { position: absolute !important }`
   (live-measured — this selector at (0,4,1) still lost, because no specificity
   beats `!important`). Overriding a utility class is the case `!important` is
   for. Scoped to these two labels inside the filter panel; every other
   `.screen-reader-text` on the site stays hidden. */
body.h4yf-skin .astra-off-canvas-sidebar .price_slider_amount .screen-reader-text {
	position: static !important;
	clip: auto !important;
	clip-path: none !important;
	width: auto !important;
	height: auto !important;
	margin: 0 !important;
	overflow: visible !important;
	white-space: normal !important;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
}

/* ---- Applied-filter chips + Apply bar (Josh 2026-08-02).
   Both are built by `skin.js`; the panel has no markup for them. The chips sit
   ABOVE the facets so the staged set is the first thing read on open, and the
   Apply bar sticks to the bottom so the count stays reachable from anywhere in
   a panel that scrolls past 30 silhouette rows. */
body.h4yf-skin .astra-off-canvas-sidebar .h4yf-filter-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	padding: 0 0 14px;
	border-bottom: 1px solid var(--h4yf-charcoal-2);
	margin-bottom: 14px;
}

/* `[hidden]` is only a UA-stylesheet `display: none`, so ANY explicit `display`
   in the theme beats it. WooCommerce's own Filter button is `display: block` and
   went on rendering after `skin.js` set `hidden` on it — visible in a live
   screenshot of the deployed panel, a second submit next to Apply doing the
   wrong thing (it posts the price form alone and drops the staged facets).
   Restored panel-wide rather than per element, so the next thing this code
   hides does not have to rediscover it. */
body.h4yf-skin .astra-off-canvas-sidebar [hidden] {
	display: none !important;
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-chip {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: var(--h4yf-tap-floor, 44px);
	padding: 0 14px;
	border: 1px solid var(--h4yf-border);
	border-radius: 999px;
	background: var(--h4yf-charcoal-2);
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	cursor: pointer;
}

/* Drawn rather than shipped as a glyph in the label: the accessible name is
   "Remove filter: <label>", and a literal × in the text node would be read out
   on top of it. */
body.h4yf-skin .astra-off-canvas-sidebar .h4yf-chip::after {
	content: "×";
	font-size: 1.15em;
	line-height: 1;
	color: var(--h4yf-gray);
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-chip:hover {
	border-color: var(--h4yf-hover);
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-chip:hover::after {
	color: var(--h4yf-hover);
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-filter-apply {
	position: sticky;
	bottom: 0;
	padding: 14px 0 0;
	border-top: 1px solid var(--h4yf-charcoal-2);
	background: var(--h4yf-charcoal);
}

body.h4yf-skin .astra-off-canvas-sidebar .h4yf-apply-btn {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 48px;
	border: 0;
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.02em;
	text-transform: uppercase;
	cursor: pointer;
}

/* Disabled = the staged set already matches the page. Muted rather than hidden,
   so the control does not appear and disappear as facets are toggled. */
body.h4yf-skin .astra-off-canvas-sidebar .h4yf-apply-btn[disabled] {
	background: var(--h4yf-charcoal-2);
	color: var(--h4yf-gray);
	cursor: default;
}

/* ================================================================== */
/* §SHOP LOOP CARD — standardisation (Josh directive 2026-08-01:      */
/* "standardize product cards and images in shop loop")               */
/* ================================================================== */

/* Astra builds each card as two sibling wrappers — `.astra-shop-thumbnail-wrap`
   and `.astra-shop-summary-wrap`. Making the card and the summary both flex
   columns lets the price be pushed to the bottom, so cards whose titles wrap to
   different line counts still end at the same baseline. Measured before this:
   293.5px and 351.5px cards in the same grid. */
.woocommerce ul.products li.product {
	display: flex;
	flex-direction: column;
}

.woocommerce ul.products li.product .astra-shop-summary-wrap {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
}

/* Price is the last thing in the card and the one element that must line up
   across a row — pin it to the bottom of the summary column. */
.woocommerce ul.products li.product .price {
	margin-top: auto;
}

/* THE IMAGE FIX. `object-fit` was never set, so it sat at its initial value of
   `fill` and every non-square source was STRETCHED to the box rather than
   cropped — live-measured, a 300x180 source rendered 174x104.4 next to
   174x174 neighbours, distorting the shoe. A fixed 1:1 plate plus `cover`
   makes every tile identical and never warps the product. */
.woocommerce ul.products li.product .astra-shop-thumbnail-wrap {
	position: relative;
	overflow: hidden;
	background: var(--h4yf-mid, #232326);
}

.woocommerce ul.products li.product .woocommerce-loop-product__link {
	display: block;
	aspect-ratio: var(--h4yf-plate);
	overflow: hidden;
	/* No text node lives here today (just the product image), so Astra's
	   default #046bd2 anchor color has never actually painted anything —
	   but per style.css's "no blue text anywhere" rule this repo has swept
	   the same stock blue off every other anchor site-wide (see the other
	   #046bd2 fixes in this file). This one was missed; closing it so the
	   card markup can't grow a text node someday and surface it. */
	color: var(--h4yf-ink);
}

.woocommerce ul.products li.product .woocommerce-loop-product__link img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	margin-bottom: 0;
	transition: transform 0.45s var(--h4yf-ease-out-expo, ease-out);
}

.woocommerce ul.products li.product:hover .woocommerce-loop-product__link img {
	transform: scale(1.04);
}

/* Title: exactly two lines on every card, so the flame row and the price start
   at the same y across the whole grid. Two, not three — at 15px/1.25 a third
   line pushed the price below the fold of a 390px two-up grid.

   A hard `height` does the work, NOT `-webkit-line-clamp`. Astra makes this h2 a
   flex item, and Chrome blockifies a flex item's `display: -webkit-box` to
   `flow-root` — live-measured, the computed value comes back `flow-root` even
   though this is the only rule on the page setting `display` here, which is why
   the clamp alone left titles at 37.5px and 53.5px in the same grid. The clamp
   properties stay for the ellipsis where the engine does honour them; the height
   is what guarantees uniformity either way. */
.woocommerce ul.products li.product .woocommerce-loop-product__title {
	/* Two lines, uniform across the grid — that part is unchanged and is what
	   keeps card heights equal.

	   [FIXED 2026-08-02] The height used to be exactly `2 * 1.25em`, i.e. the
	   two line boxes and not one pixel more, and Bebas Neue's caps overshoot
	   their line box. Live-measured on /shop/: a 38px box against a 54px
	   scrollHeight, with the second line sliced horizontally through the
	   glyphs rather than ending cleanly. The comment above explains why the
	   `-webkit-line-clamp` ellipsis never renders here (Chrome blockifies
	   `-webkit-box` to `flow-root` on a flex item), which is why the overflow
	   reads as damage rather than as truncation.
	   The fix is headroom: two line boxes plus the overshoot, so a title that
	   runs long ends between lines instead of through one. */
	line-height: 1.14;
	/* THREE lines, and the height is exactly three line boxes minus a hair.

	   [CORRECTED 2026-08-02, same day: the first attempt at this set two lines
	   plus 0.18em of "headroom" for Bebas's overshoot. That was the wrong model
	   and it made things worse — live-measured on /shop/, 46 of 48 cards showed
	   a ~3px sliver of the THIRD line's caps peeking above the cut, because any
	   height greater than n whole line boxes reveals the top of line n+1. Extra
	   height is not headroom when the content keeps going.]

	   Two lines was also simply not enough room. At the 174px mobile card width,
	   measured across all 48 titles: 2 need two lines, 37 need three, 9 need
	   four. A two-line box truncated 46 of 48 product names — on a page whose
	   whole job is telling you which shoe you are looking at.

	   The `- 1px` is what guarantees no sliver survives sub-pixel rounding.
	   Bebas is uppercase-only so there are effectively no descenders to lose.
	   Heights stay uniform across the grid because the box is fixed either way,
	   which is what the card-standardisation work required.

	   [FIXED 2026-08-04, impeccable polish pass: THREE lines -> FOUR.] The
	   analysis above is right and the arithmetic is right; the line COUNT was
	   one short. Its own measurement says 9 of 48 titles need a fourth line, so
	   the 3-line box shipped a hard mid-glyph cut on 19% of the shop grid — the
	   exact "reads as a rendering bug" failure the mask below was added to
	   soften, on the surface whose entire job is telling you which shoe you are
	   looking at.
	   Live-measured at 390px on /shop/ before changing anything: worst
	   `scrollHeight` 78px against a 61px box; after, 48 of 48 titles fit with 0
	   clipped, box 61 -> 81px and the card 401 -> 421px. Twenty pixels on a
	   two-up mobile grid is a cheap trade for never truncating a product name.
	   The stale reason for three is recorded above and no longer holds: it was
	   sized when the title was 15px/1.25 and a third line pushed the price below
	   the fold. The card type ramp moved to 18px mobile / 32px desktop on
	   2026-08-02 and the price is nowhere near the fold now.
	   The mask stays — it is the safety net for a five-line title elsewhere in
	   the 509, not dead code. */
	height: calc(4 * 1.14em - 1px);
	overflow: hidden;
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;

	/* The 9-of-48 titles that need a FOURTH line truncate with no ellipsis —
	   `-webkit-line-clamp` cannot draw one here because Chrome blockifies
	   `-webkit-box` to `flow-root` on a flex item (see the note above). A hard
	   chop mid-glyph reads as a rendering bug rather than as "there is more
	   name than fits", which is the whole reason this looked broken.

	   A bottom fade says the same thing without needing the ellipsis to work,
	   and it costs no markup. It is also self-scoping: measured live, a title
	   that fits ends 8px above the box floor, so the 6px fade never touches it
	   — only a title actually running into the cut gets softened. */
	mask-image: linear-gradient(to bottom, #000 calc(100% - 6px), transparent);
	-webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 6px), transparent);
}

/* Split title (#452): brand / silhouette / colorway as three fixed roles
   instead of one clamped string. Lives inside the same box as the rule
   above — same height/overflow/mask, still applies since `.h4yf-split-title`
   only adds a modifier class, it doesn't replace `.woocommerce-loop-product__title`.
   A split card almost never needs all 4 lines (3 fixed roles vs. an unbounded
   listing-title string), so the fade/clamp become a safety net here rather
   than something that fires every card. No italics anywhere (site-wide
   synthesized-italic removal, PR #493) — the colorway line is set off by
   quote marks (added in markup) and color/weight instead. */
.woocommerce ul.products li.product .h4yf-split-title {
	display: block;
	/* Split titles are three roles, not one string, and on a 2-up phone card the
	   brand line alone wraps to two lines. The fixed 4-line box + fade above cut
	   the colorway off mid-quote ("“SAIL/BLACK-", 2026-09-30 live check). Keep the
	   box as a FLOOR (rows stay level for the common case) and let it grow. */
	height: auto;
	min-height: calc(4 * 1.14em - 1px);
	-webkit-mask-image: none;
	mask-image: none;
}

/* Phones: a 2-up card wraps the brand line, so split titles measured 81-112px
   across the first 48 pairs. One floor at the measured ceiling keeps the HEAT
   row and price on the same y across a row; wider cards never reach it. */
@media (max-width: 768px) {
	.woocommerce ul.products li.product .h4yf-split-title {
		min-height: 112px;
	}
}

.woocommerce ul.products li.product .h4yf-split-title__brand {
	display: block;
	font-family: var(--h4yf-body);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
	line-height: 1.3;
}

.woocommerce ul.products li.product .h4yf-split-title__silhouette {
	display: block;
}

.woocommerce ul.products li.product .h4yf-split-title__colorway {
	display: block;
	font-family: var(--h4yf-body);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.01em;
	color: var(--h4yf-gray);
	line-height: 1.3;
}

/* The rest of the card, re-scaled against the new title so the block reads as
   one typographic system instead of four unrelated sizes (Josh 2026-08-02:
   "increase the other text sizes proportionally to fill the text box/window in
   a fashion shop optimized way"). Measured before: title 15 / price 14.3 /
   condition 10 / HEAT label 9 — a 15px header over a 14px price is not a
   hierarchy, and 9px on a 385px-wide card is a rounding error.
   Everything below is Montserrat and stays Montserrat: Bebas carries the name,
   the reader's eye gets a humanist face for anything it has to actually read
   (DESIGN.md Two-Family Rule). */
.woocommerce ul.products li.product .price,
.woocommerce ul.products li.product .price span {
	font-size: clamp(15px, 0.4vw + 13.5px, 17px);
	letter-spacing: 0.01em;
}

.woocommerce ul.products li.product .h4yf-score-block--compact .h4yf-score-label {
	font-size: 11px;
	letter-spacing: 0.1em;
}



/* HEAT row on the card — sits between title and price (inc/flames.php hooks
   `astra_woo_shop_price_before`). Left-aligned with the rest of the summary
   column; the mobile grid centres its text, so this opts back out. */
.woocommerce ul.products li.product .h4yf-score-block--compact {
	margin: 4px 0 8px;
	align-items: flex-start;
}

.woocommerce ul.products li.product .h4yf-score-block--compact .h4yf-score-row {
	justify-content: flex-start;
}

/* ================================================================== */
/* §SHOP CARD TYPE — desktop scale (Josh 2026-08-02: "lots of dead     */
/* space and small text. not impactful to help make conversions")      */
/* ================================================================== */

/* THE DEAD SPACE, MEASURED. The title box above reserves THREE lines because
   at the 174px MOBILE card 37 of 48 titles need three. The desktop card is
   345px of text width — 2.2x wider — and at the current 21px **all 48 titles
   fit on ONE line**. So every desktop card reserved two empty lines: ~48px of
   guaranteed hole, on all 48 cards. Same rule, wrong context.

   THE FLAT SCALE, MEASURED. Live on a 385px card: HEAT label 11 / flames 15.94
   / price 17 / CTA 20 / title 21. Step ratios 1.07, 1.18, 1.05 — the largest
   text on the card is 1.3x the smallest. DESIGN.md and the brand register both
   want >=1.25 PER STEP; a flat ramp reads as uncommitted, which is exactly the
   "not impactful" report. A previous pass (comment above) already went
   15->21 title and 14.3->17 price proportionally; proportional was the problem,
   because scaling a flat ramp keeps it flat.

   THE SWAP. 32px in a TWO-line box costs the same vertical space as 21px in a
   three-line box, so the card does not grow — the type gets 52% bigger and the
   hole disappears. Line counts re-measured at 345px before committing:
   21px -> 48 titles on one line; 32px -> 18 on one, 30 on two, ZERO on three.

   `min-height`, not `height`. A fixed box clipped "HIGH OG" straight through
   the glyphs at 32px — the `- 1px` guard the mobile rule uses works at 21px but
   Bebas's cap overshoot scales with size. min-height reserves the two lines that
   keep flame rows roughly aligned, and a longer future title takes a third line
   instead of being sliced. Card bottoms still line up because `.price` already
   carries `margin-top: auto` (see §SHOP LOOP CARD above) — the mechanism was
   there, the fixed height was doing a job nothing needed it to do.
   Live-verified at 1280px: 0 clipped titles across all 48, 16 rows x 3-up. */
@media (min-width: 769px) {
	.woocommerce ul.products li.product .woocommerce-loop-product__title {
		font-size: 32px;
		line-height: 1.08;
		letter-spacing: 0.015em;
		min-height: calc(2 * 1.08em);
		height: auto;
		max-height: none;
		overflow: visible;
		padding-top: 16px;
		margin-bottom: 10px;
	}

	/* No clip on desktop means nothing to soften — the mobile rule's bottom
	   fade would just eat the last 6px of a legitimate second line. */
	.woocommerce ul.products li.product .woocommerce-loop-product__title {
		mask-image: none;
		-webkit-mask-image: none;
	}

	/* The decision number. It was 17px/700 — second-SMALLEST thing on a card
	   whose job is to sell. `tabular-nums` so prices align down a column
	   instead of shimmering as digit widths change. */
	.woocommerce ul.products li.product .price,
	.woocommerce ul.products li.product .price span {
		font-size: 24px;
		font-weight: 800;
		letter-spacing: 0.01em;
		font-variant-numeric: tabular-nums;
		padding-bottom: 16px;
	}

	/* The flame score is H4YF's signature mechanic and it was rendering at
	   15.94px — smaller than the Add-to-cart button. It is the one thing on the
	   card no competitor has; it gets presence. */
	.woocommerce ul.products li.product .h4yf-flames {
		font-size: 22px;
	}

	/* Labels stay small and stay `muted` — they are metadata, not content, and
	   inventing a lighter grey here would be a token change smuggled in as a
	   type fix (see D22 on why colour calls are made deliberately, not in
	   passing). They get tracking and weight instead, which is what the
	   DESIGN.md `label` token actually specifies and what 11px/700 was missing. */
	.woocommerce ul.products li.product .h4yf-score-block--compact .h4yf-score-label,
	.woocommerce ul.products li.product .h4yf-cond--card {
		font-size: 12px;
		font-weight: 800;
		letter-spacing: 0.12em;
	}
}

/* Selection / hover on the card itself = basketball orange, the one signal it
   is allowed to carry (DESIGN.md). Crimson stays the CTA colour. */
.woocommerce ul.products li.product:hover {
	border-color: var(--h4yf-bball);
}

.woocommerce ul.products li.product:focus-within {
	border-color: var(--h4yf-bball);
}

/* An empty flame was `charcoal-2` — the same colour as the desktop card it sits
   on, so a 2.0 read as "two flames" with no sense of the scale it is out of.
   Now a quiet tint of ink, which holds on charcoal AND charcoal-2. */
.h4yf-f--empty {
	background: rgba(250, 250, 250, 0.22);
}

.h4yf-f--half {
	background: linear-gradient(90deg, var(--h4yf-crimson) 0 50%, rgba(250, 250, 250, 0.22) 50% 100%);
}

@media (prefers-reduced-motion: reduce) {
	.woocommerce ul.products li.product .woocommerce-loop-product__link img,
	.woocommerce ul.products li.product:hover .woocommerce-loop-product__link img {
		transition: none;
		transform: none;
	}
}

/* Condition badge on the card (inc/shop-loop-card.php). The base `.h4yf-cond`
   rule above predates this and was written for a 12px-inset PDP-ish context —
   the card variant sits in the summary column's own flow, so it drops the
   horizontal margin and pairs with the price rather than floating. */
.woocommerce ul.products li.product .h4yf-cond--card {
	align-self: flex-start;
	margin: 0 0 6px;
	padding: 2px 7px;
	border-color: var(--h4yf-border, #3a3a3c);
	color: var(--h4yf-muted, #9a9a9a);
	/* [RAISED 2026-08-02] 10px, re-scaled with the rest of the card. An earlier
	   edit this session bumped the base `.h4yf-cond` and had no effect: the
	   card always carries `--card` too, and this rule is both later and more
	   specific. Verified live before assuming it landed. */
	font-size: 11px;
	letter-spacing: 0.1em;
}

/* Desktop size for the badge, deliberately placed HERE rather than in the
   §SHOP CARD TYPE media block above. That block sets this same selector at the
   same specificity, but it sits EARLIER in the file, so this rule won on order
   and the badge stayed 11px while its sibling `.h4yf-score-label` went to 12px —
   caught live at 1280px after the 0.9.35 deploy, not assumed. Exactly the trap
   the comment above already warns about; the fix is proximity, not a bang. */
@media (min-width: 769px) {
	.woocommerce ul.products li.product .h4yf-cond--card {
		font-size: 12px;
		letter-spacing: 0.12em;
	}
}

/* Size badge on the card (inc/shop-loop-card.php, issue #303). Plain text, no
   border — condition is the axis worth a badge-weight treatment; size is
   supporting info that sits quietly beside it until the catalog actually
   varies on it. */
.woocommerce ul.products li.product .h4yf-size--card {
	display: block;
	margin: 0 0 6px;
	color: var(--h4yf-muted, #9a9a9a);
	font-size: 11px;
	letter-spacing: 0.08em;
}

/* Deadstock is the scarce state (29 of 498) and the higher-value one, so it gets
   the single bit of emphasis: a brighter hairline and ink text. Deliberately NOT
   orange — orange means focus/selection in this system, never "good" (DESIGN.md),
   and a permanent orange badge on 29 tiles would break that meaning. */
.woocommerce ul.products li.product .h4yf-cond--ds {
	border-color: var(--h4yf-soft, #34343a);
	color: var(--h4yf-ink);
}

/* ================================================================== */
/* §PDP PRICE LINE — score block beside the price (Josh 2026-08-01)    */
/* ================================================================== */

/* Wrapper opened/closed around price + scoreboard in inc/flames.php. Stacked by
   default; the summary column is ~350px at 390px and both halves need the width. */
.single-product .h4yf-pdp-priceline {
	display: flex;
	flex-direction: column;
	gap: 8px;
}

@media (min-width: 993px) {
	.single-product .h4yf-pdp-priceline {
		flex-direction: row;
		align-items: flex-start;
		justify-content: space-between;
		gap: 28px;
	}

	/* Price keeps the left edge and stays the dominant element; the scoreboard
	   takes only the width its rows need rather than stretching to fill. */
	.single-product .h4yf-pdp-priceline > .price {
		flex: 1 1 auto;
		margin-bottom: 0;
	}

	.single-product .h4yf-pdp-priceline > .h4yf-pdp-score-section {
		flex: 0 0 auto;
		padding-left: 28px;
		border-left: 1px solid var(--h4yf-border, #3a3a3c);
		/* `.h4yf-score-block` declares `container-type: inline-size`, which makes
		   it size-contained — its intrinsic width resolves to 0, so `flex: 0 0
		   auto` collapsed the whole scoreboard to 41px on the first live run.
		   `max-content` restores a real intrinsic width; dropping the containment
		   inside the price line keeps it honest rather than papering over it.
		   Measured after: 257px beside a 251px price. */
		min-width: max-content;
	}

	.single-product .h4yf-pdp-priceline .h4yf-score-block {
		container-type: normal;
	}
}

/* Numeric score — PDP rows only (h4yf-score-num is not emitted on cards).
   Tabular so 4.0 and 3.5 occupy the same width down the column. */
.h4yf-score-num {
	min-width: 2.2em;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-meta, 12px);
	color: var(--h4yf-ink);
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ */
/* Sprint 6.6 punch-list P2-10 — RESOLVED BY REMOVAL                    */
/* ------------------------------------------------------------------ */
/* The overrides that lived here (repaint the CookieYes revisit tab to
   crimson, and lift it 71px so it stopped covering ~45x41px of the mobile
   sticky ATC) are gone because CookieYes is gone: Josh, 2026-08-02,
   "US only, rip it out" — no CMP on this site, so there is no tab to
   restyle and no tab to move off the buy button.

   Deliberately not left behind "just in case". Dead selectors for a plugin
   that is no longer installed cost a UCSS whitelist entry each to survive
   at all (they were being stripped as unused), which is maintenance for
   markup that no longer exists. If a consent banner ever returns, its own
   overrides come back with it and get measured then. */

/* ------------------------------------------------------------------ */
/* Vault popup (#h4yf-popup) — ported from WPCode snippet 917, #377     */
/* ------------------------------------------------------------------ */
/* Was live-only code in no git repo (GOTCHAS, "The server can run code
   that is in NO git repo"); snippet 917 printed its CSS last on the page
   (sheet 15 of 16), which is why P2-13's eyebrow fix had to be an
   ID-scoped override to win the tie. Now that the source lives here,
   cascade order does the winning and the eyebrow is a plain rule below —
   no override needed. Markup: inc/vault-popup.php. Behavior: assets/skin.js
   "Vault popup" section. IDs/classes unchanged from the snippet — Sprint
   6.9's .h4yf-vault-trigger click wiring in skin.js depends on them. */
/* [FIXED 2026-08-05, Josh punch list: no black wallpaper/fills site-wide.]
   Was `#141414` — reads as black, off the charcoal token entirely (same
   deprecated value style.css:18-22 documents as the old, retired floor). */
#h4yf-popup { position: fixed; bottom: 24px; right: 24px; width: 320px; background: var(--h4yf-charcoal-2); border: 1px solid #2A2A2A; border-top: 3px solid #C41E1E; border-radius: 10px; box-shadow: 0 8px 40px rgba(0,0,0,.7); z-index: var(--h4yf-z-toast); font-family: 'Montserrat', sans-serif; transform: translateY(120%); opacity: 0; transition: transform .4s cubic-bezier(.16,1,.3,1), opacity .3s ease; pointer-events: none; }
#h4yf-popup.h4yf-popup--visible { transform: translateY(0); opacity: 1; pointer-events: all; }
#h4yf-popup.h4yf-popup--hiding { transform: translateY(120%); opacity: 0; pointer-events: none; }
.h4yf-popup__inner { padding: 20px 20px 16px; }
.h4yf-popup__close { position: absolute; top: 2px; right: 4px; background: none; border: none; color: var(--h4yf-gray); font-size: 1.2rem; cursor: pointer; padding: 11px 13px; line-height: 1; border-radius: 4px; z-index: 2; min-width: var(--h4yf-tap-floor, 44px); min-height: var(--h4yf-tap-floor, 44px); display: flex; align-items: center; justify-content: center; }
.h4yf-popup__close:hover { color: #FAFAFA; background: #2A2A2A; }
/* `.6rem` (8.76px) was under the 12px meta floor, unreadable at arm's length
   (measured live 2026-08-02, P2-13). Fixed here directly instead of via
   override now that this rule wins the cascade on its own. Crimson-as-text
   elsewhere in this component is a deliberate AA exception, D22. */
.h4yf-popup__eyebrow { font-size: var(--h4yf-fs-meta, 12px); font-weight: 700; letter-spacing: .25em; text-transform: uppercase; color: #C41E1E; margin: 0 0 6px; }
.h4yf-popup__title { font-family: 'Bebas Neue', sans-serif; font-size: var(--h4yf-fs-h3); letter-spacing: .06em; color: #FAFAFA; margin: 0 0 6px; line-height: 1.05; }
.h4yf-popup__sub { font-size: var(--h4yf-fs-body); color: #9A9A9A; margin: 0 0 14px; line-height: 1.5; }
.h4yf-popup__form { display: flex; flex-direction: column; gap: 8px; }
/* The expanded form's two controls compute to ~39px and ~43px from padding
   alone — under the floor the same way the close/expand buttons were (#422).
   They are only reachable after a tap on the expand button, which is why the
   live sweep that filed #422 never saw them; they are violations all the same. */
/* [FIXED 2026-08-05, Josh punch list.] Was `#0A0A0A` — same black-fill issue
   as #h4yf-popup above. Selector widened from [type="email"] to also cover
   the new Name (text) + Mobile (tel) fields added the same session. */
/* 16px literal, not a token: below 16px iOS Safari zooms the viewport on
   focus. `.8rem` rendered 11.7px against the 14.592px root defect (#870). */
.h4yf-popup__form input[type="email"],
.h4yf-popup__form input[type="text"],
.h4yf-popup__form input[type="tel"] { background: var(--h4yf-charcoal); border: 1px solid #3A3A3A; border-radius: 6px; padding: 11px 14px; color: #FAFAFA; font-family: 'Montserrat', sans-serif; font-size: 16px; outline: none; width: 100%; box-sizing: border-box; min-height: var(--h4yf-tap-floor, 44px); transition: border-color .2s; }
.h4yf-popup__form input[type="email"]:focus,
.h4yf-popup__form input[type="text"]:focus,
.h4yf-popup__form input[type="tel"]:focus { border-color: #C41E1E; }
.h4yf-popup__form input[type="email"]::placeholder,
.h4yf-popup__form input[type="text"]::placeholder,
.h4yf-popup__form input[type="tel"]::placeholder { color: var(--h4yf-gray); }
.h4yf-popup__form button[type="submit"] { background: #C41E1E; color: #FAFAFA; font-family: 'Bebas Neue', sans-serif; font-size: var(--h4yf-fs-cta); letter-spacing: .1em; padding: 12px; border: none; border-radius: 6px; cursor: pointer; transition: opacity .2s; width: 100%; min-height: var(--h4yf-tap-floor, 44px); }
.h4yf-popup__form button[type="submit"]:hover { opacity: .88; }
/* Same defect class as .h4yf-popup__eyebrow above (`.6rem` = 8.76px against
   the 14.592px root, under the 12px meta floor) — same fix (#870). */
.h4yf-popup__fine { font-size: var(--h4yf-fs-meta, 12px); color: var(--h4yf-gray); text-align: center; margin: 8px 0 0; }
.h4yf-popup__success { display: none; text-align: center; padding: 8px 0 4px; }
/* [FIXED 2026-08-04, impeccable polish pass] Was `#4CAF50` — Material Design's
   green, and the only hex on the popup that traces to no H4YF token. The palette
   has no success colour by design; "You're in." plus the brand flame already say
   it, so this is ink rather than a fifth invented hue. */
.h4yf-popup__success p { color: var(--h4yf-ink); font-size: var(--h4yf-fs-body); font-weight: 600; margin: 0; display: flex; align-items: center; gap: 6px; }
.h4yf-popup__success span { display: block; color: #9A9A9A; font-size: var(--h4yf-fs-meta); margin-top: 4px; }
.h4yf-popup__brand { display: flex; align-items: center; gap: 6px; border-top: 1px solid #2A2A2A; padding: 10px 20px; }
.h4yf-popup__brand span { font-size: var(--h4yf-fs-meta, 12px); color: var(--h4yf-gray); letter-spacing: .1em; text-transform: uppercase; }
/* [FIXED 2026-08-04, impeccable polish pass] These three glyphs were literal
   `🔥` emoji in inc/vault-popup.php — the site's ONLY real emoji after the
   score flames turned out to be a masked SVG. They now reuse `.h4yf-f--full`,
   the potrace-traced H4YF brand flame already defined in §FLAMES, so the popup
   shows the same mark as the scoreboard instead of the OS emoji font. Sizing
   only lives here; fill and mask come from .h4yf-f. */
.h4yf-popup__flame { width: 16px; height: 16px; flex-shrink: 0; }
.h4yf-popup__compact-row { display: none; align-items: center; gap: 10px; }
.h4yf-popup__compact-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: 'Bebas Neue', sans-serif; font-size: var(--h4yf-fs-body); letter-spacing: .04em; color: #FAFAFA; }
.h4yf-popup__expand-btn { flex-shrink: 0; background: #C41E1E; color: #FAFAFA; font-family: 'Bebas Neue', sans-serif; font-size: var(--h4yf-fs-meta); letter-spacing: .08em; padding: 9px 14px; border: none; border-radius: 6px; cursor: pointer; white-space: nowrap; min-height: var(--h4yf-tap-floor, 44px); }
@media (max-width: 480px) {
	#h4yf-popup { bottom: 0; right: 0; left: 0; width: 100%; border-radius: 10px 10px 0 0; max-height: 15vh; overflow: hidden; transition: max-height .35s cubic-bezier(.16,1,.3,1), transform .4s cubic-bezier(.16,1,.3,1), opacity .3s ease; }
	#h4yf-popup.h4yf-popup--expanded { max-height: 70vh; overflow-y: auto; }
	/* Right pad clears the absolutely-positioned close button, which is
	   `right: 4px` and now 44px wide (#422) — 4 + 44 = 48. At the old 44 the
	   close overlapped the compact row's expand button by 4px. */
	#h4yf-popup .h4yf-popup__inner { padding: 12px 48px 12px 16px; }
	#h4yf-popup .h4yf-popup__eyebrow,
	#h4yf-popup .h4yf-popup__title,
	#h4yf-popup .h4yf-popup__sub,
	#h4yf-popup .h4yf-popup__form,
	#h4yf-popup .h4yf-popup__fine,
	#h4yf-popup .h4yf-popup__brand { display: none; }
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__eyebrow,
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__title,
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__sub,
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__fine,
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__brand { display: block; }
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__form { display: flex; }
	#h4yf-popup .h4yf-popup__compact-row { display: flex; }
	#h4yf-popup.h4yf-popup--expanded .h4yf-popup__compact-row { display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   JOSH PUNCH LIST — 2026-08-04
   Crimson side rule, credibility bar, guarantee panel, four-tile mosaic,
   YouTube rail, FAQ disclosure, shop filter control.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- The crimson side rule -----------------------------------------------
   Josh: "add side crimson eyebrow line to main section titles/headings".

   A crimson `border-left` is CANON here, not a violation — DESIGN.md §1 names
   it explicitly ("Crimson side-stripes are brand canon… the Curator's Take
   teaser is the reference use. Generic design-system rules that class
   side-stripe borders as 'never intentional' do not apply here"). It is
   applied as a rule on the TITLE, deliberately, rather than as a tracked
   uppercase kicker above every section: the kicker-on-everything pattern is
   scaffolding, a mark on the heading is a brand device. One class, opt-in per
   heading, so a centred section never gets a left rule it cannot align to. */
.h4yf-skin .h4yf-rule {
	padding-left: clamp(10px, 1.4vw, 16px);
	border-left: 3px solid var(--h4yf-crimson);
}

/* Optical: Bebas sits high in its box, so a rule matching the full line-height
   overhangs the cap height at the bottom. Trimming to the text box keeps the
   stripe reading as a mark on the word rather than a bar beside a gap. */
.h4yf-skin h1.h4yf-rule,
.h4yf-skin h2.h4yf-rule,
.h4yf-skin h3.h4yf-rule {
	line-height: 1.06;
}

/* The kicker variant — used where a block genuinely needs a label above the
   title (content blocks on About/Authentication/Culture), never as section
   grammar on the homepage. */
.h4yf-skin .h4yf-eyebrow {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0 0 8px;
	color: var(--h4yf-crimson);
	font-family: var(--h4yf-body);
	font-weight: 800;
	font-size: var(--h4yf-fs-meta);
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.h4yf-skin .h4yf-eyebrow::before {
	content: "";
	flex: 0 0 auto;
	width: 22px;
	height: 3px;
	background: var(--h4yf-crimson);
}

/* ---- Buttons with a leading glyph ---------------------------------------- */
.h4yf-skin .h4yf-btn--icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
}

.h4yf-skin .h4yf-yt-glyph {
	flex: 0 0 auto;
	/* Optical: the YouTube rounded-rect reads heavy next to Bebas caps, so it
	   sits a hair below the cap line rather than centred on the em box. */
	transform: translateY(0.5px);
}

/* ---- Credibility bar -----------------------------------------------------
   Josh: "Change the '650+ Pairs…, 12-Point Authentication.., 99.1% Positive..,
   FREE Shipping..' Back to a bar vs plain text."

   ROOT CAUSE, not a restyle: `.h4yf-home-trust` and `.h4yf-trust-stat` had NO
   layout rules anywhere in this file — only `.h4yf-trust-stat__link`'s colour
   was ever written (line ~985). The markup has shipped since D16 with four
   unstyled divs, so the four stats ran together as one paragraph at every
   viewport. This is the missing half, not an override. */
.h4yf-skin .h4yf-home-trust {
	margin: clamp(24px, 5vw, 40px) 0 0;
	background: var(--h4yf-charcoal-2);
	border-top: 1px solid var(--h4yf-border);
	border-bottom: 1px solid var(--h4yf-border);
}

.h4yf-skin .h4yf-home-trust__inner {
	display: grid;
	/* Two-up on a phone, four-up from tablet. `1fr` columns rather than
	   auto-fit: these four are a fixed set that should read as one bar, and
	   auto-fit would reflow them 3+1 at intermediate widths. */
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1px;
	max-width: 1180px;
	margin: 0 auto;
	background: var(--h4yf-border);
}

@media (min-width: 861px) {
	.h4yf-skin .h4yf-home-trust__inner {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/* Cells sit on the FLOOR, not the wall, and the wall shows only through the 1px
   grid gap as a divider. That is the original `.h4yf-home-strip` construction
   and it is a contrast fix, not a preference: `--h4yf-gray` (#8C8C8C) is the
   documented label colour and its 5.1:1 was measured against `--h4yf-charcoal`.
   On `--h4yf-charcoal-2` the same token drops to 4.14:1 — under the 4.5:1 AA
   floor for a 10px label. Measured in the render harness; on the floor it is
   4.66:1 and passes, with no new token and no raw hex. */
.h4yf-skin .h4yf-trust-stat {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	padding: clamp(16px, 3vw, 24px) 14px;
	text-align: center;
	background: var(--h4yf-charcoal);
}

.h4yf-skin .h4yf-trust-stat b {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-trust-stat);
	line-height: 1;
	color: var(--h4yf-ink);
	text-transform: uppercase;
}

.h4yf-skin .h4yf-trust-stat > span {
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-size: var(--h4yf-fs-trust-label);
	line-height: 1.4;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	/* 4.66:1 on the wall — AA for this size. Not the lighter muted gray. */
	color: var(--h4yf-gray);
	text-wrap: balance;
}

/* ---- Guarantee panel -----------------------------------------------------
   Josh: "Stylize 'THE GUARANTEE' block so it's not just plain text."
   Seal + promise + the three checkable terms. Still hairline-bounded, never a
   crimson fill — the Never-a-Bar rule is unchanged. */
.h4yf-skin .h4yf-home-guarantee {
	position: relative;
	background:
		radial-gradient(120% 100% at 50% 0%, rgba(196, 30, 30, 0.09), transparent 62%),
		var(--h4yf-charcoal);
}

.h4yf-skin .h4yf-guarantee-seal {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 58px;
	height: 58px;
	margin: 0 auto 14px;
	color: var(--h4yf-crimson);
	border: 2px solid var(--h4yf-crimson);
	border-radius: 999px;
}

.h4yf-skin .h4yf-home-guarantee__terms {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 8px 10px;
	margin: 0 0 18px;
	padding: 0;
	list-style: none;
}

.h4yf-skin .h4yf-home-guarantee__terms li {
	padding: 7px 13px;
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 999px;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-meta);
	letter-spacing: 0.03em;
	color: var(--h4yf-body-color, #e2e2e2);
}

/* ---- Four-tile mosaic ----------------------------------------------------
   The TEAM tile joins Drops / Pickups / Reviews (Josh 2026-08-04). It is a
   <button> because it opens the capture popup rather than navigating, so the
   button reset has to be undone to match its three <a> siblings exactly. */
.h4yf-skin .h4yf-mosaic {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
	gap: 10px;
}

/* Getting a <button> to size identically to its three <a> siblings needs
   `border-box` matched explicitly, plus the UA button border cleared.
   [CORRECTED 2026-08-05, caught in LIVE verification after deploy — a static
   render harness had this WRONG and the wrong fix shipped once already.]

   `box-sizing` — the harness (skin.css + premier.css + style.css only, no
   Astra parent stylesheet loaded) measured the `<a>` siblings as content-box,
   so `.h4yf-tile--team` was set to content-box to match, and the harness
   confirmed all four tiles equal. Live, Astra's own theme.css applies a
   sitewide `box-sizing: border-box` reset that the harness never loaded — so
   on the real site the `<a>` siblings are border-box, and content-box on the
   button ADDED the 24px×2 padding on top of the aspect-ratio'd box instead of
   inside it: 197px against the siblings' 181px. This is exactly the class of
   bug `docs/GOTCHAS.md`'s "verify the browser instrument first" entry warns
   about, one layer further back — the STATIC HARNESS was the unreliable
   instrument here, not the live browser, and this repo's own binding
   standard ("Live-measured or it didn't happen") is why this was caught
   before Josh saw it rather than after.

   `border-top/left/right` — the UA's default button border is 2px, which the
   `<a>` tiles do not have. Bottom is left alone deliberately, so the shared
   `.h4yf-mosaic .h4yf-tile` divider still applies. Clearing `border-right` is
   safe because this tile is always last, and `:last-child` already removes
   the desktop divider there.

   Padding is NOT reset — zeroing it was the very first attempt (pre-dating
   even the content-box mistake) and it made the size gap worse, not better. */
.h4yf-skin .h4yf-tile--team {
	appearance: none;
	box-sizing: border-box;
	width: 100%;
	margin: 0;
	border-top: 0;
	border-left: 0;
	border-right: 0;
	font: inherit;
	color: inherit;
	text-align: left;
	cursor: pointer;
	background: var(--h4yf-charcoal-2);
}

.h4yf-skin .h4yf-mosaic .h4yf-tile--team::before {
	/* No photo for this one — a crimson wash reads as the brand's own surface
	   rather than an arbitrary sneaker standing in for a mailing list. */
	background-image: linear-gradient(150deg, rgba(196, 30, 30, 0.34), rgba(35, 35, 38, 0.9));
}

/* The crimson mark that makes each tile read as a content block
   (Josh: "Add crimson side eyebrow to each content block"). */
.h4yf-skin .h4yf-mosaic .h4yf-tile__kicker {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	color: var(--h4yf-ink);
}

.h4yf-skin .h4yf-mosaic .h4yf-tile__kicker::before {
	content: "";
	flex: 0 0 auto;
	width: 20px;
	height: 3px;
	background: var(--h4yf-crimson);
}

/* ---- YouTube rail -------------------------------------------------------- */
.h4yf-skin .h4yf-yt-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.h4yf-skin .h4yf-yt-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin: 18px 0 0;
}

/* ---- FAQ disclosure ------------------------------------------------------
   Native <details>. No script, keyboard-operable for free, and the answers are
   in the DOM for crawlers and in-page search whether or not they are open. */
.h4yf-skin .h4yf-faq__list {
	display: grid;
	gap: 8px;
}

.h4yf-skin .h4yf-faq__item {
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
}

.h4yf-skin .h4yf-faq__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 14px;
	/* Over the 44px tap floor at every viewport. */
	min-height: 52px;
	padding: 12px 16px;
	cursor: pointer;
	list-style: none;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(17px, 0.6vw + 15px, 21px);
	letter-spacing: 0.02em;
	color: var(--h4yf-ink);
	text-transform: uppercase;
}

/* Safari still paints its own disclosure triangle without this. */
.h4yf-skin .h4yf-faq__q::-webkit-details-marker {
	display: none;
}

.h4yf-skin .h4yf-faq__q::after {
	content: "";
	flex: 0 0 auto;
	width: 11px;
	height: 11px;
	border-right: 2px solid var(--h4yf-crimson);
	border-bottom: 2px solid var(--h4yf-crimson);
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform 200ms var(--h4yf-ease-out-expo, cubic-bezier(0.16, 1, 0.3, 1));
}

.h4yf-skin .h4yf-faq__item[open] > .h4yf-faq__q::after {
	transform: rotate(-135deg) translate(-2px, -2px);
}

.h4yf-skin .h4yf-faq__item[open] > .h4yf-faq__q {
	border-bottom: 1px solid var(--h4yf-border);
}

.h4yf-skin .h4yf-faq__a {
	padding: 14px 16px 16px;
}

.h4yf-skin .h4yf-faq__a p {
	margin: 0;
	max-width: 68ch;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	line-height: 1.65;
	color: var(--h4yf-body-color, #e2e2e2);
	text-wrap: pretty;
}

.h4yf-skin .h4yf-faq__more {
	margin: 18px 0 0;
}

@media (prefers-reduced-motion: reduce) {
	.h4yf-skin .h4yf-faq__q::after {
		transition: none;
	}
}

/* ---- Shop flyout Filter control ------------------------------------------
   Josh: "Enlarge the shop FILTER button and make crimson vs. hard to see grey."

   Measured on slate 2026-08-04: the control was a 68x44 transparent link whose
   inner `.astra-woo-filter-text` rendered `rgb(30,41,59)` — Astra's own slate,
   inherited from the addon's stylesheet, giving 1.3:1 against the charcoal
   floor. It was effectively invisible, and it is the ONLY entry point to every
   facet on the archive. Colour is set on the CHILD as well as the parent
   because the child carries its own explicit declaration. */
.h4yf-skin .astra-shop-filter-button.ast-flyout-filter {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
	min-height: 48px;
	padding: 0 20px;
	background: var(--h4yf-crimson);
	border: 0;
	border-radius: var(--h4yf-radius-md, 6px);
	color: var(--h4yf-ink);
	text-decoration: none;
	transition: opacity 0.15s ease;
}

.h4yf-skin .astra-shop-filter-button.ast-flyout-filter .astra-woo-filter-text {
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
}

.h4yf-skin .astra-shop-filter-button.ast-flyout-filter .astra-woo-filter-icon,
.h4yf-skin .astra-shop-filter-button.ast-flyout-filter svg {
	color: var(--h4yf-ink);
	fill: currentColor;
}

.h4yf-skin .astra-shop-filter-button.ast-flyout-filter:hover,
.h4yf-skin .astra-shop-filter-button.ast-flyout-filter:focus-visible {
	opacity: 0.9;
	color: var(--h4yf-ink);
}

/* ---- Authentication page (rebuilt 2026-08-04) ---------------------------- */
.h4yf-skin .h4yf-auth-block {
	max-width: 68ch;
	margin: 0 0 clamp(20px, 4vw, 32px);
}

.h4yf-skin .h4yf-auth-block--panel {
	max-width: 760px;
	margin-inline: auto;
	padding: clamp(22px, 4vw, 36px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-left: 3px solid var(--h4yf-crimson);
	border-radius: 8px;
	text-align: left;
}

.h4yf-skin .h4yf-auth-block__text {
	margin: 0 0 14px;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	line-height: 1.65;
	color: var(--h4yf-body-color, #e2e2e2);
	text-wrap: pretty;
}

.h4yf-skin .h4yf-auth-stats {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
	overflow: hidden;
}

/* -- Process: the one earned numbered sequence on the page ---------------- */
.h4yf-skin .h4yf-auth-steps {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: none;
}

.h4yf-skin .h4yf-auth-step {
	padding: clamp(18px, 3vw, 26px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
}

.h4yf-skin .h4yf-auth-step__n {
	display: block;
	margin: 0 0 8px;
	font-family: var(--h4yf-display);
	font-size: clamp(28px, 3vw, 38px);
	line-height: 1;
	color: var(--h4yf-crimson);
}

.h4yf-skin .h4yf-auth-step__title {
	margin: 0 0 8px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
}

.h4yf-skin .h4yf-auth-step__text {
	margin: 0;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	line-height: 1.6;
	color: var(--h4yf-body-color, #e2e2e2);
}

/* -- The twelve points ---------------------------------------------------- */
.h4yf-skin .h4yf-auth-points {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
	gap: 1px;
	margin: 0;
	padding: 0;
	list-style: none;
	background: var(--h4yf-border);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
	overflow: hidden;
}

.h4yf-skin .h4yf-auth-point {
	display: flex;
	align-items: center;
	gap: 12px;
	min-height: 56px;
	padding: 12px 16px;
	background: var(--h4yf-charcoal-2);
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-size: var(--h4yf-fs-meta);
	line-height: 1.45;
	color: var(--h4yf-body-color, #e2e2e2);
}

/* The check is decorative — the list semantics already say "these twelve
   things". Drawn rather than a glyph so it inherits crimson and never depends
   on an emoji font. */
.h4yf-skin .h4yf-auth-point::before {
	content: "";
	flex: 0 0 auto;
	width: 13px;
	height: 8px;
	border-left: 2px solid var(--h4yf-crimson);
	border-bottom: 2px solid var(--h4yf-crimson);
	transform: rotate(-45deg);
}

/* -- Guides by silhouette ------------------------------------------------- */
.h4yf-skin .h4yf-auth-guides__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
	gap: 10px;
}

.h4yf-skin .h4yf-auth-guide {
	padding: clamp(18px, 3vw, 26px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
}

.h4yf-skin .h4yf-auth-guide__title {
	margin: 0 0 16px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
}

.h4yf-skin .h4yf-auth-guide__markers {
	margin: 0;
}

.h4yf-skin .h4yf-auth-guide__markers dt {
	margin: 0 0 4px;
	font-family: var(--h4yf-body);
	font-weight: 800;
	font-size: var(--h4yf-fs-meta);
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
}

.h4yf-skin .h4yf-auth-guide__markers dd {
	margin: 0 0 16px;
	padding: 0 0 16px;
	border-bottom: 1px solid var(--h4yf-border);
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	line-height: 1.6;
	color: var(--h4yf-body-color, #e2e2e2);
	text-wrap: pretty;
}

.h4yf-skin .h4yf-auth-guide__markers dd:last-child {
	margin-bottom: 0;
	padding-bottom: 0;
	border-bottom: 0;
}

/* -- The one chip that is an action, not a filter ------------------------- */
.h4yf-skin .h4yf-dropsnav__link--cta {
	background: var(--h4yf-crimson);
	border-color: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

.h4yf-skin .h4yf-dropsnav__link--cta:hover,
.h4yf-skin .h4yf-dropsnav__link--cta:focus-visible {
	opacity: 0.9;
	color: var(--h4yf-ink);
	border-color: var(--h4yf-hover);
}

/* ---- About page: block content + intro video (2026-08-04) ---------------- */
/* The two editorial groups in `post_content` (Our Promise / For the Real Ones)
   read as run-on prose because nothing distinguished them from the paragraphs
   around them. Their eyebrows come from a `the_content` filter in
   page-about.php; the block treatment is here. Scoped to DIRECT children so
   nested groups inside a block don't stack panels — nested cards are always
   wrong. */
.h4yf-skin .h4yf-about-content > .wp-block-group {
	margin: 0 0 clamp(20px, 4vw, 34px);
	padding: clamp(20px, 4vw, 34px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-left: 3px solid var(--h4yf-crimson);
	border-radius: 8px;
}

.h4yf-skin .h4yf-about-content > .wp-block-group .wp-block-group {
	padding: 0;
	background: none;
	border: 0;
}

.h4yf-skin .h4yf-about-video {
	margin: 0 0 clamp(24px, 5vw, 40px);
}

.h4yf-skin .h4yf-about-video__title {
	margin: 0 0 14px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
}

.h4yf-skin .h4yf-about-video__sub {
	margin: 0 0 16px;
	max-width: 68ch;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-body);
	line-height: 1.6;
	color: var(--h4yf-body-color, #e2e2e2);
	text-wrap: pretty;
}
/* ---- Culture page (2026-08-04) ------------------------------------------- */
/* Section headings inside the Gutenberg body get the crimson rule too, so the
   editorial content and the template-rendered sections read as one page. Only
   `alignfull`/`alignwide` group headings — an h2 inside a narrow column is a
   sub-heading, not a section title, and a rule on it would be noise. */
.h4yf-skin .h4yf-culture-content > .wp-block-group > .wp-block-heading:not(.has-text-align-center),
.h4yf-skin .h4yf-culture-content > .wp-block-heading:not(.has-text-align-center) {
	padding-left: clamp(10px, 1.4vw, 16px);
	border-left: 3px solid var(--h4yf-crimson);
}

/* "Latest Guides" ships as core's Latest Posts block: a bare <ul> of links with
   a date under each. Josh: content blocks, not plain text. Restyled in place
   rather than replaced with a custom query — the block is already correct
   markup and already editor-managed, it was only ever missing its treatment. */
.h4yf-skin .wp-block-latest-posts,
.h4yf-skin .wp-block-latest-posts__list {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.h4yf-skin .wp-block-latest-posts > li,
.h4yf-skin .wp-block-latest-posts__list > li {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: clamp(16px, 3vw, 22px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-left: 3px solid var(--h4yf-crimson);
	border-radius: 8px;
	transition: border-color 0.15s ease;
}

.h4yf-skin .wp-block-latest-posts > li:hover,
.h4yf-skin .wp-block-latest-posts__list > li:hover {
	border-color: var(--h4yf-hover);
}

.h4yf-skin .wp-block-latest-posts__post-title {
	display: block;
	/* Over the 44px tap floor: these are the page's primary links and they were
	   a bare 14px anchor in a list. */
	min-height: 44px;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(18px, 0.6vw + 16px, 22px);
	line-height: 1.2;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	text-decoration: none;
	text-wrap: balance;
}

.h4yf-skin .wp-block-latest-posts__post-date {
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-trust-label);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
}

/* -- Curator's Take cards -------------------------------------------------- */
.h4yf-skin .h4yf-ct-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
	gap: 10px;
}

.h4yf-skin .h4yf-ct-card {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: clamp(18px, 3vw, 26px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-left: 3px solid var(--h4yf-crimson);
	border-radius: 8px;
}

.h4yf-skin .h4yf-ct-card__title {
	margin: 0;
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h3);
	line-height: 1.15;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--h4yf-ink);
	text-wrap: balance;
}

.h4yf-skin .h4yf-ct-card__teaser {
	margin: 0;
	flex: 1 1 auto;
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-fs-meta);
	line-height: 1.6;
	color: var(--h4yf-body-color, #e2e2e2);
	text-wrap: pretty;
}

.h4yf-skin .h4yf-ct-card .h4yf-home-section__link {
	align-self: flex-start;
	color: var(--h4yf-crimson);
}

/* ---- Shop toolbar back into normal flow at mobile (2026-08-04) -----------
   Josh: "the mobile page order needs to follow the same as the desktop site …
   SHOP needs to be the next block - with shop filter above like normal, below
   the trust bar."

   ROOT CAUSE, measured on slate at clientWidth 390. The DOM order is already
   correct — `.ast-shop-toolbar-container` is the grid's immediate previous
   sibling at every viewport. Astra Pro then prints this INLINE in <head>:

     @media (max-width: 544px) {
       .ast-header-break-point .ast-shop-toolbar-container {
         position: fixed; bottom: 0; left: 0; right: 0; z-index: 590;
       }
     }

   So below 545px the whole toolbar — the Filter trigger, the result count and
   the sort select — leaves normal flow and becomes a bar pinned to the bottom
   of the viewport. Measured: toolbar at viewport-bottom while the grid starts
   at 147px, against desktop where the toolbar sits at 167 and the grid at 251.
   Same markup, two different reading orders. That is the divergence.

   Two reasons to put it back rather than keep Astra's pattern:
   1. Josh asked for it, and the filter is the only entry point to every facet.
   2. This site already owns the bottom of the mobile viewport — `body` carries
      `h4yf-bottombar-on`. A second fixed bar at z-index 590 is competing for
      the same strip of screen as the site's own bottom nav.

   SPECIFICITY: Astra's rule is (0,2,0) and it is INLINE in <head>, while
   LiteSpeed combines this file into an external bundle that loads BEFORE it —
   so an equal-specificity rule loses on source order (same trap documented at
   the top of this file for the h1 palette, and in GOTCHAS for the focus ring).
   `.ast-header-break-point` sits on <body>, so chaining it onto `body.h4yf-skin`
   gives (0,3,1) and wins without an `!important`. */
@media (max-width: 544px) {
	body.h4yf-skin.ast-header-break-point .ast-shop-toolbar-container {
		position: static;
		/* Astra zeroes this in the same breakpoint because a fixed bar needs no
		   flow spacing. Back in flow it does, or the toolbar butts into the
		   first row of products. */
		margin-bottom: 1.5em;
		/* Wraps rather than squeezing three controls onto one 390px line. */
		flex-wrap: wrap;
		gap: 10px;
	}

	body.h4yf-skin.ast-header-break-point.ast-woocommerce-shop-page-modern-style .ast-shop-toolbar-container {
		margin-bottom: 1.5em;
	}

	body.h4yf-skin.ast-header-break-point .ast-shop-toolbar-container .ast-shop-toolbar-aside-wrap {
		margin-bottom: 0;
	}
}

/* ═══════════════════════════════════════════════════════════════════════════
   JOSH PUNCH LIST — 2026-08-07
   Charcoal everywhere · one type scale · section-length crimson rules ·
   header wordmark · white YouTube CTA · Drops/Culture/Auth/About fixes ·
   shop controls · mobile filter · cart.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ---- 1. NO BLACK. ANYWHERE. ---------------------------------------------
   Josh: "Make the entire site background/wallpaper/sections the charcoal
   colour — no black background, boxes, headers or anything."

   `body.h4yf-skin` has carried the charcoal wash since 2026-08-05 and the
   TOKENS have been charcoal since 2026-08-02, so the theme was already clean.
   The black that survives is INLINE, in Gutenberg `post_content` — measured on
   slate 2026-08-07: six `#0A0A0A` groups + two `#1C1C1C` on /about/, five
   `#1C1C1C` + two `#0A0A0A` on /culture/, plus a `#FFFFFF` panel. Those are
   `style=""` attributes, so no ordinary rule can reach them; a substring
   attribute selector plus `!important` is what actually beats an inline value.

   Matched on the HEX rather than on `.has-background`, deliberately: a block
   deliberately set to charcoal-2 is correct and must not be flattened. Only the
   four values that read as black (or as a white box) are overridden, and adding
   a fifth is a one-line edit here rather than a hunt through the editor on one
   server. The real repair is to clear these in the block editor — this rule is
   the floor that holds until someone does, and it costs nothing if they never
   do.  ponytail: four selectors beat auditing 300 blocks by hand. */
.h4yf-skin [style*="#0A0A0A"],
.h4yf-skin [style*="#0a0a0a"],
.h4yf-skin [style*="#1C1C1C"],
.h4yf-skin [style*="#1c1c1c"],
.h4yf-skin [style*="#141414"],
.h4yf-skin [style*="#000000"],
.h4yf-skin [style*="background-color:#FFFFFF"],
.h4yf-skin [style*="background-color:#ffffff"] {
	background-color: var(--h4yf-charcoal-2) !important;
}

/* An `alignfull` band set to black was reading as a black SECTION, not a card.
   Full-bleed groups go back to the page's own wash so the wallpaper is
   continuous — the whole point of the directive. */
.h4yf-skin .alignfull[style*="#0A0A0A"],
.h4yf-skin .alignfull[style*="#0a0a0a"],
.h4yf-skin .alignfull[style*="#141414"] {
	background-color: transparent !important;
}

/* The Mailchimp embed in `post_content` ships its own black panel and gradient
   (`.mc-inline-wrap`, authored before the charcoal directive). Same treatment,
   by class rather than by hex because this one is in a <style> block. */
.h4yf-skin .mc-inline-wrap {
	background: var(--h4yf-charcoal-2) !important;
	border-color: var(--h4yf-border) !important;
}

.h4yf-skin .mc-inline-form input[type="email"] {
	background: var(--h4yf-charcoal) !important;
	border-color: var(--h4yf-border) !important;
}

/* ---- 2. ONE TYPE SCALE ---------------------------------------------------
   Josh: "Right-size ALL section titles/headers/body to match/be uniform/
   coordinated across whole site."

   Nothing new is invented here. `style.css` already defines the fluid scale
   (`--h4yf-fs-h1…--h4yf-fs-trust-label`); these selectors are the ones that
   were still carrying a hand-typed size and therefore drifting from it.

   TWO of them were also live bugs, not just inconsistencies: `rem` bounds are
   wrong on this site. Astra sets the root font-size to 91.2% below its tablet
   breakpoint (14.592px, not 16), so every `rem` here rendered ~8.8% under spec
   on a phone while reading correctly on desktop — the exact defect the token
   block was converted from `rem` to `px` for on 2026-08-02. Two selectors were
   missed in that pass and are fixed now. */
.h4yf-skin .h4yf-reviews-header__title {
	font-size: var(--h4yf-fs-h1);
}

.h4yf-skin .h4yf-pdp-capture__title {
	font-size: var(--h4yf-fs-h3);
}

.h4yf-skin .h4yf-pdp-capture__sub,
.h4yf-skin .h4yf-reviews-header__sub,
.h4yf-skin .h4yf-home-vault__sub {
	font-size: var(--h4yf-fs-body);
}

/* Kickers/eyebrows: five different hand-typed sizes (12/12/12/13/14px) for one
   role. They are all the same thing — a small uppercase label above a title. */
.h4yf-skin .h4yf-home-vault__kicker,
.h4yf-skin .h4yf-reviews-header__kicker,
.h4yf-skin .h4yf-reviews-metric__name,
.h4yf-skin .h4yf-reviews-metric__sub,
.h4yf-skin .h4yf-drop-alert__sub,
.h4yf-skin .h4yf-pw-cop__kicker {
	font-size: var(--h4yf-fs-meta);
}

.h4yf-skin .h4yf-drawer__title,
.h4yf-skin .h4yf-cart-state__title {
	font-size: var(--h4yf-fs-h3);
}

.h4yf-skin .h4yf-cart-line__name {
	font-size: var(--h4yf-fs-body);
}

/* Shop-card titles at 32px on desktop were the single loudest type on the site
   — larger than most section subheads and out of step with every other card
   title. `--h4yf-fs-h3` is the card-title step (20–28px) and is what the Radar,
   Archive and Pickups cards already use. The `min-height` reservation that
   keeps two-line titles from clipping is untouched. */
@media (min-width: 769px) {
	.h4yf-skin .woocommerce ul.products li.product .woocommerce-loop-product__title {
		font-size: var(--h4yf-fs-h3);
	}
}

/* ---- 3. THE SECTION-LENGTH CRIMSON RULE ---------------------------------
   Josh names two different marks and they were being conflated:
     · `.h4yf-rule`         — the SHORT rule beside a heading (existing).
     · `.h4yf-rule-section` — the FULL-LENGTH rule down a whole section (new).

   Where a section gets the full rule, the short kicker dash inside it is
   suppressed: that is exactly the "remove the small left eyebrow, keep the
   full-length one" instruction, expressed once instead of per page. Same
   3px/crimson as `.h4yf-rule` so the two read as one device at two scales. */
.h4yf-skin .h4yf-rule-section {
	padding-left: clamp(14px, 2vw, 22px);
	border-left: 3px solid var(--h4yf-crimson);
}

.h4yf-skin .h4yf-rule-section .h4yf-eyebrow::before,
.h4yf-skin .h4yf-rule-section .h4yf-home-vault__kicker::before,
.h4yf-skin .h4yf-rule-section .h4yf-pw-cop__kicker::before {
	display: none;
}

/* The four homepage tiles — Drops Center · The Pickups Wall · Reviews ·
   Request a Pair — and the "650+ / 12-Point / 99.1% / FREE Shipping"
   credibility bar. Josh asked for the rule on the CONTENT SECTION, not on the
   heading, so it runs the full height of each tile.

   `position: relative` on `.h4yf-mosaic .h4yf-tile` already exists (the tiles
   layer a background image in `::before`), so a border participates normally
   and does not sit under the image overlay. */
.h4yf-skin .h4yf-mosaic .h4yf-tile {
	border-left: 3px solid var(--h4yf-crimson);
}

.h4yf-skin .h4yf-home-trust__inner {
	border-left: 3px solid var(--h4yf-crimson);
	padding-left: clamp(14px, 2vw, 22px);
}

/* Flex Your COP (Drops Center + Pickups Wall) and the Never Miss a Drop band —
   "add crimson left eyebrow to the section, not just the title", and "change
   the small left mid-line to a full-section left eyebrow". The vault band's
   crimson `border-top` goes with it: a rule on two edges reads as a box, and
   the standing Never-a-Bar rule is what that border was already skirting. */
.h4yf-skin .h4yf-pw-cop,
.h4yf-skin .h4yf-home-vault {
	border-left: 3px solid var(--h4yf-crimson);
}

.h4yf-skin .h4yf-home-vault {
	border-top: 0;
}

.h4yf-skin .h4yf-pw-cop__kicker::before,
.h4yf-skin .h4yf-home-vault__kicker::before {
	display: none;
}

/* ---- 4. HEADER + BUTTONS ------------------------------------------------- */
/* The header now always renders the spelled-out wordmark (inc/header.php).
   It was previously a 40px-tall image slot, so the text lockup needs the size
   the badge was occupying or the header reads empty next to the cart icon. */
.h4yf-skin .h4yf-logo--text {
	font-size: clamp(20px, 1.2vw + 16px, 26px);
	letter-spacing: 0.05em;
	white-space: nowrap;
}

/* "Make the WATCH THE CHANNEL YouTube button White on every page." A white
   fill, not a white outline — it was already white-on-transparent with a red
   hairline, which is what read as "not a button" in the first place. Charcoal
   ink on white measures 15.0:1, and the YouTube glyph keeps its own red so the
   channel is still identifiable at a glance. */
.h4yf-skin .h4yf-btn--yt,
.h4yf-skin .h4yf-btn--yt.h4yf-btn--ghost {
	background: #FFFFFF;
	color: var(--h4yf-charcoal);
	border: 1px solid #FFFFFF;
}

.h4yf-skin .h4yf-btn--yt:hover,
.h4yf-skin .h4yf-btn--yt:focus-visible {
	color: var(--h4yf-charcoal);
	opacity: 0.9;
}

/* Section-head buttons — the "All 100+ Questions" pointer beside a heading is a
   crimson button now (Josh), and at full `.h4yf-btn` size it would outweigh the
   heading it sits next to. Tap floor is held at 44px, not shrunk to match the
   type. */
.h4yf-skin .h4yf-btn--sm {
	min-height: var(--h4yf-tap-floor, 44px);
	padding: 0 14px;
	font-size: var(--h4yf-fs-subhead);
}

/* ---- 5. DROPS CENTER ----------------------------------------------------- */
/* "MISSED HEAT" beside The Archive, in crimson (Josh). It shared the muted grey
   `.h4yf-radar__tag` treatment with "Upcoming"/"Restocking", which made the one
   tag that means "you missed this" the quietest of the three. */
.h4yf-skin .h4yf-radar__tag--past {
	color: var(--h4yf-crimson);
	border-color: var(--h4yf-crimson);
}

/* The drop date, now printed on every Radar / New Drops card and on every
   Archive card. Metadata weight — it sits under the title and must not compete
   with it. */
.h4yf-skin .h4yf-radar-card__date,
.h4yf-skin .h4yf-drop-card__status {
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-trust-label);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
	margin: 0 0 6px;
}

.h4yf-skin .h4yf-radar-card__date time,
.h4yf-skin .h4yf-drop-card__status time {
	color: var(--h4yf-ink);
}

/* ---- 6. CULTURE ---------------------------------------------------------- */
/* "Change the EXPLORE BY TOPIC content blocks' titles from default blue to
   brand crimson."

   ROOT CAUSE, not a recolour: each `<h3>` ALREADY carries an inline
   `color:#C41E1E` from the editor. The blue is the `<a>` INSIDE it, which does
   not inherit and falls through to the default link colour — so recolouring the
   heading again would have changed nothing. `color: inherit` on the anchor is
   the fix, and it keeps working if the editor ever changes the heading colour. */
.h4yf-skin .h4yf-culture-content .wp-block-column h3 a,
.h4yf-skin .h4yf-culture-content .wp-block-column h2 a {
	color: inherit;
	text-decoration: none;
}

.h4yf-skin .h4yf-culture-content .wp-block-column h3 a:hover,
.h4yf-skin .h4yf-culture-content .wp-block-column h3 a:focus-visible {
	text-decoration: underline;
}

/* "Add crimson left eyebrow to each topic." */
.h4yf-skin .h4yf-culture-content .wp-block-columns > .wp-block-column {
	border-left: 3px solid var(--h4yf-crimson);
}

/* "Right size LATEST GUIDES content blocks to the same size as the other
   content blocks" — the topic columns are 24px-padded cards with a 20px title;
   the guides cards were padding up to 22px with a title up to 22px on their own
   scale. Both now use the same padding and the same title step. */
/* ROOT CAUSE of the size mismatch, measured on slate 2026-08-07: core's own
   `is-grid columns-3` rules set an explicit `width` (and a right margin) on
   each `<li>` for a FLEX layout. This file made the list a CSS grid back in
   2026-08-04 but never cleared that width, so every card sat at 116px inside a
   389px grid track — a sixth of the width the topic blocks get, which is
   exactly what Josh is looking at. `width: auto` hands sizing back to the grid
   track. Without this the column-count rules below change nothing visible. */
.h4yf-skin .wp-block-latest-posts > li,
.h4yf-skin .wp-block-latest-posts__list > li {
	padding: 24px;
	width: auto;
	max-width: none;
	margin-right: 0;
}

.h4yf-skin .wp-block-latest-posts__post-title {
	font-size: var(--h4yf-fs-h3);
}

/* The column COUNT was the actual size mismatch, measured on slate at 1280px:
   the topic blocks render 3-up at 380px each, the guides rendered 4-up at
   289px — visibly narrower cards for the same kind of content, on the same
   page. The block already declares its own count (`columns-3` in its class
   list, set in the editor); our `auto-fit` grid was overriding it with whatever
   fit. Honour the block's declaration instead, and keep `auto-fit` only as the
   fallback for a block that ships no count. */
.h4yf-skin .wp-block-latest-posts__list.columns-2 {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 420px), 1fr));
}

.h4yf-skin .wp-block-latest-posts__list.columns-3 {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
}

.h4yf-skin .wp-block-latest-posts__list.columns-4 {
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
}

/* ---- 7. ABOUT ------------------------------------------------------------ */
/* "Remove 'What you get' / 'Who it's for' titles entirely, shift the section
   title and content to the left to match site." The kicker labels are gone from
   the template; these blocks were centred to make room for them. */
.h4yf-skin .h4yf-about-content > .wp-block-group,
.h4yf-skin .h4yf-about-content > .wp-block-group > * {
	text-align: left;
}

/* ---- 8. SHOP CONTROLS ---------------------------------------------------- */
/* "Make the DEFAULT SORTING button white with crimson text." */
/* `appearance: none` is load-bearing, not tidiness: a <select> left at the UA
   appearance paints its own control chrome and ignores `background-color` on
   several engines, which is why setting the colour alone does nothing. Turning
   the native appearance off is what makes the element paintable at all — the
   caret then has to be drawn back, hence the inline SVG below. */
.h4yf-skin .woocommerce-ordering select,
.h4yf-skin select.orderby {
	-webkit-appearance: none;
	-moz-appearance: none;
	appearance: none;
	background-color: #FFFFFF;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8' fill='none' stroke='%23C41E1E' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	background-size: 12px 8px;
	color: var(--h4yf-crimson);
	border: 1px solid #FFFFFF;
	border-radius: 6px;
	padding: 0 34px 0 14px;
	font-family: var(--h4yf-body);
	font-weight: 700;
	min-height: var(--h4yf-tap-floor, 44px);
}

/* Sort menu entirely removed on shop archives (decision 2026-09-08) */
.h4yf-skin .woocommerce-ordering {
	display: none !important;
}

@media (max-width: 768px) {
	/* The shop toolbar container is retired — filter button lives in the header row */
	.h4yf-skin .ast-shop-toolbar-container {
		display: none !important;
	}
}

/* Zero default blue, shop-grid edition. Live-scanned 2026-08-17 across /,
   /shop/ and PDP related-products: 3 more instances of Astra's global
   rgb(4,107,210) (var(--ast-global-color-0)), same defect class as 12's
   cat-links fix and 13d's single-post meta links.

   1. Product title links (`.ast-loop-product__link`): a bare `a { color:
      var(--ast-global-color-0) }` at (0,0,1) was never out-specified for the
      grid card title, only for meta/post links elsewhere in this file.
   2. "Select options" trigger for products that DON'T carry an
      `add_to_cart_button` class on the anchor (out-of-stock / needs-a-variant
      cards render `ast-on-card-button ast-select-options-trigger
      product_type_simple` with nothing else) — the skin already themes
      `a[class*="add_to_cart_button"]` elsewhere, but that attribute selector
      doesn't match this variant, so it also fell through to the bare `a`.
   3. Pagination "current page" badge: Astra's own
      `.woocommerce nav.woocommerce-pagination ul li span.current` rule pins
      both background and border to the global blue at (0,3,4) — see the
      round-3 note below the rule for how this was actually scoped (the
      first attempt at a fix here didn't work). */
body.h4yf-skin .ast-loop-product__link {
	color: var(--h4yf-ink);
}

body.h4yf-skin .ast-loop-product__link:hover,
body.h4yf-skin .ast-loop-product__link:focus-visible {
	color: var(--h4yf-hover);
}

body.h4yf-skin .ast-select-options-trigger {
	color: var(--h4yf-ink);
	border-color: currentcolor;
}

/* [ROUND 3 FIX, same day] Originally scoped `body.h4yf-skin .woocommerce
   nav.woocommerce-pagination …` — same same-node `.woocommerce`-on-`<body>`
   bug as the add-to-cart button above (confirmed live via `el.matches()`
   returning false), so this never actually applied despite computing a
   comfortable specificity margin on paper. `nav.woocommerce-pagination`
   alone is specific enough context; no separate `.woocommerce` ancestor
   needed. */
body.h4yf-skin nav.woocommerce-pagination ul li span.current {
	background: var(--h4yf-crimson);
	border-color: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

/* The blog archive (`/category/real-heat-real-talk/`) paginates through
   Astra's plain `nav.pagination`/`.ast-pagination` markup, not WooCommerce's
   `nav.woocommerce-pagination` — the rule above never matches there, and
   Astra's own `.ast-pagination .page-numbers.current` rule (0,2,2) still
   wins default blue. Confirmed live 2026-08-17 the rule above doesn't cover
   this page. `body.h4yf-skin .page-numbers.current` at (0,3,1) beats (0,2,2)
   on class count alone and coexists with the more specific WooCommerce rule
   above without conflict — each wins on its own page. */
body.h4yf-skin .page-numbers.current {
	background: var(--h4yf-crimson);
	border-color: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

/* Cart-drawer loading spinner dots — `.ast-loader > div` at (0,1,1) picked
   up the same global blue as its background. */
body.h4yf-skin .ast-loader > div {
	background-color: var(--h4yf-crimson);
}

/* Round 2 — found by re-verifying the three fixes above with a hard reload
   (a stale cached DOM snapshot briefly hid these behind false-positive
   noise). Confirmed live 2026-08-17 on /shop/:

   1. "Read more" — the CTA for a product with no visible price (no
      `add_to_cart_button`/`ajax_add_to_cart` classes, unlike the ordinary
      add-to-cart button) fell all the way through to the bare `a`. Rather
      than chase every WooCommerce anchor-class permutation one at a time,
      this targets any `a.button` inside a product card directly — Add to
      cart, Select options, and Read more all render as `a.button` in this
      loop, so one rule now covers whichever class combination WooCommerce
      picks for a given product's state.
   2. Non-current pagination links/arrows (`.page-numbers` without
      `.current`) — the fix above only themed the current-page badge, not
      the other page numbers or the `→` next-page link.
   3. The price-filter widget's "Filter" submit button
      (`.price_slider_amount button.button`) — hidden until the price-range
      JS reveals it, so a plain page load never shows it.

   [ROUND 3 FIX, same day] Both selectors below originally carried a
   `.woocommerce` ancestor token (`body.h4yf-skin .woocommerce ul.products
   …` / `… .woocommerce nav.woocommerce-pagination …`) — same same-node bug
   as the add-to-cart button and the current-page badge above:
   `.woocommerce` lives on `<body>` itself, so requiring it as a *descendant*
   of `body.h4yf-skin` (the same node) can never match. Dropped; the
   remaining context (`ul.products`, `nav.woocommerce-pagination`) is
   specific enough on its own. */
body.h4yf-skin ul.products li.product a.button {
	color: var(--h4yf-ink);
	background-color: var(--h4yf-crimson);
	border-color: currentcolor;
}

body.h4yf-skin ul.products li.product a.button:hover,
body.h4yf-skin ul.products li.product a.button:focus-visible {
	background-color: #a8182b;
}

/* [ROUND 4 FIX, same day] Live re-check after round 3 found the text/hover
   colors landed but the border stayed default blue — this rule only set
   `color`, never `border-color`, so Astra's `.woocommerce nav.woocommerce-pagination
   ul li > .page-numbers { border-color: var(--ast-global-color-0) }` kept
   winning that one property uncontested. */
body.h4yf-skin nav.woocommerce-pagination ul li a.page-numbers {
	color: var(--h4yf-ink);
	border-color: currentcolor;
}

/* The `<li>` separators between pagination items carry a real, visible 1px
   border (unlike the 0px `<ul>`/`.dots` hits found alongside it, which are
   invisible currentcolor artifacts not worth touching) — also default blue
   via Astra's `.woocommerce nav.woocommerce-pagination ul, … ul li` rule. */
body.h4yf-skin nav.woocommerce-pagination ul li {
	border-color: var(--h4yf-charcoal-2);
}

body.h4yf-skin nav.woocommerce-pagination ul li a.page-numbers:hover,
body.h4yf-skin nav.woocommerce-pagination ul li a.page-numbers:focus-visible {
	color: var(--h4yf-hover);
}

body.h4yf-skin .price_slider_amount button.button {
	border-color: currentcolor;
	background-color: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

/* ---- 9. CART ------------------------------------------------------------- */
/* "Remove the —OR— line that is at the bottom of the pay options on cart page."
   WooCommerce Blocks renders it as a rule between the express-payment buttons
   and the normal checkout button. Hidden rather than unregistered: it is core
   block output with no filter, and the express buttons themselves stay. */
.h4yf-skin .wc-block-components-express-payment-continue-rule {
	display: none;
}

/* ---- 10. BRAND GLYPHS ---------------------------------------------------- */
/* Footer channel row and the eBay marks (inc/brand-glyphs.php). */
.h4yf-skin .h4yf-footer__social a {
	gap: 8px;
}

.h4yf-skin .h4yf-brand-glyph {
	flex: 0 0 auto;
	display: block;
}

/* eBay ships its own four brand colours and must not inherit the link colour or
   the hover crimson — it is a logotype, not an icon. As of 2026-08-20 the same
   is true of YouTube, Facebook, Instagram and TikTok (Josh: "use color versions
   of platform logos"), and each of those paints its own `fill` in the SVG, so
   only eBay's `<text>` still needs the colour inheritance broken here. */
.h4yf-skin .h4yf-brand-glyph--ebay {
	color: initial;
}

/* ---- 11. PDP BRANDED PLACEHOLDER ---------------------------------------- */
/* The "REAL HEAT. REAL TALK." line on the branded DROPPING card. */
.h4yf-skin .h4yf-pdp-hero-placeholder__kicker {
	margin: 10px 0 0;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-trust-label);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
}

/* ---- 12. BLOG ARCHIVE HERO ----------------------------------------------- */
/* category-real-heat-real-talk.php (#873, own-the-markup) — logo +
   "REAL HEAT. REAL TALK." in place of the legacy "Ported – SNKRS Blog"
   category name. Used to be `.ast-archive-description .ast-archive-title`,
   Astra's own page-header wrapper; the template now owns its own section. */
.h4yf-blog-hero {
	text-align: center;
	padding: 40px 20px 24px;
}

.h4yf-blog-hero__heading {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 12px;
	margin: 0;
}

.h4yf-blog-hero__mark {
	display: block;
	width: clamp(80px, 20vw, 140px);
	height: auto;
}

.h4yf-blog-hero__title {
	font-family: var(--h4yf-display);
	/* No font-size rule existed here (#870) — fell through to the browser's
	   default h1 2em, compounding to 29.184px against the 14.592px root
	   defect. Matches .h4yf-pw-hero__title's role: a page-level hero title. */
	font-size: var(--h4yf-fs-h1);
	font-weight: 400;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

/* [#873] Used to be a structural selector (`.ast-archive-description > p`)
   because Astra printed `the_archive_description()` as a bare, class-less
   <p> — the template now gives it a class directly. */
.h4yf-blog-hero__tagline {
	margin: 12px 0 0;
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: var(--h4yf-fs-subhead);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--h4yf-crimson);
}

/* Zero default blue, archive card edition — same defect class as 13d below,
   different page. Live-scanned 2026-08-17 on /category/real-heat-real-talk/:
   the post card's category tag (`<a rel="category tag">`, inside
   `.cat-links`) resolves Astra's global default-blue rgb(4,107,210) via a
   bare `a { color: var(--ast-global-color-0) }` rule in the LiteSpeed CSS
   bundle. Unlike the single-post comment-submit button (13f), there is no ID
   selector to out-rank here — `body.h4yf-skin .cat-links a` at (0,3,1) beats
   the bare `a` at (0,0,1) outright, so no `!important` needed. */
/* P2-5: category tag measured 16px tall. Real navigation into filtered shop
   views, so it gets the full floor, inline-flex so min-height actually grows the box. */
body.h4yf-skin .cat-links a {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	color: var(--h4yf-ink);
	text-decoration: none;
	/* No font-size rule existed here (#870) — fell through to Astra's
	   category-link em default, compounding to 12.768px against the
	   14.592px root defect. */
	font-size: var(--h4yf-fs-meta);
	transition: color var(--pm-fast, 150ms) var(--pm-ease, ease);
}

body.h4yf-skin .cat-links a:hover,
body.h4yf-skin .cat-links a:focus-visible {
	color: var(--h4yf-hover);
}

/* ---- 13. BLOG POST (single) — the reading surface ------------------------
   Josh directive 2026-08-17: "update the blog post detail page text
   size/font colors to match site with white/crimson colors. zero default
   blue text, ensure readable and mobile optimized."

   THE BUG THIS FIXES FIRST — measured live on 0.9.53, /wasted-youth-x-nike-sb-dunk-low/:
   `<article class="ast-article-single">` resolved to background #F9F6EE (cream)
   while its text resolved to #FAFAFA. That is a contrast ratio of ~1.01:1 —
   every one of the 425 posts in this category was, literally, near-invisible.

   Astra paints that cream in `.ast-separate-container .ast-article-inner` and
   `.ast-separate-container .ast-article-single:not(.ast-related-post)`. The skin's
   existing dark-canvas override stops at `.site-content`/`.ast-container` and never
   reached the ARTICLE itself, so single posts — the only layout on the site using
   `ast-separate-container` — fell through the gap. Archives were unaffected because
   they render under `ast-page-builder-template`, which the earlier rule does cover.

   NO `!important` ANYWHERE IN THIS SECTION (PRODUCT.md: "no !important-war CSS").
   Every rule here outranks Astra on specificity alone — `body.h4yf-skin` plus a body
   layout class is (0,3,1) against Astra's (0,2,0), which is why the overrides land
   without escalation. ---------------------------------------------------------- */

/* Reading scale, local to the article. The site's `--h4yf-fs-body` is a UI token
   (14px floor) — correct for nav, labels, and product chrome, wrong for a
   1000-word article, which is what the 14px/1.65 measured here actually was.
   17→19px fluid. Light-on-dark reads lighter than dark-on-light, so line-height
   is 1.75 rather than the UI 1.4 (impeccable brand register: add 0.05–0.1 on
   dark). */
body.h4yf-skin.single-post {
	--h4yf-read-fs: clamp(1.0625rem, 1rem + 0.28vw, 1.1875rem);
	--h4yf-read-lh: 1.75;
	--h4yf-read-measure: 44rem;
}

/* 13a. Kill the cream — put the article back on the charcoal canvas.
   Transparent rather than an elevated charcoal-2 card: the page is already a
   single column of prose, and a card around it would be chrome for its own sake
   ("restraint signals premium", and cards are the lazy answer). */
body.h4yf-skin.ast-separate-container .ast-article-inner,
body.h4yf-skin.ast-separate-container .ast-article-single:not(.ast-related-post),
body.h4yf-skin.ast-separate-container .comments-area,
body.h4yf-skin.ast-separate-container .comments-count-wrapper,
body.h4yf-skin.ast-separate-container .related-posts-title-wrapper,
body.h4yf-skin.ast-separate-container .ast-archive-description,
body.h4yf-skin.single.ast-separate-container .site-main .ast-author-meta {
	background-color: transparent;
	background-image: none;
}

/* 13b. Reading measure. Astra's narrow container is a hard-coded 400px in its
   dynamic CSS (NOT `var(--ast-narrow-container-width)` — the variable exists but
   this rule inlines the literal, so overriding the token alone does nothing).
   400px at 14px was ~45ch; 44rem here lands the prose at ~69ch, inside the 65–75ch
   reading band. The two `--wp--custom--*` vars are what Gutenberg sizes its own
   default/wide blocks against, so they move with it or blocks stay 400px wide. */
body.h4yf-skin.single-post.ast-narrow-container {
	--wp--custom--ast-content-width-size: var(--h4yf-read-measure);
	--wp--custom--ast-wide-width-size: 52rem;
}

body.h4yf-skin.single-post.ast-narrow-container .site-content > .ast-container {
	max-width: var(--h4yf-read-measure);
}

/* 13c. The prose itself. */
body.h4yf-skin.single-post .entry-content {
	font-family: var(--h4yf-body);
	font-size: var(--h4yf-read-fs);
	line-height: var(--h4yf-read-lh);
	color: #e2e2e2;
	/* Fewer orphans across a 69ch measure; ignored where unsupported. */
	text-wrap: pretty;
}

body.h4yf-skin.single-post .entry-content p,
body.h4yf-skin.single-post .entry-content li {
	font-size: var(--h4yf-read-fs);
	line-height: var(--h4yf-read-lh);
}

/* Rule of 4: 24px between paragraphs, 8px between list items. */
body.h4yf-skin.single-post .entry-content p {
	margin: 0 0 24px;
}

body.h4yf-skin.single-post .entry-content ul,
body.h4yf-skin.single-post .entry-content ol {
	margin: 0 0 24px;
	padding-left: 1.25em;
}

body.h4yf-skin.single-post .entry-content li + li {
	margin-top: 8px;
}

body.h4yf-skin.single-post .entry-content li::marker {
	color: var(--h4yf-crimson);
}

/* Bold runs inside prose are the spec labels ("Silhouette:", "Colorway:") that
   carry most of these posts — ink lifts them off the body grey without spending
   crimson, which stays a scalpel. */
body.h4yf-skin.single-post .entry-content strong,
body.h4yf-skin.single-post .entry-content b {
	color: var(--h4yf-ink);
	font-weight: 700;
}

/* Headings: breathe above, tight below — the gap should bind a heading to the
   text it introduces, not float it between two blocks. */
body.h4yf-skin.single-post .entry-content h2,
body.h4yf-skin.single-post .entry-content h3,
body.h4yf-skin.single-post .entry-content h4 {
	margin: 48px 0 12px;
	text-wrap: balance;
}

body.h4yf-skin.single-post .entry-content > :first-child {
	margin-top: 0;
}

body.h4yf-skin.single-post .entry-title {
	text-wrap: balance;
	margin-bottom: 12px;
}

body.h4yf-skin.single-post .entry-content blockquote {
	margin: 32px 0;
	padding: 0 0 0 20px;
	/* 1px, not a slab: a >1px colored side-stripe is a banned decoration. */
	border-left: 1px solid var(--h4yf-crimson);
	color: var(--h4yf-ink);
	font-style: normal;
}

body.h4yf-skin.single-post .entry-content img,
body.h4yf-skin.single-post .entry-content figure {
	border-radius: var(--h4yf-radius, 6px);
}

body.h4yf-skin.single-post .entry-content figcaption {
	color: var(--h4yf-gray);
	font-size: var(--h4yf-fs-meta);
	text-align: center;
}

/* 13d. ZERO DEFAULT BLUE. Astra's global link colour is rgb(4,107,210); a live
   scan of every rendered element found it on 12 of them — the author vcard, the
   author link, `.author-name`, the `.published` date, both post-navigation
   directions, and the comment submit button's fill. `.entry-meta`/`.posted-on`
   were already handled further up this file; these were the ones that selector
   list never named. Meta text is muted grey, meta LINKS are ink and go crimson
   on hover — the same link contract the rest of the site uses. */
body.h4yf-skin .posted-by,
body.h4yf-skin .author-name,
body.h4yf-skin .published,
body.h4yf-skin .entry-meta .posted-on,
body.h4yf-skin .ast-author-details .author-title {
	color: var(--h4yf-gray);
}

/* P2-5: author link measured 35x15 on blog archive. */
body.h4yf-skin .entry-meta a,
body.h4yf-skin .posted-by a,
body.h4yf-skin .ast-post-meta a,
body.h4yf-skin a.url.fn.n {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	color: var(--h4yf-ink);
	text-decoration: none;
	transition: color var(--pm-fast, 150ms) var(--pm-ease, ease);
}

body.h4yf-skin .entry-meta a:hover,
body.h4yf-skin .entry-meta a:focus-visible,
body.h4yf-skin .posted-by a:hover,
body.h4yf-skin .posted-by a:focus-visible,
body.h4yf-skin .ast-post-meta a:hover,
body.h4yf-skin .ast-post-meta a:focus-visible,
body.h4yf-skin a.url.fn.n:hover,
body.h4yf-skin a.url.fn.n:focus-visible {
	color: var(--h4yf-hover);
}

/* 13e. Post navigation — prev/next. Astra colours the whole block blue and
   divides the two halves with a 1px pseudo-element it already themes off
   `--ast-border-color`; only the text colour needs correcting. */
body.h4yf-skin .post-navigation .nav-previous,
body.h4yf-skin .post-navigation .nav-next,
body.h4yf-skin .post-navigation .nav-previous a,
body.h4yf-skin .post-navigation .nav-next a {
	color: var(--h4yf-ink);
}

body.h4yf-skin .post-navigation a {
	font-family: var(--h4yf-body);
	font-weight: 600;
	text-decoration: none;
	transition: color var(--pm-fast, 150ms) var(--pm-ease, ease);
	/* 44px tap floor — these are the main "keep reading" affordance on mobile. */
	display: inline-flex;
	align-items: center;
	min-height: 44px;
}

body.h4yf-skin .post-navigation a:hover,
body.h4yf-skin .post-navigation a:focus-visible {
	color: var(--h4yf-hover);
}

body.h4yf-skin .post-navigation .ast-post-nav-title,
body.h4yf-skin .post-navigation .nav-links .nav-previous span:first-child,
body.h4yf-skin .post-navigation .nav-links .nav-next span:first-child {
	color: var(--h4yf-gray);
}

/* 13f. Comments — the form is the one place on this page that was still a
   stock-blue Astra button on a cream field. */
body.h4yf-skin .comments-title,
body.h4yf-skin .comment-reply-title,
body.h4yf-skin .comment-author .fn,
body.h4yf-skin .comment-author .fn a {
	color: var(--h4yf-ink);
}

body.h4yf-skin .comment-metadata,
body.h4yf-skin .comment-metadata a,
body.h4yf-skin .says {
	color: var(--h4yf-gray);
}

body.h4yf-skin .comment-content {
	color: #e2e2e2;
}

body.h4yf-skin .ast-comment-list li {
	border-color: var(--h4yf-charcoal-2);
}

/* "Cancel Reply" link (`#cancel-comment-reply-link`) — hidden by default,
   only shown by WP core's own JS when replying to a specific comment, which
   is why the earlier live scans of this page never caught it. Live-checked
   2026-08-17 by forcing `display:block`: it was still the bare-`a` default
   blue, same defect class as the rest of §13f. ID selector, no specificity
   fight needed. */
body.h4yf-skin #cancel-comment-reply-link {
	color: var(--h4yf-gray);
}

body.h4yf-skin #cancel-comment-reply-link:hover,
body.h4yf-skin #cancel-comment-reply-link:focus-visible {
	color: var(--h4yf-hover);
}

body.h4yf-skin .comment-form textarea,
body.h4yf-skin .comment-form input[type="text"],
body.h4yf-skin .comment-form input[type="email"],
body.h4yf-skin .comment-form input[type="url"] {
	background: var(--h4yf-charcoal-2);
	border: 1px solid #3a3a3c;
	border-radius: var(--h4yf-radius, 6px);
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	padding: 12px 14px;
}

body.h4yf-skin .comment-form textarea::placeholder,
body.h4yf-skin .comment-form input::placeholder {
	/* Placeholders need the same 4.5:1 as body text — --h4yf-gray on charcoal
	   clears it; Astra's default #9CA3AF on this canvas does not. */
	color: var(--h4yf-gray);
}

/* `input[type="submit"]` alone loses this one — measured live 2026-08-17: WP
   core renders this button as `<input id="submit" class="submit" type="submit">`,
   and Astra's own dynamic-CSS bundle carries a rule that includes the literal
   `input#submit` in its selector list. An ID selector outranks any number of
   stacked classes regardless of source order (ID > class, full stop), so
   `body.h4yf-skin .comment-form input[type="submit"]` — all classes — never had
   a chance. Matching the ID is the only fix; `#submit` alone would work but
   scoping it under `.comment-form` keeps it from ever matching an unrelated
   future `#submit` elsewhere on the site. */
body.h4yf-skin .comment-form input[type="submit"],
body.h4yf-skin .comment-form input#submit,
body.h4yf-skin .comment-form .submit {
	background-color: var(--h4yf-crimson);
	border: 0;
	border-radius: var(--h4yf-radius, 6px);
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-cta);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	min-height: 48px;
	padding: 0 28px;
	transition: background-color var(--pm-fast, 150ms) var(--pm-ease, ease);
}

body.h4yf-skin .comment-form input[type="submit"]:hover,
body.h4yf-skin .comment-form input#submit:hover,
body.h4yf-skin .comment-form .submit:hover {
	background-color: #a8182b;
}

/* 13g. Mobile — ~85% of traffic (PRODUCT.md). Astra's separate-container pads
   the article 2.5em (40px) a side, which on a 375px phone spends 21% of the
   screen on gutters; 20px keeps the measure honest. Inputs stay ≥16px so iOS
   does not zoom the viewport on focus. */
@media (max-width: 921px) {
	body.h4yf-skin.single-post.ast-separate-container .ast-article-single,
	body.h4yf-skin.single-post.ast-separate-container .comments-area,
	body.h4yf-skin.single-post.ast-separate-container .comment-respond {
		padding-left: 20px;
		padding-right: 20px;
	}

	body.h4yf-skin.single-post .entry-content h2,
	body.h4yf-skin.single-post .entry-content h3,
	body.h4yf-skin.single-post .entry-content h4 {
		margin-top: 36px;
	}
}

@media (max-width: 767px) {
	body.h4yf-skin .comment-form textarea,
	body.h4yf-skin .comment-form input[type="text"],
	body.h4yf-skin .comment-form input[type="email"],
	body.h4yf-skin .comment-form input[type="url"] {
		font-size: 16px;
	}
}

@media (prefers-reduced-motion: reduce) {
	body.h4yf-skin .post-navigation a,
	body.h4yf-skin .entry-meta a,
	body.h4yf-skin .comment-form input[type="submit"] {
		transition: none;
	}
}

/* --- Dual pricing (Retail/Market/H4YF price) — issue #555 slice 2 --- */
/* PDP PRICE ANCHORS (rebuilt 2026-08-20 — see inc/pdp-dual-pricing.php for why
   the H4YF price is no longer restated here).

   The two anchors sit on ONE row, not stacked: they are context read at a
   glance, and a two-row definition list gave them the vertical weight of a spec
   table directly beneath the price. The saving underneath is the only crimson
   in the block, which is the Alarm-Light rule applied literally — it is the one
   line here that is a reason to act. */
.h4yf-skin .h4yf-dual-pricing {
	margin: 10px 0 4px;
	font-family: var(--h4yf-body);
}

.h4yf-skin .h4yf-dual-pricing__anchors {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 22px;
	margin: 0;
}

.h4yf-skin .h4yf-dual-pricing__row {
	display: flex;
	align-items: baseline;
	gap: 7px;
	margin: 0;
}

.h4yf-skin .h4yf-dual-pricing__row dt {
	margin: 0;
	color: var(--h4yf-gray);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* Muted, not ink, and not struck through. These are real published figures, not
   a fake "was" price — a strikethrough would read as our own former price and
   is the exact pattern that gets a resale storefront accused of invented
   discounts. Weight and colour carry the demotion instead. */
.h4yf-skin .h4yf-dual-pricing__row dd {
	margin: 0;
	color: var(--h4yf-body-color, #e2e2e2);
	font-weight: 700;
	font-size: 14px;
	font-variant-numeric: tabular-nums;
}

.h4yf-skin .h4yf-dual-pricing__savings,
.h4yf-skin .h4yf-dual-pricing__card-badge {
	color: var(--h4yf-crimson);
	font-weight: 800;
	font-size: 12.5px;
	letter-spacing: 0.03em;
	text-transform: uppercase;
}

.h4yf-skin .h4yf-dual-pricing__savings {
	margin: 8px 0 0;
}

.h4yf-skin .h4yf-dual-pricing__card-badge { display: inline-block; margin-top: 2px; }

/* ================================================================== */
/* §REAL HEAT. REAL TALK — /culture/ editorial section (2026-08-20)    */
/*                                                                     */
/* Replaces the INDIANAPOLIS topic tile (Josh 2026-08-20). Uses the     */
/* homepage section frame so /culture/ and / agree about what a content */
/* section looks like, plus the full-length crimson rule Josh asked for */
/* on the Watch the Breakdowns section — same device, same meaning.     */
/* ================================================================== */

/* One LEAD plus four. Five equal boxes is the identical-card-grid reflex the
   design system names; a lead gives the section a reading order and lets the
   strongest post carry an excerpt at a size worth reading. `auto-fit`/`minmax`
   collapses to one column on a phone with no breakpoint to maintain. */
.h4yf-realtalk__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: clamp(20px, 2.6vw, 32px);
	align-items: start;
}

@media (min-width: 860px) {
	.h4yf-realtalk__grid {
		grid-template-columns: repeat(4, 1fr);
	}

	.h4yf-realtalk-card--lead {
		grid-column: 1 / -1;
	}
}

/* Hairline over the card, no box. DESIGN.md's Flat-Floor rule: separation comes
   from a rule and a tonal step, never from a raised surface — and five bordered
   boxes here would be the one place on this page that disagrees with the
   Curator's Take cards directly below it. */
.h4yf-realtalk-card {
	padding-top: 16px;
	border-top: 1px solid var(--h4yf-border);
}

.h4yf-realtalk-card__link {
	text-decoration: none;
	display: block;
}

.h4yf-realtalk-card__title {
	margin: 0;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: clamp(18px, 0.6vw + 16px, 22px);
	line-height: 1.14;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	text-wrap: balance;
	transition: color 160ms var(--h4yf-ease-out-expo);
}

/* The lead earns its size from the layout, not from a second treatment — one
   step up the same scale, so the two card types read as one component. */
.h4yf-realtalk-card--lead .h4yf-realtalk-card__title {
	font-size: clamp(22px, 1.4vw + 18px, 30px);
	max-width: 22ch;
}

.h4yf-realtalk-card__link:hover .h4yf-realtalk-card__title,
.h4yf-realtalk-card__link:focus-visible .h4yf-realtalk-card__title {
	color: var(--h4yf-hover);
}

.h4yf-realtalk-card__excerpt {
	margin: 8px 0 0;
	color: var(--h4yf-body-color, #e2e2e2);
	font-family: var(--h4yf-body);
	font-weight: 500;
	font-size: 13.5px;
	line-height: 1.55;
	/* 65ch is the readable ceiling; the lead is the only card wide enough to
	   ever reach it. */
	max-width: 65ch;
}

.h4yf-realtalk-card--lead .h4yf-realtalk-card__excerpt {
	font-size: clamp(14px, 0.5vw + 12px, 16px);
}

.h4yf-realtalk-card__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 14px;
	margin: 10px 0 0;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* ================================================================== */
/* §PDP STAGE BLOCK — the CTA where "Sold out" used to be (2026-08-20) */
/* ================================================================== */

/* WooCommerce renders nothing where the add-to-cart form would be on a
   non-purchasable product, so the highest-intent area of an 86-product slice of
   the catalog was blank. `inc/inventory-lifecycle.php` puts the request route
   there instead. Charcoal-2 with a hairline, not a crimson panel: the BUTTON is
   the crimson, per the Alarm-Light rule. */
.h4yf-pdp-stage {
	margin: 18px 0;
	padding: 18px;
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: 8px;
}

.h4yf-pdp-stage__line {
	margin: 0 0 14px;
	color: var(--h4yf-body-color, #e2e2e2);
	font-family: var(--h4yf-body);
	font-weight: 600;
	font-size: clamp(14px, 0.6vw + 12px, 16px);
	line-height: 1.5;
	max-width: 46ch;
}

.h4yf-pdp-stage .h4yf-btn {
	width: 100%;
}

/* SOLD OUT — proof, not a dead end (Josh, 2026-09-09).
   Deliberately quiet: an outlined chip, never a filled crimson one. The Alarm-
   Light rule says the BUTTON is the crimson, and on these cards the button is
   "Request This Pair" — the thing we want clicked. A loud badge next to it would
   compete with the only action on the page. Letter-spaced caps carry the weight
   instead of colour. Only ever rendered on stage === placed. */
.h4yf-badge--sold {
	display: inline-flex;
	align-items: center;
	align-self: flex-start;
	margin: 0 0 10px;
	padding: 4px 10px;
	border: 1px solid var(--h4yf-border);
	border-radius: 999px;
	background: transparent;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-weight: 800;
	font-size: 11px;
	letter-spacing: 0.12em;
	line-height: 1.4;
	text-transform: uppercase;
	white-space: nowrap;
}

/* On a shop card the badge sits over the image, so it needs its own ground to
   stay legible on a light colourway. `position` comes from the card wrapper
   Astra already establishes. */
.woocommerce ul.products li.product .h4yf-badge--sold,
.woocommerce-page ul.products li.product .h4yf-badge--sold {
	position: absolute;
	top: 10px;
	left: 10px;
	z-index: 2;
	margin: 0;
	border-color: rgba(255, 255, 255, 0.28);
	background: rgba(18, 18, 18, 0.82);
	color: #f2f2f2;
	backdrop-filter: blur(2px);
}

.h4yf-pdp-stage__wall {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	margin-top: 4px;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.h4yf-pdp-stage__wall:hover,
.h4yf-pdp-stage__wall:focus-visible {
	color: var(--h4yf-hover);
}

/* ================================================================== */
/* §SIZE FACET + THE EMPTY-GRID GATE (2026-08-20)                      */
/* ================================================================== */

/* Sizes we DON'T stock are shown, not hidden — that is the whole feature (see
   inc/size-filter.php). So the facet needs two resting states that are legible
   as different without one of them looking broken or disabled: a stocked chip
   has a hairline and ink text, an unstocked one is dimmer and dashed. Dashed
   rather than greyed: grey reads "disabled, don't bother", dashed reads
   "different kind of thing", and these are very much clickable. */
.h4yf-size-facet__list {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	list-style: none;
	margin: 0 0 10px;
	padding: 0;
}

.h4yf-size-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 46px;
	min-height: var(--h4yf-tap-floor, 44px);
	padding: 0 10px;
	border: 1px solid var(--h4yf-border);
	border-radius: 999px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 13px;
	font-variant-numeric: tabular-nums;
	text-decoration: none;
	transition: border-color 160ms var(--h4yf-ease-out-expo),
		color 160ms var(--h4yf-ease-out-expo);
}

.h4yf-size-chip--request {
	border-style: dashed;
	color: var(--h4yf-gray);
}

/* The size we actually have on the shelf, in crimson (Josh 2026-09-06: "just
   make the size '12' label crimson"). Written against the STOCKED class, not
   the literal 12, so it follows the inventory instead of needing an edit the
   day a 10.5 lands — `h4yf_size_in_stock()` decides which chip gets it.

   Outline crimson, not filled: filled crimson is the SELECTED state one rule
   down, and two chips that read as "on" is the state-that-lies defect that got
   the old ALL chip deleted. */
.h4yf-size-chip--stocked {
	border-color: var(--h4yf-crimson);
	color: var(--h4yf-crimson);
}

.h4yf-size-chip:hover,
.h4yf-size-chip:focus-visible {
	border-color: var(--h4yf-hover);
	color: var(--h4yf-hover);
}

/* Selected, not hovered — crimson, because this is a resting state and crimson
   is the resting accent. Same split the rest of the system now runs on. */
.h4yf-size-chip.is-on {
	background: var(--h4yf-crimson);
	border-color: var(--h4yf-crimson);
	color: var(--h4yf-ink);
}

.h4yf-size-facet__note {
	margin: 0;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-size: 12px;
	line-height: 1.45;
}

/* The gate replaces an empty product grid. Sized like a real section, not like
   an error: this is a conversion surface, and it is the only thing on the page. */
.h4yf-size-gate {
	max-width: 620px;
	margin: clamp(24px, 6vw, 56px) auto;
	padding: clamp(24px, 5vw, 40px);
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-left: 3px solid var(--h4yf-crimson);
	border-radius: 8px;
	text-align: left;
}

.h4yf-size-gate__kicker {
	margin: 0 0 8px;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-weight: 800;
	font-size: 11px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

.h4yf-size-gate__title {
	margin: 0 0 10px;
	color: var(--h4yf-ink);
	font-family: var(--h4yf-display);
	font-weight: 400;
	font-size: var(--h4yf-fs-h2);
	line-height: 1.06;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	text-wrap: balance;
}

.h4yf-size-gate__sub {
	margin: 0 0 20px;
	color: var(--h4yf-body-color, #e2e2e2);
	font-family: var(--h4yf-body);
	font-weight: 500;
	font-size: clamp(14px, 0.6vw + 12px, 16px);
	line-height: 1.55;
	max-width: 52ch;
}

.h4yf-size-gate__browse {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	margin-left: 16px;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.h4yf-size-gate__browse:hover,
.h4yf-size-gate__browse:focus-visible {
	color: var(--h4yf-hover);
}

@media (max-width: 520px) {
	.h4yf-size-gate .h4yf-btn {
		width: 100%;
	}

	.h4yf-size-gate__browse {
		margin: 8px 0 0;
	}
}

/* The Pickups Wall card CTA (2026-08-20) — replaces the outbound eBay link.
   Full-width crimson, same button as the shop grid: a placed pair and a live
   pair should offer the same weight of action, because the wall's job is to
   convert the proof it just showed you. */
.h4yf-pw-card__cta {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: var(--h4yf-tap-floor, 44px);
	margin-top: 10px;
	font-size: 13px;
	letter-spacing: 0.04em;
}

/* The receipt is a badge now, never a link — no pointer, no underline, no
   affordance suggesting there is somewhere to go. */
.h4yf-pw-card__receipt--badge {
	display: inline-block;
	color: var(--h4yf-gray);
	font-family: var(--h4yf-body);
	font-weight: 700;
	font-size: 11px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

/* Live-PDP "different size?" line — deliberately quiet. It sits under the
   crimson Add to Cart and must never compete with it; the request route is the
   fallback for one case, not the page's ask. */
.h4yf-pdp-othersize {
	margin: 12px 0 0;
	font-family: var(--h4yf-body);
	font-size: 13px;
}

.h4yf-pdp-othersize a {
	display: inline-flex;
	align-items: center;
	min-height: var(--h4yf-tap-floor, 44px);
	color: var(--h4yf-gray);
	font-weight: 600;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.h4yf-pdp-othersize a:hover,
.h4yf-pdp-othersize a:focus-visible {
	color: var(--h4yf-hover);
}

/* ------------------------------------------------------------------ */
/* PDP gallery — never crop, never stretch the hero                   */
/* ------------------------------------------------------------------ */
/* THE STRETCH BUG. Nothing in this theme or Astra ever set `object-fit` on the
   single-product gallery image, so it sat at its initial value of `fill`. Any
   source whose aspect does not match the slot it lands in is WARPED to fit —
   live-measured in the catalogue, featured images range from 1000x1000 pipeline
   cutouts to 1600x1200 and 1080x1920 raw camera photos, so the mismatch is the
   common case, not the edge case. Josh 2026-08-29: "some images in single
   product shop gallery have been stretched and flattened."

   `contain` on a 1:1 plate is the fix and the deliberate difference from the
   grid: the grid crops to a uniform tile because a row of tiles has to read as
   one structure, but a detail page's job is to show the whole product. A
   non-square source letterboxes against the charcoal card instead of warping,
   and a square pipeline cutout — the 90%+ case — fills the plate exactly, so
   this is a no-op for most of the catalogue and a rescue for the rest.

   Scoped to the gallery IMAGE, not the wrapper: `.woocommerce-product-gallery`
   itself already carries the charcoal card, radius and overflow above. */
body.h4yf-skin .woocommerce-product-gallery .woocommerce-product-gallery__image,
body.h4yf-skin .woocommerce-product-gallery .woocommerce-product-gallery__wrapper > div {
	aspect-ratio: 1 / 1;
	overflow: hidden;
}

body.h4yf-skin .woocommerce-product-gallery .woocommerce-product-gallery__image img,
body.h4yf-skin .woocommerce-product-gallery .woocommerce-product-gallery__wrapper > div img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

/* Gallery thumbnails take the same rule for the same reason — they are the same
   photos at 1/4 the size, and a warped thumbnail misrepresents what the buyer
   is about to click. */
body.h4yf-skin .flex-control-thumbs li img,
body.h4yf-skin .woocommerce-product-gallery .flex-control-nav li img {
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background: var(--h4yf-charcoal-2);
}

/* ------------------------------------------------------------------ */
/* Blog archive — REAL HEAT. REAL TALK.                               */
/* ------------------------------------------------------------------ */
/* [#873, own-the-markup] category-real-heat-real-talk.php now emits its own
   `.h4yf-blog-*` classes instead of Astra's generic `.entry-title` /
   `.ast-article-inner` / `.ast-taxonomy-container` / `.ast-blog-meta-
   container` / `.ast-excerpt-container` / `.post-thumb`. Those classes are
   shared by every other archive on the site, which is why the block this
   replaced had to double every selector under `body.category-real-heat-
   real-talk`/`body.category-ported-snkrs-blog` to avoid leaking — and why
   Astra's own Customizer CSS could still win the SAME selectors on a
   Customizer change (#750 P1-1's actual root cause). `.h4yf-blog-card__*`
   exists nowhere else, so no scoping prefix and no specificity fight is
   needed here at all.

   Values unchanged from the 2026-08-29 pass (Josh: "make the titles on this
   page Crimson and format the typography and layout to match the rest of
   site.") — this is a rename, not a redesign. */
.h4yf-blog-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
	gap: 20px;
	margin: 0 0 32px;
}

.h4yf-blog-card {
	background: var(--h4yf-charcoal-2);
	border: 1px solid var(--h4yf-border);
	border-radius: var(--pm-radius, 4px);
	padding: 20px;
	height: 100%;
	transition: box-shadow 200ms ease, border-color 200ms ease;
}

.h4yf-blog-card:hover {
	border-color: var(--h4yf-crimson);
	box-shadow: var(--pm-ring, 0 0 0 .1rem rgba(250, 250, 250, .2));
}

.h4yf-blog-card__link {
	display: block;
	color: inherit;
	text-decoration: none;
}

/* Shared product plate so the blog grid and the shop grid crop to the same
   shape — one listing structure across the site. */
.h4yf-blog-card__image {
	width: 100%;
	aspect-ratio: var(--h4yf-plate);
	object-fit: cover;
	border-radius: var(--pm-radius, 4px);
	display: block;
	margin-bottom: 14px;
}

/* The category tag above the title is a route back to the archive you are
   already on — a kicker, so it reads as a label, not a second headline
   competing with the crimson one. */
.h4yf-blog-card__kicker {
	display: block;
	margin-bottom: 8px;
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--h4yf-gray);
}

.h4yf-blog-card__title {
	font-family: var(--h4yf-display);
	font-size: clamp(20px, 2.4vw, 26px);
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: 0.01em;
	text-transform: uppercase;
	text-wrap: balance;
	margin: 0;
	color: var(--h4yf-crimson);
}

.h4yf-blog-card__link:hover .h4yf-blog-card__title,
.h4yf-blog-card__link:focus-visible .h4yf-blog-card__title {
	color: var(--h4yf-hover);
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* Byline and date: supporting metadata, not content. */
.h4yf-blog-card__meta {
	color: var(--h4yf-gray);
	font-size: 12px;
	margin: 10px 0 0;
}

.h4yf-blog-card__excerpt {
	color: var(--h4yf-ink);
	font-size: 15px;
	line-height: 1.6;
	margin: 8px 0 0;
}

/* ------------------------------------------------------------------ */
/* One focus signal, every page                                       */
/* ------------------------------------------------------------------ */
/* Josh 2026-08-29: "Ensure consistent use, sizing, and color of crimson left
   eyebrow + orange glow highlight/selector/focus across every page on site."

   The eyebrow half was already consistent — `.h4yf-rule` and `.h4yf-rule-section`
   both draw `3px solid var(--h4yf-crimson)` down the left edge, and
   `.h4yf-eyebrow` carries the same crimson at the same 3px weight. Nothing to
   reconcile there.

   Focus was not. Counted in this file: 76 `:focus-visible` selectors, and only
   SIX of them declare an `outline`. The other seventy signal focus by changing a
   colour or adding an underline — which is a different indicator on almost every
   component, is invisible on anything that was already coloured or underlined,
   and on an icon-only control (the gallery zoom trigger, the cart icon, the nav
   toggle) is no indicator at all.

   Rather than edit seventy rules, this declares the ring ONCE for everything
   focusable. The per-component colour and underline changes above are left
   alone: they still fire, and they now read as secondary affordance on top of a
   ring that is the same size, colour and offset on every page.

   `--h4yf-hover` already resolves to `--h4yf-bball` (#ee6730) — the one orange
   the palette kept, and it was kept for exactly this: see the note on the token
   itself, which is the WCAG 1.4.11 non-text indicator, and records that crimson
   measures 2.88:1 on charcoal and cannot legally carry a focus ring. So the
   "orange glow" Josh is asking for is the colour this already had to be.

   `:where()` keeps the whole selector at zero specificity, so any component rule
   that genuinely needs its own ring still wins without `!important`. */
:root {
	--h4yf-focus-ring: 2px;
	--h4yf-focus-offset: 2px;
}

body.h4yf-skin :where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: var(--h4yf-focus-ring) solid var(--h4yf-hover);
	outline-offset: var(--h4yf-focus-offset);
	/* The glow. An outline alone disappears against the charcoal card at a
	   glance; the halo is what makes it read as "this one" across a dense grid.
	   Kept low-alpha so it never looks like a selected/error state. */
	box-shadow: 0 0 0 4px rgba(238, 103, 48, 0.25);
	border-radius: 3px;
}

/* Cards and tiles clip their children (`overflow: hidden` on the image plate),
   which would slice an outline drawn outside the box. Pull the ring inside for
   those, same colour and weight, so the signal survives the clip. */
body.h4yf-skin :where(.h4yf-drop-card, .h4yf-radar-card, .h4yf-heat-card, .h4yf-grail-card, .h4yf-pw-card, .h4yf-home-cat, .woocommerce ul.products li.product) a:focus-visible {
	outline-offset: calc(var(--h4yf-focus-offset) * -1);
}

/* Text selection carries the same orange rather than the browser default blue —
   the one remaining place a stock blue could still paint on this site. */
body.h4yf-skin ::selection {
	background: rgba(238, 103, 48, 0.3);
	color: var(--h4yf-ink);
}
/**
 * H4YF Premier layer — structural design system extracted from
 * thepremierstore.com (skillui, 2026-07-05), re-tokened to the locked
 * H4YF palette (h4yf_global_invariants: crimson = CTAs/accents ONLY).
 *
 * Contributes STRUCTURE, not brand: 4px grid density, 4px radius,
 * motion scale + easings, elevation rings, badge pills, card hover.
 * Loads AFTER skin.css (cascade order wins, no !important arms race).
 */

:root {
	/* premier structural tokens — no new brand hexes */
	--pm-radius: 4px;
	--pm-ease: cubic-bezier(.25, .46, .45, .94);
	--pm-ease-enter: cubic-bezier(.29, .63, .44, 1);
	--pm-fast: 150ms;
	--pm-med: 300ms;
	--pm-slow: 500ms;
	--pm-ring: 0 0 0 .1rem rgba(250, 250, 250, .2);        /* --h4yf-ink @ 20% */
	--pm-ring-strong: 0 0 .2rem rgba(250, 250, 250, .3);   /* --h4yf-ink @ 30% */
}

/* ------------------------------------------------------------------ */
/* Product cards — surface, radius, hover ring + image zoom            */
/* ------------------------------------------------------------------ */
.woocommerce ul.products li.product {
	background: var(--h4yf-charcoal-2, #2C2C2E);
	border-radius: var(--pm-radius);
	overflow: hidden;
	transition: box-shadow 200ms ease;
}

.woocommerce ul.products li.product:hover {
	box-shadow: var(--pm-ring);
}

.woocommerce ul.products li.product img {
	border-radius: 0;
	transition: transform var(--pm-med) var(--pm-ease);
}

.woocommerce ul.products li.product:hover img {
	transform: scale(1.06);
}

.woocommerce ul.products li.product .woocommerce-loop-product__title {
	padding: 12px 16px 4px;
}

.woocommerce ul.products li.product .price {
	padding: 0 16px 16px;
}

/* Sale pricing — compare struck + muted, current price crimson */
.woocommerce ul.products li.product .price del {
	color: var(--h4yf-gray, #9A9A9A);
	font-weight: 400;
}

.woocommerce ul.products li.product .price ins {
	color: var(--h4yf-ink);
	text-decoration: none;
	margin-left: 8px;
}

/* ------------------------------------------------------------------ */
/* Sale badge — premier pill, crimson accent                           */
/* ------------------------------------------------------------------ */
.woocommerce span.onsale {
	background: var(--h4yf-crimson);
	color: var(--h4yf-ink);
	border-radius: 9999px;
	padding: 4px 8px;
	font-size: 12px;
	font-weight: 500;
	line-height: 1.5;
	min-height: 0;
	min-width: 0;
	top: 8px;
	left: 8px;
	right: auto;
	margin: 0;
}

/* ------------------------------------------------------------------ */
/* Buttons — premier geometry, crimson fill accent, orange focus ring   */
/* ------------------------------------------------------------------ */
.h4yf-btn,
.woocommerce .button,
.woocommerce button.button,
.woocommerce a.button {
	border-radius: var(--pm-radius);
	text-decoration: none;
	transition: opacity var(--pm-fast) ease, border-color var(--pm-fast) ease;
}

.h4yf-btn:hover,
.woocommerce .button:hover {
	opacity: .9;
}

/* [DELETED 2026-08-02] A `.h4yf-btn / .woocommerce .button / .h4yf-icon-btn
   :focus-visible` block lived here with `outline: 2px solid var(--h4yf-crimson);
   outline-offset: 2px`. Two things were wrong with it and both were live:
   `--h4yf-orange` (#D4571A) is the HOVER colour — canon focus is #EE6730
   (`--h4yf-bball`) WITH a glow — and premier.css enqueues AFTER skin.css
   (functions.php), so at (0,3,0) it beat skin.css's `body.h4yf-skin
   button:focus-visible` blanket (0,2,2) on both specificity and order. Measured
   on the PDP add-to-cart: ring rendered #D4571A at 2px offset instead of
   #EE6730 at 3px. Deleted rather than recoloured — the blanket in
   `skin.css` (§ "Focus indicators") already covers every one of these three
   selectors, and one focus declaration is the point. */

/* ------------------------------------------------------------------ */
/* Entry motion — staggered appear-down on product grids               */
/* ------------------------------------------------------------------ */
@keyframes pm-appear-down {
	from { opacity: 0; transform: translateY(-8px); }
	to   { opacity: 1; transform: translateY(0); }
}

.woocommerce ul.products li.product {
	animation: pm-appear-down var(--pm-slow) var(--pm-ease-enter) backwards;
}

.woocommerce ul.products li.product:nth-child(1) { animation-delay: 0ms; }
.woocommerce ul.products li.product:nth-child(2) { animation-delay: 100ms; }
.woocommerce ul.products li.product:nth-child(3) { animation-delay: 200ms; }
.woocommerce ul.products li.product:nth-child(4) { animation-delay: 300ms; }
/* deeper rows load in-viewport later; no stagger needed past the fold */

/* ------------------------------------------------------------------ */
/* Home sections — premier density on the 4px grid                     */
/* ------------------------------------------------------------------ */
.h4yf-home-section {
	padding-top: 48px;
	padding-bottom: 48px;
}

.h4yf-home-section__head {
	margin-bottom: 24px;
}

.h4yf-home-cat,
.h4yf-home-strip__item {
	border-radius: var(--pm-radius);
	transition: box-shadow 200ms ease, transform var(--pm-med) var(--pm-ease);
}

.h4yf-home-cat:hover,
.h4yf-home-strip__item:hover {
	box-shadow: var(--pm-ring);
}

/* ------------------------------------------------------------------ */
/* Anti-patterns (premier + h4yf invariants agree)                     */
/* no blur, no zebra striping — borders separate rows                  */
/* ------------------------------------------------------------------ */
.woocommerce table.shop_table tr:nth-child(even) td,
.woocommerce table.shop_table tr:nth-child(odd) td {
	background: transparent;
}

.woocommerce table.shop_table td,
.woocommerce table.shop_table th {
	border-bottom: 1px solid var(--h4yf-charcoal-2, #2C2C2E);
}

/* ------------------------------------------------------------------ */
/* Reduced motion                                                      */
/* ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
	.woocommerce ul.products li.product,
	.woocommerce ul.products li.product img,
	.h4yf-home-cat,
	.h4yf-home-strip__item {
		animation: none;
		transition: none;
	}
}

/* ------------------------------------------------------------------ */
/* Culture mosaic — premier hero-tile pattern (front page)             */
/* ------------------------------------------------------------------ */
.h4yf-mosaic {
	display: grid;
	grid-template-columns: 1fr;
	gap: 16px;
	max-width: 1280px;
	margin: 0 auto;
	padding: 0 16px;
}

@media (min-width: 750px) and (max-width: 920px) {
	.h4yf-mosaic { grid-template-columns: 1fr 1fr; }
}

@media (min-width: 921px) {
	.h4yf-mosaic { grid-template-columns: 1fr 1fr 1fr; }
}

.h4yf-tile {
	position: relative;
	display: flex;
	align-items: flex-end;
	aspect-ratio: 3 / 2;
	padding: 24px;
	border-radius: var(--pm-radius);
	overflow: hidden;
	text-decoration: none;
	color: var(--h4yf-ink);
	animation: pm-appear-down var(--pm-slow) var(--pm-ease-enter) backwards;
}

.h4yf-tile::before {
	content: '';
	position: absolute;
	inset: 0;
	transition: transform var(--pm-med) var(--pm-ease);
	background:
		radial-gradient(circle at 70% 30%, var(--h4yf-charcoal-2, #2C2C2E) 0%, transparent 55%),
		linear-gradient(160deg, var(--h4yf-charcoal-2, #2C2C2E) 0%, var(--h4yf-charcoal) 100%);
}

.h4yf-tile--drops::before {
	background:
		radial-gradient(circle at 60% 40%, rgba(196, 30, 30, .35) 0%, transparent 55%),
		linear-gradient(135deg, var(--h4yf-charcoal) 0%, var(--h4yf-charcoal-2, #2C2C2E) 100%);
}

.h4yf-tile:hover::before { transform: scale(1.05); }
.h4yf-tile:hover { box-shadow: var(--pm-ring); }
.h4yf-tile:focus-visible { outline: 2px solid var(--h4yf-crimson); outline-offset: 2px; }

.h4yf-tile__body {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
}

.h4yf-tile__kicker {
	font-size: 12px;
	text-transform: uppercase;
	letter-spacing: .12em;
	color: var(--h4yf-gray, #9A9A9A);
}

.h4yf-tile__title {
	font-family: var(--h4yf-display, "Bebas Neue", Impact, sans-serif);
	font-weight: 400;
	font-size: clamp(24px, 4vw, 40px);
	text-transform: uppercase;
	line-height: 1.2;
}

.h4yf-tile__cta { margin-top: 12px; }

/* ------------------------------------------------------------------ */
/* Pickup Wall — premier alignment (beats inline page <style> via      */
/* body scope specificity, no !important)                              */
/* ------------------------------------------------------------------ */
/* [PADDING DROPPED 2026-08-11] The 16px belonged to the old horizontal card,
   whose 96px thumbnail sat inside the padded box. The Rotation card is a
   vertical tile now — a bleed-to-edge 4/5 image with the copy in its own
   padded body (.h4yf-pw-card__body) — so a padding here insets the photo and
   double-pads the text under it. */
body.h4yf-skin .h4yf-pw-card {
	background: var(--h4yf-charcoal-2, #2C2C2E);
	border: none;
	border-radius: var(--pm-radius);
	overflow: hidden;
	transition: box-shadow 200ms ease;
}

body.h4yf-skin .h4yf-pw-card:hover { box-shadow: var(--pm-ring); }

body.h4yf-skin .h4yf-pw-price { color: var(--h4yf-ink); font-variant-numeric: tabular-nums; }
body.h4yf-skin .h4yf-pw-date  { color: var(--h4yf-gray, #9A9A9A); }

/* ------------------------------------------------------------------ */
/* Drops Center + shared chips/badges — premier geometry               */
/* ------------------------------------------------------------------ */
body.h4yf-skin .h4yf-cond-badge {
	border-radius: 9999px;
	padding: 4px 8px;
}

body.h4yf-skin .h4yf-rv-card {
	background: var(--h4yf-charcoal-2, #2C2C2E);
	border: none;
	border-radius: var(--pm-radius);
	padding: 16px;
}

/* Live Search Widget & Realigned Header Search Box (Bug #4) */
.h4yf-search-widget {
	position: relative;
	display: flex;
	align-items: center;
}
.h4yf-search-form {
	display: flex;
	align-items: center;
	margin: 0;
	position: relative;
}
.h4yf-search-input-wrap {
	position: relative;
	display: flex;
	align-items: center;
	background: #1C1C1E;
	border: 1px solid #3A3A3C;
	border-radius: 6px;
	padding: 0 12px;
	height: 38px;
	width: 220px;
	box-sizing: border-box;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
@media (max-width: 768px) {
	.h4yf-search-input-wrap {
		width: 150px;
	}
}
.h4yf-search-input-wrap:focus-within {
	border-color: var(--h4yf-hover);
	box-shadow: 0 0 0 1px var(--h4yf-hover);
}
.h4yf-search-field {
	flex: 1;
	background: transparent;
	border: none;
	-webkit-appearance: none;
	appearance: none;
	color: #FAFAFA;
	font-family: 'Montserrat', sans-serif;
	font-size: 13px;
	font-weight: 500;
	padding: 0;
	height: 100%;
	outline: none;
}
.h4yf-search-field::-webkit-search-decoration,
.h4yf-search-field::-webkit-search-cancel-button,
.h4yf-search-field::-webkit-search-results-button,
.h4yf-search-field::-webkit-search-results-decoration {
	-webkit-appearance: none;
	display: none;
}
.h4yf-search-field::placeholder {
	color: #9A9A9A;
	font-size: 12.5px;
}
.h4yf-search-clear {
	background: transparent;
	border: none;
	color: #9A9A9A;
	font-size: 18px;
	cursor: pointer;
	padding: 0 4px;
}
.h4yf-search-results {
	position: absolute;
	top: calc(100% + 8px);
	right: 0;
	width: 320px;
	max-width: 90vw;
	background: #0A0A0A;
	border: 1px solid #2C2C2E;
	border-radius: 8px;
	padding: 10px;
	box-shadow: 0 10px 30px rgba(0,0,0,0.8);
	z-index: 1000;
	max-height: 380px;
	overflow-y: auto;
}

/* Additional Information Tab Table Styling (Bug #3 — Column A White Text Fix) */
#tab-additional_information table,
.woocommerce-Tabs-panel--additional_information table,
table.woocommerce-product-attributes,
table.shop_attributes,
.woocommerce table.shop_attributes,
.ast-single-post table.shop_attributes,
body table.shop_attributes {
	background: #0A0A0A !important;
	border: 1px solid #2C2C2E !important;
	border-radius: 6px !important;
	width: 100% !important;
	border-collapse: separate !important;
	border-spacing: 0 !important;
	margin-bottom: 24px !important;
}

#tab-additional_information table th,
.woocommerce-Tabs-panel--additional_information table th,
table.woocommerce-product-attributes th,
table.shop_attributes th,
.woocommerce table.shop_attributes th,
.woocommerce-product-attributes-item__label,
th.woocommerce-product-attributes-item__label,
tr.woocommerce-product-attributes-item th,
body table.shop_attributes th {
	color: #FAFAFA !important;
	background: #1C1C1E !important;
	font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, sans-serif !important;
	font-weight: 700 !important;
	font-size: 13px !important;
	padding: 12px 16px !important;
	border-bottom: 1px solid #2C2C2E !important;
	border-right: 1px solid #2C2C2E !important;
	text-align: left !important;
	width: 35% !important;
}

#tab-additional_information table th a,
.woocommerce-Tabs-panel--additional_information table th a,
table.woocommerce-product-attributes th a,
table.shop_attributes th a,
.woocommerce table.shop_attributes th a,
.woocommerce-product-attributes-item__label a,
body table.shop_attributes th a {
	color: #FAFAFA !important;
	text-decoration: none !important;
	font-weight: 700 !important;
}

#tab-additional_information table td,
.woocommerce-Tabs-panel--additional_information table td,
table.woocommerce-product-attributes td,
table.shop_attributes td,
.woocommerce table.shop_attributes td,
.woocommerce-product-attributes-item__value,
td.woocommerce-product-attributes-item__value,
tr.woocommerce-product-attributes-item td,
body table.shop_attributes td {
	color: #FAFAFA !important;
	background: #0A0A0A !important;
	font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, sans-serif !important;
	font-size: 14px !important;
	padding: 12px 16px !important;
	border-bottom: 1px solid #2C2C2E !important;
}

#tab-additional_information table td a,
.woocommerce-Tabs-panel--additional_information table td a,
table.woocommerce-product-attributes td a,
table.shop_attributes td a,
.woocommerce table.shop_attributes td a,
.woocommerce-product-attributes-item__value a,
#tab-additional_information table td p,
.woocommerce-Tabs-panel--additional_information table td p,
table.woocommerce-product-attributes td p,
table.shop_attributes td p,
.woocommerce-product-attributes-item__value p {
	color: #FAFAFA !important;
	margin: 0 !important;
	padding: 0 !important;
}
.h4yf-search-list {
	list-style: none;
	margin: 0;
	padding: 0;
}
.h4yf-search-item {
	margin-bottom: 6px;
	border-bottom: 1px solid #1C1C1E;
	padding-bottom: 6px;
}
.h4yf-search-link {
	display: flex;
	align-items: center;
	gap: 10px;
	text-decoration: none;
	color: #FAFAFA;
	padding: 6px;
	border-radius: 4px;
	transition: background 0.15s ease;
}
.h4yf-search-link:hover, .h4yf-search-link:focus {
	background: #1C1C1E;
}
.h4yf-search-thumb {
	width: 44px;
	height: 44px;
	object-fit: cover;
	border-radius: 4px;
	background: #141414;
	flex-shrink: 0;
}
.h4yf-search-details {
	display: flex;
	flex-direction: column;
	overflow: hidden;
}
.h4yf-search-title {
	font-size: 12.5px;
	font-weight: 700;
	color: #FAFAFA;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.h4yf-search-meta {
	font-size: 11px;
	color: #9A9A9A;
	margin-top: 2px;
}
.h4yf-search-price {
	color: #FAFAFA;
}
.h4yf-search-no-results {
	padding: 12px 6px;
	font-size: 12.5px;
	color: #9A9A9A;
	text-align: center;
}
.h4yf-search-view-all {
	display: block;
	text-align: center;
	padding: 8px 0 4px;
	font-size: 12px;
	font-weight: 700;
	color: #C41E1E;
	text-decoration: none;
	border-top: 1px solid #2C2C2E;
	margin-top: 8px;
}
.h4yf-drawer-search {
	padding: 12px 16px;
	border-bottom: 1px solid #2C2C2E;
}
.h4yf-drawer-search .h4yf-search-input-wrap {
	width: 100%;
}

/* ================================================================== */
/* Storefront audit 2026-09-30 — header, card rhythm, empty states     */
/* ================================================================== */

/* Phone header: search is an icon that opens the drawer's full-width field
   (inc/header.php). Logo + 150px field + menu + cart measured 421px on a
   375px screen and pushed the cart button off-canvas. */
.h4yf-search-open {
	display: none;
}

@media (max-width: 768px) {
	.h4yf-header__actions .h4yf-search-widget {
		display: none;
	}

	.h4yf-search-open {
		display: inline-flex;
	}
}

/* One left edge per card. Title and price carried 12-16px of their own inset
   on top of the summary wrap's, the flames and condition badge carried none,
   so every card read as two ragged columns (desktop: text at 36px, flames at
   20px; phones mixed centred and left). */
.woocommerce ul.products li.product .astra-shop-summary-wrap,
.woocommerce ul.products li.product .woocommerce-loop-product__title,
.woocommerce ul.products li.product .price {
	text-align: left;
}

.woocommerce ul.products li.product .woocommerce-loop-product__title,
.woocommerce ul.products li.product .price {
	padding-left: 0;
	padding-right: 0;
}

/* The card's HEAT row is a <div>, not a link (inc/flames.php keeps it out of
   the thumbnail anchor), so the 44px tap floor was 26px of dead air per card. */
.woocommerce ul.products li.product .h4yf-score-block--compact .h4yf-score-row {
	min-height: 0;
}

/* Phones: 2-up again (Josh 2026-09-30, reversing the 2026-08-29 1-up rule).
   1-up put ~1.3 pairs on a screen and made /shop/ page 1 ~27,000px tall. */
@media (max-width: 768px) {
	.woocommerce ul.products li.product .astra-shop-summary-wrap {
		padding-left: 10px;
		padding-right: 10px;
	}

	.woocommerce ul.products li.product .price {
		padding-bottom: 4px;
	}

	.woocommerce ul.products li.product .h4yf-loop-cta {
		width: 100%;
		margin-inline: 0;
	}
}

/* Empty cart drawer: one route back to product, and no View Cart / Checkout
   pair pointing at an empty cart. `[data-cart-empty]` is in the server markup,
   so UCSS sees it at crawl time. */
.h4yf-cart-state__cta {
	margin-top: 20px;
}

.h4yf-drawer--cart:has([data-cart-empty]) .h4yf-drawer__foot {
	display: none;
}

/* Live search, no results: offer the request route instead of a dead end. */
.h4yf-search-request {
	display: block;
	margin-top: 8px;
	color: var(--h4yf-ink);
	font-weight: 700;
	text-decoration: underline;
	text-underline-offset: 3px;
}

.h4yf-search-request:hover,
.h4yf-search-request:focus-visible {
	color: var(--h4yf-hover);
}

/* Tapping the cart or menu opens a drawer and moves focus to its close button
   (assets/skin.js). That is :focus without :focus-visible, so Astra's
   `button:focus { background: var(--ast-global-color-1) }` painted it
   default blue on every phone open. Keyboard focus keeps its ring. */
.h4yf-icon-btn:focus:not(:focus-visible) {
	background: transparent;
}

/* Header + drawer search: ONE bar (2026-10-01, Josh: "double search bar").
   The wrapper draws the bar (border, fill, radius). The <input> inside kept a
   second box of its own: a sitewide `body.h4yf-skin input[type="search"]` rule
   (!important fill + 1px border + 10px 14px padding + 44px min-height) beats
   `.h4yf-search-field` at (0,2,2) against our (0,1,0), so a filled, bordered,
   44px input sat inside a 38px bordered wrapper and overflowed it. This rule
   outranks it, and the wrapper takes the 44px tap floor so the field fits. */
body.h4yf-skin .h4yf-search-input-wrap {
	height: 44px;
}

body.h4yf-skin .h4yf-search-input-wrap input.h4yf-search-field {
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	padding: 0 !important;
	min-height: 0;
	height: 100%;
	outline: none;
}


/* Cart/checkout sat flush against the left edge at <=1200px: Astra gives
   .alignwide blocks -20px side margins but the width stays the container's,
   so the block shifts left instead of widening (iPhone report, #1098). */
body.h4yf-skin .entry-content > .wp-block-woocommerce-cart.alignwide,
body.h4yf-skin .entry-content > .wp-block-woocommerce-checkout.alignwide {
	margin-left: 0;
	margin-right: 0;
}

/* TEAM $10 opt-in (#1098): top banner + consent labels. */
.h4yf-optin-banner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 10px 44px;
	background: var(--h4yf-crimson);
	color: #FFFFFF;
}
.h4yf-optin-banner__cta {
	background: none;
	border: 0;
	padding: 0;
	color: inherit;
	/* Bebas ships one weight, so the bold banner uses Montserrat 900 (#1098; the 800 face is not shipped). */
	font-family: var(--h4yf-body, "Montserrat", system-ui, sans-serif);
	font-size: 18px;
	font-weight: 900;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	cursor: pointer;
}
@media (max-width: 600px) {
	.h4yf-optin-banner__cta { font-size: 15px; }
}
.h4yf-optin-banner__close {
	position: absolute;
	right: 12px;
	top: 50%;
	transform: translateY(-50%);
	background: none;
	border: 0;
	color: inherit;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
}
.h4yf-optin-banner__cta:focus-visible,
.h4yf-optin-banner__close:focus-visible {
	outline: 2px solid #FFFFFF;
	outline-offset: 2px;
}
.h4yf-optin-consent {
	display: flex;
	gap: 8px;
	align-items: flex-start;
	font-size: 11px;
	line-height: 1.4;
	color: #B5B5B5;
	text-align: left;
}
#h4yf-popup .h4yf-optin-consent input,
.h4yf-optin-consent input {
	flex: none;
	width: auto;
	min-height: 0;
	margin: 2px 0 0;
	padding: 0;
}
.h4yf-optin-consent a {
	color: inherit;
	text-decoration: underline;
}

/* #1098: inline TEAM form (homepage band + footer). */
.h4yf-optin-inline {
	position: relative;
	display: grid;
	gap: 10px;
	max-width: 520px;
	margin: 0 auto;
	text-align: left;
}
.h4yf-optin-inline input[type="text"],
.h4yf-optin-inline input[type="email"],
.h4yf-optin-inline input[type="tel"] {
	width: 100%;
	min-height: 48px;
	padding: 12px 14px;
	font-size: 16px;
}
.h4yf-optin-inline button[type="submit"] { width: 100%; }

/* #1108: cart "Get $10 off this order". */
.h4yf-cart-optin { margin: 0 0 20px; padding: 14px 16px; border: 1px solid var(--h4yf-crimson); }
.h4yf-cart-optin summary { cursor: pointer; font-weight: 700; color: var(--h4yf-ink); }
.h4yf-cart-optin .h4yf-optin-inline { margin-top: 14px; }

/* #1109: TEAM10 page. */
.h4yf-t10 { max-width: 620px; margin: 0 auto; padding: 0 16px; }
.h4yf-t10__steps { padding-left: 20px; }
.h4yf-t10__steps li { margin: 0 0 24px; }
.h4yf-t10__steps input[readonly] { width: 100%; min-height: 44px; padding: 10px; font-size: 15px; }
.h4yf-t10__done { color: var(--h4yf-crimson); }
.h4yf-t10__note, .h4yf-t10__code { padding: 12px 14px; border: 1px solid var(--h4yf-crimson); }
.h4yf-t10__fine { font-size: 12px; color: #B5B5B5; }
