/* Ported verbatim from the block-theme prototype (v0.4.1). Tokens live in tokens.css. */
/* ==========================================================================
   Base
   ========================================================================== */
body {
	font-family: var(--ps-font);
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}
img { max-width: 100%; height: auto; }
summary { cursor: pointer; list-style: none; }
summary::-webkit-details-marker { display: none; }
:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 2px; }

/* ==========================================================================
   MOTION — reveal on scroll (the primitive that "awakens" the platform)
   Elements tagged .ps-reveal rise + fade in when scrolled into view (ps.js
   IntersectionObserver adds .is-in, once). The hidden resting state is gated
   on html.ps-anim — set synchronously by a tiny inline <head> script — so
   without JS content is simply visible (never stuck at opacity:0), and there
   is no first-paint flash. Reduced-motion shows everything instantly.
   A container with data-ps-stagger cascades its .ps-reveal children (ps.js
   sets an incremental transition-delay).
   ========================================================================== */
.ps-reveal {
	/* Opacity leads slightly (shorter, plainer curve) while the movement runs the
	   S — the element reads as arriving rather than being switched on. */
	transition: opacity var(--ps-dur-3) ease, transform var(--ps-dur-4) var(--ps-ease-enter);
	will-change: opacity, transform;
}
html.ps-anim .ps-reveal { opacity: 0; transform: translateY(14px); }
html.ps-anim .ps-reveal.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
	html.ps-anim .ps-reveal { opacity: 1 !important; transform: none !important; transition: none; }
	.ps-ordermeter-bar i { transition: none; }
}

/* Kill the WordPress root blockGap (1.5rem) that inserts a white strip between
   the <header> (announce bar) and <main> — the hero must sit flush under it. */
.ps-main { min-height: 60vh; margin-top: 0; margin-block-start: 0; }

/* Section rhythm: a 1200px column inside the root gutter. Uniform 3.5rem gap
   to match the Figma's consistent ~60px between content blocks. */
.ps-section {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 0 auto var(--ps-section);
}
/* The hero already fades to white for ~12% of its height, so a full section
   margin on top of that reads as dead air. The why-us block and the catalog
   that follows it sit on a tighter rhythm. */
.ps-why2 { margin-bottom: var(--ps-sp-7); }
.ps-why2 > .ps-h2 { margin-bottom: var(--ps-sp-3); }
.ps-h2 {
	font-size: var(--ps-t-h2);
	font-weight: 500;
	line-height: 1.167;
	letter-spacing: -0.01em;
	color: var(--ps-blue);
	margin: 0 0 var(--ps-sp-5);
}

/* Buttons */
.ps-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--ps-sp-2);
	font-family: var(--ps-font);
	font-size: var(--ps-t-sm);
	font-weight: 500;
	letter-spacing: -0.01em;
	line-height: 1;
	padding: 0.875rem 1.875rem;
	border: 0;
	border-radius: 0;
	text-decoration: none;
	cursor: pointer;
	transition: background-color var(--ps-dur-1) ease, color var(--ps-dur-1) ease;
}
.ps-btn-blue { background: var(--ps-blue); color: #fff; }
.ps-btn-blue:hover { background: var(--ps-blue-deep); color: #fff; }

/* ==========================================================================
   Announcement + header
   ========================================================================== */
/* The header — top bar + black announce liner together — sticks to the top on
   scroll, desktop and mobile. `sticky` keeps it in the flow so there's no content
   jump (the only ancestor overflow is the transient age-gate scroll-lock). z-index
   sits above page content but below the age-gate overlay (1000). Offset below the
   WordPress admin bar for logged-in users. */
.ps-site-header {
	position: sticky;
	top: 0;
	z-index: 100;
}
body.admin-bar .ps-site-header { top: 32px; }
@media screen and (max-width: 782px) {
	body.admin-bar .ps-site-header { top: 46px; }
}

/* Announce ticker — a scrolling strip of value props (replaces the static line
   the client found "depressing"). Two identical groups translate -50% for a
   seamless loop; pauses on hover; static + clipped under
   reduced-motion. Keyword <b> gets a light-blue accent that reads on the dark bar. */
.ps-announce {
	background: var(--ps-dark);
	color: #fff;
	overflow: hidden; /* no edge fade (user call) — items read clean to the edges */
}
.ps-ticker-track { display: flex; width: max-content; animation: ps-ticker 44s linear infinite; will-change: transform; }
.ps-ticker:hover .ps-ticker-track { animation-play-state: paused; }
.ps-ticker-group { display: flex; align-items: center; flex: 0 0 auto; }
.ps-ticker-item {
	flex: 0 0 auto;
	padding: 0.5rem 0;
	font-size: var(--ps-t-xs);
	line-height: 1.4;
	letter-spacing: -0.01em;
	color: rgba(255, 255, 255, 0.9);
	white-space: nowrap;
}
.ps-ticker-item b { color: #7CC1EC; font-weight: 700; } /* accent keyword, light-blue on --ps-dark */
.ps-ticker-sep { flex: 0 0 auto; display: inline-flex; align-items: center; color: var(--ps-blue); opacity: 0.9; margin: 0 1.25rem; }
@keyframes ps-ticker { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
	.ps-ticker-track { animation: none; }
	.ps-ticker-group[aria-hidden="true"] { display: none; }
}

.ps-header {
	display: flex;
	align-items: center;
	background: var(--ps-paper);
	padding: 0.5rem var(--ps-gutter);
	position: relative;
	z-index: 40;
}
.ps-logo { display: inline-flex; align-items: center; }
.ps-logo img.ps-logo-full { width: 80px; height: 28px; }
.ps-logo img.ps-logo-mark { display: none; width: 26px; height: auto; }
.ps-nav {
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	gap: 1.75rem;
}
.ps-nav a {
	font-size: var(--ps-t-ui);
	font-weight: 500;
	letter-spacing: -0.01em;
	color: var(--ps-navy);
	text-decoration: none;
}
.ps-nav a:hover { color: var(--ps-blue); }
.ps-header-actions { margin-left: auto; display: flex; align-items: center; gap: var(--ps-sp-5); }
.ps-header-cta { padding: 0.5rem 1.15rem; font-size: var(--ps-t-sm); }
/* CART CONTROL — solid blue when loaded, per the client reference.
   The blue is the SAME token as the "Why choose us" heading (--ps-blue), so the
   one saturated accent on the page is reused rather than a new colour invented.
   Reading order matches the reference: bag → amount → quantity badge.
   Empty stays a quiet outline chip so an empty cart never shouts.
   28px tall keeps the header at its production height (44px desktop). */
.ps-cart {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 0.4375rem;
	height: 28px;
	padding: 0 0.5rem;
	/* Blue with a white bag in BOTH states — an outline-when-empty chip made the
	   control change identity depending on the cart, which read as two different
	   components. One object, one colour; only the contents change. */
	border: 1px solid var(--ps-blue);
	background: var(--ps-blue);
	color: #fff;
	text-decoration: none;
	font-size: var(--ps-t-xs);
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1;
	transition: background var(--ps-dur-1) ease, border-color var(--ps-dur-1) ease, box-shadow var(--ps-dur-1) ease;
}
.ps-cart:hover { border-color: var(--ps-blue-deep); background: var(--ps-blue-deep); color: #fff; }
.ps-cart:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 2px; }
.ps-cart-ico { display: inline-flex; color: #fff; }
.ps-cart-ico svg { width: 15px; height: 15px; }
.ps-cart-total { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ps-cart-total:empty { display: none; }
/* Quantity rides in a translucent well so it reads as a value ON the button,
   not a second button beside it. */
.ps-cart-count {
	display: inline-grid;
	place-items: center;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	background: rgba(255, 255, 255, 0.24);
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 1;
	font-variant-numeric: tabular-nums;
}
.ps-cart-count[hidden] { display: none; }

/* Loaded: the blue state from the reference. */
.ps-cart.has-items {
	padding: 0 0.375rem 0 0.625rem;
	box-shadow: 0 4px 14px -6px rgba(0, 118, 184, 0.55);
}
.ps-cart.has-items:hover {
	background: var(--ps-blue-deep);
	border-color: var(--ps-blue-deep);
	color: #fff;
	box-shadow: 0 8px 20px -8px rgba(0, 118, 184, 0.6);
}

/* One beat when the number changes. */
.ps-cart.is-bumped .ps-cart-count { animation: ps-cart-pop var(--ps-dur-3) var(--ps-ease-pop); }
@keyframes ps-cart-pop { 0% { transform: scale(1); } 40% { transform: scale(1.35); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) {
	.ps-cart { transition: none; }
	.ps-cart.is-bumped .ps-cart-count { animation: none; }
}

/* Header icon buttons — the menu hamburger + search trigger. Flat, transparent,
   navy → blue on hover; SVGs block-level so the hit area hugs the glyph. */
.ps-icon-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.375rem;
	margin: 0;
	background: transparent;
	border: 0;
	color: var(--ps-navy);
	cursor: pointer;
	line-height: 0;
	transition: color var(--ps-dur-1) ease;
}
.ps-icon-btn:hover { color: var(--ps-blue); }
.ps-icon-btn svg { display: block; }

/* Menu hamburger — mobile-only trigger (desktop keeps the inline .ps-nav). The
   three bars flip to an X while the menu overlay is open (aria-expanded). */
.ps-menu-trigger { display: none; margin-left: -0.375rem; }
.ps-burger { display: block; width: 22px; height: 16px; position: relative; }
.ps-burger i {
	position: absolute;
	left: 0; right: 0;
	height: 2px;
	background: currentColor;
	border-radius: 0;
	transition: transform var(--ps-dur-1) ease, opacity var(--ps-dur-1) ease, top var(--ps-dur-1) ease;
}
.ps-burger i:nth-child(1) { top: 0; }
.ps-burger i:nth-child(2) { top: 7px; }
.ps-burger i:nth-child(3) { top: 14px; }
.ps-menu-trigger[aria-expanded="true"] .ps-burger i:nth-child(1) { top: 7px; transform: rotate(45deg); }
.ps-menu-trigger[aria-expanded="true"] .ps-burger i:nth-child(2) { opacity: 0; }
.ps-menu-trigger[aria-expanded="true"] .ps-burger i:nth-child(3) { top: 7px; transform: rotate(-45deg); }

/* ==========================================================================
   Hero
   ========================================================================== */
.ps-hero {
	position: relative;
	min-height: 204px;
	display: grid;
	place-items: center;
	overflow: hidden;
	margin-bottom: var(--ps-sp-6);   /* the hero already fades to white — a full section margin on top reads as dead air */
}
.ps-hero-media { position: absolute; inset: 0; z-index: 0; }
/* ps.js sets height/top so a chosen point in the SOURCE lands at a chosen point
   in the hero. Width is always 100%; when the computed box is taller than the
   source ratio, cover crops horizontally and the full height stays visible —
   which is what lets a 204px hero still show the strip. */
.ps-hero-media img { position: absolute; left: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; }
/* Compact hero: mobile 204px (Figma "Frame 143"), desktop 276px (Figma "Hero"),
   both the correct hands-up crop. */
@media (max-width: 740px) {
	/* Production height, restored exactly. The strip is brought to the button by
	   cropping the photo (ps.js), not by growing the hero. */
	.ps-hero { min-height: 204px; }
}
/* ≤360px the headline wraps to three lines, pushing the button past the tallest
   hero a 568px-high screen can carry. One size step brings it back to two. */
@media (max-width: 360px) {
	/* .ps-hero prefix: this block sits ABOVE the base h1 rule in source order, so a
	   bare .ps-hero-copy h1 would lose the cascade to it. */
	.ps-hero .ps-hero-copy h1 { font-size: 1.5rem; }
}
@media (min-width: 741px) {
	.ps-hero { min-height: 276px; }
	/* height/top come from the crop solver in ps.js */
}
/* Shadow overlay ABOVE the image (z-index:1) — matches the Figma "Background"
   layer: a flat black scrim so the white copy stays legible over the bright lab
   coat (this replaces the old white wash that washed the image out). The bottom
   ramps to solid white so the hero blends into the page. A pseudo-element paints
   below its parent's child <img> by default, hence the explicit z-index. */
.ps-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	/* Three layers, lightest-touch first:
	   1. the bottom fade that hands off to the white page,
	   2. a SHADOW CAST BY THE TICKER — strongest exactly at its bottom edge and
	      gone within ~150px, so the dark bar reads as sitting above the photo,
	   3. a light overall wash (was 0.46 flat, which flattened the whole image
	      into a grey slab) that only guarantees a contrast floor for the type. */
	/* ONE monotonic ramp for the shadow. The previous version layered a short
	   dark gradient over a separate wash that got darker again lower down, so
	   the two crossed and left a visible light band a few px under the ticker.
	   This only ever gets lighter, top to bottom, full-bleed edge to edge. */
	background:
		linear-gradient(180deg, rgba(255,255,255,0) 88%, rgba(255,255,255,0.5) 95%, #fff 100%),
		linear-gradient(180deg,
			rgba(8,20,33,0.30) 0,
			rgba(8,20,33,0.20) 34px,
			rgba(8,20,33,0.14) 80px,
			rgba(8,20,33,0.11) 150px,
			rgba(8,20,33,0.10) 100%);
}
.ps-hero-copy { position: relative; z-index: 2; text-align: center; padding: 1.5rem var(--ps-gutter); }
/* Contrast is bought per-glyph, not per-photograph. The overlay above was
   carrying legibility for the whole hero, which is why it had to be dark enough
   to grey out the image; a tight shadow behind the type does the same job for
   the only pixels that need it, so the wash can drop from 0.44 to 0.30 and the
   photo comes back. Two layers: a close dark core for edge definition, a wider
   soft one so the letterforms hold over a bright patch of glove or cuff. */
.ps-hero-copy h1,
.ps-hero-copy > p {
	text-shadow: 0 1px 2px rgba(8, 20, 33, 0.42), 0 2px 14px rgba(8, 20, 33, 0.34);
}
.ps-hero-copy::before {
	content: "";
	position: absolute;
	inset: -12% -8%;
	z-index: -1;
	pointer-events: none;
	background: radial-gradient(ellipse at 50% 44%, rgba(8, 20, 33, 0.56) 0%, rgba(8, 20, 33, 0.32) 48%, rgba(8, 20, 33, 0) 74%);
}
/* The CTA is nudged onto the strip by ps.js when panning alone can't reach it. */
.ps-hero-copy .ps-btn { will-change: transform; }
@media (min-width: 741px) {
	.ps-hero-copy { padding: 2rem var(--ps-gutter); }
}
.ps-hero-copy h1 {
	font-size: clamp(1.875rem, 1.4rem + 2vw, 2.5rem);
	font-weight: 700;
	line-height: 1.1;
	letter-spacing: -0.01em;
	color: #fff;
	margin: 0 0 0.5rem;
	text-shadow: 0 1px 2px rgba(8, 20, 33, 0.42), 0 2px 22px rgba(8, 20, 33, 0.5);
}
.ps-hero-copy p {
	font-size: 1rem;
	color: #fff;
	line-height: 1.4;
	margin: 0 0 1.75rem;
	text-shadow: 0 1px 2px rgba(8, 20, 33, 0.45), 0 2px 18px rgba(8, 20, 33, 0.5);
}

/* ==========================================================================
   Wash cards (support / keypoints / shop values)
   ========================================================================== */
.ps-support-cards {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--ps-gap-grid);
}
.ps-wash-card {
	background: var(--ps-wash);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-sp-3);
	padding: 1.125rem 0 1.125rem 1.5rem;
	min-height: 6rem;
	overflow: hidden;
}
.ps-wash-copy { min-width: 0; }
.ps-wash-card h3 {
	font-size: 1.25rem;
	font-weight: 500;
	line-height: 1.2;
	letter-spacing: -0.01em;
	color: var(--ps-ink);
	margin: 0 0 0.375rem;
}
.ps-wash-card p { font-size: var(--ps-t-sm); line-height: 1.35; color: var(--ps-muted); margin: 0; }
.ps-wash-card .ps-wash-sub { color: var(--ps-blue); font-weight: 500; margin-bottom: 0.25rem; }
.ps-wash-card img { flex: 0 0 auto; width: 122px; height: 104px; object-fit: contain; object-position: right center; }

/* ==========================================================================
   Why choose us — wash cards with the Figma render treatment (the ORIGINAL,
   restored at the user's call after the panel / plates / dossier experiments).
   ========================================================================== */
.ps-why-cards {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.8125rem; /* original Figma rhythm for this row (predates --ps-gap-grid) */
}
/* Why-us card icons — matched to the Figma: each bleeds off the right, the
   DNA helix tilts and fades at the bottom, the COA sheet zooms + angles, the
   gauge sits cropped at the edge. Absolute so they can overflow the card. */
.ps-why-cards .ps-wash-card { position: relative; overflow: hidden; }
.ps-why-cards .ps-wash-card .ps-wash-copy { position: relative; z-index: 2; }
.ps-why-cards .ps-wash-card > img {
	position: absolute;
	top: 50%;
	right: 0;
	width: auto;
	height: 150px;
	margin: 0;
	pointer-events: none;
	z-index: 1;
}
.ps-why-cards .ps-icon-dna > img {
	height: 176px;
	right: -34px;
	transform: translateY(-50%) rotate(23deg);
	-webkit-mask-image: linear-gradient(176deg, #000 50%, transparent 86%);
	mask-image: linear-gradient(176deg, #000 50%, transparent 86%);
}
.ps-why-cards .ps-icon-coa > img {
	height: auto;
	width: 205px;
	right: -34px;
	transform: translateY(-50%) rotate(-12deg);
	filter: drop-shadow(0 10px 16px rgba(11, 19, 30, 0.10));
}
.ps-why-cards .ps-icon-gauge > img {
	height: 112px;
	right: -14px;
	transform: translateY(-50%);
	filter: drop-shadow(0 8px 14px rgba(11, 19, 30, 0.12));
}

/* ==========================================================================
   Products marquee (home)
   ========================================================================== */
/* The track is NOT animated until ps.js confirms every image has decoded:
   Chrome rasterizes an animated (composited) layer once and misses textures
   that decode later — cards painted blank. No animation → normal raster;
   .is-ready then starts the loop with all textures present. */
.ps-marquee {
	overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
	mask-image: linear-gradient(90deg, transparent 0, #000 5%, #000 95%, transparent 100%);
}
.ps-marquee-track { display: flex; width: max-content; }
.ps-marquee.is-ready .ps-marquee-track { animation: ps-marquee 45s linear infinite; }
.ps-marquee:hover .ps-marquee-track { animation-play-state: paused; }
.ps-marquee-group { display: flex; padding-right: 1rem; }
@keyframes ps-marquee { to { transform: translateX(-50%); } }

/* Captions/fine-print HUG the component they annotate (--ps-caption-gap);
   the full section gap always comes AFTER the caption, never around it. */
.ps-disclaimer { font-size: var(--ps-t-xs); color: var(--ps-soft); margin: var(--ps-caption-gap) 0 0; }

/* Woo loop cards — shared by marquee + shop grid.
   The shortcode wraps everything in div.woocommerce — flatten it, then kill
   Woo's clearfix pseudo grid items and width presets. */
.ps-shop-grid > .woocommerce,
.ps-marquee-group > .woocommerce { display: contents; }
ul.products[class*="columns-"]::before,
ul.products[class*="columns-"]::after { display: none !important; content: none !important; }
ul.products[class*="columns-"] { margin: 0 !important; padding: 0 !important; list-style: none; }
ul.products[class*="columns-"] li.product {
	float: none !important;
	width: auto !important;
	margin: 0 !important;
	background: var(--ps-wash);
	padding: 1.25rem 1.25rem 1rem;
	display: flex;
	flex-direction: column;
	text-align: left;
}
/* The loop link carries the whole card body (title/meta/price/image, already
   in design order via functions.php hooks). NOT display:contents — Chrome
   skips painting replaced elements through contents-anchors inside the
   max-content marquee track (verified empirically). */
ul.products[class*="columns-"] li.product a.woocommerce-LoopProduct-link {
	display: flex !important;
	flex-direction: column;
	flex: 1 1 auto;
	min-width: 0;
	color: inherit;
	text-decoration: none;
}
ul.products[class*="columns-"] li.product .woocommerce-loop-product__title {
	font-size: 1rem;
	font-weight: 500;
	letter-spacing: -0.01em;
	color: var(--ps-ink);
	padding: 0;
	margin: 0 0 0.25rem;
	order: 1;
}
ul.products[class*="columns-"] li.product .ps-card-meta {
	font-size: var(--ps-t-xs);
	color: var(--ps-muted);
	margin: 0 0 0.375rem;
	order: 2;
}
ul.products[class*="columns-"] li.product .price {
	font-size: var(--ps-t-ui);
	font-weight: 500;
	color: var(--ps-blue) !important;
	margin: 0 0 0.75rem;
	order: 3;
}
ul.products[class*="columns-"] li.product img.attachment-woocommerce_single,
ul.products[class*="columns-"] li.product img {
	order: 4;
	width: auto;
	max-width: 78%;
	height: 170px;
	object-fit: contain;
	margin: auto;
}
ul.products[class*="columns-"] li.product .ps-card-actions {
	order: 5;
	margin-top: auto;
	display: flex;
	justify-content: flex-end;
}
.ps-learn-more {
	display: inline-flex;
	align-items: center;
	gap: 0.25rem;
	font-size: var(--ps-t-xs);
	font-weight: 500;
	color: var(--ps-blue);
	text-decoration: underline;
	text-underline-offset: 3px;
}
.ps-learn-more:hover { color: var(--ps-blue-deep); }
/* Stray empty paragraphs from wpautop inside cards */
ul.products li.product > p:empty { display: none; }

/* Marquee-specific card geometry */
.ps-marquee ul.products[class*="columns-"] { display: flex !important; gap: var(--ps-sp-6); width: max-content; }
.ps-marquee-group { padding-right: 1.5rem; }
.ps-marquee li.product { width: 230px !important; min-height: 300px; }
.ps-marquee ul.products[class*="columns-"] li.product img { height: 162px; max-width: 92%; }

/* ==========================================================================
   Splits + considerations + accordion + shipping
   ========================================================================== */
.ps-split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 2.5rem;
	align-items: center;
}
.ps-split-media { margin: 0; }
.ps-split-media img { width: 100%; height: 300px; object-fit: cover; }
.ps-media-plain img { height: auto; max-height: 224px; width: auto; max-width: 100%; object-fit: contain; margin: 0 auto; }
.ps-split-sub {
	font-size: 1rem;
	font-weight: 500;
	color: var(--ps-ink);
	margin: -0.75rem 0 1rem;
}
.ps-split-body { font-size: 1rem; line-height: 1.45; color: var(--ps-muted); margin: 0 0 1.5rem; max-width: 36rem; }

.ps-kicker { font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-ink); margin: 0 0 1.25rem; }
.ps-considerations-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 2.5rem; }
.ps-considerations-grid h4 {
	font-size: var(--ps-t-sm);
	font-weight: 500;
	color: var(--ps-blue);
	margin: 0 0 0.5rem;
}
.ps-considerations-grid p { font-size: var(--ps-t-xs); line-height: 1.45; color: var(--ps-muted); margin: 0; }

.ps-accordion { display: flex; flex-direction: column; gap: var(--ps-sp-2); margin: 0 0 1.5rem; }
.ps-accordion details { background: var(--ps-wash); }
.ps-accordion summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0.875rem 1rem;
	font-size: var(--ps-t-ui);
	font-weight: 500;
	color: var(--ps-ink);
}
.ps-accordion summary::after {
	content: "";
	width: 8px;
	height: 8px;
	border-right: 1.6px solid var(--ps-muted);
	border-bottom: 1.6px solid var(--ps-muted);
	transform: rotate(45deg);
	transition: transform var(--ps-dur-1) ease;
	flex: 0 0 auto;
	margin-left: 1rem;
}
.ps-accordion details[open] summary::after { transform: rotate(-135deg); }
.ps-accordion-body { padding: 0 1rem 1rem; }
.ps-accordion-body p { font-size: var(--ps-t-sm); line-height: 1.45; color: var(--ps-muted); margin: 0 0 0.625rem; }
.ps-tested-for { color: var(--ps-ink); }
.ps-tested-for span { color: var(--ps-blue); font-weight: 500; }

/* ==========================================================================
   FAQ
   ========================================================================== */
.ps-faq-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ps-sp-3); align-items: start; }
.ps-faq details, .ps-faq-col details {
	background: var(--ps-paper);
	border: 1px solid var(--ps-line);
}
.ps-faq summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0.875rem 1rem;
	font-size: var(--ps-t-sm);
	font-weight: 500;
	color: var(--ps-ink);
}
.ps-faq summary::after {
	content: "";
	width: 7px;
	height: 7px;
	border-right: 1.6px solid var(--ps-muted);
	border-bottom: 1.6px solid var(--ps-muted);
	transform: rotate(45deg);
	transition: transform var(--ps-dur-1) ease;
	margin-left: 1rem;
	flex: 0 0 auto;
}
.ps-faq details[open] summary::after { transform: rotate(-135deg); }
.ps-faq details > p { padding: 0 1rem 0.875rem; margin: 0; font-size: var(--ps-t-sm); line-height: 1.5; color: var(--ps-muted); }
.ps-faq-col { display: flex; flex-direction: column; gap: var(--ps-sp-3); }

/* ==========================================================================
   CTA band
   ========================================================================== */
/* Slim premium bands — Figma tiles are 590×180 (~3.3:1), 20px gap. */
/* minmax, not a flat 180px: between 901 and ~1000px the band is still two
   columns while the help card is at its narrowest, and the Figma's one-sentence
   contact line wrapped past 180px and was CLIPPED. The row may grow there.
   .ps-cta-shop keeps an explicit height (below) precisely so its 200px bleed
   image cannot drive the row's min-content and inflate every other width. */
