/*
Theme Name:   Owsa Labs
Theme URI:    https://github.com/dsampson-oss/supplement-store
Description:  Clinical, trust-forward child theme for a UK research peptide store. Built on Kadence (classic/hybrid parent). Research-use framing only.
Author:       Owsa Labs
Author URI:   https://owsa-labs.com
Template:     kadence
Version:      0.11.0
Requires at least: 6.4
Requires PHP: 8.0
Text Domain:  owsa
License:      GNU General Public License v2 or later
License URI:  https://www.gnu.org/licenses/gpl-2.0.html

Implements DESIGN.md. Every value resolves to a token in assets/css/tokens.css —
no raw colours or sizes below, so the brand re-skins from that one file.

The organising idea, taken from the reference: structure is carried by whitespace
and hairlines, not by cards, borders and shadows. Square corners throughout, with
the ghost button's pill as the single deliberate exception.
*/

/* ── Base ────────────────────────────────────────────────────────────────── */
body {
	font-family: var(--font-body);
	color: var(--text);
	background: var(--ground);
	font-size: var(--fs-body);
	line-height: var(--lh-body);
	-webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4,
.owsa-sec-title {
	font-family: var(--font-display);
	font-weight: 800;
	letter-spacing: var(--tracking-display);
	line-height: var(--lh-tight);
	color: var(--text);
	text-wrap: balance;
}

h3, .owsa-sec-title { font-weight: 700; letter-spacing: -0.01em; }

a {
	color: var(--link);
	text-decoration: underline;
	text-underline-offset: 0.2em;
	text-decoration-thickness: 1px;
}
a:hover { color: var(--brand-ink); }
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* Mono uppercase label — the one place the design allows personality. It reads as
   specification, which is the whole positioning. `display: block` also matters: the
   compliance panels render it inline before a value, and without it the label and
   value run together. */
.owsa-eyebrow {
	display: block;
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--brand-teal-ink);
	margin-bottom: var(--sp-3);
}

/* ── Home hero ───────────────────────────────────────────────────────────── */
body.home .entry-hero.page-hero-section { display: none; }

/* Was a centred block over a stock sky photograph behind a white scrim. The sky
   was decorative atmosphere, which DESIGN.md §1 rules out, and it made the one
   screen that has to establish credibility look like a wellness brand. The
   specimens do that job instead: product photography on white is documentary, it
   is the actual thing being sold, and it needs no scrim to stay readable. */
.owsa-home-hero {
	background: var(--ground);
	padding-block: clamp(3rem, 8vw, 6rem);
	border-bottom: 1px solid var(--rule);
}

.owsa-hero-grid { align-items: center; gap: clamp(2rem, 6vw, 5rem); }

/* Left-aligned, per DESIGN.md §5. These plain margin rules only work because the
   copy sits inside .owsa-hero-copy, a flow-layout group — see the note above the
   heredoc in patterns/home-hero.php. Directly inside the constrained section,
   core's `margin-inline: auto !important` would centre anything with a max-width. */
.owsa-home-hero { text-align: left; }
.owsa-home-hero .owsa-eyebrow { margin-bottom: var(--sp-6); }
.owsa-home-hero h1 {
	max-width: 20ch;
	margin-inline: 0;
	margin-bottom: var(--sp-6);
}
.owsa-hero-lead {
	max-width: 52ch;
	margin-block: 0;
	margin-inline: 0;
}
.owsa-home-hero .wp-block-buttons { gap: var(--sp-3); margin-top: var(--sp-8); }

/* Media panel.
   hero-vials.jpg is the vials-only export: specimens on white, no brand lockup and
   no baked-in headline. That matters — the page carries its headline as live text,
   and a second one burnt into the raster would neither reflow nor scale, and would
   sit competing beside the h1.

   aspect-ratio matches the source exactly (1792x1008), so nothing is cropped and
   the space is reserved before the image loads — no layout shift, without width
   and height attributes that would fight the CSS. `contain` rather than `cover` is
   belt and braces: swap in artwork of a different shape and it letterboxes onto
   the white ground instead of silently slicing the vials.

   If you ever point this at a composite with text in it, set --owsa-hero-focus to
   the horizontal centre of the part worth showing and switch object-fit to cover. */
.owsa-hero-media {
	--owsa-hero-focus: 50%;
	margin: 0;
}
.owsa-hero-media img {
	display: block;
	width: 100%;
	aspect-ratio: 1792 / 1008;
	object-fit: contain;
	object-position: var(--owsa-hero-focus) 50%;
	border-radius: 0;
	background: var(--ground);
}

