/* ==========================================================================
   PENNARD STONE — main stylesheet
   The single source of truth for all frontend CSS (playbook §3.1).
   Ported from the static prototype; BEM class names are kept 1:1 so the port
   stays verifiable against theme/css/style.css.

   Sections, in order:
     CUSTOM PROPERTIES · RESET · ACCESSIBILITY · TYPOGRAPHY · BUTTONS · FORMS
     UTILITY CLASSES · LAYOUT UTILITIES · SITE HEADER · NAV & MOBILE MENU
     MINI BASKET · HERO · SECTION SCAFFOLDING · TILES & PLINTH · PILLARS
     COLLECTION BROWSER · BREADCRUMBS · PIECE (SINGLE PRODUCT) · SPEC & OPTIONS
     PROCESS · MEDIA BAND & ENQUIRY · ICON GRID · CONTACT · TABS · STEPPER
     BENEFITS · FOOTER · WIDGETS · BLOG & SEARCH · 404
     WOOCOMMERCE (shop archive, single, cart, checkout, account, notices)
     GRAVITY FORMS · BLOCK SPACING UTILITIES · RESPONSIVE · REDUCED MOTION
   ========================================================================== */

/* ---------- CUSTOM PROPERTIES ----------
   Brand colours and the two type families are injected by the Customizer as an
   inline :root block before this file loads (playbook §2.8), so the values
   here are fallbacks for when that output is missing. Everything else is a
   design-system token and lives only here. */

:root {
	/* Brand — mirrored by inc/customizer.php */
	--limewash: #E1DDD2;
	--chalk: #EEEBE4;
	--slate: #585F67;
	--sage: #DAE4DB;
	--khaki: #BAB3A1;

	/* Derived ink tones — contrast-corrected, not brand-editable.
	   khaki is 1.54:1 on limewash and rose 2.25:1, so neither raw colour may
	   carry text on a light ground. */
	--ink-deep: #35383D;
	--ink-black: #111111;

	/* The select chevron, drawn once and shared by every control that strips
	   `appearance`. Kept as a token so the colour lives with the palette. */
	--ps-select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23585F67' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	--slate-ink: #3F444A;
	--khaki-ink: #615D54;
	--khaki-strong: #474339;
	--rose-ink: #6E5C58;
	--rose-soft: #E9D5CF;
	--stone: #EAE6E2;
	--white: #fff;
	--positive: #5F7355;

	--hairline: rgba(88, 95, 103, 0.28);
	--hairline-dark: rgba(225, 221, 210, 0.22);

	--serif: "Libre Baskerville", Baskerville, Georgia, serif;
	--sans: "Jost", "Avenir Next", "Century Gothic", sans-serif;

	/* Type scale — eight steps, nothing below 12px. Use these rather than
	   ad-hoc rem values or the scale drifts into near-duplicates. */
	--fs-3xs: 0.75rem;    /* 12px — micro labels, counts */
	--fs-2xs: 0.8125rem;  /* 13px — uppercase eyebrows, spec & form labels */
	--fs-xs:  0.875rem;   /* 14px — captions, notes, small UI */
	--fs-sm:  0.9375rem;  /* 15px — secondary body, filters, controls */
	--fs-md:  1rem;       /* 16px — UI default */
	--fs-lg:  1.0625rem;  /* 17px — body copy */
	--fs-xl:  1.1875rem;  /* 19px — small headings */
	--fs-2xl: 1.375rem;   /* 22px — sub-headings */

	--measure: 62ch;
	--gutter: clamp(1.25rem, 4vw, 3rem);
	--site-max: 1440px;

	/* Block spacing scale — drives the .pt-*/.pb-*/.mt-*/.mb-* utilities. */
	--space-none: 0rem;
	--space-sm: clamp(1rem, 2vw, 1.6rem);
	--space-md: clamp(3rem, 7vw, 5.5rem);
	--space-lg: clamp(4rem, 9vw, 7rem);
	--space-xl: clamp(5rem, 12vw, 9rem);

	--ease: cubic-bezier(0.22, 0.7, 0.3, 1);
}

/* ---------- RESET ---------- */

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

html { scroll-behavior: smooth; }

body {
	margin: 0;
	background: var(--chalk);
	color: var(--slate);
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-lg);
	line-height: 1.7;
	-webkit-font-smoothing: antialiased;
	caret-color: var(--rose-ink);
	accent-color: var(--slate);
}

img { max-width: 100%; display: block; }

/* The UA's [hidden] rule loses to any element rule that sets display (.tile
   for one), so filtered-out tiles would otherwise stay on screen. */
[hidden] { display: none !important; }

a { color: inherit; }

::selection { background: var(--slate); color: var(--limewash); }

/* ---------- ACCESSIBILITY ---------- */

/* WordPress relies on this for form labels and skip links; without it, text
   like "Search for:" renders visually and breaks layouts (lesson #9). */
.screen-reader-text,
.sr-only {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}

.screen-reader-text:focus {
	background: var(--slate);
	clip: auto;
	clip-path: none;
	color: var(--limewash);
	display: block;
	height: auto;
	left: 5px;
	padding: 0.7rem 1.2rem;
	top: 5px;
	width: auto;
	z-index: 100000;
}

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	background: var(--slate);
	color: var(--limewash);
	padding: 0.7rem 1.2rem;
	font-size: var(--fs-2xs);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	text-decoration: none;
}

.skip-link:focus { left: 0; }

:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 3px;
}

/* The darkened rose disappears on dark grounds — use the light counterpart. */
.section--charcoal :focus-visible,
.scheme-slate :focus-visible,
.enquiry-band :focus-visible,
.site-footer :focus-visible,
.site-header--over :focus-visible,
.site-nav.open :focus-visible,
.mini-basket :focus-visible {
	outline-color: var(--rose-soft);
}

/* ---------- TYPOGRAPHY ----------
   Headings inherit their colour so a dark section colours them automatically;
   only set an explicit colour where the parent cannot supply one (lesson #13).
   The scoping selector is wrapped in :where() so it contributes no specificity
   and any single component class beats it (lesson #34). */

:where(.site-main) h1,
:where(.site-main) h2,
:where(.site-main) h3,
:where(.site-main) h4,
:where(.site-main) h5,
:where(.site-main) h6 {
	color: inherit;
}

h1, h2, h3, h4, h5, h6 {
	color: inherit;
	font-weight: 400;
	text-wrap: balance;
}

p { text-wrap: pretty; }

/* The single shared label utility. Components declare their own tracking —
   the prototype uses a different letter-spacing per component (0.32em on an
   eyebrow, 0.22em on form labels, 0.1em in the nav), so a shared value here
   would silently override any component that did not restate it. */
.mono-label {
	font-family: var(--sans);
	text-transform: uppercase;
	letter-spacing: 0.14em;
}

.eyebrow {
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.32em;
	color: var(--slate);
	margin: 0 0 1.1rem;
	font-family: var(--sans);
	text-transform: uppercase;
}

.display {
	font-family: var(--serif);
	font-weight: 400;
	line-height: 1.18;
	margin: 0;
}

.page-title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.7rem, 3.6vw, 2.5rem);
	letter-spacing: 0.09em;
	text-transform: uppercase;
	line-height: 1.25;
	margin: 0;
}

.display,
.page-title,
.section__title,
.enquiry-band__title,
.piece__title { text-wrap: balance; }

.lede {
	max-width: var(--measure);
	color: var(--slate);
	font-size: var(--fs-lg);
}

.entry-content > * + * { margin-top: 1.1rem; }
.entry-content h2,
.entry-content h3 { font-family: var(--serif); margin-top: 2.2rem; }
.entry-content a { color: var(--rose-ink); text-decoration: underline; text-underline-offset: 0.2em; }

/* Imported/pasted content can carry inline widths and stray markup; keep it
   inside the column regardless (lesson #33). */
.entry-content img { max-width: 100%; height: auto; }
.entry-content figure,
.entry-content .wp-caption { max-width: 100% !important; width: auto !important; }
.entry-content figcaption,
.entry-content .wp-caption-text { font-size: var(--fs-xs); color: var(--khaki-ink); }
.entry-content iframe,
.entry-content video { max-width: 100%; }
.entry-content table { display: block; overflow-x: auto; }

/* ---------- BUTTONS ---------- */

.btn {
	display: inline-block;
	/* A <button> inherits a smaller line box than an <a>, so a stacked pair
	   rendered 51px and 54px. One explicit line-height equalises them. */
	line-height: 1.7;
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-decoration: none;
	text-align: center;
	white-space: nowrap;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	background: var(--slate);
	color: var(--limewash);
	cursor: pointer;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
	font-family: var(--sans);
	text-transform: uppercase;
}

.btn:hover { background: var(--rose-ink); border-color: var(--rose-ink); color: var(--limewash); }

.btn--ghost { background: transparent; color: var(--slate); }
.btn--ghost:hover { background: var(--slate); border-color: var(--slate); color: var(--limewash); }

.btn--on-dark { background: var(--limewash); border-color: var(--limewash); color: var(--slate); }
.btn--on-dark:hover { background: var(--rose-soft); border-color: var(--rose-soft); color: var(--slate); }

.btn--small { padding: 0.6rem 1.3rem; font-size: var(--fs-3xs); }
.btn--full { display: block; width: 100%; }

.btn.is-added { background: var(--positive); border-color: var(--positive); }

.btn[disabled],
.btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }

/* The core button block puts its `className` on the wrapper div as well as the
   anchor, so a button classed `btn` drew the padding, border and background
   twice — one box nested in the other, 87px tall instead of 54px. The wrapper
   is reduced to a plain box and the anchor keeps the button treatment. */
.wp-block-button.btn,
.wp-block-button.btn--ghost,
.wp-block-button.btn--on-dark,
.wp-block-button.btn--small,
.wp-block-button.btn--full {
	padding: 0;
	border: 0;
	background: none;
	font-size: inherit;
	letter-spacing: normal;
}

.wp-block-buttons {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
}

/* Buttons inherit the alignment of the block they sit in. Every centred
   container — the CTA bands, the centred intro — otherwise left-aligned its
   buttons under centred copy. A left-aligned split keeps its buttons left. */
.block-container--centred .wp-block-buttons,
.media-band--centred .wp-block-buttons,
.enquiry-band .wp-block-buttons,
.has-text-align-center .wp-block-buttons { justify-content: center; }

.wp-block-button__link.btn { display: inline-block; }

/* A stacked pair at phone width spans the column and shares a left edge. */
@media (max-width: 560px) {
	.piece__actions,
	.step__actions { display: flex; flex-direction: column; gap: 0.7rem; }

	/* The variation wrapper also holds the quantity field; the two action
	   controls each take the full width and stack beneath it. */
	.single-product .product:not(.product-card) form.cart .single_add_to_cart_button,
	.single-product .product:not(.product-card) form.cart .piece__view-basket { display: block; width: 100%; margin: 0; }
	/* The desktop side-by-side gap must not survive as a left indent. */
	.single-product .product:not(.product-card) form.cart .piece__view-basket { margin: 0.7rem 0 0 0; }

	.piece__actions .btn,
	.step__actions .btn,
	.single-product .product:not(.product-card) form.cart .single_add_to_cart_button,
	.single-product .product:not(.product-card) form.cart .piece__view-basket {
		display: block;
		width: 100%;
		margin: 0;
		box-sizing: border-box;
		text-align: center;
	}
}

/* WordPress emits a pill radius for core buttons through its own global-styles
   inline stylesheet, which is not one of the sheets the theme dequeues. The
   square corner is declared in theme.json so core writes the right value into
   that layer; this restates it for any surface core styles later. */
.wp-block-button__link,
.wp-block-button__link.btn { border-radius: 0; }

/* A solid button on a slate band is slate on slate — the text shows but the
   box does not. The prototype marks these `btn--on-dark` by hand; the core
   button block offers no such control, so any plain button dropped into a
   band through the editor takes the reversed fill automatically. */
.enquiry-band .btn:not(.btn--ghost):not(.btn--on-dark),
.scheme-slate .btn:not(.btn--ghost):not(.btn--on-dark) {
	background: var(--limewash);
	border-color: var(--limewash);
	color: var(--slate);
}

.enquiry-band .btn:not(.btn--ghost):not(.btn--on-dark):hover,
.scheme-slate .btn:not(.btn--ghost):not(.btn--on-dark):hover {
	background: var(--rose-soft);
	border-color: var(--rose-soft);
	color: var(--slate);
}

/* An outlined button on a dark ground needs the light edge, not the slate one. */
.enquiry-band .btn--ghost,
.scheme-slate .btn--ghost {
	border-color: var(--limewash);
	color: var(--limewash);
}

.enquiry-band .btn--ghost:hover,
.scheme-slate .btn--ghost:hover {
	background: var(--limewash);
	border-color: var(--limewash);
	color: var(--slate);
}

.link-btn {
	font: inherit;
	background: none;
	border: 0;
	padding: 0;
	color: var(--rose-ink);
	text-decoration: underline;
	text-underline-offset: 0.2em;
	cursor: pointer;
}

/* ---------- FORMS ---------- */

.form-field { margin-bottom: 1.3rem; }

.form-field label {
	display: block;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate);
	margin-bottom: 0.45rem;
	text-transform: uppercase;
}

.form-field input,
.form-field select,
.form-field textarea,
.search-form__input {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-md);
	color: var(--slate);
	background: var(--white);
	border: 1px solid var(--hairline);
	padding: 0.85rem 1rem;
	transition: border-color 0.25s ease;
}

.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 1px;
	border-color: var(--rose-ink);
}

.form-field input:user-invalid,
.form-field textarea:user-invalid { border-color: var(--rose-ink); }

.form-field textarea { resize: vertical; min-height: 9rem; }

.form-field__opt { color: var(--slate); font-weight: 300; text-transform: none; letter-spacing: 0; }

.form-note { font-size: var(--fs-xs); color: var(--slate); margin-top: 1rem; max-width: 48ch; }

.form-status { margin-top: 1rem; font-size: var(--fs-2xs); color: var(--slate); }
.form-status.is-shown { color: var(--rose-ink); }

.search-form { display: flex; gap: 0.6rem; max-width: 30rem; }
.search-form__input { flex: 1 1 auto; }

/* ---------- UTILITY CLASSES ---------- */

.wrap {
	max-width: var(--site-max);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

.wrap--narrow { max-width: 800px; }

/* Fade-up for grids — the hidden state only applies once JS claims the page,
   so content is never stranded invisible. */
.js .reveal {
	opacity: 0;
	transform: translateY(14px);
	transition: opacity 0.7s ease, transform 0.7s var(--ease);
}
.js .reveal.in { opacity: 1; transform: none; }

/* ---------- LAYOUT UTILITIES ---------- */

.section { padding-block: clamp(3rem, 7vw, 5.5rem); }


.section--chalk,
.scheme-chalk { background: var(--chalk); border-block: 1px solid var(--hairline); }

/* The about page's card row runs edge to edge inside the section; the
   section head above keeps the page gutter so it lines up with every other
   heading on the site. */
.block-container.scheme-chalk:has(> .wrap > .acf-innerblocks-container > .block-icon-grid) > .wrap > .acf-innerblocks-container > .block-icon-grid > .wrap { padding-inline: 0; }

.section--charcoal,
.scheme-slate {
	background: var(--slate);
	color: var(--limewash);
}

.section--charcoal .eyebrow,
.scheme-slate .eyebrow { color: var(--limewash); }

.section--charcoal .section__aside,
.scheme-slate .section__aside { color: var(--limewash); border-color: var(--limewash);
	text-transform: uppercase;
}

.section--charcoal .section__aside:hover,
.scheme-slate .section__aside:hover { color: var(--rose-soft); border-color: var(--rose-soft); }

.section--charcoal .tile__frame,
.scheme-slate .tile__frame { border: none; }

.section--charcoal .plinth__name,
.scheme-slate .plinth__name { color: var(--limewash);
	font-family: var(--sans);
	text-transform: uppercase;
}

.section--charcoal .plinth__price,
.scheme-slate .plinth__price { color: var(--stone); }

.section__head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.2rem 2rem;
	margin-bottom: clamp(1.8rem, 4vw, 2.8rem);
}

.section__head .eyebrow { margin-bottom: 0.7rem; }

.section__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.4rem, 2.8vw, 1.9rem);
	letter-spacing: 0.09em;
	text-transform: uppercase;
	margin: 0;
}

.section__aside {
	font-size: var(--fs-2xs);
	letter-spacing: 0.2em;
	color: var(--slate);
	text-decoration: none;
	border-bottom: 1px solid var(--khaki);
	padding-bottom: 0.25rem;
	transition: color 0.25s ease, border-color 0.25s ease;
}

.section__aside:hover { color: var(--rose-ink); border-color: var(--rose-ink); }

.section--page-head { padding-block: clamp(2.4rem, 5vw, 3.6rem) 0; }

/* The page head closes at 0, so the following content section's own top
   padding is the entire gap under the title. On the shop surfaces that title
   sits directly over a panel rather than over prose, and the full section
   step reads as a hole — halved here, and here only. */
.woocommerce-checkout .site-main > .wrap.section,
.woocommerce-cart .site-main > .wrap.section { padding-top: clamp(1.5rem, 3.5vw, 2.75rem); }

/* Framed imagery — the arch mount used by split sections and the about grid. */
.arch {
	overflow: hidden;
	background: var(--sage);
	border: 1px solid rgba(88, 95, 103, 0.18);
}

.arch img { width: 100%; height: 100%; object-fit: cover; }

/* ---------- SITE HEADER ---------- */

.site-header {
	position: sticky;
	top: 0;
	z-index: 40;
	background: var(--slate);
	border-bottom: 1px solid var(--hairline-dark);
	transition: transform 0.35s ease, background-color 0.3s ease, border-color 0.3s ease;
}

.site-header--hidden { transform: translateY(-101%); }

/* Home page: the header overlays the film hero and goes transparent over it. */
.page-home .site-header { position: fixed; top: 0; left: 0; right: 0; }

.site-header--over {
	background: transparent;
	border-bottom-color: transparent;
	backdrop-filter: none;
}

.site-header__bar {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: clamp(0.75rem, 2vw, 1.5rem);
	padding-block: 1rem;
}

.brand { display: inline-flex; align-items: center; justify-self: center; }

/* the_custom_logo() emits .custom-logo-link > .custom-logo, not the
   prototype's markup — style WordPress's classes (lesson #16). */
.brand .custom-logo-link,
.custom-logo-link { display: block; transition: opacity 0.3s ease; }

.brand img,
.custom-logo-link .custom-logo {
	height: 18px;
	width: auto;
	display: block;
	transition: opacity 0.3s ease;
}

.site-header--over .brand img,
.site-header--over .custom-logo-link .custom-logo { opacity: 0; }
.site-header--over .brand:focus-visible img,
.site-header--over .brand a:focus-visible img,
.site-header--over .custom-logo-link:focus-visible .custom-logo { opacity: 1; }

.site-header__actions {
	display: flex;
	align-items: center;
	gap: clamp(0.6rem, 1.5vw, 1.1rem);
	justify-self: end;
}

.header-search {
	display: inline-flex;
	padding: 0.45rem;
	color: var(--limewash);
	transition: color 0.25s ease;
}

.header-search:hover { color: var(--rose-soft); }
.header-search svg { width: 20px; height: 20px; display: block; }

.site-header--over .header-search { color: var(--white); }
.site-header--over .header-search:hover { color: rgba(255, 255, 255, 0.75); }

/* Basket and quote indicators. */
.header-mini {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	min-height: 24px;
	font-size: var(--fs-3xs);
	letter-spacing: 0.16em;
	text-decoration: none;
	color: var(--limewash);
	transition: color 0.25s ease;
	text-transform: uppercase;
}

/* Both links only appear once they hold something; without JS the counts
   cannot be trusted, so they stay visible. */
.js .header-mini:not(.is-active) { display: none; }

.header-mini:hover { color: var(--rose-soft); }
.header-mini.is-active { color: var(--white); }

.header-mini__count {
	display: inline-grid;
	place-items: center;
	min-width: 1.35rem;
	height: 1.35rem;
	padding: 0 0.3rem;
	border: 1px solid var(--hairline-dark);
	font-size: var(--fs-3xs);
	letter-spacing: 0;
	font-variant-numeric: tabular-nums;
}

.header-mini.is-active .header-mini__count {
	background: var(--limewash);
	border-color: var(--limewash);
	color: var(--slate);
}

.site-header--over .header-mini { color: rgba(255, 255, 255, 0.85); }
.site-header--over .header-mini__count { border-color: rgba(255, 255, 255, 0.5); }

/* ---------- NAV & MOBILE MENU ---------- */

.site-nav {
	display: flex;
	align-items: center;
	gap: clamp(0.9rem, 1.8vw, 1.9rem);
	justify-self: start;
}

/* Spacing lives on the list item, not as a gap on the list: WordPress injects
   its own list styles and a gap does not survive them (lesson #3). */
.site-nav__list {
	display: flex;
	align-items: center;
	list-style: none;
	margin: 0;
	padding: 0;
}

.site-nav__item {
	list-style: none;
	margin: 0 clamp(0.45rem, 0.9vw, 0.95rem);
	padding: 0;
}

.site-nav__item:first-child { margin-left: 0; }

.site-nav__link {
	display: inline-block;
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.1em;
	text-decoration: none;
	color: var(--limewash);
	padding-block: 0.35rem;
	border-bottom: 1px solid transparent;
	transition: color 0.25s ease, border-color 0.25s ease;
	font-family: var(--sans);
	text-transform: uppercase;
}

.site-nav__link:hover { color: var(--rose-soft); }

/* WordPress marks the active item with current-menu-item, never .active. */
.site-nav__item--current > .site-nav__link,
.site-nav__link[aria-current="page"] { border-bottom-color: var(--limewash); }

.site-header--over .site-nav__link { color: var(--white); }
.site-header--over .site-nav__link:hover { color: rgba(255, 255, 255, 0.75); }
.site-header--over .site-nav__item--current > .site-nav__link,
.site-header--over .site-nav__link[aria-current="page"] { border-bottom-color: var(--white); }

.site-nav__sub { display: none; }

.nav-toggle {
	display: none;
	background: none;
	border: 0;
	padding: 0.55rem;
	cursor: pointer;
	color: var(--limewash);
	position: relative;
	z-index: 3;
}

.nav-toggle__bar {
	display: block;
	width: 24px;
	height: 2px;
	background: currentColor;
	transition: transform 0.3s ease, opacity 0.3s ease;
}

.nav-toggle__bar + .nav-toggle__bar { margin-top: 6px; }