.ps-cta-band { display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: minmax(180px, auto); gap: var(--ps-sp-5); }
/* Fixed row height (grid-auto-rows) is what actually pins the slim tiles — items
   with align-items:stretch ignore their own height and stretch to the row, and
   without a fixed row the portrait box image inflates it. min-height:0 lets the
   image be clipped rather than setting the row's min-content floor. */
.ps-cta-band > * { min-height: 0; box-sizing: border-box; }
.ps-cta-help {
	background: var(--ps-blue);
	color: #fff;
	padding: 2rem;
	position: relative;
	overflow: hidden;
	min-height: 180px;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
}
.ps-cta-help h2 { font-size: 1.375rem; font-weight: 500; line-height: 1.15; letter-spacing: -0.01em; color: #fff; margin: 0 0 0.75rem; max-width: 45%; }
/* Same copy column the h2 keeps. The old line was two short fragments
   ("Reach us out at" + the address) and never reached the chat mockup, so it
   carried no constraint; the Figma line is one full sentence and ran straight
   under the bubbles. The limit is derived from .ps-chat, not guessed: that box
   is 52% wide with right:2rem, so the copy may occupy 48% minus the two 2rem
   gutters. A flat percentage only clears while the card is wide — at 1024 and
   768 the card narrows and a fixed 42% starts colliding again. */
.ps-cta-reach { font-size: var(--ps-t-sm); line-height: 1.5; color: rgba(255, 255, 255, 0.85); margin: 0; max-width: calc(48% - 4rem); }
.ps-cta-reach a { color: #fff; font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
.ps-chat { position: absolute; right: 2rem; top: 50%; transform: translateY(-50%); display: flex; flex-direction: column; gap: 0.375rem; width: 52%; }
.ps-chat p { margin: 0; font-size: var(--ps-t-xs); line-height: 1.3; padding: 0.5rem 0.875rem; border-radius: var(--ps-r-pill); width: fit-content; }
.ps-chat-in { background: #16A2F9; color: #fff; align-self: flex-end; }
.ps-chat-out { background: #fff; color: var(--ps-ink); align-self: flex-start; margin-top: 0.5rem; border-radius: var(--ps-r-md); }
/* height:100%, not a fixed 180px: the row is now minmax(180px, auto) and the
   help card can grow with its copy, so a pinned shop card would sit short of
   its neighbour. 100% stretches to whatever the row resolves to, while still
   giving the 200px bleed image a definite height to overflow out of — an
   `auto` height here would let that image drive the row instead. */
.ps-cta-shop { background: var(--ps-navy); color: #fff; padding: 2rem 2rem 0; display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ps-sp-4); overflow: hidden; position: relative; height: 100%; min-height: 180px; }
.ps-cta-shop .ps-cta-shop-copy { padding-bottom: 2rem; }
.ps-cta-shop h2 { font-size: 1.375rem; font-weight: 500; line-height: 1.15; letter-spacing: -0.01em; color: #fff; margin: 0 0 1rem; }
.ps-cta-dim { color: rgba(255, 255, 255, 0.45); }
.ps-cta-shop img { position: absolute; right: 2rem; bottom: -1.25rem; height: 200px; width: auto; filter: drop-shadow(0 18px 24px rgba(0, 0, 0, 0.45)); pointer-events: none; }

/* ==========================================================================
   SHOP (v2 redesign) — Figma HyPStzuochxvctFWZiAGrc / 1445:2731
   Masthead → 3 value cards → search → 4×2 product grid (+ not-found tile) →
   Same-Day Shipping. Content column is the shared 1200px track; product tiles
   reuse the global Woo loop card so they're identical to Home's. Colors sampled
   from the artboard all resolve to existing tokens — nothing hardcoded.
   Card / tile / field rounding (16px) comes from the shared radius block below.
   ========================================================================== */

/* Masthead — eyebrow / H1 / subhead. These three are generic page-masthead
   helpers (also used by index.php, page.php, page-coa.php) — keep them global. */
.ps-shop-intro { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: var(--ps-lede) auto var(--ps-sp-5); }
.ps-eyebrow { font-size: var(--ps-t-xs); font-weight: 500; color: var(--ps-blue); margin: 0 0 0.75rem; }
.ps-page-title {
	font-size: var(--ps-t-h2);
	font-weight: 500;
	line-height: 1.167;
	letter-spacing: -0.01em;
	color: var(--ps-navy);
	margin: 0 0 0.5rem;
}
.ps-page-sub { font-size: 1rem; color: var(--ps-muted); margin: 0; }

/* Left-biased page wash — the pale-blue "Rectangle 50" glow behind the value
   cards + first product row (Figma samples to ~#E5F5FF on the left edge). The
   global .ps-main::before glows are tuned for the Home artboard; override just
   the background for the shop so the light pools on the left, not the centre. */
.ps-shop.ps-main::before {
	background:
		radial-gradient(40rem 26rem at -4% 14%, rgba(0, 118, 184, 0.07), transparent 66%),
		radial-gradient(46rem 34rem at -8% 42%, rgba(0, 118, 184, 0.055), transparent 66%),
		radial-gradient(24rem 22rem at 104% 28%, rgba(0, 118, 184, 0.03), transparent 70%);
}

/* Value row — Supported / Informed / Confident. Same card family as Home's
   key-points (white + hairline border vs the borderless why-us wash); 3-across
   on desktop with the Figma's 20px gutter, stacking on mobile. */
.ps-shop-values { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto var(--ps-section); }
.ps-shop-values .ps-wash-card { background: var(--ps-paper); border: 1px solid var(--ps-line); }

/* Search — a styled field wrapping the live client-side filter (#ps-shop-filter,
   wired in ps.js); the leading glyph is a static magnifier. */
.ps-shop-search {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 0 auto var(--ps-sp-5);
	display: flex;
	align-items: center;
	gap: var(--ps-sp-3);
	background: var(--ps-field);
	border: 1px solid var(--ps-line);
	padding: 0.875rem 1.125rem;
	color: var(--ps-soft);
}
.ps-shop-search input {
	flex: 1;
	min-width: 0;
	border: 0;
	background: transparent;
	font-family: var(--ps-font);
	font-size: 1rem;
	color: var(--ps-ink);
	outline: none;
}
.ps-shop-search input::placeholder { color: var(--ps-soft); }

/* Product grid — 4 columns × 2 rows (7 products + the not-found tile = 8), the
   Figma's 20px gutter. The [products] shortcode wraps the loop in div.woocommerce
   (flattened to display:contents by the shared Woo-loop block above) and ul.products
   (flattened here) so each li.product becomes a direct grid item. Tile geometry
   matches Home's card (1.125rem padding); the image fills the wider 4-up cell. */
.ps-shop-grid {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 0 auto var(--ps-section);
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--ps-gap-grid);
}
.ps-shop-grid ul.products[class*="columns-"] { display: contents !important; }
.ps-shop-grid li.product { min-height: 288px; padding: 1.125rem; }
.ps-shop-grid ul.products[class*="columns-"] li.product img { height: 162px; max-width: 78%; }
.ps-shop-grid li.product[hidden] { display: none !important; }

/* Not-found tile — the grid's last cell, a pale-blue panel (Figma ~#DEF1F7,
   token-derived from --ps-blue; --ps-pale is the no-color-mix fallback). Grid
   row-stretch matches its height to the product cards. */
.ps-notfound-tile {
	background: var(--ps-pale);
	background: color-mix(in srgb, var(--ps-blue) 12%, #fff);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--ps-sp-2);
	min-height: 288px;
	padding: 1.25rem;
	text-align: center;
}
.ps-notfound-tile .ps-notfound-title { font-size: 1rem; font-weight: 500; line-height: 1.3; color: var(--ps-ink); margin: 0; }
.ps-notfound-tile a { font-size: var(--ps-t-sm); color: var(--ps-blue); text-decoration: underline; text-underline-offset: 3px; }

/* Catalog mobile — natural DOM order (masthead → values → search → grid →
   shipping) per the 390 artboard; grid drops to 2-up, value cards stack. The
   .ps-shop-values selector out-specifies the base stacking rule, so restate it. */
@media (max-width: 900px) {
	.ps-shop-grid { grid-template-columns: repeat(2, 1fr); }
	.ps-shop-grid ul.products[class*="columns-"] li.product img { height: 190px; }
	.ps-shop-values .ps-support-cards { grid-template-columns: 1fr; }
}

/* ==========================================================================
   PDP
   ========================================================================== */
/* Buy box: image panel (left) + summary (right), 1200 container (Figma 12952:1957) */
.ps-pd-crumb {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 1.5rem auto 0;
	display: flex;
	align-items: center;
	gap: var(--ps-sp-2);
}
.ps-pd-crumb a { font-size: var(--ps-t-sm); color: var(--ps-muted); text-decoration: none; }
.ps-pd-crumb a:hover { color: var(--ps-blue); }
.ps-pd-crumb span { font-size: var(--ps-t-sm); font-weight: 500; color: var(--ps-ink); }
.ps-pd-crumb .ps-crumb-sep { color: var(--ps-line-2); flex: 0 0 auto; }

.ps-pdp .woocommerce { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto; }
.ps-pdp div.product {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 1.75rem auto 0;
	display: grid;
	/* Specimen plate, not billboard: the product is a pocket-sized box, so the
	   image column yields width to the data-dense buy column (~446px / ~694px
	   at full content width). */
	grid-template-columns: minmax(0, 9fr) minmax(0, 14fr);
	gap: 3.75rem;
	align-items: start;
}
/* min-width: 0 — grid items default to min-width:auto, so any wide child
   (the bundle rail's unwrappable card row) would inflate the whole column
   past the viewport instead of scrolling inside its own overflow box. */
.ps-pdp div.product > .woocommerce-product-gallery,
.ps-pdp div.product > .summary { float: none !important; width: auto !important; min-width: 0; }

/* Image panel — a compact specimen plate: the render is height-capped at a
   believable scale and floats in generous wash, and the whole plate is sticky
   so the product stays in view while the buy column scrolls. (Woo ships the
   gallery at opacity:0 for a flexslider we don't load, so force it visible.) */
/* !important: WooCommerce core loads after us and re-declares position on the
   gallery. Sticky only in two-column mode (>900px) — pinning the image while a
   single column scrolls underneath would be hostile on phones. */
@media (min-width: 901px) {
	.ps-pdp div.product > .woocommerce-product-gallery { position: sticky !important; top: 96px; }
}
.ps-pdp .woocommerce-product-gallery { margin: 0 !important; opacity: 1 !important; }
.ps-pdp .woocommerce-product-gallery__wrapper {
	margin: 0;
	background: var(--ps-pale);
	border-radius: var(--ps-r-lg);
	display: grid;
	/* The plate's TOP edge sits on the title line (sizer), and the render
	   floats dead-center inside it — both axes. */
	place-items: center;
	padding: 1.5rem;
}
.ps-pdp .woocommerce-product-gallery .flex-viewport { overflow: visible; width: 100%; }
.ps-pdp .woocommerce-product-gallery img { width: auto; max-width: 100%; height: auto; max-height: 300px; object-fit: contain; }
.ps-pdp .woocommerce-product-gallery__trigger { display: none !important; }

/* Trust badges under the image (injected via woocommerce_product_thumbnails) */
/* Trust marks — boxed chips OUTSIDE the plate (per the Figma PDP), centered
   under it. They ride inside the sticky gallery column via the product-image
   template override. */
.ps-pd-trust { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem; margin: 0.875rem 0 0; padding: 0; }
.ps-pd-trust li {
	border: 1px solid var(--ps-line);
	color: var(--ps-muted);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 0.4375rem 0.6875rem;
	white-space: nowrap;
}
.ps-trust-abbr { display: none; }

/* Summary (right column) — stack in hook-priority order */
.ps-pdp .summary { margin: 0 !important; position: static; display: flex; flex-direction: column; }
/* Title row: name LEFT, availability badge top-RIGHT on the same visual line.
   Long names wrap under the badge (title flexes, badge never shrinks). */
/* Header block — a 2×2 grid so every edge lines up (Figma): the name and
   IN STOCK share the top line (badge top-aligned to the name's edge); the
   CAS spec line and the price share the second. */
.ps-pd-head {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	grid-template-areas: "title badge" "spec price";
	/* Rows align on CENTERS: IN STOCK rides the name's midline, the price
	   rides the CAS line's midline — one horizontal plane per row. */
	align-items: center;
	column-gap: 0.875rem;
	row-gap: 0.5rem;
}
.ps-pd-head .product_title { grid-area: title; min-width: 0; }
.ps-pd-head .ps-pd-stock { grid-area: badge; margin: 0; justify-self: end; }
.ps-pd-spec { grid-area: spec; margin: 0; align-self: center; font-size: var(--ps-t-sm); color: var(--ps-muted); letter-spacing: -0.01em; }
.ps-pd-price { grid-area: price; margin: 0; align-self: center; justify-self: end; font-size: var(--ps-t-xs); color: var(--ps-muted); white-space: nowrap; }
.ps-pd-price b { font-size: 1.375rem; font-weight: 700; color: var(--ps-navy); letter-spacing: -0.01em; margin-right: 0.25rem; }
.ps-pd-stock {
	flex: 0 0 auto;
	font-size: var(--ps-t-2xs);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	padding: 0.3125rem 0.625rem;
	border-radius: var(--ps-r-xs);
	margin: 0.625rem 0 0; /* optically centers on the title's first line */
	white-space: nowrap;
}
.ps-pd-stock.is-in { color: #1B7F4E; background: #E4F3EA; }
.ps-pd-stock.is-out { color: #9A3B33; background: #F6E7E5; }
.ps-pdp .summary .product_title {
	font-size: var(--ps-t-h1);
	font-weight: 700;
	line-height: 1.05;
	letter-spacing: -0.02em;
	color: var(--ps-navy);
	margin: 0;
	max-width: none;
	display: block;
}
.ps-pd-desc { font-size: 1rem; line-height: 1.5; color: var(--ps-ink); margin: 1.25rem 0 0; }

.ps-pdp .summary > .price {
	position: static;
	margin: 1.5rem 0 0;
	padding: 0;
	font-size: 2rem;
	font-weight: 700;
	line-height: 1;
	color: var(--ps-navy) !important;
}
.ps-pdp .summary > .price .woocommerce-Price-amount { font-weight: 700; color: var(--ps-navy); }
.ps-pdp .summary > .price::after {
	content: " per box";
	font-size: var(--ps-t-base);
	font-weight: 400;
	letter-spacing: 0;
	color: var(--ps-muted);
}

/* Pack-size selector (3 radio cards; ps.js sets the qty input) */
.ps-pack { margin: 1.5rem 0 0; }
.ps-pack-label {
	margin: 0 0 var(--ps-sp-2);
	font-size: var(--ps-t-2xs);
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--ps-soft);
}
/* Ridge-style pack tiles: three side-by-side cards, save pill on the corner,
   ring = selection. The radio stays real (form logic + no-JS) but invisible;
   :has() keeps the ring honest even before JS runs. */
.ps-pack-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ps-sp-2); }
.ps-pack-opt {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.125rem;
	padding: 0.875rem 0.875rem 0.75rem;
	border: 1px solid var(--ps-line);
	background: #fff;
	cursor: pointer;
	transition: border-color var(--ps-dur-1) var(--ps-ease), background var(--ps-dur-1) var(--ps-ease);
}
.ps-pack-opt:hover { border-color: var(--ps-line-2); }
.ps-pack-opt input { position: absolute; opacity: 0; pointer-events: none; margin: 0; }
.ps-pack-opt.is-selected,
.ps-pack-opt:has(input:checked) { border-color: var(--ps-blue); background: var(--ps-pale); box-shadow: inset 0 0 0 1px var(--ps-blue); }
.ps-pack-pill {
	position: absolute;
	top: -1px;
	right: -1px;
	padding: 0.1875rem 0.4375rem;
	background: var(--ps-blue);
	color: #fff;
	font-size: 9px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}
.ps-pack-name { font-size: var(--ps-t-xs); font-weight: 600; color: var(--ps-ink); }
.ps-pack-price { margin-top: 0.125rem; font-size: 1.125rem; font-weight: 700; color: var(--ps-navy); letter-spacing: -0.01em; }
.ps-pack-each { font-size: 10px; color: var(--ps-muted); white-space: nowrap; }
.ps-pack-strips { margin-top: 0.125rem; font-size: 10px; color: var(--ps-soft); }

/* Order-volume meter — the one place the mixable order-level tiers speak on
   the PDP. A supplier's fact line, not a promotion: hairline track, ticks at
   the 5-box mark (50%) and 10-box end, no animation theatrics. */
.ps-ordermeter { margin: var(--ps-caption-gap) 0 0; }
.ps-ordermeter-line { margin: 0 0 0.5rem; font-size: var(--ps-t-xs); color: var(--ps-muted); }
.ps-ordermeter-fact { font-weight: 700; color: var(--ps-navy); }
.ps-ordermeter-next::before { content: " — "; color: var(--ps-muted); font-weight: 400; }
.ps-ordermeter.is-active .ps-ordermeter-next { color: var(--ps-blue-deep); font-weight: 500; }
.ps-ordermeter-bar { position: relative; height: 2px; border-radius: var(--ps-r-pill); background: var(--ps-line); }
.ps-ordermeter-bar i { display: block; height: 100%; max-width: 100%; border-radius: var(--ps-r-pill); background: var(--ps-blue); transition: width var(--ps-dur-2) var(--ps-ease); }
.ps-ordermeter-tick { position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--ps-line-2); }
.ps-ordermeter-tick.is-end { left: auto; right: 0; }

/* ---- "Build your bundle" strip (PDP, below the add-to-cart form) ----
   Eyebrow + the order meter + a one-tap add rail of the other compounds.
   The rail is user-scrolled only (snap + a peeking card as the affordance) —
   no automatic motion this close to the money button. */
.ps-bundle { margin-top: var(--ps-sp-4); margin-bottom: 0; padding: var(--ps-sp-4); border: 1px solid var(--ps-line); background: var(--ps-wash); min-width: 0; max-width: 100%; }
.ps-bundle-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--ps-sp-3); margin: 0 0 var(--ps-sp-2); }
.ps-bundle-head .ps-bundle-eyebrow { margin: 0; color: var(--ps-navy); }
.ps-bundle-flag { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ps-blue-deep); white-space: nowrap; }
.ps-bundle-eyebrow { margin: 0 0 var(--ps-sp-2); font-size: var(--ps-t-2xs); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ps-soft); }
.ps-bundle .ps-ordermeter { margin-top: 0; }
.ps-bundle-rail { display: flex; gap: var(--ps-sp-3); margin-top: var(--ps-sp-3); overflow-x: auto; scroll-snap-type: x proximity; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.ps-bundle-rail::-webkit-scrollbar { display: none; }
.ps-bundle-card { flex: 0 0 108px; scroll-snap-align: start; display: flex; flex-direction: column; }
.ps-bundle-thumb { position: relative; display: block; height: 72px; border-radius: var(--ps-r-sm); background: #fff; border: 1px solid var(--ps-line); overflow: hidden; }
.ps-bundle-thumb img { width: 100%; height: 100%; object-fit: contain; padding: var(--ps-sp-2); box-sizing: border-box; }
.ps-bundle-count { display: none; }
.ps-bundle-name { margin-top: var(--ps-sp-2); font-size: 11px; font-weight: 500; line-height: 1.3; color: var(--ps-ink); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 2.6em; }
.ps-bundle-price { margin-top: 1px; font-size: 10px; color: var(--ps-muted); }
.ps-bundle-add { margin-top: var(--ps-sp-2); display: inline-flex; align-items: center; justify-content: center; height: 30px; border: 1px solid var(--ps-line-2); border-radius: var(--ps-r-xs); background: #fff; color: var(--ps-blue-deep); font-family: inherit; font-size: var(--ps-t-2xs); font-weight: 600; text-decoration: none; cursor: pointer; transition: border-color var(--ps-dur-1) var(--ps-ease), background var(--ps-dur-1) var(--ps-ease); }
.ps-bundle-add:hover { border-color: var(--ps-blue); background: var(--ps-pale); }
.ps-bundle-add:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 1px; }
.ps-bundle-add[hidden] { display: none; }
.ps-bundle-card.is-in-cart .ps-bundle-thumb { box-shadow: inset 0 0 0 1px var(--ps-blue); }
/* Food-app stepper: Add morphs into − n + once the compound is in the order. */
.ps-bundle-step { margin-top: var(--ps-sp-2); display: flex; align-items: stretch; height: 30px; border: 1px solid var(--ps-blue); background: #fff; }
.ps-bundle-step[hidden] { display: none; }
.ps-bundle-step-btn { flex: 0 0 30px; display: inline-flex; align-items: center; justify-content: center; border: 0; background: none; color: var(--ps-blue-deep); font-size: 15px; font-weight: 600; line-height: 1; cursor: pointer; }
.ps-bundle-step-btn:hover { background: var(--ps-pale); }
.ps-bundle-step-btn:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: -2px; }
.ps-bundle-step b { flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; color: var(--ps-navy); }
/* Minus ↔ trashcan: at exactly one box the decrement removes the compound, so
   the glyph says so (ps.js sets .is-qty-1 from the cart map). */
.ps-bstep-trash { display: none; }
.ps-bundle-card.is-qty-1 .ps-bundle-step-btn[data-ps-bstep="-1"] .ps-bstep-minus { display: none; }
.ps-bundle-card.is-qty-1 .ps-bundle-step-btn[data-ps-bstep="-1"] .ps-bstep-trash { display: block; }
/* Rail expand/collapse controls exist for phones only — desktop shows the
   full horizontal rail and never renders them visible. */
.ps-bundle-toggle { display: none; }
.ps-bundle-card.is-busy .ps-bundle-add,
.ps-bundle-card.is-busy .ps-bundle-step { opacity: 0.55; pointer-events: none; }
/* Pack-fixed quantities (5/10 supplies) hide the manual stepper — the pack IS
   the quantity; the button stretches to the full row. */
.ps-pdp form.cart .quantity.is-pack-fixed { display: none !important; } /* beats the anti-Woo inline-flex!important below */

/* Quantity stepper (left) + add-to-cart (right) — one row, form intact */
.ps-pdp form.cart {
	display: grid;
	grid-template-columns: 118px 1fr;
	gap: 0.625rem;
	margin: 0.75rem 0 0 !important;
	align-items: stretch;
	clear: both;
}
/* Pack-fixed state (5/10 preselected): the stepper track is gone, the button
   owns the whole row. */
.ps-pdp form.cart:has(.quantity.is-pack-fixed) { grid-template-columns: 1fr; }
.ps-pdp form.cart .quantity {
	order: 1;
	display: inline-flex !important;
	float: none !important;
	align-items: stretch;
	border: 1px solid var(--ps-line-2);
	border-radius: var(--ps-r-sm);
	overflow: hidden;
	height: 52px;
}
.ps-pdp form.cart .quantity .qty {
	flex: 1 1 auto;
	width: 100%;
	min-width: 0;
	border: 0;
	text-align: center;
	font-family: var(--ps-font);
	font-size: 1rem;
	color: var(--ps-ink);
	appearance: textfield;
	-moz-appearance: textfield;
	background: transparent;
}
.ps-pdp .quantity .qty::-webkit-outer-spin-button,
.ps-pdp .quantity .qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.ps-qty-btn {
	border: 0;
	background: transparent;
	color: var(--ps-navy);
	font-size: 1.25rem;
	line-height: 1;
	width: 2.25rem;
	flex: 0 0 auto;
	cursor: pointer;
	font-family: var(--ps-font);
}
.ps-qty-btn:hover { color: var(--ps-blue); }
.ps-pdp form.cart .single_add_to_cart_button {
	order: 2;
	background: var(--ps-blue);
	color: #fff;
	border: 0;
	border-radius: var(--ps-r-sm);
	font-family: var(--ps-font);
	font-size: var(--ps-t-base);
	font-weight: 500;
	text-transform: none;
	padding: 0 1.5rem;
	height: 52px;
	width: 100%;
	cursor: pointer;
	transition: background var(--ps-dur-1) ease;
}
.ps-pdp form.cart .single_add_to_cart_button:hover { background: var(--ps-blue-deep); }

/* COA assurance line under the cart form */
.ps-pd-coa {
	display: flex;
	align-items: flex-start;
	gap: var(--ps-sp-3);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-md);
	padding: 1rem 1.125rem;
	margin: 1.25rem 0 0;
}
.ps-pd-coa-ico { color: var(--ps-blue); flex: 0 0 auto; margin-top: 1px; line-height: 0; }
.ps-pd-coa-txt { font-size: var(--ps-t-sm); line-height: 1.45; color: var(--ps-muted); margin: 0; flex: 1 1 auto; }
.ps-pd-coa-txt strong { color: var(--ps-ink); font-weight: 700; }
.ps-pd-coa-link {
	flex: 0 0 auto;
	align-self: center;
	color: var(--ps-blue);
	font-size: var(--ps-t-sm);
	font-weight: 500;
	text-decoration: underline;
	text-underline-offset: 3px;
	white-space: nowrap;
}
.ps-pdp .summary .ps-ruo-inline { margin-top: 1rem; }


/* PDP sections — 750px centered column */
.ps-pdp-section { width: min(var(--ps-prose), 100% - 2 * var(--ps-gutter)); margin: var(--ps-section-sm) auto; }
.ps-pdp-section h2 {
	font-size: 1.25rem;
	font-weight: 500;
	letter-spacing: -0.01em;
	color: var(--ps-navy);
	margin: 0 0 0.875rem;
}
.ps-pdp-body p { font-size: 1rem; line-height: 1.45; color: var(--ps-muted); margin: 0 0 0.75rem; }
.ps-pdp-contents { font-size: var(--ps-t-base); color: var(--ps-muted); margin: 0.75rem 0 0; }
.ps-pdp-contents strong { color: var(--ps-ink); font-weight: 500; }

.ps-coa-head { display: flex; align-items: center; justify-content: space-between; gap: var(--ps-sp-4); margin-bottom: 1rem; }
.ps-coa-head h2 { margin: 0; }
.ps-coa-tabs button {
	border: 0;
	background: transparent;
	color: var(--ps-blue);
	font-family: var(--ps-font);
	font-size: var(--ps-t-xs);
	font-weight: 500;
	padding: 0.5rem 0.875rem;
	cursor: pointer;
}
.ps-coa-tabs button[aria-selected="true"] { background: var(--ps-blue); color: #fff; }
.ps-coa-chips { display: flex; gap: var(--ps-sp-3); overflow-x: auto; scrollbar-width: none; padding-bottom: 0.25rem; }
.ps-coa-chips::-webkit-scrollbar { display: none; }
.ps-coa-chip {
	flex: 0 0 auto;
	background: var(--ps-chip);
	color: var(--ps-blue);
	font-size: var(--ps-t-xs);
	font-weight: 500;
	padding: 0.625rem 1.125rem;
	border-radius: var(--ps-r-pill);
	text-decoration: none;
}
.ps-coa-chip[aria-disabled="true"] { pointer-events: none; }
.ps-coa-chip[hidden] { display: none; }

.ps-structure-img { max-height: 280px; max-width: 100%; width: auto; height: auto; display: block; margin: 0 0 1rem; }
.ps-structure-meta { margin: 0; }
.ps-structure-meta div { display: flex; gap: var(--ps-sp-2); margin-bottom: 0.375rem; }
.ps-structure-meta dt { font-size: var(--ps-t-xs); font-weight: 700; color: var(--ps-ink); }
.ps-structure-meta dd { font-size: var(--ps-t-xs); color: var(--ps-muted); margin: 0; }

.ps-key-areas-h { font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-blue); margin: 1.25rem 0 0.75rem; }
.ps-key-areas { list-style: none; margin: 0 0 1.25rem; padding: 0; }
.ps-key-areas li {
	font-size: var(--ps-t-ui);
	color: var(--ps-muted);
	padding-left: 1.125rem;
	position: relative;
	margin-bottom: 0.625rem;
}
.ps-key-areas li::before {
	content: "";
	position: absolute;
	left: 0.25rem;
	top: 0.5em;
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background: var(--ps-soft);
}

.ps-ref-band {
	background: var(--ps-blue);
	padding: 2.5rem var(--ps-gutter);
	margin: 2.5rem calc(50% - 50vw);
	width: 100vw;
}
.ps-ref-inner { max-width: var(--ps-prose); margin: 0 auto; }
.ps-ref-inner h2 { font-size: 1.25rem; font-weight: 500; color: #fff; margin: 0 0 1rem; }
.ps-ref-inner ul { list-style: none; margin: 0; padding: 0; }
.ps-ref-inner li { margin-bottom: 0.625rem; }
.ps-ref-inner a {
	color: #fff;
	font-size: var(--ps-t-base);
	text-decoration: underline;
	text-underline-offset: 3px;
}
.ps-ref-inner a:hover { color: var(--ps-chip); }

.ps-others-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--ps-sp-3); }
.ps-other-tile {
	background: var(--tile, var(--ps-navy));
	aspect-ratio: 172 / 200;
	display: grid;
	place-items: center;
	overflow: hidden;
}
.ps-other-tile img {
	width: 80%;
	height: auto;
	object-fit: contain;
	filter: drop-shadow(0 16px 18px rgba(0, 0, 0, 0.3));
	transition: transform var(--ps-dur-1) ease;
}
.ps-other-tile:hover img { transform: scale(1.05); }