/* Core stacks the columns at 781px. */
@media (max-width: 781px) {
	.owsa-home-hero h1 { max-width: 18ch; }
}

/* ── Trust bar ───────────────────────────────────────────────────────────── */
/* Four claims in a row, marked up as the list they are. The tick characters that
   used to open each line are gone: as text content a screen reader announces
   "check mark" before every item, four times over, and DESIGN.md §1 rules out
   badge clutter. The marker is now a cyan rule, matching .owsa-tag — decorative,
   silent to assistive tech, and already part of the vocabulary. */
.owsa-trustbar {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--sp-4) var(--sp-8);
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	letter-spacing: 0.02em;
}
.owsa-trustbar li {
	margin: 0;
	display: flex;
	align-items: center;
	gap: var(--sp-3);
}
.owsa-trustbar li::before {
	content: "";
	flex: none;
	inline-size: 0.875rem;
	block-size: 2px;
	background: var(--brand-teal);
}

/* ── Section furniture ───────────────────────────────────────────────────── */
.owsa-section-lead { max-width: 58ch; }
.owsa-section-cta { margin-top: var(--sp-12); }

/* ── Contact form ────────────────────────────────────────────────────────── */
/* Hairlines and square corners, like everything else. Inputs get a visible
   border rather than a filled box: a form is a datasheet you write into. */
.owsa-field { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-6); }
.owsa-field label { font-size: 0.9375rem; font-weight: 600; }
.owsa-field input,
.owsa-field select,
.owsa-field textarea {
	font-family: var(--font-body);
	font-size: 1rem;
	color: var(--text);
	background: var(--ground);
	border: var(--bw) solid var(--rule-strong);
	border-radius: 0;
	padding: 0.7rem 0.85rem;
	width: 100%;
	/* 16px minimum, or iOS Safari zooms the viewport on focus and never zooms back. */
	min-height: 44px;
}
.owsa-field textarea { min-height: 11rem; resize: vertical; }
.owsa-field input:focus-visible,
.owsa-field select:focus-visible,
.owsa-field textarea:focus-visible {
	outline: 2px solid var(--focus-ring);
	outline-offset: 2px;
	border-color: var(--brand-ink);
}
.owsa-field-help { font-size: var(--fs-small); color: var(--text-muted); }
.owsa-field-actions { margin: var(--sp-8) 0 var(--sp-4); }
.owsa-field-legal { font-size: var(--fs-small); color: var(--text-muted); max-width: 60ch; }

/* The honeypot. Off-screen rather than display:none — some bots skip hidden
   fields, and this one needs to look fillable to anything reading the DOM. It
   carries aria-hidden and tabindex="-1", so nobody using the page ever meets it. */
.owsa-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.owsa-form-notice {
	padding: var(--sp-4);
	border-left: 3px solid var(--rule-strong);
	background: var(--ground-alt);
	margin-bottom: var(--sp-6);
	font-size: 0.9375rem;
}
.owsa-form-ok { border-left-color: var(--c-success); }
.owsa-form-error { border-left-color: var(--c-danger); }

/* ── Buttons ─────────────────────────────────────────────────────────────── */
/* Unscoped from .owsa-home-hero deliberately. These used to apply only inside the
   hero, so any block button placed anywhere else on the site fell back to the
   WordPress default and quietly broke the system. A button is a button. */
.owsa-btn,
.wp-block-button__link,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce .single_add_to_cart_button {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-2);
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 0.9375rem;
	text-decoration: none;
	padding: 0.9rem 1.75rem;
	border-radius: var(--radius);
	border: var(--bw) solid var(--brand-ink);
	background: var(--brand-ink);
	color: var(--brand-white);
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
		border-color var(--dur) var(--ease);
}

.owsa-btn:hover,
.wp-block-button:not(.is-style-outline) .wp-block-button__link:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce .single_add_to_cart_button:hover {
	background: var(--brand-teal-deep);
	border-color: var(--brand-teal-deep);
	color: var(--brand-white);
}

.owsa-btn:focus-visible,
.woocommerce a.button:focus-visible,
.woocommerce button.button:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; }

/* Keep the base fill on :focus. Kadence styles `button:hover, button:focus,
   button:active` with its own palette, and the previous override only covered
   :hover — so any focused button turned Kadence blue. Most visible on the entry
   gate, where the confirm button takes focus on load and was the first thing
   anyone saw. The outline above is the focus indicator; the fill should not move. */
