/*
Theme Name: Hermizon
Theme URI: https://hermizon.com
Author: WPDeveloper
Author URI: https://wpdeveloper.com
Description: The custom block theme for Hermizon, a Bangladeshi women's footwear store. Built from the Figma design tokens so the design lives in theme.json rather than in per-block overrides. Server-rendered blocks only; no page-builder dependency.
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.0
Version: 1.0.6
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: hermizon
Domain Path: /languages
Tags: e-commerce, full-site-editing, block-patterns, custom-colors, custom-logo, editor-style, featured-images, wide-blocks, accessibility-ready
*/

/*
 * Everything expressible as a design token lives in theme.json.
 * This file carries only what theme.json cannot express.
 */

/* --------------------------------------------------------------------------
 * Focus ring
 * The design defines no focus state (design-tokens.md §7). Invented here:
 * a 2px brand ring at 2px offset, applied only to keyboard focus so it never
 * appears on a mouse click. theme.json reaches :focus on links and buttons
 * but not on form controls, which is why this lives in CSS.
 * ----------------------------------------------------------------------- */

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: var(--wp--custom--state--focus-width) solid var(--wp--custom--state--focus);
	outline-offset: var(--wp--custom--state--focus-offset);
	border-radius: var(--wp--custom--radius--sm);
}

/* Suppress the UA ring only where our own ring has replaced it. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus:not(:focus-visible) {
	outline: none;
}

/* --------------------------------------------------------------------------
 * Form controls
 * Core exposes no theme.json surface for native inputs, and the checkout,
 * search and account screens are built almost entirely out of them.
 * ----------------------------------------------------------------------- */

:where(input:not([type="submit"]):not([type="checkbox"]):not([type="radio"]), select, textarea) {
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	padding: 12px 16px;
	transition: border-color var(--wp--custom--transition--fast);
}

:where(input, select, textarea)::placeholder {
	color: var(--wp--preset--color--muted-soft);
	opacity: 1;
}

:where(input, select, textarea)[aria-invalid="true"] {
	border-color: var(--wp--custom--state--error);
}

:where(input, select, textarea, button)[disabled] {
	color: var(--wp--preset--color--disabled);
	border-color: var(--wp--preset--color--line-light);
	cursor: not-allowed;
}

/* --------------------------------------------------------------------------
 * Selection
 * ----------------------------------------------------------------------- */

::selection {
	background-color: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--base);
}

/* --------------------------------------------------------------------------
 * Sticky header
 *
 * Not in the design — the Figma has one viewport and no scrolled state — but
 * decided 2026-08-12: the row pins, the announcement bar scrolls out from
 * under it.
 *
 * The sticky element cannot simply be `.hermizon-header`, and this is the
 * whole reason the rule below looks indirect. A sticky element only sticks
 * inside its parent's box, and the header's parent is the wrapper core emits
 * for `wp:template-part` — a div that is *exactly* as tall as the part it
 * holds. Measured: both 81px before this phase. `position: sticky` on the
 * header would therefore release on the first pixel of scroll.
 *
 * `display: contents` removes that wrapper's box entirely, so the header's
 * containing block becomes `.wp-site-blocks` (5,601px on the front page) and
 * the announcement bar becomes its flow sibling. The bar then scrolls away on
 * its own and the row pins at 0 — with no offset to maintain, which matters
 * because the bar is 40px at 1600, 58px at 390 and 74px at 360. Any
 * arithmetic here would have been wrong at one of those widths.
 *
 * z-index 50 is measured, not guessed: WooCommerce's drawer overlay is 9999
 * and core's navigation overlay is 100000, so both still paint above the
 * pinned row, while the mega-menu panel's 100 sits inside the header's own
 * stacking context and paints above the page.
 * ----------------------------------------------------------------------- */

.wp-block-template-part:has(> .hermizon-header) {
	display: contents;
}

/* `sticky` is a positioned value, so this also gives the mega-menu panel the
 * containing block it anchors to (mega-menu/style.css). Both depend on it. */
.hermizon-header {
	position: sticky;
	top: 0;
	z-index: 50;
}

/* Logged in, `#wpadminbar` is fixed at the top and the row would slide under
 * it — which is every browser pass on this build. */
.admin-bar .hermizon-header {
	top: 32px;
}

@media (max-width: 782px) {
	.admin-bar .hermizon-header {
		top: 46px;
	}
}

/* --------------------------------------------------------------------------
 * Header — the four utility controls
 * search · cart · account, confirmed left to right in content-ia.md §3 — read
 * from Figma node 722:233 itself, which corrected the earlier PNG-derived
 * order. Re-confirmed in the browser during Phase 8. Phase 22 added a store-
 * locations pin to the left of the three (not in the Figma frame — the stores
 * post-date it).
 * 42 x 42 hit target carrying an 18px icon (design-tokens.md §2). Each control
 * comes from a different block — a plain core/html anchor, hermizon/search-overlay,
 * woocommerce/customer-account, woocommerce/mini-cart — so there is no single
 * block-supports surface that can size them all.
 * ----------------------------------------------------------------------- */

.hermizon-header__utility .hermizon-header__stores,
.hermizon-header__utility .hermizon-search__trigger,
.hermizon-header__utility .wc-block-customer-account__link,
.hermizon-header__utility .wc-block-mini-cart__button {
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	width: 42px;
	height: 42px;
	min-width: 42px;
	padding: 0;
	color: var(--wp--preset--color--contrast);
	background-color: transparent;
	border: 0;
	border-radius: var(--wp--custom--radius--md);
	transition: background-color var(--wp--custom--transition--fast);
}

.hermizon-header__utility .hermizon-header__stores:hover,
.hermizon-header__utility .hermizon-search__trigger:hover,
.hermizon-header__utility .wc-block-customer-account__link:hover,
.hermizon-header__utility .wc-block-mini-cart__button:hover {
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--line-light);
}

/* Scoped to the three controls, not to every `svg` in the group. The search
 * overlay's `<dialog>` is a descendant of this group, and a bare
 * `.hermizon-header__utility svg` reached inside it to force its field icon and
 * its two close buttons to 18px as well. `:where()` keeps the specificity
 * exactly where it was, so the cart and account rules are unaffected. */
.hermizon-header__utility
	:where(.hermizon-header__stores, .hermizon-search__trigger, .wc-block-customer-account__link, .wc-block-mini-cart__button)
	svg {
	width: 18px;
	height: 18px;
}

/* The cart needs its own rule, and it is a specificity fault of the kind this
 * build keeps meeting. WooCommerce ships `.wc-block-mini-cart__button
 * .wc-block-mini-cart__icon { width: 1.5em }` at (0,2,0); the rule above is
 * (0,1,1), because `:where()` contributes nothing. So the cart rendered **24px
 * against the other two at 18** — measured, and visible in the header as a
 * noticeably larger middle icon. The frame draws all three at the same size: in
 * the Figma icon export the ink measures 15 x 15, 15 x 15 and 12 x 16, and
 * design-tokens.md §2 states 18. */
.hermizon-header__utility .wc-block-mini-cart__button .wc-block-mini-cart__icon {
	width: 18px;
	height: 18px;
}

/* Take the mini-cart out of the row on Cart and Checkout, Phase 36.
 *
 * WooCommerce does not remove it there — `MiniCart::render()` returns the
 * wrapper with **`style="visibility:hidden" aria-hidden="true"`** and a
 * `disabled` button. `visibility` keeps the box, so the control still occupied
 * **42px** in the utility row and left a hole: measured on the cart page, the
 * search icon ends at 1360 and the account icon starts at 1418, a **58px gap
 * against the 8px** between every other pair. Identical at 390 (`286+40`,
 * hidden). Nothing was broken and nothing shifted — it simply looked like a
 * missing icon, which is exactly what it was.
 *
 * WooCommerce's reason for `visibility` over `display` is real: removing the
 * box moves the three remaining controls 50px right, so the header shifts
 * between an ordinary page and the cart. **That trade was taken deliberately
 * (owner's call).** The shift is confined to the two pages a shopper enters as
 * a separate context, and dropping a control is a direct easing of the
 * **192px floor** the next comment block describes — the one that made every
 * page scroll sideways below 380px.
 *
 * Accessibility is unaffected either way: `aria-hidden` and `disabled` already
 * kept it out of the accessibility tree and the tab order.
 *
 * Two classes to WooCommerce's one (`.wc-block-mini-cart { display:inline-block }`
 * at (0,1,0)), so it wins on count without `!important`. The inline
 * `visibility:hidden` is a different property and does not compete.
 */
.woocommerce-cart .wc-block-mini-cart,
.woocommerce-checkout .wc-block-mini-cart {
	display: none;
}

/* The narrow-phone header, Phase 34.
 *
 * The four controls are 42px with an 8px gap — a 192px floor that does not
 * shrink, because each carries `min-width` from the rule above and the two
 * WooCommerce blocks size themselves. The row's other members do shrink, so
 * below about 380px the account icon was pushed past the viewport and **every
 * page on the site scrolled sideways**: measured `scrollWidth` 372 against 360,
 * and 355 against 320. It is the whole site because this is the header part.
 *
 * Three changes buy back 28px, and none of them removes a control: the gap
 * drops to 4, the target to 40 — still well above the 24px WCAG 2.2 AA
 * minimum — and the wordmark is allowed to shrink instead of holding a width
 * the row cannot afford. `min-width: 0` is the one that actually fixes it: a
 * flex item's automatic minimum is its content size, so without it the logo
 * refused to give up the last pixels and the overflow simply moved.
 *
 * 480 rather than 600: this is a fault of the *icon row*, and the icon row is
 * the same at 480 as at 360. Above it there is room to spare.
 */
@media (max-width: 480px) {
	/* The group must not absorb the shrink itself. With `min-width: 0` on it and
	 * unshrinkable children, the browser shrank the *box* to 131px and let the
	 * icons overflow it — the page still scrolled, only the blame moved. Pinning
	 * the group puts every pixel of shrink on the wordmark, where it belongs. */
	.hermizon-header__utility {
		gap: 4px;
		flex-shrink: 0;
	}

	.hermizon-header__utility .hermizon-header__stores,
	.hermizon-header__utility .hermizon-search__trigger,
	.hermizon-header__utility .wc-block-customer-account__link,
	.hermizon-header__utility .wc-block-mini-cart__button {
		width: 40px;
		height: 40px;
		min-width: 40px;
	}

	.hermizon-header > .wp-block-group {
		gap: 8px;
	}

	.hermizon-header .wp-block-site-logo {
		min-width: 0;
	}

	.hermizon-header .wp-block-site-logo img {
		width: auto;
		max-width: 100%;
		height: auto;
	}
}

/* Phase 10's `core/search` rules are gone with the block they contained.
 *
 * They existed because core kept its collapsed input in the flow — width 0,
 * height unchanged — which theme.json's `12px 16px` padding made **48.39px**,
 * six pixels taller than the row and enough to put the three header icons on
 * two lines. `hermizon/search-overlay` renders a single 42 x 42 anchor and a
 * `<dialog>` that is `display: none` until it is opened, so there is nothing
 * left in the row to contain. The mobile `:has()` rules that hid the wordmark
 * and the nav while the field was open went for the same reason.
 */

/* The "Sale" nav item and its accent red are gone as of Phase 10.
 * `wc_get_product_ids_on_sale()` returns 0, so the item pointed at /shop/ and
 * showed the whole catalogue — a claim with nothing behind it. The `accent`
 * palette entry stays: this rule was its only use in theme or plugin code, but
 * two published posts reference it in their own content.
 *
 * When a campaign exists, the item comes back here and `SALE` comes back to
 * the mega menu's first column. Both are content, not code. */

/* --------------------------------------------------------------------------
 * Nav items answer in brand red — hover, keyboard focus, and the current page
 *
 * theme.json's global link `:hover` already says brand, but it never reaches
 * these: core's navigation styles win on specificity, so the row sat inert in
 * contrast ink at every state — measured, Phase 19. The mega menu's trigger
 * carries the same colours in its own stylesheet, so the whole row answers
 * alike. `aria-current` is ours too: every link here is `kind: "custom"`, which
 * core never matches against the request — `Hermizon\Core\Navigation` marks it.
 * ----------------------------------------------------------------------- */

.hermizon-header .wp-block-navigation .wp-block-navigation-item__content {
	transition: color var(--wp--custom--transition--fast);
}

.hermizon-header .wp-block-navigation .wp-block-navigation-item__content:hover,
.hermizon-header .wp-block-navigation .wp-block-navigation-item__content:focus-visible,
.hermizon-header .wp-block-navigation .wp-block-navigation-item__content[aria-current="page"] {
	color: var(--wp--preset--color--brand);
}

/* --------------------------------------------------------------------------
 * Footer
 * ----------------------------------------------------------------------- */

/* The only logo asset is a black wordmark, invisible on #1D2328. Inverting a
 * monochrome mark is exact; replace this with a white asset when the designer
 * supplies one and the rule can go.
 */
.hermizon-logo--inverse img {
	filter: brightness(0) invert(1);
}

/* Body links are underlined by default (design-tokens.md §7). Footer
 * navigation is a list of destinations, not prose, so the underline moves to
 * hover — theme.json reaches link colour per block but not link decoration.
 */
.hermizon-footer a:where(:not(.wp-block-social-link-anchor)) {
	text-decoration: none;
}

.hermizon-footer a:where(:not(.wp-block-social-link-anchor)):hover {
	text-decoration: underline;
}

.hermizon-footer__links {
	padding-left: 0;
	list-style: none;
}

/* theme.json sets a global heading colour — `contrast`, the body ink — and an
 * element style wins over the colour a dark group passes down to its children.
 * So the four footer column headings rendered #202124 on #1D2328: a contrast
 * ratio of 1.01:1, black on black, invisible on every page of the site. Found
 * by measuring in Phase 8; four browser passes had looked straight at it.
 * The links in this footer needed the same kind of override, just above. */
.hermizon-footer :is(h1, h2, h3, h4, h5, h6) {
	color: var(--wp--preset--color--base);
}

/* --------------------------------------------------------------------------
 * The account screens — Phase 12, docs/phase-12-account.md
 *
 * Two Figma frames on one URL. The shape is in the theme's WooCommerce
 * override (woocommerce/myaccount/form-login.php); the behaviour is in
 * Hermizon\Core\Account. This is everything neither of those can express.
 *
 * page 9 is still the [woocommerce_my_account] shortcode and WooCommerce 11
 * ships no block replacement (commerce-ux-spec.md §9), so all of it is class
 * selectors rather than theme.json. Buttons already carry `wp-element-button`,
 * so theme.json does reach those.
 * ----------------------------------------------------------------------- */

/* The box-sizing trap, scoped rather than risked a seventh time.
 *
 * This theme deliberately ships no global `* { box-sizing: border-box }`, and
 * that decision has now cost six defects — the collection tile, the map
 * placeholder, the quantity stepper on three surfaces at once. This region is
 * built almost entirely out of controls that state a width and carry 12px/16px
 * of padding, which is exactly the shape that fails. A reset scoped to the
 * region removes the whole class of fault here without reopening the global
 * decision.
 */
.hermizon-auth,
.hermizon-auth *,
.hermizon-auth *::before,
.hermizon-auth *::after {
	box-sizing: border-box;
}

