/*
Theme Name: WOW Merid
Theme URI: https://wows.com.my/
Author: WOW Supplies
Author URI: https://wows.com.my/
Description: Standalone WordPress theme for wows.com.my (WOW Supplies), built from the v2 HTML mockup. Replaces the generatepress-child theme, which stays installed as the rollback target.
Version: 0.1.0
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 8.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: wow-merid
Tags: e-commerce, custom-menu, translation-ready
WC requires at least: 8.0
WC tested up to: 9.9
*/

/* ============================================================
   TABLE OF CONTENTS
   ------------------------------------------------------------
   1.  Design tokens (:root)
   2.  Reset & base
   3.  Typography
   4.  Layout & containers
   5.  Header
   6.  Navigation
   7.  Footer
   8.  Buttons & forms
   9.  Components — marketing & content blocks
   9b. Scroll reveal
   10. WooCommerce — shop / archive
   11. WooCommerce — product card
   12. WooCommerce — single product
   13. WooCommerce — cart & checkout
   14. Content compatibility (wows-* classes from v1 page content)
   15. Utilities
   16. Accessibility
   17. Responsive
   ============================================================ */


/* ============================================================
   1. DESIGN TOKENS
   ------------------------------------------------------------
   Extracted from _mockup/ and approved by Eddy, 14 Aug 2026.
   Precedence rule set that session: the mockup wins on anything
   visual (palette, fonts, scale); INSTRUCTIONS.md / PORTING-MAP.md
   win on code and naming. So this palette fully replaces v1's
   #0073aa / #00838f / #e67e22 set, and the fonts replace Poppins
   and Courier Prime — but the --wows- prefix rule still stands.

   No raw hex anywhere else in this file or in css/*.css.
   ============================================================ */

:root {

	/* --- Colour: core ------------------------------------- */
	--wows-ink: #121723;             /* headings, body, dark bands, utility bar */
	--wows-accent: #3A35A0;          /* primary — from the logo's royal blue */
	--wows-accent-dark: #2A2680;     /* hover / pressed, gradient end */
	--wows-accent-tint: #EBEAF7;     /* icon chips, badges, selected rows */
	--wows-accent-tint-2: #F5F4FC;   /* selected payment row, highlighted card */
	--wows-white: #FFFFFF;
	--wows-footer: #0E121B;

	/* --- Colour: text ------------------------------------- */
	--wows-text: #4A5363;            /* paragraphs */
	--wows-text-muted: #6B7384;      /* sub-labels, captions */
	--wows-text-faint: #8A92A1;      /* placeholders, breadcrumb, meta */
	--wows-on-dark: #C7CCD6;         /* text on --wows-ink */
	--wows-on-dark-faint: #9AA2B1;   /* footer text */

	/*
	 * Text sitting directly on a photo, not on a flat surface. Darker than
	 * --wows-text because a photo's worst pixel, not its average, sets the
	 * contrast — and the homepage hero's scrim is deliberately translucent
	 * (Eddy, 18 Aug 2026) so the room shows through.
	 *
	 * Measured on the home hero at the shipped 68% scrim: --wows-text gave the
	 * lede 3.47:1 and --wows-text-muted gave the stat labels 4.16:1, both
	 * **failing** AA's 4.5:1 for body text. This value takes them to 5.05:1 and
	 * 9.86:1.
	 *
	 * Sample at 1px when you re-measure. A 4px step reported the H1 at 7.39:1
	 * when the true worst is 5.70:1 — the dark spot it was stepping over is
	 * only a few pixels across. Coarse sampling flatters; it never warns.
	 *
	 * If the hero photo is ever swapped, re-measure rather than assuming this
	 * still clears — the binding constraint is one dark region behind the lede,
	 * and a different photo moves it.
	 */
	--wows-text-on-photo: #333B49;   /* body copy over an image */

	/*
	 * Left edge of the centred container, in viewport pixels.
	 *
	 * Every photo hero in this theme lays a white ramp over the image and puts
	 * ink copy on the light end. The ramp's stops were originally measured from
	 * the **viewport**, but the copy sits in a container that is centred — so
	 * as the window widens the copy slides right and walks out from under its
	 * own scrim. Measured on 18 Aug 2026 at 1920px and 2560px: the Contact lede
	 * hit 1.03:1, the category-hero lede 1.00:1, About 1.50:1. Invisible text,
	 * on pages that looked perfect at 1440.
	 *
	 * Adding this offset to every stop makes the ramp travel with the copy, so
	 * the relationship holds at any width. `max()` pins it to 0 once the
	 * viewport is narrower than the container, which is the gutter's job.
	 *
	 * Used by: the home hero (style.css), About, Contact, Repair, and the nine
	 * category heroes + Services (css/category-heroes.css). **Any new photo
	 * hero must use it too** — a bare px stop is the bug.
	 */
	--wows-scrim-x: max(0px, (100vw - var(--wows-container)) / 2);

	/* --- Colour: borders ---------------------------------- */
	/* All are --wows-ink at opacity; keep them in step if ink changes. */
	--wows-border: rgba(18, 23, 35, 0.10);        /* default hairline */
	--wows-border-strong: rgba(18, 23, 35, 0.16); /* inputs, emphasis */
	--wows-border-soft: rgba(18, 23, 35, 0.08);   /* header + section dividers */
	--wows-border-hover: rgba(18, 23, 35, 0.18);  /* card hover */

	/* --- Colour: chrome ----------------------------------- */
	--wows-header-bg: rgba(255, 255, 255, 0.88);   /* sticky header, over blur */
	--wows-header-blur: 12px;
	--wows-border-on-dark: rgba(255, 255, 255, 0.08); /* footer bar divider */

	/* --- Colour: surfaces --------------------------------- */
	--wows-surface: #F6F7F9;         /* image wells */
	--wows-surface-2: #F8F9FB;       /* table header rows */
	--wows-search: #F3F5F8;          /* header search pill */
	--wows-row-hover: #FAFAFC;       /* cart row hover */
	--wows-divider: #EEF0F6;         /* light rule */

	/* --- Colour: semantic --------------------------------- */
	--wows-success: #3DBE6B;         /* status dot, WhatsApp buttons */
	--wows-success-text: #2A7D46;
	--wows-success-bg: #E7F7ED;
	--wows-success-on-dark: #6FE39A; /* WhatsApp number in the utility bar */
	--wows-rating: #F0A92B;          /* stars */
	--wows-error: #C8431F;           /* form errors, sale accents */
	--wows-error-bg: #FBEAEF;

	/* --- Colour: category tints --------------------------- */
	/* Six decorative wells from the mockup's category cards. Assigned by
	   position, so they work for any number of real categories. */
	--wows-tint-1: #EAF1FB;
	--wows-tint-2: #EBEAF7;
	--wows-tint-3: #EAF6EE;
	--wows-tint-4: #F4EEFB;
	--wows-tint-5: #FBF3E6;
	--wows-tint-6: #EDEFF3;

	/* --- Colour: on dark bands ---------------------------- */
	--wows-on-dark-body: #A7AEBC;                  /* value-band body text */
	--wows-on-accent: rgba(255, 255, 255, 0.9);    /* CTA band body text */
	--wows-value-rule: rgba(58, 53, 160, 0.6);     /* value-band left borders */
	--wows-btn-ghost-border: rgba(255, 255, 255, 0.28); /* outline button on dark */

	/* Brand spotlight panel (css/brands.css §2). A lighter cast of the
	   accent, because --wows-accent itself is unreadable on --wows-ink. */
	--wows-spot-eyebrow: #9C97E8;
	--wows-spot-chip-text: #D6D4F5;
	--wows-spot-chip-bg: rgba(154, 151, 232, 0.16);

	/* --- Gradients ---------------------------------------- */
	--wows-gradient-accent: linear-gradient(135deg, var(--wows-accent), var(--wows-accent-dark));
	/* Spotlight photo panel — a shade off --wows-ink, so the image well
	   separates from the copy half without a border. */
	--wows-gradient-spot: linear-gradient(150deg, #23283A, #171C29);

	/* --- Type: families ----------------------------------- */
	--wows-font-display: 'Space Grotesk', system-ui, sans-serif;  /* 500/600/700 */
	--wows-font-body: 'Hanken Grotesk', system-ui, sans-serif;    /* 400/500/600/700 */

	/*
	 * Monospace, for the typewriter and punch animations only (PORTING-MAP
	 * D2/D3). A system stack, not a loaded font: v1 pulled Courier Prime from
	 * Google for this and INSTRUCTIONS.md §4 caps the theme at the two
	 * families above. The effect needs *a* monospace, not a specific one.
	 */
	--wows-font-mono: ui-monospace, 'Courier New', Courier, monospace;

	/* --- Type: scale -------------------------------------- */
	--wows-fs-2xs: 11px;   /* sub-wordmark, micro-labels */
	--wows-fs-xs: 12px;    /* card captions */
	--wows-fs-sm: 13px;    /* utility bar, eyebrow, small buttons, breadcrumb */
	--wows-fs-base: 15px;  /* body, nav, card names — the workhorse */
	--wows-fs-md: 16px;    /* longer prose */
	--wows-fs-lg: 18px;    /* card titles, price, wordmark */
	--wows-fs-xl: 22px;    /* marquee wordmarks */
	--wows-fs-2xl: 28px;   /* stat numbers, sub-headings */
	--wows-fs-3xl: 34px;   /* section h2, large price */
	--wows-fs-4xl: 46px;   /* page h1 */
	--wows-fs-5xl: 54px;   /* hero h1 (About, Services) */
	--wows-fs-6xl: 62px;   /* home hero h1 only */

	/* --- Type: fluid (responsive mockup) ------------------ */
	/* Every heading >=30px is a clamp, floored at 24px, so nothing needs a
	   font-size override in a media query. Values are the mockup's. */
	--wows-fs-hero: clamp(34px, 7.4vw, 62px);      /* home hero h1 */
	--wows-fs-section: clamp(26px, 4.8vw, 38px);   /* section h2 */
	--wows-fs-band: clamp(23px, 3.6vw, 30px);      /* value / CTA band h2 */
	--wows-fs-stat: clamp(21px, 3vw, 26px);        /* hero stat numbers */
	--wows-fs-lede: clamp(16px, 2.1vw, 19px);      /* hero lede */
	--wows-hero-min: clamp(470px, 64vh, 620px);    /* photo hero height */

	/* --- Type: tracking ----------------------------------- */
	--wows-ls-hero: -0.03em;
	--wows-ls-h1: -0.025em;
	--wows-ls-h2: -0.02em;
	--wows-ls-tight: -0.01em;   /* card titles, wordmark */
	--wows-ls-wide: 0.02em;
	--wows-ls-eyebrow: 0.08em;  /* uppercase eyebrows */

	/* --- Type: line-height -------------------------------- */
	--wows-lh-hero: 1.04;
	--wows-lh-heading: 1.12;
	--wows-lh-body: 1.6;
	--wows-lh-lede: 1.65;

	/* --- Layout ------------------------------------------- */
	/* Gutters are fluid per the responsive mockup: clamp(18px, 4vw, 32px)
	   replaces the fixed 32px, and wide dark/accent panels get their own
	   clamp. No separate mobile override needed. */
	--wows-container: 1240px;
	--wows-gutter: clamp(18px, 4vw, 32px);
	--wows-gutter-panel: clamp(24px, 4.4vw, 50px);
	--wows-sticky-top: 96px;    /* shop sidebar, cart summary */

	/* --- Spacing (2px base, preferred steps) -------------- */
	--wows-sp-1: 8px;
	--wows-sp-2: 12px;
	--wows-sp-3: 14px;
	--wows-sp-4: 16px;
	--wows-sp-5: 18px;   /* card grid gap */
	--wows-sp-6: 22px;   /* card padding */
	--wows-sp-7: 26px;   /* panel padding */
	--wows-sp-8: 28px;
	--wows-sp-9: 40px;
	--wows-sp-10: 56px;  /* hero column gap */

	/* --- Section rhythm ----------------------------------- */
	--wows-section-sm: 50px;
	--wows-section: 56px;
	--wows-section-lg: 64px;
	--wows-section-xl: 76px;

	/* --- Radii -------------------------------------------- */
	--wows-r-sm: 10px;    /* small buttons */
	--wows-r-chip: 11px;  /* icon chips */
	--wows-r-md: 12px;    /* buttons, inputs */
	--wows-r-panel: 16px; /* shop sidebar cards */
	--wows-r-lg: 18px;    /* cards */
	--wows-r-xl: 22px;    /* panels, gallery */
	--wows-r-2xl: 26px;   /* feature bands */
	--wows-r-pill: 999px;

	/* --- Shadows ------------------------------------------ */
	--wows-shadow-card: 0 18px 40px -24px rgba(18, 23, 35, 0.45);
	--wows-shadow-card-lg: 0 22px 50px -28px rgba(18, 23, 35, 0.5);
	--wows-shadow-float: 0 12px 30px -16px rgba(18, 23, 35, 0.4);
	--wows-shadow-accent: 0 20px 50px -30px rgba(58, 53, 160, 0.55);
	--wows-focus-ring: 0 0 0 3px rgba(58, 53, 160, 0.12);

	/* --- Motion ------------------------------------------- */
	--wows-t-fast: .15s ease;
	--wows-t-base: .2s ease;
	--wows-t-slow: .25s ease;

	/*
	 * Scroll reveal (§9b). Settled at .7s on 16 Aug 2026, between v1's .6s
	 * (Eddy: too fast) and .85s (too slow). The matching per-card stagger is
	 * STAGGER_STEP in js/reveal.js; if this changes materially, move that too
	 * or the last card in a row starts before the first has finished.
	 */
	--wows-reveal-duration: .7s;
	--wows-z-header: 60;
}


/* ============================================================
   2. RESET & BASE
   ============================================================ */

*,
*::before,
*::after {
	box-sizing: border-box;
}

body {
	margin: 0;
}

img,
svg,
video {
	max-width: 100%;
	height: auto;
}


/* ============================================================
   3. TYPOGRAPHY
   ============================================================ */

body {
	background: var(--wows-white);
	color: var(--wows-ink);
	font-family: var(--wows-font-body);
	font-size: var(--wows-fs-base);
	line-height: var(--wows-lh-body);
	-webkit-font-smoothing: antialiased;
	overflow-x: hidden;
}

h1,
h2,
h3,
h4 {
	font-family: var(--wows-font-display);
	line-height: var(--wows-lh-heading);
	color: var(--wows-ink);
}

h1 {
	font-size: var(--wows-fs-4xl);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h1);
}

h2 {
	font-size: var(--wows-fs-3xl);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
}

p {
	color: var(--wows-text);
}

a {
	color: var(--wows-accent);
}


/* ============================================================
   4. LAYOUT & CONTAINERS
   ------------------------------------------------------------
   COMPONENT-INVENTORY A12.
   ============================================================ */

.wows-container {
	max-width: var(--wows-container);
	margin: 0 auto;
	padding-left: var(--wows-gutter);
	padding-right: var(--wows-gutter);
}

/*
 * THE GENERIC PAGE TEMPLATE — page.php.
 *
 * These rules exist because until 23 August 2026 there were none, anywhere:
 * `style.css` had no `.site-main`, `.entry-header` or `.entry-content` rule at
 * all, so `page.php` shipped edge-to-edge with no container, no measure and no
 * vertical rhythm. The only page on the site that reaches it is
 * `/terms-and-conditions-for-service-requests/` — every other page has a
 * template of its own — which is why it went unnoticed through go-live and
 * QA, and why Eddy found it only when he walked all 15 pages by hand.
 *
 * Kept global rather than in a per-page file, against INSTRUCTIONS.md §4's
 * usual rule: this is the fallback for *any* page without a template, so a
 * conditional enqueue would have to guess which slugs those are, and it is the
 * next new page that would ship unstyled. Twenty lines is the right price for
 * "no page can ever be naked again".
 *
 * The measure lives on the wrapper here, and is centred with it — see the
 * note on the next rule for why the obvious alternative, a cap on the
 * children, is what made the first version look broken.
 */