.ps-ruo { background: var(--ps-lilac); padding: 1.5rem; }
.ps-ruo h2 { margin-bottom: 0.5rem; }
.ps-ruo p { font-size: var(--ps-t-ui); line-height: 1.5; color: var(--ps-muted); margin: 0; }

/* ==========================================================================
   Figma rounding — 16px on cards, tiles & field containers.
   (Client review: match the Figma's rounded corners. Buttons stay square per
   Figma; pills/chips stay fully round.)
   ========================================================================== */
.ps-wash-card,
.ps-notfound-tile,
.ps-other-tile,
.ps-cta-help,
.ps-cta-shop,
.ps-shop-search,
.ps-post-card,
.ps-ruo,
ul.products[class*="columns-"] li.product {
	border-radius: var(--ps-r-lg);
}

/* Woo notices, kept quiet and on-brand */
.woocommerce-notices-wrapper { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto; }
.woocommerce-message, .woocommerce-info, .woocommerce-error {
	border-top: 2px solid var(--ps-blue);
	background: var(--ps-wash);
	color: var(--ps-ink);
	font-size: var(--ps-t-ui);
}
.woocommerce-message a.button, .woocommerce-info a.button { background: var(--ps-blue); color: #fff; border-radius: 0; }

/* Shared disclosure entrance — used by BOTH the PDP bundle and the homepage
   product grid. Declared at top level on purpose: nested inside a media block
   it silently fails to resolve for rules in a different one. */
@keyframes ps-tile-in {
	from { opacity: 0; transform: translateY(9px); }
	to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   Prose pages (about/contact/blog fallbacks)
   ========================================================================== */
.ps-prose { padding-top: var(--ps-lede); padding-bottom: var(--ps-section); }
.ps-prose .ps-page-title { margin-bottom: var(--ps-sp-6); }
.ps-prose p { color: var(--ps-muted); line-height: 1.55; }
.ps-prose h2, .ps-prose h3 { color: var(--ps-navy); }

/* ==========================================================================
   Footer — Figma 12544:585 (desktop 1440×324) / 12544:1134 (mobile 390×504),
   built to the frame's exact numbers: 40px band padding, 114×40 logo, 24px
   logo→label, 343px newsletter row on #EFF4FA with a flush blue Subscribe,
   About/Resources 138px columns (14px, white/70 links), 60px to the legal bar
   (border white/11, 8px inset, 12px type, white links).
   ========================================================================== */
.ps-footer {
	background: var(--ps-dark);
	color: #fff;
	padding: 2.5rem var(--ps-gutter);
	margin-top: 0; /* the preceding section's own rhythm provides the gap (Figma butts them) */
}
.ps-footer-grid,
.ps-footer-legal { max-width: var(--ps-col); margin-left: auto; margin-right: auto; }
.ps-footer-grid { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ps-sp-9); }
.ps-footer-logo { width: 114px; height: auto; display: block; margin-bottom: var(--ps-sp-6); }
.ps-newsletter { width: 343px; max-width: 100%; }
.ps-newsletter-label { display: block; font-size: var(--ps-t-ui); letter-spacing: -0.01em; margin-bottom: var(--ps-sp-4); }
.ps-newsletter-row {
	display: flex;
	align-items: center;
	background: #EFF4FA; /* Figma field tint (deliberately cooler than --ps-pale) */
}
.ps-newsletter input {
	flex: 1 1 auto;
	min-width: 0;
	height: 40px;
	border: 0;
	padding: 0 var(--ps-sp-4);
	font-family: var(--ps-font);
	font-size: var(--ps-t-ui);
	color: var(--ps-ink);
	background: transparent;
}
.ps-newsletter input::placeholder { color: var(--ps-soft); }
.ps-newsletter .ps-btn { flex: 0 0 auto; height: 40px; padding: 0.625rem 1.25rem; font-size: var(--ps-t-ui); font-weight: 700; }
.ps-newsletter-note { font-size: var(--ps-t-2xs); color: rgba(255, 255, 255, 0.6); margin: 0.375rem 0 0; }
.ps-newsletter-note.ps-newsletter-done { color: var(--ps-chip); }
.ps-footer-cols { display: flex; gap: var(--ps-sp-5); }
.ps-footer-col { width: 138px; }
.ps-footer-head { font-size: var(--ps-t-ui); font-weight: 500; letter-spacing: -0.01em; color: #fff; margin: 0 0 var(--ps-sp-3); }
.ps-footer-col a {
	display: block;
	font-size: var(--ps-t-ui);
	line-height: 1.45;
	color: rgba(255, 255, 255, 0.7);
	text-decoration: none;
	margin-bottom: var(--ps-sp-2);
	transition: color var(--ps-dur-1) ease;
}
.ps-footer-col a:last-child { margin-bottom: 0; }
.ps-footer-col a:hover { color: #fff; }
.ps-footer-legal {
	margin-top: 3.75rem; /* Figma: 60px block gap */
	padding-top: var(--ps-sp-2);
	border-top: 1px solid rgba(255, 255, 255, 0.11);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-sp-6);
	flex-wrap: wrap;
}
.ps-footer-legal p { margin: 0; font-size: var(--ps-t-xs); color: rgba(255, 255, 255, 0.7); }
.ps-footer-legal-links { display: flex; gap: var(--ps-sp-6); }
.ps-footer-legal a { color: #fff; text-decoration: none; transition: color var(--ps-dur-1) ease; }
.ps-footer-legal a:hover { color: var(--ps-accent-sky); }

/* ==========================================================================
   Responsive
   ========================================================================== */
@media (max-width: 1023px) {
	.ps-nav, .ps-header-cta { display: none; }
	.ps-menu-trigger { display: inline-flex; }
	.ps-logo { position: absolute; left: 50%; transform: translateX(-50%); }
	.ps-logo img.ps-logo-full { display: none; }
	.ps-logo img.ps-logo-mark { display: block; }
	/* Phones KEEP the total — showing the basket's value is the whole reason this
	   control exists, and hiding it left mobile with a bare icon. Tighten instead. */
	/* Phones: icon + count only. The running total belongs to the wider header;
	   on a 390px bar it crowds the logo and reads as clutter. */
	/* Phones: icon + quantity only — the amount crowds a 390px bar. The blue
	   loaded state is kept, so the cart still reads as filled at a glance. */
	.ps-cart { height: 28px; gap: 0.375rem; }
	.ps-cart.has-items { padding: 0 0.375rem 0 0.5rem; }
	.ps-cart-total { display: none; }
	.ps-header { padding-top: 0.625rem; padding-bottom: 0.625rem; }
}

@media (max-width: 900px) {
	.ps-split { grid-template-columns: 1fr; gap: var(--ps-sp-6); }
	.ps-split-flip .ps-split-media { order: 2; }
	.ps-split-media img { height: 260px; }
	.ps-considerations-grid { grid-template-columns: 1fr 1fr; gap: var(--ps-sp-6); }
	.ps-cta-band { grid-template-columns: 1fr; grid-auto-rows: auto; }
	/* CTA tiles: drop the fixed 180px height so the chat bubbles / box image
	   aren't clipped on mobile, and let the headings use full width. */
	.ps-cta-help, .ps-cta-shop { height: auto; }
	.ps-cta-help { justify-content: flex-start; }
	.ps-cta-help h2, .ps-cta-shop h2 { max-width: none; }
	.ps-why-cards, .ps-support-cards { grid-template-columns: 1fr; }
	.ps-faq-grid { grid-template-columns: 1fr; }
	.ps-footer-grid { flex-direction: column; align-items: stretch; gap: 3.75rem; } /* Figma mobile: 60px stack gap */
	.ps-pdp div.product { grid-template-columns: 1fr; gap: var(--ps-sp-6); }
	.ps-pdp .woocommerce-product-gallery { max-width: none; margin: 0 !important; }
	.ps-pdp .woocommerce-product-gallery__wrapper { aspect-ratio: 10 / 7; padding: 1.25rem; }
}

@media (max-width: 740px) {
	/* Same-Day Shipping: the truck art is now tightly cropped; keep it compact
	   so it doesn't leave big gaps above/below. */
	.ps-shipping .ps-media-plain img { max-height: 150px; }
	/* Figma keeps the catalog grid 2-up on mobile (390), not 1-up. */
	.ps-shop-grid ul.products[class*="columns-"] li.product img { height: 132px; }
	.ps-shop-grid li.product { min-height: 220px; }
	.ps-others-grid { grid-template-columns: 1fr 1fr; }
	.ps-marquee li.product { width: 200px !important; }
	.ps-chat { position: static; transform: none; width: auto; max-width: 20rem; margin-top: var(--ps-sp-4); }
	/* Released HERE, at the breakpoint where .ps-chat leaves the flow — there is
	   nothing left to dodge, and keeping the constraint would only narrow the
	   text for no reason. */
	.ps-cta-reach { max-width: none; }
	/* CTA tiles, phone composition: tighter padding; the box render scales down
	   and pulls UP beside the Browse button (negative top margin) so the navy
	   tile carries no dead zone — copy top-left, render nested bottom-right,
	   still bleeding off the tile's corner. Keeps both tiles near-equal height. */
	.ps-cta-help { padding: var(--ps-sp-6); }
	.ps-cta-shop { flex-direction: column; align-items: stretch; padding: var(--ps-sp-6) var(--ps-sp-6) 0; }
	.ps-cta-shop .ps-cta-shop-copy { padding-bottom: 0; }
	/* Back into the flow. The desktop rule lifts this image OUT of flow so its
	   200px height cannot inflate the two-column band's row; here the card is a
	   single stacked column and this layout depends on the image taking part
	   (align-self plus the negative top margin that pulls it under the copy). */
	.ps-cta-shop img { position: static; align-self: flex-end; height: 160px; margin-top: -4rem; margin-bottom: -1rem; }
	.ps-footer { padding-top: 1.875rem; padding-bottom: 1.875rem; } /* Figma mobile: 30px band */
	.ps-newsletter { width: 100%; } /* Figma mobile: row spans the full 350px content width */
	.ps-footer-cols { gap: var(--ps-sp-5); width: 100%; }
	.ps-footer-col { width: auto; flex: 1 1 0; }
	.ps-newsletter-row { width: 100%; }
	.ps-newsletter input { flex: 1; width: auto; min-width: 0; }
	.ps-footer-legal { flex-direction: column; align-items: flex-start; gap: var(--ps-sp-3); }
	.ps-coa-head { flex-wrap: wrap; }
	/* Figma mobile PDP (12544:2323): Add-To-Cart + qty stay on one row (was
	   stacked full-width), price stays top-right of the title, and the COA lot
	   chips wrap 3-up instead of scrolling off the right edge. */
	.ps-pdp form.cart { grid-template-columns: 1fr 118px; }
	.ps-coa-chips { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--ps-sp-2); overflow: visible; padding-bottom: 0; }
	.ps-coa-chip { text-align: center; padding: 0.625rem 0.5rem; }
}

@media (max-width: 560px) {
	/* Why-us cards on narrow phones: slightly smaller headline + pull the COA
	   sheet fully right so it stops overlapping the "Batch-Level Verification"
	   text (client feedback). */
	.ps-why-cards .ps-wash-card h3 { font-size: 1.125rem; }
	.ps-why-cards .ps-icon-coa > img { width: 132px; right: -14px; }
}

@media (prefers-reduced-motion: reduce) {
	.ps-marquee-track, .ps-marquee.is-ready .ps-marquee-track { animation: none; }
	.ps-marquee { overflow-x: auto; }
	.ps-other-tile img, .ps-btn, .ps-burger i { transition: none; }
}

/* ==========================================================================
   About + Contact pages (page-about.php / page-contact.php)
   Contact: Figma 12513:630. Shared page-head band + inquiry block below.
   About: rebuilt — see the "ABOUT (v2 redesign)" block further down.
   Reuses .ps-section, .ps-split, .ps-cta-band, .ps-btn + the tokens.
   ========================================================================== */

/* Shared type helpers + larger button (Figma body buttons are Bold 16 / h48) */
.ps-h4 { font-size: 1rem; font-weight: 500; line-height: 1.25; letter-spacing: -0.01em; color: var(--ps-ink); margin: 0 0 0.75rem; }
.ps-lead { font-size: 1rem; font-weight: 400; line-height: 1.35; letter-spacing: -0.01em; color: var(--ps-soft); margin: 0 0 1.5rem; }
.ps-btn-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ps-sp-4); }
.ps-btn-lg { font-size: 1rem; font-weight: 700; line-height: 1; padding: 1rem 1.875rem; }
.ps-btn-outline { background: transparent; border: 1px solid var(--ps-blue); color: var(--ps-ink); }
.ps-btn-outline:hover { background: var(--ps-wash); color: var(--ps-ink); }
.ps-btn-white { background: #fff; color: var(--ps-navy); }
.ps-btn-white:hover { background: var(--ps-wash); color: var(--ps-navy); }
.ps-cta-contact { align-self: flex-start; }

/* --- Interior page-head band (breadcrumb + blue title + DNA) --- */
.ps-page-head { position: relative; background: var(--ps-wash); overflow: hidden; }
.ps-page-head-inner { position: relative; z-index: 1; width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto; padding: var(--ps-lede) 0; }
.ps-breadcrumb { display: flex; align-items: center; gap: var(--ps-sp-2); margin: 0 0 0.5rem; }
.ps-breadcrumb a { font-size: var(--ps-t-xs); color: var(--ps-muted); text-decoration: none; }
.ps-breadcrumb a:hover { color: var(--ps-blue); }
.ps-breadcrumb span { font-size: var(--ps-t-xs); font-weight: 500; color: var(--ps-ink); }
.ps-crumb-sep { color: var(--ps-muted); flex: 0 0 auto; }
.ps-page-head-title { font-size: var(--ps-t-h2); font-weight: 500; line-height: 1.167; letter-spacing: -0.01em; color: var(--ps-blue); margin: 0; }
.ps-page-head-dna { position: absolute; top: -46px; right: 5%; width: 460px; height: auto; transform: rotate(23deg); opacity: 0.92; pointer-events: none; z-index: 0; }

/* ==========================================================================
   ABOUT (v2 redesign) — Figma HyPStzuochxvctFWZiAGrc / 1100:6361
   Desktop artboard 1445:7684 (1440) · mobile 1445:7285 (390). Rebuilt against
   the client Figma: the hero is now a CONTAINED rounded band (was full-bleed),
   the Mission card shows on DESKTOP over the microscope, the feature fine-print
   is centred, and the doc panel is rounded. The v1 "research inquiry" split is
   gone from About (its shared inquiry/contact rules remain below for Contact).
   Reuses .ps-section / .ps-split / .ps-btn / .ps-cta-band + the tokens.
   ========================================================================== */

/* --- Hero: contained tinted band (wash → bubble photo), copy + product trio.
       The band is the 1200px content track with 16px rounding; the product
       column bleeds to the right/bottom edges and is clipped by overflow. --- */
.ps-about-hero {
	position: relative;
	overflow: hidden;
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 0 auto var(--ps-section);
	border-radius: var(--ps-r-lg);
	background:
		linear-gradient(90deg, var(--ps-wash) 0%, rgba(248, 251, 252, 0.94) 32%, rgba(248, 251, 252, 0) 60%),
		url('../img/about/hero-bg.png') center right / cover no-repeat,
		var(--ps-wash);
}
.ps-about-hero-inner {
	position: relative;
	z-index: 1;
	/* pad the copy side only; the product column reaches the band's right edge */
	padding: 2.25rem 0 2.25rem 2.5rem;
	min-height: 354px;
	display: grid;
	grid-template-columns: 480px 1fr;
	gap: var(--ps-sp-6);
	align-items: center;
}
.ps-about-hero-copy { max-width: 480px; }
.ps-about-hero-copy .ps-h2 { margin-bottom: 0.75rem; }
.ps-about-hero-copy .ps-h4 { margin-bottom: 0.875rem; }
.ps-ruo-inline { display: flex; align-items: flex-start; gap: var(--ps-sp-2); font-size: var(--ps-t-xs); font-style: italic; line-height: 1.3; color: var(--ps-soft); margin: 1.25rem 0 0; }
.ps-ruo-icon { color: #E0483B; flex: 0 0 auto; margin-top: 1px; }
.ps-lbl-m { display: none; }

.ps-hero-boxes { position: relative; align-self: stretch; min-height: 320px; }
.ps-hero-box { position: absolute; height: auto; object-fit: contain; filter: drop-shadow(0 22px 32px rgba(11, 25, 40, 0.2)); }
.ps-hero-box-c { width: 300px; left: 28%; top: -4%; z-index: 3; }
.ps-hero-box-l { width: 244px; left: -6%; top: 16%; z-index: 2; }
.ps-hero-box-r { width: 250px; right: -4%; top: 10%; z-index: 1; }

/* --- Values: microscope photo (narrower column, ~40/60 per Figma) + mission
       overlay on desktop + 3 value columns --- */
.ps-values { grid-template-columns: minmax(0, 480px) 1fr; align-items: center; }
.ps-values-media { position: relative; }
.ps-values-media img { height: 410px; }
.ps-mission-card {           /* Figma 1445:7770 — bottom-right, overhangs the photo */
	position: absolute;
	right: -10px;
	bottom: -26px;
	width: min(268px, 88%);
	background: #fff;
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-lg);
	padding: 1rem 1.125rem;
	text-align: left;
	font-size: var(--ps-t-base);
	font-weight: 500;
	line-height: 1.32;
	color: var(--ps-ink);
	box-shadow: 0 18px 40px rgba(11, 25, 40, 0.14);
}
.ps-mission-label { display: block; color: var(--ps-blue); margin-bottom: 0.375rem; }
.ps-values-copy .ps-h2 { margin-bottom: 0.75rem; }
.ps-values-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--ps-sp-5); margin-top: var(--ps-flow); }
.ps-value-icon { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: var(--ps-r-sm); background: var(--ps-wash); color: var(--ps-blue); margin-bottom: 0.75rem; }
.ps-value-title { font-size: 1rem; font-weight: 500; color: var(--ps-ink); margin: 0 0 0.375rem; }
.ps-value-desc { font-size: var(--ps-t-ui); line-height: 1.35; color: var(--ps-muted); margin: 0; }

/* --- Inquiry block (shared: About split + Contact solo) --- */
.ps-inquiry-copy .ps-h2 { margin-bottom: 0.75rem; }
.ps-inquiry-lead { font-size: 1rem; font-weight: 500; line-height: 1.25; color: var(--ps-ink); margin: 0 0 1.5rem; max-width: 34rem; }
.ps-inquiry-extra { display: none; font-size: var(--ps-t-ui); line-height: 1.4; color: var(--ps-soft); margin: 0 0 1.5rem; }
.ps-contact-lines { display: flex; flex-direction: column; gap: var(--ps-sp-5); margin: 0 0 1.25rem; }
.ps-contact-line { display: flex; align-items: center; gap: var(--ps-sp-3); margin: 0; }
.ps-contact-chip { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; background: var(--ps-wash); color: var(--ps-blue); flex: 0 0 auto; }
.ps-contact-text { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
.ps-contact-label { font-size: var(--ps-t-ui); color: var(--ps-muted); }
.ps-contact-value { font-size: 1rem; font-weight: 500; color: var(--ps-ink); text-decoration: none; }
.ps-contact-value:hover { color: var(--ps-blue); }
.ps-contact-phone { font-weight: 700; }
.ps-inquiry-note { font-size: var(--ps-t-xs); font-style: italic; line-height: 1.35; color: var(--ps-muted); margin: 0 0 1.5rem; }
.ps-inquiry-copy .ps-btn { margin-top: 0; }
.ps-inquiry-solo { padding-top: 0.5rem; padding-bottom: 1rem; }
.ps-inquiry-solo .ps-inquiry-note { margin-bottom: 0; }
/* Contact is a short page — don't let the global .ps-main min-height stretch it
   and push the footer down into dead space (Figma keeps the footer close). */
.ps-main:has(.ps-inquiry-solo) { min-height: 0; }

/* --- Feature cards: centered heading + 4 illustrated cards --- */
.ps-feature-head { text-align: center; max-width: 44rem; margin: 0 auto var(--ps-flow); }
.ps-feature-head .ps-h2 { margin-bottom: var(--ps-flow-lockup); }
.ps-feature-head .ps-h4 { margin: 0; }
.ps-feature-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--ps-sp-5); }
.ps-feature-card { position: relative; border: 1px solid var(--ps-line); border-radius: var(--ps-r-lg); padding: 0.875rem; min-height: 106px; overflow: hidden; }
.ps-feature-copy { position: relative; z-index: 1; max-width: 68%; }
.ps-feature-title { font-size: 1rem; font-weight: 500; line-height: 1.2; color: var(--ps-ink); margin: 0 0 0.375rem; }
.ps-feature-desc { font-size: var(--ps-t-sm); line-height: 1.35; color: var(--ps-muted); margin: 0; }
.ps-feature-card > img { position: absolute; right: -8px; bottom: -8px; width: auto; height: 96px; object-fit: contain; pointer-events: none; }
.ps-feature-fine { font-size: var(--ps-t-xs); line-height: 1.4; color: var(--ps-muted); max-width: 40rem; margin: var(--ps-caption-gap) auto 0; text-align: center; }