.nav-toggle[aria-expanded="true"] { color: var(--white); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

.site-header--over .nav-toggle { color: var(--white); border-color: rgba(255, 255, 255, 0.55); }

html.menu-open { overflow: hidden; }

/* backdrop-filter would make the header the containing block for the fixed
   full-page menu, clipping it to the bar — lift it while open (lesson #8). */
html.menu-open .site-header { backdrop-filter: none; }

/* ---------- MINI BASKET ---------- */

.mini-basket {
	position: fixed;
	inset: 0;
	z-index: 60;
	visibility: hidden;
	pointer-events: none;
}

.mini-basket.is-open { visibility: visible; pointer-events: auto; }

.mini-basket__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(46, 51, 55, 0.55);
	opacity: 0;
	transition: opacity 0.3s ease;
}

.mini-basket.is-open .mini-basket__backdrop { opacity: 1; }

.mini-basket__panel {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	width: min(24rem, 100%);
	display: flex;
	flex-direction: column;
	background: var(--limewash);
	border-left: 1px solid var(--hairline);
	transform: translateX(100%);
	transition: transform 0.3s var(--ease);
	overflow-y: auto;
}

.mini-basket.is-open .mini-basket__panel { transform: none; }

.mini-basket__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.4rem var(--gutter);
	border-bottom: 1px solid var(--hairline);
}

.mini-basket__title {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	margin: 0;
}

.mini-basket__close {
	background: none;
	border: 0;
	padding: 0.4rem;
	cursor: pointer;
	color: var(--slate);
	display: inline-flex;
}

.mini-basket__close svg { width: 20px; height: 20px; }
.mini-basket__close:hover { color: var(--rose-ink); }

.mini-basket__body { padding: 1.2rem var(--gutter) 2rem; }

/* The drawer shows WooCommerce's mini cart list, which ships unstyled. These
   give it the prototype's line treatment: thumbnail, name, quantity, price. */
.mini-basket .woocommerce-mini-cart,
.mini-basket .cart_list {
	list-style: none;
	margin: 0;
	padding: 0;
}

/* WooCommerce nests the thumbnail and the name inside one anchor, with the
   quantity as a following sibling — so the row is laid out from the anchor,
   not from the image. */
/* WooCommerce nests the thumbnail inside the product anchor, so the image
   cannot be placed in a grid area of its own — it inherits the anchor's. The
   anchor is therefore the row: a two-column grid holding image and name, with
   the quantity following beneath. */
.mini-basket .mini_cart_item {
	position: relative;
	display: grid;
	grid-template-columns: 64px 1fr;
	column-gap: 0.9rem;
	row-gap: 0.2rem;
	align-items: start;
	padding: 1rem 2rem 1rem 0;
	border-bottom: 1px solid var(--hairline);
}

/* The rules separate items; the last one closes on the subtotal's own rule. */
.mini-basket .mini_cart_item:last-child { border-bottom: 0; }

.mini-basket .mini_cart_item > a:not(.remove) {
	grid-column: 1 / -1;
	display: grid;
	grid-template-columns: 64px 1fr;
	column-gap: 0.9rem;
	align-items: center;
}

.mini-basket .mini_cart_item img {
	grid-column: 1;
	align-self: center;
	width: 64px;
	height: 64px;
	object-fit: cover;
	background: var(--sage);
	margin: 0;
	float: none;
}

/* The quantity lines up under the name, clear of the thumbnail column. */
.mini-basket .mini_cart_item .quantity {
	grid-column: 1 / -1;
	margin-left: calc(64px + 0.9rem);
}

.mini-basket .mini_cart_item > a:not(.remove) {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--slate);
	line-height: 1.5;
}

.mini-basket .mini_cart_item > a:not(.remove):hover { color: var(--rose-ink); }

.mini-basket .mini_cart_item .quantity {
	display: block;
	font-size: var(--fs-2xs);
	color: var(--slate);
	font-variant-numeric: tabular-nums;
}

.mini-basket .mini_cart_item .variation {
	margin: 0.15rem 0 0;
	font-size: var(--fs-3xs);
	color: var(--khaki-ink);
}

.mini-basket .mini_cart_item .variation dt,
.mini-basket .mini_cart_item .variation dd { display: inline; margin: 0; }

/* WooCommerce's remove control is a bare × — set it as a quiet corner action. */
/* The drawer is outside any `.woocommerce` wrapper, so the shared remove
   rule never reaches it — the treatment is restated here. */
.mini-basket .mini_cart_item a.remove {
	position: absolute;
	top: 0.9rem;
	right: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.35rem;
	height: 1.35rem;
	border-radius: 50%;
	background: var(--white);
	border: 1px solid var(--hairline);
	color: var(--khaki-ink);
	/* The × glyph is not vertically centred in its own line box, so the
	   flex centring alone leaves it sitting high. font-size: 0 hides the
	   character and the mark is drawn instead — dead centre, every time. */
	font-size: 0;
	line-height: 0;
	text-decoration: none;
	overflow: hidden;
	transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}

.mini-basket .mini_cart_item a.remove::before,
.mini-basket .mini_cart_item a.remove::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 0.6rem;
	height: 1px;
	background: currentColor;
}

.mini-basket .mini_cart_item a.remove::before { transform: translate(-50%, -50%) rotate(45deg); }
.mini-basket .mini_cart_item a.remove::after { transform: translate(-50%, -50%) rotate(-45deg); }

.mini-basket .mini_cart_item a.remove:hover,
.mini-basket .mini_cart_item a.remove:focus-visible {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--white);
}

.mini-basket .woocommerce-mini-cart__total {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	align-items: baseline;
	margin: 1.2rem 0;
	padding-top: 1rem;
	border-top: 1px solid var(--hairline);
	font-family: var(--serif);
	font-size: var(--fs-lg);
}

.mini-basket .woocommerce-mini-cart__total strong {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
}

.mini-basket .woocommerce-mini-cart__buttons {
	display: grid;
	gap: 0.6rem;
	margin: 0;
}

.mini-basket .woocommerce-mini-cart__buttons a {
	display: block;
	width: 100%;
	text-align: center;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	background: var(--slate);
	color: var(--limewash);
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	text-decoration: none;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.mini-basket .woocommerce-mini-cart__buttons a:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
}

/* The first button is the quieter "view basket" action. */
.mini-basket .woocommerce-mini-cart__buttons a:not(.checkout) {
	background: transparent;
	color: var(--slate);
}

.mini-basket .woocommerce-mini-cart__buttons a:not(.checkout):hover {
	background: var(--slate);
	color: var(--limewash);
}

.mini-basket .woocommerce-mini-cart__empty-message {
	margin: 2rem 0;
	color: var(--slate);
	font-size: var(--fs-xs);
}

html.basket-open { overflow: hidden; }

/* ---------- HERO ---------- */

.hero-film {
	position: relative;
	height: max(560px, calc(100vh - 77px));
	height: max(560px, calc(100svh - 77px));
	overflow: hidden;
	background: var(--slate);
}

/* With the fixed overlay header the hero owns the full viewport (lesson #4). */
.page-home .hero-film {
	height: max(560px, 100vh);
	height: max(560px, 100svh);
}

.hero-slides { position: absolute; inset: 0; overflow: hidden; }

.hero-slides__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	/* Held slightly in so the outgoing frame never exposes an edge. */
	transform: scale(1.04);
	transition: opacity 1.6s ease-in-out;
	will-change: opacity, transform;
}

/* A frame drifts for its full life on screen: 3s holding the stage plus the
   1.6s spent fading out under the next one. Keeping the animation on both
   states means the scale is never reassigned mid-flight. */
.hero-slides__img.is-current,
.hero-slides__img.is-leaving { animation: hero-drift 4.6s linear forwards; }

.hero-slides__img.is-current { opacity: 1; }
.hero-slides__img.is-leaving { opacity: 0; }

@keyframes hero-drift {
	from { transform: scale(1.04); }
	to   { transform: scale(1.1); }
}

html:not(.js) .hero-slides__img:first-child { opacity: 1; }

.hero-film__overlay {
	position: absolute;
	inset: 0;
	background: var(--ink-black);
	opacity: 0.7;
}

.hero-film__content {
	position: relative;
	height: 100%;
	display: grid;
	place-items: center;
	padding-inline: var(--gutter);
	text-align: center;
	color: var(--white);
}

.hero-film__logo { width: min(640px, 78vw); height: auto; }

@keyframes settle {
	from { opacity: 0; transform: translateY(16px); }
	to   { opacity: 1; transform: none; }
}

.hero-film__logo { animation: settle 1.1s 0.2s var(--ease) both; }

/* Inner-page hero — same treatment, sized so content still shows above fold. */
.hero-page {
	position: relative;
	min-height: clamp(300px, 42vh, 440px);
	display: grid;
	overflow: hidden;
	background: var(--slate);
}

.hero-page--short { min-height: clamp(220px, 30vh, 320px); }

/* The hero supplies the top spacing, so the first section drops its own. */
.hero-page + .section,
.hero-film + .section { padding-top: clamp(2.4rem, 5vw, 3.6rem); }

.hero-page__slides { position: absolute; inset: 0; }

.hero-page__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 42%;
	opacity: 0;
	transition: opacity 1.6s ease-in-out;
}

.hero-page__img.is-current { opacity: 1; }
html:not(.js) .hero-page__img:first-child { opacity: 1; }

.hero-page__overlay {
	position: absolute;
	inset: 0;
	/* The same flat veil the film hero uses, rather than a radial pool. */
	background: var(--ink-black);
	opacity: 0.7;
}

.hero-page__content {
	position: relative;
	align-self: center;
	justify-self: center;
	width: 100%;
	max-width: var(--site-max);
	padding: clamp(3rem, 8vw, 5rem) var(--gutter);
	text-align: center;
	color: var(--white);
}

.hero-page__content .eyebrow {
	color: rgba(255, 255, 255, 0.92);
	text-shadow: 0 1px 10px rgba(24, 27, 30, 0.5);
	animation: settle 0.9s 0.05s var(--ease) both;
}

.hero-page__title {
	text-shadow: 0 2px 18px rgba(24, 27, 30, 0.45);
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(2rem, 4.4vw, 3rem);
	letter-spacing: 0.09em;
	text-transform: uppercase;
	line-height: 1.2;
	margin: 0;
	text-wrap: balance;
	animation: settle 0.9s 0.16s var(--ease) both;
}

.hero-page__lede {
	text-wrap: pretty;
	max-width: 54ch;
	margin: 1.2rem auto 0;
	font-size: var(--fs-lg);
	color: var(--white);
	text-shadow: 0 1px 12px rgba(24, 27, 30, 0.55);
	animation: settle 0.9s 0.28s var(--ease) both;
}

/* Intro section on the home page. */
.intro { text-align: center; }
.intro__inner { max-width: 840px; margin-inline: auto; }
.intro__title { font-size: clamp(2.1rem, 4.6vw, 3.3rem); }
.intro .lede { max-width: none; margin: 1.6rem auto 2.2rem; }
.intro__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.9rem; }

/* ---------- TILES & PLINTH ---------- */

.tile-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1.1rem, 2vw, 1.6rem);
}

.tile-grid--2 { grid-template-columns: repeat(2, 1fr); }
.tile-grid--4 { grid-template-columns: repeat(4, 1fr); }

.tile {
	text-decoration: none;
	color: inherit;
	display: block;
}

.tile__frame {
	overflow: hidden;
	background: var(--sage);
	border: 1px solid rgba(88, 95, 103, 0.16);
}

.tile__frame img {
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: cover;
	transition: transform 0.7s var(--ease);
}

/* A piece with no photograph yet still needs to hold its place in the grid. */
.tile__frame--empty {
	aspect-ratio: 1 / 1;
	display: grid;
	place-items: center;
	color: var(--khaki-ink);
	font-size: var(--fs-3xs);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	text-align: center;
	padding: 1rem;
}

.tile:hover .tile__frame img,
.tile:focus-visible .tile__frame img { transform: scale(1.045); }

/* The plinth: name and price beneath each photograph. */
.plinth { display: block; margin-top: 1rem; }

.plinth__name {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--slate);
	display: block;
}

.plinth__price {
	display: block;
	margin-top: 0.45rem;
	font-size: var(--fs-2xs);
	color: var(--slate);
	font-variant-numeric: tabular-nums;
}

.plinth__price .amount,
.plinth__price bdi { font-variant-numeric: tabular-nums; }

/* A quote piece's price arrives from `woocommerce_empty_price_html` wrapped in
   `.price--guide`, which is sized for the single-product page (a ~29px serif).
   On a catalogue tile that inner span outranks `.plinth__price`, because it
   styles the child rather than the parent, so the caption rendered at more
   than twice the prototype's size. The tile restates its own treatment. */
.plinth__price .price,
.plinth__price .price--guide {
	font-family: inherit;
	font-size: inherit;
	line-height: inherit;
	color: inherit;
}

/* ---------- PIECE LIGHTBOX ----------
   The stacked gallery's own full-screen viewer: previous, next and close, on
   the site's slate rather than the plugin's black. */
.piece-lightbox {
	position: fixed;
	inset: 0;
	z-index: 80;
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: clamp(0.5rem, 2vw, 1.5rem);
	padding: clamp(1rem, 4vw, 3rem);
}

.piece-lightbox__backdrop {
	position: absolute;
	inset: 0;
	background: rgba(17, 17, 17, 0.92);
}

.piece-lightbox__figure {
	position: relative;
	grid-column: 2;
	margin: 0;
	display: grid;
	place-items: center;
	max-height: 100%;
}

.piece-lightbox__figure img {
	max-width: 100%;
	max-height: calc(100vh - clamp(2rem, 8vw, 6rem) - 3rem);
	width: auto;
	height: auto;
	display: block;
}

.piece-lightbox__nav,
.piece-lightbox__close {
	position: relative;
	z-index: 1;
	display: inline-grid;
	place-items: center;
	width: 3rem;
	height: 3rem;
	padding: 0;
	border: 1px solid rgba(225, 221, 210, 0.45);
	border-radius: 50%;
	background: transparent;
	color: var(--limewash);
	cursor: pointer;
	transition: background-color 0.25s ease, border-color 0.25s ease;
}

.piece-lightbox__nav:hover,
.piece-lightbox__close:hover,
.piece-lightbox__nav:focus-visible,
.piece-lightbox__close:focus-visible {
	background: var(--limewash);
	border-color: var(--limewash);
	color: var(--ink-black);
}

/* Chevrons and the cross, drawn rather than shipped as assets. */
.piece-lightbox__nav::before {
	content: "";
	width: 0.75rem;
	height: 0.75rem;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
}

.piece-lightbox__nav--prev::before { transform: translateX(2px) rotate(135deg); }
.piece-lightbox__nav--next::before { transform: translateX(-2px) rotate(-45deg); }

.piece-lightbox__close::before,
.piece-lightbox__close::after {
	content: "";
	position: absolute;
	width: 1rem;
	height: 2px;
	background: currentColor;
}

.piece-lightbox__close::before { transform: rotate(45deg); }
.piece-lightbox__close::after { transform: rotate(-45deg); }

.piece-lightbox__close {
	position: absolute;
	top: clamp(1rem, 3vw, 2rem);
	right: clamp(1rem, 3vw, 2rem);
}

.piece-lightbox__count {
	position: absolute;
	left: 50%;
	bottom: clamp(1rem, 3vw, 2rem);
	transform: translateX(-50%);
	margin: 0;
	z-index: 1;
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--stone);
	font-variant-numeric: tabular-nums;
}

html.lightbox-open { overflow: hidden; }

@media (max-width: 560px) {
	.piece-lightbox { grid-template-columns: 1fr; }
	.piece-lightbox__figure { grid-column: 1; }

	/* The controls sit over the image at phone width rather than beside it. */
	.piece-lightbox__nav {
		position: absolute;
		top: 50%;
		transform: translateY(-50%);
	}

	.piece-lightbox__nav--prev { left: 0.6rem; }
	.piece-lightbox__nav--next { right: 0.6rem; }
}

/* ---------- PILLARS ---------- */

.pillars { padding: 0; border-bottom: 1px solid var(--hairline); }

.pillars__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.pillar {
	text-align: center;
	padding: clamp(3rem, 6vw, 4.5rem) clamp(1rem, 3vw, 3rem);
	border-left: 1px solid var(--hairline);
}

.pillar:first-child { border-left: 0; }

.pillar__icon {
	display: block;
	width: 44px;
	height: 44px;
	margin: 0 auto 1.2rem;
	color: var(--khaki-ink);
}

.pillar__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: var(--fs-md);
	letter-spacing: 0.14em;
	margin: 0 0 0.6rem;
	text-transform: uppercase;
}

.pillar p {
	text-wrap: pretty;
	margin: 0 auto;
	max-width: 36ch;
	font-size: var(--fs-sm);
	color: var(--slate);
}

/* ---------- COLLECTION BROWSER ---------- */

/* Without JS the rail is inert, so hide it and show the full grid uncluttered. */
html:not(.js) .collection__rail { display: none; }
html:not(.js) .collection__more { display: none; }

.collection {
	display: grid;
	grid-template-columns: 15rem 1fr;
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
}

.collection__rail-inner { position: sticky; top: 7.5rem; }

.filter-search { display: block; margin-bottom: 2rem; }

.filter-search__label,
.filter-select__label {
	display: block;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate-ink);
	margin-bottom: 0.6rem;
	text-transform: uppercase;
}

.filter-search input {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-sm);
	color: var(--slate);
	background: transparent;
	border: 0;
	border-bottom: 1px solid var(--hairline);
	padding: 0.5rem 0;
	-webkit-appearance: none;
	appearance: none;
}

.filter-search input::placeholder { color: var(--khaki-ink); opacity: 1; }

.filter-search input:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 2px;
	border-bottom-color: var(--slate);
}

.filter-rail { display: block; }

.filter-group {
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--khaki-strong);
	margin: 1.9rem 0 0.7rem;
}

.filter-group:first-child { margin-top: 0; }

.filter-link {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.75rem;
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-xs);
	line-height: 1.4;
	text-align: left;
	background: none;
	border: 0;
	border-bottom: 1px solid transparent;
	color: var(--slate-ink);
	padding: 0.42rem 0;
	cursor: pointer;
	transition: color 0.22s ease, border-color 0.22s ease;
}

.filter-link:hover { color: var(--slate); }

.filter-link__count {
	font-size: var(--fs-3xs);
	letter-spacing: 0.08em;
	color: var(--khaki-strong);
	font-variant-numeric: tabular-nums;
}

.filter-link.is-current { color: var(--slate); border-bottom-color: var(--slate); }
.filter-link.is-current .filter-link__count { color: var(--slate); }

/* "All pieces" sits above the first group heading. */
.filter-link[data-filter="all"] {
	font-weight: 400;
	letter-spacing: 0.06em;
	padding-bottom: 0.6rem;
	margin-bottom: 0.4rem;
}

/* The route filter — a vertical radio list. */
.route-toggle {
	border: 0;
	border-bottom: 1px solid var(--hairline);
	margin: 0 0 1.6rem;
	padding: 0 0 1.3rem;
}

.route-toggle__legend {
	padding: 0;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate-ink);
	margin-bottom: 0.7rem;
	text-transform: uppercase;
}

.route-opt {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	min-height: 28px;
	padding: 0.22rem 0;
	cursor: pointer;
	color: var(--slate-ink);
	font-size: var(--fs-xs);
	transition: color 0.2s ease;
}

.route-opt:hover { color: var(--slate); }

.route-opt input {
	appearance: none;
	-webkit-appearance: none;
	flex: 0 0 auto;
	width: 15px;
	height: 15px;
	margin: 0;
	border: 1px solid var(--slate-ink);
	border-radius: 50%;
	display: grid;
	place-content: center;
	cursor: pointer;
}

.route-opt input::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: 50%;
	transform: scale(0);
	background: var(--slate);
	transition: transform 0.16s ease;
}

.route-opt input:checked { border-color: var(--slate); }
.route-opt input:checked::before { transform: scale(1); }
.route-opt input:focus-visible { outline: 2px solid var(--rose-ink); outline-offset: 2px; }
.route-opt.is-current { color: var(--slate); font-weight: 400; }

/* On small screens the rail gives way to a dropdown. */
.filter-select { display: none; }

.filter-select select {
	width: 100%;
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-xs);
	letter-spacing: 0.06em;
	color: var(--slate);
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: 0.8rem 1rem;
}

.filter-select select:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 1px;
	border-color: var(--rose-ink);
}

.collection-count {
	font-size: var(--fs-3xs);
	letter-spacing: 0.2em;
	color: var(--slate-ink);
	margin: 0 0 1.6rem;
	text-transform: uppercase;
}

.collection-empty { color: var(--slate); padding: 3rem 0; }

.collection__more {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.9rem;
	padding-top: clamp(2.2rem, 5vw, 3.2rem);
}

.collection__more-count {
	margin: 0;
	font-size: var(--fs-3xs);
	letter-spacing: 0.2em;
	color: var(--slate-ink);
	text-transform: uppercase;
}

/* ---------- BREADCRUMBS ---------- */

.breadcrumb-bar { border-bottom: 1px solid var(--hairline); }

.breadcrumb {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: left;
	gap: 0.55rem;
	padding-block: 1.1rem;
	font-size: var(--fs-3xs);
	letter-spacing: 0.2em;
	color: var(--slate);
	text-align: left;
	margin: 0;
	text-transform: uppercase;
}

.breadcrumb a { color: inherit; text-decoration: none; transition: color 0.22s ease; }
.breadcrumb a:hover { color: var(--rose-ink); }
.breadcrumb [aria-current="page"] { color: var(--slate); }

.breadcrumb__sep {
	color: var(--khaki-ink);
	font-size: 1.15em;
	line-height: 1;
	letter-spacing: 0;
	transform: translateY(-0.04em);
}

/* ---------- PIECE (SINGLE PRODUCT) ---------- */

/* Equal above and below so the summary never touches the section that follows. */
.piece { padding-block: clamp(3rem, 7vw, 5rem); }

.piece__grid {
	display: grid;
	/* Named areas rather than implicit placement: WooCommerce's product wrapper
	   drops notices and clearfix elements in among the figure and the summary,
	   and implicit placement gives each of them a column of its own
	   (lesson WC-7). */
	grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
	grid-template-areas: "figure summary";
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
}

.piece__grid > .piece__figure { grid-area: figure; }
.piece__grid > .summary,
.piece__grid > .entry-summary { grid-area: summary; }

/* Anything else WooCommerce injects sits full width beneath the two columns
   rather than claiming a track. */
.piece__grid > *:not(.piece__figure):not(.summary):not(.entry-summary) {
	grid-column: 1 / -1;
}

.piece__figure { margin: 0; }

.piece__figure figcaption {
	margin-top: 0.9rem;
	font-size: var(--fs-3xs);
	color: var(--slate);
	letter-spacing: 0.06em;
	text-align: center;
}

.piece__stage {
	overflow: hidden;
	background: var(--sage);
	border: 1px solid rgba(88, 95, 103, 0.16);
}

