/**
 * WC2026 - reusable component styles
 * ==================================
 *
 * Depends on tokens.css, which must be enqueued first.
 *
 * Rules for anything added here:
 *   1. No hardcoded colours, font sizes or spacing values. Add a token.
 *   2. Class names are generic (.rp-card, not .rp-category-page-card) so the
 *      next page built can reuse them without a rename.
 *   3. Nothing is scoped to the WooCommerce category template. The only
 *      WooCommerce-specific rules are the resets at the bottom, kept apart
 *      deliberately so they are easy to find and delete.
 *
 * Block index:
 *   1. Layout      .rp-container, .rp-grid
 *   2. Card        .rp-card and its elements
 *   2b. Cat card   .rp-cat-grid, .rp-cat-card
 *   3. Price       .rp-price
 *   4. Button      .rp-btn
 *   4b. Forms      .rp-form, .rp-field, .rp-check, .rp-captcha
 *   4c. Account    .rp-account-menu (header drop-down)
 *   5. Read more   .rp-readmore
 *   6. Load more   .rp-loadmore
 *   7. Single prod  .rp-product
 *   8. Breadcrumb   .rp-breadcrumb
 *   9. Gallery      .rp-gallery
 *  10. Header      .rp-header, .rp-nav
 *  11. Utilities   .rp-visually-hidden
 *  14. WooCommerce structural resets   <- out of order in the body, not a typo
 *  12. Newsletter  .rp-newsletter
 *  13. Footer      .rp-footer
 *  18. Delivery    .rp-delivery   <- at the end of the file, after 17
 *
 * THE ORDER ABOVE IS THE ORDER IN THE FILE, including 14 sitting between 11 and
 * 12. A hand-maintained index on a 2,000-line stylesheet drifts - this one had
 * already lost 4b and 4c - so it is written to match reality rather than to
 * look tidy. If it drifts again, that is the file asking to be split.
 */


/* ===================================================================
 * 0. Reset
 *
 * A global border-box, added deliberately rather than as part of a bug fix.
 *
 * WHY: without it, every component that pairs a width with padding has to
 * remember to say box-sizing itself, and the one that forgot made the flyout
 * panel rows 302px wide inside a 270px panel - pushing their chevrons outside
 * the menu and, on the last item, past the viewport edge.
 *
 * Components that already declare border-box are unaffected. Anything relying
 * on content-box would change, which is why this was applied as its own change
 * with a pass over each page rather than bundled into that fix.
 * =================================================================== */

*,
*::before,
*::after {
	box-sizing: border-box;
}


/* ===================================================================
 * 1. Layout
 * =================================================================== */

/**
 * Space between the content and the full-width bands above and below it.
 *
 * BOTH SIDES. Figma's "v-padding" variable is 80, and the design applies it
 * top and bottom — measured on two frames to be sure:
 *
 *   category  Body Wrap 1126 tall, wrapper 966 at y=80  -> 80 below
 *   product   Product List 766 tall, wrapper 606 at y=80 -> 80 below
 *
 * Setting only padding-block-start left the last row of cards, and the end of a
 * product description, butted straight against the newsletter band.
 *
 * Applied to the content wrapper rather than to the breadcrumb or the grid, so
 * it holds on pages that have neither.
 *
 * The visible gap is larger than 80px because the newsletter band carries its
 * own 80px of top padding. That is the design's doing, not double-spacing here.
 */
/* 40 above, 80 below. The frames put the breadcrumb 40px under the nav bar;
 * the 80 below is the rhythm down to the newsletter band. */
/* BOTH page wrappers, not just .rp-container. The spacing belongs to the
 * wrapper rather than to .rp-breadcrumb - see the note above, a page with no
 * breadcrumb still needs it - which means every wrapper has to carry it.
 * .rp-page (brochure bands) did not, so its trail sat against the nav bar. */
main.rp-container,
main.rp-page {
	padding-block-start: var(--rp-page-top);
}

/* Bottom only on .rp-container: a band page ends in a band, and the last one
 * already carries its own 80px down to the newsletter. */
main.rp-container {
	padding-block-end: var(--rp-v-padding);
}

/**
 * --rp-container-max is the CONTENT width, so the gutter has to be added to the
 * max-width rather than taken out of it. Without the calc, border-box spends the
 * padding inside the 1200 and every page runs 40px narrow - cards at 275 instead
 * of Figma's 285, product columns at 550 instead of 570.
 *
 * .rp-header__inner and .rp-home-wrap already do this; this rule did not, which
 * is why the home page measured right and nothing else did.
 */
.rp-container {
	box-sizing: border-box;
	width: 100%;
	max-width: calc(var(--rp-container-max) + (2 * var(--rp-space-lg)));
	margin-inline: auto;
	padding-inline: var(--rp-space-lg);
}

/**
 * Card grid.
 *
 * Column counts are fixed per breakpoint rather than auto-fitting, because
 * the design specifies exactly 4 / 2 / 1 and an auto-fit track would give 5
 * columns at 1200px. minmax(0, 1fr) rather than minmax(230px, 1fr) so a
 * narrow viewport shrinks the cards instead of overflowing the page.
 */
.rp-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	column-gap: var(--rp-grid-gap-x);
	row-gap: var(--rp-grid-gap-y);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 600px) {
	.rp-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 992px) {
	.rp-grid {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}


/* ===================================================================
 * 2. Card
 * =================================================================== */

.rp-card {
	display: flex;
	flex-direction: column;
	min-width: 0;                       /* lets long titles wrap instead of stretching the track */
	background: var(--rp-surface-card);
	overflow: hidden;
	font-family: var(--rp-font-family);
}

/**
 * The card carries two links to the same product - one on the image, one on
 * the text block. They are separate because the button between them is also a
 * link, and anchors cannot nest.
 *
 * The image link is aria-hidden and tabindex="-1" in the template, so this is
 * one tab stop and one accessible name, not two.
 */
.rp-card__link {
	display: block;
	color: inherit;
	text-decoration: none;
}

.rp-card__link--info {
	width: 100%;
	min-width: 0;
}

/* No hover underline by client decision, matching .rp-cat-card. Kept on
 * focus-visible so keyboard users still get the text cue. */
.rp-card__link--info:focus-visible .rp-card__title {
	text-decoration: underline;
}

.rp-card__link:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: -2px;
}

/**
 * Media.
 *
 * A fixed aspect ratio keeps the grid rows aligned; `contain` shows the whole
 * photograph inside it.
 *
 * THE HISTORY MATTERS, because this flipped twice. It was `contain`, then
 * `cover` when the source turned out to be WooCommerce's 1:1 hard crop - all
 * `contain` was preserving was a crop, in a box the wrong shape for it. The
 * source is now `medium_large`, which is uncropped (see
 * wc2026_card_image_size), so `contain` shows the real photo and `cover` would
 * start throwing parts of it away again. Change the size and the fit together
 * or not at all.
 */
.rp-card__media {
	position: relative;
	width: 100%;
	aspect-ratio: var(--rp-card-media-ratio);
	/* Shows while the image loads and on products with no photo. Cream rather
	 * than white: Figma runs the image well in the same Light 1 as the panel. */
	background: var(--rp-surface-card-detail);
	overflow: hidden;
}

.rp-card__media img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	object-fit: contain;
}

/* Detail block - the cream panel under the photo.
 *
 * flex: 1 1 auto so the panel absorbs any leftover card height; that is what
 * gives rp-card__detail-inner something to distribute with space-between. */
.rp-card__detail {
	display: flex;
	flex: 1 1 auto;
	justify-content: center;
	box-sizing: border-box;
	min-height: var(--rp-card-detail-height);
	/* 10 top/bottom, 4 each side - the 277 inner wrap inside a 285 card. */
	padding: var(--rp-space-xs) var(--rp-space-2xs);
	background: var(--rp-surface-card-detail);
}

/* space-between pins the button to the bottom, so buttons line up across a
 * row even when titles wrap to different line counts */
.rp-card__detail-inner {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	gap: var(--rp-space-3xs);
	min-width: 0;
}

.rp-card__info {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--rp-space-3xs);
	width: 100%;
	min-width: 0;
}

.rp-card__title {
	margin: 0;
	padding: 0;
	color: var(--rp-text-heading);
	font-size: var(--rp-type-heading-sm-size);
	font-weight: var(--rp-type-heading-sm-weight);
	line-height: var(--rp-type-heading-sm-leading);
	text-align: center;
	overflow-wrap: break-word;
}

/* Meta row: "Stock: S789" on the left, dimensions or availability on the right */
.rp-card__meta {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--rp-space-xs);
	width: 100%;
	color: var(--rp-text-muted);
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-regular);
	line-height: var(--rp-type-body-sm-leading);
}

.rp-card__meta-item {
	margin: 0;
	white-space: nowrap;
}

.rp-card__meta-label {
	font-size: var(--rp-type-label-sm-size);
	font-weight: var(--rp-font-weight-medium);
}

.rp-card__meta-strong {
	font-weight: var(--rp-font-weight-bold);
}


/* ===================================================================
 * 2b. Category card
 *
 * Figma "3-Product Categories Grid" (79:546) and "category-card" (388:62982).
 *
 * A category page draws EITHER these or product cards, never both - the branch
 * is in woocommerce/archive-product.php. Nothing here is shared with .rp-card
 * on purpose: they look nothing alike, and forcing a common base would leave
 * both fighting it.
 * =================================================================== */

/* WooCommerce's own wrapper, so the class is not rp-prefixed. Applies to the
   product grid too - both sit directly under this header with no margin. */
.term-description {
	padding-block-end: var(--rp-term-description-gap);
}