.owsa-btn:focus,
.wp-block-button:not(.is-style-outline) .wp-block-button__link:focus,
.woocommerce a.button:focus,
.woocommerce button.button:focus,
.woocommerce .single_add_to_cart_button:focus {
	background: var(--brand-ink);
	border-color: var(--brand-ink);
	color: var(--brand-white);
}
.owsa-btn-ghost:focus,
.is-style-outline .wp-block-button__link:focus {
	background: transparent;
	color: var(--brand-ink);
	border-color: var(--rule-strong);
}

.owsa-btn[disabled],
.woocommerce button.button[disabled] {
	background: var(--brand-ink-lt);
	border-color: transparent;
	cursor: not-allowed;
}

/* The single pill in the system. */
.owsa-btn-ghost,
.is-style-outline .wp-block-button__link {
	background: transparent;
	color: var(--brand-ink);
	border-color: var(--rule-strong);
	border-radius: var(--radius-pill);
}
.owsa-btn-ghost:hover,
.is-style-outline .wp-block-button__link:hover {
	background: var(--brand-ink);
	color: var(--brand-white);
	border-color: var(--brand-ink);
}
.owsa-btn-ghost[disabled] { color: var(--brand-ink-lt); border-color: var(--rule); }

/* ── Trust bar ───────────────────────────────────────────────────────────── */
.owsa-trust-bar {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-6);
	justify-content: center;
	align-items: center;
	background: var(--surface-inverse);
	color: var(--text-on-inverse);
	padding: var(--sp-3) var(--gutter);
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	letter-spacing: 0.04em;
}
.owsa-trust-bar span { display: inline-flex; align-items: center; gap: var(--sp-2); }
.owsa-trust-bar .dot { color: var(--brand-teal); }

/* ── Category marker ─────────────────────────────────────────────────────── */
/* No pill badges anywhere. Category reads as a 3px cyan rule, echoing the accent
   bar already printed on the product vial labels. */
.owsa-tag {
	display: inline-block;
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
	border-top: 3px solid var(--brand-teal);
	padding-top: var(--sp-2);
}

/* ── Product grid — no card ──────────────────────────────────────────────── */
.woocommerce ul.products li.product {
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	padding: 0;
	text-align: left;
}
.woocommerce ul.products li.product img {
	background: var(--ground);
	border-radius: 0;
	margin-bottom: var(--sp-4);
	transition: opacity var(--dur) var(--ease);
}
.woocommerce ul.products li.product a:hover img { opacity: 0.88; }
.woocommerce ul.products li.product .woocommerce-loop-product__title {
	font-family: var(--font-body);
	font-size: 1rem;
	font-weight: 500;
	letter-spacing: normal;
	margin: 0 0 var(--sp-1);
}
.woocommerce ul.products li.product .price {
	color: var(--text-muted);
	font-weight: 500;
	font-size: 1rem;
}
.woocommerce ul.products li.product a:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }

/* Grid tiles carry image, name and price only — the purchase decision belongs on
   the product page, beside the specification and the certificate. The loop
   add-to-cart is also unhooked in functions.php; this is the visual belt to that
   braces, in case a template renders it another way. */
.woocommerce ul.products li.product .button,
.woocommerce ul.products li.product .added_to_cart { display: none; }

/* ── Product grid, BLOCK rendering ───────────────────────────────────────── */
/* The homepage pattern uses WooCommerce blocks, not the classic loop, so none of
   the rules above reach it and neither does the functions.php unhook — the block
   emits its own markup and its own button. Left unstyled it rendered as one giant
   image per row with a default-blue "Add to cart", which is how it shipped in the
   first pass of this redesign. */
.wc-block-product-template,
.wp-block-woocommerce-product-template {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	gap: var(--sp-8);
	list-style: none;
	margin: 0;
	padding: 0;
}

.wc-block-product,
.wc-block-grid__product {
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	padding: 0;
	text-align: left;
}

.wc-block-components-product-image img,
.wc-block-grid__product-image img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: 0;
	background: var(--ground);
	transition: opacity var(--dur) var(--ease);
}
.wc-block-components-product-image a:hover img { opacity: 0.88; }
.wc-block-components-product-image a:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }

.wc-block-components-product-price,
.wc-block-grid__product-price {
	color: var(--text-muted);
	font-weight: 500;
	font-size: 1rem;
}