.piece__stage img { width: 100%; height: auto; object-fit: cover; }

/* ---------- STACKED PHOTOGRAPH LAYOUT ----------
   The per-piece alternative to WooCommerce's stage-and-thumbnails gallery:
   every photograph down the column at full width. No thumbnail strip and no
   full-screen trigger — each image is its own link, and hovering lifts it
   slightly under a white magnifier. */
.piece__stack {
	display: grid;
	gap: clamp(0.8rem, 2vw, 1.2rem);
}

.piece__stack-item {
	position: relative;
	display: block;
	overflow: hidden;
	background: var(--sage);
	border: 1px solid rgba(88, 95, 103, 0.16);
	line-height: 0;
}

.piece__stack-img {
	width: 100%;
	height: auto;
	display: block;
	transition: transform 0.6s var(--ease, cubic-bezier(0.22, 0.61, 0.36, 1));
}

.piece__stack-item:hover .piece__stack-img,
.piece__stack-item:focus-visible .piece__stack-img { transform: scale(1.04); }

/* The magnifier sits over the image, centred, and fades in with the lift. */
.piece__stack-zoom {
	position: absolute;
	inset: 0;
	opacity: 0;
	background: rgba(17, 17, 17, 0.22);
	/* Fading out must not also re-centre the mark — the position is left
	   exactly where the pointer left it, and `visibility` stops the fully
	   transparent overlay from being picked up by a stray hover. */
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0s linear 0.3s;
	pointer-events: none;
}

/* The drawn mark IS the affordance, so the cursor is hidden outright over the
   image — `pointer` draws a hand and `zoom-in` draws a magnifying glass, either
   of which reads as a second icon beside the mark. The link stays
   keyboard-reachable and labelled, and the cursor returns on leaving. */
.piece__stack-item,
.piece__stack-item * { cursor: none; }

.piece__stack-item:hover .piece__stack-zoom,
.piece__stack-item:focus-visible .piece__stack-zoom {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.3s ease, visibility 0s;
}

/* A magnifier with a plus, drawn as one SVG so the glass, handle and plus can
   never drift apart. White, centred over the lifted image. */
/* The mark follows the pointer — lightbox.js writes --ps-zoom-x/y on move;
   before the first move it rests in the middle. */
.piece__stack-zoom::before {
	content: "";
	position: absolute;
	left: var(--ps-zoom-x, 50%);
	top: var(--ps-zoom-y, 50%);
	transform: translate(-50%, -50%);
	width: 2rem;
	height: 2rem;
	background-repeat: no-repeat;
	background-position: center;
	background-size: contain;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='1' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M11 8v6M8 11h6'/%3E%3Cpath d='m16.5 16.5 5 5'/%3E%3C/svg%3E");
	filter: drop-shadow(0 1px 2px rgba(17, 17, 17, 0.35));
}

@media (prefers-reduced-motion: reduce) {
	.piece__stack-img { transition: none; }
	.piece__stack-item:hover .piece__stack-img { transform: none; }
}

/* WooCommerce's full-screen trigger arrives as a bare 19px icon in the
   gallery's top-left corner. Set it as a round control in the bottom-right of
   the stage, with the magnifier drawn rather than the plugin's raster. */
.single-product .woocommerce-product-gallery { position: relative; }

/* The trigger is a sibling of the image viewport, not a child of it, so it
   cannot be positioned against the image box. It is offset from the gallery's
   top instead, which is the main image's top edge, and pushed to the far side
   — the thumbnail strip below no longer drags it down. */
.single-product .woocommerce-product-gallery__trigger {
	position: absolute;
	right: 0.9rem;
	top: 0.9rem;
	bottom: auto;
	z-index: 5;
	width: 2.6rem;
	height: 2.6rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: var(--limewash);
	border: 1px solid var(--hairline);
	color: var(--slate);
	text-decoration: none;
	transition: background-color 0.3s ease, color 0.3s ease;
}

.single-product .woocommerce-product-gallery__trigger:hover { background: var(--slate); color: var(--limewash); }

.single-product .woocommerce-product-gallery__trigger img,
.single-product .woocommerce-product-gallery__trigger span { display: none; }

.single-product .woocommerce-product-gallery__trigger::before {
	content: "";
	width: 0.7rem;
	height: 0.7rem;
	border: 1.5px solid currentColor;
	border-radius: 50%;
	transform: translate(-0.12rem, -0.12rem);
}

.single-product .woocommerce-product-gallery__trigger::after {
	content: "";
	position: absolute;
	width: 0.42rem;
	height: 1.5px;
	background: currentColor;
	transform: translate(0.42rem, 0.42rem) rotate(45deg);
}

/* No photograph yet — hold the shape rather than collapsing the layout. A full
   square of flat colour dominates the page on the pieces still awaiting
   photography, so the placeholder is kept to a calmer band. */
.piece__stage--empty {
	aspect-ratio: 4 / 3;
	max-height: 26rem;
	display: grid;
	place-items: center;
	color: var(--khaki-ink);
	font-size: var(--fs-2xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
}

.gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
	gap: 0.55rem;
	margin-top: 0.75rem;
	list-style: none;
	padding: 0;
}

.gallery__thumb {
	padding: 0;
	border: 1px solid transparent;
	background: var(--sage);
	cursor: pointer;
	overflow: hidden;
	opacity: 0.62;
	transition: opacity 0.25s ease, border-color 0.25s ease;
}

.gallery__thumb img { width: 100%; height: auto; aspect-ratio: 1 / 1; object-fit: cover; }
.gallery__thumb:hover { opacity: 1; }
.gallery__thumb.is-current { opacity: 1; border-color: var(--slate); }

.piece__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.7rem, 3.4vw, 2.4rem);
	letter-spacing: 0.05em;
	line-height: 1.2;
	margin: 0 0 0.4rem;
}

.piece__category {
	font-size: var(--fs-2xs);
	letter-spacing: 0.24em;
	text-transform: uppercase;
	color: var(--slate);
	text-decoration: none;
}

.piece__category:hover { color: var(--rose-ink); }

.piece__body { margin-top: 1.6rem; }
.piece__body p { margin: 0 0 1rem; max-width: 54ch; color: var(--ink-deep); }
.piece__body .piece__note { color: var(--slate); font-size: var(--fs-md); }

.piece__price {
	font-family: var(--serif);
	font-size: var(--fs-2xl);
	color: var(--slate);
	margin: 1.6rem 0 0;
}

.piece__price-figure { font-size: clamp(1.6rem, 2.6vw, 1.95rem); }
.piece__vat,
.price-vat-note {
	font-size: var(--fs-2xs);
	color: var(--slate);
	font-family: var(--sans);
	letter-spacing: 0.08em;
}

.price--guide { font-family: var(--serif); font-size: clamp(1.4rem, 2.4vw, 1.8rem); color: var(--slate); }

.piece__price-note {
	font-size: var(--fs-xs);
	color: var(--slate);
	margin: 0.4rem 0 0;
	max-width: 46ch;
}

.piece__stock {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--fs-2xs);
	color: var(--slate);
	margin: 0.5rem 0 0;
}

.piece__stock-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--positive); }

.piece__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.9rem;
	align-items: center;
	margin: 20px 0 0 0;
}

.piece__phone-line { margin-top: 1.4rem; font-size: var(--fs-xs); color: var(--slate); }
.piece__phone-line a { color: var(--slate); text-decoration: none; border-bottom: 1px solid var(--khaki); }
.piece__phone-line a:hover { color: var(--rose-ink); border-color: var(--rose-ink); }

.buy { margin-top: 2rem; }
.buy__row { display: flex; gap: 1rem; flex-wrap: wrap; }
.buy__field { display: block; flex: 1 1 12rem; margin-bottom: 1rem; }
.buy__field--qty { flex: 0 0 5.5rem; }

.buy__field > span {
	display: block;
	font-size: var(--fs-2xs);
	letter-spacing: 0.2em;
	color: var(--slate);
	margin-bottom: 0.45rem;
	text-transform: uppercase;
}

.buy__field select,
.buy__field input {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-sm);
	color: var(--slate);
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: 0.7rem 0.8rem;
}

.buy__field select:focus-visible,
.buy__field input:focus-visible { outline: 2px solid var(--rose-ink); outline-offset: 1px; }

.buy__note { font-size: var(--fs-2xs); color: var(--slate); margin-top: 1rem; }
.buy__note a { color: var(--rose-ink); }

/* ---------- SPEC & OPTIONS ---------- */

.spec { margin: 1.8rem 0 2.2rem; border-top: 1px solid var(--hairline); }

.spec__row {
	display: grid;
	grid-template-columns: 9.5rem 1fr;
	gap: 1rem;
	padding-block: 0.7rem;
	border-bottom: 1px solid var(--hairline);
	margin: 0;
}

.spec__row dt {
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate);
	padding-top: 0.15rem;
	text-transform: uppercase;
}

.spec__row dd { margin: 0; font-weight: 400; font-size: var(--fs-xs); color: var(--slate); }

.options { margin-top: 2.4rem; }

.options__title {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate);
	margin: 0 0 0.9rem;
	font-family: var(--sans);
	text-transform: uppercase;
}

.options__list { margin: 0; }

.options__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 0.7rem 0;
	border-top: 1px solid var(--hairline);
	margin: 0;
}

.options__row dt { font-size: var(--fs-xs); color: var(--slate); }

.options__row dd {
	margin: 0;
	font-size: var(--fs-xs);
	color: var(--slate);
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

/* ---------- PROCESS ---------- */

.process {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 1px;
	background: var(--hairline);
	border: 1px solid var(--hairline);
}

.process__step { background: var(--limewash); padding: clamp(1.4rem, 3vw, 2rem); }

/* Matches the trade benefit icons: 44px, currentColor, round joins. The colour
   follows the step number so the two marks read as one pair. */
/* The icon sits beside the content rather than above it, in the same 44px
   column .benefit uses, spanning the step's rows. */
.process__step:has(.process__icon) {
	display: grid;
	grid-template-columns: 32px minmax(0, 1fr);
	column-gap: 0.9rem;
	align-items: start;
}

.process__step .process__icon { grid-row: 1 / span 3; }

.process__icon {
	display: block;
	/* 32px in the four-up row: at 44px the remaining text column was narrow
	   enough to break the titles across two lines. The trade cards can afford
	   44px because they are wider. */
	width: 32px;
	height: 32px;
	color: var(--rose-ink);
	stroke-linecap: round;
	stroke-linejoin: round;
}

.section--charcoal .process__icon,
.scheme-slate .process__icon { color: var(--rose-soft); }

.process__num {
	display: block;
	margin-bottom: 0.8rem;
	font-family: var(--serif);
	font-size: var(--fs-xl);
	line-height: 1;
	color: var(--rose-ink);
	font-variant-numeric: tabular-nums;
}

.process__title {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.16em;
	color: var(--slate);
	margin: 0.15rem 0 0.4rem;
	font-family: var(--sans);
	text-transform: uppercase;
}

.process__text { margin: 0; font-size: var(--fs-sm); color: var(--slate-ink); }

.section--chalk .process__step,
.scheme-chalk .process__step { background: var(--chalk); }

/* On the dark ground every part of a step card has to be re-toned: the grid's
   hairlines, the card fill, the number, the title and the body copy are all
   tuned for a light section and would otherwise sit at the wrong contrast (or
   vanish — the card fill is --limewash, which is near enough the text colour).
   The card is a lifted panel rather than a lighter box, keeping the rule-grid
   look of the light version. */
/* The cards sit on the section's own ground rather than as lifted panels, so
   the grid's 1px gap-as-rule trick is dropped: with no fill difference there is
   nothing for it to separate. The rule closes the section as a whole — put on
   each step it merely merged into one line across a desktop row anyway. */
.section--charcoal .process,
.scheme-slate .process {
	background: none;
	gap: 0;
}



/* The section closes with its own rule, separating it from the charcoal
   related-products section beneath. */
.section--charcoal:has(.process),
.scheme-slate:has(.process) { border-bottom: 1px solid var(--hairline-dark); }

/* Bordered like the about page's "what we look for": the grid carries the
   outer edge and each step is divided from its neighbour, so the four read as
   one enclosed set of cards rather than four loose columns. */
.section--charcoal .process,
.scheme-slate .process { border: 1px solid var(--hairline-dark); }

/* Stacked by default, so the divider runs along the top of each step after the
   first. The vertical divider is restored per breakpoint below, where the grid
   actually has columns — a `border-left` here would hang as a stub beside a
   stacked card. */
.section--charcoal .process__step,
.scheme-slate .process__step {
	background: transparent;
	border-top: 1px solid var(--hairline-dark);
}

.section--charcoal .process__step:first-child,
.scheme-slate .process__step:first-child { border-top: 0; }

.section--charcoal .process__num,
.scheme-slate .process__num { color: var(--rose-soft); }

.section--charcoal .process__title,
.scheme-slate .process__title { color: var(--limewash); }

.section--charcoal .process__text,
.scheme-slate .process__text { color: var(--stone); }

/* ---------- SINGLE POST ----------
   The banner is .hero-page, shared with the pages; only what follows it is
   particular to a post. */

.hero-page--post .eyebrow span { margin-inline: 0.5em; }

.post-single__lede {
	margin: 0 0 2rem;
	padding-bottom: 2rem;
	border-bottom: 1px solid var(--hairline);
	font-family: var(--serif);
	font-size: var(--fs-lg);
	line-height: 1.55;
	color: var(--slate);
	text-wrap: pretty;
}

.post-single__pages {
	margin-top: 2rem;
	font-size: var(--fs-sm);
}

.post-single__tags {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	margin-top: 2.6rem;
	padding-top: 1.4rem;
	border-top: 1px solid var(--hairline);
}

.post-single__tags-label,
.post-nav__label {
	font-family: var(--sans);
	font-size: var(--fs-3xs);
	font-weight: 500;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--khaki-ink);
}

.post-single__tags-label { margin-right: 0.4rem; }

.post-single__tags a {
	padding: 0.3rem 0.75rem;
	border: 1px solid var(--hairline);
	font-size: var(--fs-xs);
	color: var(--slate);
	text-decoration: none;
	transition: border-color 0.22s ease, color 0.22s ease;
}

.post-single__tags a:hover { border-color: var(--slate); color: var(--rose-ink); }

/* Previous / all / next, ruled off above and below like the breadcrumb bar. */
.post-nav { border-block: 1px solid var(--hairline); background: var(--chalk); }

.post-nav__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	align-items: center;
	gap: 1.5rem;
	padding-block: clamp(1.6rem, 3.5vw, 2.4rem);
}

.post-nav__item { min-width: 0; }
.post-nav__item--next { text-align: right; }

.post-nav__item > a:not(.btn) {
	display: inline-flex;
	flex-direction: column;
	gap: 0.35rem;
	max-width: 100%;
	color: var(--slate);
	text-decoration: none;
}

.post-nav__title {
	font-family: var(--serif);
	font-size: var(--fs-md);
	line-height: 1.3;
	transition: color 0.22s ease;
}

.post-nav__item > a:not(.btn):hover .post-nav__title { color: var(--rose-ink); }

@media (max-width: 700px) {
	.post-nav__grid { grid-template-columns: minmax(0, 1fr); text-align: center; }
	.post-nav__item--next { text-align: center; }
	.post-nav__item--all { order: 3; }
	.post-nav__item:empty { display: none; }
}

/* Comments. The fields are .form-field and the submit is .btn, so only the
   list and the spacing are particular to this. */
.comments__title {
	font-family: var(--serif);
	font-size: var(--fs-xl);
	font-weight: 400;
	margin: 0 0 1.4rem;
}

.comments__list,
.comments__list .children { list-style: none; margin: 0; padding: 0; }

.comments__list { margin-bottom: 3rem; }
.comments__list .children { margin-left: clamp(1rem, 4vw, 2.2rem); }

.comments__list .comment-body {
	padding: 1.3rem 0;
	border-bottom: 1px solid var(--hairline);
	font-size: var(--fs-sm);
}

.comments__list .comment-author { font-weight: 500; color: var(--slate); }
.comments__list .comment-author .says { display: none; }

.comments__list .comment-metadata,
.comments__list .reply {
	font-size: var(--fs-xs);
	color: var(--khaki-ink);
}

.comments__list .comment-metadata a,
.comments__list .reply a { color: inherit; }

.comments__list .comment-content { margin-top: 0.6rem; }

.comment-respond .comment-notes,
.comment-respond .logged-in-as { font-size: var(--fs-sm); color: var(--slate-ink); margin-bottom: 1.4rem; }

.comment-respond .comment-form-cookies-consent {
	display: flex;
	align-items: flex-start;
	gap: 0.6rem;
	margin: 0 0 1.4rem;
	font-size: var(--fs-sm);
}

.comment-respond .comment-form-cookies-consent input { margin-top: 0.3em; }
.comment-respond .form-submit { margin: 0; }

/* ---------- MEDIA BAND & ENQUIRY ---------- */
/* Content left, full-bleed image right — shared by the dark enquiry bands and
   the light feature sections. */

.media-band { padding-block: 0; }

.media-band__grid {
	display: grid;
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
	align-items: stretch;
}

.media-band--flip .media-band__grid { direction: rtl; }
.media-band--flip .media-band__content,
.media-band--flip .media-band__media { direction: ltr; }

.media-band__content {
	padding-block: clamp(3.5rem, 8vw, 6rem);
	padding-left: max(var(--gutter), calc((100vw - var(--site-max)) / 2 + var(--gutter)));
	padding-right: clamp(2rem, 5vw, 5rem);
}

.media-band__media { position: relative; min-height: 300px; background: var(--sage); }

.media-band__media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Centred variant: one column, no image — the playbook's CTA banner. */
.media-band--centred .media-band__grid { grid-template-columns: 1fr; }

.media-band--centred .media-band__content {
	text-align: center;
	max-width: 760px;
	margin-inline: auto;
	padding-block: clamp(3rem, 7vw, 5rem);
	padding-inline: var(--gutter);
}

.media-band--centred .media-band__content p:not(.enquiry-band__actions) { margin-inline: auto; }

.enquiry-band {
	background: var(--slate);
	color: var(--limewash);
	padding-block: clamp(3.5rem, 8vw, 6rem);
}

.enquiry-band.media-band { padding-block: 0; }

.enquiry-band .eyebrow { color: var(--limewash); }

.enquiry-band__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.6rem, 3.4vw, 2.4rem);
	line-height: 1.3;
	max-width: 24ch;
	margin: 0 0 1.2rem;
}

.enquiry-band p { color: var(--stone); max-width: 52ch; }

.enquiry-band__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1.4rem;
	margin-top: 2rem;
}

.enquiry-band__phone {
	font-family: var(--serif);
	font-size: var(--fs-lg);
	color: var(--limewash);
	text-decoration: none;
}

.enquiry-band__phone:hover { color: var(--rose-soft); }

/* The telephone number is rendered by the block template as a sibling of the
   InnerBlocks container. `display: contents` dissolves that container so the
   buttons block and the phone paragraph become siblings in the same formatting
   context; making that context a centred wrapping row puts them side by side,
   while the eyebrow, heading and copy above stay full width. */
.enquiry-band .acf-innerblocks-container { display: contents; }

/* A band with a photograph is left-aligned in its column; only the centred,
   imageless band centres its row. */
/* Everything in the band stacks in one column, except the action row: the
   buttons block and the phone share a single wrapping row. A column flex can
   never place two items side by side, so the content is a two-column grid
   where every child spans both columns except those two, which take one
   column each on the same row. */
.enquiry-band .media-band__content {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	justify-items: start;
	column-gap: 1rem;
	row-gap: 0;
}

.enquiry-band .media-band__content > *,
.enquiry-band .media-band__content > .acf-innerblocks-container > * { grid-column: 1 / -1; }

.enquiry-band .media-band__content .wp-block-buttons {
	grid-column: 1;
	display: inline-flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin-top: 2rem;
	margin-bottom: 0;
}

.enquiry-band .media-band__content .enquiry-band__actions {
	grid-column: 2;
	justify-self: start;
	margin-top: 2rem;
	margin-bottom: 0;
}

.enquiry-band.media-band--centred .media-band__content {
	justify-items: center;
	grid-template-columns: auto auto;
	justify-content: center;
}

/* Narrow screens: the two action columns cannot sit side by side, so the row
   becomes a single column and the phone follows the button. */
@media (max-width: 560px) {
	.enquiry-band .media-band__content,
	.enquiry-band.media-band--centred .media-band__content { grid-template-columns: minmax(0, 1fr); }

	.enquiry-band .media-band__content > .wp-block-buttons,
	.enquiry-band .media-band__content .wp-block-buttons,
	.enquiry-band .media-band__content > .enquiry-band__actions,
	.enquiry-band .media-band__content .enquiry-band__actions { grid-column: 1 / -1; }

	.enquiry-band .media-band__content .enquiry-band__actions { margin-top: 1rem; }
	.enquiry-band__phone { width: 100%; text-align: center; box-sizing: border-box; }
}

.enquiry-band .wp-block-buttons {
	flex: 0 0 auto;
	margin-bottom: 0;
	justify-content: flex-start;
}

.enquiry-band.media-band--centred .wp-block-buttons { justify-content: center; }

.enquiry-band .enquiry-band__actions {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	/* `.enquiry-band p` centres body copy with large auto side margins; the
	   actions paragraph inherited them and was pushed ~158px from the button,
	   so the gap varied wildly from page to page. */
	margin: 2rem 0 0;
	max-width: none;
}

/* The buttons block and the phone open the action row together. */
.enquiry-band .wp-block-buttons { margin-top: 2rem; }

.enquiry-band__phone {
	display: inline-block;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--limewash);
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	/* Matches the button anchor's line box so both stand 54px tall. */
	line-height: 22.1px;
	white-space: nowrap;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.enquiry-band__phone:hover {
	background: var(--limewash);
	border-color: var(--limewash);
	color: var(--slate);
}

/* Copy beside a photograph, inside the page gutter. */
.split-grid {
	display: grid;
	grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: center;
}