.wows-page__inner {
	padding-top: var(--wows-sp-8);
	padding-bottom: var(--wows-section);
}

/*
 * The column is centred, not left-aligned inside the 1240 container.
 *
 * The first attempt relied on a 68ch cap on the children alone. That gives a
 * correct line length and a wrong composition: a column pinned to the left
 * edge of a wide container with a third of the row empty beside it, which
 * reads as something having failed to load rather than as a design. Measured
 * before and after on the live page — 68ch-on-children put the text at x=221
 * in a 1710 viewport; this centres it at x=488.
 *
 * 720px sets the measure on the wrapper instead, so the cap on the children
 * comes off — two rules competing for the same job is how the first version
 * ended up looking wrong. Narrower than `.wows-tc-wrap`'s 860px in
 * css/policy-pages.css deliberately: that file's 860 holds section cards and
 * a quick-nav, this is unadorned prose and wants the tighter measure.
 */
.wows-page .entry-header,
.wows-page article {
	max-width: 720px;
	margin-left: auto;
	margin-right: auto;
}

.wows-page .entry-header {
	margin-bottom: var(--wows-sp-6);
}

.wows-page .entry-title {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-3xl);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h1);
	line-height: var(--wows-lh-heading);
	color: var(--wows-ink);
	margin: 0;
}

.wows-page .entry-content p,
.wows-page .entry-content li {
	font-size: var(--wows-fs-base);
	line-height: var(--wows-lh-body);
	color: var(--wows-text);
}

.wows-page .entry-content p {
	margin: 0 0 var(--wows-sp-4);
}

.wows-page .entry-content h2 {
	font-size: var(--wows-fs-xl);
	margin: var(--wows-sp-8) 0 var(--wows-sp-3);
}

.wows-page .entry-content h3 {
	font-size: var(--wows-fs-lg);
	margin: var(--wows-sp-6) 0 var(--wows-sp-2);
}

.wows-page .entry-content ul,
.wows-page .entry-content ol {
	margin: 0 0 var(--wows-sp-4);
	padding-left: var(--wows-sp-5);
}

.wows-page .entry-content li {
	margin-bottom: var(--wows-sp-1);
}

.wows-page .entry-content a {
	color: var(--wows-accent);
}

/* The block editor leaves empty <p>s behind between blocks — the same rule
   css/policy-pages.css needs for the same reason. Without it the gaps between
   paragraphs are doubled at random. */
.wows-page .entry-content > p:empty {
	display: none;
	margin: 0;
	padding: 0;
}


/* --- Inline SVG icons (inc/icons.php) -------------------- */

/* Sized in em so an icon tracks the type beside it, and stroked in
   currentColor so it inherits the container's colour rule rather than
   needing one of its own. Contexts that want a fixed size set width and
   height; the rest just set font-size, as they already did for the emoji
   these replaced. */
.wows-icon {
	display: block;
	width: 1em;
	height: 1em;
	flex-shrink: 0;
}


/* ============================================================
   5. HEADER
   ------------------------------------------------------------
   A1 utility bar · A2 sticky header · A3 logo lockup ·
   A5 search pill · A6 cart button.
   ============================================================ */

/* --- A1: utility bar ------------------------------------ */

.wows-utility {
	background: var(--wows-ink);
	color: var(--wows-on-dark);
	font-size: var(--wows-fs-sm);
}

.wows-utility__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wows-sp-4);
	padding-top: 9px;
	padding-bottom: 9px;
}

.wows-utility__tagline {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-1);
	margin: 0;
	color: inherit;
}

.wows-utility__dot {
	width: 6px;
	height: 6px;
	border-radius: var(--wows-r-pill);
	background: var(--wows-success);
	flex-shrink: 0;
}

.wows-utility__contact {
	display: flex;
	align-items: center;
	gap: 22px;
}

.wows-utility__link {
	display: flex;
	align-items: center;
	gap: 7px;
	color: inherit;
	text-decoration: none;
}

/* 15px, not 14: the handset needs the extra pixel to keep daylight between
   its two edges at a 1.8 stroke. */
.wows-utility__link .wows-icon {
	width: 15px;
	height: 15px;
}

.wows-utility__link:hover {
	text-decoration: underline;
}

.wows-utility__link--whatsapp {
	color: var(--wows-success-on-dark);
}

.wows-utility__sep {
	opacity: .35;
}

/* --- A2: sticky header ---------------------------------- */

.wows-header {
	position: sticky;
	top: 0;
	z-index: var(--wows-z-header);
	background: var(--wows-header-bg);
	-webkit-backdrop-filter: blur(var(--wows-header-blur));
	backdrop-filter: blur(var(--wows-header-blur));
	border-bottom: 1px solid var(--wows-border-soft);
}

.wows-header__inner {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-8);
	padding-top: var(--wows-sp-4);
	padding-bottom: var(--wows-sp-4);
}

.wows-header__actions {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-2);
	margin-left: auto;
}

/* --- A3: logo lockup ------------------------------------ */

.wows-logo {
	display: flex;
	align-items: center;
	gap: 11px;
	text-decoration: none;
	color: inherit;
	flex-shrink: 0;
}

.wows-logo__mark {
	width: 46px;
	height: 46px;
	border-radius: 50%;
	object-fit: cover;
	display: block;
	flex-shrink: 0;
}

.wows-logo--footer .wows-logo__mark {
	width: 40px;
	height: 40px;
}

.wows-logo__text {
	display: block;
	line-height: 1.05;
}

.wows-logo__name {
	display: block;
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-lg);
	font-weight: 700;
	letter-spacing: var(--wows-ls-tight);
}

.wows-logo__suffix {
	display: block;
	font-size: var(--wows-fs-2xs);
	color: var(--wows-text-muted);
	letter-spacing: var(--wows-ls-wide);
}

.wows-logo--footer .wows-logo__name {
	color: var(--wows-white);
}

/* --- A5: search pill ------------------------------------ */

.wows-search {
	display: flex;
	align-items: center;
	gap: 9px;
	width: 240px;
	padding: 9px var(--wows-sp-4);
	background: var(--wows-search);
	border: 1px solid var(--wows-border-soft);
	border-radius: var(--wows-r-pill);
	transition: border-color var(--wows-t-base), box-shadow var(--wows-t-base);
}

.wows-search:focus-within {
	border-color: var(--wows-accent);
	box-shadow: var(--wows-focus-ring);
}

/*
 * The three header icons are inline SVGs drawn in currentColor: they scale
 * with the box rather than with a font, and they render identically on every
 * platform — the emoji cart and the ⌕ glyph they replaced did neither.
 */
.wows-search__icon {
	display: flex;
	color: var(--wows-text-faint);
	line-height: 1;
}

.wows-search__icon .wows-icon {
	width: 17px;
	height: 17px;
}

.wows-search__input {
	flex: 1;
	min-width: 0;
	border: 0;
	background: transparent;
	font-family: inherit;
	font-size: 14px;
	color: var(--wows-ink);
	appearance: none;
}

.wows-search__input::placeholder {
	color: var(--wows-text-faint);
}

.wows-search__input:focus {
	outline: none;
}

.wows-search--mobile {
	width: 100%;
}

/* --- A6: cart button ------------------------------------ */

.wows-cart-button {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	flex-shrink: 0;
	background: var(--wows-white);
	border: 1px solid var(--wows-border-strong);
	border-radius: var(--wows-r-md);
	color: var(--wows-ink);
	text-decoration: none;
	font-size: var(--wows-fs-base);
	transition: border-color var(--wows-t-base);
}

.wows-cart-button:hover {
	border-color: var(--wows-ink);
}

.wows-cart-button__icon {
	display: flex;
	line-height: 1;
}

.wows-cart-button__icon .wows-icon {
	width: 21px;
	height: 21px;
}

.wows-cart-button__count {
	position: absolute;
	top: -7px;
	right: -7px;
	min-width: 19px;
	height: 19px;
	padding: 0 5px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--wows-accent);
	color: var(--wows-white);
	font-size: var(--wows-fs-2xs);
	font-weight: 700;
	border-radius: var(--wows-r-pill);
}

.wows-cart-button__count[hidden] {
	display: none;
}


/* ============================================================
   6. NAVIGATION
   ------------------------------------------------------------
   A4 primary nav + E4 underline grow. The underline is a pure
   ::after on the link, exactly as in the mockup — no Walker and
   no extra span needed.
   ============================================================ */

.wows-nav__list {
	display: flex;
	align-items: center;
	gap: 26px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.wows-nav__list a {
	position: relative;
	font-size: var(--wows-fs-base);
	font-weight: 500;
	color: var(--wows-ink);
	text-decoration: none;
	white-space: nowrap;
}

.wows-nav__list a::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: -4px;
	height: 2px;
	width: 0;
	background: var(--wows-accent);
	transition: width var(--wows-t-slow);
}

.wows-nav__list a:hover::after,
.wows-nav__list a:focus-visible::after {
	width: 100%;
}

/* Current page — accent + 600, and the underline sits open. */
.wows-nav__list .current-menu-item > a,
.wows-nav__list .current-menu-ancestor > a,
.wows-nav__list .current_page_item > a {
	color: var(--wows-accent);
	font-weight: 600;
}

.wows-nav__list .current-menu-item > a::after,
.wows-nav__list .current-menu-ancestor > a::after,
.wows-nav__list .current_page_item > a::after {
	width: 100%;
}

/* Sub-menus: plain hover dropdown, no JS. */
.wows-nav__list .sub-menu {
	position: absolute;
	top: 100%;
	left: 0;
	min-width: 200px;
	margin: var(--wows-sp-2) 0 0;
	padding: var(--wows-sp-1) 0;
	list-style: none;
	background: var(--wows-white);
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-md);
	box-shadow: var(--wows-shadow-float);
	opacity: 0;
	visibility: hidden;
	transition: opacity var(--wows-t-base), visibility var(--wows-t-base);
}

.wows-nav__list > li {
	position: relative;
}

.wows-nav__list > li:hover > .sub-menu,
.wows-nav__list > li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
}

.wows-nav__list .sub-menu a {
	display: block;
	padding: var(--wows-sp-1) var(--wows-sp-4);
}

.wows-nav__list .sub-menu a::after {
	display: none;
}

/* --- Mobile toggle + panel ------------------------------ */

/*
 * Mobile search toggle. Shares the 44×44 box language of the cart button and
 * the burger, and takes the search pill's slot in the row once the pill
 * retires at 1040px.
 */
.wows-search-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: var(--wows-white);
	border: 1px solid var(--wows-border-strong);
	border-radius: var(--wows-r-md);
	color: var(--wows-ink);
	cursor: pointer;
	transition: border-color var(--wows-t-base);
}

.wows-search-toggle:hover,
.wows-search-toggle[aria-expanded="true"] {
	border-color: var(--wows-ink);
}

.wows-search-toggle__icon {
	display: flex;
	line-height: 1;
}

.wows-search-toggle__icon .wows-icon {
	width: 20px;
	height: 20px;
}

/* Shares the drawer's panel treatment — same strip, same surface. */
.wows-search-panel {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	padding: var(--wows-sp-2) var(--wows-sp-5);
	background: var(--wows-white);
	border-bottom: 1px solid var(--wows-border);
	box-shadow: 0 26px 44px -30px rgba(18, 23, 35, 0.5);
}

.wows-search-panel[hidden] {
	display: none;
}

.wows-search-panel .wows-search {
	width: 100%;
}

.wows-nav-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: var(--wows-white);
	border: 1px solid var(--wows-border-strong);
	border-radius: var(--wows-r-md);
	cursor: pointer;
}

.wows-nav-toggle__bars,
.wows-nav-toggle__bars::before,
.wows-nav-toggle__bars::after {
	display: block;
	width: 18px;
	height: 2px;
	background: var(--wows-ink);
	transition: transform var(--wows-t-base), opacity var(--wows-t-base);
}

.wows-nav-toggle__bars {
	position: relative;
}

.wows-nav-toggle__bars::before,
.wows-nav-toggle__bars::after {
	content: "";
	position: absolute;
	left: 0;
}

.wows-nav-toggle__bars::before {
	top: -6px;
}

.wows-nav-toggle__bars::after {
	top: 6px;
}

.wows-nav-toggle[aria-expanded="true"] .wows-nav-toggle__bars {
	background: transparent;
}

.wows-nav-toggle[aria-expanded="true"] .wows-nav-toggle__bars::before {
	transform: translateY(6px) rotate(45deg);
}

.wows-nav-toggle[aria-expanded="true"] .wows-nav-toggle__bars::after {
	transform: translateY(-6px) rotate(-45deg);
}

.wows-drawer {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	display: flex;
	flex-direction: column;
	padding: 10px var(--wows-sp-5) var(--wows-sp-5);
	background: var(--wows-white);
	border-bottom: 1px solid var(--wows-border);
	box-shadow: 0 26px 44px -30px rgba(18, 23, 35, 0.5);
}

.wows-drawer[hidden] {
	display: none;
}

.wows-drawer .wows-search {
	width: 100%;
	margin-bottom: var(--wows-sp-2);
}

.wows-drawer__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.wows-drawer__list a {
	display: block;
	/* >=44px touch target, per the responsive mockup. */
	padding: 13px 4px;
	min-height: 44px;
	font-size: var(--wows-fs-md);
	font-weight: 600;
	color: var(--wows-ink);
	text-decoration: none;
	border-bottom: 1px solid rgba(18, 23, 35, 0.07);
}

.wows-drawer__list .current-menu-item > a,
.wows-drawer__list .current_page_item > a {
	color: var(--wows-accent);
}

.wows-drawer__list .sub-menu {
	list-style: none;
	margin: 0;
	padding: 0 0 0 var(--wows-sp-4);
}

.wows-drawer__call {
	margin-top: var(--wows-sp-3);
	padding: var(--wows-sp-3);
	background: var(--wows-ink);
	color: var(--wows-white);
	font-size: var(--wows-fs-base);
	font-weight: 700;
	text-align: center;
	text-decoration: none;
	border-radius: var(--wows-r-md);
}



/* ============================================================
   7. FOOTER
   ------------------------------------------------------------
   A9 compact (all pages) · A10 4-column (front page).
   ============================================================ */

.wows-footer {
	background: var(--wows-footer);
	color: var(--wows-on-dark-faint);
	margin-top: var(--wows-section-lg);
}

.wows-footer a {
	color: inherit;
	text-decoration: none;
}

.wows-footer a:hover {
	color: var(--wows-white);
	text-decoration: underline;
}

.wows-footer__top {
	padding-top: var(--wows-section-sm);
	padding-bottom: var(--wows-sp-8);
}

.wows-footer--compact .wows-footer__top {
	display: flex;
	justify-content: space-between;
	gap: var(--wows-sp-9);
	flex-wrap: wrap;
}

.wows-footer--wide .wows-footer__top {
	display: grid;
	grid-template-columns: 1.4fr 1fr 1fr 1fr;
	gap: var(--wows-sp-9);
	padding-top: 60px;
}

.wows-footer .wows-logo {
	margin-bottom: var(--wows-sp-3);
}