/* Same rule as the classic grid: no purchase control on a thumbnail.
   Specificity note: WooCommerce sets display:flex through a two-class selector
   (.wp-block-button.wc-block-components-product-button), so a single-class rule
   here loses and the button stays visible — which is exactly what happened on the
   first attempt. Three classes wins it cleanly, without !important. */
.wp-block-button.wc-block-components-product-button.wp-block-woocommerce-product-button,
.wc-block-grid__product-add-to-cart { display: none; }

/* ── Category list block ─────────────────────────────────────────────────── */
/* Two classes, for the third time in this file: WooCommerce indents the list from
   a compound selector, so a single-class `padding: 0` lost and the list sat 32px
   right of the heading above it. Measured, not assumed. */
.wc-block-product-categories .wc-block-product-categories-list,
.wc-block-product-categories-list { list-style: none; margin: 0; padding-left: 0; }
.wc-block-product-categories-list-item { border-bottom: var(--bw) solid var(--rule); }
.wc-block-product-categories-list-item a {
	display: block;
	padding: var(--sp-4) 0;
	text-decoration: none;
	color: var(--text);
	font-size: 1rem;
}
.wc-block-product-categories-list-item a:hover { color: var(--brand-teal-ink); }
/* Two classes: the placeholder carries a modifier class and WooCommerce styles it
   through a compound selector, so a single-class rule loses — the same specificity
   trap as the product button. These render as broken-image icons and carry no
   information; the category name is the link. */
.wc-block-product-categories-list-item .wc-block-product-categories-list-item__image,
.wc-block-product-categories-list-item__image--placeholder { display: none; }

/* ── Compliance panels — hairlines, not cards ────────────────────────────── */
.owsa-panels {
	display: grid;
	gap: 0;
	max-width: var(--content-max);
	margin: var(--sp-16) auto;
	padding: 0 var(--gutter);
}
.owsa-panel {
	background: none;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	padding: var(--sp-8) 0;
	border-top: var(--bw) solid var(--rule);
}
.owsa-panel:last-child { border-bottom: var(--bw) solid var(--rule); }
.owsa-panel.owsa-mandatory { background: none; }
.owsa-sec-title { font-size: var(--fs-h4); margin: 0 0 var(--sp-4); }
.owsa-panel-sub { color: var(--text-muted); font-size: var(--fs-small); margin-bottom: var(--sp-4); }

/* Specification table — mono keys, hairline rows. A datasheet is more credible
   than the same figures in a rounded grey card. */
.owsa-facts { width: 100%; border-collapse: collapse; font-size: 0.9375rem; }
.owsa-facts th[scope="col"] {
	text-align: left;
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
	border-bottom: 2px solid var(--rule-strong);
	padding: var(--sp-2) 0;
}
.owsa-facts th[scope="row"] {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
	font-weight: 500;
	text-align: left;
	width: 12rem;
	vertical-align: top;
	padding: var(--sp-3) 0;
	border-bottom: var(--bw) solid var(--rule);
}
.owsa-facts td {
	padding: var(--sp-3) 0;
	border-bottom: var(--bw) solid var(--rule);
	text-align: left;
	font-weight: 400;
}
.owsa-facts-note, .owsa-na { color: var(--text-muted); font-size: var(--fs-small); }
.owsa-facts-note { margin-top: var(--sp-4); }

/* Ingredients + allergen emphasis */
.owsa-ingredient-list { line-height: 1.7; }
.owsa-allergen { font-weight: 700; }
.owsa-allergen-contains {
	margin-top: var(--sp-3);
	padding: var(--sp-3) 0 var(--sp-3) var(--sp-4);
	background: none;
	border-left: 3px solid var(--c-warning);
	border-radius: 0;
}
.owsa-free-from {
	margin-top: var(--sp-3);
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	color: var(--brand-teal-ink);
}

/* Certificate of analysis */
.owsa-coa .owsa-eyebrow { color: var(--c-success); }
.owsa-coa .owsa-btn-ghost { margin-top: var(--sp-4); }