.split-grid--flip { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
.split-grid--flip .split-grid__media { order: -1; }
.split-grid .arch { aspect-ratio: 1 / 1; max-width: 400px; justify-self: center; }

.about-copy { max-width: 80ch; margin-inline: auto; text-align: center; }
.about-copy p + p { margin-top: 1.1rem; }

/* ---------- ICON GRID ---------- */

.benefits {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
}

.benefit + .benefit { border-top: 1px solid var(--hairline); }

/* The list carries the outer edge that matches the rules between items. */
.benefits { border: 1px solid var(--hairline); }

/* The thirds variant is a row of cards, not a stack — the trade page's list
   stacks, the about page's "what we look for" sits inline. */
.benefits--thirds {
	flex-direction: row;
	flex-wrap: wrap;
}

.benefits--thirds > .benefit {
	flex: 1 1 0;
	min-width: 14rem;
}

.benefits--thirds > .benefit + .benefit {
	border-top: 0;
	border-left: 1px solid var(--hairline);
}

.benefit {
	background: var(--chalk);
	padding: 1.5rem 1.6rem;
	display: grid;
	grid-template-columns: 44px 1fr;
	grid-template-rows: auto auto;
	column-gap: 1.2rem;
	align-items: start;
}

.benefit__icon { grid-row: 1 / span 2; color: var(--rose-ink); }

.benefit__icon svg {
	width: 44px;
	height: 44px;
	display: block;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.benefit__title {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.16em;
	color: var(--slate);
	margin: 0.2rem 0 0.4rem;
	font-family: var(--sans);
	text-transform: uppercase;
}

.benefit__text { margin: 0; font-size: var(--fs-sm); color: var(--slate-ink); }
.benefit__link { font-size: var(--fs-2xs); letter-spacing: 0.16em; text-transform: uppercase; color: var(--rose-ink); text-decoration: none; }
.benefit__link:hover { text-decoration: underline; text-underline-offset: 0.2em; }

/* On a chalk ground the cards keep the page colour so they still read as cards. */
.section--chalk .benefit,
.scheme-chalk .benefit { background: var(--chalk); }
.scheme-slate .benefit { background: var(--slate); color: var(--limewash); }
.scheme-slate .benefit__title { color: var(--limewash); }
.scheme-slate .benefit__text { color: var(--stone); }
.scheme-slate .benefit__icon { color: var(--rose-soft); }

/* ---------- CONTACT ---------- */

.contact-grid {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
	gap: clamp(2.5rem, 6vw, 5rem);
	align-items: start;
}

.contact-details h2 {
	font-family: var(--serif);
	font-weight: 400;
	font-size: var(--fs-xl);
	letter-spacing: 0.06em;
	margin: 0 0 0.6rem;
}

.contact-block {
	display: grid;
	grid-template-columns: auto 1fr;
	column-gap: 1.15rem;
	align-items: start;
	padding-block: 1rem;
	margin: 0;
}

.contact-block__icon {
	grid-row: 1 / span 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 54px;
	height: 54px;
	background: var(--chalk);
	border: 1px solid var(--hairline);
	color: var(--slate);
}

.contact-block__icon svg { width: 20px; height: 20px; }

.contact-block dt {
	grid-column: 2;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate);
	margin-bottom: 0.35rem;
	text-transform: uppercase;
}

.contact-block dd { grid-column: 2; margin: 0; }
.contact-block a { color: var(--slate); text-decoration: none; border-bottom: 1px solid var(--khaki); }
.contact-block a:hover { color: var(--rose-ink); border-color: var(--rose-ink); }

.contact-form {
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: clamp(1.6rem, 3.5vw, 2.6rem);
}

.contact-form__title {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate);
	margin: 0 0 1.8rem;
	font-family: var(--sans);
	text-transform: uppercase;
}

/* ---------- TABS ---------- */

.tabs { background: var(--chalk); border: 1px solid var(--hairline); }

.tabs__list { display: flex; border-bottom: 1px solid var(--hairline); }

.tabs__tab {
	flex: 1;
	background: none;
	border: 0;
	border-bottom: 2px solid transparent;
	padding: 1rem 0.9rem;
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.14em;
	color: var(--slate-ink);
	cursor: pointer;
	transition: color 0.22s ease, border-color 0.22s ease, background-color 0.22s ease;
	text-transform: uppercase;
}

.tabs__tab:hover { color: var(--slate); background: rgba(255, 255, 255, 0.4); }
.tabs__tab.is-current { color: var(--slate); border-bottom-color: var(--slate); font-weight: 500; }
.tabs__tab:focus-visible { outline: 2px solid var(--rose-ink); outline-offset: -3px; }

.tabs__panel { padding: clamp(1.4rem, 3vw, 2.2rem); }

/* A form inside a panel no longer needs its own frame. */
.tabs__panel .contact-form,
.tabs__panel .gform_wrapper { background: none; border: 0; padding: 0; }

/* ---------- STEPPER ---------- */

.stepper {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 2.4rem;
	list-style: none;
	margin: 0 0 clamp(2rem, 4vw, 3rem);
	padding: 0 0 1.4rem;
	border-bottom: 1px solid var(--hairline);
}

.stepper__item {
	display: flex;
	align-items: center;
	gap: 0.7rem;
	color: var(--khaki-strong);
	font-size: var(--fs-xs);
	transition: color 0.22s ease;
}

.stepper__num {
	display: grid;
	place-items: center;
	width: 26px;
	height: 26px;
	border: 1px solid currentColor;
	border-radius: 50%;
	font-size: var(--fs-3xs);
	font-variant-numeric: tabular-nums;
}

.stepper__item.is-current { color: var(--slate); }

.stepper__item.is-current .stepper__num {
	background: var(--slate);
	border-color: var(--slate);
	color: var(--limewash);
}

.stepper__item.is-done { color: var(--slate-ink); }
.stepper__item.is-done .stepper__num { border-color: var(--slate-ink); }

.quote-steps { max-width: 46rem; }

.step {
	background: var(--chalk);
	border: 1px solid var(--hairline);
	margin: 0 0 1.4rem;
	padding: clamp(1.4rem, 3vw, 2rem);
}

.step__title { font-family: var(--serif); font-weight: 400; font-size: var(--fs-2xl); padding: 0; margin: 0 0 0.5rem; }
.step__lede { color: var(--slate-ink); font-size: var(--fs-sm); margin: 0 0 1.8rem; max-width: 52ch; }

.step__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
	margin-top: 2rem;
	padding-top: 1.6rem;
	border-top: 1px solid var(--hairline);
}

/* ---------- CART LINES (quote list, mini basket) ---------- */

.line {
	display: grid;
	grid-template-columns: 84px 1fr auto 6.5rem 5.5rem;
	gap: 1.2rem;
	align-items: center;
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: clamp(1.4rem, 3vw, 2rem);
}

.line + .line { margin-top: 0.9rem; }

/* Line panels inside a chalk step read better in white. */
.step .line { background: var(--white); }

.line__img { width: 84px; height: 84px; object-fit: cover; background: var(--sage); }
.line__img--placeholder { display: block; }

.line__name {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.12em;
	margin: 0;
	font-family: var(--sans);
	text-transform: uppercase;
}

.line__name a { text-decoration: none; display: inline-flex; align-items: center; min-height: 24px; }
.line__name a:hover { color: var(--rose-ink); }

.line__meta,
.line__unit { font-size: var(--fs-2xs); color: var(--slate); margin: 0.3rem 0 0; }

.line__price { margin: 0; font-size: var(--fs-md); font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.line__price--guide { font-size: var(--fs-xs); color: var(--slate); }

/* The quote list's remove is a button, but reads the same as the basket's. */
.line__remove {
	justify-self: end;
	margin-left: auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.35rem;
	height: 1.35rem;
	padding: 0;
	border-radius: 50%;
	background: var(--white);
	border: 1px solid var(--hairline);
	color: var(--khaki-ink);
	font-family: var(--sans);
	font-size: 0;
	line-height: 1;
	cursor: pointer;
	text-decoration: none;
	transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}

/* The mark is drawn from two bars rather than set as an × glyph, which sits
   high in its line box and never looks centred. */
.line__remove { position: relative; line-height: 0; overflow: hidden; }

.line__remove::before,
.line__remove::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 0.6rem;
	height: 1px;
	background: currentColor;
}

.line__remove::before { transform: translate(-50%, -50%) rotate(45deg); }
.line__remove::after { transform: translate(-50%, -50%) rotate(-45deg); }

.line__remove:hover,
.line__remove:focus-visible {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--white);
}


.cart__empty { color: var(--slate); padding: 2.5rem 0; }
.cart__empty a { color: var(--rose-ink); }

.cart__list-title,
.cart__summary-title {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--slate);
	margin: 0 0 0.9rem;
	font-family: var(--sans);
	text-transform: uppercase;
}

/* ---------- FOOTER ---------- */

.site-footer {
	background: var(--slate);
	color: var(--stone);
	border-top: 1px solid var(--hairline-dark);
	padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
	font-size: var(--fs-sm);
}

.site-footer a { color: var(--limewash); text-decoration: none; }
.site-footer a:hover { color: var(--rose-soft); }

.site-footer__grid {
	display: grid;
	grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
	gap: clamp(2rem, 4vw, 3.5rem);
	padding-bottom: 2.5rem;
	border-bottom: 1px solid var(--hairline-dark);
}

.site-footer__brand img,
.site-footer__brand .custom-logo { height: 18px; width: auto; margin-bottom: 1.1rem; }
.site-footer__brand p { max-width: 34ch; margin: 0; }

.site-footer h3,
.site-footer__heading {
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.26em;
	text-transform: uppercase;
	color: var(--stone);
	margin: 0 0 1rem;
}

.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li { margin-bottom: 0.2rem; }

/* Footer links get a 24px hit area (WCAG 2.2 target size) without changing
   how the list looks. */
.site-footer li a,
.site-footer address a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
	padding-block: 0.15rem;
}

.site-footer address { font-style: normal; }
.site-footer__hours { margin: 0.6rem 0 0; }

.site-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: 0.8rem 2rem;
	padding-top: 1.6rem;
	font-size: var(--fs-3xs);
	letter-spacing: 0.08em;
	color: var(--stone);
}

.site-footer__bottom p { margin: 0; }

/* Copyright left, Zonkey credit hard right. */
.site-footer__bottom .widget_zonkey_powered { margin-left: auto; }

.site-footer__menu { display: flex; flex-wrap: wrap; gap: 0.4rem 1.4rem; }
.site-footer__menu li { margin: 0; }

/* ---------- WIDGETS ---------- */

.site-footer__widget + .site-footer__widget { margin-top: 1.8rem; }

.zonkey-powered-by-widget { margin-left: auto; }

.zonkey-powered-by-widget p {
	margin: 0;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	font-size: var(--fs-3xs);
}

.zonkey-powered-by-widget a {
	display: inline-flex;
	align-items: center;
	gap: 0.34rem;
	min-height: 24px;
	transition: color 0.3s ease;
}

.zonkey-powered-by-widget svg { display: block; vertical-align: middle; }

/* strong carries its own colour in most typographic bases, which would beat
   the link's inherited colour — inherit explicitly (playbook §2.7). */
.zonkey-powered-by-widget strong { font-weight: 700; color: inherit; }

.zonkey-powered-by-widget--light p { color: rgba(234, 230, 226, 0.6); }
.zonkey-powered-by-widget--light a { color: rgba(234, 230, 226, 0.85); }
.zonkey-powered-by-widget--light a:hover { color: var(--limewash); }

.zonkey-powered-by-widget--dark p { color: var(--khaki-ink); }
.zonkey-powered-by-widget--dark a { color: var(--slate); }
.zonkey-powered-by-widget--dark a:hover { color: var(--rose-ink); }

.widget_search .search-form { max-width: none; }
.widget_categories ul,
.widget_recent_entries ul,
.widget_archive ul,
.widget_nav_menu ul { list-style: none; margin: 0; padding: 0; }

/* ---------- BLOG & SEARCH ---------- */

.post-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1.4rem, 3vw, 2.2rem);
}

.post-card__image { display: block; overflow: hidden; background: var(--sage); }
/* height: auto is what lets the ratio apply — without it the img's own height
   attribute wins and the card ran to the photograph's full portrait height. */
.post-card__image img { display: block; width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; transition: transform 0.6s var(--ease, ease); }
.post-card__image:hover img { transform: scale(1.03); }

.post-card__image--empty {
	display: grid;
	place-items: center;
	aspect-ratio: 3 / 2;
	text-decoration: none;
}

.post-card__image--empty span {
	font-family: var(--serif);
	font-size: var(--fs-sm);
	letter-spacing: 0.24em;
	text-transform: uppercase;
	color: var(--slate);
	opacity: 0.55;
}
.post-card__body { padding-top: 1rem; }
.post-card__date { font-size: var(--fs-3xs); letter-spacing: 0.2em; text-transform: uppercase; color: var(--khaki-ink); }
.post-card__title { font-family: var(--serif); font-size: var(--fs-xl); margin: 0.5rem 0; }
.post-card__title a { text-decoration: none; }
.post-card__title a:hover { color: var(--rose-ink); }
.post-card__excerpt { font-size: var(--fs-sm); color: var(--slate-ink); margin: 0; }

.pagination,
.woocommerce-pagination {
	display: flex;
	justify-content: center;
	margin-top: clamp(2.4rem, 5vw, 3.5rem);
}

.pagination .page-numbers,
.woocommerce-pagination .page-numbers {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	margin: 0;
	padding: 0;
}

.page-numbers {
	display: inline-grid;
	place-items: center;
	min-width: 2.4rem;
	min-height: 2.4rem;
	padding: 0 0.6rem;
	border: 1px solid var(--hairline);
	font-size: var(--fs-2xs);
	letter-spacing: 0.1em;
	text-decoration: none;
	color: var(--slate);
}

.page-numbers:hover { border-color: var(--slate); }
.page-numbers.current { background: var(--slate); border-color: var(--slate); color: var(--limewash); }

/* ---------- 404 ---------- */

.error-404 { text-align: center; }
.error-404 .lede { margin-inline: auto; }
.error-404__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.9rem; margin: 2rem 0; }
.error-404 .search-form { margin-inline: auto; }

/* ==========================================================================
   WOOCOMMERCE
   WooCommerce ships high-specificity selectors such as
   `.single-product .product:not(.product-card) .woocommerce-tabs .panel` (0,3,1). Overrides below
   match that structure rather than reaching for !important (lesson WC-1).
   ========================================================================== */

/* ---------- WOOCOMMERCE — SHOP ARCHIVE ---------- */

.woocommerce .woocommerce-result-count,
.woocommerce .woocommerce-ordering { margin: 0; }

.woocommerce ul.products,
.products-grid {
	list-style: none;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(1.1rem, 2vw, 1.6rem);
	margin: 0;
	padding: 0;
}

/* WooCommerce floats and sizes li.product by percentage, which fights the
   grid (lesson WC-9). */
.woocommerce ul.products li.product,
.products-grid li.product {
	float: none;
	width: 100%;
	margin: 0;
	padding: 0;
}

.woocommerce ul.products li.product::before,
.woocommerce ul.products li.product::after { content: none; }

.woocommerce .products .star-rating,
.woocommerce ul.products li.product .button { display: none; }

/* ---------- WOOCOMMERCE — SINGLE PRODUCT ----------
   WooCommerce's .product div is flat: gallery, summary, tabs and related
   products are siblings, so named grid areas are the only reliable layout
   (lesson WC-7). :not(.product-card) keeps nested cards in related products
   out of the grid (lesson WC-6). */

.single-product .piece__grid .woocommerce-product-gallery { grid-area: gallery; }
.single-product .piece__grid .entry-summary { grid-area: summary; }

.single-product .product:not(.product-card) .woocommerce-product-gallery {
	/* sticky galleries float over the content below and break absolutely
	   positioned children such as the zoom trigger (lesson WC-3) */
	position: relative;
	margin: 0;
	width: 100%;
	float: none;
}

.single-product .product:not(.product-card) div.images { width: 100%; float: none; margin: 0; }
.single-product .product:not(.product-card) div.summary { width: 100%; float: none; margin: 0; }

.single-product .product:not(.product-card) .woocommerce-product-gallery__wrapper {
	margin: 0;
	background: var(--sage);
	border: 1px solid rgba(88, 95, 103, 0.16);
}

.single-product .product:not(.product-card) .woocommerce-product-gallery__image img { width: 100%; height: auto; display: block; }

.single-product .product:not(.product-card) .flex-control-thumbs {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
	gap: 0.55rem;
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
}

.single-product .product:not(.product-card) .flex-control-thumbs li { width: auto; margin: 0; float: none; }

.single-product .product:not(.product-card) .flex-control-thumbs img {
	opacity: 0.62;
	border: 1px solid transparent;
	background: var(--sage);
	transition: opacity 0.25s ease, border-color 0.25s ease;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

.single-product .product:not(.product-card) .flex-control-thumbs img:hover,
.single-product .product:not(.product-card) .flex-control-thumbs img.flex-active { opacity: 1; border-color: var(--slate); }

.single-product .product:not(.product-card) .product_title { display: none; } /* rendered by the theme's piece header */

.single-product .product:not(.product-card) p.price,
.single-product .product:not(.product-card) span.price {
	font-family: var(--serif);
	font-size: clamp(1.6rem, 2.6vw, 1.95rem);
	color: var(--slate);
	margin: 1.6rem 0 0;
	line-height: 1.25;
}

.single-product .product:not(.product-card) p.price del { opacity: 0.55; font-size: 0.7em; }
.single-product .product:not(.product-card) p.price ins { text-decoration: none; }

.price-vat-note,
.price-trade-note {
	display: block;
	margin-top: 0.3rem;
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	letter-spacing: 0.08em;
	color: var(--slate);
}

.price-trade-note { color: var(--rose-ink); }

/* Notices printed at the top of the piece, above the figure and summary. */
.piece__notices:empty { display: none; }
.piece__notices { padding-top: 0; }
.piece__notices .woocommerce-message,
.piece__notices .woocommerce-info,
.piece__notices .woocommerce-error { margin-bottom: 1.6rem; }

/* The quote confirmation banner sits under the actions, matching the basket's. */
.piece__quote-notice { margin-top: 1.2rem; }
.piece__quote-notice:empty { display: none; }
.piece__quote-notice .woocommerce-message { margin: 0; }

/* The quote route's enquiry link, beneath the phone line. */
.piece__enquire-line { margin: 0.6rem 0 0; font-size: var(--fs-xs); color: var(--slate); }
.piece__enquire-line a { color: var(--rose-ink); text-decoration: underline; text-underline-offset: 0.2em; }

.single-product .product:not(.product-card) form.cart { margin: 2rem 0 0; }

/* Add to basket + View basket side by side, like the quote route's pair. */
.single-product .product:not(.product-card) form.cart .single_add_to_cart_button,
.single-product .product:not(.product-card) form.cart .piece__view-basket { vertical-align: middle; }
/* The side-by-side gap applies only where the pair sits on one line; below
   the stacking breakpoint it would survive as a stray left indent. */
@media (min-width: 561px) {
	.single-product .product:not(.product-card) form.cart .piece__view-basket { margin-left: 0.9rem; }
}
.single-product .product:not(.product-card) form.cart::before,
.single-product .product:not(.product-card) form.cart::after { content: none; }

.single-product .product:not(.product-card) form.cart .variations {
	margin: 0;
	border: 0;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
	gap: 0 1rem;
}

.single-product .product:not(.product-card) form.cart .variations tbody,
.single-product .product:not(.product-card) form.cart .variations tr,
.single-product .product:not(.product-card) form.cart .variations th,
.single-product .product:not(.product-card) form.cart .variations td {
	display: block;
	border: 0;
	padding: 0;
	text-align: left;
}

.single-product .product:not(.product-card) form.cart .variations label {
	display: block;
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--slate);
	margin: 0 0 0.45rem;
}

.single-product .product:not(.product-card) form.cart .variations select {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-sm);
	color: var(--slate);
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: 0.7rem 0.8rem;
	margin-bottom: 1rem;
}

/* Once a variation resolves, its own price replaces the range under the
   title — two equal prices on one screen read as a mistake. */
.single-product .product:not(.product-card):has(.woocommerce-variation-price .price) > .piece__grid .summary > .price { display: none; }

.single-product .product:not(.product-card) form.cart .woocommerce-variation-price { margin-bottom: 1rem; }
.single-product .product:not(.product-card) form.cart .woocommerce-variation-price .price { margin-top: 0; }

.single-product .product:not(.product-card) form.cart div.quantity { float: none; margin: 0 0 1rem; }

.woocommerce .quantity .qty {
	width: 5.5rem;
	font-family: var(--sans);
	font-size: var(--fs-sm);
	text-align: center;
	color: var(--slate);
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: 0.7rem 0.4rem;
}

/* WooCommerce's own button classes must pick up the theme button. */
.woocommerce #respond input#submit,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt,
.woocommerce #respond input#submit.alt {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.7;
	border-radius: 0;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	background: var(--slate);
	color: var(--limewash);
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.woocommerce #respond input#submit:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce input.button.alt:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--limewash);
}

.woocommerce button.button:disabled,
.woocommerce button.button:disabled[disabled] {
	opacity: 0.5;
	padding: 0.95rem 1.5rem;
	color: var(--limewash);
}

.single-product .product:not(.product-card) .woocommerce-tabs,
.single-product .product:not(.product-card) .product_meta { display: none; }

.related.products,
.up-sells.products { grid-area: related; }

/* ---------- WOOCOMMERCE — CART / BASKET ----------
   The cart, checkout and account pages render shortcode output straight into
   the page with no container of their own (lesson #28). */

.woocommerce-cart .site-main > .woocommerce,
.woocommerce-checkout .site-main > .woocommerce,
.woocommerce-account .site-main > .woocommerce {
	max-width: var(--site-max);
	margin-inline: auto;
	padding: clamp(2rem, 5vw, 3.5rem) var(--gutter) clamp(3rem, 7vw, 5rem);
}

.woocommerce table.shop_table {
	border: 1px solid var(--hairline);
	border-radius: 0;
	border-collapse: collapse;
	background: var(--chalk);
	width: 100%;
}

.woocommerce table.shop_table th {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--slate);
	padding: 1rem;
	border-bottom: 1px solid var(--hairline);
}

.woocommerce table.shop_table td {
	padding: 1rem;
	border-top: 1px solid var(--hairline);
	font-size: var(--fs-sm);
	vertical-align: middle;
}

.woocommerce table.shop_table img { width: 72px; height: 72px; object-fit: cover; background: var(--sage); }

/* The basket page has no remove control: a line is cleared by setting its
   quantity to zero, or from the drawer. The drawer and the quote list keep
   theirs. */
.woocommerce-cart form.woocommerce-cart-form th.product-remove,
.woocommerce-cart form.woocommerce-cart-form td.product-remove { display: none; }

/* Each basket line sits on a white ground, at every width — the mobile card
   below restates it rather than carrying a different fill. */
.woocommerce-cart form.woocommerce-cart-form table.shop_table tr.woocommerce-cart-form__cart-item { background: var(--white); }

/* The remove control is a round white button rather than a bare glyph — it
   reads as an action, and gives the small × a comfortable target. */
.woocommerce a.remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.9rem;
	height: 1.9rem;
	border-radius: 50%;
	background: var(--white);
	border: 1px solid var(--hairline);
	color: var(--khaki-ink);
	font-size: var(--fs-sm);
	font-weight: 400;
	line-height: 1;
	text-decoration: none;
	transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}