.wows-footer__blurb {
	font-size: 14px;
	line-height: var(--wows-lh-body);
	color: inherit;
	max-width: 280px;
	margin: 0 0 var(--wows-sp-5);
}

.wows-footer__address {
	font-size: 14px;
	line-height: 1.7;
	font-style: normal;
}

.wows-footer__phone {
	color: var(--wows-on-dark);
}

.wows-footer__heading {
	font-family: var(--wows-font-body);
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wows-white);
	margin: 0 0 var(--wows-sp-4);
}

.wows-footer__links {
	display: flex;
	flex-direction: column;
	gap: 11px;
	list-style: none;
	margin: 0;
	padding: 0;
	font-size: 14px;
}

.wows-footer__bar {
	border-top: 1px solid var(--wows-border-on-dark);
}

.wows-footer__bar-inner {
	display: flex;
	justify-content: space-between;
	gap: var(--wows-sp-4);
	flex-wrap: wrap;
	padding-top: var(--wows-sp-6);
	padding-bottom: var(--wows-sp-6);
	font-size: var(--wows-fs-sm);
}

.wows-footer__legal-list {
	display: flex;
	gap: 22px;
	list-style: none;
	margin: 0;
	padding: 0;
	flex-wrap: wrap;
}


/* ============================================================
   8. BUTTONS & FORMS
   ------------------------------------------------------------
   B1 dark · B2 accent · B3 outline · B4 WhatsApp.
   ============================================================ */

.wows-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--wows-sp-1);
	font-family: inherit;
	font-size: var(--wows-fs-base);
	font-weight: 600;
	line-height: 1;
	padding: var(--wows-sp-3) var(--wows-sp-6);
	border: 1px solid transparent;
	border-radius: var(--wows-r-md);
	text-decoration: none;
	cursor: pointer;
	transition: background var(--wows-t-base), border-color var(--wows-t-base), transform var(--wows-t-base);
}

.wows-btn--dark {
	background: var(--wows-ink);
	color: var(--wows-white);
}

.wows-btn--dark:hover {
	background: var(--wows-accent);
	transform: translateY(-2px);
}

.wows-btn--accent {
	background: var(--wows-accent);
	color: var(--wows-white);
}

.wows-btn--accent:hover {
	background: var(--wows-accent-dark);
}

.wows-btn--outline {
	background: var(--wows-white);
	color: var(--wows-ink);
	border-color: var(--wows-border-hover);
}

.wows-btn--outline:hover {
	border-color: var(--wows-ink);
}

.wows-btn--whatsapp {
	background: var(--wows-success);
	color: var(--wows-white);
}

/* Tinted variant — the product page's full-width enquiry button, which the
   mockup renders on the success tint rather than solid green so it does not
   compete with the accent "Add to cart" directly above it. */
.wows-btn--whatsapp-soft {
	background: var(--wows-success-bg);
	color: var(--wows-success-text);
}

.wows-btn--whatsapp-soft:hover {
	background: var(--wows-success);
	color: var(--wows-white);
}

/* B6 — pill / badge. Shared primitive; modifiers live with their section. */
.wows-pill {
	display: inline-flex;
	align-items: center;
	/* Flex drops whitespace-only text nodes, so a pill whose label wraps an
	   element — "Save <span>RM550.00</span>" — needs the gap or it reads
	   "SaveRM550.00". */
	gap: 0.3em;
	padding: 4px 10px;
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	line-height: 1.4;
	white-space: nowrap;
	border-radius: var(--wows-r-pill);
	background: var(--wows-divider);
	color: var(--wows-text-muted);
}

:focus-visible {
	outline: 2px solid var(--wows-accent);
	outline-offset: 2px;
}


/* ============================================================
   9. COMPONENTS — MARKETING & CONTENT BLOCKS
   ------------------------------------------------------------
   Shared partials in templates/. Kept here rather than in a
   css/front-page.css because every block below is reused on at
   least one other screen — see COMPONENT-INVENTORY §D.
   ============================================================ */

@keyframes wows-rise {
	from {
		opacity: 0;
		transform: translateY(18px);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes wows-marquee {
	from {
		transform: translateX(0);
	}

	to {
		transform: translateX(-50%);
	}
}

/* --- Eyebrow (B7) --------------------------------------- */

.wows-eyebrow {
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	color: var(--wows-accent);
	letter-spacing: var(--wows-ls-eyebrow);
	text-transform: uppercase;
	margin: 0 0 10px;
}

/* --- Section header (D7) -------------------------------- */

.wows-section-header {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--wows-sp-7);
	margin-bottom: var(--wows-sp-9);
	flex-wrap: wrap;
}

.wows-section-header__title {
	font-size: var(--wows-fs-section);
	margin: 0;
}

.wows-section-header__link {
	font-size: var(--wows-fs-base);
	font-weight: 600;
	color: var(--wows-ink);
	text-decoration: none;
	white-space: nowrap;
}

.wows-section-header__link:hover {
	color: var(--wows-accent);
}

/* --- Home section rhythm -------------------------------- */

.wows-home-section {
	padding-top: var(--wows-section-xl);
}

/* --- Hero, full-bleed photo (D1) ------------------------ */

.wows-hero {
	position: relative;
	display: flex;
	align-items: center;
	min-height: var(--wows-hero-min);
	overflow: hidden;
	background: var(--wows-tint-6);
}

.wows-hero__image {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/*
 * The scrim ramps in px, not %, exactly as the mockup specifies. A
 * percentage ramp slides under the headline as the viewport narrows and the
 * text loses contrast at mid widths.
 *
 * **It never reaches full opacity** (Eddy, 18 Aug 2026). The mockup's recipe
 * was solid white for the first 660px, which hid the left half of the photo
 * outright — the KL skyline, the windows and the palms were all behind a white
 * wall, and the hero read as a text panel beside a picture rather than as one
 * image. It now opens at 68%, so the room is present on the left and the right
 * half keeps the full-strength crop it always had.
 *
 * **68% does not carry the copy on its own, and that is the important part.**
 * Measured against the worst pixel behind each element, this scrim leaves the
 * lede at 3.47:1 and the stat labels at 4.16:1 in the theme's normal text
 * colours — both below AA's 4.5:1. The H1 clears at 5.70:1 because it is large
 * and near-ink. The fix is at the type end, not here: those two elements use
 * `--wows-text-on-photo` below, which restores 5.05:1 and 9.86:1 while leaving
 * the photo exactly as approved.
 *
 * So **the scrim opacity and the hero's text colour are one decision, not
 * two.** Lighten this ramp and the lede fails again; there is roughly 0.06 of
 * headroom before even the darker token stops clearing AA. Re-measure, never
 * eyeball — and re-measure from scratch if the hero photo is replaced.
 *
 * There used to be a second, container-anchored layer (`.wows-hero__scrim-inner`)
 * stacked on top of this one. Two opaque layers compound — 0.68 over 0.68 is
 * effectively 0.90 — so a single ramp is both the honest control and the
 * simpler one. It was removed from the markup with this change.
 *
 * **But the ramp must then follow the container, and this is the trap.** The
 * copy sits in a centred `.wows-container`, so it slides right as the viewport
 * grows while a viewport-anchored ramp stays put. Measured with fixed stops:
 * the H1 fell to 2.34:1 at 1920px, 1.14:1 at 2200px and **1.00:1 at 2560px** —
 * invisible, ink on photo, with nothing behind it. That is what the layer being
 * removed was silently doing. Caught by Codex, confirmed by measurement.
 *
 * `--wows-scrim-x` (§1) is the container's left edge, so every stop below is
 * relative to the copy rather than to the window, and the relationship holds at
 * any width. `max()` keeps it at 0 once the viewport is narrower than the
 * container, which is the case the gutter already handles.
 *
 * The 430px offset is not arbitrary: it reproduces where the ramp sat at the
 * width the design was approved on, so the hero still looks like the version
 * that was signed off. It is deliberately *inside* the copy column — the lede
 * runs to about +500 — because the photo behind that tail is bright, and the
 * measurements below say so. A larger offset is safer and visibly whiter;
 * 560px was tried and rejected for that reason.
 *
 * Measured worst-case at 1240 / 1366 / 1440 / 1695 / 1920 / 2200 / 2560 / 3440:
 * H1 4.69–7.06, lede 5.02–7.49, stat labels 9.48–10.28. All pass AA. The
 * tightest is the H1 at 1240px (4.69:1 against a 3.0 requirement for large
 * text), so **that is the width to re-measure first** after any change here.
 */
.wows-hero__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg,
			rgba(255, 255, 255, 0.68) 0px,
			rgba(255, 255, 255, 0.68) calc(var(--wows-scrim-x) + 430px),
			rgba(255, 255, 255, 0.50) calc(var(--wows-scrim-x) + 570px),
			rgba(255, 255, 255, 0.18) calc(var(--wows-scrim-x) + 730px),
			rgba(255, 255, 255, 0) calc(var(--wows-scrim-x) + 890px));
}

.wows-hero__inner {
	position: relative;
	width: 100%;
	padding-top: 84px;
	padding-bottom: 84px;
}

.wows-hero__content {
	position: relative;
	max-width: 560px;
	min-width: 320px;
	animation: wows-rise .7s ease both;
}

.wows-hero__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	padding: 7px var(--wows-sp-3);
	margin: 0 0 var(--wows-sp-7);
	background: var(--wows-accent-tint);
	border-radius: var(--wows-r-pill);
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-accent-dark);
	letter-spacing: var(--wows-ls-wide);
}

.wows-hero__dot {
	width: 6px;
	height: 6px;
	border-radius: var(--wows-r-pill);
	background: var(--wows-accent);
}

.wows-hero__title {
	font-size: var(--wows-fs-hero);
	line-height: 1.02;
	letter-spacing: var(--wows-ls-h1);
	margin: 0 0 var(--wows-sp-6);
	text-wrap: balance;
}

/*
 * The lede and the stat labels are the only hero text with no surface of its
 * own — the eyebrow has an opaque pill, the buttons have fills, and the H1 and
 * stat values are near-ink and large. These two therefore carry the scrim's
 * translucency directly and take the darker on-photo token. See the
 * `.wows-hero__scrim` note above: opacity and these colours are one decision.
 */
.wows-hero__lede {
	font-size: var(--wows-fs-lede);
	line-height: var(--wows-lh-body);
	max-width: 470px;
	margin: 0 0 34px;
	color: var(--wows-text-on-photo);
}

.wows-hero__actions {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-3);
	flex-wrap: wrap;
}

.wows-hero__stats {
	display: flex;
	gap: 30px;
	margin-top: 44px;
}

.wows-hero__stat-divider {
	width: 1px;
	background: var(--wows-border);
}

.wows-hero__stat-value {
	display: block;
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-stat);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
}

.wows-hero__stat-label {
	display: block;
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-on-photo);
}

/* --- Brand marquee (D6 / E2) ---------------------------- */

.wows-marquee {
	border-top: 1px solid var(--wows-border-soft);
	border-bottom: 1px solid var(--wows-border-soft);
	padding: var(--wows-sp-6) 0;
	overflow: hidden;
}

/*
 * Small caps label rather than a full section heading: the live H2 has to
 * survive (INSTRUCTIONS §7) without turning the mockup's quiet brand strip
 * into a titled section.
 */
.wows-marquee__heading {
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	color: var(--wows-text-muted);
	letter-spacing: var(--wows-ls-eyebrow);
	text-transform: uppercase;
	text-align: center;
	margin: 0 0 var(--wows-sp-5);
}

.wows-marquee__track {
	display: flex;
	align-items: center;
	width: max-content;
	opacity: .72;
	animation: wows-marquee 26s linear infinite;
}

.wows-marquee__track:hover,
.wows-marquee__track:focus-within {
	animation-play-state: paused;
}

.wows-marquee__list {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-10);
	list-style: none;
	margin: 0;
	padding: 0 var(--wows-sp-10) 0 0;
}

.wows-marquee__item {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-xl);
	font-weight: 600;
	color: var(--wows-text-muted);
	letter-spacing: 0.01em;
	white-space: nowrap;
}

.wows-marquee__link {
	color: inherit;
	text-decoration: none;
}

.wows-marquee__link:hover,
.wows-marquee__link:focus-visible {
	color: var(--wows-ink);
	text-decoration: none;
}

/* --- Category card (D8) + grid -------------------------- */

/* minmax(0, …) not a bare 1fr — see the note on .woocommerce ul.products. */
.wows-cat-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--wows-sp-5);
}

.wows-cat-card {
	display: flex;
	align-items: center;
	gap: 20px;
	padding: var(--wows-sp-7);
	background: var(--wows-white);
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-lg);
	text-decoration: none;
	color: inherit;
	transition: transform var(--wows-t-slow), box-shadow var(--wows-t-slow), border-color var(--wows-t-slow);
}

.wows-cat-card:hover {
	transform: translateY(-4px);
	border-color: var(--wows-border-hover);
	box-shadow: var(--wows-shadow-card);
}

.wows-cat-card__well {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 78px;
	height: 78px;
	flex-shrink: 0;
	border-radius: var(--wows-r-chip);
	overflow: hidden;
	box-shadow: inset 0 0 0 1px var(--wows-border-soft);
	isolation: isolate;
}

.wows-cat-card--tint-1 .wows-cat-card__well { background: var(--wows-tint-1); }
.wows-cat-card--tint-2 .wows-cat-card__well { background: var(--wows-tint-2); }
.wows-cat-card--tint-3 .wows-cat-card__well { background: var(--wows-tint-3); }
.wows-cat-card--tint-4 .wows-cat-card__well { background: var(--wows-tint-4); }
.wows-cat-card--tint-5 .wows-cat-card__well { background: var(--wows-tint-5); }
.wows-cat-card--tint-6 .wows-cat-card__well { background: var(--wows-tint-6); }

/*
 * Same baked-in white backdrop as the product card (see the long note in §11),
 * but it shows up far worse here: these wells are the six coloured category
 * tints, so an opaque white photo rectangle sat inside a blue, peach or green
 * tile with hard visible edges.
 *
 * ONE THING TO EXPECT, and it is the trade the blend makes. Multiplying
 * against a coloured well tints the product itself — a white machine on
 * --wows-tint-5 comes out faintly peach. That is the intended look of this
 * treatment and it is what makes the tile read as one object, but it is a
 * real colour shift on the product, not just on its background. If a
 * particular category ever needs its product shown true, give that tile
 * --wows-tint-6 (the neutral grey) rather than switching off the blend.
 */
.wows-cat-card__thumb {
	width: 100%;
	height: 100%;
	object-fit: cover;
	mix-blend-mode: multiply;
}

.wows-cat-card__code {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-2xs);
	font-weight: 700;
	letter-spacing: 0.06em;
	color: var(--wows-ink);
	opacity: .5;
}

.wows-cat-card__text {
	flex: 1;
}

.wows-cat-card__name {
	display: block;
	font-family: var(--wows-font-display);
	font-size: 17px;
	font-weight: 600;
	letter-spacing: var(--wows-ls-tight);
	margin-bottom: 4px;
}

.wows-cat-card__caption {
	display: block;
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-muted);
}

.wows-cat-card__arrow {
	font-size: var(--wows-fs-lg);
	color: var(--wows-text-faint);
	transition: transform var(--wows-t-slow), color var(--wows-t-slow);
}

.wows-cat-card:hover .wows-cat-card__arrow {
	transform: translateX(4px);
	color: var(--wows-accent);
}

/* --- Dark value band (D12 / D33) ------------------------ */

.wows-value-band-wrap {
	padding-top: 70px;
}