/* Mandatory statements */
.owsa-mandatory-list {
	list-style: none;
	padding: 0;
	margin: 0 0 var(--sp-4);
	display: grid;
	gap: var(--sp-2);
}
.owsa-mandatory-list li {
	padding-left: 1.4rem;
	position: relative;
	color: var(--text-muted);
	font-size: var(--fs-small);
}
.owsa-mandatory-list li::before {
	content: "§";
	position: absolute;
	left: 0;
	color: var(--brand-teal-ink);
	font-family: var(--font-mono);
}
.owsa-warning-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--sp-2); }
.owsa-warning {
	padding: var(--sp-3) 0 var(--sp-3) var(--sp-4);
	background: none;
	border: 0;
	border-left: 3px solid var(--c-warning);
	border-radius: 0;
	color: var(--c-warning);
	font-weight: 500;
	font-size: var(--fs-small);
}

/* In-summary vial contents + handling */
.owsa-dosing {
	margin: var(--sp-6) 0;
	padding: var(--sp-4) 0;
	background: none;
	border-top: var(--bw) solid var(--rule);
	border-bottom: var(--bw) solid var(--rule);
	border-radius: 0;
}
.owsa-serving { font-weight: 600; }
.owsa-do-not-exceed {
	margin-top: var(--sp-2);
	font-size: var(--fs-small);
	color: var(--text-muted);
	font-family: var(--font-mono);
	letter-spacing: 0.03em;
}

/* ── Research disclaimer band ────────────────────────────────────────────── */
.owsa-research-notice {
	background: var(--surface-inverse);
	color: var(--text-on-inverse);
	padding: var(--sp-3) var(--sp-4);
	text-align: center;
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	letter-spacing: 0.03em;
}

/* ── Sticky mobile add-to-cart ───────────────────────────────────────────── */
/* A hairline, not a shadow — the only place elevation would otherwise creep back. */
.owsa-sticky-atc {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: var(--z-sticky-atc);
	display: none;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-4);
	padding: var(--sp-3) var(--gutter);
	background: var(--ground);
	border-top: var(--bw) solid var(--rule-strong);
	box-shadow: none;
}
.owsa-sticky-atc .price { font-family: var(--font-display); font-weight: 800; font-size: 1.1rem; }
.owsa-sticky-atc .owsa-btn { flex: 0 0 auto; }
@media (max-width: 767px) {
	body.single-product .owsa-sticky-atc { display: flex; }
	body.single-product { padding-bottom: 76px; }
	.owsa-facts th[scope="row"] { width: auto; display: block; border-bottom: 0; padding-bottom: 0; }
	.owsa-facts td { display: block; padding-top: var(--sp-1); }
}

/* ── Entrance (L1) ───────────────────────────────────────────────────────── */
/* One soft fade on load. No scroll-driven motion anywhere — see DESIGN.md §7. */
@keyframes owsa-fade-in {
	from { opacity: 0; transform: translateY(6px); }
	to   { opacity: 1; transform: none; }
}
main > * { animation: owsa-fade-in 380ms var(--ease) both; }
main > *:nth-child(2) { animation-delay: 60ms; }
main > *:nth-child(3) { animation-delay: 120ms; }

@media (prefers-reduced-motion: reduce) {
	main > * { animation: none; }
}

/* ── Certificates of Analysis index ──────────────────────────────────────── */
.owsa-coa-table { margin-top: var(--sp-6); }
.owsa-coa-table th[scope="col"] { white-space: nowrap; }
.owsa-coa-table td { vertical-align: top; }
.owsa-coa-sku { font-family: var(--font-mono); font-size: var(--fs-small); color: var(--text-muted); }
/* Pending is stated plainly, not styled as an alarm — it is the honest default
   until a batch has been tested, not an error condition. */
.owsa-coa-pending {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
}
.owsa-coa-index { overflow-x: auto; }

/* ── Search in the primary navigation ────────────────────────────────────── */
.owsa-menu-search { display: flex; align-items: center; }
.owsa-menu-search form { display: flex; align-items: center; gap: var(--sp-2); margin: 0; }
.owsa-menu-search .search-field,
.owsa-menu-search input[type="search"] {
	font-family: var(--font-body);
	font-size: 0.875rem;
	padding: 0.5rem 0.75rem;
	border: var(--bw) solid var(--rule-strong);
	border-radius: 0;
	background: var(--ground);
	color: var(--text);
	min-width: 12rem;
}
.owsa-menu-search input[type="search"]::placeholder { color: var(--text-muted); }
.owsa-menu-search input[type="search"]:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* The magnifier is the affordance; the submit button is redundant chrome next to it
   and would be the only other pill in a system that allows exactly one. */