.rp-cat-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--rp-grid-gap-x);
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 600px) {
	.rp-cat-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (min-width: 992px) {
	.rp-cat-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

.rp-cat-card {
	position: relative;
	aspect-ratio: var(--rp-cat-card-ratio);
	overflow: hidden;

	/* Shows through when a category has no thumbnail. WooCommerce's placeholder
	 * is not used - at this size a grey square reads as a broken page. */
	background: var(--rp-surface-card-detail);
}

.rp-cat-card__link {
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	width: 100%;
	height: 100%;
	text-decoration: none;
}

.rp-cat-card__image {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;

	/* cover, not contain - unlike product photos these are crops chosen to fill
	 * a tile, and letterboxing them would leave bands of flat colour. */
	object-fit: cover;
}

/**
 * The scrim.
 *
 * A gradient from transparent to 52% black over the lower 156px, so the white
 * title stays legible whatever the photo underneath is doing. Tokenised because
 * the stops are a design decision, not an implementation detail.
 */
.rp-cat-card__info {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-end;
	gap: 5px;
	min-height: var(--rp-cat-card-info-height);
	padding: 0 var(--rp-space-md) 17px;
	background: var(--rp-cat-card-scrim);
}

.rp-cat-card__title {
	color: var(--rp-text-on-dark);
	font-size: var(--rp-type-h3-caps-size);
	font-weight: var(--rp-type-h3-caps-weight);
	line-height: 1.1;
	text-align: center;
	text-transform: uppercase;
	overflow-wrap: break-word;
}

.rp-cat-card__view {
	display: flex;
	align-items: center;
	gap: var(--rp-space-2xs);
	color: var(--rp-text-on-dark);
	font-size: var(--rp-type-body-xs-size);
	line-height: var(--rp-type-body-xs-leading);
}

/* No hover underline by client decision. Kept on focus-visible so keyboard
   users still get the text cue, not just the outline below. */
.rp-cat-card__link:focus-visible .rp-cat-card__title {
	text-decoration: underline;
}

.rp-cat-card__link:focus-visible {
	outline: 2px solid var(--rp-text-on-dark);
	outline-offset: -4px;
}


/* ===================================================================
 * 3. Price
 *
 * WooCommerce emits <del> before <ins> for a sale price. The design shows the
 * current price first, so the two are swapped with flex `order` rather than by
 * overriding the template - keeping the markup standard means WooCommerce's own
 * price filters keep working untouched.
 *
 * THE TRAP, and it has already been fallen into once:
 *
 * A price range is "<span>$950</span> - <span>$1,195</span>". In a flex
 * container that bare " - " between the two spans becomes an ANONYMOUS FLEX
 * ITEM, and anonymous items are always order: 0 with no way to select them.
 * Putting `order: 1` on the amount spans therefore sorted the dash in front of
 * both prices: "- $950 $1,195".
 *
 * So the container is only a flex container when there is actually something to
 * reorder. Ranges stay in normal inline flow, where the separator sits wherever
 * the markup puts it and no anonymous item is created.
 *
 * Do not add `order` to anything but del/ins, and do not make this flex
 * unconditionally.
 * =================================================================== */

.rp-price {
	display: block;
	width: 100%;
	margin: 0;
	padding-bottom: var(--rp-space-3xs);
	color: var(--rp-text-heading);
	font-size: var(--rp-type-price-size);
	line-height: var(--rp-type-price-leading);
	text-align: center;
}

/* Keep a single figure from breaking mid-number, while still letting a long
 * range wrap rather than overflow a narrow card. */
.rp-price .woocommerce-Price-amount,
.rp-price .amount {
	white-space: nowrap;
}

/* Sale prices only - the one case that needs reordering.
 *
 * Without :has() support this degrades to WooCommerce's own order (was-price
 * first, then current). Readable, just the wrong emphasis. */
.rp-price:has(del) {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--rp-space-md);
}

.rp-price:has(del) ins {
	order: 1;
}

.rp-price:has(del) del {
	order: 2;
}

/* Current price - the sale price and a plain non-sale price both */
.rp-price ins,
.rp-price > .woocommerce-Price-amount,
.rp-price > .amount {
	background: none;
	color: inherit;
	font-weight: var(--rp-type-price-weight);
	text-decoration: none;
}

/* Was-price */
.rp-price del {
	color: inherit;
	font-weight: var(--rp-type-price-was-weight);
	text-decoration: line-through;
	opacity: 1;
}

/* "Enquire for price" and other bare strings returned by the price filter */
.rp-price--text {
	font-weight: var(--rp-type-price-weight);
}

/**
 * Product page size. Figma "Price Wrap" (85:5057).
 *
 * The ONLY difference between the card price and the product page price is this
 * block — 24px, left-aligned, near-black, with the was-price in grey rather than
 * the card's muted brown. Figma's gap is 16; it uses the shared 15px step.
 *
 * That is the whole reason the live site's `$position` parameter ('summ' vs
 * 'meta') does not exist here. It was presentation dressed as an argument.
 */
.rp-price--lg {
	width: auto;
	margin: var(--rp-space-sm) 0 0;
	padding-bottom: 0;
	color: var(--rp-colour-ink);
	font-size: var(--rp-type-price-lg-size);
	text-align: left;
}

.rp-price--lg:has(del) {
	justify-content: flex-start;
	gap: var(--rp-space-md);
}

.rp-price--lg del {
	color: var(--rp-colour-ink-muted);
	font-weight: var(--rp-font-weight-bold);
}


/* ===================================================================
 * 4. Button
 *
 * A TYPE SYSTEM, not a set of one-off buttons. Every button on the site is
 * .rp-btn plus one colourway, and optionally one size modifier. Nothing should
 * ever restyle a button inline or invent a fourth colour.
 *
 *   .rp-btn              base - Figma "Button/Primary": Inter Medium 14,
 *                        uppercase, 80x17 padding, 180px minimum
 *   .rp-btn--cream       Colour/Light 3 ground, brown label
 *   .rp-btn--green       Colour/Dark Green ground, light label
 *   .rp-btn--white       white ground, dark green label
 *   .rp-btn--compact     the card's tighter button: 100px, bold, not uppercase
 *   .rp-btn--on-dark     cream label swap for use on the footer band
 *
 * The three colourways match the variants already documented for the SvelteKit
 * frontend - rp2024-frontend/docs/{cream,green,white}-button.md. Same names on
 * purpose, so a design conversation about "the cream button" means one thing
 * across both codebases.
 * =================================================================== */

.rp-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-width: var(--rp-button-min-width);
	padding: var(--rp-button-padding-y) var(--rp-button-padding-x);
	border: 0;
	border-radius: 0;
	font-family: var(--rp-font-family);
	font-size: var(--rp-type-button-size);
	font-weight: var(--rp-type-button-weight);
	line-height: 1;
	text-align: center;
	text-decoration: none;
	text-transform: uppercase;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 120ms ease-in-out, color 120ms ease-in-out;
}

.rp-btn:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: 2px;
}

/* WooCommerce toggles these while an ajax add-to-cart is in flight. */
.rp-btn.loading,
.rp-btn.added {
	opacity: 0.75;
}


/* ---- Colourways ---- */

.rp-btn--green {
	background: var(--rp-colour-dark-green);
	color: var(--rp-colour-light-1);
}

.rp-btn--green:hover,
.rp-btn--green:focus {
	background: var(--rp-button-bg-hover);
	color: var(--rp-colour-light-1);
}

.rp-btn--cream {
	background: var(--rp-colour-light-3);
	color: var(--rp-colour-primary-brown);
}

.rp-btn--cream:hover,
.rp-btn--cream:focus {
	background: var(--rp-colour-light-1);
	color: var(--rp-colour-primary-brown);
}

.rp-btn--white {
	background: var(--rp-colour-white);
	color: var(--rp-colour-dark-green);
}

.rp-btn--white:hover,
.rp-btn--white:focus {
	background: var(--rp-colour-light-1);
	color: var(--rp-colour-dark-green);
}

/* The footer's cream button labels in dark green rather than brown - the only
 * difference between it and the newsletter's. A modifier rather than a fourth
 * colourway, because the ground is identical. */
.rp-btn--on-dark.rp-btn--cream {
	color: var(--rp-colour-dark-green);
}


/* ---- Sizes ---- */

/**
 * The card button. Figma "Button" inside Product Detail (I85:5520;77:1122).
 *
 * Genuinely a different type, not just a smaller one: bold rather than medium,
 * sentence case rather than uppercase, and sized to sit inside a 230px card.
 */
.rp-btn--compact {
	min-width: var(--rp-button-compact-width);
	padding: var(--rp-button-compact-pad-y) var(--rp-button-compact-pad-x);
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-bold);
	line-height: var(--rp-type-body-sm-leading);
	text-transform: none;
}


/* ===================================================================
 * 4b. Forms
 *
 * Generic on purpose - .rp-field, not .rp-login-field. The account forms are
 * the first user, and the contact, enquiry and recycle forms are the next ones.
 *
 * Surfaces follow the Figma "9-Enquire Form" frame (383:53931), which is also
 * where the SvelteKit constants.scss takes them from: the page sits on the warm
 * ground, a panel sits on it in Light 1, and only the inputs inside a panel are
 * white. Getting that the wrong way round - a white panel with white fields -
 * is what made the SvelteKit checkout look unlike the artwork.
 * =================================================================== */

.rp-form {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-lg);
	margin: 0;
}

.rp-field {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-2xs);
	margin: 0;
}

/* Body/Small - 14 / 16. It was 16 with no line-height at all, so labels ran a
 * size large and, falling back to `normal`, on a rhythm of their own.
 *
 * Weight is left at Medium: Figma's Body/Small is Regular, but a label carrying
 * slightly more weight than the value below it is deliberate here and was not
 * what looked wrong. */
.rp-field__label {
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-medium);
	line-height: var(--rp-type-body-sm-leading);
	color: var(--rp-colour-ink);
}

.rp-field__input {
	box-sizing: border-box;
	width: 100%;
	/* Figma "9-Enquire Form": Fields/Padding - Vertical 8, Horizontal Left 12.
	 * It also states Right 8, which is an icon allowance; a plain text field is
	 * padded evenly. Radius/Radius Small (Fields) is 0. */
	padding: var(--rp-field-pad-y) var(--rp-field-pad-x);

	border: 1px solid var(--rp-field-border);
	border-radius: 0;
	background: var(--rp-surface-input);

	font-family: var(--rp-font-family);
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
	color: var(--rp-colour-ink);
}

.rp-field__input:focus {
	outline: 2px solid var(--rp-colour-dark-green);
	outline-offset: -2px;
}

.rp-field__error {
	margin: 0;
	font-size: var(--rp-type-body-sm-size);
	line-height: var(--rp-type-body-sm-leading);
	color: var(--rp-colour-error);
}

/* Checkbox rows are a horizontal field, so they opt out of the column. */
.rp-field--check {
	flex-direction: row;
	align-items: center;
}

/* Body/Small, like .rp-field__label - a checkbox's text IS its label, so it
 * takes the label size rather than the body size. */
.rp-check {
	display: flex;
	align-items: center;
	gap: var(--rp-space-xs);
	font-size: var(--rp-type-body-sm-size);
	line-height: var(--rp-type-body-sm-leading);
	color: var(--rp-colour-ink);
	cursor: pointer;
}

.rp-check__input {
	width: 18px;
	height: 18px;
	margin: 0;
	accent-color: var(--rp-colour-dark-green);
}

/**
 * The dimension / price filter bar.
 *
 * Figma "search-filter" (388:62481). Same metrics as filter-inputs.svelte's
 * "bar" layout, so both storefronts render the same row.
 *
 * The heading takes a full-width line of its own; fields absorb the slack and
 * the button never shrinks, so its right edge lines up with the grid below.
 */
.rp-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	gap: var(--rp-filter-row-gap) var(--rp-filter-col-gap);
	/* No top padding — the breadcrumb above already sets the gap. */
	padding-block: 0 var(--rp-filter-block-pad);
}

.rp-filters__title {
	width: 100%;
	margin: 0;
	font-family: var(--rp-font-family);
	font-size: var(--rp-type-body-size);
	font-weight: var(--rp-type-h2-weight);
	line-height: 1;
	text-transform: uppercase;
	color: var(--rp-text-heading);
}

.rp-filters__fields {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var(--rp-filter-fields-gap-y) var(--rp-filter-fields-gap-x);

	flex: 1 0 0;
	min-width: var(--rp-filter-fields-min);
}

.rp-filters__group {
	display: flex;
	flex-direction: column;
	gap: var(--rp-filter-group-gap);

	flex: 1 0 0;
	min-width: var(--rp-filter-group-min);
}

.rp-filters__label {
	font-family: var(--rp-font-family);
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-regular);
	color: var(--rp-colour-ink);
}

.rp-filters__pair {
	display: flex;
	align-items: center;
	gap: var(--rp-filter-group-gap);
}

/* The two boxes split the group evenly rather than sitting at a fixed width -
   Figma spans the full column and left-aligns the value inside it. */
.rp-filters__input {
	box-sizing: border-box;
	flex: 1 1 0;
	min-width: var(--rp-filter-input-min);
	padding: var(--rp-space-xs) var(--rp-space-sm);

	border: 1px solid var(--rp-field-border);
	border-radius: 0;
	background: var(--rp-surface-input);

	font-family: var(--rp-font-family);
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
	text-align: left;
	color: var(--rp-colour-ink);
}

.rp-filters__input:focus {
	outline: 2px solid var(--rp-colour-dark-green);
	outline-offset: -2px;
}

/* Hugs the dash: the flex gap either side is the only spacing, so it stays
   symmetric without arithmetic. */
.rp-filters__dash {
	flex: 0 0 auto;
	font-size: 15px;
	line-height: 1;
	color: var(--rp-text-body);
}

.rp-filters__actions {
	display: flex;
	align-items: center;
	gap: var(--rp-space-xs);
	flex: 0 0 auto;
}

/* Figma "Search-Button" (274:5457). Fill and colour stay on .rp-btn--green -
   only the box and the type weight are set here. */
.rp-filters__button {
	width: var(--rp-filter-button-width);
	height: var(--rp-filter-button-height);
	min-width: 0;
	padding: var(--rp-space-sm) 28px;
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-semibold);
}

@media (max-width: 768px) {

	.rp-filters__fields {
		min-width: 0;
	}

	.rp-filters__group {
		flex: 1 1 100%;
	}
}


/**
 * The captcha.
 *
 * The widget is a 302x76 iframe Google sizes itself, so there is nothing to lay
 * out - only room to leave for it and a shrink rule for the 402 comp, where 302
 * is wider than the 354 content column minus the panel's padding.
 *
 * transform rather than width: the iframe's contents do not reflow, so scaling
 * is the only thing that makes it narrower without clipping it.
 */
.rp-captcha {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-2xs);
}

@media (max-width: 400px) {
	.rp-captcha__widget {
		transform: scale(0.87);
		transform-origin: 0 0;

		/* Reclaim the space the scale leaves behind, or the form keeps a gap
		 * the widget no longer fills. */
		height: 66px;
	}
}


/* ===================================================================
 * 4c. Account menu (header)
 *
 * A native <details>, so the open/closed state, the click target and keyboard
 * activation are the browser's. See wc2026_render_account_menu().
 * =================================================================== */

.rp-account-menu {
	position: relative;
}

/* The default triangle marker, in both the syntaxes browsers use for it. */
.rp-account-menu__toggle {
	list-style: none;
	cursor: pointer;
}

.rp-account-menu__toggle::-webkit-details-marker {
	display: none;
}

.rp-account-menu__panel {
	position: absolute;
	top: 100%;
	right: 0;
	z-index: 20;

	display: flex;
	flex-direction: column;
	min-width: 180px;
	padding: var(--rp-space-xs) 0;

	background: var(--rp-colour-white);
	box-shadow: var(--rp-shadow-dropdown);
}

.rp-account-menu__item {
	padding: var(--rp-space-xs) var(--rp-space-md);

	font-size: var(--rp-nav-link-size);
	color: var(--rp-colour-primary-brown);
	text-decoration: none;
	white-space: nowrap;
}