/* --- Quality + documentation table --- */
.ps-quality { align-items: start; }
.ps-quality-copy .ps-h2 { margin-bottom: var(--ps-flow-tight); }
.ps-quality-copy .ps-h4 { margin-bottom: 0.75rem; }
.ps-quality-list { list-style: none; margin: 0 0 var(--ps-sp-6); padding: 0; display: flex; flex-direction: column; gap: var(--ps-sp-5); }
.ps-quality-list li { display: flex; gap: var(--ps-sp-3); align-items: flex-start; }
.ps-quality-icon { color: var(--ps-blue); flex: 0 0 auto; margin-top: 2px; }
.ps-quality-list h4 { font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-ink); margin: 0 0 0.25rem; }
.ps-quality-list p { font-size: var(--ps-t-ui); line-height: 1.35; color: var(--ps-muted); margin: 0; }
.ps-doc-table { position: relative; background: var(--ps-wash); border: 1px solid var(--ps-line); border-radius: var(--ps-r-lg); padding: 1.875rem; }
.ps-doc-title { font-size: var(--ps-t-h2); font-weight: 500; line-height: 1.167; letter-spacing: -0.01em; color: var(--ps-blue); margin: 0 0 1.25rem; }
.ps-doc-rows { margin: 0; }
.ps-doc-rows > div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--ps-sp-4); padding-bottom: 0.5625rem; margin-bottom: 1rem; border-bottom: 1px solid var(--ps-line); }
.ps-doc-rows > div:last-child { margin-bottom: 0; }
.ps-doc-rows dt { font-size: var(--ps-t-ui); color: var(--ps-soft); margin: 0; }
.ps-doc-rows dd { font-size: var(--ps-t-ui); color: var(--ps-ink); text-align: right; margin: 0; flex: 0 0 auto; }
.ps-doc-head dt, .ps-doc-head dd { font-weight: 500; color: var(--ps-ink); }
.ps-doc-note { background: #fff; border: 1px solid var(--ps-line); border-radius: var(--ps-r-sm); padding: 0.75rem 0.875rem; font-size: var(--ps-t-xs); font-style: italic; line-height: 1.4; color: var(--ps-muted); margin: var(--ps-caption-gap) 0 0; }

/* --- Responsible research (split-flip) --- */
.ps-responsible-media img { height: 450px; }

/* Page ambient washes — faint token-derived radial glows behind the sections
   (the artboard's soft blue atmosphere). Overrides the Home-tuned base
   .ps-main::before so the pools sit near the hero/values + quality + responsible. */
.ps-about.ps-main::before {
	background:
		radial-gradient(42rem 30rem at 92% 5%, rgba(0, 118, 184, 0.06), transparent 68%),
		radial-gradient(40rem 30rem at -6% 30%, rgba(0, 118, 184, 0.05), transparent 70%),
		radial-gradient(30rem 26rem at 96% 60%, rgba(0, 118, 184, 0.045), transparent 70%);
}

/* Contact anchor — the CTA band carries id="contact" (nav /about/#contact). */
/* Anchor stop = the real sticky header height, measured into --ps-anchor-offset
   by ps.js, plus a breath. The old fixed 5.5rem ignored the WordPress admin bar
   (+32/46px), so a logged-in editor landed with the section under the header. */
:target,
#contact { scroll-margin-top: calc(var(--ps-anchor-offset, 5.5rem) + 1rem); }

/* --- About responsive (shared page-head + Contact rules kept above) --- */
@media (max-width: 1023px) {
	.ps-page-head-dna { right: 2%; width: 380px; top: -30px; }
}
@media (max-width: 900px) {
	/* Hero band stacks: copy over a centred product row. Uniform padding + a
	   near-opaque vertical wash so the copy stays legible over the bubble photo. */
	.ps-about-hero {
		background:
			linear-gradient(180deg, rgba(248, 251, 252, 0.96) 0%, rgba(248, 251, 252, 0.9) 42%, rgba(248, 251, 252, 0.74) 100%),
			url('../img/about/hero-bg.png') center / cover no-repeat,
			var(--ps-wash);
	}
	.ps-about-hero-inner { grid-template-columns: 1fr; gap: var(--ps-sp-6); min-height: 0; padding: 1.75rem 1.5rem; }
	.ps-hero-boxes { min-height: 0; align-self: auto; display: flex; align-items: center; justify-content: center; padding: 0.5rem 0 0; }
	.ps-hero-box { position: static; height: auto; margin: 0; }
	.ps-hero-box-l { width: 33%; max-width: 158px; margin-right: -6%; z-index: 1; }
	.ps-hero-box-c { width: 38%; max-width: 182px; z-index: 3; }
	.ps-hero-box-r { width: 33%; max-width: 158px; margin-left: -6%; z-index: 2; }
	.ps-values { grid-template-columns: 1fr; }
	.ps-mission-card { right: 0.75rem; bottom: -18px; width: min(280px, 82%); }
	.ps-feature-cards { grid-template-columns: 1fr 1fr; }
	.ps-feature-fine { max-width: none; margin: var(--ps-caption-gap) 0 0; text-align: left; }
	.ps-values-media img, .ps-responsible-media img { height: 300px; }
}
@media (max-width: 740px) {
	.ps-page-head-dna { display: none; }
	.ps-lbl-d { display: none; }
	.ps-lbl-m { display: inline; }
	.ps-btn-row { flex-direction: column; align-items: stretch; }
	.ps-btn-row .ps-btn { width: 100%; }
	.ps-values-grid { grid-template-columns: 1fr; gap: var(--ps-sp-4); }
	.ps-feature-cards { grid-template-columns: 1fr; }
	.ps-values-media img, .ps-responsible-media img { height: 260px; }
}

/* ==========================================================================
   Blog / Insights (home.php, single.php, archive.php, post-card)
   Figma 12550:73. Non-token Tailwind grays mapped back to brand tokens;
   Manrope normalized to Aeonik. Rounded filter pills are the one deliberate
   rounded control (like the PDP pills); everything else stays square.
   ========================================================================== */

/* --- Featured article --- */
.ps-blog-featured { display: grid; grid-template-columns: 1fr 1fr; gap: 2.25rem; align-items: stretch; }
.ps-featured-media { position: relative; display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--ps-wash); box-shadow: 0 0 0 1px rgba(227, 232, 239, 0.5), 0 25px 50px -12px rgba(11, 25, 40, 0.06); }
.ps-featured-media img { width: 100%; height: 100%; object-fit: cover; }
.ps-featured-badge { position: absolute; top: 1.5rem; left: 1.5rem; display: inline-flex; align-items: center; gap: var(--ps-sp-2); padding: 0.4375rem 0.5625rem; background: rgba(255, 255, 255, 0.14); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); border: 1px solid rgba(255, 255, 255, 0.25); color: #fff; font-size: var(--ps-t-xs); font-weight: 500; border-radius: var(--ps-r-xs); box-shadow: 0 6px 16px rgba(11, 25, 40, 0.18); }
.ps-featured-dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(255, 255, 255, 0.75); flex: 0 0 auto; }
.ps-featured-body { display: flex; flex-direction: column; justify-content: space-between; gap: var(--ps-sp-6); }
.ps-featured-meta { display: flex; align-items: center; gap: var(--ps-sp-2); font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-soft); margin: 0 0 1.5rem; }
.ps-meta-dot { width: 4px; height: 4px; border-radius: 50%; background: var(--ps-line-2); flex: 0 0 auto; }
.ps-featured-title { font-size: 3rem; font-weight: 500; line-height: 1.125; letter-spacing: -0.01em; color: var(--ps-ink); margin: 0 0 1.5rem; }
.ps-featured-title a { color: inherit; text-decoration: none; }
.ps-featured-title a:hover { color: var(--ps-blue); }
.ps-featured-excerpt { font-size: 1.125rem; line-height: 1.5; color: var(--ps-muted); margin: 0; }
.ps-featured-link { display: inline-flex; align-items: center; gap: 0.375rem; font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-blue); text-decoration: none; }
.ps-featured-link:hover { color: var(--ps-blue-deep); }

/* --- Intro band --- */
.ps-blog-intro { display: flex; align-items: center; justify-content: space-between; gap: 2.5rem; padding-bottom: var(--ps-flow); border-bottom: 1px solid var(--ps-line); margin-bottom: var(--ps-flow); }
.ps-blog-intro-copy { flex: 1; min-width: 0; }
.ps-blog-intro .ps-h2 { margin-bottom: var(--ps-flow-lockup); }
.ps-blog-intro-sub { font-size: 1rem; font-weight: 500; line-height: 1.25; color: var(--ps-ink); margin: 0; }
.ps-blog-intro-img { width: 177px; height: 146px; object-fit: contain; flex: 0 0 auto; }

/* --- "Latest Research" header + category filter pills --- */
.ps-blog-grid-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--ps-sp-6); flex-wrap: wrap; padding-bottom: var(--ps-sp-6); border-bottom: 1px solid var(--ps-line); margin-bottom: var(--ps-flow); }
.ps-blog-grid-title { font-size: var(--ps-t-h2); font-weight: 500; line-height: 1.333; letter-spacing: -0.01em; color: var(--ps-navy); margin: 0 0 0.25rem; }
.ps-blog-grid-sub { font-size: var(--ps-t-ui); color: var(--ps-muted); margin: 0; }
.ps-blog-filters { display: flex; gap: var(--ps-sp-2); flex-wrap: wrap; }
.ps-filter-pill { font-size: var(--ps-t-xs); font-weight: 500; color: var(--ps-muted); padding: 0.5rem 1rem; border-radius: var(--ps-r-pill); text-decoration: none; white-space: nowrap; transition: background var(--ps-dur-1) ease, color var(--ps-dur-1) ease; }
.ps-filter-pill:hover { color: var(--ps-ink); }
.ps-filter-pill.is-active { background: var(--ps-paper); color: var(--ps-navy); box-shadow: 0 1px 2px rgba(11, 25, 40, 0.08), inset 0 0 0 1px var(--ps-line); }

/* --- Post grid + card --- */
.ps-blog-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--ps-sp-5); }
.ps-post-card { display: flex; flex-direction: column; }
.ps-post-media { display: block; aspect-ratio: 3 / 2; background: var(--ps-wash); overflow: hidden; margin-bottom: 1.5rem; }
.ps-post-media img { width: 100%; height: 100%; object-fit: cover; }
.ps-post-date { font-size: var(--ps-t-xs); font-weight: 500; letter-spacing: -0.01em; color: var(--ps-soft); margin: 0 0 1rem; }
.ps-post-text { margin-bottom: 1rem; }
.ps-post-card-title { font-size: 1.25rem; font-weight: 500; line-height: 1.2; letter-spacing: -0.01em; color: var(--ps-ink); margin: 0 0 0.75rem; }
.ps-post-card-title a { color: inherit; text-decoration: none; }
.ps-post-card-title a:hover { color: var(--ps-blue); }
.ps-post-card-excerpt { font-size: var(--ps-t-ui); line-height: 1.35; color: var(--ps-muted); margin: 0; }
.ps-post-author { display: flex; align-items: center; gap: var(--ps-sp-2); margin: auto 0 0; padding-top: 0.25rem; }
.ps-avatar { width: 24px; height: 24px; border-radius: 0; object-fit: cover; filter: grayscale(1); flex: 0 0 auto; }
.ps-byline-name { font-size: var(--ps-t-xs); font-weight: 500; color: var(--ps-navy); }
.ps-blog-empty { font-size: 1rem; color: var(--ps-muted); }

/* --- Pagination (custom nav + the_posts_pagination .nav-links) --- */
.ps-pagination, .ps-pagination .nav-links { display: flex; justify-content: center; align-items: center; gap: var(--ps-sp-2); flex-wrap: wrap; margin-top: var(--ps-section-sm); }
.ps-pagination .nav-links { margin-top: 0; }
.ps-pagination .page-numbers { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 40px; padding: 0 0.5rem; font-size: 1rem; color: var(--ps-muted); text-decoration: none; border: 1px solid transparent; }
.ps-pagination a.page-numbers { border-color: var(--ps-line); }
.ps-pagination a.page-numbers:hover { border-color: var(--ps-blue); color: var(--ps-blue); }
.ps-pagination .page-numbers.current { background: var(--ps-blue); color: #fff; font-weight: 500; border-color: var(--ps-blue); }
.ps-pagination .page-numbers.dots { border: 0; color: var(--ps-soft); }
.ps-pagination .prev, .ps-pagination .next { color: var(--ps-ink); }

/* --- Article template (blog single + COA) — Figma 1262:3332 / 1266:3710 --- */
.ps-article { padding-bottom: 0; }
/* Full-bleed featured image (blog only; COA omits it) */
.ps-article-hero { margin: 0; width: 100%; height: clamp(180px, 18vw, 300px); overflow: hidden; background: var(--ps-wash); }
.ps-article-hero img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* 1200 content column */
.ps-article-inner { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto; padding: var(--ps-sp-6) 0 var(--ps-section); }
/* Legal has no hero between the band and the body, so the band's --ps-lede IS
   the gap — the extra top padding here made it 64px against About's 40px. */
.ps-legal .ps-article-inner { padding-top: 0; }
/* Header: title + subtitle left, date · category right */
.ps-article-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 2.5rem; margin-bottom: var(--ps-section); }
.ps-article-head-main { max-width: 52ch; }
.ps-article-title { font-size: var(--ps-t-h2); font-weight: 500; line-height: 1.25; letter-spacing: -0.01em; color: var(--ps-ink); margin: 0; }
.ps-article-sub { font-size: var(--ps-t-base); line-height: 1.5; color: var(--ps-muted); margin: 0.625rem 0 0; }
.ps-article-meta { flex-shrink: 0; display: flex; align-items: center; gap: var(--ps-sp-2); font-size: var(--ps-t-sm); font-weight: 500; color: var(--ps-soft); margin: 0.375rem 0 0; white-space: nowrap; }
.ps-meta-dot { width: 3px; height: 3px; border-radius: 50%; background: currentColor; }
/* Lead intro (COA, which has no article-header title/meta) */
.ps-article-intro { max-width: 60ch; font-size: 1rem; line-height: 1.6; color: var(--ps-muted); margin: 0 0 2.25rem; }
/* Two-column: sticky TOC + prose */
.ps-article-body { display: grid; grid-template-columns: 228px minmax(0, 1fr); gap: 2.25rem; align-items: start; }
.ps-toc { position: sticky; top: 96px; }
.ps-toc-title { font-size: var(--ps-t-sm); font-weight: 500; color: var(--ps-blue); margin: 0 0 0.875rem; }
.ps-toc-list, .ps-toc-sub { list-style: none; margin: 0; padding: 0; }
.ps-toc-h2 > a { display: block; font-size: var(--ps-t-sm); line-height: 1.35; color: var(--ps-ink); text-decoration: none; padding: 0.3125rem 0 0.3125rem 0.75rem; border-left: 2px solid transparent; }
.ps-toc-h2 > a:hover { color: var(--ps-blue); }
.ps-toc-h2 > a.is-active { color: var(--ps-blue); border-left-color: var(--ps-blue); font-weight: 500; }
.ps-toc-sub { margin: 0.125rem 0 0.25rem; }
.ps-toc-h3 > a { display: block; font-size: var(--ps-t-xs); line-height: 1.3; color: var(--ps-soft); text-decoration: none; padding: 0.25rem 0 0.25rem 1.5rem; }
.ps-toc-h3 > a:hover { color: var(--ps-blue); }
/* Prose body */
.ps-article-prose { padding: 0; }
.ps-article-prose :is(h2, h3) { scroll-margin-top: calc(var(--ps-anchor-offset, 5.5rem) + 1rem); }
.ps-article-prose p { font-size: var(--ps-t-base); line-height: 1.7; color: var(--ps-muted); margin: 0 0 1.125rem; }
.ps-article-prose h2 { font-size: 1.25rem; font-weight: 500; color: var(--ps-ink); margin: 2rem 0 0.75rem; letter-spacing: -0.01em; }
.ps-article-prose h2:first-child { margin-top: 0; }
.ps-article-prose h3 { font-size: 1rem; font-weight: 500; color: var(--ps-blue); margin: 1.75rem 0 0.5rem; }
.ps-article-prose ul, .ps-article-prose ol { margin: 0 0 1.125rem; padding-left: 1.125rem; color: var(--ps-muted); }
.ps-article-prose li { font-size: var(--ps-t-base); margin-bottom: 0.4rem; line-height: 1.6; }
.ps-article-prose a { color: var(--ps-blue); text-decoration: underline; text-underline-offset: 3px; }
.ps-article-prose strong { color: var(--ps-ink); font-weight: 500; }
.ps-article-prose em { color: var(--ps-soft); font-size: var(--ps-t-sm); }
.ps-article-prose img { max-width: 100%; height: auto; margin: 1.5rem 0; }

/* ==========================================================================
   COA (v2 refinements) — Figma 1266:3710 ("COA Page")
   Restyle of the batch/lot COA directory to the new design. Structure & JS
   hooks are preserved (see page-coa.php header); changes are presentational
   plus the NEW Purity/Endotoxin view toggle (segmented control, right of the
   "Search Results" heading). Blue intro heading, blue PASS, 64px lilac thumbs,
   rounded cards, 2-column FAQ, full-width help band — all off existing tokens.
   ========================================================================== */
/* No padding-top: the page-head band already spends --ps-lede below its
   title. Adding more here is the double-count that made this gap 76px. */
.ps-coa-inner { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto; padding: 0 0 var(--ps-section); }

/* Soft page wash — the Figma's ambient blue blobs (Ellipse 3/6 top, Rectangle
   50/51 behind the cards + list). Same idiom as Home/Shop, tuned to this taller
   artboard: pools top-right/top-left, then a fainter one down by the list. */
.ps-coa.ps-main::before {
	background:
		radial-gradient(38rem 28rem at 97% 3%, rgba(0, 118, 184, 0.06), transparent 66%),
		radial-gradient(30rem 24rem at 0% 8%, rgba(0, 118, 184, 0.05), transparent 68%),
		radial-gradient(44rem 34rem at 6% 44%, rgba(0, 118, 184, 0.04), transparent 70%),
		radial-gradient(30rem 26rem at 96% 70%, rgba(0, 118, 184, 0.035), transparent 72%);
}

/* Intro — blue H2 + darker subtext (no eyebrow in the Figma). */
.ps-coa-intro { margin-bottom: var(--ps-flow); }
.ps-coa-h { font-size: var(--ps-t-h2); font-weight: 500; line-height: 1.2; letter-spacing: -0.01em; color: var(--ps-blue); margin: 0 0 var(--ps-flow-lockup); }
.ps-coa-sub { font-size: var(--ps-t-base); line-height: 1.6; color: var(--ps-ink); margin: 0; }

/* 4 quality cards — white, hairline border, rounded (Figma "Border"). */
.ps-coa-features { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--ps-sp-5); margin: var(--ps-flow) 0; }
.ps-coa-feature { background: var(--ps-paper); border: 1px solid var(--ps-line); border-radius: var(--ps-r-md); padding: 1.125rem 1.25rem; }
.ps-coa-feature h3 { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-blue); margin: 0 0 0.375rem; }
.ps-coa-feature p { font-size: var(--ps-t-sm); line-height: 1.5; color: var(--ps-muted); margin: 0; }

/* Search */
.ps-coa-search { position: relative; margin-bottom: var(--ps-sp-5); }
.ps-coa-search > svg { position: absolute; left: 1.125rem; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; color: var(--ps-soft); pointer-events: none; }
.ps-coa-search input { width: 100%; box-sizing: border-box; padding: 0.9375rem 1rem 0.9375rem 2.875rem; font: inherit; font-size: var(--ps-t-base); color: var(--ps-ink); background: var(--ps-field); border: 1px solid var(--ps-line); border-radius: var(--ps-r-sm); transition: border-color var(--ps-dur-1) ease, background var(--ps-dur-1) ease; }
.ps-coa-search input::placeholder { color: var(--ps-soft); }
.ps-coa-search input:focus { outline: none; border-color: var(--ps-blue); background: #fff; box-shadow: var(--ps-ring); }

/* Type tabs (All / Peptide / Blend / …) — pills; active fills blue. */
.ps-coa-tabs { display: flex; gap: var(--ps-sp-2); margin-bottom: var(--ps-flow); }
.ps-coa-tabs button { font: inherit; font-size: var(--ps-t-sm); font-weight: 500; color: var(--ps-navy); background: #fff; border: 1px solid var(--ps-line); border-radius: var(--ps-r-sm); padding: 0.5rem 1rem; cursor: pointer; transition: border-color var(--ps-dur-1) ease, background var(--ps-dur-1) ease, color var(--ps-dur-1) ease; }
.ps-coa-tabs button:hover { border-color: var(--ps-line-2); }
.ps-coa-tabs button.is-active { background: var(--ps-blue); border-color: var(--ps-blue); color: #fff; }

/* Results toolbar — "Search Results" (navy) + live count · Purity/Endotoxin toggle. */
.ps-coa-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem 1.5rem; flex-wrap: wrap; margin-bottom: var(--ps-sp-4); }
.ps-coa-results { display: flex; align-items: baseline; gap: var(--ps-sp-3); flex-wrap: wrap; }
.ps-coa-results-h { font-size: 1.25rem; font-weight: 500; letter-spacing: -0.01em; color: var(--ps-navy); margin: 0; }
.ps-coa-count { font-size: var(--ps-t-sm); color: var(--ps-muted); margin: 0; white-space: nowrap; }

/* Product list — white cards, 64px lilac thumb, chevron affordance. */
.ps-coa-list { display: flex; flex-direction: column; gap: var(--ps-sp-3); }
.ps-coa-item { border: 1px solid var(--ps-line); border-radius: var(--ps-r-md); background: var(--ps-paper); overflow: hidden; transition: border-color var(--ps-dur-1) ease, box-shadow var(--ps-dur-1) ease; }
.ps-coa-item:hover { border-color: var(--ps-line-2); }
.ps-coa-item:has(.ps-coa-row[aria-expanded="true"]) { border-color: var(--ps-chip); box-shadow: 0 10px 30px rgba(11, 25, 40, 0.06); }
.ps-coa-row { display: grid; grid-template-columns: 64px minmax(0, 1fr) auto auto; align-items: center; gap: 1rem 1.25rem; width: 100%; text-align: left; background: none; border: 0; padding: 1.125rem 1.5rem; cursor: pointer; font: inherit; }
.ps-coa-thumb { width: 64px; height: 64px; display: flex; align-items: center; justify-content: center; background: var(--ps-lilac); border-radius: var(--ps-r-sm); padding: 5px; overflow: hidden; }
.ps-coa-thumb img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
.ps-coa-idcol { display: flex; flex-direction: column; gap: 0.25rem; min-width: 0; }
.ps-coa-name { font-size: 1rem; font-weight: 500; color: var(--ps-navy); }
.ps-coa-facts { font-size: var(--ps-t-sm); color: var(--ps-muted); }
.ps-coa-batchmeta { display: flex; flex-direction: column; align-items: flex-end; gap: 0.25rem; text-align: right; }
.ps-coa-batchcount { font-size: var(--ps-t-sm); font-weight: 500; color: var(--ps-blue); }
.ps-coa-latest { font-size: var(--ps-t-xs); color: var(--ps-soft); }
.ps-coa-chev { display: inline-flex; align-items: center; justify-content: center; color: var(--ps-soft); }
.ps-coa-chev svg { width: 18px; height: 18px; transition: transform var(--ps-dur-1) ease; }
.ps-coa-row:hover .ps-coa-chev { color: var(--ps-blue); }
.ps-coa-row[aria-expanded="true"] .ps-coa-chev { color: var(--ps-blue); }
.ps-coa-row[aria-expanded="true"] .ps-coa-chev svg { transform: rotate(180deg); }

/* Batch drawer + table */
.ps-coa-drawer { border-top: 1px solid var(--ps-line); background: var(--ps-wash); overflow-x: auto; }
.ps-coa-table { width: 100%; border-collapse: collapse; font-size: var(--ps-t-sm); }
.ps-coa-table thead th { text-align: left; font-weight: 500; color: var(--ps-soft); text-transform: uppercase; letter-spacing: 0.03em; font-size: var(--ps-t-2xs); padding: 0.875rem 1.5rem; border-bottom: 1px solid var(--ps-line); white-space: nowrap; }
.ps-coa-table td { padding: 0.9375rem 1.5rem; color: var(--ps-ink); border-bottom: 1px solid var(--ps-line); vertical-align: middle; }
.ps-coa-table tbody tr:last-child td { border-bottom: 0; }
.ps-coa-table th:last-child, .ps-coa-table td:last-child { text-align: right; }
.ps-coa-pass { font-weight: 500; color: var(--ps-blue); }
.ps-coa-actions { display: flex; gap: var(--ps-sp-4); align-items: center; justify-content: flex-end; white-space: nowrap; }
.ps-coa-view { color: var(--ps-blue); font-weight: 500; text-decoration: none; }
.ps-coa-view:hover { text-decoration: underline; }
.ps-coa-dl { background: var(--ps-blue); color: #fff; padding: 0.4375rem 0.875rem; border-radius: var(--ps-r-xs); font-weight: 500; text-decoration: none; font-size: var(--ps-t-xs); transition: background var(--ps-dur-1) ease; }
.ps-coa-dl:hover { background: var(--ps-blue-deep); }
.ps-coa-view[aria-disabled="true"], .ps-coa-dl[aria-disabled="true"] { opacity: 0.45; pointer-events: none; }
.ps-coa-nobatch { margin: 0; padding: 1.25rem 1.5rem; color: var(--ps-muted); font-size: var(--ps-t-sm); line-height: 1.55; }
.ps-coa-empty { padding: 2.5rem 1.25rem; text-align: center; color: var(--ps-muted); font-size: var(--ps-t-base); }

/* FAQ — full-width, 2-column accordion grid. */
.ps-coa-faq { margin-top: var(--ps-section); }
.ps-coa-faq > h2 { font-size: var(--ps-t-h2); font-weight: 500; letter-spacing: -0.01em; color: var(--ps-blue); margin: 0 0 var(--ps-sp-5); }
.ps-coa-faq-grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 3rem; align-items: start; }
.ps-coa-faq details { border-bottom: 1px solid var(--ps-line); }
.ps-coa-faq summary { display: flex; align-items: center; justify-content: space-between; gap: var(--ps-sp-4); cursor: pointer; list-style: none; padding: 1rem 0; font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); }
.ps-coa-faq summary::-webkit-details-marker { display: none; }
.ps-coa-faq summary svg { width: 16px; height: 16px; color: var(--ps-soft); flex: 0 0 auto; transition: transform var(--ps-dur-1) ease; }
.ps-coa-faq details[open] summary { color: var(--ps-blue); }
.ps-coa-faq details[open] summary svg { transform: rotate(180deg); color: var(--ps-blue); }
.ps-coa-faq details p { font-size: var(--ps-t-ui); line-height: 1.6; color: var(--ps-muted); margin: 0 0 1rem; padding-right: 1rem; }

/* Help band — full-width, below the FAQ ("Couldn't find your batch?"). */
.ps-coa-help { margin-top: var(--ps-section); background: var(--ps-pale); border-radius: var(--ps-r-lg); padding: 2.25rem 2rem; display: flex; flex-direction: column; align-items: center; text-align: center; gap: 0.375rem; }
.ps-coa-help-copy { display: flex; flex-direction: column; gap: 0.375rem; }
.ps-coa-help h3 { font-size: 1.125rem; font-weight: 500; color: var(--ps-navy); margin: 0; }
.ps-coa-help p { font-size: var(--ps-t-ui); line-height: 1.5; color: var(--ps-muted); margin: 0; }
.ps-coa-help-link { display: inline-flex; align-items: center; gap: 0.25rem; margin-top: 0.625rem; font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-blue); text-decoration: none; }
.ps-coa-help-link svg { width: 15px; height: 15px; transition: transform var(--ps-dur-1) ease; }
.ps-coa-help-link:hover { text-decoration: underline; }
.ps-coa-help-link:hover svg { transform: translateX(2px); }