.owsa-menu-search button[type="submit"],
.owsa-menu-search input[type="submit"] {
	font-family: var(--font-body);
	font-size: 0.8125rem;
	font-weight: 600;
	padding: 0.5rem 0.9rem;
	border: var(--bw) solid var(--brand-ink);
	border-radius: 0;
	background: var(--brand-ink);
	color: var(--brand-white);
	cursor: pointer;
}
.owsa-menu-search button[type="submit"]:hover,
.owsa-menu-search input[type="submit"]:hover { background: var(--brand-teal-deep); border-color: var(--brand-teal-deep); }

@media (max-width: 900px) {
	.owsa-menu-search { width: 100%; padding: var(--sp-3) 0; }
	.owsa-menu-search .search-field,
	.owsa-menu-search input[type="search"] { min-width: 0; flex: 1; }
}

/* ── Trade application form ──────────────────────────────────────────────── */
/* Grouped fields. A long single-column form reads as an obstacle; four short
   labelled groups read as a short one, which matters when the whole point is that
   people complete it honestly rather than abandon it. */
.owsa-fieldset {
	border: 0;
	border-top: var(--bw) solid var(--rule);
	margin: 0 0 var(--sp-8);
	padding: var(--sp-6) 0 0;
}
.owsa-fieldset legend {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--brand-teal-ink);
	padding: 0 var(--sp-3) 0 0;
}

/* Two fields per row on desktop, stacking below the columns breakpoint. */
.owsa-field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--sp-6); }
@media (max-width: 600px) {
	.owsa-field-row { grid-template-columns: 1fr; }
}

/* The declaration. Checkbox beside its label rather than above it, and the label
   stays normal weight — this is a sentence to read, not a field name to scan. */
.owsa-field-check {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--sp-3);
	align-items: start;
}
.owsa-field-check input[type="checkbox"] {
	width: 1.15rem;
	height: 1.15rem;
	min-height: 0;
	margin-top: 0.2rem;
	accent-color: var(--brand-ink);
}
.owsa-field-check label {
	font-weight: 400;
	font-size: 0.9375rem;
	line-height: 1.5;
}

/* ── Directory listing badge ─────────────────────────────────────────────── */
/* Sits above the research-use bar, on the page ground rather than the dark band,
   so a light-theme badge is not floated on near-black. width/height are on the
   img itself, so the space is reserved and the footer does not shift when a
   third-party image arrives late — or never, if their server is slow. */
.owsa-directory-badge {
	background: var(--ground);
	border-top: var(--bw) solid var(--rule);
	padding: var(--sp-6) var(--gutter);
	text-align: center;
}
.owsa-directory-badge img {
	display: inline-block;
	max-width: 100%;
	height: auto;
	border: 0;
}
.owsa-directory-badge a:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 4px; }

/* ── Entry gate ──────────────────────────────────────────────────────────── */
/* Covers the page rather than replacing it: the content underneath still renders,
   so search engines and anything without JavaScript see the site as normal. The
   scrim is opaque enough that the catalogue is not browsable behind it. */
.owsa-gate {
	position: fixed;
	inset: 0;
	z-index: var(--z-modal);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--sp-6);
	background: rgba(11, 13, 18, 0.92);
	overflow-y: auto;
}
.owsa-gate-panel {
	background: var(--ground);
	border: var(--bw) solid var(--rule-strong);
	border-radius: 0;
	padding: clamp(var(--sp-8), 5vw, var(--sp-16));
	max-width: 34rem;
	width: 100%;
	margin: auto;
}
.owsa-gate-panel h2 {
	font-size: var(--fs-h3);
	margin: 0 0 var(--sp-6);
	max-width: 22ch;
}
.owsa-gate-panel > p { margin-bottom: var(--sp-6); }

/* The three confirmations. Marked with the cyan rule used elsewhere for spec
   markers rather than ticks, which screen readers would announce three times. */
.owsa-gate-terms {
	list-style: none;
	margin: 0 0 var(--sp-8);
	padding: 0;
	border-top: var(--bw) solid var(--rule);
}
.owsa-gate-terms li {
	display: flex;
	align-items: baseline;
	gap: var(--sp-3);
	padding: var(--sp-3) 0;
	border-bottom: var(--bw) solid var(--rule);
	font-size: 0.9375rem;
}
.owsa-gate-terms li::before {
	content: "";
	flex: none;
	inline-size: 0.875rem;
	block-size: 2px;
	background: var(--brand-teal);
	transform: translateY(-0.3em);
}