/* WooCommerce caps its own wrapper, and it has to be released here.
 *
 * `woocommerce-blocktheme.css` carries
 * `.woocommerce-account main .woocommerce { max-width: 1000px }`, which is a
 * sensible default for a form on a page and wrong for a full-bleed split —
 * measured, the card came out **1000px inside a 1320px content area** and the
 * photograph 480 wide against a designed 752. Released only where the auth
 * screens are: the signed-in dashboard keeps the 1000px, because that is the
 * width Phase 8 fitted its 312px navigation column to and there is no reason to
 * reopen it.
 *
 * Three classes to core's two-classes-and-an-element, so it wins on count.
 * **This is the Phase 8 specificity trap again** — WooCommerce's own rules are
 * routinely more specific than a theme's single-class ones, and a rule that
 * "should" apply here silently does not.
 */
.woocommerce-account main .woocommerce:has(.hermizon-auth) {
	max-width: none;
}

/* The cart page's title, released from the same 1000px cap.
 *
 * `woocommerce-blocktheme.css` caps the post title on three body classes at
 * once — `.woocommerce-account .wp-block-post-title, .woocommerce-cart
 * .wp-block-post-title, .woocommerce-checkout .wp-block-post-title` — at
 * **(0,2,0)**. On the cart that left "Cart" **1000px wide starting at x=300**
 * while every other element on the page measured **1320 wide at x=140**: the
 * cart block, the line-items table, the header's inner group and the footer
 * columns. One heading, 160px out of line with the page it titles.
 *
 * `max-width: none` would be wrong — the constrained-layout rule that supplies
 * the 1320 is `.is-layout-constrained > :where(…)` at **(0,1,0)**, so a release
 * at (0,2,1) would beat that too and run the title to the full 1600. The
 * content size is therefore named rather than released.
 *
 * **Scoped to the cart deliberately.** `.woocommerce-account` keeps its 1000px
 * — Phase 8 fitted the dashboard's 312px navigation column to that width — and
 * `.woocommerce-checkout` never matches, because `page-checkout.html` carries
 * no `post-title` block at all.
 *
 * Two classes and an element to core's two classes, so it wins on count. Same
 * specificity trap as the rule above it.
 */
.woocommerce-cart main .wp-block-post-title {
	max-width: var(--wp--style--global--content-size);
}

/* The split. The frame is 1600 wide with a 388px form column and a 752 x 940
 * photograph 214px to its right. Kept inside the site's own header and footer
 * by decision, so the numbers are proportions rather than the frame's literals.
 */
.hermizon-auth {
	display: grid;
	gap: var(--wp--preset--spacing--100);
	grid-template-columns: 1fr;
}

/* Capped and centred rather than run to the full 1320.
 *
 * **The photograph is portrait — 1504 x 1872 — and the shoes are at the bottom
 * of it.** Stretched across the whole content width the cell came out 800 x 565,
 * a landscape box, and `object-fit: cover` cropped the frame down to the
 * model's skirt: the one thing the picture is *of* was outside it. Seen in a
 * screenshot; every box measured correctly. 1120 leaves the photograph 600 wide
 * against a 620 floor, which is close enough to square that the crop is gentle,
 * and `object-position` biases what survives towards the bottom. */
@media (min-width: 783px) {
	.hermizon-auth {
		max-width: 1120px;
		margin-inline: auto;
		grid-template-columns: minmax(0, 440px) minmax(0, 1fr);
		align-items: stretch;
	}
}

.hermizon-auth__forms {
	min-width: 0;
	padding-block: var(--wp--preset--spacing--60);
}

/* --- the panels -------------------------------------------------------- */

/* **There is no toggle here, and that is the point (E74).** `form-login.php`
 * emits the panel the request asked for and nothing else, so there is no hidden
 * form to show or hide.
 *
 * What used to live here: a `[data-open]` default from PHP, four `:has(…:target)`
 * rules to let a fragment override it, and `scroll-margin-top` on the panels
 * with two `.admin-bar` variants — because the anchor jump put a panel under
 * the 75px sticky header at 390 and hid its own heading. **All of it is gone
 * rather than kept "just in case": with no fragment there is no anchor jump,
 * and a rule that can never match is the dead code this change exists to
 * remove.** Twenty-eight lines of CSS replaced by two PHP conditionals.
 */

/* `section` (40px at 1600), not `display` (48px): measured off the export, the
 * heading spans 214 -> 505 for "Welcome Back 👋", which is nearer 40 than 48.
 * Verified against the frame in the browser pass. */
.hermizon-auth__title {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--section);
	line-height: 1.15;
}

.hermizon-auth__sub {
	margin: 0 0 var(--wp--preset--spacing--70);
	max-width: 42ch;
	color: var(--wp--preset--color--muted);
	line-height: 1.6;
}

/* --- the photograph ----------------------------------------------------- */

/* Stretched to the form's height rather than given the frame's aspect ratio.
 * At 752 x 940 the image is far taller than it is wide, so an `aspect-ratio`
 * on a 800px-wide column would tower over a six-field form; `object-fit: cover`
 * in a stretched cell cannot. The floor stops it collapsing to a sliver on the
 * short screens — lost password is three elements tall.
 */
.hermizon-auth__aside {
	display: none;
	margin: 0;
}

@media (min-width: 783px) {
	.hermizon-auth__aside {
		display: block;
		position: relative;
		min-height: 620px;
		border-radius: var(--wp--custom--radius--md);
		overflow: hidden;
	}

	.hermizon-auth__aside img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		/* Biased low: the shoes are at the bottom of this photograph and a
		 * centred crop loses them. */
		object-position: 50% 62%;
	}
}

/* --- form controls ------------------------------------------------------ */

/* Everything in this group is written to outrank WooCommerce rather than to
 * read tidily, and the selectors say so. Core ships, in woocommerce.css:
 *
 *   .woocommerce form.login, .woocommerce form.register  (0,2,1)
 *       border: 1px solid #cfc8d8; padding: 20px; margin: 2em 0; border-radius: 5px
 *   .woocommerce form .form-row                          (0,2,1)  padding: 3px
 *   .woocommerce form .form-row label                    (0,2,2)  line-height: 2
 *
 * A single-class theme rule loses to every one of them. **Measured, not
 * assumed**: `.woocommerce-form { padding: 0; border: 0 }` computed to 20px and
 * a 1px #cfc8d8 border, so the design's fields-on-white sat inside a grey card
 * nobody drew. Phase 8 hit exactly this on the My Account columns; it is the
 * same fault and the same fix — qualify until the class count wins.
 */
.hermizon-auth .woocommerce-form.login,
.hermizon-auth .woocommerce-form.register,
.hermizon-auth .woocommerce-ResetPassword {
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
}

.hermizon-auth .woocommerce-form .form-row,
.hermizon-auth .woocommerce-ResetPassword .form-row {
	padding: 0;
}

.woocommerce-form-row {
	margin-block-end: var(--wp--preset--spacing--40);
}

.hermizon-auth .woocommerce-form .form-row label,
.hermizon-auth .woocommerce-ResetPassword .form-row label,
.woocommerce-form-row label,
.woocommerce-MyAccount-content label {
	display: block;
	margin-block-end: var(--wp--preset--spacing--20);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.4;
	color: var(--wp--preset--color--contrast);
}

.woocommerce-Input,
.woocommerce-form-row input.input-text {
	width: 100%;
}

/* --------------------------------------------------------------------------
 * Confirm your mobile number — Phase 38.4
 *
 * The prompt above My Account while a new customer's number is unproved.
 *
 * **`box-sizing` is stated here and that is not boilerplate.** This theme
 * deliberately ships no global reset, so an input with `width: 100%` and any
 * padding is wider than its parent — measured on the first build of this
 * prompt: a 640px block holding a **674px** field, and at 390 a page that
 * scrolled sideways. `.hermizon-auth` sets the same thing for the same reason;
 * every enclosed form has to say it.
 * ----------------------------------------------------------------------- */

.hermizon-verify {
	box-sizing: border-box;
	max-width: var(--wp--style--global--content-size);
	margin-block-end: var(--wp--preset--spacing--70);
	padding: var(--wp--preset--spacing--50);
	border: 1px solid var(--wp--preset--color--line-light);
	border-radius: var(--wp--custom--radius--md);
	background-color: var(--wp--preset--color--base);
}

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

.hermizon-verify__title {
	margin-block: 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--large);
}

.hermizon-verify__lead {
	margin-block: 0 var(--wp--preset--spacing--40);
	max-width: 60ch;
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
}

/* The code is six characters and the box should say so. A full-width field
 * invites a sentence; this one invites six digits. */
.hermizon-verify__field {
	margin-block: 0 var(--wp--preset--spacing--40);
	max-width: 12rem;
}

.hermizon-verify__field input {
	width: 100%;
	font-size: var(--wp--preset--font-size--large);
	letter-spacing: 0.25em;
	text-align: center;
}

.hermizon-verify__actions {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--40);
	margin-block: 0;
}

/* Confirm is the action; sending another is a way out of trouble. Drawing them
 * as one pair of buttons would make asking for a second code look as ordinary
 * as using the first. */
.hermizon-verify__resend {
	padding: 0;
	border: 0;
	background: none;
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: underline;
	cursor: pointer;
}

.hermizon-verify__resend:disabled {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
	cursor: default;
}

.hermizon-verify__note {
	margin-block: var(--wp--preset--spacing--40) 0;
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
}

/* First Name and Last Name, the frame's two-up row. */
.hermizon-auth__row {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	grid-template-columns: 1fr 1fr;
}

.hermizon-auth__row .woocommerce-form-row {
	margin-block-end: var(--wp--preset--spacing--40);
	min-width: 0;
}

/* A field that takes the whole row, Phase 37.
 *
 * The row above is `1fr 1fr` and First Name / Last Name simply fall into it —
 * `--half` carries no rule at all, which is why adding a *third* field put the
 * mobile number in half a box on the second line rather than across the row.
 * The grid is the layout; a field that wants the whole width has to say so.
 */
.hermizon-auth__row .hermizon-auth__field--full {
	grid-column: 1 / -1;
}

/* The show/hide password button is core's — `woocommerce.min.js` wraps the
 * input in `span.password-input` and appends `.show-password-input`, on this
 * page and on checkout. It ships no positioning, so the button lands after the
 * input rather than inside it. The frame draws it inside, at the right edge.
 */
.password-input {
	display: block;
	position: relative;
}

.password-input .show-password-input {
	position: absolute;
	inset-block-start: 50%;
	inset-inline-end: 12px;
	transform: translateY(-50%);
	width: 24px;
	height: 24px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	/* Core paints its own eye via a ::after glyph; recolour rather than redraw. */
	color: var(--wp--preset--color--muted);
}

/* Room for the button so a long password never runs under it. */
.password-input .woocommerce-Input {
	padding-inline-end: 44px;
}

/* "Forgot Password?" — under the password field, right-aligned, above the
 * button, which is where the frame puts it. Core's template has it below the
 * submit; the override moved it, this aligns it.
 *
 * **A negative top margin here overlapped the password input**, printing the
 * link across its bottom border — caught in a screenshot, not by any
 * measurement, because an overlapping element still reports a healthy box. The
 * gap is closed from above instead: the row *followed by* this link gives up
 * its own bottom margin. */
.hermizon-auth .woocommerce-form-row:has(+ .woocommerce-LostPassword) {
	margin-block-end: var(--wp--preset--spacing--20);
}

.hermizon-auth .woocommerce-LostPassword {
	margin-block: 0 var(--wp--preset--spacing--50);
	text-align: right;
	font-size: var(--wp--preset--font-size--small);
}

/* WooCommerce's registration privacy notice. Real and required, but it is a
 * standing legal line rather than a thing to read every time — so it is set
 * back from the fields it sits between. */
.hermizon-auth .woocommerce-privacy-policy-text p {
	margin-block: 0 var(--wp--preset--spacing--50);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
	color: var(--wp--preset--color--muted);
}

/* Remember me is not in the design and is not being dropped for that — it is a
 * real choice a shopper makes about their own session. Given its own line above
 * the button rather than sharing one with it. */
.woocommerce-form-login__rememberme {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	margin-block-end: var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.hermizon-auth__terms {
	font-size: var(--wp--preset--font-size--small);
}

.hermizon-auth__terms .woocommerce-form__label-for-checkbox,
.woocommerce-form-login__rememberme {
	cursor: pointer;
}

.hermizon-auth__terms .woocommerce-form__label-for-checkbox {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	margin-block-end: 0;
	color: var(--wp--preset--color--contrast);
}

/* The checkbox itself has to state its size, and therefore its box-sizing —
 * see the scoped reset at the top of this section. */
.hermizon-auth__terms input[type="checkbox"],
.woocommerce-form-login__rememberme input[type="checkbox"] {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	margin: 0;
	accent-color: var(--wp--preset--color--contrast);
}

.hermizon-auth .woocommerce-form-login__submit,
.hermizon-auth .woocommerce-form-register__submit {
	width: 100%;
}

/* --- social, and the divider above it ----------------------------------- */

/* Both are rendered by Account::render_social_buttons(), and **neither renders
 * while no provider is configured** — so these rules are dormant today. The
 * divider is emitted with the buttons rather than by the template, so there is
 * never a rule to nowhere.
 */
.hermizon-auth__divider {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--40);
	margin-block: var(--wp--preset--spacing--70);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.hermizon-auth__divider::before,
.hermizon-auth__divider::after {
	content: "";
	flex: 1 1 auto;
	height: var(--wp--custom--border--width);
	background-color: var(--wp--preset--color--line);
}

.hermizon-auth__socials {
	display: grid;
	gap: var(--wp--preset--spacing--30);
}

.hermizon-auth__social {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--30);
	min-height: 48px;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--50);
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	transition: border-color var(--wp--custom--transition--fast);
}

.hermizon-auth__social:hover,
.hermizon-auth__social:focus-visible {
	border-color: var(--wp--preset--color--contrast);
}

.hermizon-auth__mark {
	flex: 0 0 auto;
}

/* --- the switch between the two panels ---------------------------------- */

.hermizon-auth__switch {
	margin-block-start: var(--wp--preset--spacing--70);
	text-align: center;
	color: var(--wp--preset--color--muted);
}

/* --- notices ------------------------------------------------------------ */

/* Captured by the override and re-emitted inside the card, above whichever
 * panel PHP opened — see the buffer in form-login.php for why the action can
 * only run once.
 *
 * **The class is `wc-block-components-notice-banner`, not `woocommerce-error`.**
 * WooCommerce 11 renders `notices/error.php` as a block notice banner and the
 * legacy `ul.woocommerce-error` never appears on this install. A first pass
 * here styled the legacy names and was **dead code that matched nothing** — the
 * banner was rendering correctly the whole time and the assertion looking for
 * it reported "no notice in the card". That is the `wc-block-…` prefix trap
 * from Phase 8, in a new place: check the rendered class, not the expected one.
 *
 * The banner is a finished component with its own colour, icon and padding, so
 * only its placement is ours. */
.hermizon-auth .woocommerce-notices-wrapper:empty {
	display: none;
}

.hermizon-auth .wc-block-components-notice-banner {
	margin: 0 0 var(--wp--preset--spacing--50);
}