/* COA responsive */
@media (max-width: 900px) {
	.ps-coa-features { grid-template-columns: 1fr 1fr; }
	.ps-coa-faq-grid { grid-template-columns: 1fr; column-gap: 0; }
}
@media (max-width: 680px) {
	.ps-coa-toolbar { align-items: flex-start; }
	.ps-coa-tabs { flex-wrap: wrap; }
	.ps-coa-row { grid-template-columns: 48px minmax(0, 1fr) auto; grid-template-areas: "thumb id chev" "meta meta meta"; gap: 0.625rem 0.875rem; padding: 1rem 1.125rem; }
	.ps-coa-thumb { grid-area: thumb; width: 48px; height: 48px; }
	.ps-coa-idcol { grid-area: id; }
	.ps-coa-chev { grid-area: chev; align-self: start; }
	.ps-coa-batchmeta { grid-area: meta; flex-direction: row; align-items: center; gap: 0.875rem; text-align: left; }
	.ps-coa-table, .ps-coa-table tbody, .ps-coa-table tr, .ps-coa-table td { display: block; }
	.ps-coa-table thead { display: none; }
	.ps-coa-table th:last-child, .ps-coa-table td:last-child { text-align: left; }
	.ps-coa-table tr { padding: 0.75rem 1.5rem; border-bottom: 1px solid var(--ps-line); }
	.ps-coa-table tbody tr:last-child { border-bottom: 0; }
	.ps-coa-table td { border: 0; padding: 0.25rem 0; display: flex; justify-content: space-between; gap: var(--ps-sp-4); }
	.ps-coa-table td::before { content: attr(data-label); color: var(--ps-soft); font-size: var(--ps-t-xs); }
	.ps-coa-measure { display: flex; justify-content: space-between; gap: var(--ps-sp-4); }
	.ps-coa-actions { justify-content: flex-start; padding-top: 0.5rem; }
	.ps-coa-actions::before { display: none; }
}
@media (max-width: 480px) {
	.ps-coa-features { grid-template-columns: 1fr; }
}

/* --- Blog responsive (theme breakpoints 1023 / 900 / 740) --- */
@media (max-width: 1023px) {
	.ps-blog-featured { grid-template-columns: 1fr; gap: 1.75rem; }
	.ps-featured-title { font-size: 2.25rem; }
	.ps-blog-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 900px) {
	.ps-blog-intro { flex-direction: column; align-items: flex-start; gap: var(--ps-sp-6); }
	.ps-blog-intro-img { display: none; }
	.ps-blog-grid-head { align-items: flex-start; }
	/* Article: single column; TOC becomes a compact static card above the prose (top-level only). */
	.ps-article-inner { padding-top: var(--ps-flow); }
	.ps-article-head { flex-direction: column; gap: 0.625rem; align-items: flex-start; padding-bottom: var(--ps-sp-5); margin-bottom: var(--ps-flow); }
	.ps-article-meta { margin-top: 0; }
	.ps-article-body { grid-template-columns: 1fr; gap: var(--ps-sp-6); }
	.ps-toc { position: static; top: auto; border: 1px solid var(--ps-line); background: var(--ps-wash); padding: 1rem 1.125rem; }
	.ps-toc-sub { display: none; }
	.ps-toc-h2 > a { padding-left: 0; border-left: 0; }
	.ps-toc-h2 > a.is-active { border-left: 0; padding-left: 0; }
}
@media (max-width: 740px) {
	.ps-blog-grid { grid-template-columns: 1fr; }
	.ps-featured-title { font-size: 1.875rem; }
	.ps-article-title { font-size: var(--ps-t-h2); }
	.ps-blog-filters { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
	.ps-blog-filters::-webkit-scrollbar { display: none; }
}

/* ==========================================================================
   BLOG (v2 refinements) — Figma 1144:1021 (index) / 1262:3332 (single)
   New selectors that layer on the base blog/article rules above. The pixel
   tweaks that pull the build onto the new Figma — featured body space-between,
   6px badge radius, one-line intro copy, white/elevated active filter pill,
   24px article title, blue TOC title, ink TOC h2 links, tightened article
   spacing — are edited in place in the rules above; these are the additions.
   ========================================================================== */

/* Blue accent word in the featured-story + article <h1> (ps_accent_title()) —
   "chromatography" in "Advancements in chromatography precision". Wins over the
   inherited link colour; on hover the whole title goes blue, so it stays put. */
.ps-accent { color: var(--ps-blue); }

/* Featured body groups meta + title + excerpt so the parent's space-between
   pins the meta to the image's top edge and "Read Full Article" to its bottom. */
.ps-featured-top { display: flex; flex-direction: column; }

/* Ambient blue wash tuned to the blog artboard. The global .ps-main::before is
   Home-tuned (pools 52–77% down); the blog is taller, so pool the glow around
   the intro band + upper article grid (~22–64% down), leaving the featured
   story reading on white up top and fading out before the dark CTA band.
   Same per-artboard idiom as the Shop/About/COA overrides. */
.ps-blog.ps-main::before {
	background:
		radial-gradient(48rem 34rem at 84% 22%, rgba(0, 118, 184, 0.05), transparent 68%),
		radial-gradient(46rem 40rem at 6% 34%, rgba(0, 118, 184, 0.06), transparent 70%),
		radial-gradient(44rem 40rem at 92% 52%, rgba(0, 118, 184, 0.04), transparent 72%),
		radial-gradient(40rem 36rem at 14% 64%, rgba(0, 118, 184, 0.035), transparent 72%);
}

/* ==========================================================================
   Age gate — full opaque splash that shields the site (Figma "Age_Popup").
   The overlay's position + opaque background also ship as critical inline CSS
   from the mu-plugin (wp_head), so the site is never seen before this loads.
   ========================================================================== */
.ps-agegate {
	position: fixed;
	inset: 0;
	z-index: 1000;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow-y: auto;
	padding: 2.5rem var(--ps-gutter);
	background: #dbe7f1 url('../img/agegate-bg.jpg') center / cover no-repeat;
}
html.ps-agegate-open, html.ps-agegate-open body { overflow: hidden; }
.ps-agegate-inner { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 440px; margin: auto; }
.ps-agegate-logo { width: 156px; height: auto; margin: 0 0 1.5rem; }
.ps-agegate-card {
	width: 100%;
	background: var(--ps-paper);
	border: 1px solid rgba(226, 232, 240, 0.8);
	padding: 1.25rem;
	box-shadow: 0 24px 60px rgba(11, 25, 40, 0.18);
}
.ps-agegate-title { font-size: 1.375rem; font-weight: 500; letter-spacing: -0.01em; color: var(--ps-ink); margin: 0 0 0.5rem; }
.ps-agegate-body { font-size: var(--ps-t-sm); line-height: 1.5; color: var(--ps-muted); margin: 0 0 1.25rem; }
.ps-agegate-checkfield {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	border: 1px solid var(--ps-line);
	padding: 0.75rem;
	margin: 0 0 1.25rem;
	font-size: var(--ps-t-sm);
	color: var(--ps-ink);
	cursor: pointer;
}
.ps-agegate-checkfield input { flex: 0 0 auto; width: 16px; height: 16px; margin: 0; accent-color: var(--ps-blue); }
.ps-agegate-field { margin: 0 0 1.25rem; }
.ps-agegate-label { display: block; font-size: var(--ps-t-sm); font-weight: 500; color: var(--ps-ink); margin: 0 0 0.5rem; }
.ps-agegate-req { color: #D3492F; font-weight: 400; }
.ps-agegate-select {
	width: 100%;
	font-family: var(--ps-font);
	font-size: var(--ps-t-ui);
	color: var(--ps-ink);
	background-color: var(--ps-paper);
	border: 1px solid var(--ps-line);
	padding: 0.6875rem 2.5rem 0.6875rem 0.75rem;
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23808597' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 0.75rem center;
}
.ps-agegate-select:invalid { color: var(--ps-soft); }
.ps-agegate-enter { width: 100%; padding: 0.8125rem; font-size: var(--ps-t-base); font-weight: 500; }
.ps-agegate-enter:disabled { background: var(--ps-line); color: var(--ps-soft); cursor: not-allowed; }
.ps-agegate-exit { text-align: center; font-size: var(--ps-t-sm); color: var(--ps-ink); margin: 0.875rem 0 0; }
.ps-agegate-leave { color: var(--ps-blue); text-decoration: none; }
.ps-agegate-leave:hover { text-decoration: underline; text-underline-offset: 3px; }
.ps-agegate-disclaimer { width: 100%; font-size: var(--ps-t-xs); font-style: italic; line-height: 1.45; color: var(--ps-muted); margin: 1.5rem 0 0; }
@media (max-width: 560px) {
	.ps-agegate { padding: 1.5rem var(--ps-gutter); align-items: flex-start; }
	.ps-agegate-card { padding: 1.125rem; }
}

/* ==========================================================================
   Wholesale page (page-wholesale.php)
   Figma HyPStzuochxvctFWZiAGrc, section 1196:1095 (desktop 1196:1096 /
   mobile 1262:2828). Reuses .ps-section / .ps-split / .ps-faq / .ps-ruo /
   page-head; adds the B2B intro, feature grid, audience cards, doc list,
   ordering steps, CTA band. Column widths + gaps + the 240px CTA band are
   measured off the artboard; text/icon colors map to the tokens.
   ========================================================================== */
.ps-wh-center { text-align: center; }
.ps-wh-cta-center { display: flex; width: max-content; max-width: 100%; margin: var(--ps-flow) auto 0; }

/* ① B2B intro — copy left, product cluster right (floats on white, per Figma) */
.ps-wh-intro { grid-template-columns: 1fr 1.32fr; }  /* copy ~500 / cluster ~660 in the 1200 col */
.ps-wh-intro-copy .ps-h2 { margin-bottom: 0.75rem; }
.ps-wh-intro-copy .ps-lead { color: var(--ps-ink); }  /* Figma intro body = ink, not the lighter shared lead */
.ps-wh-intro-copy .ps-btn { margin-top: 0.25rem; }
.ps-wh-intro-media { display: flex; align-items: center; justify-content: center; }
.ps-wh-intro-img { width: 100%; max-width: 660px; height: auto; object-fit: contain; }

/* ② Feature grid — 2×2 icon + title + copy (24px gutters, pale icon tiles) */
.ps-wh-features { display: grid; grid-template-columns: 1fr 1fr; gap: var(--ps-sp-6); }
.ps-wh-feat-icon { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border-radius: var(--ps-r-sm); background: var(--ps-wash); color: var(--ps-blue); margin-bottom: 1.125rem; }
.ps-wh-feature h3 { font-size: 1rem; font-weight: 500; color: var(--ps-ink); margin: 0 0 0.375rem; }
.ps-wh-feature p { font-size: var(--ps-t-ui); line-height: 1.45; color: var(--ps-muted); margin: 0; max-width: 30rem; }

/* ③ Who wholesale is for — heading + 2×2 image cards (navy titles) */
.ps-wh-audience .ps-h2 { margin-bottom: var(--ps-sp-5); }
.ps-wh-aud-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 2.25rem 1.5rem; }
.ps-wh-aud-card figure { margin: 0 0 0.875rem; }
.ps-wh-aud-card img { width: 100%; height: 232px; object-fit: cover; display: block; }
.ps-wh-aud-card h3 { font-size: var(--ps-t-md); font-weight: 500; color: var(--ps-navy); margin: 0 0 0.375rem; }
.ps-wh-aud-card p { font-size: var(--ps-t-ui); line-height: 1.45; color: var(--ps-muted); margin: 0; }

/* ④ Quality communication — product + copy left, bordered doc cards right */
.ps-wh-docs { align-items: center; gap: 3rem; }
.ps-wh-docs-boxes { margin: 0 0 var(--ps-flow); }
.ps-wh-docs-boxes img { display: block; height: 152px; width: auto; max-width: 100%; object-fit: contain; }
.ps-wh-docs-copy .ps-h2 { margin-bottom: var(--ps-flow-tight); max-width: 26rem; }
.ps-wh-docs-copy .ps-lead { color: var(--ps-ink); }  /* Figma docs body = ink */
.ps-wh-doclist { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1.375rem; }
.ps-wh-doclist li { display: flex; gap: var(--ps-sp-3); align-items: center; min-height: 68px; border: 1px solid var(--ps-line); border-radius: var(--ps-r-md); padding: 0.75rem 1rem; }
.ps-wh-doc-icon { display: inline-flex; color: var(--ps-blue); flex: 0 0 auto; }
.ps-wh-doclist h4 { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); margin: 0 0 0.1875rem; }
.ps-wh-doclist p { font-size: var(--ps-t-sm); line-height: 1.4; color: var(--ps-muted); margin: 0; }

/* ⑤ How ordering works — 5 numbered process cards (3 + 2, centered) */
.ps-wh-steps-head { text-align: center; max-width: 42rem; margin: 0 auto var(--ps-flow); }
.ps-wh-steps-head .ps-h2 { margin-bottom: var(--ps-flow-lockup); }
.ps-wh-steps-head .ps-h4 { margin: 0; color: var(--ps-muted); font-weight: 400; }
.ps-wh-steps-grid { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: var(--ps-sp-5); }
.ps-wh-step { flex: 0 1 calc(33.333% - 0.834rem); border: 1px solid var(--ps-line); border-radius: var(--ps-r-lg); padding: 1.5rem 1.25rem; box-sizing: border-box; }
.ps-wh-step-ico { display: block; width: 120px; height: 120px; margin: 0 auto 1rem; object-fit: contain; }
.ps-wh-step h3 { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); margin: 0 0 0.5rem; line-height: 1.3; }
.ps-wh-step-n { color: var(--ps-blue); font-weight: 700; }
.ps-wh-step p { font-size: var(--ps-t-sm); line-height: 1.45; color: var(--ps-muted); margin: 0; }

/* ⑥ FAQ heading */
.ps-wh-faq .ps-h2 { margin-bottom: var(--ps-sp-5); }

/* ⑦ CTA band — blue 240px band, copy left, product cluster bleeding top/bottom.
   The desktop asset (cta-boxes-t.png) is a transparent 422×422 render pinned to
   the Figma coordinates (x≈779, y=-101 within the 1200×240 band): the blue comes
   from the band itself, so the boxes + molecules simply overshoot above/below. */
.ps-wh-cta { position: relative; display: flex; align-items: center; background: var(--ps-blue); color: #fff; padding: 1.875rem 2.5rem; min-height: 240px; box-sizing: border-box; overflow: visible; }
.ps-wh-cta-copy { position: relative; z-index: 1; }
.ps-wh-cta-copy h2 { font-size: var(--ps-t-h1); font-weight: 500; line-height: 1.12; letter-spacing: -0.01em; color: #fff; margin: 0 0 1.375rem; }
.ps-wh-cta-img { position: absolute; right: 0; top: -101px; height: 422px; width: auto; object-fit: contain; pointer-events: none; }
.ps-wh-cta-img-m { display: none; }  /* mobile-only: solid-blue-bg composite, seam-free on the band */

/* ⑧ RUO band heading tightening (uses shared .ps-ruo) */
.ps-wh-ruo h2 { color: var(--ps-ink); }

/* --- Wholesale responsive --- */
@media (max-width: 900px) {
	.ps-wh-intro { grid-template-columns: 1fr; }  /* re-declared: our column override outranks the shared .ps-split collapse */
	.ps-wh-features { gap: 1.5rem 1.75rem; }
	.ps-wh-aud-grid { gap: 1.75rem 1.5rem; }
	.ps-wh-step { flex-basis: calc(50% - 0.625rem); }
	/* CTA stacks: left-aligned copy, full-width button, boxes+molecules image on the blue band */
	.ps-wh-cta { flex-direction: column; align-items: stretch; text-align: left; min-height: 0; height: auto; padding: 2.25rem var(--ps-gutter); overflow: hidden; }
	.ps-wh-cta-copy h2 { font-size: 1.875rem; }
	.ps-wh-cta-copy .ps-btn { display: block; width: 100%; box-sizing: border-box; }
	.ps-wh-cta-img { display: none; }
	.ps-wh-cta-img-m { display: block; width: 100%; max-width: 420px; height: auto; margin: 1.5rem auto 0; }
}
@media (max-width: 560px) {
	/* Figma mobile keeps features + audience as 2×2 — only tighten the gaps */
	.ps-wh-features { gap: 1.5rem 1.25rem; }
	.ps-wh-aud-grid { gap: 1.25rem 1rem; }
	.ps-wh-step { flex-basis: 100%; }
	.ps-wh-aud-card img { height: 178px; }
	.ps-wh-cta-copy h2 { font-size: 1.625rem; }
}
@media (max-width: 380px) {
	/* very narrow: features stack so descriptions stay legible; audience stays 2-up */
	.ps-wh-features { grid-template-columns: 1fr; }
}

/* ==========================================================================
   HOME (v2 redesign — Figma HyPStzuochxvctFWZiAGrc / artboard 1445:1624)
   --------------------------------------------------------------------------
   Restyle pass over the ported home: a curated five-across product GRID (was
   the marquee), the three faint decorative gradient washes ("Ellipse 3/4/5"),
   bordered key-point cards, and the blue FAQ open-state. Reuses the tokens and
   the shared Woo loop card — only the grid container + these polish rules are new.
   ========================================================================== */

/* Decorative page washes — the faint radial "Ellipse" glows behind the lower
   half of the artboard. Token-derived, very low alpha (Figma washes to ~#F8FBFC)
   and painted on a non-interactive layer beneath the content. */
.ps-main { position: relative; }
.ps-main::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background:
		radial-gradient(46rem 40rem at 12% 52%, rgba(0, 118, 184, 0.06), transparent 70%),
		radial-gradient(26rem 24rem at 88% 63%, rgba(0, 118, 184, 0.05), transparent 70%),
		radial-gradient(21rem 22rem at 47% 77%, rgba(0, 118, 184, 0.045), transparent 70%);
}

/* Products grid — five curated cards across, reusing the global Woo loop card
   (name / meta / price / image / Learn More). display:contents promotes the
   <li> to grid items of .ps-products-grid (same trick as .ps-shop-grid). */
.ps-products-grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: var(--ps-gap-grid);
}
.ps-products-grid > .woocommerce { display: contents; }
.ps-products-grid ul.products[class*="columns-"] { display: contents !important; }
.ps-products-grid li.product { min-height: 288px; padding: 1.125rem 1.125rem 0.875rem; }
.ps-products-grid ul.products[class*="columns-"] li.product img { height: 150px; max-width: 88%; }
@media (max-width: 1000px) {
	.ps-products-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 680px) {
	.ps-products-grid { grid-template-columns: repeat(2, 1fr); gap: var(--ps-sp-3); }
	.ps-products-grid ul.products[class*="columns-"] li.product img { height: 160px; }
}

/* Key-point cards (Supported / Informed / Confident) — white + hairline border
   in the Figma (vs the borderless wash of the why-us row). */
.ps-keypoints .ps-wash-card {
	background: var(--ps-paper);
	border: 1px solid var(--ps-line);
}

/* FAQ open-state — the Figma highlights an expanded item with a pale-blue panel
   and a blue question + chevron. */
.ps-faq details[open] {
	border-color: var(--ps-chip);
	background: var(--ps-pale);
}
.ps-faq details[open] summary { color: var(--ps-blue); }
.ps-faq details[open] summary::after { border-color: var(--ps-blue); }

/* ==========================================================================
   PDP (v2 redesign) — Figma 12952:452
   Overview / Handling / Quality & Testing / Related. Full-width bands with a
   1200 inner track; each has a 285px left rail (eyebrow + heading) and a 1fr
   content column. Buy box + pack selector styles live in the PDP block above.
   ========================================================================== */
.ps-pd-sec { width: 100%; }
.ps-pd-sec-inner {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 0 auto;
	padding: var(--ps-section) 0;
	display: grid;
	grid-template-columns: 285px 1fr;
	gap: 3.75rem;
	border-top: 1px solid var(--ps-line);
}
.ps-pd-sec:first-of-type .ps-pd-sec-inner { margin-top: var(--ps-section-sm); }
.ps-pd-eyebrow { font-size: var(--ps-t-ui); font-weight: 500; color: var(--ps-blue); margin: 0 0 0.5rem; }
.ps-pd-h2 {
	font-size: 1.75rem;
	font-weight: 700;
	line-height: 1.15;
	letter-spacing: -0.02em;
	color: var(--ps-navy);
	margin: 0;
}
.ps-pd-lead { font-size: 1rem; line-height: 1.6; color: var(--ps-muted); margin: 0 0 1.5rem; }
.ps-pd-note { font-size: var(--ps-t-base); line-height: 1.5; color: var(--ps-muted); margin: 0.75rem 0 0; }
.ps-pd-link {
	color: var(--ps-blue);
	font-size: var(--ps-t-ui);
	font-weight: 500;
	text-decoration: underline;
	text-underline-offset: 3px;
	white-space: nowrap;
}

/* Overview — spec grid */
.ps-spec-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--ps-sp-3); }
.ps-spec {
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-md);
	padding: 1rem 1.125rem;
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
}
.ps-spec-k { font-size: var(--ps-t-2xs); font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ps-muted); }
.ps-spec-v { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); }
.ps-spec-v sub { font-size: 0.72em; }

/* Handling — numbered steps */
.ps-pd-steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; }
.ps-pd-step-n {
	display: inline-grid;
	place-items: center;
	width: 34px;
	height: 34px;
	border: 1.5px solid var(--ps-blue);
	border-radius: var(--ps-r-sm);
	color: var(--ps-blue);
	font-size: var(--ps-t-ui);
	font-weight: 700;
}
.ps-pd-step h3 { font-size: 1rem; font-weight: 500; color: var(--ps-navy); margin: 1rem 0 0.5rem; }
.ps-pd-step p { font-size: var(--ps-t-ui); line-height: 1.5; color: var(--ps-muted); margin: 0; }

/* Quality & Testing — batch COA card */
.ps-pd-quality .ps-pd-lotlabel {
	font-size: var(--ps-t-2xs);
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--ps-muted);
	margin: 1.5rem 0 0.25rem;
}
.ps-pd-lot { font-size: 1.125rem; font-weight: 700; color: var(--ps-navy); margin: 0; }
.ps-pd-lotsub { font-size: var(--ps-t-sm); color: var(--ps-muted); margin: 0.25rem 0 1rem; }
.ps-pd-coa-card { border: 1px solid var(--ps-line); border-radius: var(--ps-r-lg); padding: 1.75rem; }
.ps-pd-coa-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--ps-sp-4); margin: 0 0 1.25rem; }
.ps-pd-coa-card-title { font-size: var(--ps-t-md); font-weight: 500; color: var(--ps-navy); margin: 0; }
.ps-pd-coa-card-meta { font-size: var(--ps-t-sm); color: var(--ps-muted); margin: 0.25rem 0 0; }
.ps-pd-coa-dl {
	flex: 0 0 auto;
	background: var(--ps-blue);
	color: #fff;
	font-size: var(--ps-t-sm);
	font-weight: 500;
	padding: 0.625rem 1rem;
	border-radius: var(--ps-r-sm);
	text-decoration: none;
	white-space: nowrap;
	transition: background var(--ps-dur-1) ease;
}
.ps-pd-coa-dl:hover { background: var(--ps-blue-deep); color: #fff; }
.ps-pd-coa-table { width: 100%; border-collapse: collapse; }
.ps-pd-coa-table th {
	text-align: left;
	font-size: var(--ps-t-2xs);
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--ps-muted);
	padding: 0 0 0.75rem;
	border-bottom: 1px solid var(--ps-line);
}
.ps-pd-coa-table th:last-child, .ps-pd-coa-table td:last-child { text-align: right; }
.ps-pd-coa-table td { font-size: var(--ps-t-ui); color: var(--ps-muted); padding: 0.875rem 0; border-bottom: 1px solid var(--ps-line); }
.ps-pd-coa-table tbody tr:last-child td { border-bottom: 0; }
.ps-pd-coa-table td.is-strong { color: var(--ps-ink); font-weight: 700; }
.ps-pd-coa-table td.is-pass { color: var(--ps-blue); font-weight: 700; }
.ps-pd-coa-foot { font-size: var(--ps-t-xs); line-height: 1.4; color: var(--ps-soft); margin: 1.25rem 0 0; }

/* Related — 4 product cards (image-first) */
.ps-pd-related-inner {
	width: min(var(--ps-col), 100% - 2 * var(--ps-gutter));
	margin: 0 auto;
	padding: 3rem 0 var(--ps-section);
	border-top: 1px solid var(--ps-line);
}
.ps-pd-related-head { display: flex; align-items: flex-end; justify-content: space-between; gap: var(--ps-sp-4); margin: 0 0 1.5rem; }
.ps-pd-related-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--ps-sp-5); }
.ps-pd-card { display: flex; flex-direction: column; text-decoration: none; }
.ps-pd-card-media {
	background: var(--ps-pale);
	border-radius: var(--ps-r-lg);
	aspect-ratio: 1 / 1;
	display: grid;
	place-items: center;
	padding: 1.5rem;
}
.ps-pd-card-media img { width: 100%; height: auto; object-fit: contain; transition: transform var(--ps-dur-1) ease; }
.ps-pd-card:hover .ps-pd-card-media img { transform: scale(1.04); }
.ps-pd-card-body { display: flex; flex-direction: column; gap: 0.25rem; padding: 0.875rem 0.25rem 0; }
.ps-pd-card-name { font-size: 1rem; font-weight: 500; color: var(--ps-navy); }
.ps-pd-card-meta { font-size: var(--ps-t-sm); color: var(--ps-muted); }
.ps-pd-card-price { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); margin-top: 0.125rem; }
.ps-pd-card-price .woocommerce-Price-amount { color: var(--ps-ink); }
.ps-pd-card-price del { color: var(--ps-soft); font-weight: 400; margin-right: 0.375rem; }