.owsa-gate-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-3);
	align-items: center;
}
.owsa-gate-note {
	font-size: var(--fs-small);
	color: var(--text-muted);
	margin: var(--sp-6) 0 0;
}

@media (max-width: 480px) {
	.owsa-gate { padding: 0; }
	.owsa-gate-panel { border: 0; min-height: 100%; display: flex; flex-direction: column; justify-content: center; }
	.owsa-gate-actions .owsa-btn { width: 100%; justify-content: center; }
}

/* Set in <head> before paint when the acknowledgement cookie is present, so a
   returning visitor never sees the overlay flash on a cached page. */
.owsa-ack .owsa-gate { display: none !important; }

/* ── Included-with-every-order line ──────────────────────────────────────── */
/* A supporting fact, not a sale flash. It uses the same mono uppercase treatment as
   .owsa-eyebrow because that is what this design already uses for specification —
   the reading is "here is another documented detail", which is the positioning.
   Deliberately not the teal accent: the accent marks things that are interactive,
   and colouring a static claim with it would be the first place that stops being
   true. Muted ink, one size down, and it earns its attention from position alone. */
.owsa-freebie {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
	margin: var(--sp-2) 0 0;
	line-height: var(--lh-tight);
}

/* On the single product page it sits under a much larger price, so it needs a little
   more room above it than it does in a grid cell. */
.single-product .owsa-freebie { margin-top: var(--sp-3); }

/* ── Header cart ─────────────────────────────────────────────────────────── */
/* The control is Kadence's own element, so nearly all of its appearance is inherited
   and nothing here restyles it. These rules cover the two things the theme leaves at
   its defaults and this design does differently: the focus ring, and a count bubble
   that has to read against the header rather than against Kadence's palette. */
.header-cart-button:focus-visible {
	outline: 2px solid var(--focus-ring);
	outline-offset: 3px;
}

.header-cart-total {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	background: var(--brand-ink);
	color: var(--brand-white);
	border-radius: var(--radius-sm);
}

/* The server always renders this empty — the real count arrives from cart fragments
   after load, because a count baked into a cached page belongs to whoever was served
   first. Hiding the empty state stops a returning visitor seeing a bubble appear and
   then blank itself on every page. */
.header-cart-total.header-cart-is-empty-true,
.header-cart-total:empty {
	display: none;
}

/* ── Offer surfaces (Task 11) ────────────────────────────────────────────────── */
/* Ported from offer-surfaces.html. The structure, proportions and hairline grid are
   the reference's; every colour and face here is this theme's, because the reference
   states in its own header that its tokens are inferred from the vial label rather
   than lifted from source. Shipping its blue would have put a second accent into a
   design built on one, and the teal already carries that job everywhere else. */

.owsa-ico { flex: none; }

/* 1 · Announcement bar — above the header, every page. */
.owsa-bar {
	background: var(--surface-inverse);
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 46px;
	padding: 0 var(--sp-4);
}
.owsa-bar__list {
	display: flex;
	align-items: center;
	gap: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}
.owsa-bar__item {
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	padding: 0 var(--sp-6);
	margin: 0;
	color: var(--text-on-inverse);
	font-size: var(--fs-small);
	font-weight: 500;
	line-height: 1.3;
}
/* The icon takes the accent; the text stays legible on the dark ground. */
.owsa-bar__item .owsa-ico { color: var(--brand-teal); }
.owsa-bar__item + .owsa-bar__item { border-left: var(--bw) solid var(--border-inverse); }

/* Narrow screens rotate one promise at a time. The rotating list is aria-hidden and
   the full set is repeated in .screen-reader-text, so hiding two of three costs
   nothing to a screen reader — display:none removes an element from the
   accessibility tree as well as the layout. */
@media (max-width: 860px) {
	.owsa-bar__item + .owsa-bar__item { border-left: 0; }
	.owsa-bar__item { display: none; padding: 0; }
	.owsa-bar__item.is-active { display: flex; }
}

/* 2 · Shop and category banner — above the product grid. */
.owsa-banner {
	border: var(--bw) solid var(--rule);
	background: var(--surface);
	padding: var(--sp-8);
	display: flex;
	align-items: center;
	gap: var(--sp-12);
	flex-wrap: wrap;
	margin-bottom: var(--sp-8);
}
.owsa-banner__lede { flex: 1 1 240px; min-width: 240px; max-width: 300px; }
.owsa-banner__eyebrow {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--brand-teal-ink);
	margin: 0 0 var(--sp-3);
}
.owsa-banner__title {
	font-family: var(--font-display);
	font-size: var(--fs-h4);
	line-height: var(--lh-tight);
	letter-spacing: var(--tracking-display);
	margin: 0;
	text-wrap: balance;
}
.owsa-banner__sub {
	color: var(--text-muted);
	font-size: var(--fs-small);
	line-height: var(--lh-body);
	margin: var(--sp-3) 0 0;
}
/* A one-pixel gap over a rule ground draws the grid lines without four borders
   meeting and doubling up — the same hairline logic the panels use. */