.woocommerce a.remove:hover,
.woocommerce a.remove:focus-visible {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--white);
	text-decoration: none;
}

.woocommerce .cart-collaterals { width: 100%; }
.woocommerce .cart-collaterals .cart_totals { width: 100%; float: none; }

.woocommerce .cart_totals h2 {
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	margin: 0 0 1.2rem;
}

.woocommerce .cart_totals table.shop_table { background: var(--chalk); }
.woocommerce .cart_totals .order-total .amount { font-family: var(--serif); font-size: var(--fs-xl); }

.woocommerce .cart .actions .coupon { display: flex; gap: 0.6rem; flex-wrap: wrap; }
.woocommerce .cart .actions .coupon .input-text {
	width: auto;
	flex: 1 1 12rem;
	font-family: var(--sans);
	font-size: var(--fs-sm);
	background: var(--white);
	border: 1px solid var(--hairline);
	padding: 0.85rem 1rem;
}

.woocommerce .cart-empty,
.woocommerce .return-to-shop { text-align: left; }
.woocommerce .cart-empty { font-size: var(--fs-lg); padding: 2rem 0 1rem; }

/* ---------- WOOCOMMERCE — CHECKOUT ---------- */

.woocommerce-checkout .woocommerce form.checkout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.woocommerce-checkout #customer_details { grid-column: 1; }
.woocommerce-checkout #order_review_heading,
.woocommerce-checkout #order_review { grid-column: 2; }
.woocommerce-checkout .col2-set .col-1,
.woocommerce-checkout .col2-set .col-2 { width: 100%; float: none; }

.woocommerce form .form-row { padding: 0; margin: 0 0 1.3rem; }

.woocommerce form .form-row label {
	display: block;
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
	margin-bottom: 0.45rem;
}

.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce form .form-row .select2-container .select2-selection--single {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-md);
	color: var(--slate);
	background: var(--white);
	border: 1px solid var(--hairline);
	border-radius: 0;
	padding: 0.85rem 1rem;
	height: auto;
}

.woocommerce form .form-row .select2-container .select2-selection__rendered { padding: 0; line-height: 1.6; color: var(--slate); }
.woocommerce form .form-row .select2-container .select2-selection__arrow { top: 50%; transform: translateY(-50%); }

.woocommerce-checkout #payment {
	background: var(--white);
	border: 1px solid var(--hairline);
	border-radius: 0;
}

/* The privacy/terms note and the "no payment methods" notice sit on the same
   white ground as the rest of the information box. */
.woocommerce-checkout #payment .woocommerce-privacy-policy-text,
.woocommerce-checkout #payment .woocommerce-terms-and-conditions-wrapper,
.woocommerce-checkout #payment .woocommerce-notice,
.woocommerce-checkout #payment .woocommerce-info { background: var(--white); border: 0; margin: 0; }

/* Inside the order panel a payment notice is plain text; the site notice's
   marker dot belongs on a standalone message, not here. */
.woocommerce-checkout #payment .woocommerce-notice::before,
.woocommerce-checkout #payment .woocommerce-info::before,
.woocommerce-checkout #payment li.woocommerce-notice::before { content: none; }

.woocommerce-checkout #payment .woocommerce-notice,
.woocommerce-checkout #payment .woocommerce-info { padding: 1.2rem; }
.woocommerce-checkout #payment ul.payment_methods { border-bottom: 1px solid var(--hairline); padding: 1.2rem 0; }
.woocommerce-checkout #payment div.payment_box { background: var(--limewash); border: 1px solid var(--hairline); font-size: var(--fs-xs); }
.woocommerce-checkout #payment div.payment_box::before { display: none; }
.woocommerce-checkout #payment div.form-row { padding: 1.2rem 0; }
.woocommerce-checkout #place_order { width: 100%; }

/* The order column reads as the prototype's summary panel: chalk ground,
   hairline border, and the totals set as label/value rows. */
.woocommerce-checkout #order_review_heading {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
	margin: 0 0 1.2rem;
}

/* The heading and the panel are separate grid items in column 2. Without an
   explicit row the panel fell into row 2, level with the foot of the tall
   billing column, leaving the heading stranded at the top. */
/* WooCommerce inserts a notice group as the form's first child after a failed
   submit. Named rows let it take a full-width row of its own, so the panel is
   never displaced beneath the billing column when errors appear. */
.woocommerce-checkout .woocommerce form.checkout {
	grid-template-rows: auto auto;
	grid-template-areas:
		"notice notice"
		"billing order";
}

.woocommerce-checkout form.checkout > .woocommerce-NoticeGroup,
.woocommerce-checkout form.checkout > .woocommerce-notices-wrapper {
	grid-area: notice;
	grid-column: 1 / -1;
	margin-bottom: 1.4rem;
}

.woocommerce-checkout #customer_details { grid-area: billing; }

.woocommerce-checkout #order_review_heading {
	grid-area: order;
	align-self: start;
}

/* Row 1 is sized by the billing column, so the panel must not be pushed into
   a second row — it sits in row 1 too, directly beneath its heading, with the
   heading's height reserved by padding rather than by a tall empty row. */
.woocommerce-checkout #order_review {
	grid-area: order;
	align-self: start;
	margin-top: 2.6rem;
}

.woocommerce-checkout #customer_details {
	grid-area: billing;
	/* The same panel as the contact form, so the two forms read as one family. */
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: clamp(1.6rem, 3.5vw, 2.6rem);
}

.woocommerce-checkout #customer_details h3 {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
	margin: 0 0 1.4rem;
}

.woocommerce-checkout #customer_details .woocommerce-shipping-fields h3,
.woocommerce-checkout #customer_details .woocommerce-additional-fields h3 { margin-top: 1.6rem; }

.woocommerce-checkout #customer_details h3 label { font: inherit; letter-spacing: inherit; text-transform: inherit; }

/* Billing fields pair up on desktop. WooCommerce already marks the names
   `form-row-first`/`form-row-last`; the short address fields are widened to
   `form-row-wide` by the UK locale, so they are paired here by id. The wrapper
   is the grid, and `min-width: 0` keeps a long label from forcing a track
   wider than its half (the grid-track lesson from the 400px overflow). */
@media (min-width: 1025px) {
	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		column-gap: 1.2rem;
	}

	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > .form-row,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper > .form-row {
		grid-column: 1 / -1;
		min-width: 0;
	}

	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > .form-row-first,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper > .form-row-first,
	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > #billing_city_field,
	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > #billing_postcode_field,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper > #shipping_city_field,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper > #shipping_postcode_field { grid-column: 1; }

	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > .form-row-last,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper > .form-row-last,
	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > #billing_state_field,
	.woocommerce-checkout .woocommerce-billing-fields__field-wrapper > #billing_phone_field,
	.woocommerce-checkout .woocommerce-shipping-fields__field-wrapper > #shipping_state_field { grid-column: 2; }
}

.woocommerce-checkout #order_review {
	background: var(--white);
	border: 1px solid var(--hairline);
	padding: clamp(1.4rem, 3vw, 2rem);
	position: sticky;
	top: 7.5rem;
}

.woocommerce-checkout #order_review table.shop_table {
	background: none;
	border: 0;
	margin: 0 0 1rem;
}

.woocommerce-checkout #order_review table.shop_table th,
.woocommerce-checkout #order_review table.shop_table td {
	border: 0;
	padding: 0.4rem 0;
	font-size: var(--fs-xs);
}

.woocommerce-checkout #order_review table.shop_table thead th {
	border-bottom: 1px solid var(--hairline);
	padding-bottom: 0.7rem;
}

.woocommerce-checkout #order_review .order-total th,
.woocommerce-checkout #order_review .order-total td {
	border-top: 1px solid var(--hairline);
	padding-top: 0.9rem;
}

/* Your order: the review table is a stack of label/value rows, like the
   basket totals, with the piece itself set as a line item above them. */
.woocommerce-checkout #order_review table.shop_table,
.woocommerce-checkout #order_review table.shop_table thead,
.woocommerce-checkout #order_review table.shop_table tbody,
.woocommerce-checkout #order_review table.shop_table tfoot { display: block; width: 100%; }

.woocommerce-checkout #order_review table.shop_table tr {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 1rem;
	width: 100%;
	padding: 0.45rem 0;
}

.woocommerce-checkout #order_review table.shop_table thead tr {
	border-bottom: 1px solid var(--hairline);
	padding-bottom: 0.7rem;
	margin-bottom: 0.4rem;
}

/* The heading cells carry no rule of their own — the row provides it. */
.woocommerce-checkout #order_review table.shop_table thead th {
	border: 0;
	text-decoration: none;
}

.woocommerce-checkout #order_review table.shop_table th {
	flex: 0 0 auto;
	text-align: left;
	white-space: nowrap;
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--slate);
}

.woocommerce-checkout #order_review table.shop_table td {
	flex: 1 1 auto;
	text-align: right;
	font-size: var(--fs-xs);
}

.woocommerce-checkout #order_review .cart_item td.product-name {
	flex: 1 1 auto;
	text-align: left;
	font-size: var(--fs-xs);
	color: var(--slate);
}

.woocommerce-checkout #order_review .cart_item .product-quantity {
	font-weight: 400;
	color: var(--khaki-ink);
	margin-left: 0.35rem;
}

.woocommerce-checkout #order_review tfoot { border-top: 1px solid var(--hairline); margin-top: 0.5rem; padding-top: 0.5rem; }

.woocommerce-checkout #order_review .order-total { border-top: 1px solid var(--hairline); margin-top: 0.4rem; padding-top: 0.9rem; }

.woocommerce-checkout #order_review .order-total .amount {
	font-family: var(--serif);
	font-size: var(--fs-xl);
}

/* WooCommerce renders shipping choices as a bare list. */
.woocommerce-checkout #order_review ul#shipping_method {
	list-style: none;
	margin: 0;
	padding: 0;
}

.woocommerce-checkout #order_review ul#shipping_method li { margin: 0; }

.woocommerce-checkout #payment ul.payment_methods { list-style: none; margin: 0; }
.woocommerce-checkout #payment ul.payment_methods li { margin: 0; }
.woocommerce-checkout #payment .woocommerce-notice,
.woocommerce-checkout #payment .woocommerce-info { font-size: var(--fs-xs); }

/* ---------- WOOCOMMERCE — MY ACCOUNT ---------- */

.woocommerce-account .woocommerce {
	display: grid;
	grid-template-columns: 240px 1fr;
	gap: clamp(2rem, 5vw, 3.5rem);
	align-items: start;
}

/* The login form is not part of the account grid. */
.woocommerce-account:not(.logged-in) .woocommerce { display: block; max-width: 34rem; }

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

.woocommerce-account .woocommerce-MyAccount-navigation-link a {
	display: block;
	padding: 0.7rem 1rem;
	border-left: 2px solid transparent;
	font-size: var(--fs-2xs);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--slate-ink);
	text-decoration: none;
}

.woocommerce-account .woocommerce-MyAccount-navigation-link a:hover { color: var(--slate); background: var(--chalk); }

.woocommerce-account .woocommerce-MyAccount-navigation-link.is-active a {
	border-left-color: var(--rose-ink);
	background: var(--chalk);
	color: var(--slate);
	font-weight: 500;
}

.woocommerce-account .woocommerce-MyAccount-content h2,
.woocommerce-account .woocommerce-MyAccount-content h3 { font-family: var(--serif); font-weight: 400; }

/* The password section is a browser-styled fieldset unless reset. */
.woocommerce .woocommerce-EditAccountForm fieldset { border: 1px solid var(--hairline); padding: 1.4rem; margin: 1.6rem 0; }

.woocommerce .woocommerce-EditAccountForm legend {
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	padding: 0 0.6rem;
}

.woocommerce-form-register { border: 1px solid var(--hairline); background: var(--chalk); padding: clamp(1.4rem, 3vw, 2.2rem); border-radius: 0; }

/* The trade sign-in sits inside the tab panel, which already provides the
   frame, so the form itself carries no box. Its fields take the same
   treatment as the application form beside it. */
.trade-signedin__note { margin: 0 0 1.1rem; color: var(--slate); }
.trade-signedin__link { display: inline-block; }

.tabs__panel .woocommerce-form-login { border: 0; background: none; padding: 0; margin: 0; }

.tabs__panel .woocommerce-form-login .form-row { float: none; width: 100%; margin: 0 0 1.3rem; padding: 0; }

.tabs__panel .woocommerce-form-login label:not(.woocommerce-form__label-for-checkbox) {
	display: block;
	margin: 0 0 0.45rem;
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
}

.tabs__panel .woocommerce-form-login label .required { color: var(--rose-ink); text-decoration: none; }

.tabs__panel .woocommerce-form-login input.input-text {
	width: 100%;
	box-sizing: border-box;
	padding: 0.85rem 1rem;
	font-family: var(--sans);
	font-size: var(--fs-md);
	color: var(--slate);
	background: var(--white);
	border: 1px solid var(--hairline);
	border-radius: 0;
}

.tabs__panel .woocommerce-form-login input.input-text:focus-visible { outline: none; border-color: var(--slate); }
.tabs__panel .woocommerce-form-login button[type="submit"],
.tabs__panel .woocommerce-form-login .woocommerce-form-login__submit {
	display: block;
	width: 100%;
	margin-top: 0.4rem;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	background: var(--slate);
	color: var(--limewash);
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	cursor: pointer;
	border-radius: 0;
	transition: background-color 0.3s ease, border-color 0.3s ease;
}

.tabs__panel .woocommerce-form-login button[type="submit"]:hover { background: var(--rose-ink); border-color: var(--rose-ink); }
.tabs__panel .woocommerce-form-login .form-row:has(.woocommerce-form-login__rememberme) { margin-bottom: 1rem; }
.woocommerce-form-login__rememberme { font-size: var(--fs-xs); text-transform: none; letter-spacing: 0; }
.woocommerce-LostPassword { font-size: var(--fs-xs); }

/* ---------- WOOCOMMERCE — NOTICES ---------- */

/* Notices read as a quiet chalk panel with a hairline and a drawn tick,
   rather than WooCommerce's coloured bar and dingbat glyph. */
.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	background: var(--chalk);
	border: 1px solid var(--hairline);
	color: var(--slate);
	font-size: var(--fs-sm);
	padding: 1.1rem 1.4rem 1.1rem 3.6rem;
	list-style: none;
	margin: 0 0 1.6rem;
}

/* The plugin's ::before is a WooCommerce icon-font glyph; replace it. */
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-error::before {
	content: "";
	position: absolute;
	left: 1.4rem;
	top: 50%;
	width: 1.35rem;
	height: 1.35rem;
	margin: 0;
	transform: translateY(-50%);
	border-radius: 50%;
	background: var(--positive);
	font-size: 0;
	animation: none;
}

.woocommerce-message::after {
	content: "";
	position: absolute;
	left: calc(1.4rem + 0.47rem);
	top: calc(50% - 0.17rem);
	width: 0.3rem;
	height: 0.56rem;
	border-right: 2px solid var(--limewash);
	border-bottom: 2px solid var(--limewash);
	transform: translateY(-50%) rotate(45deg);
}

.woocommerce-info::before { background: var(--slate); }
.woocommerce-error::before { background: var(--rose-ink); }

/* The info and error discs carry a drawn "i" and "!" — the plugin's icon
   font never loads here, which left them as blank circles. Tick stays green
   only by exception: it is the one universally-read success mark. */
.woocommerce-info::after,
.woocommerce-error::after {
	content: "";
	position: absolute;
	left: calc(1.4rem + 0.6rem);
	top: 50%;
	width: 2px;
	height: 0.5rem;
	background: var(--limewash);
	transform: translate(-50%, -30%);
}

.woocommerce-info::after { box-shadow: 0 -0.42rem 0 0 var(--limewash); height: 0.42rem; transform: translate(-50%, -10%); }
.woocommerce-error::after { box-shadow: 0 0.42rem 0 0 var(--limewash); height: 0.42rem; transform: translate(-50%, -60%); }

/* Success uses the palette's positive green — the one exception, kept
   because a tick in any other colour reads as a warning. */
.woocommerce-message::before { background: var(--positive); }

/* The notice's own icon-font glyph, when the font does load, would double the
   drawn mark. Suppress it. */
.woocommerce-message .gform-icon,
.woocommerce-info .gform-icon,
.woocommerce-error .gform-icon { display: none; }

.woocommerce-message a:not(.button),
.woocommerce-info a:not(.button) { color: var(--rose-ink); }

/* The notice's action is a ghost button on the panel. */
.woocommerce-message .button,
.woocommerce-info .button,
.woocommerce-error .button {
	margin-left: auto;
	padding: 0.7rem 1.2rem;
	border: 1px solid var(--slate);
	background: transparent;
	color: var(--slate);
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-3xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	text-decoration: none;
	border-radius: 0;
	transition: background-color 0.3s ease, color 0.3s ease;
}

.woocommerce-message .button:hover,
.woocommerce-info .button:hover,
.woocommerce-error .button:hover { background: var(--slate); color: var(--limewash); }

@media (max-width: 560px) {
	.woocommerce-message,
	.woocommerce-info,
	.woocommerce-error { padding-left: 3.2rem; }

	.woocommerce-message .button,
	.woocommerce-info .button,
	.woocommerce-error .button { margin-left: 0; width: 100%; text-align: center; box-sizing: border-box; }
}

/* ---------- GRAVITY FORMS ---------- */

.gform_wrapper .gfield { margin-bottom: 1.3rem; padding: 0; }

.gform_wrapper.gravity-theme .gfield_label,
.gform_wrapper .gfield_label {
	display: block;
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
	margin-bottom: 0.45rem;
}

.gform_wrapper.gravity-theme input[type="text"],
.gform_wrapper.gravity-theme input[type="email"],
.gform_wrapper.gravity-theme input[type="tel"],
.gform_wrapper.gravity-theme input[type="url"],
.gform_wrapper.gravity-theme input[type="number"],
.gform_wrapper.gravity-theme input[type="password"],
.gform_wrapper.gravity-theme textarea,
.gform_wrapper.gravity-theme select {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-md);
	color: var(--slate);
	background: var(--white);
	border: 1px solid var(--hairline);
	border-radius: 0;
	padding: 0.85rem 1rem;
	transition: border-color 0.25s ease;
}

.gform_wrapper.gravity-theme textarea { min-height: 9rem; resize: vertical; }

.gform_wrapper.gravity-theme input:focus-visible,
.gform_wrapper.gravity-theme textarea:focus-visible,
.gform_wrapper.gravity-theme select:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 1px;
	border-color: var(--rose-ink);
}

.gform_wrapper.gravity-theme .gform_footer,
.gform_wrapper.gravity-theme .gform_page_footer {
	padding: 0;
	margin: 1.6rem 0 0;
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
}