.wows-value-band {
	display: grid;
	grid-template-columns: 1.1fr 1fr 1fr;
	gap: var(--wows-sp-9);
	padding: var(--wows-gutter-panel);
	background: var(--wows-ink);
	border-radius: var(--wows-r-2xl);
	color: var(--wows-white);
}

.wows-value-band__title {
	font-size: var(--wows-fs-band);
	color: var(--wows-white);
	margin: 0 0 var(--wows-sp-3);
}

.wows-value-band__lede {
	font-size: var(--wows-fs-base);
	line-height: var(--wows-lh-body);
	color: var(--wows-on-dark-body);
	margin: 0;
}

.wows-value-band__item {
	border-left: 2px solid var(--wows-value-rule);
	padding-left: 20px;
}

.wows-value-band__icon {
	display: block;
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-xl);
	font-weight: 700;
	/* Not --wows-accent: this band sits on --wows-ink, where the accent
	   measures 1.87:1. The ✓ and ⚙ that used to render here had the same
	   problem — an SVG at 26px only makes it easier to see that they were
	   never readable. --wows-spot-eyebrow is the accent's lighter cast,
	   already defined for exactly this, and measures 6.83:1. */
	color: var(--wows-spot-eyebrow);
	margin-bottom: var(--wows-sp-2);
}

.wows-value-band__icon .wows-icon {
	width: 26px;
	height: 26px;
}

.wows-value-band__item-title {
	font-size: 17px;
	font-weight: 600;
	color: var(--wows-white);
	margin: 0 0 7px;
}

.wows-value-band__item-body {
	font-size: 14px;
	line-height: 1.55;
	color: var(--wows-on-dark-body);
	margin: 0;
}

/* --- Accent CTA band (D13) ------------------------------ */

.wows-cta-wrap {
	padding-top: var(--wows-section);
}

.wows-cta {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wows-sp-8);
	flex-wrap: wrap;
	padding: 46px var(--wows-gutter-panel);
	background: var(--wows-gradient-accent);
	border-radius: var(--wows-r-2xl);
	color: var(--wows-white);
}

.wows-cta__title {
	font-size: var(--wows-fs-band);
	color: var(--wows-white);
	margin: 0 0 var(--wows-sp-1);
}

.wows-cta__body {
	font-size: var(--wows-fs-md);
	color: var(--wows-on-accent);
	margin: 0;
}

.wows-cta__button {
	font-size: var(--wows-fs-md);
	font-weight: 700;
	color: var(--wows-accent-dark);
	background: var(--wows-white);
	padding: var(--wows-sp-4) 30px;
	border-radius: var(--wows-r-md);
	text-decoration: none;
	white-space: nowrap;
	transition: transform var(--wows-t-base);
}

.wows-cta__button:hover {
	transform: translateY(-2px);
}


/* ============================================================
   9b. SCROLL REVEAL
   ------------------------------------------------------------
   Cards and panels fade up as they enter the viewport. Driven by
   inc/reveal.php + js/reveal.js; see that PHP file for which
   pages and selectors take part.

   Read the scoping carefully before changing anything here.
   **Every rule that hides something is under `.wows-reveal-on`,
   a class JavaScript puts on <html> in the head.** No JS means
   no class, which means nothing is hidden. v1 hid unconditionally
   and relied on JS to undo it, so a script that failed to load
   left the page blank with the HTML all present.

   That class is also *provisional*: inc/reveal.php removes it
   again on window.load or after 3s unless js/reveal.js says it
   is alive. Otherwise reveal.js failing on its own — a 404, a
   blocker, a throw — would hide everything with nothing left to
   un-hide it, which is v1's bug moved one step down the chain.
   Codex caught exactly that in the session-9 review.

   The `opacity: 0` start state is not here either: it is printed
   in <head> by wows_reveal_head(), because the selector list is
   per page and it has to land before first paint.

   Reduced motion needs no rule at all — the head script does not
   arm, so nothing hides and nothing transitions.
   ============================================================ */

/*
 * Duration is a token so the next "slightly slower" is one edit, not a hunt
 * through two files. `ease-out` rather than `ease`: at this length `ease`
 * spends too long crawling to the finish and the card looks stuck at 95%.
 */
.wows-reveal-on .wows-reveal {
	transition:
		opacity var(--wows-reveal-duration) ease-out,
		transform var(--wows-reveal-duration) ease-out;
}

/*
 * Two classes plus the ancestor beats the head block's one-class rule, so this
 * wins without !important. If the head rule ever gains specificity, this must
 * gain it too or nothing will ever become visible.
 */
.wows-reveal-on .wows-reveal.is-revealed {
	opacity: 1;
	transform: none;
}


/* ============================================================
   10. WOOCOMMERCE — SHOP / ARCHIVE
   ------------------------------------------------------------
   C2–C7 plus the ported category bar (B1/B2) and FAQ block (B3).
   Markup comes from inc/archive.php and
   templates/shop-sidebar.php — no archive-product.php override.
   ============================================================ */

/* --- Page head (C6) ------------------------------------- */

.wows-shop-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--wows-sp-7);
	flex-wrap: wrap;
	padding-top: var(--wows-sp-8);
	padding-bottom: var(--wows-sp-5);
}

.wows-shop-head__text {
	flex: 1 1 380px;
	min-width: 0;
}

/* Woo's own loop/header.php, kept intact — it owns the H1 and the term
   description, both of which are live content (INSTRUCTIONS.md §7). */
.woocommerce-products-header {
	margin: 0;
}

.woocommerce-products-header__title {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-4xl);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h1);
	line-height: var(--wows-lh-heading);
	color: var(--wows-ink);
	margin: 0;
}

/* The term / shop description, moved out of the head row — see the note in
   inc/archive.php on why it is no longer inside .wows-shop-head__text. */
.wows-shop-desc {
	font-size: var(--wows-fs-md);
	line-height: var(--wows-lh-body);
	color: var(--wows-text);
	padding-bottom: var(--wows-sp-2);
}

/* The measure is capped on the children, not on .wows-shop-desc itself:
   .wows-container is `margin: 0 auto`, so narrowing the container would centre
   the description in the viewport instead of aligning it under the H1. */
.wows-shop-desc > * {
	max-width: 68ch;
}

.wows-shop-desc > :first-child,
.wows-shop-desc .term-description > :first-child {
	margin-top: 0;
}

.wows-shop-desc > :last-child,
.wows-shop-desc .term-description > :last-child {
	margin-bottom: 0;
}

/* --- Derived facts panel (mockup's heroFacts column) ------ */

/* The mockup's 1.35fr / 1fr header grid, re-sited to the description row —
   see wows_shop_head_description() in inc/archive.php for why it is not in
   the head row where the mockup draws it.

   The modifier is only ever on the wrapper when inc/category-facts.php
   returned cards, so the plain .wows-shop-desc rules above still describe
   every archive that has no facts. minmax(0, …) on both tracks because the
   left one holds arbitrary term HTML — a wide table or an unbroken URL in a
   description would otherwise blow the track past its share. */
.wows-shop-desc--facts {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
	gap: var(--wows-sp-9);
	align-items: start;
}

/* The 68ch measure moves down one level: it belongs to the prose, and
   capping the grid children would cap the card panel too. */
.wows-shop-desc--facts > * {
	max-width: none;
}

/* Same escape for the facts-only row, and it is not optional: the wrapper
   carries `wows-shop-desc` as well as the modifier, so `.wows-shop-desc > *`
   above caps the panel at a 68ch text measure and the four-column rule below
   then lays its cards out inside half a row. The `--facts` override does not
   reach here — different modifier. Found by Codex, 21 Aug 2026, after the
   markup was already live.

   Unbounded rather than inside the 901px block on purpose: 68ch is wider than
   any phone viewport, so the cap has no effect below the breakpoint either
   way, and scoping it would imply it does. */
.wows-shop-desc--facts-only > * {
	max-width: none;
}

.wows-shop-desc__text > * {
	max-width: 68ch;
}

.wows-shop-desc__text > :first-child,
.wows-shop-desc__text .term-description > :first-child {
	margin-top: 0;
}

.wows-shop-desc__text > :last-child,
.wows-shop-desc__text .term-description > :last-child {
	margin-bottom: 0;
}

/* A category with no description at all — 49 of the 76 on live. There is no
   prose to sit beside, so the panel takes the full row and the cards spread
   along it, exactly as they do below 900px. Without this the two-column
   .wows-facts default would leave a tall narrow stack against a blank right
   half. Added 21 Aug 2026 with the archive.php fix that let facts render at
   all on a description-less term.

   Bounded at 901px on purpose. Below that the existing max-width blocks
   already lay the cards out in a row, and these selectors are *more* specific
   than the 680px two-across rule — unbounded, they would win at phone width
   and hold four ~80px cards on a 320px screen. A modifier that only has work
   to do in one band belongs inside that band. */
@media (min-width: 901px) {
	.wows-shop-desc--facts-only > .wows-facts {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	.wows-shop-desc--facts-only > .wows-facts[data-count="2"] {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.wows-shop-desc--facts-only > .wows-facts[data-count="3"] {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	/* Three in three columns already fill the row; the desktop span rule below
	   would otherwise stretch the last card across a third of it. */
	.wows-shop-desc--facts-only > .wows-facts[data-count="3"] .wows-fact:last-child {
		grid-column: auto;
	}
}

.wows-facts {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--wows-sp-2);
}

/* Three cards would otherwise leave a ragged hole in the corner. The odd one
   out spans the row instead, which reads as a decision rather than a gap. */
.wows-facts[data-count="3"] .wows-fact:last-child {
	grid-column: 1 / -1;
}

.wows-fact {
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-lg);
	background: var(--wows-white);
	padding: var(--wows-sp-4) var(--wows-sp-4) var(--wows-sp-5);
}

.wows-fact__value {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-xl);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
	line-height: var(--wows-lh-heading);
	color: var(--wows-ink);
	margin-bottom: 4px;
}

/* wc_price() ships its own <span class="amount"> with a currency-symbol span
   inside. Both inherit here rather than being re-styled — the value line owns
   the type, whether it holds a price or a plain number. */
.wows-fact__value .woocommerce-Price-amount,
.wows-fact__value bdi {
	font: inherit;
	color: inherit;
}

.wows-fact__label {
	font-size: var(--wows-fs-sm);
	line-height: 1.45;
	color: var(--wows-text-muted);
}

.wows-shop-head__tools {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-2);
	flex-wrap: wrap;
}

/* Woo prints "Showing 1–16 of 564 results" here; the mockup's "{n} products".
   The sentence is Woo's and stays translatable — only the styling is ours. */
.wows-shop-head__tools .woocommerce-result-count {
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-muted);
	margin: 0;
}

.wows-shop-head__tools .woocommerce-ordering {
	margin: 0;
}

.wows-shop-head__tools .woocommerce-ordering select {
	font-family: inherit;
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-ink);
	background: var(--wows-white);
	border: 1px solid var(--wows-border-strong);
	border-radius: var(--wows-r-sm);
	padding: 10px var(--wows-sp-3);
	cursor: pointer;
}

.wows-shop-head__tools .woocommerce-ordering select:focus-visible {
	outline: none;
	border-color: var(--wows-accent);
	box-shadow: var(--wows-focus-ring);
}

/* --- Two-column body ------------------------------------ */

.wows-shop-body {
	display: grid;
	grid-template-columns: 248px 1fr;
	gap: 34px;
	align-items: start;
	padding-top: var(--wows-sp-5);
	padding-bottom: var(--wows-sp-9);
}

.wows-shop-main {
	min-width: 0;
}

/* search.php's fallback branch renders no sidebar (see the note there), so
   without this its single child would sit in the 248px filter column. */
.wows-shop-body--full {
	grid-template-columns: 1fr;
}

/* --- Sidebar cards (C3, C4) ----------------------------- */

.wows-shop-sidebar {
	position: sticky;
	top: var(--wows-sticky-top);
	display: flex;
	flex-direction: column;
	gap: var(--wows-sp-3);
	min-width: 0;
}

.wows-filter-card {
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-panel);
	padding: var(--wows-sp-6) var(--wows-sp-6) var(--wows-sp-4);
}

.wows-filter-card__title {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	letter-spacing: var(--wows-ls-eyebrow);
	text-transform: uppercase;
	color: var(--wows-text-faint);
	margin: 0 0 var(--wows-sp-3);
}

/*
 * The brand card's disclosure (templates/shop-sidebar.php). Desktop must look
 * exactly as it did before it became a <details>, so the summary is stripped
 * of its marker and the chevron is hidden until the 900px rule turns the card
 * into something you can actually operate.
 */
.wows-filter-card__summary {
	list-style: none;
	cursor: default;
}

.wows-filter-card__summary::-webkit-details-marker {
	display: none;
}

.wows-filter-card__chevron {
	display: none;
}

.wows-filter-card__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 3px;
}

.wows-filter-row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wows-sp-1);
	padding: var(--wows-sp-1) var(--wows-sp-2);
	border-radius: 9px;
	font-size: var(--wows-fs-base);
	font-weight: 500;
	color: var(--wows-text);
	text-decoration: none;
	transition: background var(--wows-t-fast), color var(--wows-t-fast);
}

.wows-filter-row:hover {
	background: var(--wows-surface);
	color: var(--wows-ink);
}

.wows-filter-row.is-active {
	background: var(--wows-accent-tint);
	color: var(--wows-accent-dark);
	font-weight: 700;
}

.wows-filter-row__count {
	font-size: var(--wows-fs-xs);
	opacity: .6;
	flex-shrink: 0;
}


/* --- The branch: parent + its children ------------------
 *
 * Added 19 Aug 2026. On a category archive the card used to list the parent
 * and its children at the same indent, so nothing said the rows below belonged
 * to the row above — Projector read as a peer of Office Machine, not as part
 * of it. templates/shop-sidebar.php now nests them in a real <ul>; this draws
 * the containment.
 *
 * THE ACTIVE CHILD DOES NOT GET A PILL, AND THAT IS THE POINT.
 * On a subcategory page both the parent row and one child row are "where you
 * are", in different senses: the parent is everything here (346), the child is
 * one slice of it (112). Give them both the tinted pill and the card shows two
 * current pages and answers neither question. So the parent keeps the pill —
 * it is the level header — and the active child takes a solid segment of the
 * rail instead. The branch you are on lights up as one continuous mark, and
 * which level you are on is legible at a glance.
 *
 * No rail on /shop/ or a tag archive: there is no parent there, the template
 * emits no branch, and nothing contains those terms.
 */

.wows-filter-branch__list {
	/*
	 * One variable for the rail-to-row gap because two rules depend on it —
	 * this padding and the active segment's offset below. Split them and the
	 * segment drifts off the rail the first time either is touched.
	 */
	--wows-rail-gap: var(--wows-sp-1);

	list-style: none;
	/* margin-left aligns the rail with the parent row's text, so it reads as
	   dropping from the parent's first letter rather than from the card edge.
	   It equals .wows-filter-row's horizontal padding. */
	margin: 3px 0 0 var(--wows-sp-2);
	padding: 0 0 0 var(--wows-rail-gap);
	border-left: 2px solid var(--wows-accent-tint);
	display: flex;
	flex-direction: column;
	gap: 3px;
}

.wows-filter-row--parent {
	font-family: var(--wows-font-display);
	font-weight: 600;
	color: var(--wows-ink);
}

/*
 * Children give back some horizontal padding — the rail is already drawing
 * their left edge, so the row does not need to inset as far. In a 248px column
 * the 4px buys a word before "Time Attendance Machine" wraps.
 */
.wows-filter-row--child {
	position: relative;
	padding-left: var(--wows-sp-1);
}