.rp-account-menu__item:hover,
.rp-account-menu__item:focus-visible {
	background: var(--rp-colour-light-1);
	color: var(--rp-colour-dark-green);
}


/* ===================================================================
 * 5. Read-more disclosure
 *
 * Built on native <details>/<summary>, so there is no JavaScript anywhere in
 * this theme. The browser handles the open/closed state, the keyboard
 * interaction and the screen-reader semantics.
 *
 * The only thing CSS has to do is swap which label is visible, because a
 * <summary> cannot change its own text without script.
 * =================================================================== */

/* .rp-readmore IS the <details> element. There is no wrapper. */
.rp-readmore {
	display: block;
}

/**
 * The toggle.
 *
 * Removing the native disclosure triangle needs all three of these, because
 * browsers expose it differently:
 *
 *   display: block            <summary> defaults to display: list-item; taking
 *                             it off the list-item display removes the marker
 *                             in modern Chrome, Firefox and Safari
 *   list-style: none          standards-compliant belt
 *   ::-webkit-details-marker  older WebKit/Safari, which honours neither
 *
 * If a triangle ever reappears, the cause is almost always that this
 * stylesheet is not loading at all rather than a missing rule here - check
 * the ?ver= query string on components.css before adding a fourth.
 */
.rp-readmore__toggle {
	display: block;
	padding-top: var(--rp-space-lg);
	color: var(--rp-link-subtle);
	font-size: var(--rp-type-link-subtle-size);
	cursor: pointer;
	list-style: none;
}

.rp-readmore__toggle::-webkit-details-marker {
	display: none;
}

.rp-readmore__toggle::marker {
	content: "";
}

.rp-readmore__toggle:hover .rp-readmore__label {
	text-decoration: underline;
}

.rp-readmore__toggle:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: 2px;
}

/**
 * Exactly one label at a time.
 *
 * Closed: "[read more...]". Open: "[read less]".
 *
 * Both selectors are anchored on .rp-readmore[open], the <details> itself.
 * Seeing BOTH labels means these are not matching - check the element the
 * [open] attribute is actually on.
 */
.rp-readmore__label--less {
	display: none;
}

.rp-readmore[open] .rp-readmore__label--more {
	display: none;
}

.rp-readmore[open] .rp-readmore__label--less {
	display: inline;
}

.rp-readmore__body {
	padding-bottom: var(--rp-space-lg);
}

/**
 * Slide open, approximating the jQuery slideToggle() on the live site.
 *
 * Progressive enhancement: where ::details-content and interpolate-size are
 * unsupported the whole block is skipped and the panel snaps open, which is
 * the correct fallback rather than a broken one.
 */
@supports (interpolate-size: allow-keywords) {

	:root {
		interpolate-size: allow-keywords;
	}

	.rp-readmore::details-content {
		block-size: 0;
		overflow: hidden;
		transition:
			block-size 250ms ease,
			content-visibility 250ms allow-discrete;
	}

	.rp-readmore[open]::details-content {
		block-size: auto;
	}
}

@media (prefers-reduced-motion: reduce) {

	.rp-readmore::details-content {
		transition: none;
	}
}


/* ===================================================================
 * 6. Load more
 *
 * The server always renders real WooCommerce pagination. load-more.js hides it
 * and inserts this block; without JavaScript none of these classes exist and
 * the page links are simply visible, which is the intended fallback.
 * =================================================================== */

.rp-loadmore {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--rp-space-xs);
	padding-top: var(--rp-space-xl);
}

.rp-loadmore__status {
	margin: 0;
	min-height: var(--rp-type-body-sm-leading);   /* reserve the line so appearing text does not shift the page */
	color: var(--rp-text-muted);
	font-size: var(--rp-type-body-sm-size);
	line-height: var(--rp-type-body-sm-leading);
	text-align: center;
}

/**
 * Applied by JavaScript only.
 *
 * Not `display: none` on .woocommerce-pagination outright - that would hide the
 * links from crawlers and from anyone without JS, which is the whole point of
 * rendering them.
 */
.woocommerce-pagination.is-js-hidden {
	display: none;
}


/**
 * The page links themselves.
 *
 * ONE set of styles for the whole site: search.php renders woocommerce_pagination()
 * too rather than the_posts_pagination(), so there is a single markup to style.
 *
 * On a category these are usually hidden by load-more.js — but they are what a
 * crawler follows, what anyone without JavaScript uses, and what appears again
 * when a fetch fails. They were unstyled until 10 August 2026 because the JS
 * path hid them before anyone looked.
 */
.woocommerce-pagination {
	padding-top: var(--rp-space-xl);
	padding-bottom: var(--rp-space-lg);
}

.woocommerce-pagination ul.page-numbers {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: var(--rp-space-xs);
	margin: 0;
	padding: 0;
	list-style: none;
	border: 0;                              /* WooCommerce's own default */
}

.woocommerce-pagination ul.page-numbers li {
	margin: 0;
	padding: 0;
	border: 0;
	list-style: none;
}

.woocommerce-pagination .page-numbers {
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	/* 44px minimum touch target, and square unless the label is wider. */
	min-width: 44px;
	height: 44px;
	padding: 0 var(--rp-space-sm);
	border: 1px solid var(--rp-field-border);
	background: var(--rp-surface-input);
	color: var(--rp-text-heading);
	font-family: var(--rp-font-family);
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-medium);
	line-height: 1;
	text-decoration: none;
}

.woocommerce-pagination a.page-numbers:hover {
	background: var(--rp-surface-panel);
}

.woocommerce-pagination .page-numbers.current {
	background: var(--rp-colour-dark-green);
	border-color: var(--rp-colour-dark-green);
	color: var(--rp-text-on-dark);
	font-weight: var(--rp-font-weight-bold);
}

/* The gap marker is not a control - no box, no target size. */
.woocommerce-pagination .page-numbers.dots {
	min-width: 0;
	padding-inline: var(--rp-space-2xs);
	border-color: transparent;
	background: none;
	color: var(--rp-text-muted);
}

.woocommerce-pagination a.page-numbers:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: 2px;
}


/* ===================================================================
 * 7. Single product
 *
 * Two equal columns - gallery left, content right - matching Figma
 * "5-Product Variation 1" (85:4820): 570 / 60 gutter / 570 inside the 1200
 * wrapper.
 *
 * Equal 1fr tracks rather than two fixed 570px columns, so the split survives
 * a change to --rp-container-max without anyone having to recalculate it.
 * =================================================================== */

.rp-product {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--rp-product-gap);
	align-items: start;
}

@media (min-width: 992px) {
	.rp-product {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/**
 * Reserved gallery column.
 *
 * Empty by design. It holds its space from the start so the content column is
 * already at its final width — dropping the real gallery in later will not
 * reflow anything around it.
 *
 * The fill is the card surface colour so it reads as a deliberate reserved
 * area rather than a failed image.
 */
/**
 * The gallery column.
 *
 * NO fixed aspect ratio and no background. It used to carry
 * --rp-product-gallery-ratio (570/550 — the whole Figma block, main plus strip)
 * so a product with no photos still had a panel. But the column cannot tell "no
 * images" from "one image", so every single-image product got a blank Light 1
 * band underneath where the thumbnail strip would have been.
 *
 * The no-photo panel is .rp-gallery__placeholder now, rendered by the template,
 * which does know. Height here follows the content.
 */
.rp-product__gallery {
	width: 100%;
}

/* The whole block's height, for a product with no photos at all. */
.rp-gallery__placeholder {
	width: 100%;
	aspect-ratio: var(--rp-product-gallery-ratio);
	background: var(--rp-surface-card-detail);
}

.rp-product__content {
	min-width: 0;                       /* lets long words wrap instead of widening the track */
}

/* Figma "Product Name Wrap" (85:5053): Heading/H2, Inter Bold 24 at 100%
 * line-height, in the product page's near-black rather than the card brown. */
.rp-product__title {
	margin: 0 0 var(--rp-product-title-gap);
	color: var(--rp-colour-ink);
	font-size: var(--rp-type-h2-size);
	font-weight: var(--rp-type-h2-weight);
	line-height: 1.1;
}

/**
 * Summary — the type-specific block between title and description.
 *
 * Styled once, here, for every product type. The templates under
 * template-parts/ differ in WHAT they render, not in how it looks, so the
 * --simple / --variable modifier classes exist as hooks and are deliberately
 * unstyled. Add a rule against one only when the design actually diverges.
 */
/**
 * Summary - the type-specific block between title and description.
 *
 * Figma node 348:5430: ONE line, Heading/H4 (Inter Semi Bold 18) in the
 * product page near-black, reading "Stock: S789  |  1 available".
 *
 * Note the whole line is a single weight. The card splits label and value into
 * different sizes and weights; the product page does not. Do not reuse the
 * card's .rp-card__meta-label sizing here.
 *
 * The --simple / --variable modifiers are hooks and are deliberately unstyled:
 * the templates differ in WHAT they render, not how it looks. Add a rule
 * against one only when the design actually diverges.
 */
.rp-summary {
	margin: 0 0 var(--rp-product-block-gap);
	color: var(--rp-colour-ink);
	font-size: var(--rp-type-h4-size);
	font-weight: var(--rp-type-h4-weight);
	line-height: 1.2;
}

.rp-summary__line {
	margin: 0;
}

/* Figma "Product Description Wrap" (85:5061): a rule, then the dimensions, then
 * the description. Rendered together with the dimensions so a divider never
 * appears with nothing under it. */
.rp-summary__rule {
	height: 0;
	margin: var(--rp-space-md) 0;
	border: 0;
	border-top: 1px solid var(--rp-colour-ink-muted);
	opacity: 0.25;
}

/* Same treatment as the stock line - Heading/H4, inherited from .rp-summary. */
.rp-summary__dimensions {
	margin: 0;
}

/**
 * Action buttons. Figma "Price Wrap" (85:5182).
 *
 * Both share the row equally and wrap rather than shrink below 180px - the
 * design's minimum, and below it "CALCULATE DELIVERY" breaks onto two lines.
 * The SvelteKit original hits the same problem; its comment names 115px as the
 * point where the label wraps.
 *
 * The buttons themselves are plain .rp-btn types - nothing is restyled here,
 * which is the point of having types.
 */
.rp-summary__actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--rp-space-xs) var(--rp-space-lg);
	margin-block-start: var(--rp-product-block-gap);
}

.rp-summary__actions .rp-btn {
	flex: 1 0 auto;
	padding-inline: var(--rp-space-lg);
}

/* The pipe between stock number and availability. aria-hidden in the markup -
 * it is punctuation, and a screen reader announcing "vertical line" between
 * two facts is noise. */
.rp-summary__sep {
	padding: 0 var(--rp-space-2xs);
}


/**
 * The buy controls - quantity, Add to cart, and the two login buttons.
 *
 * NO FIGMA FRAME DRAWS THIS. Checked on "5-Product Variation 1" (85:4820) and
 * "7-Product Variation 3" (381:52524): the product column has one button row and
 * it holds the enquiry and delivery pair. So this reuses the theme's button and
 * field types rather than inventing a look - if the design ever specifies one,
 * this block is where it goes.
 */
.rp-buy {
	display: flex;
	flex-wrap: wrap;
	align-items: end;
	gap: var(--rp-space-xs) var(--rp-space-lg);
	margin-block-start: var(--rp-product-block-gap);
}

/* .rp-field is a column; a quantity label belongs beside its select, and the
 * select is narrow enough that stacking wastes the row. */
.rp-buy__quantity {
	flex-direction: row;
	align-items: center;
	gap: var(--rp-space-xs);
}

/* Weight restated: .rp-summary sets Heading/H4 semibold on everything under it,
 * and .rp-field__input states a size but not a weight. */
.rp-buy__select {
	width: auto;
	font-weight: var(--rp-font-weight-regular);
}

.rp-buy__login {
	margin: 0;
	margin-block-start: var(--rp-product-block-gap);
}

/* Colour only, as Availability.svelte has it - the word is already upper-case
 * in the frontend and the line's own type is what sets it apart here. Same
 * value as the SvelteKit --sold; see the token's note. */
.rp-buy__sold {
	margin: 0;
	margin-block-start: var(--rp-product-block-gap);
	color: var(--rp-colour-error);
}

/**
 * Description.
 *
 * Deliberately light-touch: this is editor output, so it is given readable
 * defaults rather than a rule per element. Headings, lists and tables inside it
 * keep browser defaults until the design says otherwise.
 */
/**
 * Description.
 *
 * Figma node 85:5064: Body/Regular, Inter Regular 16 / 22, in #666 - grey body
 * copy against the near-black headings above it.
 *
 * 22/16 is a ratio of 1.375, noticeably tighter than the 1.5-1.6 a generic body
 * default would give. It is set as an explicit px line-height rather than a
 * unitless ratio so it matches the design exactly and does not drift if the
 * font-size token changes.
 *
 * Otherwise light-touch: this is editor output, so headings, lists and tables
 * inside it keep browser defaults until the design says otherwise.
 */