.gform_wrapper.gravity-theme .gform_button,
.gform_wrapper.gravity-theme .gform_next_button,
.gform_wrapper.gravity-theme .gform_previous_button {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	background: var(--slate);
	color: var(--limewash);
	border-radius: 0;
	cursor: pointer;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.gform_wrapper.gravity-theme .gform_button:hover,
.gform_wrapper.gravity-theme .gform_next_button:hover { background: var(--rose-ink); border-color: var(--rose-ink); }



.gform_wrapper.gravity-theme .gfield_required { color: var(--rose-ink); }
.gform_wrapper.gravity-theme .gfield_description { font-size: var(--fs-xs); color: var(--khaki-ink); padding-top: 0.4rem; }

.gform_wrapper.gravity-theme .gfield_error input,
.gform_wrapper.gravity-theme .gfield_error textarea,
.gform_wrapper.gravity-theme .gfield_error select { border-color: var(--rose-ink); }

.gform_wrapper .gform_validation_errors,
.gform_wrapper.gravity-theme .gform_validation_errors {
	background: var(--chalk);
	border: 1px solid var(--rose-ink);
	border-radius: 0;
	box-shadow: none;
	color: var(--rose-ink);
	font-size: var(--fs-sm);
}

/* The quote form's own page-step bar duplicated the theme's stepper above
   it, so two progress indicators showed. The theme's stepper follows
   gform_page_loaded and owns the display. */
.block-quote .gf_page_steps,
.block-quote [id^="gf_page_steps_"] { display: none !important; }

/* Item 13: the success message as a card with a tick, rather than a bare
   paragraph. The tick is drawn with a border so no icon asset is needed. */
.gform_confirmation_message {
	position: relative;
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: 1.6rem 1.8rem 1.6rem 4.6rem;
	font-size: var(--fs-lg);
	color: var(--slate);
}

.gform_confirmation_message::before {
	content: "";
	position: absolute;
	left: 1.6rem;
	top: 1.55rem;
	width: 1.9rem;
	height: 1.9rem;
	border-radius: 50%;
	background: var(--positive);
}

.gform_confirmation_message::after {
	content: "";
	position: absolute;
	left: calc(1.6rem + 0.62rem);
	top: calc(1.55rem + 0.5rem);
	width: 0.42rem;
	height: 0.78rem;
	border-right: 2px solid var(--limewash);
	border-bottom: 2px solid var(--limewash);
	transform: rotate(45deg);
}

.gform_confirmation_message p { margin: 0; }
.gform_confirmation_message p + p { margin-top: 0.6rem; }

/* Once the quote form confirms, the stepper has done its job. */
.block-quote:has(.gform_confirmation_message) .stepper { display: none; }

/* ---------- QUOTE FORM PAGES AS PANELS ----------
   The prototype gives every step its own bordered chalk panel with a title and
   a ruled action row. Gravity Forms renders its pages as bare field groups, so
   the panel is built around .gform_page here. */
.block-quote .gform_wrapper .gform_page {
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: clamp(1.4rem, 3vw, 2rem);
	margin: 0;
}

/* The steps repeater names the panels; the form's own page titles are the
   fallback when a label is missing. */
.block-quote .gform_wrapper .gform_page::before {
	content: attr(data-step-title);
	display: block;
	font-family: var(--serif);
	font-weight: 400;
	font-size: var(--fs-2xl);
	color: var(--slate);
	margin: 0 0 0.5rem;
}

.block-quote .gform_wrapper .gform_page:not([data-step-title])::before { content: none; }

.block-quote .gform_wrapper .gform_page_footer {
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
	margin-top: 2rem;
	padding: 1.6rem 0 0;
	border-top: 1px solid var(--hairline);
}

/* The panel above holds step 1; the form's pages continue the sequence. */
.block-quote .block-quote__form { margin-top: 1.4rem; }

.block-quote .step { margin-bottom: 0; }

/* The items list is empty until a piece is added, so the panel's parts need
   their own rhythm rather than the block editor's paragraph spacing. */
.block-quote .step__lede { margin: 0 0 1.4rem; }
.block-quote .step .cart__items:empty { display: none; }
.block-quote .step .cart__empty { margin: 0; padding: 0; }
.block-quote .step .form-note { margin: 1.4rem 0 0; font-size: var(--fs-2xs); color: var(--khaki-ink); }

/* Back is the quieter of the pair. */
/* Previous is the outlined pair to Continue, matching "Add more pieces". The
   theme injects it as a <button>, while Gravity Forms' own is an <input>, and
   a broad slate-fill rule covers both — so this matches every shape at a
   weight that beats it. */
.gform_wrapper .gform_page_footer .gform_previous_button,
.gform_wrapper .gform_page_footer button.gform_previous_button,
.gform_wrapper .gform_page_footer input.gform_previous_button,
.block-quote .gform_wrapper .gform_previous_button,
.gform_wrapper.gravity-theme .gform_previous_button,
[id^="gform_wrapper"] .gform_page_footer .gform_previous_button {
	/* Previous carries `.button` AND `.gform-theme-button--secondary`, so the
	   orbital framework's high-position :where() block sets --gf-local-* on the
	   element from the SECONDARY control tokens. Setting --gf-local-* here
	   cannot win — that block loads after main.css and re-declares them on the
	   same element. The secondary tokens are the only reachable lever, so they
	   are re-pointed at the outline treatment "Add more pieces" uses. */
	--gf-ctrl-btn-bg-color-secondary: transparent;
	--gf-ctrl-btn-color-secondary: var(--slate);
	--gf-ctrl-btn-border-color-secondary: var(--slate);
	--gf-ctrl-btn-bg-color-hover-secondary: var(--slate);
	--gf-ctrl-btn-color-hover-secondary: var(--limewash);
	--gf-ctrl-btn-border-color-hover-secondary: var(--slate);
	--gf-ctrl-btn-bg-color-focus-secondary: var(--slate);
	--gf-ctrl-btn-color-focus-secondary: var(--limewash);
	--gf-ctrl-btn-border-color-focus-secondary: var(--slate);
	background: transparent;
	border: 1px solid var(--slate);
	color: var(--slate);
}

.gform_wrapper .gform_page_footer .gform_previous_button:hover,
.block-quote .gform_wrapper .gform_previous_button:hover,
.gform_wrapper.gravity-theme .gform_previous_button:hover,
[id^="gform_wrapper"] .gform_page_footer .gform_previous_button:hover {
	background: var(--slate);
	border-color: var(--slate);
	color: var(--limewash);
}

.gform_wrapper.gravity-theme .gf_progressbar_wrapper { margin-bottom: 1.6rem; }
.gform_wrapper.gravity-theme .gf_progressbar { background: var(--chalk); border-radius: 0; }
.gform_wrapper.gravity-theme .gf_progressbar_percentage { background: var(--slate); border-radius: 0; }
.gform_wrapper.gravity-theme .gf_progressbar_percentage span { color: var(--limewash); font-size: var(--fs-3xs); letter-spacing: 0.12em; }

/* ---------- BLOCK SPACING UTILITIES ----------
   Driven by the Settings tab every ACF block carries (playbook §6.3). */

.pt-none { padding-top: var(--space-none); }
.pt-sm   { padding-top: var(--space-sm); }
.pt-md   { padding-top: var(--space-md); }
.pt-lg   { padding-top: var(--space-lg); }
.pt-xl   { padding-top: var(--space-xl); }

.pb-none { padding-bottom: var(--space-none); }
.pb-sm   { padding-bottom: var(--space-sm); }
.pb-md   { padding-bottom: var(--space-md); }
.pb-lg   { padding-bottom: var(--space-lg); }
.pb-xl   { padding-bottom: var(--space-xl); }

.mt-none { margin-top: var(--space-none); }
.mt-sm   { margin-top: var(--space-sm); }
.mt-md   { margin-top: var(--space-md); }
.mt-lg   { margin-top: var(--space-lg); }
.mt-xl   { margin-top: var(--space-xl); }

.mb-none { margin-bottom: var(--space-none); }
.mb-sm   { margin-bottom: var(--space-sm); }
.mb-md   { margin-bottom: var(--space-md); }
.mb-lg   { margin-bottom: var(--space-lg); }
.mb-xl   { margin-bottom: var(--space-xl); }

/* ---------- RESPONSIVE ----------
   Desktop-first, matching the prototype. Component-level breakpoints sit with
   their component; this section is for cross-cutting collapses only. */

@media (max-width: 1024px) {
	.woocommerce-checkout .woocommerce form.checkout { grid-template-columns: 1fr; }

	/* The desktop layout pins each part to an explicit row so the panel sits
	   under its heading. Collapsing the columns without clearing those rows
	   dropped billing and the order block into the same row, overlapping. */
	.woocommerce-checkout .woocommerce form.checkout {
		grid-template-areas:
			"notice"
			"billing"
			"order";
	}

	.woocommerce-checkout #customer_details,
	.woocommerce-checkout #order_review_heading,
	.woocommerce-checkout #order_review {
		grid-column: 1;
		grid-row: auto;
	}

	/* Nothing to stick to in a single column. */
	.woocommerce-checkout #order_review {
		position: static;
		margin-top: 0;
	}

	.woocommerce-checkout #order_review_heading { margin-top: 2rem; }
	.post-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 980px) {
	.nav-toggle { display: inline-block; justify-self: start; }

	/* Full-page menu, after the fashion of the prototype. */
	.site-nav {
		display: none;
		position: fixed;
		inset: 0;
		justify-self: stretch;
		align-self: stretch;
		z-index: 2;
		background: var(--slate);
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 6rem var(--gutter) 3rem;
	}

	.site-nav.open { display: flex; animation: menu-fade 0.35s ease both; }

	@keyframes menu-fade {
		from { opacity: 0; }
		to { opacity: 1; }
	}

	.site-nav__list { flex-direction: column; gap: 0.6rem; }
	.site-nav__item { margin: 0; }

	.site-nav__link {
		color: var(--limewash);
		font-size: var(--fs-md);
		letter-spacing: 0.1em;
		padding: 0.9rem 0.5rem;
	}

	/* The over-hero white treatment must not leak into the slate panel. */
	.site-header--over .site-nav__link { color: var(--limewash); }
	.site-header--over .site-nav__item--current > .site-nav__link { border-bottom-color: var(--limewash); }
}

@media (max-width: 900px) {
	.collection { grid-template-columns: 1fr; gap: 2rem; }
	.collection__rail-inner { position: static; }
	.filter-rail { display: none; }
	.filter-select { display: block; }
	.filter-search { margin-bottom: 1.2rem; }

	.piece__grid,
	.split-grid,
	.split-grid--flip,
	.contact-grid,
	.media-band__grid { grid-template-columns: 1fr; }

	.media-band--flip .media-band__grid { direction: ltr; }
	.media-band__content { padding-right: var(--gutter); }
	.media-band__media { min-height: 260px; }
	.split-grid .arch { max-width: 360px; }
	.split-grid--flip .split-grid__media { order: 0; }

	.tile-grid,
	.tile-grid--4,
	.woocommerce ul.products,
	.products-grid { grid-template-columns: repeat(2, 1fr); }

	.site-footer__grid { grid-template-columns: 1fr 1fr; }

	.pillars__list { grid-template-columns: 1fr; }
	.pillar { border-left: 0; border-top: 1px solid var(--hairline); padding-block: 2.75rem; }
	.pillar:first-child { border-top: 0; }

	.woocommerce-account .woocommerce { grid-template-columns: 1fr; }

	.header-mini { font-size: 0; gap: 0; min-width: 24px; justify-content: center; }
	.header-mini__count { font-size: var(--fs-3xs); min-width: 24px; height: 24px; }
}

@media (max-width: 760px) {
	.line { grid-template-columns: 64px 1fr auto; gap: 0.6rem 0.9rem; }
	.line__img { width: 64px; height: 64px; grid-row: span 2; }
	.line__body { grid-column: 2 / -1; }
	.line__price { grid-column: 2; text-align: left; }
	.line__remove { grid-column: 3; justify-self: end; }

	/* The cart table stacks into cards rather than scrolling sideways. */
	.woocommerce table.shop_table_responsive thead { display: none; }
	.woocommerce table.shop_table_responsive tr { display: block; border-bottom: 1px solid var(--hairline); }
	.woocommerce table.shop_table_responsive td { display: flex; justify-content: space-between; gap: 1rem; border: 0; text-align: right; }
	.woocommerce table.shop_table_responsive td::before { content: attr(data-title); font-size: var(--fs-2xs); letter-spacing: 0.16em; text-transform: uppercase; color: var(--khaki-ink); }

	/* The totals table already renders its own <th> label per row, so the
	   responsive data-title would print every label twice. */
	.woocommerce-cart .cart_totals table.shop_table td::before { content: none; }

	.woocommerce-cart .cart-collaterals { margin-top: 0.4rem; }

	/* The totals panel's label/value rows stack at phone width: the shipping
	   row otherwise forced three columns onto one line. */
	.woocommerce-cart .cart_totals table.shop_table tr {
		flex-direction: column;
		align-items: flex-start;
		gap: 0.25rem;
	}

	.woocommerce-cart .cart_totals table.shop_table td { text-align: left; width: 100%; }
	.woocommerce-cart .cart_totals .woocommerce-shipping-methods,
	.woocommerce-cart .cart_totals .woocommerce-shipping-destination,
	.woocommerce-cart .cart_totals .woocommerce-shipping-calculator { text-align: left; }
	.woocommerce-cart .cart_totals .order-total td { text-align: left; }

	/* The stacked card: thumbnail and name on one line, then label/value
	   rows. The width rules that size the desktop columns must not apply. */
	.woocommerce-cart form.woocommerce-cart-form table.shop_table,
	.woocommerce-cart form.woocommerce-cart-form table.shop_table tbody { display: block; width: 100%; }

	.woocommerce-cart form.woocommerce-cart-form table.shop_table th.product-thumbnail,
	.woocommerce-cart form.woocommerce-cart-form table.shop_table td.product-thumbnail { width: auto; }

	/* Each line is a card: the table keeps WooCommerce's quantity and remove
	   handlers working, while the row reads as a panel on a narrow screen. */
	.woocommerce-cart form.woocommerce-cart-form table.shop_table {
		border: 0;
		background: none;
	}

	.woocommerce-cart form.woocommerce-cart-form table.shop_table tr.woocommerce-cart-form__cart-item {
		display: grid;
		grid-template-columns: 72px 1fr;
		column-gap: 1rem;
		row-gap: 0.15rem;
		align-items: start;
		padding: 1.2rem;
		margin-bottom: 0.9rem;
		background: var(--white);
		border: 1px solid var(--hairline);
	}

	.woocommerce-cart form.woocommerce-cart-form td.product-thumbnail {
		grid-row: 1 / span 5;
		align-self: start;
		display: block;
		padding: 0;
	}

	.woocommerce-cart form.woocommerce-cart-form td.product-thumbnail::before { content: none; }
	.woocommerce-cart form.woocommerce-cart-form td.product-thumbnail img { width: 72px; height: 72px; }

	.woocommerce-cart form.woocommerce-cart-form td.product-name { text-align: left; padding: 0 0 0.5rem; }
	.woocommerce-cart form.woocommerce-cart-form td.product-name a { font-size: var(--fs-sm); }
	.woocommerce-cart form.woocommerce-cart-form td.product-name::before { content: none; }

	.woocommerce-cart form.woocommerce-cart-form td.product-price,
	.woocommerce-cart form.woocommerce-cart-form td.product-quantity,
	.woocommerce-cart form.woocommerce-cart-form td.product-subtotal { padding: 0.25rem 0; }

	/* The subtotal closes the card, so it earns a rule above it. */
	.woocommerce-cart form.woocommerce-cart-form td.product-subtotal {
		margin-top: 0.35rem;
		padding-top: 0.6rem;
		border-top: 1px solid var(--hairline);
	}

	.woocommerce-cart form.woocommerce-cart-form td.product-quantity .qty { width: 4.2rem; }

	/* Remove sits with the row, not on a line of its own. */
	.woocommerce-cart form.woocommerce-cart-form td.product-remove {
		grid-column: 2;
		justify-content: flex-start;
		padding: 0.4rem 0 0;
	}

	.woocommerce-cart form.woocommerce-cart-form td.product-remove::before { content: none; }

	.woocommerce-cart form.woocommerce-cart-form td.actions { display: block; padding: 1.1rem 0 0; }
	.woocommerce-cart form.woocommerce-cart-form td.actions::before { content: none; }
}

@media (max-width: 640px) {
	.post-grid { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
	.options__row { flex-direction: column; gap: 0.2rem; }
	.options__row dd { white-space: normal; }
}

@media (max-width: 480px) {
	.tile-grid,
	.tile-grid--2,
	.tile-grid--4,
	.woocommerce ul.products,
	.products-grid { grid-template-columns: 1fr; }

	.site-footer__grid { grid-template-columns: 1fr; }
	.spec__row { grid-template-columns: 1fr; gap: 0.2rem; }
	.stepper { gap: 0.4rem 1.2rem; }
}

/* ---------- REDUCED MOTION ---------- */

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }

	.site-header,
	.tile__frame img,
	.gallery__thumb,
	.filter-link,
	.route-opt,
	.route-opt input::before,
	.stepper__item,
	.tabs__tab,
	.breadcrumb a,
	.nav-toggle__bar { transition: none; }

	.hero-film__logo,
	.hero-page__content .eyebrow,
	.hero-page__title,
	.hero-page__lede,
	.site-nav.open { animation: none; }

	.hero-slides__img { transition: none; }
	.hero-slides__img.is-current,
	.hero-slides__img.is-leaving { animation: none; transform: scale(1.04); }
	.hero-page__img { transition: none; }

	.js .reveal { opacity: 1; transform: none; transition: none; }

	.tile:hover .tile__frame img,
	.tile:focus-visible .tile__frame img { transform: none; }

	.mini-basket__panel,
	.mini-basket__backdrop { transition: none; }
}

/* ---------- BLOCK: COLUMNS ---------- */

.block-columns {
	display: grid;
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: start;
	/* The ACF InnerBlocks wrapper is display:contents, so the grid itself owns
	   the page gutter that the wrapper used to supply. */
	max-width: var(--site-max);
	margin-inline: auto;
	padding-inline: var(--gutter);
	box-sizing: border-box;
}

/* Nested inside a Section, the section's .wrap already provides the gutter. */
.block-container .block-columns,
.wrap .block-columns {
	max-width: none;
	margin-inline: 0;
	padding-inline: 0;
}

.block-columns--1-1   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.block-columns--5-6   { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
.block-columns--6-5   { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
.block-columns--1-1-1 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.block-column > * + * { margin-top: 1.1rem; }

/* A section block nested inside a column should not re-apply page padding. */
.block-column .section { padding-block: 0; }
.block-column .wrap { padding-inline: 0; max-width: none; }

/* ---------- BLOCK: SECTION / CONTAINER ---------- */

.block-container--centred { text-align: center; }
.block-container--centred .lede,
.block-container--centred p { margin-inline: auto; }
.block-container--centred .section__head { justify-content: center; text-align: center; }

.block-container > .wrap > * + *,
.block-container--full > * + * { margin-top: 1.1rem; }

.block-container .section__head + * { margin-top: 0; }

/* ---------- BLOCK: SPLIT SECTION ---------- */

.split-grid__content > * + * { margin-top: 1.1rem; }
.split-grid__plain img { width: 100%; height: auto; }
.media-band__content > * + * { margin-top: 1.1rem; }

/* ---------- BLOCK: ACCORDION ---------- */

.accordion__item { border-bottom: 1px solid var(--hairline); }
.accordion__item:first-child { border-top: 1px solid var(--hairline); }

.accordion__question {
	list-style: none;
	cursor: pointer;
	padding: 1.1rem 2.4rem 1.1rem 0;
	position: relative;
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-md);
	color: var(--slate);
}

.accordion__question::-webkit-details-marker { display: none; }

.accordion__question::after {
	content: "";
	position: absolute;
	right: 0.4rem;
	top: 50%;
	width: 9px;
	height: 9px;
	border-right: 1px solid currentColor;
	border-bottom: 1px solid currentColor;
	transform: translateY(-70%) rotate(45deg);
	transition: transform 0.25s ease;
}

.accordion__item[open] .accordion__question::after { transform: translateY(-30%) rotate(-135deg); }
.accordion__question:hover { color: var(--rose-ink); }
.accordion__answer { padding: 0 2.4rem 1.4rem 0; font-size: var(--fs-sm); color: var(--slate-ink); }
.accordion__answer > * + * { margin-top: 0.8rem; }

/* ---------- BLOCK: TESTIMONIALS ---------- */

.testimonials { display: grid; gap: clamp(1.4rem, 3vw, 2.2rem); }
.testimonials--1 { grid-template-columns: minmax(0, 60ch); justify-content: center; }
.testimonials--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.testimonials--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.testimonial {
	margin: 0;
	background: var(--chalk);
	border: 1px solid var(--hairline);
	padding: clamp(1.4rem, 3vw, 2rem);
}

.testimonial__quote {
	margin: 0;
	font-family: var(--serif);
	font-size: var(--fs-lg);
	line-height: 1.6;
	color: var(--slate);
	quotes: "\201C" "\201D";
}

.testimonial__quote::before { content: open-quote; }
.testimonial__quote::after { content: close-quote; }

.testimonial__author {
	margin-top: 1.1rem;
	font-size: var(--fs-2xs);
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--khaki-strong);
}

.testimonial__source { display: block; letter-spacing: 0.08em; text-transform: none; color: var(--khaki-ink); margin-top: 0.2rem; }

/* ---------- BLOCK: STATS BAR ---------- */

.stats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
	gap: 1px;
	margin: 0;
	background: var(--hairline);
	border: 1px solid var(--hairline);
}

.stats__item { background: var(--limewash); padding: clamp(1.4rem, 3vw, 2rem); text-align: center; }
.stats__value { font-family: var(--serif); font-size: clamp(1.8rem, 3.4vw, 2.6rem); line-height: 1; color: var(--slate); }

.stats__label {
	margin: 0.6rem 0 0;
	font-size: var(--fs-2xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--khaki-strong);
}

.scheme-chalk .stats__item { background: var(--chalk); }
.scheme-slate .stats__item { background: var(--slate); }
.scheme-slate .stats__value { color: var(--limewash); }
.scheme-slate .stats__label { color: var(--stone); }

/* ---------- BLOCK: FULL-WIDTH IMAGE ---------- */

.block-image { margin: 0; }
.block-image img { width: 100%; height: auto; display: block; }
.block-image--short img { height: clamp(220px, 34vh, 380px); object-fit: cover; }
.block-image--tall img { height: clamp(360px, 62vh, 680px); object-fit: cover; }

/* ---------- BLOCK: FORM & QUOTE ---------- */

.block-form__plain { max-width: 46rem; }
.block-quote__form { margin-top: 1.6rem; }
.block-quote .step { margin-bottom: 1.6rem; }

/* ---------- BLOCK: POST CARDS ---------- */

.post-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.post-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 900px) {
	.block-columns--1-1,
	.block-columns--5-6,
	.block-columns--6-5,
	.block-columns--1-1-1 { grid-template-columns: 1fr; }

	.testimonials--2,
	.testimonials--3 { grid-template-columns: 1fr; }

	.post-grid--2,
	.post-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
	.post-grid--2,
	.post-grid--4 { grid-template-columns: 1fr; }
}

/* ---------- SMALL COMPONENT PIECES ----------
   Classes the templates use that have no home in the sections above. */

/* The quote list and mini-basket share the line component; this is just the
   container the JS replaces wholesale. */
.cart__items:empty { display: none; }

.collection__main { min-width: 0; }

/* With infinite scroll the button is the keyboard and no-JS path only; the
   count stays visible so the visitor knows how much is left. */