.wows-filter-row--child.is-active {
	/* The rail carries the state; a fill here would be the pill again. */
	background: none;
	color: var(--wows-accent-dark);
}

.wows-filter-row--child.is-active::before {
	content: '';
	position: absolute;
	/* Out through the list's padding, then over the 2px rail itself. */
	left: calc(-1 * (var(--wows-rail-gap) + 2px));
	top: 0;
	bottom: 0;
	width: 2px;
	background: var(--wows-accent);
}

.wows-filter-row--child.is-active:hover {
	background: var(--wows-surface);
}

/* --- Dark help card (C5) -------------------------------- */

.wows-help-card {
	background: var(--wows-ink);
	border-radius: var(--wows-r-panel);
	padding: var(--wows-sp-6);
	color: var(--wows-white);
}

.wows-help-card__title {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-lg);
	font-weight: 600;
	margin: 0 0 var(--wows-sp-1);
}

.wows-help-card__body {
	font-size: var(--wows-fs-sm);
	line-height: 1.55;
	color: var(--wows-on-dark-body);
	margin: 0 0 var(--wows-sp-4);
}

.wows-help-card__cta {
	display: block;
	width: 100%;
	text-align: center;
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	color: var(--wows-ink);
	background: var(--wows-white);
	border: none;
	padding: 11px var(--wows-sp-4);
	border-radius: var(--wows-r-sm);
}

.wows-help-card__cta:hover {
	background: var(--wows-on-dark);
}

/* --- Empty state (C7) ----------------------------------- */

.wows-shop-empty {
	padding: 60px var(--wows-sp-6);
	text-align: center;
	font-size: var(--wows-fs-base);
	color: var(--wows-text-faint);
}

.wows-shop-empty p {
	margin: 0 0 var(--wows-sp-2);
}

.wows-shop-empty__link {
	font-weight: 600;
	color: var(--wows-accent);
	text-decoration: underline;
}

/* The pill from searchform.php, offered again when a search returned nothing
   (B7). Centred and widened out of the header's fixed 240px, which is sized
   for a nav bar rather than for being the only control on the screen. */
.wows-shop-empty__form {
	display: flex;
	justify-content: center;
	margin-top: var(--wows-sp-6);
}

.wows-search--page {
	width: 100%;
	max-width: 420px;
	padding: 12px var(--wows-sp-5);
	background: var(--wows-white);
	border-color: var(--wows-border-strong);
	text-align: left;
}

/* --- Pagination ----------------------------------------- */

.woocommerce nav.woocommerce-pagination {
	margin: var(--wows-sp-8) 0 0;
	text-align: left;
}

.woocommerce nav.woocommerce-pagination ul {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 6px;
	border: none;
	margin: 0;
	padding: 0;
}

.woocommerce nav.woocommerce-pagination ul li {
	border: none;
	margin: 0;
	overflow: visible;
}

.woocommerce nav.woocommerce-pagination ul li a,
.woocommerce nav.woocommerce-pagination ul li span {
	display: flex;
	align-items: center;
	justify-content: center;
	min-width: 40px;
	height: 40px;
	padding: 0 var(--wows-sp-2);
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-ink);
	background: var(--wows-white);
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-sm);
	transition: background var(--wows-t-fast), border-color var(--wows-t-fast);
}

.woocommerce nav.woocommerce-pagination ul li a:hover {
	background: var(--wows-surface);
	border-color: var(--wows-border-hover);
}

.woocommerce nav.woocommerce-pagination ul li span.current {
	color: var(--wows-white);
	background: var(--wows-accent);
	border-color: var(--wows-accent);
}

/* --- Shop category browse (preview) --------------------- */
/* Reuses .wows-cat-grid / .wows-cat-card from the homepage,
   so only the section wrapper needs rules here. */

.wows-shop-browse {
	margin-bottom: var(--wows-sp-7);
	padding-bottom: var(--wows-sp-7);
	border-bottom: 1px solid var(--wows-border);
}

.wows-shop-browse__heading {
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	color: var(--wows-text-muted);
	letter-spacing: var(--wows-ls-eyebrow);
	text-transform: uppercase;
	margin: 0 0 var(--wows-sp-4);
}

@media (max-width: 900px) {
	.wows-shop-browse .wows-cat-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.wows-shop-browse .wows-cat-grid {
		grid-template-columns: minmax(0, 1fr);
	}
}
/* --- Catalogue index (templates/shop-browse.php) -------- */
/* An index, not a card grid: the machine types are the click
   targets and the top-level categories are grouping labels.
   Depth is carried by the figures alone — a stacked-rule
   graphic scaled to each count was built here and cut. */

/* The lead group carries twice the width because it carries six times
   the stock; its list runs two-up so the column is six rows deep rather
   than twelve, which keeps all three groups to a similar height. */
.wows-index__cols {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
	gap: var(--wows-sp-7);
	align-items: start;
}

.wows-index__col {
	min-width: 0;
}

.wows-index__col:first-child .wows-index__list {
	columns: 2;
	column-gap: var(--wows-sp-7);
}

.wows-index__col:first-child .wows-index__list li {
	break-inside: avoid;
}

/* Group header — the category, demoted to a label for what follows. */
.wows-index__group {
	margin: 0 0 var(--wows-sp-3);
}

.wows-index__group-link {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--wows-sp-3);
	padding-bottom: var(--wows-sp-3);
	border-bottom: 1px solid var(--wows-border);
	text-decoration: none;
	min-width: 0;
}

.wows-index__group-name {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-lg);
	font-weight: 700;
	letter-spacing: var(--wows-ls-tight);
	/* Explicit, because style.css §3 colours every h1–h4 and a matching
	   rule beats inheritance. */
	color: var(--wows-ink);
	min-width: 0;
}

.wows-index__group-link:hover .wows-index__group-name,
.wows-index__group-link:focus-visible .wows-index__group-name {
	color: var(--wows-accent);
}

/* Counts are the utility face. Data should read as data, and tabular
   figures keep the right edge of the column straight.

   --wows-text-muted, not --wows-text-faint: the count is the argument this
   block is making, and at faint it was the quietest thing on screen. */
.wows-index__group-count,
.wows-index__count,
.wows-index__rest-count {
	flex-shrink: 0;
	font-family: var(--wows-font-mono);
	font-variant-numeric: tabular-nums;
	color: var(--wows-text-muted);
}

.wows-index__group-count {
	font-size: var(--wows-fs-sm);
	color: var(--wows-ink);
}

.wows-index__list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.wows-index__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--wows-sp-3);
	padding: 6px 10px 6px 0;
	text-decoration: none;
	min-width: 0;
}

.wows-index__name {
	font-size: var(--wows-fs-base);
	color: var(--wows-text);
	/* min-width: 0 so a long machine name truncates rather than
	   shoving its count off the right edge. */
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.wows-index__row:hover .wows-index__name,
.wows-index__row:focus-visible .wows-index__name {
	color: var(--wows-accent);
}

.wows-index__count {
	font-size: var(--wows-fs-sm);
}

.wows-index__more {
	display: inline-block;
	margin-top: var(--wows-sp-3);
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-accent);
	text-decoration: none;
}

.wows-index__more:hover,
.wows-index__more:focus-visible {
	text-decoration: underline;
}

/* The tail: categories Eddy ranks below the three primaries. Pills,
   deliberately not columns — the difference in treatment is the
   information. */
.wows-index__rest {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wows-sp-2) var(--wows-sp-3);
	list-style: none;
	margin: var(--wows-sp-7) 0 0;
	padding: var(--wows-sp-5) 0 0;
	border-top: 1px solid var(--wows-border);
}

.wows-index__rest-link {
	display: inline-flex;
	align-items: baseline;
	gap: var(--wows-sp-2);
	padding: 7px 14px;
	background: var(--wows-surface);
	border-radius: 999px;
	font-size: var(--wows-fs-sm);
	color: var(--wows-text);
	text-decoration: none;
}

.wows-index__rest-link:hover,
.wows-index__rest-link:focus-visible {
	color: var(--wows-accent);
	background: var(--wows-accent-tint);
}

.wows-index__rest-count {
	font-size: var(--wows-fs-2xs);
}

@media (max-width: 900px) {
	.wows-index__cols {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--wows-sp-6);
	}

	/* Two equal columns, with the lead group taking a full-width row of
	   its own above them. It keeps its two-up list — at this width a
	   full-width row is still wide enough for two — and only drops to a
	   single text column at 620px. */
	.wows-index__col:first-child {
		grid-column: 1 / -1;
	}
}

@media (max-width: 620px) {
	.wows-index__cols {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--wows-sp-6);
	}

	.wows-index__col:first-child .wows-index__list {
		columns: 1;
	}
}

/* --- Category bar, B1 / B2 ------------------------------ */
/* No mockup equivalent — v1 feature, restyled into the new
   design language. Collapsed by default, as in v1. */

.wows-catbar {
	margin-bottom: var(--wows-sp-2);
}

.wows-catbar__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wows-sp-2);
	flex-wrap: wrap;
	padding: var(--wows-sp-2) var(--wows-sp-4);
	background: var(--wows-surface);
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-md);
}

.wows-catbar__label {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-sm);
	font-weight: 700;
	letter-spacing: var(--wows-ls-eyebrow);
	text-transform: uppercase;
	color: var(--wows-text-faint);
}

.wows-catbar__header-right {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-2);
}

.wows-catbar__current {
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-muted);
}

.wows-catbar-toggle {
	font-family: inherit;
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-accent);
	background: none;
	border: none;
	padding: 6px var(--wows-sp-1);
	cursor: pointer;
	border-radius: var(--wows-r-sm);
}

.wows-catbar-toggle:hover {
	background: var(--wows-accent-tint);
}

.wows-catbar__grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
	gap: var(--wows-sp-5);
	padding: var(--wows-sp-6) var(--wows-sp-4);
	border: 1px solid var(--wows-border);
	border-top: none;
	border-radius: 0 0 var(--wows-r-md) var(--wows-r-md);
}

/* [hidden] loses to `display: grid` on specificity alone, so the collapsed
   state has to say so explicitly or the bar is never closed. */
.wows-catbar__grid[hidden] {
	display: none;
}

.wows-catbar-parent {
	display: block;
	font-size: var(--wows-fs-base);
	font-weight: 600;
	color: var(--wows-ink);
	text-decoration: none;
	margin-bottom: var(--wows-sp-1);
}

.wows-catbar-parent:hover {
	color: var(--wows-accent);
}

.wows-catbar-parent--static {
	color: var(--wows-text-muted);
}

.wows-catbar-subs {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.wows-catbar-subs a {
	font-size: var(--wows-fs-sm);
	color: var(--wows-text);
	text-decoration: none;
}

.wows-catbar-subs a:hover {
	color: var(--wows-accent);
}

.wows-catbar-active {
	color: var(--wows-accent);
	font-weight: 700;
}

/* The tag row spans the whole grid rather than sitting in a column. */
.wows-catbar-tags {
	grid-column: 1 / -1;
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--wows-sp-1);
	padding-top: var(--wows-sp-3);
	border-top: 1px solid var(--wows-divider);
}

.wows-catbar-tags__label {
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-text-muted);
}

.wows-catbar-tags__list {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0;
	padding: 0;
}

.wows-catbar-tags__list a {
	display: inline-block;
	font-size: var(--wows-fs-sm);
	color: var(--wows-text);
	text-decoration: none;
	padding: 4px var(--wows-sp-2);
	background: var(--wows-surface);
	border-radius: var(--wows-r-pill);
}

.wows-catbar-tags__list a:hover {
	color: var(--wows-accent);
	background: var(--wows-accent-tint);
}

/* --- Bottom FAQ block, B3 ------------------------------- */
/* ACF `bottom_description`. The markup inside is Eddy's term
   content, so this styles the wrapper and lets the content's
   own headings and lists through. */

.wows-term-bottom {
	padding-bottom: var(--wows-section);
	font-size: var(--wows-fs-md);
	line-height: var(--wows-lh-body);
	color: var(--wows-text);
}

/* Measure capped on the children — .wows-container centres itself, so a
   max-width here would centre the block instead of aligning it left. */
.wows-term-bottom > * {
	max-width: 78ch;
}

.wows-term-bottom h2,
.wows-term-bottom h3,
.wows-term-bottom h4 {
	color: var(--wows-ink);
	margin-top: var(--wows-sp-7);
}

.wows-term-bottom > :first-child {
	margin-top: 0;
}

/* ---- FAQ block -------------------------------------------
   Content is <details>/<summary> in ACF term meta on 45 terms;
   inc/archive.php wraps it into two columns at render time
   without touching what is stored. Design from
   _mockup/WOW Supplies Note Counter.dc.html.

   The base rules below stand alone: a term whose markup does
   not match the wrapper's regex keeps the flat single-column
   accordion and still looks deliberate.
   --------------------------------------------------------- */

.wows-term-bottom details {
	border-bottom: 1px solid var(--wows-divider);
}

.wows-term-bottom summary {
	padding: var(--wows-sp-3) 0;
	font-size: var(--wows-fs-md);
	font-weight: 600;
	color: var(--wows-ink);
	cursor: pointer;
	list-style-position: outside;
}

.wows-term-bottom summary:hover {
	color: var(--wows-accent);
}

.wows-term-bottom details > :not(summary) {
	margin-top: 0;
	padding-bottom: var(--wows-sp-2);
}

/* --- Two-column layout ---------------------------------- */

.wows-term-bottom .wows-faq-section {
	display: grid;
	grid-template-columns: 0.85fr 1.6fr;
	gap: clamp(28px, 5vw, 60px);
	align-items: start;
	padding-top: var(--wows-sp-8);
}

/* The 78ch measure from .wows-term-bottom > * is for prose; it would cap the
   grid itself and strand the right-hand column short of the container. */
.wows-term-bottom > .wows-faq-section {
	max-width: none;
}

.wows-faq__intro {
	position: sticky;
	top: var(--wows-sticky-top);
}

.wows-faq__eyebrow {
	margin: 0 0 var(--wows-sp-3);
	font-size: var(--wows-fs-xs);
	font-weight: 700;
	letter-spacing: var(--wows-ls-eyebrow);
	text-transform: uppercase;
	color: var(--wows-text-faint);
}

/* The heading is the term's own, straight out of the database — "Frequently
   Asked Questions — Note Counter Malaysia" and 44 others like it. It carries
   the category keyword, so INSTRUCTIONS.md §7 keeps the text; only the size
   and rhythm are the mockup's. */
.wows-term-bottom .wows-faq-section > .wows-faq__intro h2 {
	margin: 0 0 var(--wows-sp-3);
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-section);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
	line-height: var(--wows-lh-heading);
	color: var(--wows-ink);
}

.wows-faq__ask {
	display: inline-block;
	font-size: var(--wows-fs-base);
	font-weight: 700;
	color: var(--wows-ink);
	text-decoration: none;
	border-bottom: 2px solid var(--wows-accent);
	padding-bottom: 2px;
	transition: color var(--wows-t-base);
}

.wows-faq__ask:hover {
	color: var(--wows-accent);
}

/* --- The accordion column -------------------------------- */

.wows-faq__list {
	border-top: 1px solid var(--wows-divider);
}

.wows-faq__list details {
	transition: background var(--wows-t-fast);
}

.wows-faq__list summary {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--wows-sp-5);
	padding: var(--wows-sp-6) var(--wows-sp-1);
	font-size: var(--wows-fs-lg);
	font-weight: 600;
	line-height: 1.4;
	letter-spacing: var(--wows-ls-tight);
}

/* `display: flex` on <summary> already removes the marker in Chrome and
   Firefox; Safari needs its own pseudo-element switched off or the triangle
   sits on top of the flex layout. */