/* PDP v2 responsive (appended last so it wins over the earlier PDP media rules) */
@media (max-width: 900px) {
	/* Compact, contained product panel on mobile — the whole intro (image →
	   title → spec → blurb → PRICE) must fit the first screen ABOVE the fixed
	   buy dock (real-device fix: the dock was covering '$89.99 per box'). */
	.ps-pdp div.product { margin-top: 1rem; gap: var(--ps-sp-4); }
	.ps-pdp .woocommerce-product-gallery { max-width: none; margin: 0 !important; }
	.ps-pdp .woocommerce-product-gallery__wrapper { aspect-ratio: auto; padding: 0.875rem; }
	/* Cap the (portrait) box render with a DEFINITE max-height. svh tracks the
	   REAL visible viewport (Safari/Chrome bars eat ~150px of vh on phones — the
	   17 Pro Max report), so the intro scales to what's actually on screen. */
	/* Hard px cap — vh-based caps shift with browser chrome and resolve
	   inconsistently across engines (the real-device overflow bug). */
	/* Woo nests the image two levels deep (__image > a > img), and BOTH levels take
	   their height from the square source — so a % max-height on the img measured
	   against a 350px <a>, not the 160px plate, and the render spilled out (cropped
	   by the wrapper's overflow). Constrain the whole chain to the plate, then let
	   object-fit do the scaling. */
	/* The wrapper is a grid with an AUTO row: a fixed container height doesn't stop
	   an auto row from growing to its 350px content, so 100% still resolved against
	   the overflowing row. Pin the track to the container. */
	.ps-pdp .woocommerce-product-gallery__wrapper {
		grid-template-rows: minmax(0, 1fr);
		grid-template-columns: minmax(0, 1fr);
		place-items: center;
	}
	.ps-pdp .woocommerce-product-gallery__image,
	.ps-pdp .woocommerce-product-gallery__image > a {
		display: grid;
		place-items: center;
		height: 100%;
		min-height: 0;   /* grid items refuse to shrink below content without this */
		width: 100%;
	}
	.ps-pdp .woocommerce-product-gallery img { height: 100%; max-height: 100%; width: auto; max-width: 100%; object-fit: contain; }
	.ps-pdp .summary .product_title { font-size: 1.625rem; }
	.ps-pd-stock { margin-top: 0.25rem; } /* re-center on the smaller title line */
	.ps-pd-desc { font-size: var(--ps-t-ui); line-height: 1.45; margin-top: 0.875rem; }
	.ps-pdp .summary > .price { font-size: 1.625rem; margin-top: 1rem; }
	.ps-pd-sec-inner { grid-template-columns: 1fr; gap: var(--ps-sp-5); }
	.ps-pd-coa-card { padding: 1.25rem; }
	.ps-pd-related-grid { grid-template-columns: 1fr 1fr; gap: var(--ps-sp-4); }
	.ps-pd-related-head { flex-direction: column; align-items: flex-start; }
}
@media (max-width: 740px) {
	.ps-pdp div.product { grid-template-columns: 1fr; }
	.ps-pdp form.cart { grid-template-columns: 118px 1fr; }
	.ps-spec-grid { grid-template-columns: 1fr 1fr; }
	.ps-pd-steps { grid-template-columns: 1fr; gap: var(--ps-sp-6); }
	.ps-pd-coa-card-top { flex-direction: column; }
	.ps-pd-coa-dl { align-self: flex-start; }
	/* Phone first-screen budget: price + the FULL COA card must clear the dock
	   with a premium gap even inside browser chrome (~750px visible on a Pro
	   Max). Tighter crumb, 3-line blurb, compact COA card. */
	.ps-pd-crumb { margin-top: 0.875rem; }
	.ps-pd-coa { margin-top: 0.875rem; padding: 0.75rem 0.875rem; gap: 0.625rem; }
	.ps-pd-coa-txt { font-size: var(--ps-t-xs); line-height: 1.4; }
	.ps-pdp .summary > .price { margin-top: 0.75rem; }
}
@media (max-width: 480px) {
	.ps-spec-grid { grid-template-columns: 1fr; }
	.ps-pd-trust li { font-size: 10px; }
	.ps-pd-trust li + li::before { margin: 0 0.625rem; }
}

/* ==========================================================================
   HEADER OVERLAYS (menu dropdown / cart drawer / search) — Figma 12952:452
   --------------------------------------------------------------------------
   Three global overlays opened from the header (wired in ps.js). Each root is
   full-viewport: a dark scrim + a white panel on top. The root stays
   visibility:hidden until .is-open; the transition-delay on visibility keeps it
   painted through the panel's slide-out so closing animates. z-index 200 clears
   the sticky header (100) but stays under the age gate (1000). Token-driven,
   v2 flat with #0076B8 accents.
   ========================================================================== */
.ps-overlay {
	position: fixed;
	inset: 0;
	z-index: 200;
	visibility: hidden;
	pointer-events: none;
	transition: visibility 0s linear var(--ps-dur-2);
}
.ps-overlay.is-open { visibility: visible; pointer-events: auto; transition-delay: 0s; }
html.ps-overlay-open, html.ps-overlay-open body { overflow: hidden; }

.ps-overlay-scrim {
	position: absolute;
	inset: 0;
	background: rgba(11, 25, 40, 0.42);
	opacity: 0;
	transition: opacity var(--ps-dur-2) ease;
}
.ps-overlay.is-open .ps-overlay-scrim { opacity: 1; }

/* Shared panel chrome — white surface with a "Title  ✕" head bar. */
.ps-overlay-panel {
	position: absolute;
	display: flex;
	flex-direction: column;
	max-height: 100%;
	overflow: hidden;
	background: var(--ps-paper);
}
/* Open() focuses the dialog container (a11y) — never paint a ring on it. */
.ps-overlay-panel:focus, .ps-overlay-panel:focus-visible { outline: none; }
.ps-overlay-head {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--ps-sp-4);
	padding: 1rem 1.25rem;
	border-bottom: 1px solid var(--ps-line);
}
.ps-overlay-head h2 {
	margin: 0;
	font-size: 1rem;
	font-weight: 500;
	letter-spacing: -0.01em;
	color: var(--ps-ink);
}
.ps-overlay-close {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	color: var(--ps-muted);
	background: var(--ps-paper);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-sm);
	cursor: pointer;
	transition: color var(--ps-dur-1) ease, border-color var(--ps-dur-1) ease, background var(--ps-dur-1) ease;
}
.ps-overlay-close:hover { color: var(--ps-ink); border-color: var(--ps-line-2); background: var(--ps-wash); }
.ps-overlay-close svg { display: block; }

/* ---- Menu dropdown — a top sheet that drops in over the header ---- */
.ps-menu-panel {
	top: 0; left: 0; right: 0;
	width: 100%;
	border-bottom-left-radius: var(--ps-r-lg);
	border-bottom-right-radius: var(--ps-r-lg);
	box-shadow: 0 20px 44px rgba(11, 25, 40, 0.16);
	transform: translateY(-14px);
	opacity: 0;
	transition: transform var(--ps-dur-2) ease, opacity var(--ps-dur-1) ease;
}
.ps-menu-ov.is-open .ps-menu-panel { transform: none; opacity: 1; }
.ps-menu-list { list-style: none; margin: 0; padding: 0.25rem 0 0.5rem; overflow-y: auto; }
.ps-menu-list a {
	display: block;
	padding: 0.9375rem 1.25rem;
	font-size: 1rem;
	font-weight: 500;
	letter-spacing: -0.01em;
	color: var(--ps-ink);
	text-decoration: none;
	transition: color var(--ps-dur-1) ease, background var(--ps-dur-1) ease;
}
.ps-menu-list li + li a { border-top: 1px solid var(--ps-line); }
.ps-menu-list a:hover, .ps-menu-list a:focus-visible { color: var(--ps-blue); background: var(--ps-wash); }
.ps-menu-list a[aria-current="page"] { color: var(--ps-blue); }

/* ---- Cart drawer v2 — floating card on desktop, bottom sheet on phones.
   The body is stock woocommerce_mini_cart() markup, styled only (rule #3);
   the progress / savings / empty modules render via the mini-cart's own hooks
   so every AJAX fragment refresh re-renders them. ---- */
/* Desktop cart rises from the bottom centre — same arrival as the mobile sheet,
   so the cart always comes from one place. Width tracks the viewport (~half at
   desktop) instead of a fixed sidebar. */
.ps-drawer-panel-c {
	top: auto;
	right: auto;
	left: 50%;
	bottom: 0;                       /* docked to the viewport edge, not floating */
	height: auto;
	/* 50% was arbitrary: at 1440 that is 720px of mostly empty gutter around a
	   narrow item list. Sized to the content instead — comfortable for a line
	   item + thumb + price, and it still scales with the viewport. */
	width: clamp(560px, 52vw, 780px);
	max-height: min(84vh, 900px);
	border-radius: 0;
	box-shadow: 0 -30px 90px -20px rgba(6, 18, 30, 0.5), 0 -1px 0 var(--ps-line);
	transform: translate(-50%, calc(100% + 28px));
	transition: transform var(--ps-dur-3) var(--ps-ease-spring);
}
/* Footer (ledger + CTAs) pins to the sidebar's bottom; the items list flexes. */
.ps-drawer-ov.is-open .ps-drawer-panel-c { transform: translate(-50%, 0); }
/* The title bar reads as chrome, so it should be no heavier than the band
   beneath it — matched to the shipping strip's height. */
.ps-drawer-panel-c .ps-overlay-head { border-bottom: 0; padding: 0.75rem 1.25rem; }
.ps-drawer-panel-c .ps-overlay-head h2 { font-size: var(--ps-t-md); font-weight: 700; color: var(--ps-navy); }
.ps-drawer-panel-c .ps-overlay-close { width: 26px; height: 26px; }
/* No bottom padding: the buttons block owns the final gap, so it equals the gap between the two buttons exactly. */
.ps-mini-cart { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; padding: 0 1.25rem; }

/* Shipping status band — OUR chrome: a navy strip (announce-ticker heritage)
   bleeding edge-to-edge of the panel, white copy with the ticker's light-blue
   accent, and a thin blue hairline meter. No green — that's stock status only. */
.ps-mc-ship {
	flex: 0 0 auto;
	margin: 0 -1.25rem;
	padding: 0.6875rem 1.25rem 0.75rem;
	background: var(--ps-dark);
}
.ps-mc-ship-msg { display: flex; align-items: center; gap: 0.4375rem; margin: 0 0 0.5rem; font-size: var(--ps-t-xs); letter-spacing: -0.01em; color: rgba(255, 255, 255, 0.9); }
.ps-mc-ship-msg b { color: #7CC1EC; font-weight: 700; }
.ps-mc-ship-msg svg { color: #7CC1EC; flex: 0 0 auto; }
/* The threshold is the qualifier, not the news — dimmed so "Free shipping
   included" stays the line you read, with the condition available beside it. */
/* Pressed state for the drawer's Checkout / View cart. The label stays put and
   legible — dimming it would read as "disabled", not "working" — and a hairline
   sweep runs along the bottom edge for the ~0.8s the navigation takes. */
.ps-drawer-panel a.is-pending,
.ps-mc-actions a.is-pending { position: relative; pointer-events: none; overflow: hidden; }
.ps-drawer-panel a.is-pending::after,
.ps-mc-actions a.is-pending::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	height: 2px;
	width: 100%;
	background: currentColor;
	opacity: 0.55;
	transform-origin: 0 50%;
	animation: ps-pending-sweep 1.1s var(--ps-ease-enter) infinite;
}
@keyframes ps-pending-sweep {
	0%   { transform: scaleX(0); opacity: 0.15; }
	55%  { opacity: 0.6; }
	100% { transform: scaleX(1); opacity: 0.15; }
}
@media (prefers-reduced-motion: reduce) {
	.ps-drawer-panel a.is-pending::after,
	.ps-mc-actions a.is-pending::after { animation: none; transform: scaleX(1); opacity: 0.4; }
}
.ps-mc-ship-note { margin-left: 0.375rem; color: rgba(255, 255, 255, 0.5); font-weight: 400; white-space: nowrap; }
.ps-mc-bar { height: 3px; border-radius: var(--ps-r-pill); background: rgba(255, 255, 255, 0.16); overflow: hidden; }
.ps-mc-bar i { display: block; height: 100%; border-radius: var(--ps-r-pill); background: var(--ps-blue); transition: width var(--ps-dur-3) var(--ps-ease); }
.ps-mc-ship.is-unlocked .ps-mc-bar i { background: #7CC1EC; }

/* Bundle tier row — second meter in the same navy band (mixable tiers). The
   tick marks the 5-box milestone on a 10-box track. */

/* Line items — stock markup on a fixed geometry: thumb rail left, remove right,
   so the name never gets squeezed and the bulk hint reads as a quiet pill. */
.ps-mini-cart .woocommerce-mini-cart {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--ps-line);
}
/* Selectors carry ul.cart_list + li.* so they outrank WooCommerce's own
   cart-list rules (its small-screen sheet wins otherwise: 4px rows, 32px
   floated thumbs — the broken layout the client flagged). */
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item {
	position: relative;
	display: block;
	margin: 0;
	padding: 0.875rem 2rem 0.875rem 4.375rem; /* 56px thumb + 14px gap | 32px remove */
	border-bottom: 1px solid var(--ps-line);
	min-height: 5.25rem;
}
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item > a:not(.remove) {
	display: block;
	font-size: var(--ps-t-base);
	font-weight: 700;
	line-height: 1.25;
	color: var(--ps-navy);
	text-decoration: none;
}
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item > a:not(.remove):hover { color: var(--ps-blue); }
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item img {
	position: absolute;
	float: none;
	left: 0;
	top: 0.875rem;
	width: 56px;
	height: 56px;
	margin: 0;
	object-fit: contain;
	padding: 4px;
	background: var(--ps-wash);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-md);
}
/* Woo's dl.variation is hidden — its info lives in our manifest qty line. */
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item .variation { display: none; }
/* Lab-shorthand spec sub-line under the name (from our product meta). */
.ps-mini-cart .ps-mc-spec {
	display: block;
	margin-top: 0.1875rem;
	font-size: var(--ps-t-xs);
	font-weight: 400;
	color: var(--ps-muted);
	letter-spacing: -0.01em;
}
/* Manifest qty line: "×5 · $89.99 each · bulk −10%" left, line total right. */
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item .quantity {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--ps-sp-3);
	margin-top: 0.4375rem;
	font-size: var(--ps-t-xs);
	font-weight: 400;
	color: var(--ps-muted);
	font-variant-numeric: tabular-nums;
}
.ps-mini-cart .ps-mc-qline { min-width: 0; white-space: nowrap; }
.ps-mini-cart .ps-mc-line-total { flex: 0 0 auto; font-size: var(--ps-t-ui); font-weight: 700; color: var(--ps-navy); }
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item a.remove {
	position: absolute;
	top: 0.75rem;
	right: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 26px;
	height: 26px;
	font-size: 1.125rem;
	line-height: 1;
	color: var(--ps-soft) !important; /* woo core reds the ×; ours is quiet until hover */
	text-decoration: none;
	border: 1px solid transparent;
	border-radius: var(--ps-r-pill);
	transition: color var(--ps-dur-1) ease, background var(--ps-dur-1) ease, border-color var(--ps-dur-1) ease;
}
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item a.remove:hover { color: #D3492F !important; background: #F6E7E5; border-color: #EAD2CE; }

/* Empty state — invitation, not a shrug. */
.ps-mc-empty { margin: auto 0; padding: 2.25rem 0 1.5rem; text-align: center; }
.ps-mc-empty-ico { display: inline-grid; place-items: center; width: 64px; height: 64px; border-radius: var(--ps-r-lg); background: var(--ps-pale); color: var(--ps-blue); margin-bottom: 0.875rem; }
.ps-mc-empty-title { margin: 0 0 0.25rem; font-size: var(--ps-t-md); font-weight: 700; color: var(--ps-navy); }
.ps-mc-empty-sub { margin: 0 auto 1.25rem; max-width: 250px; font-size: var(--ps-t-sm); line-height: 1.5; color: var(--ps-muted); }
.ps-mc-empty-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0.8125rem 1.75rem;
	background: var(--ps-blue);
	color: #fff;
	font-size: var(--ps-t-ui);
	font-weight: 700;
	text-decoration: none;
	border-radius: 0; /* the site's flat square button language */
	transition: background var(--ps-dur-1) ease;
}
.ps-mc-empty-btn:hover { background: var(--ps-blue-deep); }

/* Ledger totals — Subtotal / Bulk pricing / Total, hairline arithmetic like
   our COA and spec tables. The template wraps it in a <p>, so rows are spans. */
.ps-mini-cart .woocommerce-mini-cart__total {
	display: block;
	margin: 0;
	padding: 0.75rem 0 0.375rem;
}
.ps-mc-row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--ps-sp-4);
	padding: 0.1875rem 0;
	font-size: var(--ps-t-sm);
	color: var(--ps-muted);
	font-variant-numeric: tabular-nums;
}
.ps-mc-row.is-discount span:last-child { color: var(--ps-blue-deep); font-weight: 700; }
.ps-mc-row.is-total {
	margin-top: 0.375rem;
	padding-top: 0.5625rem;
	border-top: 1px solid var(--ps-line);
	color: var(--ps-navy);
	font-weight: 700;
	font-size: var(--ps-t-ui);
}
.ps-mc-row.is-total span:last-child { font-size: var(--ps-t-lg); font-weight: 700; }
.ps-mc-row.is-total small { font-weight: 400; font-size: var(--ps-t-2xs); color: var(--ps-muted); margin-left: 0.25rem; }

/* DRAWER QUANTITY — a real control, not a read-out. Mirrors the PDP bundle
   rail exactly (trash at one, ± above), so the same gesture works in both
   places and the client only had to approve the pattern once. */
.ps-mini-cart li .quantity { display: block; align-items: center; }
.ps-mini-cart ul.cart_list li.woocommerce-mini-cart-item > a:not(.remove) { padding-right: 8.25rem; }
.ps-mc-step {
	display: inline-flex;
	align-items: stretch;
	height: 30px;
	border: 1px solid var(--ps-line-2);
	background: #fff;
	transition: border-color var(--ps-dur-1) ease, opacity var(--ps-dur-1) ease;
}
.ps-mc-step:hover { border-color: var(--ps-blue); }
.ps-mc-step.is-busy { opacity: 0.5; pointer-events: none; }
.ps-mc-step-btn {
	flex: 0 0 30px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	background: none;
	color: var(--ps-blue-deep);
	font-family: inherit;
	font-size: var(--ps-t-ui);
	font-weight: 700;
	line-height: 1;
	cursor: pointer;
	transition: background var(--ps-dur-1) ease, color var(--ps-dur-1) ease;
}
.ps-mc-step-btn:hover { background: var(--ps-pale); }
.ps-mc-step-btn:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: -2px; }
.ps-mc-step b {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 30px;
	font-size: var(--ps-t-sm);
	font-weight: 700;
	color: var(--ps-navy);
	font-variant-numeric: tabular-nums;
}
/* − and + are SVG strokes, not font glyphs. As text they were U+2212 against a
   plain "+", which Aeonik draws at visibly different lengths and weights — the
   minus read as a short thin dash beside a chunky plus, and the pair looked
   broken rather than paired. Two paths sharing one stroke-width cannot drift,
   at any size or font. */
.ps-mc-step-btn .ps-bstep-minus,
.ps-mc-step-btn .ps-bstep-plus,
.ps-bundle-step-btn .ps-bstep-minus,
.ps-bundle-step-btn .ps-bstep-plus { flex: 0 0 auto; display: block; }

/* At one box the decrement removes the item, so the glyph says so first. */
.ps-mc-step .ps-bstep-trash { display: none; }
.ps-mc-step.is-qty-1 .ps-mc-step-btn[data-ps-bstep="-1"] .ps-bstep-minus { display: none; }
.ps-mc-step.is-qty-1 .ps-mc-step-btn[data-ps-bstep="-1"] .ps-bstep-trash { display: block; }
.ps-mc-step.is-qty-1 .ps-mc-step-btn[data-ps-bstep="-1"]:hover { background: var(--ps-err-bg); color: var(--ps-err); }

/* Price column starts level with the NAME, not below the stepper — the row now
   reads front-to-front: name/price on one line, spec, then the control. */
.ps-mc-money {
	position: absolute;
	top: 0.875rem;
	right: 2rem;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.125rem;
	text-align: right;
}
.ps-mc-each { font-size: var(--ps-t-2xs); color: var(--ps-soft); }

/* TIER NUDGE — forward-looking only. States what is still available and
   disappears at the top tier, so it never restates the ledger's savings. */
.ps-mc-tier {
	flex: 0 0 auto;
	margin: 0 -1.25rem;
	padding: 0.8125rem 1.25rem 0.875rem;
	background: var(--ps-wash);
	border-top: 1px solid var(--ps-line);
}
.ps-mc-tier-msg { margin: 0 0 0.5rem; font-size: var(--ps-t-xs); color: var(--ps-muted); letter-spacing: -0.01em; }
.ps-mc-tier-msg b { color: var(--ps-blue-deep); font-weight: 700; }
.ps-mc-tier-bar { height: 3px; background: var(--ps-line); overflow: hidden; }
.ps-mc-tier-bar i { display: block; height: 100%; background: var(--ps-blue); transition: width var(--ps-dur-3) var(--ps-ease); }
.ps-mc-tier-adds { display: flex; flex-wrap: wrap; gap: 0.375rem; margin-top: 0.625rem; }
.ps-mc-add {
	flex: 0 1 auto;
	min-width: 0;
	max-width: 100%;
	padding: 0.4375rem 0.625rem;
	border: 1px solid var(--ps-line-2);
	background: #fff;
	color: var(--ps-blue-deep);
	font-family: inherit;
	font-size: var(--ps-t-2xs);
	font-weight: 700;
	line-height: 1;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	cursor: pointer;
	transition: border-color var(--ps-dur-1) ease, background var(--ps-dur-1) ease, opacity var(--ps-dur-1) ease;
}
.ps-mc-add:hover { border-color: var(--ps-blue); background: var(--ps-pale); }
.ps-mc-add:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 1px; }
.ps-mc-add.is-busy { opacity: 0.5; pointer-events: none; }

/* Reassurance directly above Checkout (designer copy). */
.ps-mc-assure {
	flex: 0 0 auto;
	margin: 0.625rem 0 0;
	font-size: var(--ps-t-2xs);
	line-height: 1.45;
	color: var(--ps-soft);
	text-align: center;
}
.ps-drawer-count { color: var(--ps-muted); font-weight: 400; }

@media (prefers-reduced-motion: reduce) {
	.ps-mc-tier-bar i { transition: none; }
}
/* Actions — the site's flat, SQUARE button language (.ps-btn heritage). */
.ps-mini-cart .woocommerce-mini-cart__buttons {
	display: flex;
	flex-direction: column;
	/* The gap between the two buttons and the gap below the last one are the
	   same number on purpose — the footer reads as one measured block. */
	gap: 0.75rem;
	margin: 0;
	padding: 0.375rem 0 0.75rem;
}
.ps-mini-cart .woocommerce-mini-cart__buttons a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	padding: 0.75rem 1rem;
	font-size: var(--ps-t-ui);
	font-weight: 700;
	letter-spacing: -0.01em;
	text-decoration: none;
	border-radius: 0;
	transition: background var(--ps-dur-1) ease, color var(--ps-dur-1) ease, border-color var(--ps-dur-1) ease;
}
.ps-mini-cart .woocommerce-mini-cart__buttons .checkout {
	color: #fff;
	background: var(--ps-blue);
}
.ps-mini-cart .woocommerce-mini-cart__buttons .checkout:hover { background: var(--ps-blue-deep); }
.ps-mini-cart .woocommerce-mini-cart__buttons a:not(.checkout) {
	min-height: 44px;
	color: var(--ps-navy);
	background: var(--ps-paper);
	border: 1px solid var(--ps-line-2);
}
.ps-mini-cart .woocommerce-mini-cart__buttons a:not(.checkout):hover { color: var(--ps-ink); background: var(--ps-wash); border-color: var(--ps-navy); }

/* Phones: the drawer becomes a BOTTOM SHEET — slides up, rounded, grab handle,
   hugs its content (no dead white void), safe-area aware. */
@media (max-width: 740px) {
	.ps-drawer-panel-c {
		top: auto;
		left: 0;
		right: 0;
		bottom: 0;                   /* flush with the edge on phones too */
		width: auto;
		max-width: none;
		transform: translateY(calc(100% + 24px));
		max-height: min(84vh, 700px);
		border-radius: var(--ps-r-xl);
		box-shadow: 0 -24px 70px -16px rgba(6, 18, 30, 0.5);
		transform: translateY(calc(100% + 24px));
		padding-bottom: env(safe-area-inset-bottom, 0px);
	}
	.ps-drawer-ov.is-open .ps-drawer-panel-c { transform: none; }
	.ps-drawer-panel-c::before {
		content: "";
		position: absolute;
		top: 8px;
		left: 50%;
		transform: translateX(-50%);
		width: 42px;
		height: 4px;
		border-radius: var(--ps-r-pill);
		background: var(--ps-line-2);
	}
	.ps-drawer-panel-c .ps-overlay-head { padding-top: 1.375rem; touch-action: none; } /* head = drag zone */
	.ps-drawer-panel-c.is-dragging { transition: none; } /* sheet tracks the finger 1:1 */
}