.collection__more.is-auto [data-more] {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.collection__more.is-auto [data-more]:focus-visible {
	position: static;
	width: auto;
	height: auto;
	overflow: visible;
	clip: auto;
	clip-path: none;
}

/* The label and count sit on a baseline inside the rail button. */
.filter-link__label { flex: 1 1 auto; }

.route-opt__label { flex: 1 1 auto; }

.search-form__submit { flex: 0 0 auto; }

.site-footer__column { min-width: 0; }

.site-footer__copyright { margin: 0; }

.stepper__label { white-space: nowrap; }

/* ---------- MOBILE OVERFLOW GUARDS ----------
   A grid track only shrinks below its content when it is told it may. Without
   `min-width: 0` a long word, a wide table or a textarea with a `cols`
   attribute forces its track wider than the viewport, and the whole page
   scrolls sideways. These rules are the backstop for every grid the theme
   creates, plus the ones WooCommerce and Gravity Forms create for us. */

.piece__grid > *,
.block-columns > *,
.block-column,
.split-grid > *,
.contact-grid > *,
.media-band__grid > *,
.collection > * {
	min-width: 0;
}

/* The block editor wraps InnerBlocks in its own container, which inherits no
   sizing of its own. */
.acf-innerblocks-container {
	min-width: 0;
	max-width: 100%;
}

/* A textarea carries an intrinsic width from its `cols` attribute, which
   Gravity Forms sets. */
textarea,
.gform_wrapper.gravity-theme textarea,
.gform_wrapper textarea {
	max-width: 100%;
	box-sizing: border-box;
}

@media (max-width: 900px) {
	/* WooCommerce styles the summary column at a higher specificity than a
	   bare class, so the single-column collapse has to match it (lesson WC-1)
	   rather than rely on .piece__grid alone. */
	.single-product .product:not(.product-card) .piece__grid,
	.single-product .piece__grid,
	.piece__grid {
		grid-template-columns: minmax(0, 1fr);
		/* The desktop rule names a two-column area template; leaving it in
		   place kept a second area column and starved the figure to 0px. */
		grid-template-areas:
			"figure"
			"summary";
	}

	.single-product .product:not(.product-card) .piece__grid > .piece__figure,
	.piece__grid > .piece__figure {
		width: 100%;
		max-width: 100%;
		min-width: 0;
		float: none;
	}

	.single-product .product:not(.product-card) .piece__grid > .summary,
	.single-product .product:not(.product-card) .piece__grid > .entry-summary,
	.piece__grid > .summary {
		width: 100%;
		max-width: 100%;
		min-width: 0;
		float: none;
		margin: 0;
	}

	.block-columns,
	.block-columns--1-1,
	.block-columns--5-6,
	.block-columns--6-5,
	.block-columns--1-1-1 {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* A select is sized by its longest option unless told otherwise, and the piece
   dropdown on the contact form lists every piece with its category prefix. */
select,
.gform_wrapper.gravity-theme select,
.gform_wrapper select,
.gfield_select,
.woocommerce select {
	max-width: 100%;
	min-width: 0;
	box-sizing: border-box;
}

/* ---------- PROTOTYPE PARITY ----------
   Rules the hand-port dropped. Kept together so the next person can see what
   the static build declared and check nothing else went missing. */

/* The ghost button over the film hero: white on the photograph, inverting on
   hover. Without this it renders slate-on-photograph and disappears. */
.site-header--over .site-header__actions .btn--ghost {
	border-color: var(--white);
	color: var(--white);
	background: transparent;
}

.site-header--over .site-header__actions .btn--ghost:hover {
	background: var(--white);
	border-color: var(--white);
	color: var(--slate);
}


/* The lede beneath a page title, used on the collection and trade headers. */
.page-lede {
	max-width: 46ch;
	margin: 0.9rem 0 0;
	color: var(--slate);
}

/* Quote and trade forms sit tighter than the contact form. */
.quote-form .form-field,
.trade-form .form-field,
.block-quote .form-field { margin-bottom: 1rem; }

/* The quote request recap panel on the final step. */
.step__summary {
	margin-top: 1.8rem;
	padding: 1.2rem 1.4rem;
	background: var(--chalk);
	border: 1px solid var(--hairline);
}

.step__summary-title {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate-ink);
	margin: 0 0 0.7rem;
}

.step__summary-list {
	margin: 0;
	padding-left: 1.1rem;
	font-size: var(--fs-sm);
	color: var(--slate);
}

.step__summary-list li { padding: 0.15rem 0; }
.step__summary-empty { margin: 0; font-size: var(--fs-sm); color: var(--slate-ink); }

.stepper__item:hover { color: var(--slate); }

/* Step 1 is reachable again from the stepper, so it reads as a control. */
.block-quote .stepper__item[data-step-tab="1"] { cursor: pointer; }
.block-quote .stepper__item[data-step-tab="1"]:hover .stepper__num { border-color: var(--slate); }

/* Trade page headings and the benefit list the prototype used beside the
   application form. */
.trade__title,
.trade-form__title,
.trade-login__title {
	font-family: var(--serif);
	font-weight: 400;
	font-size: var(--fs-2xl);
	margin: 0 0 1.2rem;
}

/* The trade page's own heading sits above a stacked benefit list. */
.block-column > .acf-innerblocks-container > h2.wp-block-heading:first-child,
.trade__title { margin: 0 0 2rem; }

.trade__small { font-size: var(--fs-xs); color: var(--slate); }

/* An about-page split that keeps the prototype's ratio and arch mount. */
.about-grid {
	display: grid;
	grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
	gap: clamp(2rem, 5vw, 4.5rem);
	align-items: center;
}

.about-grid--flip { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
.about-grid .arch { aspect-ratio: 1 / 1; max-width: 400px; }
.about-intro { padding-block: clamp(3rem, 7vw, 5rem) clamp(2rem, 5vw, 3.5rem); }

@media (min-width: 700px) {
	/* Two up, with the first card spanning both columns. */
	.benefit:first-child { grid-column: 1 / -1; }
	.process { grid-template-columns: 1fr 1fr; }

	/* Two columns: the right-hand step of each pair takes the vertical rule,
	   and only the first row has no rule above it. */
	.section--charcoal .process__step:nth-child(2n),
	.scheme-slate .process__step:nth-child(2n) { border-left: 1px solid var(--hairline-dark); }

	.section--charcoal .process__step:nth-child(-n + 2),
	.scheme-slate .process__step:nth-child(-n + 2) { border-top: 0; }
}

@media (min-width: 700px) and (max-width: 1024px) {
}

@media (min-width: 1100px) {
	.process { grid-template-columns: repeat(4, 1fr); }

	/* One row of four: every step but the first takes the vertical rule, and
	   none takes a horizontal one. */
	.section--charcoal .process__step,
	.scheme-slate .process__step { border-top: 0; }

	.section--charcoal .process__step:not(:first-child),
	.scheme-slate .process__step:not(:first-child) { border-left: 1px solid var(--hairline-dark); }
}

@media (max-width: 980px) {
	/* The open mobile menu carries the logo at its head. */
	.site-nav::before {
		content: "";
		position: absolute;
		top: 1.15rem;
		left: 50%;
		transform: translateX(-50%);
		width: 190px;
		height: 40px;
		background: url("../images/logo-light.svg") center / contain no-repeat;
	}

	.site-nav__link:hover { color: var(--rose-soft); }
	.site-nav__item--current > .site-nav__link,
	.site-nav__link[aria-current="page"] { border-bottom-color: var(--limewash); }
}

@media (max-width: 900px) {
	.about-grid,
	.about-grid--flip { grid-template-columns: 1fr; }
	.about-grid .arch { max-width: 360px; }
}

@media (max-width: 760px) {
	.line__qty { grid-column: 2; }
}

@media (max-width: 640px) {
	.brand img,
	.custom-logo-link .custom-logo { height: 18px; }
}

/* The basket totals sit in the prototype's chalk panel rather than WooCommerce's
   bare table: bordered, padded, and sticky beside the line items. */
.woocommerce-cart .cart-collaterals .cart_totals {
	background: var(--white);
	border: 1px solid var(--hairline);
	padding: clamp(1.4rem, 3vw, 2rem);
	position: sticky;
	top: 7.5rem;
}

.woocommerce-cart .cart_totals table.shop_table,
.woocommerce-cart .cart_totals table.shop_table td,
.woocommerce-cart .cart_totals table.shop_table th {
	background: transparent;
	border: 0;
	padding: 0.4rem 0;
	font-size: var(--fs-xs);
}

/* The totals column is the prototype's bordered chalk summary panel. */
/* The totals rules set the totals table to block; the line-item table is a
   real table and must fill its container. */
/* Above the stacking breakpoint the line-item table is a real table; the
   totals rules set `display: block` on .shop_table generally and would
   otherwise flatten this one too. Below 760px the responsive stack takes
   over, so these must not apply there. */
/* With the update button hidden, its row is an empty band under the items. */
.woocommerce-cart form.woocommerce-cart-form td.actions:not(:has(button[name="update_cart"]:enabled)) {
	padding: 0;
	border: 0;
	height: 0;
	overflow: hidden;
}

@media (min-width: 761px) {
	.woocommerce-cart form.woocommerce-cart-form table.shop_table {
		display: table;
		width: 100%;
		table-layout: auto;
	}

	.woocommerce-cart form.woocommerce-cart-form table.shop_table thead,
	.woocommerce-cart form.woocommerce-cart-form table.shop_table tbody { display: table-row-group; width: auto; }
	.woocommerce-cart form.woocommerce-cart-form table.shop_table tr { display: table-row; width: auto; }
}
/* `width: 100%` on the name cell starved the others — the thumbnail computed
   0px wide. The name takes the slack instead, and the thumbnail column is
   sized to the image it holds. */
.woocommerce-cart form.woocommerce-cart-form table.shop_table td.product-name { width: auto; }
.woocommerce-cart form.woocommerce-cart-form table.shop_table th.product-thumbnail,
.woocommerce-cart form.woocommerce-cart-form table.shop_table td.product-thumbnail { width: 88px; }
.woocommerce-cart form.woocommerce-cart-form table.shop_table td.product-thumbnail img { width: 72px; height: 72px; display: block; }
.woocommerce-cart form.woocommerce-cart-form table.shop_table td.product-thumbnail a { display: block; width: 72px; }

/* 11. Proceed spans the panel. */
.woocommerce-cart .cart_totals .wc-proceed-to-checkout { padding: 0; margin-top: 1.2rem; display: block; width: 100%; }
.woocommerce-cart .cart_totals .wc-proceed-to-checkout a.checkout-button { display: block; width: 100%; box-sizing: border-box; text-align: center; margin: 0; }

/* WooCommerce lists shipping options; strip the bullets. */
.woocommerce-cart .cart_totals ul#shipping_method { list-style: none; margin: 0; padding: 0; }
.woocommerce-cart .cart_totals ul#shipping_method li { margin: 0; }
.woocommerce-cart .cart_totals .woocommerce-shipping-destination { font-size: var(--fs-2xs); color: var(--slate); }

/* The VAT note is an inline <small> after the amount; on its own line it
   stops colliding with the figure. Applies to basket and checkout alike. */
.woocommerce .order-total .includes_tax,
.woocommerce-checkout #order_review .includes_tax {
	display: block;
	margin-top: 0.25rem;
	font-family: var(--sans);
	font-size: var(--fs-3xs);
	letter-spacing: 0.04em;
	color: var(--khaki-ink);
}

.woocommerce .order-total .includes_tax .amount,
.woocommerce-checkout #order_review .includes_tax .amount,
.woocommerce-checkout #order_review .includes_tax .woocommerce-Price-amount { font-family: var(--sans); font-size: inherit; font-weight: 300; }

/* Proceed is a button, not a link. */
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button,
.woocommerce-cart .wc-proceed-to-checkout a.checkout-button:hover { text-decoration: none; }

/* WooCommerce's totals table puts the label in a <th> and the value in a <td>;
   with a narrow panel the label column squeezed and the rows misaligned. Lay
   each row out as a label/value pair like the prototype's .cart__totals. */
.woocommerce-cart .cart_totals table.shop_table,
.woocommerce-cart .cart_totals table.shop_table tbody { display: block; width: 100%; }

.woocommerce-cart .cart_totals table.shop_table tr {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 1rem;
	width: 100%;
}

.woocommerce-cart .cart_totals table.shop_table th {
	flex: 0 0 auto;
	text-align: left;
	white-space: nowrap;
}

.woocommerce-cart .cart_totals table.shop_table td {
	flex: 1 1 auto;
	text-align: right;
}

.woocommerce-cart .cart_totals .woocommerce-shipping-methods,
.woocommerce-cart .cart_totals .woocommerce-shipping-destination,
.woocommerce-cart .cart_totals .woocommerce-shipping-calculator { text-align: right; }

/* "Update cart" is a real action, not a disabled slab. */
/* Hidden until a quantity actually changes — WooCommerce only enables it
   then, and a permanently greyed control is just noise. */
.woocommerce-cart button[name="update_cart"]:disabled,
.woocommerce-cart input[name="update_cart"]:disabled { display: none; }

.woocommerce-cart button[name="update_cart"],
.woocommerce-cart input[name="update_cart"] {
	background: transparent;
	border: 1px solid var(--slate);
	color: var(--slate);
	padding: 0.95rem 1.5rem;
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background-color 0.3s ease, color 0.3s ease;
}

.woocommerce-cart button[name="update_cart"]:hover:not(:disabled),
.woocommerce-cart input[name="update_cart"]:hover:not(:disabled) {
	background: var(--slate);
	color: var(--limewash);
}

/* Disabled until a quantity changes — legible, not washed out. The shared
   `.woocommerce button.button:disabled` rule paints every disabled button
   limewash; this selector matches its shape so source order settles it. */
.woocommerce-cart button.button[name="update_cart"]:disabled,
.woocommerce-cart button.button[name="update_cart"]:disabled[disabled],
.woocommerce-cart input.button[name="update_cart"]:disabled {
	opacity: 1;
	background: transparent;
	border-color: var(--slate);
	color: var(--slate);
	cursor: default;
}

.woocommerce-cart .cart_totals .order-total th,
.woocommerce-cart .cart_totals .order-total td {
	border-top: 1px solid var(--hairline);
	padding-top: 0.9rem;
}


/* Line items and totals side by side, as the prototype's .cart grid did. */
@media (min-width: 901px) {
	/* The shortcode output sits inside .entry-content, not directly under
	   .site-main, so the old child selector matched nothing and the basket
	   stacked full width at every size. */
	.woocommerce-cart .entry-content > .woocommerce > form.woocommerce-cart-form {
		float: none;
		width: auto;
	}

	.woocommerce-cart .entry-content > .woocommerce {
		display: grid;
		grid-template-columns: 1fr 21rem;
		gap: clamp(2rem, 5vw, 4rem);
		align-items: start;
	}

	.woocommerce-cart .entry-content > .woocommerce > .woocommerce-notices-wrapper { grid-column: 1 / -1; }

	/* An empty basket has no totals column to fill; drop to one column so the
	   message and its button sit together. */
	.woocommerce-cart .entry-content > .woocommerce:has(.cart-empty),
	.woocommerce-cart .entry-content > .woocommerce:has(.wc-empty-cart-message) { grid-template-columns: 1fr; }

	.woocommerce-cart .entry-content > .woocommerce > .return-to-shop { grid-column: 1 / -1; margin: 0; }
	.woocommerce-cart .cart-collaterals { width: 100%; float: none; }
	.woocommerce-cart .cross-sells { grid-column: 1 / -1; }
}

@media (max-width: 900px) {
	.woocommerce-cart .cart-collaterals .cart_totals { position: static; }
}

/* ---------- BASKET: CHANGE ADDRESS DIALOG ----------
   WooCommerce's shipping calculator, left where it is printed (inside its own
   form, so its AJAX submit keeps working) and positioned as a dialog by
   address-modal.js. It cannot live in the totals panel: the value column is
   about 165px wide and the form's letter-spaced labels are wider than that. */

/* The totals "table" is a block of flex rows and never needs to scroll. The
   general .entry-content table rule gave it overflow-x: auto, which is what
   sliced the right edge off everything in the cell once anything was 1px too
   wide. */
.woocommerce-cart .cart_totals table.shop_table { overflow: visible; }

html.address-modal-open { overflow: hidden; }

/* The panel is position: sticky, so it is its own stacking context, and the
   dialog and backdrop live inside it. Lifting the panel lifts both above the
   header; below 900px the panel is static, so it needs a position to take a
   z-index at all. */
html.address-modal-open .woocommerce-cart .cart-collaterals .cart_totals,
html.address-modal-open .cart_totals { z-index: 200; }

@media (max-width: 900px) {
	html.address-modal-open .woocommerce-cart .cart-collaterals .cart_totals { position: relative; }
}

.address-modal__backdrop {
	display: none;
	position: fixed;
	inset: 0;
	z-index: 1;
	background: rgba(46, 51, 55, 0.55);
}

html.address-modal-open .address-modal__backdrop { display: block; animation: address-modal-fade 0.25s ease both; }

.woocommerce-cart .cart_totals .shipping-calculator-form.address-modal {
	position: fixed;
	z-index: 2;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: min(30rem, calc(100vw - 2rem));
	max-height: calc(100vh - 2rem);
	max-height: calc(100dvh - 2rem);
	overflow-y: auto;
	margin: 0;
	padding: 0 clamp(1.4rem, 4vw, 2rem) clamp(1.4rem, 4vw, 2rem);
	background: var(--limewash);
	border: 1px solid var(--hairline);
	text-align: left;
	animation: address-modal-rise 0.3s var(--ease, ease) both;
}

.address-modal__head {
	position: sticky;
	top: 0;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin: 0 calc(-1 * clamp(1.4rem, 4vw, 2rem)) 1.6rem;
	padding: 1.2rem clamp(1.4rem, 4vw, 2rem);
	background: var(--limewash);
	border-bottom: 1px solid var(--hairline);
}

/* The mini basket's heading treatment: the two are the site's only dialogs.
   Written at the panel's own weight — `.cart_totals h2` styles every h2 in the
   panel as the serif "Basket totals" heading and outranked a single class. */
.woocommerce-cart .cart-collaterals .cart_totals .address-modal__title {
	margin: 0;
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
}

.address-modal__close {
	position: relative;
	flex: 0 0 auto;
	width: 2rem;
	height: 2rem;
	padding: 0;
	border: 0;
	background: none;
	color: var(--slate);
	cursor: pointer;
}

/* The cross is drawn from two bars, like the remove controls — a glyph never
   sits centred in its box. */
.address-modal__close::before,
.address-modal__close::after {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 1.15rem;
	height: 1px;
	background: currentColor;
}

.address-modal__close::before { transform: translate(-50%, -50%) rotate(45deg); }
.address-modal__close::after { transform: translate(-50%, -50%) rotate(-45deg); }
.address-modal__close:hover { color: var(--rose-ink); }

.woocommerce-cart .cart_totals .address-modal .form-row { text-align: left; }
.woocommerce-cart .cart_totals .address-modal .form-row label { text-align: left; }

.woocommerce-cart .cart_totals .address-modal p:last-of-type { margin-bottom: 0; }

.woocommerce-cart .cart_totals .address-modal button[name="calc_shipping"] {
	display: block;
	width: 100%;
	margin: 0.4rem 0 0;
}

/* WooCommerce dims the panel behind the dialog while it posts; the dialog has
   to say so itself. */
.address-modal.is-busy { pointer-events: none; }
.address-modal.is-busy > :not(.address-modal__head) { opacity: 0.45; transition: opacity 0.2s ease; }

@keyframes address-modal-fade { from { opacity: 0; } }
@keyframes address-modal-rise { from { opacity: 0; transform: translate(-50%, calc(-50% + 0.75rem)); } }

@media (prefers-reduced-motion: reduce) {
	html.address-modal-open .address-modal__backdrop,
	.woocommerce-cart .cart_totals .shipping-calculator-form.address-modal { animation: none; }
}

/* ---------- LEDE ----------
   The prototype marks its intro paragraphs with .lede: a 62ch measure at body
   size. Block content emits a bare paragraph, so the first paragraph of a
   centred or narrow section takes the same treatment automatically, and the
   editor can apply .lede by hand anywhere else. */

.block-container--centred .acf-innerblocks-container > p,
.block-container--centred .acf-innerblocks-container > .wp-block-paragraph,
.block-container--centred > .wrap > p {
	font-size: var(--fs-lg);
	color: var(--slate);
}

/* The prototype releases the measure only on the centred home intro, where the
   column is already narrow (.intro .lede). Copy in a column keeps its measure. */
.block-container--centred > .wrap--narrow .acf-innerblocks-container > p,
.block-container--centred > .wrap--narrow .lede {
	max-width: none;
	margin-inline: auto;
}

/* Copy inside a column keeps the prototype's 62ch measure. */
.block-column p,
.block-column .lede {
	max-width: var(--measure);
}

/* An explicit .lede keeps its measure everywhere else. */
.lede { max-width: var(--measure); color: var(--slate); font-size: var(--fs-lg); }

/* ---------- GRAVITY FORMS — MARKUP-ACCURATE SELECTORS ----------
   The rules above are written against .gform_wrapper.gravity-theme, which only
   matches when Gravity Forms' own framework CSS is loaded. These duplicate the
   essentials without that dependency, so a form always looks like the
   prototype's .form-field even if the framework class is absent. */

.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label {
	display: block;
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
	margin-bottom: 0.45rem;
}

.gform_wrapper .ginput_container input[type="text"],
.gform_wrapper .ginput_container input[type="email"],
.gform_wrapper .ginput_container input[type="tel"],
.gform_wrapper .ginput_container input[type="url"],
.gform_wrapper .ginput_container input[type="number"],
.gform_wrapper .ginput_container input[type="password"],
.gform_wrapper .ginput_container textarea,
.gform_wrapper .ginput_container select,
.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="tel"],
.gform_wrapper textarea,
.gform_wrapper select {
	width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-md);
	line-height: 1.6;
	color: var(--slate);
	background: var(--white);
	border: 1px solid var(--hairline);
	border-radius: 0;
	padding: 0.85rem 1rem;
	box-sizing: border-box;
	transition: border-color 0.25s ease;
	-webkit-appearance: none;
	appearance: none;
}

/* A select loses its chevron once `appearance` is stripped, so the theme draws
   one. Two framework rules fight it: a reset that sets `background-image:
   unset` through a long `:where()` chain, and a hover rule that swaps the mark
   for `--gf-ctrl-select-icon-hover`. Neither can be out-specified from a class
   selector, so the whole background is set as one shorthand in every state —
   a shorthand also re-establishes the colour the reset would otherwise drop. */
.gform_wrapper select,
.gform_wrapper select:hover,
.gform_wrapper select:focus,
.gform_wrapper select:focus-visible,
[id^="gform_wrapper"] select,
[id^="gform_wrapper"] select:hover,
[id^="gform_wrapper"] select:focus {
	color: var(--slate);
	background: var(--white) var(--ps-select-chevron) no-repeat right 1rem center / 10px 6px !important;
	padding-right: 2.6rem;
	text-indent: 0;
}

.gform_wrapper select option { color: var(--slate); background: var(--white); }

.gform_wrapper textarea { min-height: 9rem; resize: vertical; }

.gform_wrapper input:focus-visible,
.gform_wrapper textarea:focus-visible,
.gform_wrapper select:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 1px;
	border-color: var(--rose-ink);
}

.gform_wrapper .gfield_required { color: var(--rose-ink); text-decoration: none; }
.gform_wrapper .gfield_description { font-size: var(--fs-xs); color: var(--slate); padding-top: 0.4rem; }

.gform_wrapper .gform_footer,
.gform_wrapper .gform_page_footer {
	display: flex;
	flex-wrap: wrap;
	gap: 0.8rem;
	margin: 1.6rem 0 0;
	padding: 0;
}

.gform_wrapper input[type="submit"],
.gform_wrapper .gform_button,
.gform_wrapper .gform_next_button,
.gform_wrapper .gform_previous_button {
	display: inline-block;
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.4;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	border-radius: 0;
	background: var(--slate);
	color: var(--limewash);
	cursor: pointer;
	width: auto;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.gform_wrapper input[type="submit"]:hover,
.gform_wrapper .gform_button:hover,
.gform_wrapper .gform_next_button:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
}



/* ---------- WOOCOMMERCE VARIATION FIELDS ----------
   WooCommerce renders the Finish and Plinth rows as a real table:
   <table class="variations"><th class="label"><label>…</label></th>
   <td class="value"><select></select></td></table>
   and styles th.label at (0,3,1). A single-class selector loses to that, so
   these match WooCommerce's own structure rather than reaching for !important
   (lesson WC-1). */

/* The quantity caption, matching the Finish label above it. The template at
   woocommerce/global/quantity-input.php supplies the wording; WooCommerce's own
   label is screen-reader-only and reads "<product name> quantity". */
.single-product .product:not(.product-card) form.cart .quantity .ps-qty-label {
	display: block;
	margin: 0 0 0.5rem;
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
}

/* "Clear" is WooCommerce's variation reset. It is a genuine affordance, so it
   stays, but set in the field-caption style it read as another label sitting
   between Finish and Qty. It is now a quiet underlined link, right-aligned
   under the selects, and hidden until a variation is actually chosen (the
   plugin toggles its visibility). */
/* The reset sits on the label's line, hard right, so a field that has one is
   no taller than a field that does not. */
.single-product .product:not(.product-card) form.cart .variations tr,
.single-product .product:not(.product-card) form.cart .variations .label { position: relative; }

.single-product .product:not(.product-card) form.cart .reset_variations {
	position: absolute;
	top: 0;
	right: 0;
	display: block;
	width: fit-content;
	margin: 0;
	font-family: var(--sans);
	font-size: var(--fs-3xs);
	font-weight: 400;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--slate);
	border-bottom: 1px solid var(--hairline);
	padding-bottom: 0.1rem;
}