/* --- lost password ------------------------------------------------------ */

/* The same shell, so "Forgot Password?" does not drop the shopper onto an
 * unstyled page mid-flow. Its form is three elements tall, which is what the
 * aside's min-height above is protecting against. */
.hermizon-auth__intro {
	margin: 0 0 var(--wp--preset--spacing--50);
	max-width: 46ch;
	color: var(--wp--preset--color--muted);
	line-height: 1.6;
}

/* WooCommerce lays the two password fields out as a 47%/47% float pair
 * (`form-row-first` / `form-row-last`), which is right beside a wide content
 * column and wrong inside a 440px one. **Measured on the reset screen:
 * `password_1` came out 440 and `password_2` 206.8** — two fields that must be
 * compared against each other, at different widths, on different lines. Both go
 * full width and out of the float. */
.hermizon-auth .woocommerce-ResetPassword .form-row-first,
.hermizon-auth .woocommerce-ResetPassword .form-row-last {
	float: none;
	width: 100%;
}

.hermizon-auth .woocommerce-ResetPassword .button {
	width: 100%;
}

.hermizon-auth__back {
	margin-block-start: var(--wp--preset--spacing--50);
	font-size: var(--wp--preset--font-size--small);
}

/* --------------------------------------------------------------------------
 * My Account, signed in — moved to assets/account.css in Phase 40
 * ----------------------------------------------------------------------- */

/* The rules that were here now live in `assets/account.css`, which is enqueued
 * only on `is_account_page()`. They were carried across unchanged, Phase 8
 * specificity comment included. See that file's header for the measurement
 * that moved them: this sheet had nearly tripled since docs/perf-baseline.md
 * last weighed the question, and every other page was paying for a region it
 * never renders. */

/* --------------------------------------------------------------------------
 * Trust row — the icon that patterns/trust-row.php emits
 * ----------------------------------------------------------------------- */

/* The frame draws these icons in the body ink, not the brand red — checked
 * against node 722:233 during the Phase 5 cross-check. Red was invented in
 * Phase 4 and made four utility icons compete with the price for attention. */
.hermizon-trust__icon,
.hermizon-promise__icon,
.hermizon-feature__icon {
	display: inline-flex;
	color: var(--wp--preset--color--contrast);
}

/* The two card icons open a stacked card; they are not a glyph inside a
 * sentence. `inline-flex` sat them on a text baseline, so every card carried an
 * invisible **5px** of descender space beneath its icon — which is most of what
 * made the trust card measure 179 against the frame's 170. A block-level flex
 * box has no baseline strut. `.hermizon-promise__icon` keeps `inline-flex`
 * because on the product page it really does sit beside a line of text. */
.hermizon-trust__icon,
.hermizon-feature__icon {
	display: flex;
	width: fit-content;
	/* `width: fit-content` inside a constrained layout hands the element over to
	 * core's `margin-left: auto; margin-right: auto`, which centred both icons
	 * the moment they stopped being inline. Measured: the trust icon jumped from
	 * inset 32 to inset 138. The end margin stays auto so the box still shrinks
	 * to the glyph; only the start margin is pinned. */
	margin-inline: 0 auto;
}

/* --------------------------------------------------------------------------
 * The arrow the frame draws after a call to action
 *
 * Generated content rather than markup, because `core/button` is a save-based
 * block: an extra `<span>` inside its `<a>` does not match what `save()` would
 * produce, and the editor would flag the block invalid the first time anyone
 * opened the page. The glyph is decorative — the link text already says where
 * it goes — so generated content is the honest place for it too.
 * ----------------------------------------------------------------------- */

.hermizon-cta-arrow .wp-block-button__link::after {
	content: "\2192";
	/* 4, not the frame's 12: the frame's 12 is measured ink-to-ink and the arrow
	 * glyph carries its own left side bearing. At 12 the button came out 261
	 * against the frame's 253. */
	margin-inline-start: 4px;
}

/* --------------------------------------------------------------------------
 * Celebrities & Influencers — the heading that sits between the two card
 * columns. The frame overlaps them: the flanking cards start at y 3403 while
 * the heading block starts at 3341, so the grid has to be pulled up under it
 * rather than following it in the flow. Measured and set below.
 * ----------------------------------------------------------------------- */

.hermizon-celebrities__intro {
	position: relative;
	z-index: 1;
}

/* --------------------------------------------------------------------------
 * Elegance & Comfort — patterns/feature-cards.php
 * ----------------------------------------------------------------------- */

/* The frame does not top-align the heading with the cards: the cards begin at
 * the pink card's content edge and the heading sits 36px lower, so the first
 * line of type lands beside the icons rather than above them. Measured in the
 * frame at y=2781 against a content top of y=2745, less the 40/1.1 line box's
 * own half-leading — the frame measurement is ink, the padding is a box. */
.hermizon-features__intro {
	padding-top: 28px;
}

/* Core emits `blockGap` on a columns block as `gap`, which the intro column's
 * own stacking also inherits. The frame's heading-to-subhead gap is 18px and
 * the theme's default block gap is 24px, so it is stated here rather than
 * fought with an inline style on every paragraph. */
.hermizon-features__intro > * + * {
	margin-block-start: 18px;
}

/* --------------------------------------------------------------------------
 * Responsive
 * The design has one viewport — 1600px, fourteen frames, no phone (see
 * responsive-spec.md). Almost all of the behaviour below is the platform's
 * own at 600px and 782px (C6); this block is only the handful of places the
 * platform does not already get right.
 * ----------------------------------------------------------------------- */

/* The product page's two columns, between the platform's stacking point and the
 * width the design was drawn for.
 *
 * The gallery column is a stated 560px (pdp-spec.md) and the purchase column
 * takes what is left. At 1320 that is 632px; at **782 it is 94px**, and the Add
 * to cart button — 192px wide — hung 74px outside the viewport, so **the product
 * page scrolled sideways from 782 to about 900**. Measured, and it is the same
 * fault as the testimonial band: a number drawn at 1320 applied at every width
 * above the platform's own breakpoint.
 *
 * Both columns go fluid instead of stacking. On a shoe page the photograph and
 * the buy panel belong on one screen, and half of the row still shows the shoe
 * larger than a phone ever does: 367px at 782, 488px at 1024. The 80px gutter is
 * a 1320px number too, so it comes down with them. */
@media (min-width: 782px) and (max-width: 1100px) {
	.hermizon-product__layout {
		gap: var(--wp--preset--spacing--60);
	}

	.hermizon-product__layout > .wp-block-column:first-child {
		/* `!important` because the stated width is an inline style, which is what
		 * core's own stacking rule has to beat at 781 for the same reason. */
		flex-basis: 50% !important;
	}
}

/* The page gutter on a phone, Phase 34b.
 *
 * 20px is the cap the owner set for the site (E129) and it holds from 601 up.
 * On a phone it is still a fortieth of the screen spent on nothing: at 360 the
 * two gutters are 40 of 360 pixels, and a two-column product grid inside that
 * loses more to the column gap than the cards can spare.
 *
 * Overriding the two custom properties rather than the padding is what makes
 * this one declaration: core drives `.has-global-padding`, the negative margins
 * that let an `alignfull` child escape it, and every block that opts into root
 * padding from the same pair — so all of it moves together and nothing has to
 * be kept in sync by hand. The rules further down that need the gutter's width
 * read it from here for the same reason.
 */
@media (max-width: 600px) {
	/* `html:root` and not `:root`, and it is a source-order problem rather than a
	 * specificity preference: WordPress prints `global-styles-inline-css` — which
	 * defines this pair from theme.json — *after* the theme's own stylesheet link,
	 * so an equally specific `:root` here loses and the gutter stayed at 20.
	 * (0,1,1) against (0,1,0) settles it whatever the order becomes. */
	html:root {
		--wp--style--root--padding-left: 16px;
		--wp--style--root--padding-right: 16px;
	}
}

/* The hero, Phase 34b.
 *
 * `min-height: 680px` is on every one of the four `core/cover` slides as an
 * **inline style in the page's own content**, which is why this needs
 * `!important`: an inline declaration beats any selector. 680 is the frame's
 * height at 1320 wide — an aspect of 1.94:1 — and it was applied at every
 * width, so on a 390px phone the hero was a **350 x 680 box**: taller than it
 * is wide, and 80% of an 844px screen before the visitor sees a single product.
 *
 * The replacement is not the frame's ratio either. 350 at 1.94:1 is 180px tall,
 * which cannot hold a four-line display headline and a button. These are the
 * heights the *content* needs plus its padding, measured: the headline wraps to
 * four lines at 390 (~150px), the button is 50, and the cover's own vertical
 * rhythm wants ~60 — so 420 at phone widths, and 520 in the band above where
 * the headline wraps to two.
 *
 * The 80px inner padding is the same kind of number and comes down with it:
 * at 390 it left the 440px content column 190px to sit in.
 */
@media (max-width: 600px) {
	.hermizon-slider__slide .wp-block-cover {
		min-height: 420px !important;
		/* Inner padding, *on top of* the page gutter — the headline starts 32px
		 * from the screen edge, not 16. */
		padding-inline: 16px !important;
	}
}

@media (min-width: 601px) and (max-width: 782px) {
	.hermizon-slider__slide .wp-block-cover {
		min-height: 520px !important;
		padding-inline: var(--wp--preset--spacing--70) !important;
	}
}

/* Elegance & Comfort — the band that had no responsive behaviour at all.
 *
 * Two numbers from the 1600px frame were applied at every width: a **384px**
 * intro column and a **three-track grid** beside it. Nothing collapsed, so the
 * three cards divided whatever the second column had left. Measured before this
 * phase, card width by viewport:
 *
 *   360 → 53px    390 → 63px    430 → 76px    783 → 59px    900 → 98px
 *
 * At 390 the body copy set **one character per line** and the card ran 881px
 * tall. The 783 figure is the worse one and shows why 782 is the wrong
 * breakpoint here: below it core stacks the columns and the cards get the full
 * width; at 783 the fixed intro returns and the grid is squeezed again. The band
 * needs its own boundary, and it is the width the frame's own arithmetic asks
 * for — 384 intro + 20 gutter + (3 x 254 + 2 x 18) cards = 1202 of content, so
 * **1240** with the page's gutters. Below that the intro sits above the cards.
 *
 * The 59px inner padding is a 1320px number too. On a 390px phone it spent 118
 * of 350 available pixels on empty pink, so it comes down with the rest.
 */
@media (max-width: 1239px) {
	/* Same shape as core's own stacking rule, and `!important` for the same
	 * reason: the 384px basis is an inline style. */
	.hermizon-features .wp-block-columns > .wp-block-column {
		flex-basis: 100% !important;
	}

	.hermizon-features .wp-block-columns {
		flex-wrap: wrap !important;
	}
}

/* Three tracks down to 600, one below it: at 600–782 the full-width card row
 * still holds three legible cards, and dropping straight to a single column
 * there would make the band four screens tall for no gain.
 *
 * The selector is structural rather than `.hermizon-features__cards`, and that
 * is not a style choice. **The pattern is flattened into the page's own content
 * in the database** — there is no `wp:pattern` reference on the front page, so a
 * class added to the pattern file reaches a re-inserted copy and never reaches
 * the live page. `is-layout-grid` is what core actually emits and is present in
 * both. The class stays on the pattern for anything inserted from now on.
 *
 * Specificity (0,3,0) beats the `wp-container-core-group-is-layout-*` rule core
 * prints for `columnCount`, whatever order the two are printed in. */
@media (max-width: 599px) {
	.hermizon-features .wp-block-group.is-layout-grid,
	.hermizon-features .hermizon-features__cards {
		grid-template-columns: minmax(0, 1fr);
	}
}

@media (max-width: 782px) {
	.hermizon-features {
		padding: var(--wp--preset--spacing--80) var(--wp--style--root--padding-left) !important;
	}

	/* 60px above a 36px icon is a frame proportion, not a phone one. */
	.hermizon-features .hermizon-feature {
		padding-top: var(--wp--preset--spacing--60) !important;
		padding-bottom: var(--wp--preset--spacing--60) !important;
	}
}

/* Product grid gaps. WooCommerce hard-codes grid-gap:1.25em on its responsive
 * template; the design is 24px between columns and 40px between rows.
 *
 * The column track has to be recomputed with the gap, not just the gap
 * changed: WooCommerce's `minmax(max(150px, calc(33.33% - .83em)), 1fr)` bakes
 * its own 1.25em gap into that subtraction, so widening the gap alone makes
 * three columns no longer fit and auto-fill silently drops to two. For n
 * columns at gap g the track is `100%/n - g(n-1)/n`.
 */
.wc-block-product-template__responsive {
	grid-gap: var(--wp--preset--spacing--70) var(--wp--preset--spacing--50);
}

.wc-block-product-template__responsive.columns-3 {
	grid-template-columns: repeat(auto-fill, minmax(max(150px, calc(33.3333% - 16px)), 1fr));
}

.wc-block-product-template__responsive.columns-4 {
	grid-template-columns: repeat(auto-fill, minmax(max(150px, calc(25% - 18px)), 1fr));
}

/* Discover Our Collection is authored as a four-across row, which is right at
 * 1320 and wrong below it: auto-fill held four tracks down to 768, where a card
 * was 164px and a two-line product title did not fit one. The counts below step
 * it down instead — 3 from 900, 2 from 600 — and 2 rather than 1 on phones
 * because a visual catalogue loses its point at one card per screen
 * (responsive-spec.md §9, decision 1). The shop grid is untouched: it is
 * `columns-3` beside a sidebar and has its own arithmetic.
 */