.rp-product__description {
	color: var(--rp-colour-ink-muted);
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
}

.rp-product__description > *:first-child {
	margin-top: 0;
}

.rp-product__description > *:last-child {
	margin-bottom: 0;
}

.rp-product__description img {
	max-width: 100%;
	height: auto;
}


/* ===================================================================
 * 8. Breadcrumb
 *
 * Figma "Breadcrumb" (381:53281): 8px gap, Inter 14/16 in primary brown, a
 * house icon first and a chevron between every pair.
 *
 * The chevron is drawn by CSS on ::before, NOT put in the markup. It is
 * decoration - in the DOM it would be announced between every item.
 * =================================================================== */

/* Figma puts 40px between the breadcrumb and the block below it. Set on the
 * <nav> rather than the page templates so every page that uses the component
 * gets the same rhythm without repeating it. */
.rp-breadcrumb {
	margin-bottom: var(--rp-breadcrumb-space-after);
}

.rp-breadcrumb__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--rp-breadcrumb-gap);
	margin: 0;
	padding: 0;
	list-style: none;
	color: var(--rp-text-body);
	font-size: var(--rp-type-body-sm-size);
	font-weight: var(--rp-font-weight-regular);
	line-height: var(--rp-type-body-sm-leading);
}

/* Each item is itself a flex row so the ::before separator gets the same 8px
 * gap the list uses. That is what produces Figma's even 8px rhythm through the
 * whole trail rather than a doubled gap around each chevron. */
.rp-breadcrumb__item {
	display: flex;
	align-items: center;
	gap: var(--rp-breadcrumb-gap);
	min-width: 0;
}

/**
 * The chevron.
 *
 * A mask rather than a background-image, so it takes currentColor and stays in
 * step with the text. The exported SVG is filled black; drawn as an image it
 * would sit slightly darker than the #3e3c35 text beside it.
 *
 * url() is relative to this stylesheet, so no PHP is needed to build the path.
 */
.rp-breadcrumb__item + .rp-breadcrumb__item::before {
	content: "";
	flex: none;
	width: var(--rp-breadcrumb-separator-width);
	height: var(--rp-breadcrumb-separator-height);
	background-color: currentColor;
	-webkit-mask: url("../icons/breadcrumb-separator.svg") no-repeat center / contain;
	mask: url("../icons/breadcrumb-separator.svg") no-repeat center / contain;
}

.rp-breadcrumb__link {
	color: inherit;
	text-decoration: none;
}

.rp-breadcrumb__link:hover,
.rp-breadcrumb__link:focus-visible {
	text-decoration: underline;
}

.rp-breadcrumb__link:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: 2px;
}

.rp-breadcrumb__current {
	min-width: 0;
}

/* Keeps its own green (Colour/Primary Green, stroked in the source SVG) rather
 * than inheriting the text colour - it is a brand accent, not a glyph. */
.rp-breadcrumb__home-icon {
	display: block;
	width: auto;
	height: var(--rp-breadcrumb-home-size);
}

.rp-breadcrumb__item--home {
	flex: none;
}


/* ===================================================================
 * 9. Product gallery
 *
 * Figma "Product image" (85:5012): 570x427 main image above a 570x101 strip of
 * thumbnails with 29px arrow buttons at each end, 20px gaps throughout.
 *
 * The strip is a native overflow scroller. Touch swipe, momentum and keyboard
 * scrolling are the browser's; scroll-snap does the alignment. JavaScript only
 * adds the arrows and the image swap.
 * =================================================================== */

.rp-gallery {
	display: flex;
	flex-direction: column;
	gap: var(--rp-gallery-gap);
}

/* Reserved-but-empty state, when a product has no images at all. Matches the
 * placeholder box in content-single-product.php so the column keeps its shape. */
.rp-gallery--empty {
	width: 100%;
	aspect-ratio: var(--rp-product-gallery-ratio);
	background: var(--rp-surface-card-detail);
}

.rp-gallery__main {
	width: 100%;
	aspect-ratio: var(--rp-gallery-main-ratio);
	background: var(--rp-colour-gallery-panel);
	overflow: hidden;
}

/**
 * The main image is a button that opens the lightbox — see
 * assets/js/product-lightbox.js. Needs its own reset before it can be a
 * picture: buttons carry a UA background, border, padding and font.
 *
 * Inert until the module marks the gallery zoomable, so a blocked script leaves
 * a plain image rather than a control that does nothing.
 */
.rp-gallery__main-button {
	display: block;
	width: 100%;
	height: 100%;
	padding: 0;
	border: 0;
	background: none;
	cursor: default;
}

.rp-gallery--zoomable .rp-gallery__main-button {
	cursor: zoom-in;
}

.rp-gallery__main-button:focus-visible {
	outline: 2px solid var(--rp-colour-dark-green);
	outline-offset: -2px;
}

/* contain, not cover - this is second-hand stock photographed at every shape,
 * and cropping loses the ends of tall items. The card now crops to fill; this is
 * where the whole photo is, so it must not. */
.rp-gallery__main-image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/**
 * The lightbox caption.
 *
 * PhotoSwipe renders itself at the end of <body>, so this cannot live with the
 * gallery rules above in any scoped sense — it is here rather than in a
 * lightbox stylesheet because the theme has one component sheet. Values match
 * the SvelteKit .pswp__rp-caption in ImageGalleryWithLightbox.svelte.
 */
.pswp__rp-caption {
	position: absolute;
	bottom: 16px;
	left: 50%;
	transform: translateX(-50%);

	max-width: 80%;
	padding: 6px 13px;
	border-radius: 6px;

	background-color: rgb(255 255 255 / 90%);
	color: #000;
	text-align: center;

	/* Above the image, below the close and arrow controls. */
	z-index: 10;
}

.rp-gallery__strip {
	display: flex;
	align-items: stretch;
	gap: var(--rp-gallery-gap);
	height: var(--rp-gallery-thumb-height);
}

/**
 * The scroller.
 *
 * overflow-x: auto with scroll-snap is the entire carousel. scrollbar-width:
 * none hides the bar without disabling the scrolling, so touch and keyboard
 * still work - do not swap this for overflow: hidden.
 */
.rp-gallery__thumbs {
	display: flex;
	flex: 1 1 auto;
	gap: var(--rp-gallery-gap);
	margin: 0;
	padding: 0;
	list-style: none;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	overscroll-behavior-x: contain;
}

.rp-gallery__thumbs::-webkit-scrollbar {
	display: none;
}

.rp-gallery__thumb {
	flex: 1 0 auto;
	scroll-snap-align: start;
}

.rp-gallery__thumb-button {
	display: block;
	width: 100%;
	height: 100%;
	padding: 0;
	border: 0;
	background: var(--rp-colour-gallery-panel);
	cursor: pointer;
}

.rp-gallery__thumb-button img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* The selected thumbnail. aria-current is the source of truth for both the
 * styling and assistive tech, so the two cannot fall out of step. */
.rp-gallery__thumb-button[aria-current="true"] {
	outline: 2px solid var(--rp-colour-primary-green);
	outline-offset: -2px;
}

.rp-gallery__thumb-button:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: -2px;
}

/**
 * Arrows.
 *
 * Hidden until JavaScript adds .rp-gallery--enhanced, so a blocked or failed
 * script leaves no dead controls - the strip still scrolls by touch and
 * keyboard without them.
 */
.rp-gallery__arrow {
	display: none;
	flex: none;
	width: var(--rp-gallery-arrow-width);
	padding: 0;
	border: 0;
	background: var(--rp-colour-gallery-panel);
	color: var(--rp-text-heading);
	cursor: pointer;
}

.rp-gallery--enhanced .rp-gallery__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
}

/* Everything fits: nothing to scroll to, so the arrows are removed rather than
 * left permanently disabled. */
.rp-gallery--no-overflow .rp-gallery__arrow {
	display: none;
}

.rp-gallery__arrow::before {
	content: "";
	width: var(--rp-gallery-icon-size);
	height: var(--rp-gallery-icon-size);
	background-color: currentColor;
	-webkit-mask: url("../icons/gallery-arrow.svg") no-repeat center / contain;
	mask: url("../icons/gallery-arrow.svg") no-repeat center / contain;
}

/* The exported icon is an upward chevron. The design uses the one asset rotated
 * both ways rather than shipping two files. */
.rp-gallery__arrow--prev::before {
	transform: rotate(-90deg);
}

.rp-gallery__arrow--next::before {
	transform: rotate(90deg);
}

.rp-gallery__arrow:disabled {
	opacity: 0.35;
	cursor: default;
}

.rp-gallery__arrow:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {

	.rp-gallery__thumbs {
		scroll-behavior: auto;
	}
}


/* ===================================================================
 * 10. Site header
 *
 * Figma "Nav Bar" (96:1377): logo left, menu centre, actions right, on
 * Colour/Light 1 with a 120px page gutter and 24px of vertical padding.
 *
 * The menu markup is WordPress's own (wp_nav_menu), so the selectors below are
 * WordPress's class names — .menu-item, .sub-menu, .menu-item-has-children.
 * Those are generated, not chosen, which is why this block does not follow the
 * rp- naming used everywhere else.
 * =================================================================== */

.rp-header {
	background: var(--rp-surface-card-detail);
}

.rp-header__inner {
	/* The containing block for .rp-search, which lies over this row. */
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--rp-nav-gap);
	box-sizing: border-box;
	max-width: calc(var(--rp-container-max) + (2 * var(--rp-page-margin)));
	margin-inline: auto;
	padding: var(--rp-header-padding-y) var(--rp-page-margin);
}

/* Below the desktop breakpoint the 120px gutter is most of a phone screen. */
@media (max-width: 991px) {
	.rp-header__inner {
		flex-wrap: wrap;
		padding-inline: var(--rp-space-lg);
	}
}

/* the_custom_logo() renders its own <a><img>; size the image, not the link. */
.rp-header .custom-logo-link {
	display: block;
	flex: none;
	line-height: 0;
}

.rp-header .custom-logo {
	display: block;
	width: auto;
	height: var(--rp-header-logo-height);
}

/* Fallback when no logo is set in Site Identity. */
.rp-header__logo-text {
	flex: none;
	color: var(--rp-text-heading);
	font-size: var(--rp-type-h2-size);
	font-weight: var(--rp-type-h2-weight);
	text-decoration: none;
}


/* ---- Menu ---- */

.rp-nav__list {
	display: flex;
	align-items: center;
	gap: var(--rp-nav-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.rp-nav__list .menu-item {
	position: relative;
}

.rp-nav__list .menu-item > a {
	display: flex;
	align-items: center;
	gap: var(--rp-space-2xs);
	padding: 3px 6px;
	color: var(--rp-text-heading);
	font-size: var(--rp-nav-link-size);
	font-weight: var(--rp-font-weight-medium);
	letter-spacing: var(--rp-nav-link-tracking);
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
}

.rp-nav__list .menu-item > a:hover,
.rp-nav__list .menu-item > a:focus-visible {
	text-decoration: underline;
}

.rp-nav__list .menu-item > a:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: 2px;
}

/**
 * The chevron.
 *
 * Drawn on items WordPress has already marked as having children, so it appears
 * exactly where there is something to open — no walker and no template needed.
 *
 * A background-image rather than a mask: the exported icon is stroked in
 * Colour/Primary Green and the design keeps it that way, unlike the breadcrumb
 * separator which inherits the text colour.
 */
.rp-nav__list .menu-item-has-children > a::after {
	content: "";
	flex: none;
	width: var(--rp-nav-chevron-size);
	height: var(--rp-nav-chevron-size);
	background: url("../icons/nav-chevron-down.svg") no-repeat center / contain;
}

/**
 * Flyout menu — three levels.
 *
 * Ported from the SvelteKit Items.svelte, which is the working implementation:
 * depth 0 is the bar, depths 1 and 2 are the two panels. Deeper items are
 * dropped by the depth argument in wp_nav_menu(), matching MAX_DEPTH = 2 there.
 *
 * Level 1 drops below the bar; level 2 flies out to the right of its parent row
 * at exactly the panel width. That offset is why --rp-nav-panel-width is a
 * token rather than a literal in two places.
 *
 * COLOURS ARE 2026, STRUCTURE IS SVELTEKIT. The Svelte panels are #a30000 red
 * on white — the pre-2026 palette, still live because that menu has not been
 * restyled. Reproducing it inside this cream nav bar would look like a bug, so
 * the geometry and behaviour are ported and the colours come from tokens.
 *
 * NO JAVASCRIPT. Hover plus :focus-within, exactly as the Svelte version does.
 * That version additionally needs a `navigating` class to force the menu shut
 * after a client-side route change, because the pointer is left sitting over an
 * open panel on the new page. A WordPress page load discards the whole DOM, so
 * that problem does not exist here and the class is not ported.
 */

/* Full-height targets on the bar.
 *
 * From Items.svelte: "so the drop-down opens from the bar edge and the pointer
 * never crosses a dead gap on its way down". Without it, moving the mouse from
 * a nav item toward its panel passes over the bar's padding and the panel
 * closes underneath the cursor. */
.rp-nav__list > .menu-item {
	display: flex;
	align-items: center;
	min-height: var(--rp-nav-bar-height);
}

.rp-nav__list > .menu-item > a {
	min-height: var(--rp-nav-bar-height);
}

.rp-nav__list .sub-menu {
	position: absolute;
	z-index: 20;
	display: flex;
	flex-direction: column;
	align-items: stretch;
	box-sizing: border-box;
	width: var(--rp-nav-panel-width);
	margin: 0;
	padding: 0;
	background: var(--rp-surface-card);
	box-shadow: var(--rp-shadow-dropdown);
	list-style: none;

	/* Not display:none — opacity and visibility transition, and visibility
	 * still removes it from the accessible tree and from hit-testing. */
	opacity: 0;
	visibility: hidden;
	transition:
		opacity 250ms ease,
		visibility 250ms ease;
}

/* Level 1 drops below the bar. */
.rp-nav__list > .menu-item > .sub-menu {
	top: 100%;
	left: 0;
}

/* Level 2 flies out to the right of its parent row, overlapping the 1px border
 * so the two panels read as one surface. */
.rp-nav__list .sub-menu .sub-menu {
	top: -1px;
	left: var(--rp-nav-panel-width);
}

.rp-nav__list .menu-item:hover > .sub-menu,
.rp-nav__list .menu-item:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
}