/* The inline prompt shown when a finish has not been chosen — on both routes.
   It replaces WooCommerce's window.alert() on the buy route, and had no rule of
   its own, so it rendered as loose body copy. */
.single-product .product:not(.product-card) form.cart .variation-hint {
	margin: 0.45rem 0 0;
	font-size: var(--fs-xs);
	color: var(--rose-ink);
}

/* What was chosen for a line on the quote request. */
.line__meta--choice { color: var(--slate); }

.single-product .product:not(.product-card) form.cart .reset_variations:hover {
	color: var(--slate);
}

/* ---------- Plugin defaults, tidied ---------- */

/* Checkout's "Ship to a different address?" was a native checkbox next to a
   tracked label; it takes the theme's square control. */
.woocommerce-checkout #ship-to-different-address input[type="checkbox"],
.woocommerce-form-login__rememberme input[type="checkbox"] {
	appearance: none;
	-webkit-appearance: none;
	width: 1rem;
	height: 1rem;
	margin: 0 0.6rem 0 0;
	border: 1px solid var(--slate);
	background: var(--white);
	vertical-align: -0.15rem;
	cursor: pointer;
	position: relative;
}

.woocommerce-checkout #ship-to-different-address input[type="checkbox"]:checked,
.woocommerce-form-login__rememberme input[type="checkbox"]:checked { background: var(--slate); }

.woocommerce-checkout #ship-to-different-address input[type="checkbox"]:checked::after,
.woocommerce-form-login__rememberme input[type="checkbox"]:checked::after {
	content: "";
	position: absolute;
	left: 0.3rem;
	top: 0.08rem;
	width: 0.28rem;
	height: 0.55rem;
	border-right: 2px solid var(--limewash);
	border-bottom: 2px solid var(--limewash);
	transform: rotate(45deg);
}

/* No browser resize grip on any textarea. */
textarea,
.gform_wrapper textarea,
.woocommerce textarea { resize: none; }

/* The chosen option must not run into the chevron. */
.gform_wrapper select { padding-right: 2.8rem; text-overflow: ellipsis; }

/* Links inside body copy read as links. */
.block-quote .step .cart__empty a,
.piece__enquire-line a { text-decoration: underline; text-underline-offset: 0.2em; }

/* One box, not three: the payment notice sits directly on the panel ground. */
.woocommerce-checkout #payment { border: 0; background: transparent; padding: 0; }
.woocommerce-checkout #payment .woocommerce-notice,
.woocommerce-checkout #payment .woocommerce-info { background: var(--white); border: 1px solid var(--hairline); padding: 1.1rem 1.2rem; }

.single-product .product:not(.product-card) form.cart table.variations th.label,
.single-product .product:not(.product-card) form.cart table.variations th.label label,
.single-product .product:not(.product-card) form.cart .variations th.label label {
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--slate);
	line-height: 1.4;
	margin: 0 0 0.45rem;
	padding: 0;
	display: block;
	text-align: left;
}

.single-product .product:not(.product-card) form.cart table.variations td.value select,
.single-product .product:not(.product-card) form.cart table.variations select,
.single-product .product:not(.product-card) form.cart .variations td.value select {
	width: 100%;
	max-width: 100%;
	font-family: var(--sans);
	font-weight: 300;
	font-size: var(--fs-sm);
	line-height: 1.5;
	color: var(--slate);
	background-color: var(--chalk);
	border: 1px solid var(--hairline);
	border-radius: 0;
	padding: 0.7rem 2.4rem 0.7rem 0.8rem;
	margin: 0 0 1rem;
	box-sizing: border-box;
	-webkit-appearance: none;
	appearance: none;
	/* The same chevron as the form selects, centred rather than pinned to a
	   fixed offset. */
	background-image: var(--ps-select-chevron);
	background-position: right 0.9rem center;
	background-size: 10px 6px;
	background-repeat: no-repeat;
}

.single-product .product:not(.product-card) form.cart table.variations select option {
	color: var(--slate);
	background: var(--white);
}

.single-product .product:not(.product-card) form.cart table.variations select:focus-visible {
	outline: 2px solid var(--rose-ink);
	outline-offset: 1px;
}

/* The table itself is a layout artefact — stack it so each row reads as a
   labelled field, the way the prototype's .buy__field does. */
.single-product .product:not(.product-card) form.cart table.variations,
.single-product .product:not(.product-card) form.cart table.variations tbody,
.single-product .product:not(.product-card) form.cart table.variations tr,
.single-product .product:not(.product-card) form.cart table.variations th,
.single-product .product:not(.product-card) form.cart table.variations td {
	display: block;
	width: 100%;
	border: 0;
	padding: 0;
	margin: 0;
	background: none;
}

.single-product .product:not(.product-card) form.cart table.variations tr + tr { margin-top: 0; }

/* ---------- GRAVITY FORMS — ORBITAL THEME TOKENS ----------
   Gravity Forms 2.10 ships an "orbital" theme that writes its own custom
   properties into an inline <style> scoped to #gform_wrapper_N. That inline
   block outranks this stylesheet, so the label colour and the submit button
   came through as Gravity's navy and blue. Overriding the properties works
   with their cascade instead of fighting it; the rules that follow are the
   backstop for anything the tokens do not reach. */

.gform_wrapper,
.gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--orbital {
	/* Brand palette */
	--gf-color-primary: var(--slate);
	--gf-color-primary-rgb: 88, 95, 103;
	--gf-color-primary-contrast: var(--limewash);
	--gf-color-primary-darker: var(--rose-ink);
	--gf-color-primary-lighter: var(--slate-ink);
	--gf-color-secondary: var(--white);
	--gf-color-secondary-contrast: var(--slate);
	--gf-color-in-ctrl: var(--white);
	--gf-color-in-ctrl-contrast: var(--slate);
	--gf-color-out-ctrl-light: var(--hairline);

	/* Labels */
	--gf-ctrl-label-color-primary: var(--slate);
	--gf-ctrl-label-color-secondary: var(--slate);
	--gf-ctrl-label-font-size: var(--fs-2xs);
	--gf-ctrl-label-font-weight: 400;
	--gf-ctrl-desc-color: var(--slate);

	/* Fields */
	--gf-ctrl-border-color: var(--hairline);
	--gf-ctrl-border-color-focus: var(--rose-ink);
	--gf-ctrl-radius: 0;
	--gf-ctrl-bg-color: var(--white);
	--gf-ctrl-color: var(--slate);
	--gf-ctrl-font-size: var(--fs-md);
	--gf-ctrl-padding-x: 1rem;
	--gf-ctrl-padding-y: 0.85rem;
	--gf-ctrl-size: auto;
	--gf-field-gap-y: 1.3rem;

	/* Buttons */
	--gf-ctrl-btn-bg-color-primary: var(--slate);
	--gf-ctrl-btn-border-color-primary: var(--slate);
	--gf-ctrl-btn-color-primary: var(--limewash);
	--gf-ctrl-btn-bg-color-hover-primary: var(--rose-ink);
	--gf-ctrl-btn-border-color-hover-primary: var(--rose-ink);
	--gf-ctrl-btn-color-hover-primary: var(--limewash);
	--gf-ctrl-btn-radius: 0;
	--gf-ctrl-btn-font-size: var(--fs-2xs);
	--gf-ctrl-btn-font-weight: 500;
	--gf-ctrl-btn-padding-x: 1.5rem;
	--gf-ctrl-btn-padding-y: 0.95rem;
	--gf-ctrl-btn-size: auto;
}

/* The label and button also carry framework rules of their own, so match the
   structure rather than relying on the tokens alone. */
.gform_wrapper.gform-theme .gform_fields .gfield .gfield_label,
.gform_wrapper .gfield > .gfield_label,
.gform_wrapper .gfield_label {
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--slate);
	margin-bottom: 0.45rem;
}

.gform_wrapper.gform-theme .gform_footer input[type="submit"],
.gform_wrapper.gform-theme .gform_page_footer input[type="button"],
.gform_wrapper.gform-theme .gform_page_footer input[type="submit"],
.gform_wrapper .gform_footer input[type="submit"],
.gform_wrapper .gform-theme-button {
	font-family: var(--sans);
	font-weight: 500;
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.4;
	height: auto;
	min-height: 0;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	border-radius: 0;
	background: var(--slate);
	color: var(--limewash);
}

.gform_wrapper.gform-theme .gform_footer input[type="submit"]:hover,
.gform_wrapper .gform_footer input[type="submit"]:hover,
.gform_wrapper .gform-theme-button:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--limewash);
}



/* The orbital framework sets its label weight and button type through rules of
   its own, which the custom properties above do not reach. Match the prototype:
   a light 300 label, and a button using the theme's own button treatment. */
.gform_wrapper.gform-theme .gform_fields .gfield > .gfield_label,
.gform_wrapper.gform-theme .gfield_label,
.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label {
	font-weight: 300;
}

.gform_wrapper.gform-theme .gform_footer input[type="submit"],
.gform_wrapper.gform-theme .gform_page_footer input[type="submit"],
.gform_wrapper.gform-theme .gform_page_footer input[type="button"],
.gform_wrapper.gform-theme .gform-theme-button,
.gform_wrapper.gform-theme button.gform-theme-button {
	font-size: var(--fs-2xs);
	letter-spacing: 0.18em;
	text-transform: uppercase;
	padding-inline: 1.5rem;
}

/* The orbital framework styles its submit button through
   `.gform-theme--framework .gform_footer button`-shaped rules that carry more
   weight than a single wrapper class. Match its own structure so the button
   takes the theme's treatment rather than Gravity's. */
.gform_wrapper.gform-theme--framework .gform_footer input[type="submit"],
.gform_wrapper.gform-theme--framework .gform_footer button,
.gform_wrapper.gform-theme--framework .gform_page_footer input[type="submit"],
.gform_wrapper.gform-theme--framework .gform_page_footer input[type="button"],
.gform_wrapper.gform-theme--framework .gform_page_footer button,
.gform_wrapper.gform-theme--orbital .gform_footer input[type="submit"],
.gform_wrapper.gform-theme--orbital .gform_footer button,
.gform_wrapper.gform-theme--orbital .gform_page_footer input[type="submit"],
.gform_wrapper.gform-theme--orbital .gform_page_footer button {
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.4;
	height: auto;
	min-height: 0;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	border-radius: 0;
	background: var(--slate);
	color: var(--limewash);
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.gform_wrapper.gform-theme--framework .gform_footer input[type="submit"]:hover,
.gform_wrapper.gform-theme--framework .gform_footer button:hover,
.gform_wrapper.gform-theme--orbital .gform_footer input[type="submit"]:hover,
.gform_wrapper.gform-theme--orbital .gform_footer button:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--limewash);
}

/* The orbital button size tokens drive padding and height on some builds. */
.gform_wrapper.gform-theme {
	--gf-ctrl-btn-font-size-md: var(--fs-2xs);
	--gf-ctrl-btn-padding-x-md: 1.5rem;
	--gf-ctrl-btn-padding-y-md: 0.95rem;
	--gf-ctrl-btn-size-md: auto;
	--gf-ctrl-btn-line-height-md: 1.4;
}

/* Gravity Forms writes an inline <style> scoped to #gform_wrapper_N, and an ID
   outranks any class selector this stylesheet can offer. Matching the same ID
   shape is the only way to reach the button's tracking and case without
   resorting to !important. */
[id^="gform_wrapper"] .gform_footer input[type="submit"],
[id^="gform_wrapper"] .gform_footer button,
[id^="gform_wrapper"] .gform_page_footer input[type="submit"],
[id^="gform_wrapper"] .gform_page_footer input[type="button"],
[id^="gform_wrapper"] .gform_page_footer button,
[id^="gform_wrapper"] .gform_button,
[id^="gform_wrapper"] .gform-theme-button {
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.4;
	height: auto;
	min-height: 0;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	border-radius: 0;
	background: var(--slate);
	color: var(--limewash);
}

[id^="gform_wrapper"] .gform_footer input[type="submit"]:hover,
[id^="gform_wrapper"] .gform_footer button:hover,
[id^="gform_wrapper"] .gform_button:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--limewash);
}



/* ---------- ACF INNERBLOCKS WRAPPER ----------
   ACF wraps <InnerBlocks /> output in its own .acf-innerblocks-container div.
   Where that sits directly inside a grid, the wrapper becomes the only grid
   item and every child stacks into the first track — which collapsed the
   two-column contact and trade layouts. display: contents lets the children
   participate in the grid directly. */

.block-columns > .acf-innerblocks-container {
	display: contents;
}

/* Belt and braces: if a browser without display:contents support renders the
   wrapper as a box, it should at least span the grid rather than squash. */
@supports not (display: contents) {
	.block-columns > .acf-innerblocks-container {
		display: grid;
		grid-template-columns: inherit;
		gap: inherit;
		grid-column: 1 / -1;
	}
}

/* ---------- GRAVITY FORMS SUBMIT BUTTON ----------
   The framework stylesheet styles the submit with

     .gform-theme--framework.gform-theme.gform_wrapper
       input[type="submit"].button.gform_button

   which is specificity (0,5,1) — above anything sensible this stylesheet can
   write — and it resolves letter-spacing through `var(--gf-local-letter-spacing)`.
   That variable is undefined by default, so the property falls back to its
   initial value and the button renders untracked and lower case no matter how
   many selectors are thrown at it.

   The fix is to feed the framework its own variables rather than fight the
   selector, with a specificity-matched rule as a backstop. */

/* Gravity Forms lays fields out on a grid with a 40px row gap, and each field
   also carries its own bottom margin — together 61px between fields, against
   the prototype's single 1.3rem. The grid gap is removed so the field margin
   alone sets the rhythm. */
/* Gravity Forms sets the grid gap from its own custom property, so setting
   `row-gap` directly loses to `gap: var(--gf-form-gap-y)`. The variable is
   what has to change — the same pattern as the submit button and the select
   earlier in this build. The prototype's rhythm is a single 1.3rem margin on
   each field. */
.gform_wrapper,
.gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--framework {
	--gf-form-gap-y: 0px;
}

/* ---------- Validation and focus, in the site's own idiom ----------
   Gravity Forms paints errors in its own red and focus in its own blue; the
   palette here is slate, chalk and rose, so both are re-tokened. The
   framework drives these through custom properties on the wrapper, which is
   the layer to override — the same pattern as the button and the select. */
.gform_wrapper,
.gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--framework {
	--gf-color-danger: var(--rose-ink);
	--gf-color-danger-contrast: var(--rose-ink);
	--gf-ctrl-border-color-error: var(--rose-ink);
	--gf-ctrl-border-color-focus: var(--slate);
	--gf-ctrl-shadow-focus: none;
	--gf-ctrl-box-shadow-focus: none;
	/* The framework paints the select chevron from its own icon variables and
	   swaps them on hover and focus — its rule beats any theme selector, so a
	   restated background simply lost and half the chevron vanished. Putting
	   the theme's own chevron into all three variables makes their rule paint
	   the right mark in every state. */
	--gf-ctrl-select-icon: var(--ps-select-chevron);
	--gf-ctrl-select-icon-hover: var(--ps-select-chevron);
	--gf-ctrl-select-icon-focus: var(--ps-select-chevron);
	--gf-ctrl-outline-focus: 2px solid var(--rose-ink);
	--gf-ctrl-outline-offset-focus: 2px;
	--gf-ctrl-btn-outline-focus: 2px solid var(--rose-ink);
	--gf-ctrl-btn-outline-offset-focus: 2px;
	--gf-color-in-error: var(--rose-ink);
	--gf-ctrl-bg-color-error: var(--white);
}

.gform_wrapper .gform_validation_errors,
.gform_wrapper .gform_validation_errors.validation_error {
	background: var(--chalk);
	border: 1px solid var(--rose-ink);
	border-radius: 0;
	box-shadow: none;
	padding: 1rem 1.2rem 1rem 3.4rem;
	margin: 0 0 1.6rem !important;
	position: relative;
	color: var(--slate);
}

.gform_wrapper .gform_validation_errors::before {
	content: "";
	position: absolute;
	left: 1.2rem;
	top: 50%;
	width: 1.2rem;
	height: 1.2rem;
	transform: translateY(-50%);
	border-radius: 50%;
	background: var(--rose-ink);
}

.gform_wrapper .gform_validation_errors > h2,
.gform_wrapper .gform_validation_errors .gform_submission_error {
	font-family: var(--sans);
	font-weight: 400;
	font-size: var(--fs-sm);
	color: var(--slate);
	margin: 0;
	padding: 0;
	letter-spacing: 0;
	text-transform: none;
}

.gform_wrapper .gform_validation_errors .gform-icon,
.gform_wrapper .gform_submission_error .gform-icon { display: none; }

.gform_wrapper .gform_validation_errors .gform_validation_error_link { color: var(--rose-ink); }

.gform_wrapper .gfield_error .gfield_label,
.gform_wrapper .gfield_error legend.gfield_label { color: var(--rose-ink); }

/* One "required" convention across every form: the checkout's asterisk.
   Gravity Forms' "(Required)" badge is replaced by the same mark. */
/* Gravity Forms nests .gfield_required inside .gfield_required, so an ::after
   on the bare class renders the asterisk twice. Only the outer one carries it,
   and the inner "(Required)" text is what gets hidden. */
.gform_wrapper .gfield_required,
.gform_wrapper .gfield_required_text,
.gform_wrapper .gfield_required_asterisk { font-size: 0; letter-spacing: 0; }

/* "(Optional)" sits in the label beside the field name, as the quieter twin
   of the required asterisk. The word is moved there in PHP (ps_gf_inline_optional). */
.gform_wrapper .gfield_label .ps-optional {
	font-weight: 300;
	font-size: var(--fs-2xs);
	letter-spacing: 0;
	text-transform: none;
	color: var(--khaki-ink);
	margin-left: 0.4rem;
}

.gform_wrapper .gfield_label > .gfield_required::after {
	content: " *";
	font-size: var(--fs-2xs);
	letter-spacing: 0.22em;
	color: var(--rose-ink);
}

.gform_wrapper .gfield_validation_message,
.gform_wrapper .validation_message,
.gform_wrapper .gfield_error .gfield_validation_message {
	background: none;
	border: 0;
	padding: 0;
	margin: 0.4rem 0 0;
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	letter-spacing: 0.04em;
	color: var(--rose-ink);
}

.gform_wrapper .gfield_error input:not([type="checkbox"]):not([type="radio"]),
.gform_wrapper .gfield_error select,
.gform_wrapper .gfield_error textarea { border-color: var(--rose-ink); background: var(--white); }

/* The framework paints its blue ring as a box-shadow set on the control
   itself inside a high-position :where() block, so an outline alone leaves
   the blue underneath. Both are forced; the framework leaves no other way. */
.gform_wrapper input:focus-visible,
.gform_wrapper select:focus-visible,
.gform_wrapper textarea:focus-visible,
.gform_wrapper input:focus,
.gform_wrapper select:focus,
.gform_wrapper textarea:focus,
.gform_wrapper .gform_button:focus-visible,
.gform_wrapper .gform-theme-button:focus-visible,
.gform_wrapper .gform_button:focus,
.gform_wrapper .gform-theme-button:focus {
	outline: 2px solid var(--rose-ink) !important;
	outline-offset: 2px !important;
	box-shadow: none !important;
	border-color: var(--slate) !important;
}

.gform_wrapper,
.gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--framework {
	--gf-local-letter-spacing: 0.18em;
	--gf-local-text-transform: uppercase;
	--gf-local-font-size: var(--fs-2xs);
	--gf-local-font-weight: 500;
	--gf-local-line-height: 1.4;
	--gf-local-radius: 0;
	--gf-local-color: var(--limewash);
	--gf-local-bg-color: var(--slate);
	--gf-local-border-color: var(--slate);
	--gf-local-color-hover: var(--limewash);
	--gf-local-bg-color-hover: var(--rose-ink);
	--gf-local-border-color-hover: var(--rose-ink);
	--gf-local-padding-x: 1.5rem;
	--gf-local-padding-y: 0.95rem;
	--gf-local-height: auto;
}

/* Backstop at matching specificity, for builds that do not route these
   properties through the local variables. */
.gform-theme--framework.gform-theme.gform_wrapper input[type="submit"].button.gform_button,
.gform-theme--framework.gform-theme.gform_wrapper input[type="button"].button,
.gform-theme--framework.gform-theme.gform_wrapper button.button.gform_button,
.gform-theme.gform_wrapper input[type="submit"].gform_button.button {
	font-family: var(--sans);
	font-size: var(--fs-2xs);
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.4;
	height: auto;
	min-height: 0;
	padding: 0.95rem 1.5rem;
	border: 1px solid var(--slate);
	border-radius: 0;
	background: var(--slate);
	color: var(--limewash);
	-webkit-appearance: none;
	appearance: none;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}

.gform-theme--framework.gform-theme.gform_wrapper input[type="submit"].button.gform_button:hover,
.gform-theme.gform_wrapper input[type="submit"].gform_button.button:hover {
	background: var(--rose-ink);
	border-color: var(--rose-ink);
	color: var(--limewash);
}

/* Backstop for the Gravity Forms submit button.
   The framework redefines --gf-local-letter-spacing and --gf-local-text-transform
   on the button element inside a :where(:not(…)) selector, so neither a
   wrapper-level variable nor a more specific rule can reach them. The theme
   opts the form out of framework button styling in inc/gravity-forms.php; this
   pair is the belt to that braces, and is the one place the playbook's
   no-!important rule gives way to a plugin injecting its own styles. */
.gform_wrapper input[type="submit"],
.gform_wrapper input[type="button"],
.gform_wrapper button.gform_button,
.gform_wrapper .gform-theme-button {
	letter-spacing: 0.18em !important;
	text-transform: uppercase !important;
}

/* The framework sizes every control with `block-size: var(--gf-local-height)`,
   which resolves to --gf-ctrl-size-md (38px). With 13.6px of padding top and
   bottom plus a 25.6px line box, the selected option is pushed out of a 38px
   box and renders as a clipped sliver. `height: auto` cannot win because
   block-size is the same property resolved through their variable — so the
   variable is what has to change. */
.gform_wrapper,
.gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--framework {
	--gf-ctrl-size-md: auto;
	--gf-ctrl-size: auto;
	--gf-ctrl-line-height: 1.6;
	--gf-local-height: auto;
	--gf-local-min-height: auto;
}

.gform_wrapper select,
[id^="gform_wrapper"] select {
	block-size: auto;
	height: auto;
	min-height: 0;
	line-height: 1.6;
	padding-block: 0.85rem;
}

/* This later rule repositioned the chevron but never restated the gradient
   layers, so the select computed no background-image while `repeat` leaked
   through — and Chromium tiled the UA arrow on hover. The full stack is set
   here so nothing is inherited by accident. */