@media (max-width: 1023px) {
	.hermizon-tabs .wc-block-product-template__responsive.columns-4 {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 599px) {
	.hermizon-tabs .wc-block-product-template__responsive.columns-4 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* The shop's worst band is the one just *above* the drawer breakpoint, and it
 * is easy to miss because nothing overflows. The moment the 312px sidebar
 * returns at 783 it takes a fixed bite out of a viewport that is barely wider
 * than the drawer's, and the three-across grid divides what is left:
 *
 *   768 (drawer, full width)   3 x 224px
 *   783 (sidebar returns)      3 x 141px
 *   900                        3 x 156px
 *   1024                       3 x 197px
 *
 * So a tablet held in portrait showed *smaller* product photographs than the
 * same tablet 15 pixels narrower. Two columns is the fix rather than a narrower
 * sidebar: at 900 it gives 246px cards against the 181px that trimming the
 * sidebar to 240 would have bought, and on a shoe catalogue the photograph is
 * the product. The sidebar keeps its measured 312 and its border.
 *
 * The band ends at 1100, where three columns are 296px — within a few pixels of
 * the 312 the design draws — and the same boundary the PDP already uses.
 */
@media (min-width: 783px) and (max-width: 1100px) {
	.hermizon-shop__sidebar ~ .wp-block-column .wc-block-product-template__responsive.columns-3 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* Shop filter sidebar — the bordered card in shop-page-spec.md §1.
 *
 * It cannot go on the block: `product-filters` replaces its own style
 * attribute with CSS custom properties at render time, so any border set
 * through block supports is discarded. The card treatment therefore lives on
 * the column, and only above 783px — inside the mobile drawer a border would
 * draw a box around the whole screen.
 */
@media (min-width: 783px) {
	.hermizon-shop__sidebar .wc-block-product-filters {
		/* 21, not 24 or 20 — and the frame's own arithmetic is what decides it.
		 * `shop-page-spec.md` §1 states a 312px card with a 268px inner column,
		 * and 312 − 268 − 2 borders leaves 42 to share. Measured on the frame:
		 * the card's left border is at x=140 and the first content edge at 162.
		 * Phase 14 learned the same lesson on the home page's pink card, whose
		 * padding is 59 rather than the 60 it looks like. */
		padding: 21px;
		border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
		border-radius: var(--wp--custom--radius--md);
	}
}

/* Facet rows — the checkbox, its label and the count.
 *
 * Four differences from what WooCommerce ships, all measured off the frame:
 *
 * 1. **The checkbox is an outlined white square**, 14px with a 1px `#202124`
 *    border. The block draws it as a filled `currentColor` wash at 10% opacity
 *    with a transparent border, which on this palette is a light grey block —
 *    it reads as *disabled*, which is the opposite of "you may pick this".
 * 2. **14px, not 16.** The input is sized in `em` against the label, and the
 *    label beside it is already `.875em`; the box was a size larger than its
 *    own text.
 * 3. **Row pitch is 30px.**
 * 4. **The count is right-aligned to the column edge**, not tucked against the
 *    label. With a count immediately after the word, a facet of ten terms has
 *    ten numbers at ten different x positions and none of them can be scanned.
 */
.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__items {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__label {
	display: flex;
	align-items: center;
	width: 100%;
	gap: 12px;
	min-height: 20px;
}

.hermizon-shop__sidebar input[type="checkbox"].wc-block-product-filter-checkbox-list__input {
	font-size: 0.875em;
	background: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--contrast);
}

/* The block paints this tint *behind* a transparent checkbox to fake a fill.
 * With a real border and a real background it is a grey square showing through
 * the corners of the radius. */
.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__input-wrapper::before {
	display: none;
}

.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__text-wrapper {
	flex: 1 1 auto;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--20);
	min-width: 0;
}

.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__count {
	color: var(--wp--preset--color--muted);
	font-variant-numeric: tabular-nums;
}

/* Colour, which the frame draws as a **two-column grid of bordered pills** —
 * 130 x 32 with an 8px column gap and an 11px row gap, summing to the 268px
 * inner column exactly. Every other facet is a plain list; colour is the one
 * facet whose values are a thing to look at rather than read, so it is worth
 * the width.
 *
 * The swatch becomes an 18px rounded square. The block draws a circle, and the
 * design draws a square everywhere colour appears — the card dots, the pills,
 * the product page. A round swatch beside a square one is the sort of thing
 * nobody can name and everybody notices.
 *
 * Scoped by `input[id^="attribute/color-"]` rather than by nth-child or a
 * heading match: it is the block's own record of which attribute it is
 * rendering, so a facet reordered in the template keeps its treatment and no
 * other attribute can accidentally inherit it.
 *
 * The obvious hook, `[data-wp-context*="attribute/color"]`, **does not match**.
 * That attribute holds JSON, so its real value contains `attribute\/color` — an
 * escaped slash — and a substring selector looking for the plain one finds
 * nothing. It fails silently: the facet renders as a plain list and every rule
 * below it is dead code. Caught by measuring `gridTemplateColumns` and getting
 * `null` back, which is the only way this kind of miss ever surfaces.
 */
.hermizon-shop__sidebar
	.wc-block-product-filter-checkbox-list__items:has(input[id^="attribute/color-"]) {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 11px 8px;
}

.hermizon-shop__sidebar
	.wc-block-product-filter-checkbox-list__items:has(input[id^="attribute/color-"])
	.wc-block-product-filter-checkbox-list__item {
	box-sizing: border-box;
	min-height: 32px;
	padding: 6px 8px;
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line-light);
	border-radius: var(--wp--custom--radius--sm);
}

.hermizon-shop__sidebar
	.wc-block-product-filter-checkbox-list__items:has(input[id^="attribute/color-"])
	.wc-block-product-filter-checkbox-list__label {
	gap: 9px;
	/* The pill is 6 + content + 6 + 2 borders, so the content box has to be 18
	 * for the pill to be 32. The label's own line box is 19.6 — 14px at the
	 * theme's 1.4 — which is what held it at 33.6, and no amount of padding
	 * arithmetic fixes a line box. */
	line-height: 18px;
	min-height: 18px;
}

/* The pill *is* the row, so the checkbox has nowhere to sit inside it and
 * nothing to add: the swatch already says which colour, and the pill's own
 * `:checked` state says whether it is chosen. The input stays in the document
 * — it is what a keyboard operates and what a screen reader announces — and is
 * made a zero-size clipped box rather than `display: none`, which would take it
 * out of the accessibility tree and out of the tab order along with it. */
.hermizon-shop__sidebar
	.wc-block-product-filter-checkbox-list__items:has(input[id^="attribute/color-"])
	.wc-block-product-filter-checkbox-list__input-wrapper {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
}

.hermizon-shop__sidebar
	.wc-block-product-filter-checkbox-list__items:has(input[id^="attribute/color-"])
	.wc-block-product-filter-checkbox-list__item:has(:checked) {
	border-color: var(--wp--preset--color--contrast);
}

.hermizon-shop__sidebar
	.wc-block-product-filter-checkbox-list__items:has(input[id^="attribute/color-"])
	.wc-block-product-filter-checkbox-list__item:has(:focus-visible) {
	outline: var(--wp--custom--state--focus-width) solid var(--wp--custom--state--focus);
	outline-offset: var(--wp--custom--state--focus-offset);
}

/* --------------------------------------------------------------------------
 * Product search results — the banner's search field.
 *
 * A `core/search` in button-inside mode nests the input and the submit button
 * in one `__inside-wrapper`, but the global form-control rule above still
 * gives the input its own border, background and radius — so the field drew
 * two boxes, and the red button looked like it hung outside the form. One
 * bordered box, owned here by the wrapper; the input inside it is bare.
 *
 * Sized and shaped after the search overlay's panel: 600px, radius-lg.
 * ----------------------------------------------------------------------- */

.hermizon-results-search {
	max-width: 600px;
	margin-inline: auto;
}

.hermizon-results-search .wp-block-search__inside-wrapper {
	background-color: var(--wp--preset--color--base);
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	padding: 6px;
	transition: border-color var(--wp--custom--transition--fast);
}

.hermizon-results-search .wp-block-search__inside-wrapper:focus-within {
	border-color: var(--wp--preset--color--contrast);
}

.hermizon-results-search .wp-block-search__input {
	border: 0;
	border-radius: 0;
	background-color: transparent;
	padding: 8px 12px;
}

/* The ring moves to the wrapper (`:focus-within` above) so it can wrap the
 * whole field instead of drawing a box that stops short of the button. */
.hermizon-results-search .wp-block-search__input:focus {
	outline: none;
}

.hermizon-results-search .wp-block-search__button {
	flex-shrink: 0;
	margin-left: 6px;
	padding: 8px 18px;
	border-radius: calc(var(--wp--custom--radius--lg) - 6px);
}

/* --------------------------------------------------------------------------
 * Phase 16 — the Style facet.
 *
 * The frame's first facet is a two-column grid of line-art tiles headed
 * **Style**, and `shop-page-spec.md` §2a used to say it could not be built:
 * `ProductFilterTaxonomy` sets no `visual` on its items, so a category facet
 * can only render text and a count. That is still true, and it turned out not
 * to matter — the *filter* stays WooCommerce's checkbox list, and the tile is
 * presentation, exactly as the Colour pills above are.
 *
 * Numbers read from `style-for-shop-page.png`, which Figma exported at
 * **268 x 691 — the facet's own inner-column width** — so nothing needed
 * scaling: tile **130 x 108**, column gap **8**, row gap **9**.
 * 130 + 8 + 130 = 268 and it closes exactly.
 * ----------------------------------------------------------------------- */

.hermizon-style-facet .wc-block-product-filter-checkbox-list__items {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 9px 8px;
}

.hermizon-style-facet .wc-block-product-filter-checkbox-list__item {
	box-sizing: border-box;
	height: 108px;
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line-light);
	border-radius: var(--wp--custom--radius--sm);
	transition: border-color var(--wp--custom--transition--fast);
}

/* The whole tile is the label, so the whole tile is the hit area — the pattern
 * the Colour pills already use in this sidebar. */
.hermizon-style-facet .wc-block-product-filter-checkbox-list__label {
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 14px;
	width: 100%;
	height: 100%;
	margin: 0;
	cursor: pointer;
}

/* Clipped to a pixel rather than `display: none`: the checkbox is what a
 * keyboard operates and what a screen reader announces, and hiding it outright
 * would take it out of the tab order along with the accessibility tree. */
.hermizon-style-facet .wc-block-product-filter-checkbox-list__input-wrapper {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
}

.hermizon-style-facet .wc-block-product-filter-checkbox-list__text-wrapper {
	justify-content: center;
	color: var(--wp--preset--color--muted);
}

/* The icon is a **mask**, not a background image. A data-URI SVG is its own
 * document, so `currentColor` inside it resolves against nothing and the icon
 * would be stuck at one colour; masking `currentColor` through the shape lets
 * the tile darken on hover and on selection like every other control here. */
.hermizon-style-facet .wc-block-product-filter-checkbox-list__label::before {
	content: "";
	flex: none;
	width: 44px;
	height: 44px;
	background-color: var(--wp--preset--color--contrast);
	-webkit-mask: var(--hermizon-tile) center / contain no-repeat;
	mask: var(--hermizon-tile) center / contain no-repeat;
}

.hermizon-style-facet .wc-block-product-filter-checkbox-list__item:hover,
.hermizon-style-facet .wc-block-product-filter-checkbox-list__item:has(:checked) {
	border-color: var(--wp--preset--color--contrast);
}

.hermizon-style-facet .wc-block-product-filter-checkbox-list__item:has(:checked)
	.wc-block-product-filter-checkbox-list__text-wrapper {
	color: var(--wp--preset--color--contrast);
}

.hermizon-style-facet .wc-block-product-filter-checkbox-list__item:has(:focus-visible) {
	outline: var(--wp--custom--state--focus-width) solid var(--wp--custom--state--focus);
	outline-offset: var(--wp--custom--state--focus-offset);
}

/* Which silhouette belongs to which category.
 *
 * Keyed on the item's own `for="taxonomy/product_cat-<slug>"`. **Not**
 * `data-wp-context`: that attribute holds JSON, so its value contains an
 * escaped slash and a substring selector against the plain one matches nothing
 * at all, silently (Phase 15 lost the whole Colour facet to exactly that).
 *
 * Five of the six are the designer's own drawings. The supplied
 * `design-exports/product-category/*.svg` are **not vector** — each is a `<rect>`
 * filled with a pattern wrapping a 512px base64 PNG, which is why an icon of a
 * shoe weighs 18-48 KB — so `scripts/trace-icons.py` pulls the raster back out
 * and traces it: threshold, march the 0.5 iso-contour, simplify. Filled rather
 * than stroked, because what is traced is the outline of the designer's own
 * stroke. **Flats is ours**: the ten supplied silhouettes include Slipper and
 * Sneakers but nothing that is a flat.
 *
 * The coupling to worry about: rename a category slug and its tile loses its
 * picture. It still renders and still filters — only the drawing goes.
 */
.hermizon-style-facet [for="taxonomy/product_cat-flats"] {
	--hermizon-tile: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M8.6 30.2c-.4-2.6.9-4.9 3.4-5.5 3.4-.8 6.5 1.6 10.4 3.1 4.3 1.6 9.6 1.4 13.6 2.2 2.6.5 3.9 1.7 3.5 3.1-.4 1.4-2.4 2.2-5.3 2.2H13.6c-3 0-4.6-1.6-5-4.1z' fill='none' stroke='%23000' stroke-width='2' stroke-linejoin='round'/><path d='M12.6 25c1.7 3.6 5.2 5.6 9.8 6.2' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round'/></svg>");
}

.hermizon-style-facet [for="taxonomy/product_cat-heels"] {
	--hermizon-tile: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M6.4 7.6 7.9 7.5 11.2 8.3 14.0 9.4 17.7 11.5 20.4 14.7 21.6 17.4 22.8 21.5 27.5 20.4 31.5 18.0 32.6 18.1 33.9 20.2 33.9 21.4 33.3 22.2 29.6 24.3 23.7 25.7 25.1 29.6 27.0 31.3 29.6 32.3 32.9 32.5 36.8 31.4 40.1 32.8 43.2 35.5 44.4 37.3 44.6 38.2 44.0 39.6 42.9 40.4 25.9 40.4 24.2 39.7 22.2 37.1 20.8 31.0 17.6 23.5 14.7 20.1 13.7 19.4 11.1 18.8 9.7 19.4 8.0 21.7 7.6 39.4 6.7 40.4 4.4 40.2 3.8 39.4 3.8 18.4 3.3 14.6 4.1 10.7 6.4 7.6ZM7.0 8.9 5.4 11.4 4.8 13.3 5.3 39.0 6.2 38.9 6.6 21.4 8.6 18.3 10.7 17.4 14.7 18.3 17.8 21.2 19.4 23.7 21.3 28.0 23.4 36.4 25.2 38.6 26.1 39.0 42.5 39.0 43.0 38.5 43.0 37.6 41.8 36.1 39.9 34.4 37.6 33.2 35.9 32.8 34.0 33.7 30.6 33.9 27.7 33.2 25.0 31.6 23.4 29.2 20.8 19.3 18.5 14.4 16.3 12.2 14.6 11.1 9.3 9.2 7.0 8.9ZM31.7 19.5 27.3 22.0 23.1 22.9 23.4 24.2 27.3 23.6 31.0 22.0 32.5 20.9 31.7 19.5Z' fill='%23000' fill-rule='evenodd'/></svg>");
}

.hermizon-style-facet [for="taxonomy/product_cat-pumps"] {
	--hermizon-tile: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M6.4 13.7 10.7 15.2 17.0 18.7 19.6 20.8 23.3 25.0 25.8 26.7 28.4 27.2 30.3 27.0 32.1 26.5 35.2 24.6 35.6 24.8 43.5 30.2 44.5 31.6 44.2 33.2 42.6 34.2 24.4 34.2 22.2 33.5 14.2 28.0 14.1 32.8 13.5 33.9 12.6 34.2 5.2 34.2 4.3 33.9 3.6 32.8 3.3 20.7 4.2 17.0 6.4 13.7ZM6.9 15.4 4.9 19.6 4.7 22.9 5.2 24.8 9.4 24.6 13.1 25.6 23.6 32.6 42.8 32.6 43.1 32.1 42.2 31.1 35.4 26.5 30.5 28.5 28.1 28.7 25.5 28.1 22.9 26.7 17.0 20.6 12.6 17.8 6.9 15.4ZM6.1 26.1 5.1 26.4 5.2 32.6 12.7 32.5 12.4 26.9 9.8 26.1 6.1 26.1Z' fill='%23000' fill-rule='evenodd'/></svg>");
}