.owsa-banner__rungs {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--bw);
	background: var(--rule);
	border: var(--bw) solid var(--rule);
	flex: 1 1 420px;
	min-width: 280px;
}
.owsa-rung {
	background: var(--surface);
	padding: var(--sp-4) var(--sp-6);
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
	color: var(--brand-teal-ink);
}
.owsa-rung__when {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	color: var(--brand-teal-ink);
}
.owsa-rung__what {
	font-size: var(--fs-small);
	line-height: var(--lh-body);
	color: var(--text);
}
@media (max-width: 700px) {
	.owsa-banner__rungs { grid-template-columns: 1fr; }
}

/* 3 · Product page block — under the add-to-cart form. */
.owsa-offers {
	border: var(--bw) solid var(--rule);
	background: var(--surface);
	margin: var(--sp-6) 0;
}
.owsa-offers__head {
	padding: var(--sp-4) var(--sp-5);
	border-bottom: var(--bw) solid var(--rule);
	display: flex;
	align-items: center;
	gap: var(--sp-3);
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--brand-teal-ink);
}
.owsa-offers__row {
	display: flex;
	align-items: baseline;
	gap: var(--sp-4);
	padding: var(--sp-3) var(--sp-5);
	border-bottom: var(--bw) solid var(--border);
}
.owsa-offers__row:last-child { border-bottom: 0; }
.owsa-offers__when {
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	color: var(--brand-teal-ink);
	inline-size: 4.2rem;
	flex: none;
}
.owsa-offers__what { font-size: var(--fs-small); color: var(--text); }

.owsa-vol { border: var(--bw) solid var(--rule); margin: var(--sp-4) 0 0; }
.owsa-vol__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--bw);
	background: var(--rule);
}
.owsa-vol__cell { background: var(--surface); padding: var(--sp-4) var(--sp-3); text-align: center; }
.owsa-vol__cell--best { background: var(--surface-sunken); }
.owsa-vol__qty { font-family: var(--font-mono); font-size: var(--fs-h4); font-weight: 500; }
.owsa-vol__unit {
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
	margin-top: var(--sp-1);
}
.owsa-vol__off {
	font-family: var(--font-mono);
	font-size: var(--fs-small);
	color: var(--brand-teal-ink);
	margin-top: var(--sp-2);
}

/* 4 · Cart reward progress — hydrated client-side, never server-rendered. */
.owsa-reward {
	border: var(--bw) solid var(--rule);
	padding: var(--sp-4);
	display: flex;
	flex-direction: column;
	gap: var(--sp-3);
}
.owsa-reward + .owsa-reward { margin-top: var(--sp-3); }
.owsa-rewards:not(:empty) { margin-bottom: var(--sp-8); }
.owsa-reward__line {
	display: flex;
	align-items: baseline;
	gap: var(--sp-2);
	font-size: var(--fs-small);
	color: var(--text-muted);
	margin: 0;
}
.owsa-reward__amt { font-family: var(--font-mono); font-weight: 500; color: var(--text); }
.owsa-reward__track { block-size: 4px; background: var(--surface-sunken); }
.owsa-reward__fill { block-size: 4px; background: var(--brand-teal-ink); transition: width var(--dur) var(--ease); }
.owsa-reward__meta {
	display: flex;
	justify-content: space-between;
	font-family: var(--font-mono);
	font-size: var(--fs-eyebrow);
	letter-spacing: var(--tracking-eyebrow);
	text-transform: uppercase;
	color: var(--text-muted);
}
.owsa-reward--done {
	border-color: var(--brand-teal-ink);
	background: var(--brand-teal-dim);
}
.owsa-reward__met {
	display: flex;
	align-items: center;
	gap: var(--sp-2);
	font-size: var(--fs-small);
	font-weight: 500;
	color: var(--brand-teal-ink);
}
@media (prefers-reduced-motion: reduce) {
	.owsa-reward__fill { transition: none; }
}