/**
 * The last item opens leftward.
 *
 * Its panel is 270px anchored to the left of an item that already sits at the
 * right edge of the bar, so it opens past the viewport. That adds a horizontal
 * scrollbar and shifts the whole layout when the panel appears - which reads as
 * the menu item itself getting wider on hover.
 *
 * :last-child is the pragmatic fix, not the complete one: an item that is not
 * last can still overflow on a narrow desktop window or with a long menu.
 * Catching that properly means measuring at runtime, which is a script for a
 * problem this covers in practice.
 */
.rp-nav__list > .menu-item:last-child > .sub-menu {
	left: auto;
	right: 0;
}

/* Its second level flies out to the LEFT of its parent row, for the same
 * reason - otherwise it lands even further off-screen. */
.rp-nav__list > .menu-item:last-child .sub-menu .sub-menu {
	left: auto;
	right: var(--rp-nav-panel-width);
}

.rp-nav__list .sub-menu .menu-item {
	display: block;
	border-bottom: 1px solid var(--rp-colour-light-3);
}

.rp-nav__list .sub-menu .menu-item:last-child {
	border-bottom: 0;
}

/**
 * Panel rows.
 *
 * NO width: 100% HERE. A block or flex child already fills its parent, and
 * combining it with horizontal padding on a content-box element made each row
 * 302px wide inside a 270px panel - so justify-content: space-between pushed the
 * chevron 20px outside the panel, and on the last item, whose panel is anchored
 * to the right edge, past the viewport entirely.
 *
 * box-sizing is stated explicitly rather than relied on: this theme has no
 * global border-box reset, so every component that pairs a width with padding
 * has to say so.
 */
.rp-nav__list .sub-menu .menu-item > a {
	display: block;
	box-sizing: border-box;
	min-height: 0;
	padding: var(--rp-space-xs) var(--rp-space-lg) var(--rp-space-xs) var(--rp-space-sm);
	white-space: normal;
}

.rp-nav__list .sub-menu .menu-item > a:hover,
.rp-nav__list .sub-menu .menu-item > a:focus-visible {
	background: var(--rp-colour-light-1);
	text-decoration: none;
}

/**
 * Chevrons.
 *
 * On the bar it points down; in a panel it points right, at the row's trailing
 * edge, marking the rows that fly out further.
 *
 * Panel chevrons are a mask taking currentColor rather than the green
 * background-image used on the bar, so they stay legible against the hover
 * state and inherit the row's colour.
 */
.rp-nav__list .sub-menu .menu-item-has-children > a {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--rp-space-xs);
}

.rp-nav__list .sub-menu .menu-item-has-children > a::after {
	content: "";
	flex: none;
	width: var(--rp-nav-chevron-size);
	height: var(--rp-nav-chevron-size);
	background: currentColor;
	-webkit-mask: url("../icons/nav-chevron-down.svg") no-repeat center / contain;
	mask: url("../icons/nav-chevron-down.svg") no-repeat center / contain;
	transform: rotate(-90deg);
}

@media (prefers-reduced-motion: reduce) {

	.rp-nav__list .sub-menu {
		transition: none;
	}
}


/* ---- Actions ---- */

.rp-header__actions {
	display: flex;
	flex: none;
	align-items: center;
	gap: 13px;                          /* Figma: icon group gap */
}

.rp-header__action {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--rp-space-2xs);
	line-height: 0;
}

.rp-header__action img {
	display: block;
	width: var(--rp-nav-icon-size);
	height: var(--rp-nav-icon-size);
}

/**
 * The action icons. Taken from the SvelteKit header so both storefronts draw the
 * same marks — 28px on a 24 viewBox, 1.6 stroke, in Primary Green.
 *
 * They were 20px Figma exports in an <img>: a different size, a heavier stroke,
 * and different glyphs (a trolley rather than a bag). See
 * template-parts/nav-icon.php.
 *
 * `currentColor`, so a colour change is one declaration on the parent rather
 * than a second SVG file.
 */
.rp-nav-icon {
	display: block;
	flex-shrink: 0;
	width: var(--rp-nav-icon-size);
	height: var(--rp-nav-icon-size);
	color: var(--rp-colour-primary-green);
	fill: none;
	stroke: currentColor;
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.rp-header__action:focus-visible {
	outline: 2px solid var(--rp-focus-ring);
	outline-offset: 2px;
}

/* Visible only once focused, which is the whole point of a skip link. */
.rp-skip-link:focus {
	position: fixed;
	top: var(--rp-space-xs);
	left: var(--rp-space-xs);
	z-index: 100;
	width: auto;
	height: auto;
	margin: 0;
	padding: var(--rp-space-xs) var(--rp-space-md);
	background: var(--rp-surface-card);
	color: var(--rp-text-heading);
	clip-path: none;
}


/* -------------------------------------------------------------------
 * Header: mobile
 *
 * Figma "Nav" (390:80416) is a DIFFERENT ARRANGEMENT, not a reflow of the
 * desktop bar: logo and hamburger on one row, a full-width search field on the
 * next, and the account/cart icons gone entirely.
 *
 * Below the breakpoint the three-level flyout becomes a stacked accordion —
 * there is no hover to drive a flyout, and a 270px panel flying out to the
 * right has nowhere to go on a 402px screen.
 * ------------------------------------------------------------------- */

/* Desktop-only pieces. */
.rp-header__burger,
.rp-header__search {
	display: none;
}

/* Injected by site-nav.js; hidden on desktop where hover does the work. */
.rp-nav__toggle-sub {
	display: none;
}

@media (max-width: 991px) {

	.rp-header__inner {
		flex-wrap: wrap;
		row-gap: var(--rp-space-md);
	}

	.rp-header__burger {
		display: flex;
		align-items: center;
		justify-content: center;
		order: 2;
		width: var(--rp-burger-size);
		height: var(--rp-burger-size);
		padding: 0;
		border: 0;
		background: none;
		cursor: pointer;
	}

	/* Drawn rather than an asset: three rules that become a cross when open, so
	 * the control shows its own state without a second icon to keep in sync. */
	.rp-header__burger-bars,
	.rp-header__burger-bars::before,
	.rp-header__burger-bars::after {
		display: block;
		width: var(--rp-burger-size);
		height: 2px;
		background: var(--rp-text-heading);
		transition: transform 200ms ease, opacity 200ms ease;
	}

	.rp-header__burger-bars::before,
	.rp-header__burger-bars::after {
		content: "";
		position: absolute;
	}

	.rp-header__burger-bars::before {
		transform: translateY(-8px);
	}

	.rp-header__burger-bars::after {
		transform: translateY(8px);
	}

	.rp-header--nav-open .rp-header__burger-bars {
		background: transparent;
	}

	.rp-header--nav-open .rp-header__burger-bars::before {
		transform: rotate(45deg);
	}

	.rp-header--nav-open .rp-header__burger-bars::after {
		transform: rotate(-45deg);
	}

	/* Search takes its own full-width row, per the design. */
	.rp-header__search {
		display: flex;
		order: 3;
		align-items: center;
		gap: var(--rp-space-xs);
		box-sizing: border-box;
		width: 100%;
		height: var(--rp-search-height);
		padding-inline: var(--rp-space-xs);
		background: var(--rp-surface-card);
	}

	.rp-header__search .rp-nav-icon {
		width: 20px;
		height: 20px;
	}

	.rp-header__search-input {
		width: 100%;
		border: 0;
		background: none;
		color: var(--rp-text-heading);
		font-family: var(--rp-font-family);
		font-size: var(--rp-type-body-sm-size);
	}

	.rp-header__search-input:focus {
		outline: none;
	}

	/* The account and cart icons are not in the mobile design. */
	.rp-header__actions {
		display: none;
	}

	/**
	 * The panel.
	 *
	 * Collapsed with max-height rather than display:none so it can animate, and
	 * so the markup stays in the accessible tree in document order.
	 *
	 * WITHOUT JAVASCRIPT the .rp-header--nav-open class is never added, so the
	 * menu stays collapsed and the hamburger does nothing. That is the one place
	 * this theme depends on script for a core function — the alternative is a
	 * checkbox hack whose semantics are worse. Flagged rather than hidden.
	 */
	.rp-nav {
		order: 4;
		width: 100%;
		max-height: 0;
		overflow: hidden;
		transition: max-height 250ms ease;
	}

	.rp-header--nav-open .rp-nav {
		max-height: 80vh;
		overflow-y: auto;
	}

	.rp-nav__list {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
	}

	.rp-nav__list > .menu-item {
		display: block;
		min-height: 0;
		border-bottom: 1px solid var(--rp-colour-light-3);
	}

	.rp-nav__list .menu-item {
		position: relative;
	}

	.rp-nav__list > .menu-item > a,
	.rp-nav__list .sub-menu .menu-item > a {
		min-height: 0;
		padding: var(--rp-space-sm) 0;
		padding-inline-end: 44px;       /* clears the toggle button */
	}

	/* Flyout geometry off: panels become plain nested lists. */
	.rp-nav__list .sub-menu,
	.rp-nav__list .sub-menu .sub-menu {
		position: static;
		top: auto;
		left: auto;
		display: none;
		width: auto;
		padding-inline-start: var(--rp-space-md);
		background: none;
		box-shadow: none;
		opacity: 1;
		visibility: visible;
		transition: none;
	}

	/* Hover must not open anything on touch - only the button does. */
	.rp-nav__list .menu-item:hover > .sub-menu,
	.rp-nav__list .menu-item:focus-within > .sub-menu {
		display: none;
	}

	.rp-nav__list .menu-item--open > .sub-menu,
	.rp-nav__list .rp-nav__item--open > .sub-menu {
		display: block;
	}

	/* The chevron on the bar is replaced by the toggle button's own. */
	.rp-nav__list .menu-item-has-children > a::after {
		content: none;
	}

	.rp-nav__toggle-sub {
		position: absolute;
		top: 0;
		right: 0;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 44px;                    /* minimum comfortable touch target */
		height: 44px;
		padding: 0;
		border: 0;
		background: none;
		cursor: pointer;
	}

	.rp-nav__toggle-sub::after {
		content: "";
		width: var(--rp-nav-chevron-size);
		height: var(--rp-nav-chevron-size);
		background: var(--rp-text-heading);
		-webkit-mask: url("../icons/nav-chevron-down.svg") no-repeat center / contain;
		mask: url("../icons/nav-chevron-down.svg") no-repeat center / contain;
		transition: transform 200ms ease;
	}

	.rp-nav__toggle-sub[aria-expanded="true"]::after {
		transform: rotate(180deg);
	}

	.rp-nav__toggle-sub:focus-visible {
		outline: 2px solid var(--rp-focus-ring);
		outline-offset: -2px;
	}

	/* Stops the page scrolling behind an open panel. */
	body.rp-nav-open {
		overflow: hidden;
	}
}

@media (prefers-reduced-motion: reduce) {

	.rp-nav,
	.rp-header__burger-bars,
	.rp-header__burger-bars::before,
	.rp-header__burger-bars::after,
	.rp-nav__toggle-sub::after {
		transition: none;
	}
}


/* ===================================================================
 * 11. Utilities
 * =================================================================== */

/**
 * Visible to screen readers, not to sighted users.
 *
 * Used for the home crumb's label, whose icon carries alt="". Prefer this over
 * display: none or visibility: hidden, both of which remove the text from the
 * accessible tree as well.
 */
.rp-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}