.hermizon-style-facet [for="taxonomy/product_cat-juttis"] {
	--hermizon-tile: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M5.1 18.5 6.3 18.4 8.7 19.4 15.5 24.7 19.0 26.0 22.7 24.1 29.3 22.1 32.9 19.7 43.2 21.5 44.1 22.2 44.6 24.2 43.0 25.9 41.3 26.8 33.4 28.8 25.5 29.4 15.6 29.4 9.0 28.9 5.0 28.0 3.6 25.6 3.3 24.3 3.4 21.4 4.1 19.6 5.1 18.5ZM5.8 19.7 5.1 20.8 4.6 23.2 4.7 24.6 5.8 26.8 11.1 27.8 18.4 28.0 18.4 27.1 15.0 26.0 8.7 21.0 5.8 19.7ZM33.2 21.2 30.1 23.3 21.1 26.3 19.9 28.0 27.7 28.0 32.9 27.5 38.0 26.5 41.7 25.0 43.3 23.7 42.4 22.6 38.7 22.3 33.2 21.2Z' fill='%23000' fill-rule='evenodd'/></svg>");
}

.hermizon-style-facet [for="taxonomy/product_cat-wedges"] {
	--hermizon-tile: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M9.6 3.4 25.1 3.3 26.5 4.3 26.7 6.7 25.1 8.1 8.7 8.1 7.1 12.6 7.1 15.0 7.8 17.6 8.6 18.8 9.8 19.7 13.7 21.2 18.0 23.8 22.1 28.5 25.7 35.4 28.4 37.9 28.8 37.9 28.9 37.2 31.3 25.6 32.9 24.6 35.0 25.0 35.9 26.3 35.9 27.5 33.6 38.0 36.3 37.6 41.9 34.9 43.0 34.9 44.6 36.3 44.4 38.0 43.5 39.2 37.2 42.9 31.6 44.6 5.9 44.6 3.9 43.2 3.3 41.9 3.3 16.6 4.2 13.0 8.1 6.4 8.1 4.8 9.6 3.4ZM9.8 4.7 9.6 6.7 25.0 6.7 25.4 6.1 25.0 4.7 9.8 4.7ZM5.6 13.4 4.7 16.1 4.7 19.6 5.7 22.4 6.9 23.6 13.4 26.3 16.7 28.9 19.9 33.0 23.3 39.6 25.9 42.1 28.7 43.1 31.9 43.1 34.0 42.6 38.7 40.7 43.1 37.5 43.1 36.6 42.2 36.3 38.2 38.4 32.9 39.7 29.3 39.7 27.2 38.9 24.6 36.3 21.0 29.3 17.2 24.9 13.5 22.6 9.0 20.9 7.3 19.5 6.2 17.2 5.6 13.4ZM4.8 23.4 4.7 41.7 5.5 42.8 6.1 43.1 24.9 43.0 22.0 40.3 18.8 33.8 17.0 31.3 14.6 28.9 11.6 27.0 6.6 25.0 4.8 23.4ZM32.9 26.0 32.5 26.4 31.7 30.1 30.0 38.0 30.3 38.4 31.7 38.4 32.3 37.9 34.6 26.9 34.2 26.2 32.9 26.0Z' fill='%23000' fill-rule='evenodd'/></svg>");
}

.hermizon-style-facet [for="taxonomy/product_cat-mules"] {
	--hermizon-tile: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'><path d='M15.4 3.4 18.5 3.6 21.3 5.8 22.8 8.8 23.3 12.1 22.3 22.9 21.8 24.3 21.0 25.0 20.7 26.6 20.9 30.1 22.5 36.3 22.5 39.8 21.5 42.2 20.3 43.4 17.4 44.6 15.0 44.6 13.4 44.1 11.9 43.3 10.2 41.4 9.4 38.8 9.1 30.1 7.6 26.3 6.3 25.5 5.4 20.9 5.5 14.5 7.5 9.2 8.6 7.6 11.1 5.2 13.7 3.8 15.4 3.4ZM30.2 3.4 32.4 3.3 34.5 3.9 36.9 5.4 38.8 7.1 41.3 11.3 42.5 16.1 42.5 20.3 41.7 24.8 41.3 25.6 40.0 26.4 38.6 30.6 38.4 38.2 37.9 40.6 36.1 43.1 32.7 44.6 29.6 44.4 27.1 43.1 25.7 41.1 25.2 39.2 25.2 36.9 26.8 30.6 27.1 26.9 26.7 24.8 25.9 24.2 25.5 23.2 24.6 14.3 24.7 10.0 25.4 7.7 26.8 5.3 28.5 3.9 30.2 3.4ZM15.3 4.7 12.9 5.7 11.1 7.0 9.2 9.0 7.6 12.1 6.8 15.5 6.7 19.2 7.7 24.7 10.5 23.6 14.2 23.0 20.7 23.4 21.8 14.2 21.8 11.3 21.3 8.8 20.5 7.1 19.2 5.5 17.6 4.7 15.3 4.7ZM30.3 4.7 28.8 5.4 27.5 6.7 26.2 9.8 26.0 14.8 27.0 23.2 35.1 23.1 40.1 24.7 41.0 20.5 41.0 16.1 39.9 11.4 38.4 8.8 35.6 6.2 32.5 4.7 30.3 4.7ZM15.4 6.1 16.3 6.4 16.3 7.1 15.8 7.5 14.9 6.9 15.4 6.1ZM13.1 7.6 13.8 7.5 14.2 8.4 11.3 10.9 9.9 13.7 9.4 16.4 9.0 17.0 8.4 17.0 8.0 16.6 8.1 15.0 9.6 11.1 13.1 7.6ZM13.7 24.4 11.5 25.0 13.0 28.5 13.4 30.9 13.6 38.8 14.8 40.2 17.2 40.4 18.3 39.5 18.4 37.2 16.7 30.0 16.5 26.4 17.0 24.5 13.7 24.4ZM18.5 24.4 18.0 26.3 18.0 29.0 19.9 38.2 19.2 40.6 17.1 41.8 14.3 41.5 12.6 40.1 12.1 38.5 12.1 32.5 11.5 28.5 10.2 25.3 8.9 25.8 10.5 30.1 11.0 39.8 12.7 42.1 14.8 43.1 17.6 43.1 19.5 42.3 20.4 41.4 21.2 39.2 21.0 36.1 19.4 29.8 19.2 26.7 19.7 24.6 18.5 24.4ZM29.3 24.4 28.1 24.6 28.4 29.3 26.7 36.7 26.7 39.5 27.3 41.3 28.8 42.6 30.1 43.1 32.9 43.1 35.3 42.0 36.5 40.4 37.0 38.7 37.1 30.8 38.9 25.8 37.6 25.3 36.2 28.8 35.7 31.6 35.7 38.0 35.0 40.3 33.0 41.7 30.6 41.8 28.8 40.9 28.0 39.0 28.1 36.3 29.7 30.0 29.9 26.4 29.3 24.4ZM30.9 24.4 31.3 26.7 31.2 29.5 29.4 36.9 29.4 39.2 30.1 40.2 32.5 40.4 33.9 39.5 34.2 38.5 34.4 30.6 35.0 27.9 36.3 25.0 34.0 24.4 30.9 24.4Z' fill='%23000' fill-rule='evenodd'/></svg>");
}

/* Four tiles, then Show More — the frame's behaviour, and it has to be ours.
 * `ProductFilterCheckboxList::DISPLAY_LIMIT` is a hard `const 15` with no
 * filter, and items past the limit are **not rendered into the page at all**,
 * so even borrowing the block's own button would reveal nothing. With six
 * categories the native control never appears.
 *
 * All six tiles are therefore in the document and CSS hides the last two. The
 * toggle is a checkbox because it needs **no JavaScript** — the same reasoning
 * that made every facet here a `core/details` in Phase 5. It degrades in both
 * directions: with no CSS all six show, and with no JS the control still works.
 */
.hermizon-style-more {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
}

.hermizon-style-facet .wc-block-product-filter-checkbox-list__item:nth-child(n + 5) {
	display: none;
}

.hermizon-style-facet:has(.hermizon-style-more:checked)
	.wc-block-product-filter-checkbox-list__item:nth-child(n + 5) {
	display: block;
}

.hermizon-style-more__label {
	display: block;
	width: fit-content;
	margin: var(--wp--preset--spacing--40) auto 0;
	color: var(--wp--preset--color--contrast);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: underline;
	cursor: pointer;
}

.hermizon-style-more__label:hover {
	text-decoration: none;
}

.hermizon-style-more:focus-visible + .hermizon-style-more__label {
	outline: var(--wp--custom--state--focus-width) solid var(--wp--custom--state--focus);
	outline-offset: var(--wp--custom--state--focus-offset);
}

/* One label, two words, and only ever one of them painted. */
.hermizon-style-more__label .hermizon-style-more__less,
.hermizon-style-more:checked + .hermizon-style-more__label .hermizon-style-more__more {
	display: none;
}

.hermizon-style-more:checked + .hermizon-style-more__label .hermizon-style-more__less {
	display: inline;
}

/* Six terms fit in three rows, so the toggle only earns its place while two are
 * hidden. If a seventh category ever exists this still holds; if two are ever
 * deleted, the control has nothing to reveal and removes itself. */
.hermizon-style-facet:not(:has(.wc-block-product-filter-checkbox-list__item:nth-child(5)))
	.hermizon-style-more__label {
	display: none;
}

/* 18px, and `box-sizing` is what makes it 18 rather than 20: the swatch carries
 * its own 1px border and the theme ships no reset, so a stated width has the
 * border added outside it. **The box-sizing trap, seventh occurrence** — and
 * the two extra pixels are what put the pill at 34px against the frame's 32. */
.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__color-swatch {
	box-sizing: border-box;
	width: 18px;
	height: 18px;
	border-radius: var(--wp--custom--radius--sm);
	margin-right: 0;
}

/* The price slider is laid out for a full-width container and overflows a
 * 312px one by 154px. `max-width` does not help: its inner element is a grid
 * item spanning `grid-template-columns: 221px 0 221px`, so a percentage
 * resolves against a 466px grid area rather than the column. The fix is the
 * tracks — same three-track structure, allowed to shrink.
 */
.hermizon-shop__sidebar .wc-block-product-filter-price-slider__content {
	grid-template-columns: minmax(0, 1fr) 0 minmax(0, 1fr);

	/* The frame puts the two value fields **above** the slider; WooCommerce
	 * puts them below, and its own `grid-template-areas` is what decides it.
	 * Swapping the two rows is the whole change — the DOM order is already
	 * left-input, slider, right-input, which is the focus order the block's
	 * source says it went out of its way to get right, and named areas move
	 * the paint without touching it.
	 *
	 * The frame also repeats the two numbers as plain text *under* the slider.
	 * That is not built: it is the same two values a second time, and a second
	 * live copy would need its own binding to the same state for no information
	 * a shopper does not already have on the line above. */
	grid-template-areas:
		"left-input   middle-input right-input"
		"price-slider price-slider price-slider";

	/* 121 + 26 + 121 = 268, and that closes the frame's own arithmetic exactly.
	 * Core's 12px would make the fields 122 — and the middle track is
	 * zero-width, so the visible gap between them is *two* column gaps. */
	column-gap: 13px;
}

/* 121 x 32 with the ৳ inside, against the block's own 60px cap — which on a
 * 268px column left two small boxes adrift at either end of a wide gap.
 * `box-sizing` is stated because the theme ships no reset and this input
 * declares a width. */
/* `.wp-block-woocommerce-…`, not `.wc-block-…`. **The BEM base class is not in
 * the document**: the block wrapper carries only
 * `wp-block-woocommerce-product-filter-price-slider`, while every child carries
 * `wc-block-product-filter-price-slider__…`. So WooCommerce's own
 * `.wc-block-product-filter-price-slider .text input[type=text] { max-width:
 * 60px }` has never applied on this install either — the 60px cap this rule was
 * written to beat was already dead. The `wc-block-…` prefix trap, third
 * occurrence on this build after the notices and the empty state. */
.hermizon-shop__sidebar .wp-block-woocommerce-product-filter-price-slider .text input[type="text"] {
	box-sizing: border-box;
	width: 100%;
	max-width: none;
	height: 32px;
	padding: 6px 10px;
	border-color: var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--preset--color--contrast);
}

/* The track and the handle. Core draws a 4px bar of `currentColor` — on this
 * palette a heavy black rule across the column — with a 12px white handle in a
 * 2px `#1e1e1e` ring. The frame draws a **1px muted line**, which is right: the
 * thing a shopper drags is the handle, and a 4px bar competes with the input
 * boxes directly above it for the same meaning. */
.hermizon-shop__sidebar .wc-block-product-filter-price-slider__range {
	--wc-product-filter-price-slider: var(--wp--preset--color--muted);
	--wc-product-filter-price-slider-handle: var(--wp--preset--color--base);
	--wc-product-filter-price-slider-handle-border: var(--wp--preset--color--muted);

	height: 1px;
	margin-block: 20px;
}

.hermizon-shop__sidebar .wc-block-product-filter-price-slider__range .range-bar {
	height: 1px;
}

.hermizon-shop__sidebar .wc-block-product-filter-price-slider__range::before {
	opacity: 0.25;
}

/* The handle is positioned against a 4px track by core's own negative margin,
 * so thinning the track drops it half out of line. */
.hermizon-shop__sidebar .wc-block-product-filter-price-slider__range input[type="range"]::-webkit-slider-thumb {
	width: 10px;
	height: 10px;
	border-width: 1.5px;
	margin-top: -6px;
}

.hermizon-shop__sidebar .wc-block-product-filter-price-slider__range input[type="range"]::-moz-range-thumb {
	width: 10px;
	height: 10px;
	border-width: 1.5px;
}

.hermizon-shop__sidebar .wp-block-woocommerce-product-filter-price-slider,
.hermizon-shop__sidebar .wp-block-woocommerce-product-filter-price-slider * {
	max-width: 100%;
	box-sizing: border-box;
}

/* Facet sections.
 *
 * The design gives every sidebar section a minus icon and a 1px rule beneath
 * it. The filter blocks have no collapse affordance of their own, so each facet
 * is wrapped in `core/details`, open by default exactly as the frame draws it —
 * native disclosure, no JavaScript, and a real escape on a phone where nine
 * open facets is a long scroll inside the drawer.
 *
 * The rule goes on the *top* of every facet that has a visible facet before it,
 * rather than the bottom of all of them: an empty facet renders with
 * `wc-block-product-filter--hidden` (Rating, until a review exists) and a
 * bottom border would leave a hairline floating above the card's padding.
 */
.hermizon-shop__sidebar
	.wc-block-product-filters__overlay-content
	> *:not(.wc-block-product-filter--hidden)
	~ *:not(.wc-block-product-filter--hidden)
	.hermizon-facet {
	padding-block-start: var(--wp--preset--spacing--50);
	border-block-start: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
}

.hermizon-facet > summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--30);
	margin-block-end: var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 500;
	cursor: pointer;
	list-style: none;
}

/* Safari still needs the vendor pseudo-element to drop the disclosure triangle. */
.hermizon-facet > summary::-webkit-details-marker {
	display: none;
}

/* The frame's own icon: minus when open, plus when closed. */
.hermizon-facet > summary::after {
	content: "+";
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1;
}