/* ---- Search — top sheet (mobile) / centered modal (≥641px) ---- */
.ps-search-panel {
	top: 0; left: 0; right: 0;
	width: 100%;
	box-shadow: 0 24px 60px rgba(11, 25, 40, 0.18);
	transform: translateY(-14px);
	opacity: 0;
	transition: transform var(--ps-dur-2) ease, opacity var(--ps-dur-1) ease;
}
.ps-search-ov.is-open .ps-search-panel { transform: none; opacity: 1; }
.ps-search-form { position: relative; flex: 0 0 auto; padding: 1rem 1.25rem 0.75rem; }
.ps-search-ico {
	position: absolute;
	left: 2.125rem;
	top: 50%;
	transform: translateY(-50%);
	display: inline-flex;
	color: var(--ps-soft);
	pointer-events: none;
}
.ps-search-input {
	width: 100%;
	box-sizing: border-box;
	padding: 0.9375rem 1rem 0.9375rem 2.875rem;
	font-family: var(--ps-font);
	font-size: var(--ps-t-base);
	color: var(--ps-ink);
	background: var(--ps-field);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-sm);
	outline: none;
	transition: border-color var(--ps-dur-1) ease, box-shadow var(--ps-dur-1) ease;
}
.ps-search-input::placeholder { color: var(--ps-soft); }
.ps-search-input:focus { border-color: var(--ps-blue); box-shadow: var(--ps-ring); }
.ps-search-results { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 0 0.75rem; }
.ps-search-result {
	display: grid;
	grid-template-columns: 44px 1fr auto;
	align-items: center;
	gap: 0.875rem;
	padding: 0.625rem 1.25rem;
	border-top: 1px solid var(--ps-line);
	color: inherit;
	text-decoration: none;
	transition: background var(--ps-dur-1) ease;
}
.ps-search-result:hover { background: var(--ps-wash); }
.ps-search-thumb {
	width: 44px;
	height: 44px;
	object-fit: contain;
	background: var(--ps-pale);
	border: 1px solid var(--ps-line);
	border-radius: var(--ps-r-sm);
}
.ps-search-info { display: flex; flex-direction: column; gap: 0.125rem; min-width: 0; }
.ps-search-name { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); }
.ps-search-sub { font-size: var(--ps-t-sm); color: var(--ps-muted); }
.ps-search-price { font-size: var(--ps-t-base); font-weight: 500; color: var(--ps-ink); white-space: nowrap; }
.ps-search-empty { margin: 0; padding: 2rem 1.25rem; text-align: center; color: var(--ps-muted); font-size: var(--ps-t-base); }
@media (min-width: 641px) {
	.ps-search-panel {
		left: 50%;
		right: auto;
		width: min(560px, 100% - 2 * var(--ps-gutter));
		margin-top: 7vh;
		border-radius: var(--ps-r-lg);
		transform: translate(-50%, -14px);
	}
	.ps-search-ov.is-open .ps-search-panel { transform: translateX(-50%); }
	.ps-search-results { max-height: min(56vh, 520px); }
}

/* Reduced motion: overlays snap open/closed instead of sliding. */
@media (prefers-reduced-motion: reduce) {
	.ps-overlay,
	.ps-overlay-scrim,
	.ps-menu-panel,
	.ps-drawer-panel-c,
	.ps-search-panel { transition-duration: 0.001ms; }
}

/* ==========================================================================
   ADD-TO-CART TOAST — premium confirmation pill (replaces Woo's banner).
   Slides up bottom-centre when a product is added from the PDP: product
   thumbnail + draw-in check, "Added to cart" + name, and a blue "View cart"
   button that opens the drawer. Auto-dismisses on a countdown hairline that
   pauses on hover. Dark navy so it reads over any page (Figma toast concept).
   ========================================================================== */
.ps-toasts {
	position: fixed;
	left: 50%;
	bottom: max(24px, env(safe-area-inset-bottom, 0px));
	transform: translateX(-50%);
	z-index: 150;                       /* above header (100), below overlays (200) */
	display: flex;
	flex-direction: column;
	align-items: center;
	width: max-content;
	max-width: min(468px, calc(100vw - 28px));
	pointer-events: none;               /* only the pill itself is interactive */
}

.ps-toast {
	pointer-events: auto;
	position: relative;
	display: flex;
	align-items: center;
	gap: 13px;
	width: 100%;
	padding: 10px 10px 10px 12px;
	border-radius: var(--ps-r-pill);
	color: #fff;
	font-family: var(--ps-font);
	background: linear-gradient(157deg, #1b3a58 0%, #102539 48%, #0b1c2c 100%);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.09),
		inset 0 0 0 1px rgba(255, 255, 255, 0.05),
		0 24px 56px -20px rgba(6, 18, 30, 0.72),
		0 6px 18px -8px rgba(6, 18, 30, 0.55);
	opacity: 0;
	transform: translateY(16px) scale(0.965);
	transition:
		opacity var(--ps-dur-3) var(--ps-ease),
		transform var(--ps-dur-3) var(--ps-ease-spring);
	will-change: transform, opacity;
}
.ps-toast.is-in { opacity: 1; transform: translateY(0) scale(1); }
.ps-toast.is-out {
	opacity: 0;
	transform: translateY(9px) scale(0.975);
	transition-duration: var(--ps-dur-2), var(--ps-dur-2);
	transition-timing-function: ease, ease;
}

/* Thumbnail — rounded square, product image; the check badge overlays a corner. */
.ps-toast-thumb {
	position: relative;
	flex: 0 0 auto;
	width: 46px;
	height: 46px;
	border-radius: var(--ps-r-md);
	/* Light tile so a dark product render pops off the navy pill (reads as a chip). */
	background: #fff;
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2), 0 2px 7px -3px rgba(0, 0, 0, 0.45);
}
.ps-toast-thumb img {
	width: 46px;
	height: 46px;
	border-radius: var(--ps-r-md);
	object-fit: cover;
	display: block;
}
.ps-toast-thumb--empty { display: grid; place-items: center; }

/* Check badge — springs in at the thumbnail corner, then the tick draws itself. */
.ps-toast-check {
	position: absolute;
	top: -4px;
	right: -4px;
	width: 18px;
	height: 18px;
	border-radius: var(--ps-r-pill);
	background: var(--ps-blue);
	color: #fff;
	display: grid;
	place-items: center;
	/* Ring in the pill's navy so the badge separates cleanly from the white tile. */
	box-shadow: 0 0 0 2.5px #122a40, 0 4px 10px -3px rgba(0, 118, 184, 0.8);
	transform: scale(0);
	transition: transform var(--ps-dur-3) var(--ps-ease-pop) var(--ps-dur-1);
}
.ps-toast.is-in .ps-toast-check { transform: scale(1); }
.ps-toast-check svg { width: 13px; height: 13px; display: block; }
.ps-toast-check svg path {
	stroke-dasharray: 26;
	stroke-dashoffset: 26;
	transition: stroke-dashoffset var(--ps-dur-2) ease var(--ps-dur-2);
}
.ps-toast.is-in .ps-toast-check svg path { stroke-dashoffset: 0; }
.ps-toast-thumb--empty .ps-toast-check {
	position: static;
	transform: scale(1);
	box-shadow: none;
	width: 26px;
	height: 26px;
}

/* Copy — eyebrow + product name (single line, ellipsis). */
.ps-toast-text {
	display: flex;
	flex-direction: column;
	gap: 1px;
	min-width: 0;
	padding: 0 2px;
}
.ps-toast-eyebrow {
	font-size: var(--ps-t-2xs);
	font-weight: 700;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.56);
}
.ps-toast-name {
	font-size: var(--ps-t-ui);
	font-weight: 700;
	line-height: 1.25;
	color: #fff;
	max-width: 216px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* View cart — blue affordance; opens the cart drawer (data-ps-open="cart"). */
.ps-toast-view {
	flex: 0 0 auto;
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 9px 15px;
	border-radius: var(--ps-r-pill);
	background: var(--ps-blue);
	color: #fff;
	font-size: var(--ps-t-xs);
	font-weight: 700;
	text-decoration: none;
	white-space: nowrap;
	transition: background var(--ps-dur-1) ease, transform var(--ps-dur-1) ease;
}
.ps-toast-view:hover { background: var(--ps-blue-deep); }
.ps-toast-view:active { transform: scale(0.965); }
.ps-toast-view svg { transition: transform var(--ps-dur-1) ease; }
.ps-toast-view:hover svg { transform: translateX(2px); }
.ps-toast-view:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Countdown hairline — inset so its rounded ends clear the pill's corners. */
.ps-toast-progress {
	position: absolute;
	left: 16px;
	right: 16px;
	bottom: 5px;
	height: 2.5px;
	border-radius: var(--ps-r-pill);
	background: rgba(255, 255, 255, 0.85);
	opacity: 0.45;
	transform-origin: left center;
	transform: scaleX(1);
}

/* An open overlay (drawer/menu/search) supersedes the toast — fade it out. */
html.ps-overlay-open .ps-toasts {
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--ps-dur-1) ease;
}

/* PDP add-to-cart button while the AJAX request is in flight. */
.single_add_to_cart_button.ps-atc-loading { opacity: 0.72; cursor: progress; }

@media (max-width: 560px) {
	.ps-toasts { max-width: calc(100vw - 24px); }
	.ps-toast-name { max-width: 40vw; }
}

@media (prefers-reduced-motion: reduce) {
	.ps-toast {
		transition: opacity var(--ps-dur-1) ease;
		transform: none;
	}
	.ps-toast.is-in { transform: none; }
	.ps-toast.is-out { transform: none; }
	.ps-toast-check { transition: none; transform: scale(1); }
	.ps-toast-check svg path { transition: none; stroke-dashoffset: 0; }
	.ps-toast-progress { display: none; }
}

/* ==========================================================================
   ELEVATION — static, light, blurred card shadows site-wide (client call) and
   ONE shared hover motion: lift −4px + the same shadow deepened. Product cards
   keep their approved ring + image zoom on top of the shared motion.
   ========================================================================== */
/* Blog cards share the exact same motion. */
.ps-post-card { transition: transform var(--ps-dur-2) var(--ps-ease), box-shadow var(--ps-dur-2) var(--ps-ease); }
.ps-post-card:hover { transform: translateY(-4px); box-shadow: var(--ps-shadow-card-hover); }

ul.products[class*="columns-"] li.product,
.ps-wash-card,
.ps-post-card,
.ps-blog-featured,
.ps-notfound-tile,
.ps-pd-coa,
.ps-pd-coa-card,
.ps-cta-help,
.ps-cta-shop { box-shadow: var(--ps-shadow-card); }

/* ==========================================================================
   AWAKEN — homepage motion & hover life (products rail, cards, CTA band)
   ========================================================================== */

/* Products rail: the marquee sits in the SAME 1200px column as "Why choose us"
   above it (user call — no full bleed); the mask fades the cards at the column
   edges. Vertical padding gives the hover lift + drop shadow room inside the
   rail's overflow clip (otherwise the raised card's top border is cut off). */
.ps-products-section { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto var(--ps-section); }
.ps-products-head { margin-bottom: 0.5rem; }
.ps-marquee { padding: 10px 0 24px; }
/* The marquee's 24px bottom padding is hover-shadow room, not rhythm — pull the
   research disclaimer back up so it hugs the rail at the caption gap. */
@media (min-width: 741px) {
	/* Cancels .ps-marquee's 24px bottom padding (hover-lift room) so the caption
	   still hugs the rail at --ps-caption-gap. Phones drop that padding to 0, so
	   this must NOT follow them there — uncompensated it overlapped the
	   "Show all products" button by 12px. */
	.ps-products-section .ps-disclaimer { margin-top: calc(var(--ps-caption-gap) - 24px); }
}

/* Product marquee travels left→right; each card lifts, rings blue, and zooms its
   image on hover (the whole rail already pauses on hover via .ps-marquee:hover). */
.ps-marquee.is-ready .ps-marquee-track { animation-direction: reverse; }
.ps-marquee li.product {
	transition: box-shadow var(--ps-dur-2) var(--ps-ease), transform var(--ps-dur-2) var(--ps-ease);
}
.ps-marquee li.product:hover {
	box-shadow: inset 0 0 0 1.5px var(--ps-blue), var(--ps-shadow-card-hover);
	transform: translateY(-4px);
}
.ps-marquee li.product img { transition: transform var(--ps-dur-3) var(--ps-ease); }
.ps-marquee li.product:hover img { transform: scale(1.06); }

/* Wash cards (why-us / keypoints / shop values): a restrained hover lift. */
.ps-why-cards .ps-wash-card,
.ps-keypoints .ps-wash-card,
.ps-shop-values .ps-wash-card {
	transition: transform var(--ps-dur-2) var(--ps-ease), box-shadow var(--ps-dur-2) var(--ps-ease);
}
.ps-why-cards .ps-wash-card:hover,
.ps-keypoints .ps-wash-card:hover,
.ps-shop-values .ps-wash-card:hover {
	transform: translateY(-3px);
	box-shadow: var(--ps-shadow-md);
}

/* CTA band: chat bubbles pop in, staggered, once the band reveals. */
html.ps-anim .ps-cta-band .ps-chat p {
	opacity: 0;
	transform: translateY(10px) scale(0.96);
	transition: opacity var(--ps-dur-3) var(--ps-ease-spring), transform var(--ps-dur-3) var(--ps-ease-spring);
}
html.ps-anim .ps-cta-band.is-in .ps-chat p { opacity: 1; transform: none; }
html.ps-anim .ps-cta-band.is-in .ps-chat p:nth-child(1) { transition-delay: var(--ps-dur-2); }
html.ps-anim .ps-cta-band.is-in .ps-chat p:nth-child(2) { transition-delay: var(--ps-dur-3); }
html.ps-anim .ps-cta-band.is-in .ps-chat p:nth-child(3) { transition-delay: var(--ps-dur-4); }

/* CTA band micro-interactions: button lift + shop image nudge. */
.ps-cta-band .ps-btn { transition: transform var(--ps-dur-1) ease, box-shadow var(--ps-dur-1) ease, background var(--ps-dur-1) ease, color var(--ps-dur-1) ease; }
.ps-cta-band .ps-btn:hover { transform: translateY(-2px); box-shadow: 0 12px 24px -12px rgba(11, 25, 40, 0.45); }
.ps-cta-shop img { transition: transform var(--ps-dur-3) var(--ps-ease); }
.ps-cta-shop:hover img { transform: scale(1.03); }

@media (prefers-reduced-motion: reduce) {
	html.ps-anim .ps-cta-band .ps-chat p { opacity: 1 !important; transform: none !important; transition: none; }
	.ps-marquee li.product,
	.ps-marquee li.product img,
	.ps-why-cards .ps-wash-card,
	.ps-keypoints .ps-wash-card,
	.ps-shop-values .ps-wash-card,
	.ps-cta-band .ps-btn,
	.ps-cta-shop img { transition: none; }
}

/* ==========================================================================
   AWAKEN — shop catalog card hover life (mirrors the homepage rail)
   ========================================================================== */
/* Clip so the hover image-zoom stays inside the rounded card on both surfaces. */
.ps-marquee li.product,
.ps-shop-grid li.product { overflow: hidden; }

.ps-shop-grid li.product {
	transition: box-shadow var(--ps-dur-2) var(--ps-ease), transform var(--ps-dur-2) var(--ps-ease);
}
.ps-shop-grid li.product:hover {
	box-shadow: inset 0 0 0 1.5px var(--ps-blue), var(--ps-shadow-card-hover);
	transform: translateY(-4px);
}
.ps-shop-grid li.product img { transition: transform var(--ps-dur-3) var(--ps-ease); }
.ps-shop-grid li.product:hover img { transform: scale(1.05); }
.ps-shop-grid .ps-learn-more svg { transition: transform var(--ps-dur-1) ease; }
.ps-shop-grid li.product:hover .ps-learn-more svg { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
	.ps-shop-grid li.product,
	.ps-shop-grid li.product img,
	.ps-shop-grid .ps-learn-more svg { transition: none; }
}

/* ==========================================================================
   PDP MOBILE — buy dock (frosted). On phones this IS the buy experience:
   always visible from load; the in-page pack selector + cart form are hidden
   below (JS-gated so no-JS keeps the stock form and never sees the dock).
   Segmented pack control (1 SINGLE / 5 SAVE 10% / 10 SAVE 20%) + total with
   per-box equivalent + Add. Drives the real form. ≥901px hidden entirely.
   ========================================================================== */
.ps-buybar { display: none; }
@media (max-width: 900px) {
	html.ps-anim .ps-buybar {
		display: block;
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 140; /* below the add-to-cart toast (150) */
		padding: 0 12px calc(12px + env(safe-area-inset-bottom, 0px));
		pointer-events: none;
		/* Soft white apron under the card — quiets page text in the gutters and
		   the safe-area strip below the floating card. */
		background: linear-gradient(to top, rgba(255, 255, 255, 0.95) 45%, rgba(255, 255, 255, 0));
		transform: translateY(18px) scale(0.98);
		opacity: 0;
		/* No filter here, ever: any ancestor filter (even blur(0)) becomes a
		   backdrop root and silently disables the card's backdrop-filter glass. */
		transition: transform var(--ps-dur-3) var(--ps-ease-spring), opacity var(--ps-dur-2) ease;
	}
	html.ps-anim .ps-buybar.is-show { transform: none; opacity: 1; }
	.ps-buybar-card {
		pointer-events: auto;
		background: rgba(255, 255, 255, 0.92);
		-webkit-backdrop-filter: blur(20px) saturate(1.6);
		backdrop-filter: blur(20px) saturate(1.6);
		border: 1px solid var(--ps-line);
		border-radius: var(--ps-r-xl);
		box-shadow: 0 20px 48px -16px rgba(11, 25, 40, 0.32), 0 2px 8px -4px rgba(11, 25, 40, 0.16);
		padding: 12px;
		display: flex;
		flex-direction: column;
	}
	/* Identity row — collapsed while the on-page H1 is visible (the page carries
	   the name); .is-context (ps.js) slides it in once the title scrolls away. */
	.ps-buybar-top {
		display: flex;
		align-items: center;
		gap: 11px;
		max-height: 0;
		opacity: 0;
		overflow: hidden;
		margin-bottom: 0;
		transform: translateY(4px);
		transition: max-height var(--ps-dur-2) ease, opacity var(--ps-dur-2) ease, margin-bottom var(--ps-dur-2) ease, transform var(--ps-dur-2) ease;
	}
	.ps-buybar.is-context .ps-buybar-top { max-height: 52px; opacity: 1; margin-bottom: 10px; transform: none; }
	.ps-buybar-thumb {
		flex: 0 0 auto;
		width: 44px;
		height: 44px;
		border-radius: var(--ps-r-md);
		background: var(--ps-pale);
		border: 1px solid var(--ps-line);
		overflow: hidden;
	}
	.ps-buybar-thumb img { width: 100%; height: 100%; object-fit: contain; padding: 4px; }
	.ps-buybar-info { min-width: 0; flex: 1 1 auto; display: flex; flex-direction: column; gap: 2px; }
	.ps-buybar-name { font-size: var(--ps-t-base); font-weight: 700; color: var(--ps-navy); line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
	.ps-buybar-sub { font-size: var(--ps-t-2xs); color: var(--ps-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
	.ps-buybar-bottom { display: flex; align-items: stretch; gap: 9px; }

	/* Segmented pack control — one connected piece, active cell filled blue.
	   Each cell is two-line: the quantity + what it means (Single / Save 10%…). */
	.ps-buybar-seg {
		flex: 0 0 auto;
		display: flex;
		gap: 2px;
		padding: 3px;
		border: 1px solid var(--ps-line-2);
		border-radius: var(--ps-r-lg);
		background: #fff;
	}
	.ps-buybar-opt {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 1px;
		min-width: 56px;
		padding: 5px 8px;
		border: 0;
		border-radius: var(--ps-r-md);
		background: transparent;
		font-family: var(--ps-font);
		cursor: pointer;
		transition: background var(--ps-dur-1) ease, box-shadow var(--ps-dur-1) ease;
	}
	.ps-buybar-opt b { font-size: var(--ps-t-base); font-weight: 700; line-height: 1; color: var(--ps-navy); font-variant-numeric: tabular-nums; }
	.ps-buybar-opt small { font-size: 8.5px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ps-muted); white-space: nowrap; }
	.ps-buybar-opt:hover b { color: var(--ps-blue); }
	.ps-buybar-opt.is-active { background: var(--ps-blue); box-shadow: 0 3px 10px -3px rgba(0, 118, 184, 0.55); }
	.ps-buybar-opt.is-active b { color: #fff; }
	.ps-buybar-opt.is-active small { color: rgba(255, 255, 255, 0.82); }
	.ps-buybar-opt.is-active:hover b { color: #fff; }

	.ps-buybar-add {
		flex: 1 1 auto;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		gap: 7px;
		min-height: 48px;
		padding: 0 12px;
		background: var(--ps-blue);
		color: #fff;
		border: 0;
		border-radius: var(--ps-r-lg);
		font-family: var(--ps-font);
		font-size: var(--ps-t-base);
		font-weight: 700;
		white-space: nowrap;
		font-variant-numeric: tabular-nums;
		cursor: pointer;
		transition: background var(--ps-dur-1) ease, transform var(--ps-dur-1) ease;
	}
	.ps-buybar-add:hover { background: var(--ps-blue-deep); }
	.ps-buybar-add:active { transform: scale(0.98); }
	.ps-buybar-add svg { flex: 0 0 auto; }

	/* The dock replaces the in-page buy controls on phones (no duplication).
	   JS-gated: without JS the stock form stays usable and the dock never shows.
	   The bundle strip (meter + rail) STAYS — it's the mix story, not a buy
	   control; the dock remains the only add path for this product. */
	html.ps-anim .ps-pdp .ps-pack,
	html.ps-anim .ps-pdp form.cart { display: none !important; }
	/* Bundle strip, phone fit: tighter rhythm, slightly smaller cards. */
	.ps-bundle { margin-top: var(--ps-sp-5); padding-top: var(--ps-sp-4); }
	.ps-bundle-card { flex-basis: 112px; }
	.ps-bundle-thumb { height: 80px; }
	/* Gallery trust chips — clutter at phone width. */
	/* Trust chips stay on phones (Figma mobile) — centered under the plate. */
	/* Content + the toast clear the always-on dock; its height is measured into
	   --ps-dock-h by ps.js (fallback ≈ two-row dock). */
	html.ps-anim body.single-product { padding-bottom: calc(var(--ps-dock-h, 128px) + 30px + env(safe-area-inset-bottom, 0px)); }
	html.ps-anim body.single-product .ps-toasts { bottom: calc(var(--ps-dock-h, 128px) + 26px + env(safe-area-inset-bottom, 0px)); }
}

@media (prefers-reduced-motion: reduce) {
	html.ps-anim .ps-buybar { transition: opacity var(--ps-dur-1) ease; transform: none; }
	html.ps-anim .ps-buybar.is-show { transform: none; }
	.ps-buybar-top { transition: none; transform: none; }
	.ps-buybar-opt, .ps-buybar-add { transition: none; }
}

/* PDP title block on phones — name owns its line; the second line reads
   price (left, the number people scan for) with availability tucked right.
   Declared last so it wins the base titlerow rules. */
@media (max-width: 900px) {
	.ps-pd-head {
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-areas: "title title" "price badge" "spec spec";
		row-gap: 0.375rem;
	}
	.ps-pd-price { justify-self: start; }
	.ps-pd-price b { font-size: 1.5rem; }
	.ps-pd-spec { font-size: var(--ps-t-xs); }
}

/* ============ Mobile buy experience v2 (Ridge pass) ============ */
@media (max-width: 900px) {
	/* Header: ONE axis — badge alone, name, price. CAS moves to the science
	   grid (reference data lives with reference data). */
	/* (Header lockup + spec line are defined in the TYPE SYSTEM block above —
	   the old stacked override lived here and has been removed.) */

	/* Trust chips: abbreviated, one row, never wraps, no triangle. */
	.ps-trust-full { display: none; }
	.ps-trust-abbr { display: inline; }
	/* Chips are relocated below the bundle module by ps.js on phones. The margin
	   keeps their top edge BELOW the dock's top at 390×844 — a partially visible
	   row peeking out from behind the dock reads as broken. */
	.ps-pd-trust { flex-wrap: nowrap; gap: 0.375rem; margin-top: var(--ps-flow); justify-content: center; }
	.ps-pd-trust li { font-size: var(--ps-t-2xs); letter-spacing: 0.06em; padding: 0.375rem 0.5rem; }

	/* ==================================================================
	   TYPE SYSTEM (mobile buy-box) — six steps, every one a token.
	   The mess this replaces: 12 distinct sizes, three below 11px, plus a
	   13.333px UA button default nobody authored. Rules: no literal px font
	   sizes here, nothing under 11px, nothing inherits a UA size.
	     title 19/700 · price 17/700 · body 15/1.5 · data 13/700
	     meta 12/600  · micro 11/700 caps
	   ================================================================== */
	.ps-pd-crumb { font-size: var(--ps-t-xs); color: var(--ps-muted); }
	.ps-pdp .summary .product_title { font-size: var(--ps-t-lg); line-height: 1.18; letter-spacing: -0.02em; }
	.ps-pd-price { font-size: var(--ps-t-2xs); }
	.ps-pd-price b { font-size: var(--ps-t-md); }
	.ps-pd-spec { font-size: var(--ps-t-xs); }
	.ps-pd-desc { font-size: var(--ps-t-base); line-height: 1.5; }
	.ps-pd-stock { font-size: var(--ps-t-2xs); }
	.ps-pd-trust li { font-size: var(--ps-t-2xs); }
	.ps-bundle-eyebrow, .ps-bundle-flag { font-size: var(--ps-t-2xs); }
	.ps-bundle-name { font-size: var(--ps-t-xs); }
	.ps-bundle-price { font-size: var(--ps-t-sm); }
	.ps-bundle-add, .ps-bundle-toggle { font-size: var(--ps-t-xs); }
	.ps-bundle-step b { font-size: var(--ps-t-xs); }
	.ps-pd-coa-txt { font-size: var(--ps-t-xs); }
	.ps-buybar-meter-txt { font-size: var(--ps-t-2xs); }
	/* .ps-buybar-opt inherited the UA button default (13.333px) — pin both rows. */
	.ps-buybar-opt { font-size: var(--ps-t-xs); }
	.ps-buybar-opt b { font-size: var(--ps-t-base); }
	.ps-buybar-add { font-size: var(--ps-t-base); }

	/* HEADER LOCKUP: name left, availability + price right — the desktop grid,
	   restored on phones (it was being flattened into four stacked lines). */
	.ps-pd-head {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		grid-template-areas: "title badge" "spec price";
		align-items: center;
		column-gap: 0.75rem;
		row-gap: 0.375rem;
	}
	.ps-pd-head .ps-pd-stock { justify-self: end; align-self: start; margin-top: 0.125rem; }
	.ps-pd-spec { display: block; grid-area: spec; }
	.ps-pd-price { grid-area: price; justify-self: end; align-self: start; }

	/* DESCRIPTION: never clamped. It is the one block on a PDP that has to be
	   readable, so it is not traded for fold budget (client call 2026-07-31). */
	.ps-pd-desc-more {
		display: inline-flex;
		align-items: center;
		gap: 0.25rem;
		margin-top: 0.375rem;
		padding: 0;
		border: 0;
		background: none;
		cursor: pointer;
		font-family: inherit;
		font-size: var(--ps-t-xs);
		font-weight: 600;
		color: var(--ps-blue-deep);
	}
	.ps-pd-desc-more[hidden] { display: none; }
	.ps-pd-desc-more:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 2px; }
	.ps-pd-desc-chev { transition: transform var(--ps-dur-1) var(--ps-ease); }
	.ps-pd-descwrap.is-open .ps-pd-desc-chev { transform: rotate(180deg); }

	/* Bundle module on phones: a 3-up grid of full tiles (name, art, price,
	   control) — the first three compounds visible, the rest expanding in
	   place. The dock carries the meter. */
	html.ps-anim .ps-pdp .ps-bundle .ps-ordermeter { display: none; }
	.ps-bundle { padding: var(--ps-sp-3) var(--ps-sp-3) 0.5rem; }
	.ps-bundle-head { margin-bottom: 0.375rem; }
	.ps-bundle-rail { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--ps-sp-2); margin-top: 0; overflow: visible; }
	.ps-bundle { margin-top: 0.5rem; }
	.ps-bundle-card { flex: none; min-width: 0; }
	html.ps-anim .ps-bundle:not(.is-expanded) .ps-bundle-card:nth-child(n + 4) { display: none; }
	.ps-bundle-thumb { height: 50px; order: 2; }
	/* Tablets get taller art — 50px stamps drown in ~460px-wide tiles. */
	@media (min-width: 741px) { .ps-bundle-thumb { height: 96px; } }
	/* Tile reading order (client call): NAME → art → price → control. Reordered in
	   CSS, not markup, so desktop keeps art-first. The name reserves two lines so
	   art and prices share baselines across all six tiles regardless of length. */
	.ps-bundle-name {
		display: grid;
		align-content: end;      /* short names hug the art; slack sits above */
		order: 1;
		margin: 0 0 0.3125rem;
		line-height: 1.25;
		min-height: 2.5em;       /* 2 lines reserved → art aligns across the row */
		max-height: 2.5em;
		overflow: hidden;        /* replaces -webkit-line-clamp (not a flex/grid item) */
		font-weight: 600;
		color: var(--ps-navy);
	}
	.ps-bundle-price { order: 3; margin-top: 0.3125rem; line-height: 1.2; font-weight: 700; color: var(--ps-navy); }
	.ps-bundle-add, .ps-bundle-step { order: 4; margin-top: 0.25rem; height: 28px; }
	.ps-bundle-step-btn { flex-basis: 28px; }
	.ps-bundle-step b { order: 0; }

	/* ONE CONTROL, ON A FOOTER RAIL. The sticky header pill is gone: expanded,
	   this module is ~340px — well under a screen — so an escape hatch that
	   follows you solved nothing and cost a second control. The button now says
	   what the NEXT tap does ("Show all 6 compounds" ⇄ "Show less"), because
	   "Show all" stops being true the moment all of them are shown.

	   Narrow on a full-width hairline rail: narrow so it reads as secondary
	   against three "+ Add"s and the dock's Add CTA; on a rail so it anchors to
	   the module's bottom edge instead of floating loose inside it. */
	html.ps-anim .ps-bundle-foot {
		display: flex;
		justify-content: center;
		margin-top: 0.5rem;
		padding-top: 0.5rem;
		border-top: 1px solid var(--ps-line);
	}
	.ps-bundle-toggle[hidden] { display: none !important; }
	html.ps-anim .ps-bundle-toggle {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		gap: 0.375rem;
		width: auto;
		height: 28px;
		margin: 0;
		padding: 0 0.875rem;
		border: 1px solid var(--ps-line-2);
		border-radius: var(--ps-r-xs);
		background: #fff;
		cursor: pointer;
		font-family: inherit;
		font-size: var(--ps-t-2xs);
		font-weight: 600;
		letter-spacing: 0.01em;
		color: var(--ps-blue-deep);
		transition: border-color var(--ps-dur-1) var(--ps-ease), background var(--ps-dur-1) var(--ps-ease);
	}
	html.ps-anim .ps-bundle-toggle:hover { border-color: var(--ps-blue); background: var(--ps-pale); }
	html.ps-anim .ps-bundle-toggle:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 1px; }
	/* One control that toggles ⇒ the chevron turns with it (the old pair each
	   shipped a fixed chevron because neither ever reversed). */
	.ps-btoggle-chev { flex: 0 0 auto; transition: transform var(--ps-dur-2) var(--ps-ease-enter); }
	.ps-bundle.is-expanded .ps-btoggle-chev { transform: rotate(180deg); }

	/* The revealed tiles fade up behind the opening height. A bare height tween
	   reads as a shutter going up; the stagger reads as the list unfolding.
	   .is-revealing is transient (ps.js clears it on settle) so a cart-fragment
	   refresh never replays the entrance. */
	.ps-bundle.is-revealing .ps-bundle-card:nth-child(n + 4) {
		animation: ps-tile-in var(--ps-dur-3) var(--ps-ease-enter) both;
	}
	.ps-bundle.is-revealing .ps-bundle-card:nth-child(4) { animation-delay: 0.03s; }
	.ps-bundle.is-revealing .ps-bundle-card:nth-child(5) { animation-delay: 0.075s; }
	.ps-bundle.is-revealing .ps-bundle-card:nth-child(6) { animation-delay: 0.12s; }

	/* Dock filament: hairline progress + one micro line above the controls. */
	.ps-buybar-meter { display: block; padding: 0.5rem 0.125rem 0.4375rem; }
	.ps-buybar-meter-bar { display: block; position: relative; height: 2px; background: var(--ps-line); margin-bottom: 0.375rem; }
	.ps-buybar-meter-bar i { display: block; height: 100%; max-width: 100%; background: var(--ps-blue); transition: width var(--ps-dur-2) var(--ps-ease); }
	.ps-buybar-meter-txt { display: block; font-size: var(--ps-t-2xs); font-weight: 600; color: var(--ps-muted); letter-spacing: 0.02em; }
	.ps-buybar-meter.is-active .ps-buybar-meter-txt { color: var(--ps-blue-deep); }
}
@media (prefers-reduced-motion: reduce) {
	.ps-buybar-meter-bar i { transition: none; }
}
/* Desktop never shows the dock (or its meter). */
@media (min-width: 901px) {
	.ps-buybar-meter { display: none; }
}

/* ============ Why choose us v2 (Arham Figma 1640-1462) ============
   Three technical-evidence cards on a soft radial wash: annotated strip
   schematic / mini-COA chart / hot-cold stability art. Square corners
   (rectangle doctrine), quiet hairline cards, Figma copy verbatim. */
.ps-why2 { position: relative; }
.ps-why2::before {
	content: "";
	position: absolute;
	/* No negative side insets — they leaked 15px past the mobile viewport and
	   put a horizontal wobble on the whole page. The glow stays inside. */
	inset: 10% 0 0;
	background: radial-gradient(70% 70% at 50% 45%, rgba(0, 118, 184, 0.07), rgba(0, 118, 184, 0) 70%);
	pointer-events: none;
}
.ps-why2-grid {
	position: relative;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--ps-gap-grid);
	margin-top: var(--ps-sp-4);
}
/* Slim horizontal tiles: claim on the left, artefact bleeding off the right.
   The tall centred cards were ~380px of mostly empty card; this states the same
   three facts in a third of the height. */