/* ===================================================================
 * 14. WooCommerce structural resets
 *
 * WooCommerce's own stylesheets are dequeued in inc/woocommerce-setup.php
 * (see wc2026_dequeue_woocommerce_styles), so these resets only need to
 * undo browser defaults on the markup WooCommerce generates - not fight
 * WooCommerce CSS.
 *
 * If you re-enable WooCommerce's stylesheets, this block will need to grow.
 * =================================================================== */

.woocommerce ul.products.rp-grid,
ul.products.rp-grid {
	margin: 0;
	padding: 0;
	list-style: none;
}

.woocommerce ul.products.rp-grid::before,
.woocommerce ul.products.rp-grid::after {
	content: none;                      /* WooCommerce's clearfix, unwanted in grid */
}

.woocommerce ul.products.rp-grid li.product,
ul.products.rp-grid li.product {
	float: none;
	width: auto;
	margin: 0;
	padding: 0;
	clear: none;
}


/* ===================================================================
 * 12. Newsletter band
 *
 * Figma "newsletter" (89:1679). Full-width band above the footer on every page.
 * =================================================================== */

.rp-newsletter {
	background: var(--rp-surface-newsletter);
	padding: var(--rp-v-padding) var(--rp-page-margin);
}

.rp-newsletter__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--rp-space-lg);
	max-width: var(--rp-container-max);
	margin-inline: auto;
}

.rp-newsletter__text {
	margin: 0;
	color: var(--rp-text-on-dark);
	font-size: var(--rp-type-body-lg-size);
	line-height: var(--rp-type-body-lg-leading);
	text-align: center;
}

/* The design caps the button at 354px rather than letting it span the band. */
.rp-newsletter__button {
	max-width: 354px;
	width: 100%;
}


/* ===================================================================
 * 13. Site footer
 *
 * Figma "Footer section" (106:1947): brand column plus three link columns,
 * over a legal bar.
 * =================================================================== */

.rp-footer {
	background: var(--rp-surface-footer);
	padding: var(--rp-v-padding) var(--rp-page-margin);
	color: var(--rp-text-on-dark);
}

.rp-footer__inner {
	display: flex;
	flex-direction: column;
	gap: 48px;
	max-width: var(--rp-container-max);
	margin-inline: auto;
}

.rp-footer__columns {
	display: flex;
	flex-wrap: wrap;
	gap: 32px 171px;
}

.rp-footer__brand {
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: var(--rp-space-md);
	min-width: 200px;
	max-width: 250px;
}

.rp-footer__logo-text {
	color: var(--rp-text-on-dark);
	font-size: var(--rp-type-h2-size);
	font-weight: var(--rp-type-h2-weight);
	text-decoration: none;
}

.rp-footer .custom-logo {
	width: 100%;
	height: auto;
}

.rp-footer__socials {
	display: flex;
	align-items: center;
}

.rp-footer__social {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--rp-space-2xs);
	line-height: 0;
}

.rp-footer__social:focus-visible {
	outline: 2px solid var(--rp-text-on-dark-heading);
	outline-offset: 2px;
}

.rp-footer__cta {
	width: 100%;
}

.rp-footer__nav {
	display: flex;
	flex: 1 1 300px;
	flex-wrap: wrap;
	gap: 48px 39px;
}

.rp-footer__column {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-md);
	width: 180px;
}

.rp-footer__column--contact {
	width: 280px;
	gap: var(--rp-space-lg);
}

/* Figma: Heading/H4 Caps at 50% opacity. Opacity rather than a lightened hex,
 * so the one sand token stays the single source for this colour. */
.rp-footer__heading {
	margin: 0;
	color: var(--rp-text-on-dark-heading);
	font-size: var(--rp-type-h4-caps-size);
	font-weight: var(--rp-type-h4-caps-weight);
	line-height: 1;
	text-transform: uppercase;
	opacity: 0.5;
}

.rp-footer__links {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-sm);
	margin: 0;
	padding: 0;
	list-style: none;
}

.rp-footer__links a,
.rp-footer__contact a,
.rp-footer__contact-item span {
	color: var(--rp-text-on-dark);
	font-size: var(--rp-type-body-sm-size);
	line-height: var(--rp-type-body-sm-leading);
	text-decoration: none;
	opacity: 0.8;
}

.rp-footer__links a:hover,
.rp-footer__contact a:hover {
	opacity: 1;
	text-decoration: underline;
}

.rp-footer__contact {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-md);
	margin: 0;
	padding: 0;
	list-style: none;
}

.rp-footer__contact-item {
	display: flex;
	align-items: flex-start;
	gap: var(--rp-space-sm);
}

.rp-footer__contact-item img {
	flex: none;
	display: block;
	width: 18px;
	height: 18px;
}

/* ---- Legal bar ---- */

.rp-footer__legal {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--rp-space-md);
	padding-block-start: 40px;
	color: var(--rp-text-legal);
	font-size: var(--rp-type-body-xs-size);
	line-height: var(--rp-type-body-xs-leading);
}

.rp-footer__copyright,
.rp-footer__legal-links {
	margin: 0;
}

.rp-footer__legal-links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--rp-space-lg);
}

.rp-footer__legal-links a {
	color: inherit;
	text-decoration: none;
}

.rp-footer__legal-links a:hover {
	text-decoration: underline;
}

@media (max-width: 991px) {

	.rp-newsletter,
	.rp-footer {
		padding-inline: var(--rp-space-lg);
	}

	.rp-footer__columns {
		gap: 32px;
	}
}


/* ===================================================================
 * 12. The enquiry list
 *
 * Header heart + count, and the slide-out panel. Ported from the SvelteKit
 * SlideOutPanel / EnquiryPanel / CountBadge - no Figma frame draws any of it.
 *
 * The panel is closed by default and opened either by :target (no script) or
 * by .rp-panel--open (script). Both selectors drive the same rules, so the two
 * paths cannot look different.
 * =================================================================== */

.rp-enquiry-toggle {
	position: relative;
}

/* Count badge. A pill rather than a circle: two digits squash a 16px circle
 * and three break it, and an enquiry list reaches both. */
.rp-count-badge {
	position: absolute;
	top: 0;
	right: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-width: 16px;
	height: 16px;
	padding: 0 var(--rp-space-2xs);
	border-radius: 8px;
	background: var(--rp-colour-dark-green);
	color: var(--rp-text-on-dark);
	font-size: 11px;
	font-weight: var(--rp-font-weight-bold);
	line-height: 1;
	/* Proportional digits make the pill twitch as the number changes. */
	font-variant-numeric: tabular-nums;
}

.rp-count-badge--empty {
	display: none;
}

.rp-count-badge--pulse {
	animation: rp-count-pulse 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}

@keyframes rp-count-pulse {
	0%   { transform: scale(1); }
	40%  { transform: scale(1.35); }
	100% { transform: scale(1); }
}


/* ---- The panel ---- */

.rp-panel {
	position: fixed;
	inset: 0;
	z-index: 200;
	/* Closed, it must not swallow clicks meant for the page underneath. */
	pointer-events: none;
}

.rp-panel:target,
.rp-panel--open {
	pointer-events: auto;
}

.rp-panel__scrim {
	position: absolute;
	inset: 0;
	background: var(--rp-panel-scrim);
	opacity: 0;
	transition: opacity 0.35s ease;
}

.rp-panel:target .rp-panel__scrim,
.rp-panel--open .rp-panel__scrim {
	opacity: 1;
}

.rp-panel__sheet {
	position: absolute;
	inset-block: 0;
	right: 0;
	display: flex;
	flex-direction: column;
	box-sizing: border-box;
	width: var(--rp-panel-width);
	min-width: var(--rp-panel-min-width);
	max-width: 100vw;
	background: var(--rp-surface-panel);
	box-shadow: var(--rp-shadow-panel);
	transform: translateX(100%);
	transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.rp-panel:target .rp-panel__sheet,
.rp-panel--open .rp-panel__sheet {
	transform: translateX(0);
}

.rp-panel__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-shrink: 0;
	gap: var(--rp-space-sm);
	padding: 14px 12px 14px var(--rp-space-lg);
	background: var(--rp-panel-header-bg);
	color: var(--rp-text-on-dark);
}

.rp-panel__title {
	margin: 0;
	padding: 0;
	color: var(--rp-text-on-dark);
	font-family: var(--rp-font-family);
	font-size: 20px;
	font-weight: var(--rp-type-h2-weight);
	line-height: 1.2;
}

.rp-panel__close {
	display: flex;
	align-items: center;
	justify-content: center;
	/* 44px minimum touch target. */
	min-width: 44px;
	min-height: 44px;
	color: var(--rp-text-on-dark);
}

.rp-panel__close svg {
	display: block;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.rp-panel__body {
	flex: 1;
	overflow-y: auto;
	padding: 0 var(--rp-space-lg);
}

.rp-panel__empty {
	padding: 24px 0;
	font-family: var(--rp-font-family);
	color: var(--rp-text-body);
}


/* ---- A row in the panel ---- */

.rp-enquiry-item {
	display: grid;
	grid-template-columns: 88px minmax(0, 1fr);
	gap: var(--rp-space-md);
	align-items: start;
	padding: var(--rp-space-lg) 0;
	/* Warmer than the theme's greys, which go muddy on cream. */
	border-bottom: 1px solid var(--rp-panel-rule);
}

.rp-enquiry-item__image {
	display: block;
	width: 88px;
	height: 110px;
}

.rp-enquiry-item__image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.rp-enquiry-item__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--rp-space-xs);
}

.rp-enquiry-item__name {
	color: var(--rp-colour-ink);
	font-family: var(--rp-font-family);
	font-size: 17px;
	font-weight: var(--rp-font-weight-bold);
	line-height: 1.25;
	text-decoration: none;
	overflow-wrap: break-word;
}

.rp-enquiry-item__name:hover {
	text-decoration: underline;
}

.rp-enquiry-item__remove {
	flex-shrink: 0;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
	color: var(--rp-colour-primary-green);
}

.rp-enquiry-item__remove svg {
	display: block;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.rp-enquiry-item__meta {
	margin: 0;
	padding-top: var(--rp-space-2xs);
	font-family: var(--rp-font-family);
	font-size: var(--rp-type-body-sm-size);
	color: var(--rp-text-muted);
}


/* ---- The add control ---- */

/* The button is the form's only content, so the form must not introduce a box
 * of its own - the summary's action row lays these out. */
.rp-enquiry-add {
	display: contents;
}

/* "Added" keeps its colours: disabled here means "nothing left to do", not
 * "unavailable". */
.rp-btn--added {
	gap: 8px;
	opacity: 1;
	cursor: default;
}

.rp-btn__tick {
	display: inline-block;
	width: 18px;
	height: 18px;
	background-image: url("../icons/tick-white.svg");
	background-repeat: no-repeat;
	background-size: 18px 18px;
	background-position: center;
}

@media (max-width: 600px) {
	.rp-panel__sheet {
		width: 100vw;
		min-width: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.rp-panel__sheet,
	.rp-panel__scrim {
		transition: none;
	}

	.rp-count-badge--pulse {
		animation: none;
	}
}


/* ===================================================================
 * 13. Panel surface — generic, use it for any panel
 *
 * .rp-panel-surface is THE content panel: the enquiry form, Your Items, the
 * thank-you page, and whatever is built next. Named for what it is, not where it
 * first appeared — it was `.rp-enquiry-panel` until 10 August 2026, which is the
 * page-specific naming this file's own rules warn against.
 *
 * THE THREE-TONE STACK, and getting the order wrong is what made the SvelteKit
 * checkout look unlike the artwork:
 *
 *   page   --rp-surface-page    Light 3   the ground
 *   panel  --rp-surface-panel   Light 1   this
 *   input  --rp-surface-input   white     inputs, and only inputs
 *
 * **A panel is never white. An input is always white.** The panel reads as a
 * panel because it is a shade lighter than the page, not because it has a
 * border; the input reads as an input because it is lighter again. Make the
 * panel white and both distinctions collapse.
 *
 * Same reason .rp-btn--white must not go inside one: white on Light 1 has no
 * edge to read against. Use --green there.
 *
 * Sampled from Figma "9-Enquire Form" (383:53931). Full write-up:
 * rp2024-frontend/docs/panel-surface.md.
 * =================================================================== */

.rp-enquiry-page__columns {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--rp-space-lg);
	align-items: start;
}

/* Figma: the form is the narrower column and Your Items the wider. */
@media (min-width: 992px) {
	.rp-enquiry-page__columns {
		grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	}
}

.rp-panel-surface {
	box-sizing: border-box;
	padding: var(--rp-space-lg);
	background: var(--rp-surface-panel);
}

.rp-panel-surface--narrow {
	max-width: 640px;
}

.rp-panel-surface__title {
	margin: 0 0 var(--rp-space-sm);
	/* line-height: 1 below removes the half-leading a heading normally sits on,
	 * so the text sat tight against what follows. 10px puts it back. */
	padding: 0 0 var(--rp-space-xs);
	font-family: var(--rp-font-family);
	/* Heading/H3 - Inter Bold 20 - which is what the "9-Enquire Form" frame sets
	 * its H1 in. It was H4 semibold 18 here, a style that frame does not use.
	 *
	 * line-height 1 because Figma states every heading at lineHeight 100.
	 * Without it the browser falls back to `normal`, ~20% taller, which is what
	 * made the heading look wrong. */
	font-size: var(--rp-type-h3-size);
	font-weight: var(--rp-type-h3-weight);
	line-height: 1;
	color: var(--rp-colour-ink);
}

/**
 * Supporting paragraphs in a panel - the intro, "Or reset your password", "A
 * link will be sent to your email address".
 *
 * Direct children only. The fields are `<p class="rp-field">` inside .rp-form,
 * and 10px under every field row would loosen the whole form.
 */
.rp-panel-surface > p {
	padding-bottom: var(--rp-space-xs);
}

.rp-panel-surface__intro {
	margin: 0 0 var(--rp-space-lg);
	font-size: var(--rp-type-body-sm-size);
	line-height: var(--rp-type-body-sm-leading);
	color: var(--rp-colour-ink-muted);
}

.rp-panel-surface__actions {
	margin: 0;
}

/* Multi-line fields size by rows, so the shared input padding is all they need. */
.rp-field__input--area {
	resize: vertical;
}


/* ---- A line in Your Items ---- */

.rp-enquiry-line {
	display: grid;
	grid-template-columns: 110px minmax(0, 1fr);
	gap: var(--rp-space-md);
	align-items: start;
	padding: var(--rp-space-lg) 0;
	border-bottom: 1px solid var(--rp-panel-rule);
}

.rp-enquiry-line:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.rp-enquiry-line__image {
	display: block;
	width: 110px;
	height: 110px;
}

.rp-enquiry-line__image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.rp-enquiry-line__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--rp-space-xs);
}