.hermizon-facet[open] > summary::after {
	content: "\2212";
}

/* Every `wc-visual` term carries a `visual` key even when it holds nothing, so
 * WooCommerce draws an empty crossed-out swatch beside Size, Occasion, Material
 * and Craft — 25 of them — and beside the two colours that have no hex.
 * `is-empty` marks exactly those, and none of them means anything to a shopper.
 */
.hermizon-shop__sidebar .wc-block-product-filter-checkbox-list__color-swatch.is-empty {
	display: none;
}

/* A size is not a colour.
 *
 * Same root cause as the Shop sidebar (shop-page-spec.md §2z-6): every
 * `wc-visual` term carries a `visual` key even when it holds nothing, so
 * `ProductFilterChips::has_visual_swatches()` returns true and the chips take
 * `is-style-swatch` — which draws a crossed-out circle and clips the label out
 * of view with a screen-reader-only rect.
 *
 * On the product page that left **six blank circles where the six sizes should
 * be**, on a catalogue where every product is variable and size is the only
 * axis: nothing could be selected, so nothing could be added to the cart. The
 * Shop sidebar avoids it by using checkbox lists; the variation selector has no
 * such choice, because `add-to-cart-with-options` generates its own inner
 * blocks and chips is what it generates.
 *
 * So: any chip whose swatch is empty stops pretending to be a swatch. `:has()`
 * is what makes this per-item rather than per-block — a colour attribute with
 * one missing hex keeps its swatches and shows a label only where it must.
 */
.wc-block-product-filter-chips__item:has(.wc-block-product-filter-chips__swatch--no-color) {
	min-width: 3rem;
	padding: 0.4em 0.9em;
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--sm);
}

.wc-block-product-filter-chips__item:has(.wc-block-product-filter-chips__swatch--no-color) .wc-block-product-filter-chips__swatch--no-color {
	display: none;
}

.wc-block-product-filter-chips__item:has(.wc-block-product-filter-chips__swatch--no-color) .wc-block-product-filter-chips__text {
	position: static;
	width: auto;
	height: auto;
	overflow: visible;
	clip: auto;
	clip-path: none;
	white-space: nowrap;
}

/* And a colour is more than a circle (Phase 20). The frame labels every
 * colour chip — swatch dot beside the name, Black · Golden · Olive — while
 * the swatch style ships the name inside a screen-reader rect, which left
 * the PDP offering nameless dots. Decided 2026-08-14 with the owner: show
 * both, per the frame, rather than a hover tooltip the design never drew.
 *
 * Scoped to the variation selector: the Shop sidebar's chips and facets have
 * their own treatments, and the quick-view dialog renders a plain form. The
 * dot keeps an inset hairline so Silver stays visible on the white chip.
 */
.wp-block-woocommerce-add-to-cart-with-options .wc-block-product-filter-chips__item:has(.wc-block-product-filter-chips__swatch:not(.wc-block-product-filter-chips__swatch--no-color)) {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	width: auto;
	height: auto;
	min-width: 0;
	padding: 6px 14px 6px 8px;
	background-color: var(--wp--preset--color--base);
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--sm);
	transition: border-color var(--wp--custom--transition--fast);
}

.wp-block-woocommerce-add-to-cart-with-options .wc-block-product-filter-chips__item:has(.wc-block-product-filter-chips__swatch:not(.wc-block-product-filter-chips__swatch--no-color)):hover {
	border-color: var(--wp--preset--color--contrast);
}

/* The selected ring is a box-shadow so choosing a colour moves no layout. */
.wp-block-woocommerce-add-to-cart-with-options .wc-block-product-filter-chips__item[aria-checked="true"]:has(.wc-block-product-filter-chips__swatch:not(.wc-block-product-filter-chips__swatch--no-color)) {
	border-color: var(--wp--preset--color--contrast);
	box-shadow: 0 0 0 1px var(--wp--preset--color--contrast);
}

.wp-block-woocommerce-add-to-cart-with-options .wc-block-product-filter-chips__item .wc-block-product-filter-chips__swatch:not(.wc-block-product-filter-chips__swatch--no-color) {
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	border-radius: var(--wp--custom--radius--pill);
	box-shadow: inset 0 0 0 1px rgb(0 0 0 / 12%);
}

.wp-block-woocommerce-add-to-cart-with-options .wc-block-product-filter-chips__item:has(.wc-block-product-filter-chips__swatch:not(.wc-block-product-filter-chips__swatch--no-color)) .wc-block-product-filter-chips__text {
	position: static;
	width: auto;
	height: auto;
	overflow: visible;
	clip: auto;
	clip-path: none;
	white-space: nowrap;
	font-size: var(--wp--preset--font-size--small);
}

/* "Shop by Style" tiles — shop-page-spec.md §2a. A category filter can only
 * render text and a count, so the design's line-art tiles moved out of the
 * sidebar and above the grid, where a pattern can carry any image.
 *
 * The tile is a fixed square whatever it holds, so a row of six stays a row of
 * six whether the images exist or not: with a photograph it crops to cover,
 * without one it is the banner's own #FFEFEF wash — inline per decision C8,
 * which keeps the section tints out of the colour picker. Three of the six
 * categories have an image today.
 */
.hermizon-style-tile {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.hermizon-style-tile__media {
	display: block;
	overflow: hidden;
	aspect-ratio: 1;
	background-color: #FFEFEF;
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	transition: border-color var(--wp--custom--transition--fast);
}

.hermizon-style-tile img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.hermizon-style-tile__label {
	font-size: var(--wp--preset--font-size--small);
	text-align: center;
}

.hermizon-style-tile:hover .hermizon-style-tile__media,
.hermizon-style-tile:focus-visible .hermizon-style-tile__media {
	border-color: var(--wp--preset--color--contrast);
}

.hermizon-style-tile:hover .hermizon-style-tile__label {
	text-decoration: underline;
}

/* On a phone the tile row was **608px tall and sat between the filter toggle
 * and the first product**, so the catalogue began at roughly 1248px and every
 * phone shopper scrolled past six squares to reach it (Phase 8 §7). The frame
 * draws no mobile layout at all, so what replaces it is ours to decide.
 *
 * A horizontal scroller: same six tiles, same order, same links, one row deep.
 * The tile stops being a square — a label under a 1:1 image is what made it
 * 186px tall — and becomes a wide thumbnail, which is also the shape a shopper
 * swipes along. Measured after: the row is ~120px and the grid starts a
 * screenful earlier.
 *
 * `scroll-snap` on the row rather than free scroll, because a half-cropped
 * tile at rest reads as a rendering fault rather than an invitation. The
 * negative margin plus matching padding is what lets the first tile line up
 * with the page's content edge while the strip still runs to the viewport
 * edge — a scroller that stops short of the edge looks like it has ended.
 */
@media (max-width: 600px) {
	/* Two classes deliberately. Core prints the pattern's `layout: grid` as
	 * `.wp-container-core-group-is-layout-xxx { display: grid }` — a single
	 * class, in a `<style>` block whose position relative to this file is not
	 * something a theme should bet on. Phase 5 lost an afternoon to exactly
	 * this with the sidebar sort. */
	.wp-block-group.hermizon-style-row {
		display: flex;
		flex-wrap: nowrap;
		gap: var(--wp--preset--spacing--30);
		margin-inline: calc(-1 * var(--wp--preset--spacing--50));
		padding-inline: var(--wp--preset--spacing--50);
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scrollbar-width: none;
	}

	.wp-block-group.hermizon-style-row::-webkit-scrollbar {
		display: none;
	}

	.wp-block-group.hermizon-style-row .hermizon-style-tile {
		flex: 0 0 auto;
		width: 104px;
		scroll-snap-align: start;
	}

	.hermizon-style-tile__media {
		aspect-ratio: 4 / 3;
	}
}

/* Pagination. The frame draws one strip of adjacent square cells with shared
 * borders — not spaced buttons — so the gap is zero and each cell pulls itself
 * 1px into its neighbour to collapse the two borders into one. The current page
 * takes the dark border from the design and a stacking level, or the collapsed
 * neighbour would draw over it.
 *
 * `showLabel: false` on the parent leaves the arrow as the only content, and
 * core still ships `margin-right: 1ch` on it for the label that is no longer
 * there; without resetting it the glyph sits off-centre in its cell. The arrow
 * links keep their `aria-label`, which core adds precisely when the label is
 * hidden.
 *
 * On page 1 there is no previous cell at all: core renders nothing rather than
 * a disabled control, and a decorative dead cell is not worth custom markup.
 */
.hermizon-pagination,
.hermizon-pagination .wp-block-query-pagination-numbers {
	display: flex;
	gap: 0;
}

.hermizon-pagination .page-numbers,
.hermizon-pagination .wp-block-query-pagination-previous,
.hermizon-pagination .wp-block-query-pagination-next {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-width: 38px;
	height: 38px;
	padding: 0 0.5rem;
	margin-inline-start: -1px;
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
}

.hermizon-pagination .wp-block-query-pagination-previous-arrow,
.hermizon-pagination .wp-block-query-pagination-next-arrow {
	margin: 0;
}

.hermizon-pagination .page-numbers.current {
	position: relative;
	z-index: 1;
	border-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
}

.hermizon-pagination a:hover,
.hermizon-pagination a:focus-visible {
	position: relative;
	z-index: 1;
	border-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--contrast);
}

/* --------------------------------------------------------------------------
 * Phase 15 — the Shop page pixel pass.
 * Every number below was read off `design-exports/shop-figma.png` (node
 * 722:233) by pixel scan and then measured back in the browser.
 * ----------------------------------------------------------------------- */

/* The page banner.
 *
 * The frame sets "Shop" at the same 32px the theme already gives it, but at
 * **regular** weight — measured by stem width, 2–3px against the built 4px.
 * `elements.heading.fontWeight: 500` in theme.json is right for section
 * headings and wrong for this one word at display size, so it is overridden
 * here rather than in the token, which every other heading depends on.
 */
.wp-block-cover .wp-block-query-title {
	font-weight: 400;
}

/* The breadcrumb.
 *
 * The frame marks each crumb with a bullet and no separator between them; the
 * delimiter is emptied in `Storefront::breadcrumb_defaults()` and the bullet
 * drawn here, on the item, because a leading marker is not something
 * `delimiter` can express. The parent crumb is muted and unadorned — the
 * underline core gives it fights the bullets for a reader's attention in a
 * line this small, and the crumb is a link whether or not it is underlined:
 * hover and focus restore it, which is where the affordance actually matters.
 */
/* The nav's own `display` is left alone, deliberately.
 *
 * Two attempts to set it lost. WooCommerce ships
 * `.woocommerce.woocommerce-shop .wc-block-breadcrumbs .woocommerce-breadcrumb
 * { display: block }` — **four classes** — so both a bare `.woocommerce-breadcrumb`
 * and a two-class version were outranked, and the failure was quiet in the
 * worst way: `justify-content: center` applied and the `display: flex` it needs
 * did not, so the crumbs ran together as "HomeShop All" while a centring
 * declaration sat in the computed style doing nothing.
 *
 * Rather than climb to five classes and leave the next person a selector nobody
 * can read, the spacing moves onto the crumbs themselves. Nothing in
 * WooCommerce styles those — they are ours, emitted by
 * `Storefront::breadcrumb_defaults()` — so there is no specificity race to
 * lose. **WooCommerce beats a single-class theme rule**, recorded for the
 * fourth time on this build; this is the first time the answer was to stop
 * fighting it.
 */
.wc-block-breadcrumbs {
	text-align: center;
	color: var(--wp--preset--color--contrast);
}