.wows-faq__list summary::-webkit-details-marker {
	display: none;
}

.wows-faq__list summary::marker {
	content: '';
}

.wows-faq__list summary:hover {
	color: var(--wows-ink);
}

.wows-faq__list details:hover {
	background: var(--wows-surface);
}

/* The +/− is generated, not authored — the stored markup has no icon element
   and adding one would mean editing 45 terms. */
.wows-faq__list summary::after {
	content: '+';
	flex: none;
	font-size: var(--wows-fs-xl);
	font-weight: 400;
	line-height: 1;
	color: var(--wows-text-faint);
	transition: transform var(--wows-t-base), color var(--wows-t-base);
}

.wows-faq__list details[open] summary::after {
	content: '\2212';           /* proper minus sign, not a hyphen */
	color: var(--wows-accent);
}

.wows-faq__list details > :not(summary) {
	padding: 0 60px var(--wows-sp-7) var(--wows-sp-1);
	font-size: var(--wows-fs-md);
	line-height: var(--wows-lh-lede);
	color: var(--wows-text);
	text-wrap: pretty;
}

.wows-faq__list .faq-body > :first-child {
	margin-top: 0;
}

.wows-faq__list .faq-body > :last-child {
	margin-bottom: 0;
}


/* ============================================================
   11. WOOCOMMERCE — PRODUCT CARD
   ------------------------------------------------------------
   C1 / C2. templates/product-card.php. Session 5 points
   woocommerce/content-product.php at the same partial (B8).
   ============================================================ */

/* minmax(0, …) not a bare 1fr — see the note on .woocommerce ul.products. */
.wows-product-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wows-sp-5);
}

.wows-product-card {
	display: flex;
	flex-direction: column;
	background: var(--wows-white);
	border: 1px solid var(--wows-border);
	border-radius: var(--wows-r-lg);
	overflow: hidden;
	transition: transform var(--wows-t-slow), box-shadow var(--wows-t-slow);
}

.wows-product-card:hover {
	transform: translateY(-4px);
	box-shadow: var(--wows-shadow-card-lg);
}

/*
 * THE WHITE-RECTANGLE PROBLEM, AND WHY IT IS SOLVED WITH A BLEND MODE.
 *
 * 455 of the 564 published products have a JPEG featured image, and a JPEG
 * cannot carry transparency — the white studio backdrop is baked into the
 * file. `object-fit: contain` then centres that opaque white rectangle inside
 * this grey well, so every card showed a visible white square with hard edges
 * rather than a product sitting on the well.
 *
 * `mix-blend-mode: multiply` makes white pixels take the colour underneath
 * them, so the photo's backdrop becomes the well and the edges disappear. It
 * works on all 564 without touching a single file, which matters: the
 * alternative is reprocessing the media library, and that is content work on
 * the live server, not a theme change.
 *
 * `isolation: isolate` is not optional. Without it the blend reaches past the
 * card to whatever is behind it — the page background, and on the archive the
 * grid gap — so cards would tint differently depending on what they sat on.
 *
 * WHAT IT COSTS. Multiply darkens everything by the well colour, and
 * #F6F7F9 is ~4% off white, so light-grey product bodies sit a touch darker
 * than the original file. Imperceptible at these colours, but it is why the
 * well must stay near-white; deepen --wows-surface and the photos go visibly
 * murky. A product shot on a genuinely dark or coloured backdrop would be
 * darkened too — none of the current catalogue is, but that is the thing to
 * look for if an image ever appears wrong.
 *
 * THE ZERO-RISK ALTERNATIVE, if the blend ever misbehaves: delete the
 * mix-blend-mode line and set this background to var(--wows-white). The white
 * rectangle then matches the well exactly. It costs the tinted well the
 * mockup asks for, and nothing else.
 */
.wows-product-card__media {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1.05;
	padding: var(--wows-sp-6);
	background: var(--wows-surface);
	overflow: hidden;
	isolation: isolate;
}

.wows-product-card__media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	mix-blend-mode: multiply;
	transition: transform .35s ease;
}

.wows-product-card:hover .wows-product-card__media img {
	transform: scale(1.05);
}

/*
 * The Sale badge reads red rather than ink (Eddy, 16 Aug 2026). --wows-error
 * is the token for it — §1 already describes it as "form errors, sale
 * accents", so this is the palette being used as intended rather than a new
 * colour. It also stops the badge reading as a neutral label next to the ink
 * product names, which is what it looked like in black.
 *
 * The badge is a sibling of the image, not a child, so the multiply blend on
 * .wows-product-card__media img leaves it alone — it stays solid red over the
 * photo.
 */
.wows-product-card__badge {
	position: absolute;
	top: var(--wows-sp-3);
	left: var(--wows-sp-3);
	z-index: 2;
	padding: 5px 10px;
	background: var(--wows-error);
	color: var(--wows-white);
	font-size: var(--wows-fs-2xs);
	font-weight: 700;
	letter-spacing: 0.03em;
	border-radius: var(--wows-r-pill);
}

.wows-product-card__body {
	display: flex;
	flex-direction: column;
	flex: 1;
	padding: var(--wows-sp-5);
}

.wows-product-card__caption {
	font-size: var(--wows-fs-xs);
	color: var(--wows-text-faint);
	margin: 0 0 6px;
}

.wows-product-card__name {
	font-family: var(--wows-font-body);
	font-size: var(--wows-fs-base);
	font-weight: 600;
	line-height: 1.35;
	letter-spacing: normal;
	margin: 0 0 var(--wows-sp-3);
	flex: 1;
}

.wows-product-card__name a {
	color: var(--wows-ink);
	text-decoration: none;
}

.wows-product-card__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wows-sp-1);
}

.wows-product-card__price {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-lg);
	font-weight: 700;
	letter-spacing: var(--wows-ls-tight);
	color: var(--wows-ink);
}

.wows-product-card__price del {
	color: var(--wows-text-faint);
	font-weight: 500;
	margin-right: 6px;
}

/* <ins> is underlined by default, which reads as a link inside a price. */
.wows-product-card__price ins {
	text-decoration: none;
	background: none;
}

/*
 * Woo's own loop button (B5 small Add).
 *
 * Qualified `a.button` / `button.button` rather than a bare `.button`: on any
 * page WooCommerce owns, woocommerce.css styles the loop button through
 * `.woocommerce:where(…) a.button`, whose :where() adds nothing but whose
 * `a.button` still out-specifies a two-class selector. This card looked
 * correct on the homepage (no `woocommerce` body class there) and grey
 * everywhere Woo renders it until these were element-qualified.
 */
.wows-product-card__foot a.button,
.wows-product-card__foot button.button {
	font-family: inherit;
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-white);
	background: var(--wows-accent);
	border: none;
	padding: 9px var(--wows-sp-3);
	border-radius: var(--wows-r-sm);
	cursor: pointer;
	text-decoration: none;
	white-space: nowrap;
	transition: background var(--wows-t-base);
}

.wows-product-card__foot a.button:hover,
.wows-product-card__foot button.button:hover {
	background: var(--wows-accent-dark);
}

.wows-product-card__foot .added_to_cart {
	font-size: var(--wows-fs-xs);
	color: var(--wows-accent);
}

/*
 * Enquiry-only products — inc/enquiry.php.
 *
 * Outlined rather than solid, and that is the point: on an archive where most
 * cards say "Add to cart", an identical solid button saying "Enquire" reads as
 * the same action. The outline says "this one is different" before the label
 * is read. It is the same accent, so it does not read as disabled either.
 *
 * The selector repeats the base's element qualification (`a.button`) for the
 * reason given above it — Woo's `.woocommerce:where(…) a.button` out-specifies
 * a plain class list on every page Woo owns. Adding `.wows-enquire-btn` to a
 * selector that already carries `a.button` keeps us ahead of both.
 */
.wows-product-card__foot a.button.wows-enquire-btn {
	color: var(--wows-accent);
	background: var(--wows-white);
	border: 1.5px solid var(--wows-accent);
	padding: 7.5px var(--wows-sp-3);
}

.wows-product-card__foot a.button.wows-enquire-btn:hover {
	color: var(--wows-white);
	background: var(--wows-accent);
}

/*
 * "Price on request" must not look like a price.
 *
 * It sits in `.wows-product-card__price`, which is the display face at
 * --wows-fs-lg and 700 — at that weight the phrase reads as a number and the
 * eye stops on it. Muted and at body size it reads as the absence of one,
 * which is what it is.
 */
.wows-price-on-request {
	font-family: var(--wows-font-body);
	font-size: var(--wows-fs-sm);
	font-weight: 500;
	letter-spacing: normal;
	color: var(--wows-text-muted);
}

/* Single product — the sentence that stands in for the absent add-to-cart
   form. There is no button rule here on purpose: `wows_pdp_whatsapp()`
   already renders one five priorities below, and this note sits above it.
   See the docblock on wows_enquiry_single_note(). */
.wows-enquire__note {
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-muted);
	margin: var(--wows-sp-2) 0 0;
}


/* ============================================================
   12. WOOCOMMERCE — SINGLE PRODUCT
   ------------------------------------------------------------
   COMPONENT-INVENTORY C8–C14 + R4. Layout is driven from
   inc/single-product.php via Woo's hooks — there is no
   single-product template override, so a fair amount of this
   section is undoing WooCommerce's own stylesheet (floats,
   48% widths, the tab "folder" chrome). Those resets are
   marked; don't tidy them away.
   ============================================================ */

/* --- Breadcrumb (A11) ----------------------------------- */

.wows-breadcrumb {
	padding-top: var(--wows-sp-7);
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-faint);
}

.wows-breadcrumb a {
	color: var(--wows-text-faint);
	text-decoration: none;
}

.wows-breadcrumb a:hover {
	color: var(--wows-accent);
}

.wows-breadcrumb .last,
.wows-breadcrumb .breadcrumb_last {
	color: var(--wows-ink);
	font-weight: 600;
}

/* --- Gallery + summary grid (C8/C9) --------------------- */

.wows-pdp {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--wows-sp-9) 48px;
	align-items: start;
	padding-top: var(--wows-sp-6);
	padding-bottom: var(--wows-sp-9);
}

/*
 * Woo floats the gallery and summary and gives each 48%. In a grid the
 * floats are inert but the widths are not — reset both.
 *
 * THE `#content` IS LOAD-BEARING. Every override in this section that fights
 * woocommerce-layout.css carries the full `.woocommerce #content div.product`
 * prefix, and it cannot be shortened. woocommerce-layout.css writes its
 * layout rules four ways, one of which is
 * `.woocommerce #content div.product div.images` — an **ID** selector, which
 * beats any number of classes. header.php happens to wrap the page in
 * `<div id="content">`, so that variant matches here and a class-only
 * override silently loses no matter how specific it looks. Symptom if you
 * shorten it: the gallery and summary snap back to 48% and the product page
 * renders as two narrow columns inside a wide grid.
 */
.woocommerce #content div.product .wows-pdp div.images,
.woocommerce #content div.product .wows-pdp div.summary {
	float: none;
	width: auto;
	margin: 0;
}

.wows-pdp__media {
	position: relative;
	position: sticky;
	top: var(--wows-sticky-top);
	animation: wows-rise .6s ease both;
}

/* Sale flash — the mockup's badge slot, top-left of the image well. Red, in
   step with the archive card's badge; see the note there. */
.woocommerce #content div.product .wows-pdp__media span.onsale {
	position: absolute;
	top: var(--wows-sp-5);
	left: var(--wows-sp-5);
	z-index: 3;
	min-width: 0;
	min-height: 0;
	margin: 0;
	padding: 6px 12px;
	font-size: var(--wows-fs-xs);
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.03em;
	background: var(--wows-error);
	color: var(--wows-white);
	border-radius: var(--wows-r-pill);
}

/*
 * The image well. Two selectors because flexslider moves the gallery wrapper
 * inside a .flex-viewport it creates at runtime — the first matches once JS
 * has run, the second before it has (or if it never does).
 *
 * The well carries no padding. flexslider measures this box on init and
 * writes pixel widths onto the wrapper and every slide; padding here makes
 * its arithmetic disagree with the layout and the image spills over the
 * rounded corners. The inset is on the slide instead, where it is inside
 * everything flexslider sizes.
 */
.woocommerce #content div.product .wows-pdp__media .flex-viewport,
.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery > .woocommerce-product-gallery__wrapper {
	aspect-ratio: 1;
	max-height: none;
	overflow: hidden;
	background: var(--wows-surface);
	border: 1px solid var(--wows-border-soft);
	border-radius: var(--wows-r-xl);
	isolation: isolate;
}

.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery__wrapper,
.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery__image {
	height: 100%;
}

.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery__image {
	padding: var(--wows-sp-9);
}

/* Same baked-in white backdrop as the product card — see the note in §11. */
.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery__image img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	mix-blend-mode: multiply;
}

/* Woo's zoom-hint anchor is a lightbox trigger; it must fill the slide or the
   image collapses to its intrinsic height. */
.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery__image > a {
	display: block;
	height: 100%;
}

/* Woo's own lightbox trigger button, top-right of the well. */
.woocommerce #content div.product .wows-pdp__media .woocommerce-product-gallery__trigger {
	top: var(--wows-sp-5);
	right: var(--wows-sp-5);
	z-index: 3;
}

/* Thumbnail row (R6) — four across at every breakpoint, which makes the
   minmax(0, …) floor load-bearing: these cells are nothing but images. */
.woocommerce #content div.product .wows-pdp__media .flex-control-thumbs {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wows-sp-2);
	margin: var(--wows-sp-3) 0 0;
	padding: 0;
	overflow: visible;
}

/*
 * The well moved from the <img> to the <li> here, and that move is what makes
 * the blend work at all: mix-blend-mode blends an element with its *backdrop*,
 * never with its own background. Left on the image, the grey would have been
 * part of the thing being blended instead of the thing blended against.
 */
.woocommerce #content div.product .wows-pdp__media .flex-control-thumbs li {
	float: none;
	width: auto;
	margin: 0;
	padding: 6px;
	background: var(--wows-surface);
	border: 2px solid var(--wows-border);
	border-radius: var(--wows-r-sm);
	transition: border-color var(--wows-t-fast);
	isolation: isolate;
}

.woocommerce #content div.product .wows-pdp__media .flex-control-thumbs img {
	display: block;
	width: 100%;
	aspect-ratio: 1;
	object-fit: contain;
	border: none;
	opacity: 1;
	mix-blend-mode: multiply;
}

.woocommerce #content div.product .wows-pdp__media .flex-control-thumbs li:hover {
	border-color: var(--wows-border-hover);
}

/*
 * flexslider puts `flex-active` on the <img>, but the border it used to colour
 * now lives on the <li> — so the selected-thumbnail state has to reach upwards.
 * If :has() is ever unavailable the thumbnail simply shows no selected state;
 * it never shows the wrong one.
 */
.woocommerce #content div.product .wows-pdp__media .flex-control-thumbs li:has(img.flex-active) {
	border-color: var(--wows-accent);
}

/* --- Summary column ------------------------------------- */

.wows-pdp .summary {
	animation: wows-rise .7s ease .05s both;
}

.wows-pdp__eyebrow {
	margin: 0 0 var(--wows-sp-2);
}

.woocommerce #content div.product .wows-pdp .product_title {
	font-family: var(--wows-font-display);
	font-size: clamp(27px, 4.2vw, 36px);
	font-weight: 700;
	line-height: var(--wows-lh-heading);
	letter-spacing: var(--wows-ls-h1);
	margin: 0 0 var(--wows-sp-4);
}