.rp-enquiry-line__name {
	color: var(--rp-colour-ink);
	font-size: var(--rp-type-body-size);
	font-weight: var(--rp-font-weight-bold);
	line-height: 1.25;
	text-decoration: none;
	overflow-wrap: break-word;
}

.rp-enquiry-line__name:hover {
	text-decoration: underline;
}

.rp-enquiry-line__remove {
	flex-shrink: 0;
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
	color: var(--rp-colour-primary-green);
}

.rp-enquiry-line__remove svg {
	display: block;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.rp-enquiry-line__meta {
	margin: var(--rp-space-3xs) 0 0;
	font-size: var(--rp-type-body-sm-size);
	line-height: var(--rp-type-body-sm-leading);
	color: var(--rp-text-muted);
}

.rp-enquiry-line__comment {
	margin-top: var(--rp-space-xs);
}

/* The panel's link through to this page. */
.rp-panel__submit {
	margin: 0;
	padding: 22px 0 28px;
}

.rp-panel__submit .rp-btn {
	width: 100%;
	box-sizing: border-box;
}

/* Send to friend. Revealed by the checkbox rather than by script, so the fields
 * are reachable with JavaScript blocked like everything else on this page. */
.rp-friend {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-lg);
}

.rp-friend__fields {
	display: none;
	flex-direction: column;
	gap: var(--rp-space-lg);
}

.rp-friend:has( .rp-check__input:checked ) .rp-friend__fields {
	display: flex;
}

/* Without :has() the fields simply stay visible - usable, just not collapsed.
 * Better than hiding something the browser can never reveal. */
@supports not selector(:has(*)) {
	.rp-friend__fields {
		display: flex;
	}
}

/* A select is not an input; it needs the arrow room and the same metrics. */
select.rp-field__input {
	appearance: none;
	background-image: url("../icons/nav-chevron-down.svg");
	background-repeat: no-repeat;
	background-position: right var(--rp-space-sm) center;
	background-size: 10px;
	padding-right: calc(var(--rp-space-sm) * 2 + 10px);
}

/* ===================================================================
 * 15. Pending state
 *
 * The spinning house beside a button that has been pressed. Injected by
 * assets/js/pending.js on any navigating submit - see the head of that file.
 *
 * The animation is INSIDE assets/icons/spinner-house.svg. An SVG used as a
 * background-image renders as its own document and its CSS runs, so nothing
 * here rotates - which is the point: rotating an element would take its label
 * round with it.
 * =================================================================== */

.rp-pending {
	/* A fixed 30px slot at 20px of artwork, matching the SvelteKit forms, so a
	 * row does not jump when the spinner appears. */
	flex-shrink: 0;
	width: 30px;
	height: 30px;
	background-image: url("../icons/spinner-house.svg");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 20px 20px;
}

/* The button keeps its colours - it is working, not unavailable - but stops
 * inviting a second press. */
.rp-btn[aria-busy="true"] {
	cursor: progress;
	gap: 8px;                       /* the gap .rp-btn--added uses for its tick */
}

/* Inside a button (data-pending-inside), the spinner takes the tick's slot and
 * its metrics, so the working state and the finished state occupy exactly the
 * same space and the label does not shift between them. */
.rp-btn .rp-pending {
	width: 18px;
	height: 18px;
	background-size: 18px 18px;
}

/* A white house on the dark ground. Primary Green on Dark Green is nearly
 * invisible, which is what the default file draws.
 *
 * Scoped to --green rather than .rp-btn, deliberately: on the cream and white
 * colourways the green house is the one with contrast, so they keep it. */
.rp-btn--green .rp-pending {
	background-image: url("../icons/spinner-house-white.svg");
}

/* The spinner is injected as the button's next sibling, so the row holding it
 * has to be a flex row or the spinner drops below.
 *
 * ONLY the enquiry form's row is listed. .rp-summary__actions and
 * .rp-filters__actions are already flex with gaps of their own, and repeating
 * them here silently overrode those gaps - 20px became 15 on the product page
 * before this comment existed. Add a row here only if it is not already flex. */
.rp-panel-surface__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--rp-space-md);
}

/* ===================================================================
 * 16. Header search
 *
 * Ported from Menu2026/SearchBar.svelte. The bar wipes in over the nav row with
 * clip-path - no distortion, unlike animating width or scaleX.
 *
 * clip-path clips descendants, so .rp-search__results is a SIBLING of the
 * wiping form, not a child. Moving it inside hides the dropdown entirely.
 * =================================================================== */

.rp-search {
	position: absolute;
	inset-inline: var(--rp-page-margin);
	top: 0;
	bottom: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	/* Closed, clicks belong to the nav underneath. */
	pointer-events: none;
}