.hermizon-crumb {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.hermizon-crumb + .hermizon-crumb {
	margin-inline-start: var(--wp--preset--spacing--30);
}

.hermizon-crumb::before {
	content: "";
	width: 3px;
	height: 3px;
	border-radius: 50%;
	background: currentColor;
}

.hermizon-crumb a {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

.hermizon-crumb a:hover,
.hermizon-crumb a:focus-visible {
	color: var(--wp--preset--color--contrast);
	text-decoration: underline;
}

/* The Sale badge — shop-page-spec.md §7: #CE1A32, white, 14px, top-right.
 *
 * WooCommerce ships it as a white pill with a grey border and grey text, and
 * that is what this store rendered: **a badge whose whole job is to be seen,
 * white on a white card**. It was invisible until the Discover seed (E75) put
 * products on sale and a screenshot was read — nothing was measuring it,
 * because a badge that renders at the right size passes every geometry check.
 *
 * The block's own wrapper is a 0-height flex row and the pill inside it is
 * absolutely positioned, so the inset belongs to the pill.
 */
.wc-block-components-product-sale-badge {
	padding: 5px 12px;
	border: 0;
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 1.2;
}

.wc-block-components-product-sale-badge__text {
	color: inherit;
}

/* The inset needs three classes, and the reason is subtle enough to be worth
 * writing down. WooCommerce positions the badge with **physical** `top` and
 * `right` from a two-class rule; the first attempt here used the **logical**
 * `inset-block-start` / `inset-inline-end` from a one-class rule. Logical and
 * physical longhands for the same side cascade together, so this was never two
 * properties coexisting — it was one contest, lost on specificity, and the
 * badge stayed at WooCommerce's 4px while the declaration sat in the
 * stylesheet looking applied.
 *
 * The frame insets it 10. Scoped to the product image so the card, the PDP and
 * the home rails all agree. */
.wc-block-components-product-image .wc-block-components-product-sale-badge.alignright {
	inset-block-start: 10px;
	inset-inline-end: 10px;
}

/* The product card, and its hover surface.
 *
 * The frame draws its **first** card on a white surface with a `#F0F0F0`
 * border, an 8px radius and `0 14px 24px rgba(0,0,0,.08)`, and the other
 * fourteen with nothing at all. That is a hover state drawn once, not a card
 * style drawn wrong — a static treatment on all fifteen would be a wall of
 * boxes, and the design is plainly not that.
 *
 * Measured off the frame: the surface is **exactly the 312px column, flush with
 * the image on all three sides**, running from the image's top edge to 24px
 * below the colour dots. So there is no horizontal padding, and the border has
 * to be present at all times and merely colourless until hover — a border that
 * appears on hover is 2px of layout arriving under the pointer, and every card
 * to its right jumps.
 */
.wc-block-product-template > li {
	box-sizing: border-box;
	position: relative;
	padding-block-end: var(--wp--preset--spacing--50);
	border: var(--wp--custom--border--width) solid transparent;
	border-radius: var(--wp--custom--radius--md);
	transition:
		border-color var(--wp--custom--transition--base),
		box-shadow var(--wp--custom--transition--base);
}

.wc-block-product-template > li:hover,
.wc-block-product-template > li:focus-within {
	border-color: var(--wp--preset--color--line-light);
	box-shadow: 0 14px 24px rgb(0 0 0 / 8%);
}

.wc-block-product-template > li:hover .hermizon-card-actions,
.wc-block-product-template > li:focus-within .hermizon-card-actions {
	visibility: visible;
	opacity: 1;
	transform: none;
}

/* The price row. The frame centres it and sets the current price in the brand
 * red with the original struck through beside it in `muted` — which is what a
 * sale looks like everywhere, and what WooCommerce renders in neither colour.
 *
 * `<ins>` also arrives underlined from the user agent, directly beneath a
 * struck-through sibling: two lines through two numbers, one meaning "this one"
 * and one meaning "not this one". */
.wc-block-product-template .wc-block-components-product-price {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
}

.wc-block-product-template .wc-block-components-product-price ins {
	color: var(--wp--preset--color--brand);
	text-decoration: none;
}

.wc-block-product-template .wc-block-components-product-price del {
	color: var(--wp--preset--color--muted);
}

/* The colour dots — `hermizon/product-swatches`, built in Phase 6 for E28 and
 * **never placed on a surface until now**. The block hides itself below two
 * colourways, which today is 51 of 56 published products, so most cards show
 * nothing and that is the decision working rather than the block failing. */
.wc-block-product-template .hermizon-swatches {
	justify-content: center;
}

/* Sort renders twice and is never visible twice. The design draws it in the
 * sidebar ("Short By", above Colour); every WooCommerce store puts it above
 * the grid — decided 2026-08-11 to keep both, one per breakpoint.
 *
 * The swap happens at 601px because that is the filter block's own drawer
 * breakpoint, read from `product-filters-style.css`, not the 783px used for
 * the sidebar card. Below it the sidebar *is* the drawer, so the sidebar copy
 * would put sort two taps behind a modal; the copy above the grid takes over.
 *
 * `display: none` also removes the hidden one from the accessibility tree, so
 * exactly one `<select name="orderby">` is ever exposed — the block renders no
 * `id`, so the duplicate is otherwise harmless.
 */
@media (min-width: 601px) {
	.hermizon-sort--grid {
		display: none;
	}
}

/* Three classes, because the block ships
 * `:where(.wc-block-product-filters) .wc-block-product-filters__content
 * .wp-block-group { display: block }` inside this same breakpoint — (0,2,0),
 * which outranks a single class and left the sidebar sort visible inside the
 * drawer next to the one above the grid. Measured in the browser; every static
 * check passed. */
@media (max-width: 600px) {
	.hermizon-shop__sidebar .wc-block-product-filters .hermizon-sort--sidebar {
		display: none;
	}
}

.hermizon-sort--sidebar .woocommerce-ordering,
.hermizon-sort--sidebar select.orderby {
	width: 100%;
	max-width: 100%;
	box-sizing: border-box;
}

/* Buttons on the product page. responsive-spec.md §5: the design forces width
 * with `padding: 16px 230px`, which overflows every viewport below ~500px.
 * Width comes from the container instead, with real padding from theme.json. */
.wp-block-woocommerce-add-to-cart-with-options .wp-element-button {
	flex: 1 1 auto;
	justify-content: center;
	min-width: 12rem;
}

/* The navigation overlay, at and below 900px.
 *
 * **The theme sets this boundary, not core, and it is measured rather than
 * adopted.** `overlayMenu: "mobile"` collapses at 600 — two `min-width: 600px`
 * blocks in core's navigation stylesheet, one showing the closed container inline
 * and one hiding the hamburger. That left everything from 601 up rendering the
 * full row, and the row does not fit there: measured 131px tall, with "Contact
 * Us" wrapping onto its own line, at 620, 660, 720, 782 — and at 783 as well.
 *
 * responsive-spec.md §2 asks for the overlay at md and the inline row at lg,
 * which starts at 783. **That assumed the row fits at 783 and it does not.**
 * Widened one pixel at a time, the wrap clears at **813**: logo 185 + gap 40 +
 * nav 355 + gap 40 + icons 142 = 762, plus 2 × 24 root padding. So the boundary
 * is 900 — the width this build already uses for the mega menu's promo tiles, so
 * the header has one boundary instead of two, and 88px of headroom over the
 * measurement rather than none.
 *
 * **It will have to be re-measured if the nav grows.** Four items ship; the
 * design draws six, and both withheld items have return conditions (E61). Six
 * needs roughly 1,000px, which is past this boundary.
 *
 * The two rules that move the collapse are scoped to `.hermizon-header`, which
 * outranks core's own selectors on specificity rather than on stylesheet order,
 * and they leave any other navigation on the site with core's defaults.
 *
 * Only the *closed* state needs overriding. Everything core needs for an open
 * overlay is width-independent — `position: fixed; inset: 0` on the container,
 * `display: flex` and `z-index: 100000` on `.is-menu-open`, `position: relative`
 * on the dialog — which is why an overlay opened at 599 and widened stays correct
 * today.
 *
 * The accordion's own band moves with this one, in the mega menu block
 * (`max-width: 900px`), as do the E59 static resets (`min-width: 901px`).
 *
 * Two more things core does not get right here, and neither was visible until the
 * mega menu put a full-width panel inside the overlay.
 *
 * **It has no horizontal padding.** Core intends `clamp(1rem,
 * var(--wp--style--root--padding-left), 20rem)`, and on this build that
 * computes to 0 — the custom property is set on `body`, not `:root`. Nothing
 * noticed while every item was a centred, content-width label; the panel
 * stretches, so its links landed flat against the viewport edge. Measured.
 *
 * **And it inherits the desktop row's centring.** `justifyContent: center` is
 * right for a row of five labels and wrong for a column containing an
 * eighteen-link accordion, which is unscannable centred. The design draws no
 * phone layout at all (responsive-spec.md), so this is ours to decide: the
 * overlay is left-aligned.
 */
@media (max-width: 900px) {
	.hermizon-header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}

	.hermizon-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	.hermizon-header .wp-block-navigation__responsive-container.is-menu-open {
		padding-inline: var(--wp--preset--spacing--50);
	}

	.hermizon-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
		align-items: flex-start;
	}
}

/* Header: this is not the overlay breakpoint — that is 782px, above. It is where
 * the row itself runs out of room. Collapsed, the row is logo | menu toggle |
 * three icons, which measures about 431px and fits a 601px viewport with room to
 * spare; a phone is where the gap and the wordmark have to give way first. */
@media (max-width: 600px) {
	/* The row only. `.hermizon-header .wp-block-group.is-nowrap` matched the
	 * utility group as well, which is also nowrap, so the three icons were pushed
	 * to a 12px gap where the design sets 8 — measured, both groups computing
	 * 12px. The row is a direct child of the header; the utility group is a level
	 * deeper. */
	.hermizon-header > .wp-block-group.is-nowrap {
		gap: var(--wp--preset--spacing--30);
	}

	.hermizon-header .wp-block-site-logo img {
		width: 132px;
		height: auto;
	}

	/* Phase 10 needed three rules here to stop core's expanding search field
	 * overflowing the row — measured at scrollWidth 443 against innerWidth 390 —
	 * including a `:has()` pair that hid the wordmark and the menu toggle while
	 * the field was open. Phase 11 replaced the field with an overlay that takes
	 * no room in the row at all, so all three are gone. `min-width: 0` stays:
	 * the utility group is still a flex item that must be allowed to shrink. */
	.hermizon-header__utility {
		min-width: 0;
	}
}

/* Footer: five columns stack natively at 782px.
 *
 * **E14, open since Phase 4, closed here.** Stacked, the five columns are one
 * 1,200px scroll of links between the last product and the bottom of the page;
 * the design's own mobile answer is an accordion, and the note that used to
 * stand here said the tool for it did not exist. It does — `core/details` is
 * what the Shop sidebar's ten facets have been built from since Phase 5.
 *
 * The markup ships `open`, so **the desktop layout is unchanged and the
 * no-CSS state is everything visible**. What changes below 782px is only that
 * the disclosure becomes operable.
 *
 * Above it the summary is inert: no marker, no pointer cursor, and
 * `pointer-events: none` so a click cannot collapse a column on a layout the
 * frame draws open. `::details-content` restates the open state for the one
 * case CSS can otherwise not reach — a shopper who collapses a section on a
 * phone and then widens the window, who would otherwise be left with a
 * section that is closed and, with the summary inert, unopenable. Firefox has
 * not shipped that pseudo-element; there the section stays closed until it is
 * clicked at a narrow width again, which is why `pointer-events` is the *only*
 * thing making it inert and the element is never actually disabled.
 */
@media (max-width: 781px) {
	.hermizon-footer .wp-block-columns {
		gap: var(--wp--preset--spacing--40);
	}

	.hermizon-footer__section {
		border-block-end: var(--wp--custom--border--width) solid var(--wp--preset--color--footer-rule);
		padding-block-end: var(--wp--preset--spacing--40);
	}
}

.hermizon-footer__section > summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--inter-tight);
	font-weight: 500;
	line-height: 1.2;
	list-style: none;
}

.hermizon-footer__section > summary::-webkit-details-marker {
	display: none;
}

/* Same glyph pair as the Shop sidebar's facets, so a disclosure means the same
 * thing in both places on this site. */
.hermizon-footer__section > summary::after {
	content: "+";
	color: var(--wp--preset--color--footer-muted);
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1;
}

.hermizon-footer__section[open] > summary::after {
	content: "\2212";
}

@media (min-width: 782px) {
	.hermizon-footer__section > summary {
		cursor: default;
		pointer-events: none;
	}

	/* `[open]` too, and that is the whole point: the open-state rule that swaps
	 * the plus for a minus is `.hermizon-footer__section[open] > summary::after`
	 * — one class *and* one attribute — so an unqualified override loses to it
	 * and the desktop footer kept a "−" beside every column heading. It read as
	 * a control on a layout where nothing can be collapsed. Caught in a
	 * screenshot; no assertion was pointed at a pseudo-element. */
	.hermizon-footer__section > summary::after,
	.hermizon-footer__section[open] > summary::after {
		content: none;
	}

	.hermizon-footer__section::details-content {
		content-visibility: visible;
		block-size: auto;
	}
}

/* --------------------------------------------------------------------------
 * Mini-cart drawer — commerce-ux-spec.md §5.
 * The drawer itself needs no styling: it already inherits the theme font, the
 * 8px radius and the brand red on "Go to checkout" through theme.json. The one
 * thing it does need is a box-sizing declaration.
 * ----------------------------------------------------------------------- */

/* The quantity stepper. WooCommerce lays this control out with flex and budgets
 * 30 + 40 + 30 for minus, field and plus; theme.json's input padding then lands
 * on a *content-box* input, so 32px of horizontal padding is added outside the
 * 40 and the field renders 72px wide. The plus button is pushed 26px past the
 * stepper's own 1px border, and the remove button then overlaps it by 14px —
 * which means the right edge of "+" deletes the line instead of incrementing
 * it. Measured stable at 1600 and 390, at 2.5s and 8.5s after the drawer opens.
 *
 * This is the box-sizing trap for the fourth time (Phase 6 twice, Phase 5 once):
 * the theme ships no `* { box-sizing: border-box }` reset, so any control that
 * states a width must declare its own. The field centres its own text, so the
 * horizontal padding buys nothing and goes. */
.wc-block-components-quantity-selector__input {
	box-sizing: border-box;
	padding-left: 0;
	padding-right: 0;
}

/* --------------------------------------------------------------------------
 * Product page — the rating pill (Phase 20)
 * The frame draws the rating row as bare stars and "35 Reviews"; the owner
 * asked for something less ordinary, decided 2026-08-14: the row becomes a
 * soft pill in the review region's own peach — the raw hexes below are the
 * §6 review-card palette, tints deliberately kept out of theme.json like the
 * auth screens' (C8). Stars gold, average bold, count muted; the whole pill
 * is one click target for the `#reviews` anchor core already renders, via a
 * stretched ::after on core's own link — wrapping it in another anchor would
 * nest interactive elements.
 * ----------------------------------------------------------------------- */

.hermizon-rating-pill {
	position: relative;
	display: inline-flex;
	width: fit-content;
	padding: 6px 16px;
	background-color: #fff4e8;
	border: var(--wp--custom--border--width) solid #fcd6ac;
	border-radius: var(--wp--custom--radius--pill);
	transition: border-color var(--wp--custom--transition--fast);
}

.hermizon-rating-pill:hover,
.hermizon-rating-pill:focus-within {
	border-color: #f0b269;
}

.hermizon-rating-pill .wc-block-components-product-rating__container {
	display: inline-flex;
	align-items: center;
	gap: 10px;
}

/* Both layers of the star glyphs: the base row and the width-masked overlay. */
.hermizon-rating-pill .wc-block-components-product-rating__stars {
	font-size: var(--wp--preset--font-size--large);
	color: #e8dfd0;
}

.hermizon-rating-pill .wc-block-components-product-rating__stars span::before {
	color: #fcb021;
}

.hermizon-rating-pill__average {
	font-weight: 600;
	line-height: 1;
	color: var(--wp--preset--color--contrast);
}

.hermizon-rating-pill .wc-block-components-product-rating__reviews_count {
	margin: 0;
}

.hermizon-rating-pill .woocommerce-review-link {
	color: var(--wp--preset--color--muted);
	text-decoration: none;
}

/* The stretched click target. The focus ring moves out to the pill's edge
 * with it, so the link's own ring is suppressed — :focus-visible on the link
 * is what lights the ::after. */
.hermizon-rating-pill .woocommerce-review-link::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--wp--custom--radius--pill);
}

.hermizon-rating-pill .woocommerce-review-link:focus-visible {
	outline: none;
}

.hermizon-rating-pill .woocommerce-review-link:focus-visible::after {
	outline: var(--wp--custom--state--focus-width) solid var(--wp--custom--state--focus);
	outline-offset: var(--wp--custom--state--focus-offset);
}

/* The pill scrolls the page to the reviews; "Write a Review" links scroll it
 * to the form. Smooth is fine here because the Motion section below turns
 * scroll-behavior off wholesale under prefers-reduced-motion. The 96px is
 * measured: the stuck header is 75px tall at 1600 (E108), plus breathing room
 * so the heading does not kiss its shadow. */
html {
	scroll-behavior: smooth;
}

#reviews,
#review_form_wrapper {
	scroll-margin-top: 96px;
}

/* The Size Chart pill shares the "Size" label's line. The frame draws it on
 * the size row, but `add-to-cart-with-options` generates that row's markup
 * and leaves nothing to place a block inside — so the pill is its own block
 * *above* the selector, pulled down onto the label line: its own 24px plus
 * the column's 32px blockGap, and right-aligned so a wrapping chip row never
 * collides with it. z-index because the pull makes it share paint space with
 * the selector's first line. */
.hermizon-product__layout .hermizon-product__size-chart {
	position: relative;
	z-index: 1;
	display: flex;
	justify-content: flex-end;
	margin-bottom: -56px;
}

/* --------------------------------------------------------------------------
 * Product page — pixel pass (Phase 20)
 * The T1 scan's fixes that are CSS rather than template attributes.
 * ----------------------------------------------------------------------- */

/* The struck-through original must not inherit the price row's brand red —
 * two red numbers read as two prices. Muted, per the frame. */
.hermizon-product__layout .wp-block-woocommerce-product-price del {
	color: var(--wp--preset--color--muted);
}

.hermizon-product__layout .wp-block-woocommerce-product-price ins {
	text-decoration: none;
}

/* The accordion, as §4 draws it: three panels sharing 1px #E0E0E0 rules —
 * gap −1 so adjacent borders collapse into one — radius on the outer
 * corners only, 18px headers, and a chevron where core prints "+"/"×".
 * The chevron is a mask so it takes currentColor, and the whole glyph
 * rotates rather than swapping characters. */