.wows-pdp__row {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--wows-sp-3);
}

.wows-pdp__row--rating {
	margin-bottom: var(--wows-sp-6);
}

/* Woo's star rating block is a floated 1em-wide widget by default. */
.woocommerce #content div.product .wows-pdp__row .woocommerce-product-rating {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-2);
	margin: 0;
	line-height: 1;
}

.woocommerce #content div.product .wows-pdp__row .star-rating {
	float: none;
	margin: 0;
	color: var(--wows-rating);
}

.woocommerce #content div.product .wows-pdp__row .woocommerce-review-link {
	font-size: var(--wows-fs-base);
	color: var(--wows-text-muted);
	text-decoration: none;
}

.wows-pill--stock {
	background: var(--wows-success-bg);
	color: var(--wows-success-text);
}

.wows-pill--nostock {
	background: var(--wows-error-bg);
	color: var(--wows-error);
}

.wows-pill--save {
	background: var(--wows-accent-tint);
	color: var(--wows-accent-dark);
	font-weight: 700;
}

.wows-pdp__row--price {
	align-items: baseline;
	gap: var(--wows-sp-2);
	margin-bottom: var(--wows-sp-7);
}

.woocommerce #content div.product .wows-pdp__row--price .price {
	display: flex;
	align-items: baseline;
	gap: var(--wows-sp-2);
	font-family: var(--wows-font-display);
	font-size: clamp(28px, 4.4vw, 38px);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
	color: var(--wows-ink);
	margin: 0;
}

/*
 * Woo emits <del>old</del> <ins>new</ins>; the mockup leads with the price you
 * pay and trails the struck-through one. Reordered visually with flex rather
 * than by rewriting Woo's price HTML, so the source order — and what a screen
 * reader announces — stays old-then-new.
 */
.woocommerce #content div.product .wows-pdp__row--price .price del {
	order: 2;
	font-size: var(--wows-fs-lg);
	font-weight: 500;
	color: var(--wows-text-faint);
	opacity: 1;
}

.woocommerce #content div.product .wows-pdp__row--price .price ins {
	order: 1;
	text-decoration: none;
	background: none;
	color: inherit;
}

/* Woo's configured tax suffix, e.g. "excl. SST" — real, and the only note
   under the price. The mockup's SST line is invented copy; see the NOT BUILT
   note in inc/single-product.php. */
.woocommerce #content div.product .wows-pdp__row--price .price .woocommerce-price-suffix {
	font-family: var(--wows-font-body);
	font-size: var(--wows-fs-sm);
	font-weight: 400;
	color: var(--wows-text-muted);
}

.wows-pdp .woocommerce-product-details__short-description {
	font-size: var(--wows-fs-md);
	line-height: var(--wows-lh-lede);
	color: var(--wows-text);
	margin-bottom: var(--wows-sp-7);
}

.wows-pdp .woocommerce-product-details__short-description > *:last-child {
	margin-bottom: 0;
}

/* --- Buy box (C11, B12) --------------------------------- */

.wows-pdp form.cart {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--wows-sp-3);
	margin: 0 0 var(--wows-sp-4);
}

/* Variable products render selectors above the row, so the table needs the
   full width before the qty/button line. */
.wows-pdp form.cart .variations,
.wows-pdp form.cart .woocommerce-variation,
.wows-pdp form.cart .woocommerce-variation-add-to-cart {
	flex: 1 0 100%;
}

.wows-pdp form.cart .woocommerce-variation-add-to-cart {
	display: flex;
	align-items: center;
	gap: var(--wows-sp-3);
}

.woocommerce #content div.product .wows-pdp form.cart .quantity {
	display: flex;
	align-items: center;
	border: 1px solid var(--wows-border-strong);
	border-radius: var(--wows-r-md);
	overflow: hidden;
}

.woocommerce #content div.product .wows-pdp form.cart .quantity input.qty {
	width: 46px;
	height: 50px;
	padding: 0;
	font-family: var(--wows-font-display);
	font-size: 17px;
	font-weight: 700;
	text-align: center;
	color: var(--wows-ink);
	background: var(--wows-white);
	border: none;
	border-radius: 0;
	-moz-appearance: textfield;
}

.wows-pdp form.cart .quantity input.qty::-webkit-outer-spin-button,
.wows-pdp form.cart .quantity input.qty::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

/* Injected by js/single-product.js — absent, and unneeded, without JS. */
.wows-qty__btn {
	width: 46px;
	height: 50px;
	font-family: inherit;
	font-size: 20px;
	line-height: 1;
	color: var(--wows-text);
	background: var(--wows-white);
	border: none;
	cursor: pointer;
	transition: background var(--wows-t-fast);
}

.wows-qty__btn:hover {
	background: var(--wows-surface);
}

.woocommerce #content div.product .wows-pdp form.cart button.single_add_to_cart_button {
	flex: 1;
	min-width: 180px;
	font-family: inherit;
	font-size: var(--wows-fs-md);
	font-weight: 700;
	line-height: 1;
	color: var(--wows-white);
	background: var(--wows-accent);
	border: none;
	border-radius: var(--wows-r-md);
	padding: 17px var(--wows-sp-7);
	cursor: pointer;
	transition: background var(--wows-t-base);
}

.woocommerce #content div.product .wows-pdp form.cart button.single_add_to_cart_button:hover {
	background: var(--wows-accent-dark);
}

/* Woo prints the stock state again under the buy box (and, for out-of-stock
   products, in place of the form). The pill in the rating row already says it,
   so the duplicate is hidden rather than shown twice. */
.woocommerce #content div.product .wows-pdp .summary > p.stock {
	display: none;
}

.wows-pdp__whatsapp {
	width: 100%;
	margin-bottom: var(--wows-sp-6);
}

/* Assurances list (C12), under the meta row. Quiet by design — it reassures
   after the decision is made, so it must not compete with the price or the
   add-to-cart. The tick is a text glyph rather than an icon font: three
   characters do not justify a dependency, and it is aria-hidden so screen
   readers get the sentence, not "check mark" before every line. */
.wows-pdp__assurances {
	list-style: none;
	margin: var(--wows-sp-5) 0 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 10px;
	font-size: var(--wows-fs-sm);
	color: var(--wows-text);
}

.wows-pdp__assurances li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	line-height: var(--wows-lh-body);
}

/* --wows-success-text, not --wows-success: the latter is the dot/button green
   (#3DBE6B) and sits at about 2.2:1 on white. This glyph is decorative to a
   screen reader but still has to be legible on screen. */
.wows-pdp__assurance-tick {
	flex: none;
	color: var(--wows-success-text);
	font-weight: 700;
	line-height: inherit;
}

/* Nudged down to sit on the first line's centre — the li is flex-start. */
.wows-pdp__assurance-tick .wows-icon {
	width: 16px;
	height: 16px;
	margin-top: 4px;
}

/* Woo's SKU / category / tag block. The mockup has no slot for it, but it is
   real indexed content, so it is kept and made quiet rather than removed
   (INSTRUCTIONS.md §7). */
.woocommerce #content div.product .wows-pdp .product_meta {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding-top: var(--wows-sp-5);
	border-top: 1px solid var(--wows-border);
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-faint);
}

.woocommerce #content div.product .wows-pdp .product_meta a {
	color: var(--wows-text-muted);
	text-decoration: none;
}

.woocommerce #content div.product .wows-pdp .product_meta a:hover {
	color: var(--wows-accent);
}

/* --- Tabs (C13 / B4) ------------------------------------ */

.woocommerce #content div.product .woocommerce-tabs,
.woocommerce #content div.product .related.products,
.woocommerce #content div.product .upsells.products {
	max-width: var(--wows-container);
	margin: 0 auto;
	padding: var(--wows-section-sm) var(--wows-gutter) 0;
}

.woocommerce #content div.product .woocommerce-tabs ul.tabs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wows-sp-1);
	list-style: none;
	margin: 0 0 var(--wows-sp-8);
	padding: 0;
	overflow: visible;
	border-bottom: 1px solid var(--wows-border);
}

/* Woo draws its tabs as paper folders: a rule via ul::before and two curled
   corners per tab via li::before/::after. All three have to go. */
.woocommerce #content div.product .woocommerce-tabs ul.tabs::before,
.woocommerce #content div.product .woocommerce-tabs ul.tabs li::before,
.woocommerce #content div.product .woocommerce-tabs ul.tabs li::after {
	content: none;
	display: none;
}

.woocommerce #content div.product .woocommerce-tabs ul.tabs li {
	margin: 0 0 -1px;
	padding: 0;
	background: none;
	border: none;
	border-radius: 0;
	box-shadow: none;
}

.woocommerce #content div.product .woocommerce-tabs ul.tabs li a {
	display: block;
	padding: var(--wows-sp-2) var(--wows-sp-5);
	font-family: inherit;
	font-size: var(--wows-fs-base);
	font-weight: 600;
	color: var(--wows-text-faint);
	text-decoration: none;
	border-bottom: 2px solid transparent;
	transition: color var(--wows-t-fast), border-color var(--wows-t-fast);
}

.woocommerce #content div.product .woocommerce-tabs ul.tabs li a:hover {
	color: var(--wows-ink);
}

.woocommerce #content div.product .woocommerce-tabs ul.tabs li.active a {
	color: var(--wows-accent);
	border-bottom-color: var(--wows-accent);
}

.woocommerce #content div.product .woocommerce-tabs .panel {
	max-width: 920px;
	margin: 0;
	padding: 0;
	font-size: var(--wows-fs-md);
	line-height: var(--wows-lh-body);
	color: var(--wows-text);
}

/* Description content is editor HTML from the live database and contains
   fixed-width images and oEmbed iframes — several products embed a 1024px
   YouTube player, which shoots straight out of the panel without this. */
.woocommerce #content div.product .woocommerce-tabs .panel img,
.woocommerce #content div.product .woocommerce-tabs .panel iframe,
.woocommerce #content div.product .woocommerce-tabs .panel video {
	max-width: 100%;
	height: auto;
}

/* Woo repeats the tab title as an h2 inside each panel; the tab already says
   it, and a second H2 per panel muddies the heading outline. */
.woocommerce #content div.product .woocommerce-tabs .panel > h2:first-child {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Additional Information: Woo's attribute table, restyled as the mockup's
   two-column spec rows. */
.woocommerce #content div.product .woocommerce-tabs table.shop_attributes {
	border: none;
	margin: 0;
	max-width: 760px;
}

.woocommerce #content div.product .woocommerce-tabs table.shop_attributes tr {
	border-bottom: 1px solid var(--wows-border-soft);
}

.woocommerce #content div.product .woocommerce-tabs table.shop_attributes th,
.woocommerce #content div.product .woocommerce-tabs table.shop_attributes td {
	padding: var(--wows-sp-3) 0;
	border: none;
	font-style: normal;
	line-height: 1.5;
}

.woocommerce #content div.product .woocommerce-tabs table.shop_attributes th {
	width: 45%;
	font-size: var(--wows-fs-base);
	font-weight: 400;
	color: var(--wows-text-muted);
}

.woocommerce #content div.product .woocommerce-tabs table.shop_attributes td {
	font-size: var(--wows-fs-base);
	font-weight: 600;
	color: var(--wows-ink);
}

.woocommerce #content div.product .woocommerce-tabs table.shop_attributes td p {
	margin: 0;
	padding: 0;
}

/* Specification tab — an ACF WYSIWYG, so it can hold anything the editor
   typed. Mostly bulleted lists on the current data. */
.wows-spec {
	max-width: 760px;
}

.wows-spec ul {
	margin: 0 0 var(--wows-sp-4);
	padding-left: 1.2em;
}

.wows-spec li {
	margin-bottom: 6px;
}

.wows-spec > *:last-child {
	margin-bottom: 0;
}

/* --- Downloads tab (B5) --------------------------------- */

.wows-downloads {
	max-width: 760px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.wows-downloads__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wows-sp-4);
	padding: var(--wows-sp-4) 0;
	border-bottom: 1px solid var(--wows-border-soft);
}

.wows-downloads__row:last-child {
	border-bottom: none;
}

.wows-downloads__info {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

.wows-downloads__title {
	font-size: var(--wows-fs-base);
	font-weight: 600;
	color: var(--wows-ink);
}

.wows-downloads__desc {
	font-size: var(--wows-fs-sm);
	color: var(--wows-text-muted);
}

.wows-downloads__btn {
	flex-shrink: 0;
	padding: 10px var(--wows-sp-4);
	font-size: var(--wows-fs-sm);
	font-weight: 600;
	color: var(--wows-accent);
	background: var(--wows-accent-tint);
	border-radius: var(--wows-r-sm);
	text-decoration: none;
	transition: background var(--wows-t-base), color var(--wows-t-base);
}

.wows-downloads__btn:hover {
	background: var(--wows-accent);
	color: var(--wows-white);
}

/* --- Related products (C14) ----------------------------- */

.woocommerce #content div.product .related.products > h2,
.woocommerce #content div.product .upsells.products > h2 {
	font-family: var(--wows-font-display);
	font-size: var(--wows-fs-2xl);
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
	color: var(--wows-ink);
	margin: 0 0 var(--wows-sp-7);
}

/* Woo lays the loop out with floats and percentage widths; the cards are a
   grid instead (C2).

   `minmax(0, 1fr)`, never a bare `1fr`. `1fr` is `minmax(auto, 1fr)`, and the
   `auto` floor pins each track at its content's intrinsic width — so the cards
   stayed 243px wide while .wows-shop-main shrank to 574px and the grid spilled
   out of the page. Measured: 54px of horizontal scroll at 1024px (iPad
   landscape), 158px at 920px, on every archive and the shop page. Sound at
   901–1040px only, because the 900px block below reshapes the whole layout and
   1040px is where the container stops shrinking.

   This is the trap CLAUDE.md records from session 11's brand grid. The rule
   was written; this grid was never swept for it. */
.woocommerce #content ul.products {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wows-sp-5);
	list-style: none;
	margin: 0;
	padding: 0;
}

/* The archive runs 3-up (B9 sets loop_shop_columns, which puts .columns-3 on
   the <ul>); the related-products row above stays 4-up. The extra class
   out-specifies the rule above, so source order does not matter — but it does
   mean the responsive overrides in §17 have to name .columns-3 too. */
.woocommerce #content ul.products.columns-3 {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.woocommerce #content ul.products::before,
.woocommerce #content ul.products::after {
	content: none;
	display: none;
}

.woocommerce #content ul.products li.product {
	display: flex;
	float: none;
	width: auto;
	margin: 0;
	padding: 0;
}

/* The <li> is the grid item and stretches; the card inside has to stretch with
   it or a two-line product name makes its card taller than its neighbours and
   the price row stops lining up across the row. */
.woocommerce #content ul.products li.product > .wows-product-card,
.woocommerce #content ul.products li.product-category > .wows-cat-card {
	flex: 1;
}

/*
 * Subcategory tiles (woocommerce/content-product-cat.php) reuse the homepage's
 * category card, but the homepage gives it a full-width 3-up row (~400px) and
 * the archive gives it a column beside the sidebar (~300px). At that width the
 * card's side-by-side well and text squeeze category names into three or four
 * lines, so here it stacks: image band on top, text under it, arrow pinned to
 * the corner. Same component, same data — a width variant, not a second card.
 */
.woocommerce #content ul.products li.product-category > .wows-cat-card {
	position: relative;
	flex-direction: column;
	align-items: stretch;
	gap: var(--wows-sp-4);
	padding: var(--wows-sp-6);
}

.woocommerce #content ul.products li.product-category .wows-cat-card__well {
	width: 100%;
	height: 132px;
}