.ps-why2-card {
	position: relative;
	overflow: hidden;
	min-height: 104px;
	display: flex;
	align-items: center;
	padding: 1.125rem 1.25rem;
	background: linear-gradient(180deg, #fff 0%, var(--ps-wash) 100%);
	border: 1px solid var(--ps-line);
	transition: border-color var(--ps-dur-2) var(--ps-ease), box-shadow var(--ps-dur-2) var(--ps-ease);
}
.ps-why2-card:hover { border-color: var(--ps-line-2); box-shadow: var(--ps-shadow-sm); }
.ps-why2-copy { position: relative; z-index: 1; max-width: 62%; }
.ps-why2-card h3 {
	margin: 0 0 0.3125rem;
	font-size: var(--ps-t-md);
	font-weight: 500;
	line-height: 1.2;
	color: var(--ps-navy);
	letter-spacing: -0.01em;
}
.ps-why2-card p {
	margin: 0;
	font-size: var(--ps-t-sm);
	line-height: 1.45;
	color: var(--ps-muted);
}
/* Art is decorative and bleeds off the right edge, cropped by the tile. Each
   piece is framed individually — one shared box would letterbox all three.
   The Figma artwork (1640:1513) is upright product illustration with legible
   callout labels, unlike the abstract helix/gauge it replaces, so the rotation
   is gone: tilting a labelled diagram reads as a mistake, not a flourish. Tile
   geometry and copy positions are untouched — this is art framing only. */
.ps-why2-art {
	position: absolute;
	right: -18px;
	top: 50%;
	width: auto;
	height: 132px;
	transform: translateY(-50%);
	opacity: 0.95;
	pointer-events: none;
	/* Horizontal fade, not the old vertical one. The new copy is a full
	   sentence rather than two clipped fragments, so it reaches further across
	   the tile and the artwork's left edge now sits under it. Fading the art in
	   from the left lets the two occupy the same band without a collision —
	   the alternative (shrinking the art until it clears the longest line)
	   leaves a stamp too small to read at any breakpoint. */
	-webkit-mask-image: linear-gradient(90deg, transparent 0, rgba(0, 0, 0, 0.55) 30%, #000 58%);
	mask-image: linear-gradient(90deg, transparent 0, rgba(0, 0, 0, 0.55) 30%, #000 58%);
}
/* Per-artwork placement (client review 2026-07-31). A more negative `right`
   slides the piece further off the tile's right edge, which both moves it away
   from the copy and crops more of its own right side — so each value is the
   point where the subject still reads whole. */
/* FENCED to >=741px on purpose. These are placement values for the slim
   horizontal tile — absolute offsets and a vertical nudge — and they are
   meaningless once the phone carousel stacks the art above centred copy.
   Unfenced, `.ps-why2-art.is-america` (0,2,0) out-specified the carousel's
   `.ps-why2-art { transform: none }` (0,1,0) and dragged the factory 72px
   above the card, clipping the flag off the top. Media-query order does not
   save you from a specificity loss; scoping does. */
@media (min-width: 741px) {
	/* The strip diagram carries three callout labels; nudged right only as far
	   as "Quick Dissolving" allows, since clipping a label mid-word is worse
	   than a little extra overlap. */
	.ps-why2-art.is-precision { height: 116px; right: -13px; }
	/* Moved right the most and dropped slightly: the factory sat too far into
	   the copy and rode high against the tile's optical centre. The artwork's
	   right fifth is empty canvas, so it takes the largest shift without
	   losing the flag. */
	.ps-why2-art.is-america   { height: 130px; right: -60px; transform: translateY(calc(-50% + 7px)); }
	/* Widest ambient glow of the three; pushed out so the pouch rather than
	   the haze occupies the visible sliver. */
	.ps-why2-art.is-stable    { height: 148px; right: -40px; }
}

/* Dots are a phone-only affordance — at ≥741px all three tiles are on screen
   at once, so a position indicator would be indicating nothing. */
.ps-why2-dots { display: none; }

/* ==========================================================================
   THE PEPTIDE STRIPS STANDARD — phone carousel (Figma 1640:2073 / 2217:1625)
   --------------------------------------------------------------------------
   Phones get square-ish tiles swiped one at a time, art above centred copy,
   with a three-square position indicator underneath. Desktop is untouched:
   ≥741px keeps the slim horizontal grid with art bleeding off the right.

   Geometry is lifted from the mobile frame at its 390px reference width:
     card   350 × 306      art box  y 18 → 188 (170 tall)
     gap    20             copy     y 208, 290 wide
     dots   6×6 active / 4×4 idle, 2px apart, 8px below the card
   Native scroll-snap does the swiping — no JS drag handling, no library, and
   momentum/rubber-banding stay the platform's own.
   ========================================================================== */
@media (max-width: 740px) {
	.ps-why2-grid {
		display: flex;
		grid-template-columns: none;
		gap: var(--ps-gap-grid);
		margin-top: var(--ps-sp-4);
		overflow-x: auto;
		/* Both axes stated. `overflow-x: auto` alone leaves overflow-y computing
		   to auto (CSS forbids one axis being visible while the other scrolls),
		   which made the track scrollable VERTICALLY by 14px — the exact
		   translateY of an unrevealed .ps-reveal card. The tile could be dragged
		   up and down until it settled. One axis only. */
		overflow-y: hidden;
		/* And the same rule for touch: a finger may pan this track sideways,
		   never up and down. */
		touch-action: pan-x;
		scroll-snap-type: x mandatory;
		/* Keep a horizontal swipe from becoming a browser back-gesture or a
		   page-level scroll chain at the ends of the track. */
		overscroll-behavior-x: contain;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}
	/* Slides must NOT be individually reveal-gated. They live in a horizontal
	   scroller, so cards 2 and 3 sit outside the viewport and the scroll
	   observer never fires for them — "Made in America" stayed at opacity 0
	   even after you swiped to it. The section as a whole still reveals; its
	   slides are simply present. This is also what removed the 14px of vertical
	   overflow above. */
	html.ps-anim .ps-why2-grid .ps-why2-card.ps-reveal {
		opacity: 1;
		transform: none;
	}
	.ps-why2-grid::-webkit-scrollbar { display: none; }

	.ps-why2-card {
		flex: 0 0 100%;
		scroll-snap-align: center;
		/* Without this a fast flick can skate past a slide and land on the
		   third — the indicator would then jump two steps for one gesture. */
		scroll-snap-stop: always;
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
		text-align: center;
		min-height: 306px;
		/* 17/29, not the Figma's 18/30. The tile carries a 1px border and the
		   theme is border-box, so the frame's own stroke eats a pixel at each
		   edge: 1 + 17 + 170 + 20 + 68 + 29 + 1 = 306 exactly, and the art then
		   starts at y18 and the copy at y208 as drawn. Using 18/30 verbatim
		   double-counts the border and the tile lands at 308. */
		padding: 17px 0 29px;
		/* Flat, and exactly the colour baked behind the artwork — the tile's
		   desktop white→wash gradient would make that opaque backdrop read as a
		   pale rectangle floating inside the card. Same trick the Figma uses. */
		background: var(--ps-art-bg);
		/* Cards stretch to the tallest of the three (default align-items on the
		   flex track), so the indicator never shifts between slides. */
	}
	/* Copy metrics come straight off the Figma frame: title 24px tall, 4px to
	   the body, body two lines at 20px = a 68px block. That is what closes the
	   arithmetic: 18 + 170 art + 20 + 68 + 30 = the 306px card. Guessed
	   line-heights put it at 311 and the whole tile drifted off-spec. */
	.ps-why2-copy { order: 2; max-width: none; padding: 0 30px; }
	.ps-why2-card h3 { font-size: var(--ps-t-lg); line-height: 1.25; margin-bottom: 4px; }
	.ps-why2-card p  { font-size: var(--ps-t-base); line-height: 1.3333; }

	/* Art rejoins the flow: on phones it is the subject of the tile, not a
	   decorative bleed, so no absolute positioning, no crop, no fade. */
	.ps-why2-art {
		position: static;
		order: 1;
		height: 170px;
		width: auto;
		max-width: 92%;
		margin: 0 0 20px;
		object-fit: contain;
		transform: none;
		opacity: 1;
		-webkit-mask-image: none;
		mask-image: none;
	}
	/* Per-artwork heights from the Figma frames (314.83×170 / 290×158 /
	   233×165); each keeps its own scale so the three read as one set rather
	   than three arbitrarily-zoomed stamps. */
	.ps-why2-art.is-precision { height: 170px; right: auto; max-width: 100%; }
	.ps-why2-art.is-america   { height: 158px; right: auto; }
	.ps-why2-art.is-stable    { height: 165px; right: auto; }

	.ps-why2-dots {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 2px;
		/* 8px is the gap Figma puts between the card edge and the MARK, but the
		   buttons carry 10px of invisible hit padding above the mark — so the
		   row itself starts 2px higher. Measure the mark, not the box. */
		margin-top: -2px;
	}
	/* The Figma marks sit 2px apart — a tight cluster, not a spread row — and
	   6px/4px squares are far below any usable touch target. So the mark is
	   drawn by ::before while the button carries an invisible hit area: 2px of
	   horizontal padding preserves the cluster (2px gap + 2 + 2 = 6px between
	   marks at the widest), and 10px of vertical padding gives a 26px-tall
	   target. Swiping is the primary interaction here; the squares are an
	   indicator that also happens to be tappable. */
	.ps-why2-dot {
		appearance: none;
		border: 0;
		background: none;
		padding: 10px 2px;
		margin: 0;
		cursor: pointer;
		line-height: 0;
		display: block;
	}
	.ps-why2-dot::before {
		content: "";
		display: block;
		width: 4px;
		height: 4px;
		background: var(--ps-chip);
		transition: width var(--ps-dur-2) var(--ps-ease-enter),
		            height var(--ps-dur-2) var(--ps-ease-enter),
		            background-color var(--ps-dur-2) var(--ps-ease-enter);
	}
	.ps-why2-dot.is-active::before { width: 6px; height: 6px; background: var(--ps-blue); }
	.ps-why2-dot:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: -4px; }
}
@media (max-width: 740px) and (prefers-reduced-motion: reduce) {
	.ps-why2-dot::before { transition: none; }
}

/* Tablet band ONLY. This used to be `max-width: 900px`, but it now sits after
   the phone carousel block above, so at ≤740px its min-height:96px and the 66%
   copy clamp were winning and flattening the slides. Phones = carousel,
   741–900 = the stacked slim tiles, ≥901 = the three-across grid. */
@media (min-width: 741px) and (max-width: 900px) {
	.ps-why2-grid { grid-template-columns: 1fr; }
	.ps-why2-card { min-height: 96px; }
	.ps-why2-copy { max-width: 66%; }
}

/* ============ Mobile buy fold budget + header lockup ============ */
@media (max-width: 900px) {
	/* Header lockup: tight, managed — badge micro, name+price close-set. */
	.ps-pd-head { row-gap: 0.3125rem; }
	.ps-pd-head .ps-pd-stock { font-size: var(--ps-t-2xs); padding: 0.25rem 0.5rem; }
	.ps-pdp .summary .product_title { font-size: var(--ps-t-lg); line-height: 1.18; }
	.ps-pd-price b { font-size: var(--ps-t-md); }
	.ps-pd-price { font-size: var(--ps-t-2xs); }
	/* Fold budget: 2-line blurb, slimmer plate, snug module — the goal is
	   plate → header → blurb → bundle module all visible, a breath of air,
	   then the dock. The COA card lives below the fold, never peeking. */
	/* Deterministic containment: percentage max-height vs an aspect-ratio box
	   resolves as NO constraint in some engines — the render spilled over the
	   chips on real devices. Hard px cap + overflow guard. */
	.ps-pdp .woocommerce-product-gallery__wrapper {
		height: clamp(100px, 19svh, 180px);   /* svh: immune to browser-chrome resize */
		aspect-ratio: auto;
		padding: 0.75rem;
		overflow: hidden;
	}
	.ps-pd-crumb { margin-top: 0.75rem; margin-bottom: 0.75rem; }
	.ps-bundle { margin-top: 0.5rem; }
	/* Plain rhythm. The 3.75rem here used to hold the COA card below the fold
	   while the description was clamped; the description is full now, the fold
	   budget is gone with it, and a spacer whose only job was to hide something
	   just reads as a hole. */
	html.ps-anim body.single-product .ps-pd-coa { margin-top: var(--ps-flow); }
}

/* Mobile cart sheet: the bundle-tier row made the navy band fat — the dock
   filament + bundle module own that story on phones now. */
@media (max-width: 740px) {
}

/* ==========================================================================
   HOME PRODUCTS — phones get a 2x2 grid of the range instead of an
   auto-scrolling rail you cannot survey. Four visible, the rest expands in
   place, and the collapse control HOVERS over the page while the expanded
   grid is on screen so you can fold it away without scrolling back.
   ≥741px is untouched: the marquee still animates.
   ========================================================================== */
/* The footer rail is nothing without its control: desktop shows all six
   tiles, so there is no disclosure there and the bare hairline + padding
   rendered as a stray line under the grid. */
.ps-bundle-foot { display: none; }
.ps-products-more { display: none; }
.ps-products-collapse { display: none; }
@media (max-width: 740px) {
	.ps-marquee {
		overflow: visible;
		-webkit-mask-image: none;
		mask-image: none;
		padding: 0;
	}
	.ps-marquee-track,
	.ps-marquee.is-ready .ps-marquee-track { display: block; width: auto; animation: none; }
	/* The rail duplicates the loop for a seamless scroll — a grid must not. */
	.ps-marquee-group[aria-hidden="true"] { display: none; }
	.ps-marquee-group { display: block; padding-right: 0; }
	.ps-marquee ul.products[class*="columns-"] {
		display: grid !important;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--ps-gap-grid);
		width: auto;
	}
	.ps-marquee li.product { width: auto !important; min-height: 0; }
	.ps-marquee ul.products[class*="columns-"] li.product img { height: 128px; max-width: 82%; }
	html.ps-anim .ps-products-section:not(.is-expanded) .ps-marquee li.product:nth-child(n + 5) { display: none; }

	html.ps-anim .ps-products-more {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 0.375rem;
		width: 100%;
		height: 40px;
		margin-top: var(--ps-sp-3);
		border: 1px solid var(--ps-line-2);
		background: #fff;
		cursor: pointer;
		font-family: inherit;
		font-size: var(--ps-t-xs);
		font-weight: 600;
		color: var(--ps-blue-deep);
		transition: border-color var(--ps-dur-1) ease, background var(--ps-dur-1) ease;
	}
	html.ps-anim .ps-products-more:hover { border-color: var(--ps-blue); background: var(--ps-pale); }
	html.ps-anim .ps-products-more:focus-visible { outline: 2px solid var(--ps-blue); outline-offset: 2px; }
	html.ps-anim .ps-products-section.is-expanded .ps-products-more { display: none; }

	/* Identical entrance to the PDP bundle — same keyframe, same curve, same
	   stagger step. Two disclosures on one site must not move differently. */
	.ps-products-section.is-revealing .ps-marquee li.product:nth-child(n + 5) {
		animation: ps-tile-in var(--ps-dur-3) var(--ps-ease-enter) both;
	}
	.ps-products-section.is-revealing .ps-marquee li.product:nth-child(5) { animation-delay: 0.03s; }
	.ps-products-section.is-revealing .ps-marquee li.product:nth-child(6) { animation-delay: 0.075s; }
	.ps-products-section.is-revealing .ps-marquee li.product:nth-child(7) { animation-delay: 0.12s; }

	/* The hovering collapse: floats above the page, only while the expanded grid
	   is actually in view (ps.js observes it), so it never shadows other content. */
	html.ps-anim .ps-products-collapse {
		position: fixed;
		left: 50%;
		bottom: calc(18px + env(safe-area-inset-bottom, 0px));
		z-index: 130;
		display: inline-flex;
		align-items: center;
		gap: 0.375rem;
		height: 38px;
		padding: 0 1rem;
		border: 1px solid rgba(255, 255, 255, 0.14);
		background: rgba(16, 37, 57, 0.94);
		-webkit-backdrop-filter: blur(14px) saturate(1.4);
		backdrop-filter: blur(14px) saturate(1.4);
		box-shadow: 0 16px 36px -12px rgba(6, 18, 30, 0.6);
		color: #fff;
		font-family: inherit;
		font-size: var(--ps-t-xs);
		font-weight: 700;
		cursor: pointer;
		opacity: 0;
		transform: translate(-50%, 14px);
		pointer-events: none;
		transition: opacity var(--ps-dur-2) ease, transform var(--ps-dur-2) var(--ps-ease-spring);
	}
	html.ps-anim .ps-products-collapse.is-show {
		opacity: 1;
		transform: translate(-50%, 0);
		pointer-events: auto;
	}
	html.ps-anim .ps-products-collapse:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
}
@media (max-width: 740px) and (prefers-reduced-motion: reduce) {
	html.ps-anim .ps-products-collapse { transition: opacity var(--ps-dur-1) ease; transform: translate(-50%, 0); }
}
@media (prefers-reduced-motion: reduce) {
	/* psDisclose already skips the height tween; kill the tile entrance too. */
	.ps-bundle.is-revealing .ps-bundle-card,
	.ps-products-section.is-revealing .ps-marquee li.product { animation: none !important; }
	.ps-btoggle-chev { transition: none; }
}

/* Catalog type chips reuse the COA component; only the rhythm differs. */
.ps-shop-tabs { width: min(var(--ps-col), 100% - 2 * var(--ps-gutter)); margin: 0 auto var(--ps-flow); flex-wrap: wrap; }