.wp-block-woocommerce-product-details .wp-block-accordion-item {
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line);
}

.wp-block-woocommerce-product-details .wp-block-accordion-item + .wp-block-accordion-item {
	margin-block-start: -1px;
}

.wp-block-woocommerce-product-details .wp-block-accordion-item:first-child {
	border-start-start-radius: var(--wp--custom--radius--sm);
	border-start-end-radius: var(--wp--custom--radius--sm);
}

.wp-block-woocommerce-product-details .wp-block-accordion-item:last-child {
	border-end-start-radius: var(--wp--custom--radius--sm);
	border-end-end-radius: var(--wp--custom--radius--sm);
}

.wp-block-woocommerce-product-details .wp-block-accordion-heading__toggle {
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--50);
	font-size: var(--wp--preset--font-size--large);
}

.wp-block-woocommerce-product-details .wp-block-accordion-panel {
	padding-inline: var(--wp--preset--spacing--50);
	padding-block-end: var(--wp--preset--spacing--50);
}

.wp-block-woocommerce-product-details .wp-block-accordion-heading__toggle-icon {
	width: 24px;
	height: 24px;
	overflow: hidden;
	color: transparent;
	background-color: var(--wp--preset--color--contrast);
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	mask-repeat: no-repeat;
	mask-position: center;
	transition: transform var(--wp--custom--transition--base);
}

.wp-block-woocommerce-product-details .wp-block-accordion-heading__toggle[aria-expanded="true"] .wp-block-accordion-heading__toggle-icon,
.wp-block-woocommerce-product-details .wp-block-accordion-item.is-open .wp-block-accordion-heading__toggle-icon {
	transform: rotate(180deg);
}

/* The CTA, per the frame's correction of 2026-08-11: full-width and stacked
 * under the quantity row, not beside it. Buy It Now is deferred (E5), so
 * the one shipping button takes the frame's primary ink — #2A2A2E is the
 * design's CTA colour, not a palette member (C8). */
.wp-block-woocommerce-add-to-cart-with-options .wp-block-group:has(> .wc-block-add-to-cart-with-options__quantity-selector) {
	flex-direction: column;
	align-items: stretch;
}

.wp-block-woocommerce-add-to-cart-with-options .wc-block-components-quantity-selector {
	margin: 0;
}

/* Three classes: the button wrapper arrives as `.wp-block-button.align-left`,
 * and core floats the align classes — a floated wrapper shrinks to fit and
 * left the button at its 12rem minimum inside a stretched column. */
.wp-block-woocommerce-add-to-cart-with-options .wp-block-woocommerce-product-button.wp-block-button {
	float: none;
	width: 100%;
	margin: 0;
}

.wp-block-woocommerce-add-to-cart-with-options .wp-block-woocommerce-product-button .wp-element-button {
	width: 100%;
	padding-block: var(--wp--preset--spacing--40);
	background-color: #2a2a2e;
	color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--md);
}

/* --------------------------------------------------------------------------
 * Product page — reviews (Phase 20)
 * The review region had no styling at all: stock list, stock form. It is
 * also the most control-heavy region on the page — inputs, star buttons,
 * a textarea, a submit — which is the exact shape that has produced six
 * box-sizing defects on this build. So the region gets the E73 treatment:
 * a reset scoped to it, global decision unchanged.
 * ----------------------------------------------------------------------- */

.wp-block-woocommerce-product-reviews,
.wp-block-woocommerce-product-reviews *,
.wp-block-woocommerce-product-reviews *::before,
.wp-block-woocommerce-product-reviews *::after {
	box-sizing: border-box;
}

/* The review list becomes a column of cards — the home band's card
 * vocabulary (32px padding, md radius) on a neutral border, because the
 * home card's straw-yellow answers a band tint this page does not have. */
.wp-block-woocommerce-product-review-template {
	display: grid;
	gap: var(--wp--preset--spacing--40);
	margin: 0;
	padding: 0;
	list-style: none;
}

.wp-block-woocommerce-product-review-template > li.review {
	margin: 0;
	padding: var(--wp--preset--spacing--60);
	background-color: var(--wp--preset--color--base);
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line-light);
	border-radius: var(--wp--custom--radius--md);
	box-shadow: 0 2px 8px rgb(0 0 0 / 3%);
}

/* Head row: initial disc · name · verified badge · stars · date at the far
 * end. The date's auto margin is what pushes it there. */
.hermizon-review-card__head {
	row-gap: var(--wp--preset--spacing--20);
}

.hermizon-review-card__initial {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	background-color: #fff4e8;
	border: var(--wp--custom--border--width) solid #fcd6ac;
	border-radius: var(--wp--custom--radius--pill);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--contrast);
}

.wp-block-woocommerce-product-review-author-name {
	font-weight: 600;
}

.hermizon-review-card__verified {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 2px 10px;
	background-color: var(--wp--custom--state--success-surface);
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--custom--state--success);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.6;
}

.hermizon-review-card__head .wp-block-woocommerce-product-review-date {
	margin-inline-start: auto;
}

/* Gold stars, both layers — same glyph mechanism as the rating pill, but
 * matching core's own two-class weight: WooCommerce sets the star colours
 * from `.wp-block-woocommerce-product-review-rating .…__stars span:before`,
 * which outranks a single class (the wc-block prefix trap, once more). */
.wp-block-woocommerce-product-review-rating .wc-block-product-review-rating__stars {
	color: #e8dfd0;
}

.wp-block-woocommerce-product-review-rating .wc-block-product-review-rating__stars span::before {
	color: #fcb021;
}

.wp-block-woocommerce-product-review-content {
	margin-block-start: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--muted-soft);
	line-height: 1.7;
}

.wp-block-woocommerce-product-review-content p {
	margin: 0;
}

/* The review form. The markup is core's `comment_form()` inside the
 * product-review-form block — a column of `<p>` tags — restyled into the
 * card the rest of the region already speaks. The star input is a
 * radiogroup of five 24px SVG buttons whose path hardcodes `fill="none"`;
 * a stylesheet outranks a presentation attribute, which is what lets the
 * selected stars fill gold with no markup change.
 *
 * The card selector carries two ids it did not choose. WooCommerce's
 * *classic* stylesheet still ships `.woocommerce #review_form #respond
 * { padding:0; background:transparent; border:0 }` at (2,1,0) — measured
 * via CDP after a single class lost to it while its own border-radius,
 * which the legacy rule does not set, applied happily. The prefix trap
 * again, this time with ids. */
.woocommerce #review_form #respond.wp-block-woocommerce-product-review-form {
	padding: var(--wp--preset--spacing--60);
	background-color: var(--wp--preset--color--base);
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line-light);
	border-radius: var(--wp--custom--radius--lg);
	box-shadow: 0 2px 8px rgb(0 0 0 / 3%);
}

.wp-block-woocommerce-product-review-form .comment-reply-title {
	display: block;
	margin-block-end: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
}

.wp-block-woocommerce-product-review-form .comment-form {
	display: grid;
	gap: var(--wp--preset--spacing--40);
}

/* Same fight, one level down: the legacy sheet margins every `#respond p`,
 * which would stack under the form's own grid gap. */
.woocommerce #review_form #respond .comment-form > p,
.woocommerce #review_form #respond .comment-form > div {
	margin: 0;
}

.wp-block-woocommerce-product-review-form .comment-notes {
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--x-small);
}

.wp-block-woocommerce-product-review-form label {
	display: block;
	margin-block-end: var(--wp--preset--spacing--10);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
}

/* The five star buttons: bare of button chrome, 32px, gold when hovered or
 * chosen — both layers of each glyph, stroke and fill. */
.wp-block-woocommerce-product-review-form .stars-wrapper {
	margin: 0;
}

.wp-block-woocommerce-product-review-form .stars {
	display: inline-flex;
	gap: var(--wp--preset--spacing--10);
}

.wp-block-woocommerce-product-review-form .stars button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 2px;
	background: none;
	border: 0;
	color: #b0aa97;
	cursor: pointer;
	transition: color var(--wp--custom--transition--fast), transform var(--wp--custom--transition--fast);
}

.wp-block-woocommerce-product-review-form .stars button svg {
	width: 30px;
	height: 30px;
}

.wp-block-woocommerce-product-review-form .stars button.is-hovered,
.wp-block-woocommerce-product-review-form .stars button.is-selected {
	color: #fcb021;
	transform: scale(1.08);
}

.wp-block-woocommerce-product-review-form .stars button.is-hovered svg path,
.wp-block-woocommerce-product-review-form .stars button.is-selected svg path {
	fill: currentcolor;
}

.wp-block-woocommerce-product-review-form .rating-error {
	display: block;
	margin-block-start: var(--wp--preset--spacing--20);
	padding: 6px 12px;
	background-color: var(--wp--custom--state--error-surface);
	border-radius: var(--wp--custom--radius--sm);
	color: var(--wp--custom--state--error);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--x-small);
}

.wp-block-woocommerce-product-review-form .rating-error[hidden] {
	display: none;
}

.wp-block-woocommerce-product-review-form textarea {
	width: 100%;
	resize: vertical;
	min-height: 140px;
}

.wp-block-woocommerce-product-review-form .comment-form-author input,
.wp-block-woocommerce-product-review-form .comment-form-email input {
	width: min(360px, 100%);
}

.wp-block-woocommerce-product-review-form .comment-form-cookies-consent {
	display: flex;
	align-items: baseline;
	gap: var(--wp--preset--spacing--20);
}

.wp-block-woocommerce-product-review-form .comment-form-cookies-consent label {
	margin: 0;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 400;
}

.wp-block-woocommerce-product-review-form input[type="checkbox"] {
	accent-color: var(--wp--preset--color--brand);
}

.wp-block-woocommerce-product-review-form .logged-in-as {
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--x-small);
}

.wp-block-woocommerce-product-review-form .form-submit {
	margin-block-start: var(--wp--preset--spacing--20);
}

.wp-block-woocommerce-product-review-form .form-submit .wp-element-button {
	min-width: 12rem;
}

/* The locked state of the verified-buyer gate (E111). Neutral, not peach:
 * peach is this region's invitation, and a closed door should not wear it. */
.hermizon-review-gate {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--70) var(--wp--preset--spacing--50);
	background-color: #fbfbfb;
	border: var(--wp--custom--border--width) solid var(--wp--preset--color--line-light);
	border-radius: var(--wp--custom--radius--lg);
	text-align: center;
}

.hermizon-review-gate__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	margin-block-end: var(--wp--preset--spacing--20);
	background-color: #fff4e8;
	border: var(--wp--custom--border--width) solid #fcd6ac;
	border-radius: var(--wp--custom--radius--pill);
	color: var(--wp--preset--color--contrast);
}

.hermizon-review-gate__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 600;
}

.hermizon-review-gate__body {
	margin: 0;
	max-width: 52ch;
	color: var(--wp--preset--color--muted);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.7;
}

.hermizon-review-gate__action {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin-block-start: var(--wp--preset--spacing--30);
	padding: 10px 28px;
	background-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--md);
	font-family: var(--wp--preset--font-family--public-sans);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	text-decoration: none;
	transition: opacity var(--wp--custom--transition--fast);
}

.hermizon-review-gate__action:hover {
	opacity: 0.85;
}

/* The mini-cart drawer's close button, Phase 34.
 *
 * WooCommerce positions it `inset-inline-end: 12px` and then applies
 * `margin: -18px` to turn an 24px icon into a 60px target. With `right`
 * positioning the negative margin pushes *outward*, so the button spanned
 * `vw - 54` to `vw + 6` — the last 6px of the hit area sat off-screen at every
 * viewport, phone or desktop. It never showed up as page scroll because the
 * drawer is `position: fixed`, which is exactly why it survived nine phases.
 *
 * Cancelling the horizontal margin and pulling the inset to 0 keeps the whole
 * 60px target on screen and moves the icon 6px inward — from 24px off the edge
 * to 30 — which is within a pixel of the drawer's own 16px content padding plus
 * the icon's optical centre. The vertical margin is left alone; it is doing no
 * harm.
 */
.wc-block-mini-cart__drawer .wc-block-components-drawer__close {
	inset-inline-end: 0;
	margin-inline: 0;
}

/* --------------------------------------------------------------------------
 * About page — the two things the frame does that block attributes cannot
 *
 * page-specs.md §4. Both are scoped to classes the page markup opts into, so
 * nothing here reaches another template.
 * ----------------------------------------------------------------------- */

/* The frame staggers the second timeline card 66px below the first — measured
 * at y 342 against y 408 on frame `565:511`. It is a deliberate offset, not a
 * grid, so it cannot come from the columns block.
 *
 * 782 rather than 600: that is where core stacks `wp-block-columns`, and a
 * 66px top margin on a stacked column is not a stagger, it is a gap.
 *
 * **The parent selector is load-bearing, and it cost a browser pass to find.**
 * A bare `.hermizon-about__offset` is (0,1,0) and loses to the block-supports
 * rule core prints inline for every flex layout —
 * `.is-layout-flex > :is(*, div) { margin: 0 }` — which is (0,1,1) because
 * `:is()` takes its most specific argument, `div`. The rule was in the served
 * stylesheet, the element matched it, the media query was true, and the
 * computed margin was still 0. Naming the column's parent takes this to (0,2,0)
 * and it wins. */
@media (min-width: 782px) {
	.wp-block-columns > .hermizon-about__offset {
		margin-block-start: 66px;
	}
}

/* "Explore Our Journey" — text plus the frame's 40px circular arrow button.
 *
 * The arrow is generated content rather than an asset: the frame draws a
 * north-east arrow inside a 40px ring, and `\2197` is that glyph. An SVG here
 * would mean either a core/html block in the page or a new icon file, and this
 * needs neither. It is decorative — the link text already says where it goes —
 * so it is hidden from assistive technology by being generated content. */
.hermizon-about__journey {
	margin-block-start: var(--wp--preset--spacing--30);
}

.hermizon-about__journey a {
	display: inline-flex;
	align-items: center;
	gap: 16px;
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
}

.hermizon-about__journey a::after {
	content: "\2197";
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 40px;
	height: 40px;
	border: var(--wp--custom--border--width) solid #e2e2e4;
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--base);
	font-size: 18px;
	line-height: 1;
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.hermizon-about__journey a:hover::after,
.hermizon-about__journey a:focus-visible::after {
	border-color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--surface);
}

/* The reviews band is the design's 2 x 2, and the shared block will not give it
 * on its own. `hermizon/testimonials` in its grid arrangement is
 * `repeat(auto-fit, minmax(260px, 1fr))`, which is right for the home page and
 * wrong here: measured, this column is 862px, auto-fit takes three 271px cards,
 * and the fourth is left orphaned on a row of its own. The frame draws two
 * columns of 424.
 *
 * Pinned rather than widened, because a larger `minmax` would change the home
 * page too — that band is five cards and wants to reflow. Two is a property of
 * *this* band's four cards, so it is stated here.
 */
@media (min-width: 782px) {
	.hermizon-about__reviews .hermizon-testimonials.is-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* --------------------------------------------------------------------------
 * Motion
 * ----------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