.rp-search__form {
	display: flex;
	align-items: center;
	gap: 14px;
	width: 100%;
	box-sizing: border-box;
	padding: 7px 0 6px;
	border-bottom: 1px solid rgb(62 60 53 / 45%);
	background: var(--rp-surface-panel);
	color: var(--rp-text-heading);
	clip-path: inset(0 0 0 100%);
	transition: clip-path 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.rp-search--open {
	pointer-events: auto;
}

.rp-search--open .rp-search__form {
	clip-path: inset(0 0 0 0);
}

.rp-search__input {
	flex: 1;
	min-width: 0;
	padding: 0;
	border: 0;
	outline: none;
	background: none;
	font-family: var(--rp-font-family);
	font-size: 20px;
	color: var(--rp-text-heading);
}

.rp-search__input::placeholder {
	color: rgb(62 60 53 / 60%);
}

/* The bar's glass: 22px and the form's own colour, matching the SvelteKit
 * search bar rather than the 28px green of the header row. */
.rp-search__form .rp-nav-icon {
	width: 22px;
	height: 22px;
	color: inherit;
}

.rp-search__close {
	display: flex;
	align-items: center;
	justify-content: center;
	/* 44px minimum touch target. */
	min-width: 44px;
	min-height: 44px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	color: var(--rp-text-heading);
}

.rp-search__close svg {
	display: block;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.6;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* The house again, so a loading state looks the same wherever it appears. */
.rp-search__spinner {
	flex-shrink: 0;
	width: 22px;
	height: 22px;
	background-image: url("../icons/spinner-house.svg");
	background-repeat: no-repeat;
	background-position: center;
	background-size: 18px 18px;
}

.rp-search__results {
	position: absolute;
	top: 100%;
	inset-inline: 0;
	z-index: 20;
	max-height: 420px;
	overflow-y: auto;
	pointer-events: auto;
	background: var(--rp-colour-white);
	border: 1px solid var(--rp-field-border);
	box-shadow: 0 12px 28px rgb(0 0 0 / 18%);
}

.rp-search__result {
	display: flex;
	align-items: center;
	gap: var(--rp-space-sm);
	padding: 8px 14px;
	color: var(--rp-colour-ink);
	text-decoration: none;
}

.rp-search__result:hover,
.rp-search__result:focus-visible {
	background: var(--rp-surface-panel);
}

.rp-search__result img {
	flex-shrink: 0;
	width: 50px;
	height: 50px;
	object-fit: contain;
}

.rp-search__result span {
	font-size: var(--rp-type-body-sm-size);
	line-height: 1.35;
}

.rp-search__empty {
	margin: 0;
	padding: var(--rp-space-lg);
	text-align: center;
	font-size: var(--rp-type-body-sm-size);
	color: var(--rp-text-muted);
}

/* ---- The results page ---- */

.rp-search__count {
	margin: 0 0 var(--rp-space-lg);
	font-size: var(--rp-type-body-sm-size);
	color: var(--rp-text-muted);
}

.rp-search__empty-page {
	padding: var(--rp-space-xl) 0;
	font-size: var(--rp-type-body-size);
	color: var(--rp-text-body);
}

@media (prefers-reduced-motion: reduce) {
	.rp-search__form {
		transition: none;
	}
}

/* ===================================================================
 * 17. The View arrow
 *
 * template-parts/view-arrow.php. Ported from the SvelteKit components/ViewArrow,
 * including the reasoning - read that file's header before changing this.
 *
 * It was an <img> in all three callers, and NOTHING INSIDE AN <img> CAN BE
 * ANIMATED - it is a separate document. The shaft and head are two paths in the
 * page now so the hover below can exist at all. Do not put it back in an <img>.
 * =================================================================== */

.rp-arrow {
	/* A bare inline <svg> picks up the baseline gap, and the flex row it sits in
	 * would otherwise squeeze it. */
	display: block;
	flex-shrink: 0;

	/* The extended shaft overhangs the 9px box. SVG defaults to overflow:hidden,
	 * which clips the tip mid-animation. */
	overflow: visible;
}

/* transform-box: view-box puts transform-origin in viewBox units, so these read
 * as the coordinates in the path data rather than as percentages of a box whose
 * size the caller picks. */
.rp-arrow__shaft,
.rp-arrow__head {
	transform-box: view-box;

	/* Out and back at different speeds: 260ms leaving so it arrives softly,
	 * 180ms returning so the card is not still finishing after the pointer has
	 * gone. */
	transition: transform 180ms ease-out;
}

.rp-arrow__shaft {
	/* The tail end - the shaft grows away from it, so the gap to the word "View"
	 * never moves. */
	transform-origin: 1px 5.5px;
}

/**
 * A pointer that can hover. Without the query the transform latches on after a
 * tap and every card in the grid stays stuck in its hover state - `:hover` has
 * no counterpart to "the finger left" on touch.
 *
 * `a:hover` and not a class, because the trigger is whichever link this sits
 * inside: the whole category card, and the whole tile in Be Inspired. **The
 * arrow answers the card's hover, not its own** - a 9px target is too small to
 * be the thing you have to hit, and the card is one link anyway.
 */
@media (hover: hover) {
	a:hover .rp-arrow__shaft {
		/* 9 units of shaft become 12.15. The head moves the same 3.15 so the
		 * two stay joined. */
		transform: scaleX(1.35);
		transition-duration: 260ms;
		transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
	}

	a:hover .rp-arrow__head {
		transform: translateX(3.15px);
		transition-duration: 260ms;
		transition-timing-function: cubic-bezier(0.22, 0.61, 0.36, 1);
	}
}

/* Decoration - it communicates no state the card does not already say in words -
 * so it is dropped rather than shortened. */
@media (prefers-reduced-motion: reduce) {
	.rp-arrow__shaft,
	.rp-arrow__head {
		transition: none;
	}

	a:hover .rp-arrow__shaft,
	a:hover .rp-arrow__head {
		transform: none;
	}
}


/* ===================================================================
 * 18. Delivery calculator
 *
 * template-parts/delivery-calculator.php + assets/js/delivery.js. Figma
 * "7-Product Variation 3" (381:52524), node 419:82250 - the same panel at all
 * three frames, only the column width changes.
 *
 * It is a .rp-panel-surface with this frame's own metrics on top: 20/24 padding
 * where the generic panel is 20 all round, a 1px border, and a uniform 24px gap
 * between all five blocks.
 *
 * EVERY DISPLAY RULE IS SCOPED :not([hidden]). The template renders the panel,
 * the estimate and the map hidden and the script un-hides them - and an author
 * `display` beats the UA rule behind the hidden attribute, so an unscoped
 * `display: flex` here would leave all three permanently visible.
 * =================================================================== */

.rp-delivery:not([hidden]) {
	display: flex;
	flex-direction: column;
	gap: var(--rp-delivery-gap);
	padding: var(--rp-delivery-pad-y) var(--rp-delivery-pad-x);
	border: 1px solid var(--rp-delivery-border);

	/* The button row owns no space below it, so the whole gap is here. */
	margin-block-start: var(--rp-delivery-space-above);

	/* Body/Regular, RESTATED - the panel sits inside .rp-summary, which sets
	 * Heading/H4 18 semibold on everything under it. Set once at the panel
	 * boundary rather than on every text rule inside; the blocks that are not
	 * Body/Regular (both headings and the cost) state their own. */
	font-size: var(--rp-type-body-size);
	font-weight: var(--rp-font-weight-regular);
	line-height: var(--rp-type-body-leading);
	color: var(--rp-colour-ink);
}

/* The toggle is rendered hidden and un-hidden by the script, so a blocked one
 * leaves no dead control. .rp-btn is inline-flex, which outranks [hidden]. */
.rp-delivery-toggle[hidden] {
	display: none;
}

/* The panel's own 24px gap is the only spacing between blocks - the shared
 * title carries a margin and a padding that would add to it. */
.rp-delivery > .rp-panel-surface__title {
	margin: 0;
	padding: 0;
}

/* Figma draws this field with a 4px radius and a 5px inset, where the form
 * standard is radius 0 and 8/12. Different frame, different component - see
 * "Forms - the standard" in CLAUDE.md before unifying them. */
/* padding: 0 is not redundant. `.rp-panel-surface > p` adds 10px to direct-child
 * paragraphs - the enquiry form escapes it by nesting its fields in .rp-form,
 * and these two are direct children. The panel's 24px gap is the only spacing
 * here. */
.rp-delivery__field {
	margin: 0;
	padding: 0;
}

.rp-delivery__input {
	padding: var(--rp-delivery-field-pad);
	border: 1px solid var(--rp-delivery-border);
	border-radius: var(--rp-delivery-radius);
	font-size: var(--rp-type-body-lg-size);
	line-height: var(--rp-type-body-lg-leading);
}

/* The house is animated inside the SVG, so nothing here rotates an element -
 * same file and same reason as the site-wide pending spinner. */
.rp-delivery__input--pending {
	padding-right: 40px;
	background-image: url(../icons/spinner-house.svg);
	background-repeat: no-repeat;
	background-position: right 10px center;
	background-size: 24px 24px;
}

/* The shipping-class notice and the out-of-range message. Brand green with a
 * white body and the logo brown for links - straight off the frame. This is
 * NOT the yellow warning component /delivery and checkout use. */
.rp-delivery__notice {
	padding: var(--rp-delivery-field-pad);
	border-radius: var(--rp-delivery-radius);
	background: var(--rp-colour-primary-green);
	color: var(--rp-colour-white);
}

.rp-delivery__notice > *:first-child {
	margin-top: 0;
}

.rp-delivery__notice > *:last-child {
	margin-bottom: 0;
}

.rp-delivery__notice a {
	color: var(--rp-colour-primary-brown);
	text-decoration: underline;
	word-break: break-word;
}

.rp-delivery__estimate:not([hidden]) {
	display: flex;
	flex-direction: column;
	gap: var(--rp-space-xs);
}

/* Heading/H3, and line-height 1 because Figma states every heading at 100%. */
.rp-delivery__estimate-title {
	margin: 0;
	padding: 0;
	font-size: var(--rp-type-h3-size);
	font-weight: var(--rp-type-h3-weight);
	line-height: 1;
	color: var(--rp-colour-ink);
}

/* Long addresses have no spaces to break on in the middle of a street name. */
.rp-delivery__lines {
	margin: 0;
	word-break: break-word;
}

/* The frame's "Line 3" - the same 0.5px hairline that brackets the description. */
.rp-delivery__rule {
	height: 0;
	margin: 0;
	border: 0;
	border-top: 0.5px solid var(--rp-delivery-rule);
}

/* Heading/H3 Caps. */
.rp-delivery__cost {
	margin: 0;
	font-size: var(--rp-type-h3-caps-size);
	font-weight: var(--rp-type-h3-caps-weight);
	line-height: 1;
	text-transform: uppercase;
	color: var(--rp-colour-ink);
}

.rp-delivery__error {
	margin: 0;
	padding: 0;
	color: var(--rp-colour-error);
}

/* Fixed ratio rather than a fixed height: at 768 and 402 the column is narrow
 * enough that a 400px map would be most of the panel. */
.rp-delivery__map:not([hidden]) {
	display: block;
	width: 100%;
	aspect-ratio: var(--rp-delivery-map-ratio);
	border-radius: var(--rp-delivery-radius);
	overflow: hidden;
}


/* ===================================================================
 * 19. Brochure page blocks
 *
 * inc/page-blocks.php + template-parts/blocks/. /delivery and its siblings.
 *
 * NO FIGMA FRAME DRAWS THESE. figma-todo.md section 14 records that the 2026
 * artwork has no delivery page - the calculator moved onto the product page and
 * /delivery was never redrawn. So this composes from the theme's settled parts
 * rather than inventing a look, and every background colour is content-managed.
 * =================================================================== */

/* A full-bleed band. Each carries its own background from ACF, so it cannot sit
 * inside .rp-container - the colour would be inset from the page edge. Same
 * arrangement the home sections use. */
.rp-band {
	padding-block: var(--rp-band-pad-y);
}

/* Consecutive bands of the same colour would otherwise read as one block with a
 * double gap down the middle. */
.rp-band + .rp-band {
	padding-block-start: 0;
}

/* Display/Page Title - Nuosu SIL 40, the second typeface. The webfont loader
 * already fetches it for the home page. */
.rp-page-heading__title {
	margin: 0 0 var(--rp-space-lg);
	font-family: var(--rp-page-title-family);
	font-size: var(--rp-page-title-size);
	font-weight: var(--rp-font-weight-regular);
	line-height: 1.1;
	color: var(--rp-colour-ink);
}

.rp-page-heading__content {
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
	color: var(--rp-colour-ink-muted);
}

.rp-page-heading__content > *:first-child { margin-top: 0; }
.rp-page-heading__content > *:last-child { margin-bottom: 0; }

.rp-delivery-block__intro {
	margin-bottom: var(--rp-space-lg);
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
	color: var(--rp-colour-ink-muted);
}

/* The panel is a form, so it takes the form width rather than the full column -
 * "A form is not page-wide" in CLAUDE.md. */
.rp-delivery-block .rp-delivery {
	max-width: 640px;
	margin-block-start: 0;
}

/* ---- FAQs ---- */

.rp-faqs__inner--split {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: var(--rp-space-xl);
	align-items: start;
}

@media (min-width: 992px) {
	.rp-faqs__inner--split {
		grid-template-columns: var(--rp-faq-media-width) minmax(0, 1fr);
	}
}

.rp-faqs__media img {
	display: block;
	width: 100%;
	height: auto;
}

.rp-faqs__text {
	margin-bottom: var(--rp-space-lg);
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
	color: var(--rp-colour-ink-muted);
}

/* Native <details>, the same mechanism as the [read_more] shortcode: state,
 * keyboard handling and screen-reader semantics for free, no script, and it
 * works with JavaScript off. */
.rp-faq {
	border-block-end: 1px solid var(--rp-panel-rule);
}

.rp-faq__question {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--rp-space-md);
	padding-block: var(--rp-faq-gap);
	cursor: pointer;
	font-size: var(--rp-type-h4-size);
	font-weight: var(--rp-type-h4-weight);
	line-height: 1.2;
	color: var(--rp-colour-ink);

	/* The default triangle is replaced by the chevron below. */
	list-style: none;
}

.rp-faq__question::-webkit-details-marker {
	display: none;
}

/* Drawn with CSS so it stays out of the accessible tree - <summary> already
 * announces its own expanded state. */
.rp-faq__question::after {
	content: "";
	flex-shrink: 0;
	width: 10px;
	height: 10px;
	border-right: 2px solid var(--rp-colour-primary-green);
	border-bottom: 2px solid var(--rp-colour-primary-green);
	transform: rotate(45deg) translate(-2px, -2px);
	transition: transform 150ms ease-in-out;
}

.rp-faq[open] .rp-faq__question::after {
	transform: rotate(-135deg) translate(-2px, -2px);
}

.rp-faq__answer {
	padding-block-end: var(--rp-space-lg);
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
	color: var(--rp-colour-ink-muted);
}

.rp-faq__answer > *:first-child { margin-top: 0; }
.rp-faq__answer > *:last-child { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
	.rp-faq__question::after { transition: none; }
}

/* The delivery page's item-size select. Same field metrics as the address
 * input beside it. */
.rp-delivery__select {
	padding: var(--rp-delivery-field-pad);
	border: 1px solid var(--rp-delivery-border);
	border-radius: var(--rp-delivery-radius);
	font-size: var(--rp-type-body-lg-size);
	line-height: var(--rp-type-body-lg-leading);
	font-weight: var(--rp-font-weight-regular);
}

/* The delivery PAGE runs both fields at Body/Regular 16, not the panel's
 * Body/Large 18.
 *
 * The 18 is Figma's, and it belongs to the PRODUCT panel only - Address.svelte's
 * own style is 16 and DeliveryCalculator.svelte overrides it from outside for
 * that frame. DeliveryPage.svelte applies no such override, and its item-size
 * select is 16 too (DeliveryPage.svelte:39). No frame draws this page, so the
 * frontend is the source here. */
.rp-delivery--page .rp-delivery__input,
.rp-delivery--page .rp-delivery__select {
	font-size: var(--rp-type-body-size);
	line-height: var(--rp-type-body-leading);
}

/* On a band page the gap below the trail is the first band's own 80px top
 * padding - the component's 40 would add to it. */
.rp-page .rp-breadcrumb {
	margin-bottom: 0;
}

/* The band under the trail closes to the breadcrumb's own 40, not the 80px band
 * rhythm - Figma puts the next block 40px below the breadcrumb, which is what
 * --rp-breadcrumb-space-after is. Every later band keeps the 80. */
.rp-page__crumbs + .rp-band {
	padding-block-start: var(--rp-breadcrumb-space-after);
}


/* ===================================================================
 * 20. Links in authored copy
 *
 * NOT a global `a` rule. Most links on this site are not text links - the whole
 * card, the nav, .rp-btn, the breadcrumb, the View arrow - and colouring or
 * underlining those would wreck them. So this covers only the containers that
 * hold WordPress-authored HTML, where a link falls back to the browser's blue
 * and purple.
 *
 * ADD NEW EDITOR-CONTENT CONTAINERS TO THIS LIST. They are the same ones that
 * carry a `> *:first-child` margin reset, for the same reason: nobody controls
 * what the editor puts in them.
 * =================================================================== */

.rp-product__description a,
.term-description a,
.rp-page-heading__content a,
.rp-delivery-block__intro a,
.rp-faqs__text a,
.rp-faq__answer a,
.rp-account__note a {
	color: var(--rp-link);

	/* Underlined, so the link is distinguishable from body text by more than
	 * colour - which is what WCAG 1.4.1 asks for and what lets the visited
	 * state below be dropped safely. */
	text-decoration: underline;

	/* Emails and long URLs are most of the authored links on this site and they
	 * have nowhere to break. */
	word-break: break-word;
}

.rp-product__description a:hover,
.term-description a:hover,
.rp-page-heading__content a:hover,
.rp-delivery-block__intro a:hover,
.rp-faqs__text a:hover,
.rp-faq__answer a:hover,
.rp-account__note a:hover {
	color: var(--rp-link-hover);
}

/**
 * VISITED IS THE SAME COLOUR, deliberately.
 *
 * The palette has no visited colour, and browsers restrict :visited so heavily
 * - a handful of properties, and getComputedStyle deliberately lies about it -
 * that a second colour buys little. On a catalogue where most authored links
 * are products and carriers, a purple trail is noise.
 *
 * The cost is orientation on link-dense pages, and the underline above is what
 * pays for it: these links never rely on colour alone.
 *
 * An author `a` rule already beats the UA's a:visited on cascade origin, so
 * this is a statement of intent rather than a fix - keep it, or the next person
 * wonders whether purple was overlooked.
 */
.rp-product__description a:visited,
.term-description a:visited,
.rp-page-heading__content a:visited,
.rp-delivery-block__intro a:visited,
.rp-faqs__text a:visited,
.rp-faq__answer a:visited,
.rp-account__note a:visited {
	color: var(--rp-link);
}