.woocommerce #content ul.products li.product-category .wows-cat-card__thumb {
	max-height: 100%;
	object-fit: contain;
}

.woocommerce #content ul.products li.product-category .wows-cat-card__text {
	padding-right: var(--wows-sp-7);
}

.woocommerce #content ul.products li.product-category .wows-cat-card__arrow {
	position: absolute;
	right: var(--wows-sp-6);
	bottom: var(--wows-sp-6);
}

/* --- Sticky mobile buy bar (R4) ------------------------- */

.wows-buybar {
	display: none;
	position: fixed;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 80;
	align-items: center;
	gap: var(--wows-sp-2);
	padding: 11px var(--wows-sp-4);
	background: rgba(255, 255, 255, 0.96);
	backdrop-filter: blur(14px);
	border-top: 1px solid var(--wows-border-strong);
	box-shadow: 0 -16px 34px -26px rgba(18, 23, 35, 0.65);
}

.wows-buybar__info {
	flex: 1;
	min-width: 0;
}

.wows-buybar__price {
	display: block;
	font-family: var(--wows-font-display);
	font-size: 19px;
	font-weight: 700;
	letter-spacing: var(--wows-ls-h2);
	color: var(--wows-ink);
}

.wows-buybar__price del {
	font-size: var(--wows-fs-sm);
	font-weight: 500;
	color: var(--wows-text-faint);
}

.wows-buybar__price ins {
	text-decoration: none;
	background: none;
}

.wows-buybar__name {
	display: block;
	font-size: var(--wows-fs-xs);
	color: var(--wows-text-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.woocommerce .wows-buybar a.button,
.wows-buybar .button {
	flex-shrink: 0;
	font-family: inherit;
	font-size: var(--wows-fs-base);
	font-weight: 700;
	color: var(--wows-white);
	background: var(--wows-accent);
	border: none;
	border-radius: var(--wows-r-md);
	padding: 14px var(--wows-sp-6);
	text-decoration: none;
}

/* The loop button's "View cart" follow-up link has nowhere to go in a
   one-line bar. */
.wows-buybar .added_to_cart {
	display: none;
}


/* ============================================================
   13. WOOCOMMERCE — CART & CHECKOUT
   ------------------------------------------------------------
   Intentionally empty. Cart, checkout, my-account and
   order-received are styled in **css/commerce.css**, enqueued
   only on those four screens (INSTRUCTIONS.md §4's per-page
   rule). It runs to ~1300 lines, most of it overrides of
   WooCommerce's block CSS that no other page can use, so
   keeping it out of the global stylesheet is worth more than
   keeping this section populated.

   The PDP went the other way in session 6 — style.css §12 —
   because it shares the product-card rules with the archive.
   Cart and checkout share nothing with either.

   See inc/commerce.php for why cart/checkout are CSS-only.
   ============================================================ */


/* ============================================================
   14. CONTENT COMPATIBILITY
   ------------------------------------------------------------
   Existing page content in the DB uses wows-* classes styled in
   v1's style.css. See PORTING-MAP.md §E — port / restyle /
   rewrite decision is per page.
   ============================================================ */


/* ============================================================
   15. UTILITIES
   ============================================================ */


/* ============================================================
   16. ACCESSIBILITY
   ============================================================ */

.screen-reader-text {
	border: 0;
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	white-space: nowrap;
	width: 1px;
}

.skip-link:focus {
	clip-path: none;
	height: auto;
	margin: 0;
	padding: 1em;
	position: fixed;
	top: 0;
	left: 0;
	width: auto;
	z-index: 100000;
	background: var(--wows-white);
	color: var(--wows-ink);
}


@media (prefers-reduced-motion: reduce) {

	*,
	*::before,
	*::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
		scroll-behavior: auto !important;
	}
}


/* ============================================================
   17. RESPONSIVE
   ------------------------------------------------------------
   Three breakpoints, straight from the responsive mockup's
   README: 1040 / 900 / 680. js/navigation.js hardcodes 1041px
   to match the first — change both together.

   Most type needs no override here: every heading >=30px is a
   clamp() in §1, and the page gutter is fluid.
   ============================================================ */

/* --- 1040px: the desktop nav retires -------------------- */

@media (max-width: 1040px) {

	.wows-nav,
	.wows-header__inner .wows-search--header {
		display: none;
	}

	.wows-nav-toggle,
	.wows-search-toggle {
		display: flex;
	}

	.wows-header__inner {
		gap: var(--wows-sp-3);
	}

	/* The lockup and buttons must not compress as the row tightens. */
	.wows-logo,
	.wows-cart-button,
	.wows-search-toggle,
	.wows-nav-toggle {
		flex-shrink: 0;
	}

	.wows-logo__name {
		white-space: nowrap;
	}

	/* 4-up card grids go 2-up. */
	.wows-product-grid,
	.woocommerce #content ul.products {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.wows-footer--wide .wows-footer__top {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* --- 900px: heroes and weighted grids ------------------- */

@media (max-width: 900px) {

	/*
	 * FAQ drops to one column. The desktop layout is a sticky heading column
	 * beside the accordion; below this width the heading column eats a third
	 * of the viewport and squeezes questions into a two-word-per-line ribbon.
	 * Sticky has to go with it — a sticky block in a single-column stack
	 * pins the heading over the answers as you scroll. The answer's 60px
	 * right inset is desktop breathing room and becomes lost width here.
	 * (Codex, session-10 second review — correct, and it applied to every
	 * phone visitor on 45 category pages.)
	 */
	.wows-term-bottom .wows-faq-section {
		grid-template-columns: 1fr;
		gap: var(--wows-sp-7);
	}

	.wows-faq__intro {
		position: static;
	}

	.wows-faq__list details > :not(summary) {
		padding-right: var(--wows-sp-6);
	}

	/*
	 * Facts panel drops under the description. At 1.35fr / 1fr the card
	 * column is ~330px here, which is two cards of ~155px carrying a
	 * three-word label — "Sub-categories to browse" wraps to three lines and
	 * the panel grows taller than the prose beside it.
	 *
	 * Below the description rather than above it: the description is the
	 * page's answer to "what is this category", the facts are a footnote to
	 * it, and the source order already says so.
	 */
	.wows-shop-desc--facts {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--wows-sp-7);
	}

	/* Full width now, so the 68ch measure that kept the prose readable in a
	   narrow track is doing the work again rather than the track width.

	   One row, and as many columns as there are cards — not always four. A
	   fixed four-column track left a two-fact panel using half the row and the
	   other half blank, which is the exact defect this whole component was
	   built to fix, reappearing at tablet width. Measured at 800px: 51% of the
	   row empty on Comb Binder. Six categories have two facts and eight have
	   three, so neither case is hypothetical. (Codex, session-12 review.) */
	.wows-facts {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}

	.wows-facts[data-count="2"] {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.wows-facts[data-count="3"] {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	/* Three cards in three columns already fill the row, so the desktop span
	   would now stretch one card over a third of it. Reset it here — and note
	   the 680px block below has to put it back, because this media query still
	   matches at phone width. */
	.wows-facts[data-count="3"] .wows-fact:last-child {
		grid-column: auto;
	}

	/*
	 * Photo hero: the desktop recipe is a pixel-based *horizontal* scrim,
	 * which at narrow widths either covers the photo or leaves the headline
	 * sitting on it. The mockup's answer is to flip the scrim vertical, keep
	 * the image filling a taller hero, and push the copy down so it overlaps
	 * the lower third of the photo.
	 */
	.wows-hero {
		align-items: flex-end;
		min-height: 660px;
	}

	.wows-hero__scrim {
		left: 0;
		width: 100%;
		background: linear-gradient(180deg,
				rgba(255, 255, 255, 0) 0%,
				rgba(255, 255, 255, 0.06) 20%,
				rgba(255, 255, 255, 0.72) 30%,
				rgba(255, 255, 255, 0.97) 40%,
				var(--wows-white) 48%);
	}

	.wows-hero__inner {
		padding-top: 250px;
	}

	/*
	 * Home only: the image keeps filling the hero and is framed by
	 * object-position alone, so the "WOW Supplies Sdn. Bhd." signage stays
	 * readable. Do not add a band height here — that produces the
	 * "only sky, no building" crop the mockup README warns about.
	 */
	.wows-hero__image {
		object-position: 91% 100%;
	}

	.wows-hero__content {
		max-width: none;
	}

	/* Weighted / fixed-track layout grids stack; card grids stay 2-up. */
	.wows-value-band {
		grid-template-columns: 1fr;
	}

	.wows-footer--wide .wows-footer__top,
	.wows-footer--compact .wows-footer__top {
		display: grid;
		grid-template-columns: 1fr;
	}

	/* 3-up card grids go 2-up. */
	.wows-cat-grid,
	.woocommerce #content ul.products.columns-3 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/*
	 * Shop archive: the sidebar stops being a column and stacks above the
	 * grid, per the responsive mockup. It also stops being sticky — a sticky
	 * block in normal flow pins nothing and only complicates scrolling.
	 */
	.wows-shop-body {
		grid-template-columns: 1fr;
	}

	/*
	 * `display: contents` promotes the three cards to grid items of
	 * .wows-shop-body so they can be ordered independently. Filters stay above
	 * the products, which is the ordinary pattern and what stacking gives us
	 * for free; the dark help card moves below them, because promotional copy
	 * between a filter list and the products it filters is a wall, not a
	 * prompt. The two filter cards are <nav> elements with their own labels, so
	 * dropping the <aside> box costs no landmark.
	 */
	.wows-shop-sidebar {
		display: contents;
	}

	/*
	 * "Browse by category" goes (Eddy, 25 Aug 2026). On a phone the strip is
	 * six or more full-width tiles between the visitor and the first product,
	 * and the Category card immediately below it is the same set of terms as
	 * a list — the page opened with its own index printed twice. Desktop
	 * keeps it: there it is one row beside the grid, not a screen of scroll.
	 *
	 * Hidden in CSS rather than skipped in PHP so the links stay in the
	 * markup for crawlers, and so nothing here depends on guessing the device
	 * server-side. Desktop is untouched — this rule only exists below 900px.
	 */
	.wows-shop-browse {
		display: none;
	}

	/*
	 * The brand card becomes operable: the summary is now a control, so it
	 * gets the affordances of one. js/archive.js closes it on load at this
	 * width; these rules are what makes the closed state look deliberate
	 * rather than broken.
	 */
	.wows-filter-card__summary {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: var(--wows-sp-2);
		cursor: pointer;
	}

	.wows-filter-card__summary .wows-filter-card__title {
		margin: 0;
	}

	/* Closed, the title is the whole card, so the bottom padding goes with
	   the list it was spacing. */
	.wows-filter-card__disclosure:not([open]) {
		margin-bottom: calc(var(--wows-sp-4) * -1 + var(--wows-sp-1));
	}

	.wows-filter-card__disclosure[open] .wows-filter-card__list {
		margin-top: var(--wows-sp-3);
	}

	.wows-filter-card__chevron {
		display: block;
		width: 9px;
		height: 9px;
		border-right: 2px solid var(--wows-text-faint);
		border-bottom: 2px solid var(--wows-text-faint);
		transform: translateY(-2px) rotate(45deg);
		transition: transform var(--wows-t-fast);
	}

	.wows-filter-card__disclosure[open] .wows-filter-card__chevron {
		transform: translateY(2px) rotate(-135deg);
	}

	.wows-shop-main {
		order: 2;
	}

	.wows-help-card {
		order: 3;
	}

	/*
	 * PDP: gallery over summary, and the gallery stops sticking — a sticky
	 * column is meaningless once it is the full width of the page.
	 */
	.wows-pdp {
		grid-template-columns: 1fr;
	}

	.wows-pdp__media {
		position: relative;
		top: auto;
	}

	/*
	 * R4 — sticky buy bar appears, and the footer gains clearance so the bar
	 * never covers the copyright line. Keyed off the body class rather than
	 * a sibling selector: the bar is printed on wp_footer, after </footer>.
	 */
	.wows-buybar {
		display: flex;
	}

	.wows-has-buybar .wows-footer {
		padding-bottom: 74px;
	}
}

/* --- 680px: single column ------------------------------- */

@media (max-width: 680px) {

	/* The question sits at --wows-fs-lg on desktop; at phone width that wraps
	   to three lines against the +/- glyph. */
	.wows-faq__list summary {
		gap: var(--wows-sp-3);
		padding: var(--wows-sp-5) 0;
		font-size: var(--wows-fs-md);
	}

	.wows-faq__list details > :not(summary) {
		padding: 0 0 var(--wows-sp-6);
	}

	/* Four across becomes two: a 320px phone gives each card ~140px, which is
	   narrower than "Sub-categories to browse" can wrap without breaking a
	   word. Two across at ~145px is the same problem, so the value line drops
	   a step too and the labels get their own line-height back.

	   The two- and three-card selectors have to be named explicitly: the 900px
	   block above still matches at phone width, and its per-count rules are
	   equally specific, so a bare `.wows-facts` here would lose to them. */
	.wows-facts,
	.wows-facts[data-count="2"],
	.wows-facts[data-count="3"] {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* Back to two columns, so three cards are a ragged 2 + 1 again unless the
	   odd one spans — measured at 390px before this rule, the last row was 52%
	   empty. Desktop had always handled this; the phone did not, because the
	   900px reset above stayed in force. (Codex, session-12 review.) */
	.wows-facts[data-count="3"] .wows-fact:last-child {
		grid-column: 1 / -1;
	}

	.wows-fact {
		padding: var(--wows-sp-3) var(--wows-sp-3) var(--wows-sp-4);
	}

	.wows-fact__value {
		font-size: var(--wows-fs-lg);
	}

	.wows-fact__label {
		font-size: var(--wows-fs-xs);
	}

	.wows-cat-grid,
	.wows-product-grid,
	.woocommerce #content ul.products,
	.woocommerce #content ul.products.columns-3 {
		grid-template-columns: 1fr;
	}

	/* The head's count + sort row drops under the H1 rather than sharing its
	   line at phone width. */
	.wows-shop-head {
		align-items: flex-start;
	}

	.wows-shop-head__tools {
		width: 100%;
		justify-content: space-between;
	}

	/* Downloads rows: the button drops under the title rather than squeezing
	   a long filename into a shared line. */
	.wows-downloads__row {
		flex-direction: column;
		align-items: flex-start;
		gap: var(--wows-sp-2);
	}

	/* The buy box goes full-width buttons; a 180px minimum plus the stepper
	   overflows below this width. */
	.woocommerce div.product .wows-pdp form.cart button.single_add_to_cart_button {
		min-width: 0;
	}

	/* Large feature panels drop to a tighter fixed padding. */
	.wows-value-band,
	.wows-cta {
		padding: 26px 22px;
	}

	/*
	 * Utility bar stacks into two left-aligned rows and is allowed to wrap.
	 * The tagline stays — it is hidden at no breakpoint in the mockup.
	 */
	.wows-utility__inner {
		flex-direction: column;
		align-items: flex-start;
		gap: 6px;
		font-size: var(--wows-fs-xs);
	}

	.wows-utility__contact {
		flex-wrap: wrap;
		gap: var(--wows-sp-2);
	}

	.wows-utility__tagline,
	.wows-utility__contact,
	.wows-utility__link {
		white-space: normal;
	}

	.wows-hero__stats {
		flex-wrap: wrap;
		gap: var(--wows-sp-6);
	}

	.wows-hero__stat-divider {
		display: none;
	}

	.wows-footer__bar-inner {
		flex-direction: column;
	}

	.wows-home-section {
		padding-top: var(--wows-section);
	}
}
