/* =========================================================
   Satueen — design tokens
   ========================================================= */
:root {
	/* Brand palette (from Satueen Brand Guideline) */
	--color-bg: #eef3f8;          /* pale blue page base */
	--color-bg-soft: #dee5ed;     /* brand pale blue — alt sections / product bg */
	--color-band: #ececec;        /* neutral grey — welcome band + founders quote panels */
	--color-blush: #e6ecf3;       /* soft cool neutral */
	--color-ink: #131313;         /* near-black */
	--color-ink-soft: rgba(19, 19, 19, 0.66);
	--color-ink-faint: rgba(19, 19, 19, 0.45);
	--color-border: #cdd8e4;      /* cool hairline */
	--color-sand: #cfb59e;        /* warm tan accent */
	--color-green: #39513b;       /* deep brand green */
	--color-blue: #dee5ed;        /* pale brand blue */
	--color-accent: #506277;      /* slate-blue logo color (links/brand) */
	--color-accent-dark: #3e4d5e;
	--color-accent-soft: rgba(80, 98, 119, 0.08);
	--color-dark: #211b16;        /* warm near-black for dark bands */
	--color-navy: #1c2836;        /* deep slate blue, footer — darkened --color-accent */
	--color-sale: #b0492f;        /* terracotta sale price */
	--color-on-accent: #ffffff;

	/* Instrument Serif is the sitewide display face as of 2026-09-14; Noto Serif
	   was retired and is no longer loaded. IMPORTANT: Instrument Serif ships
	   REGULAR AND ITALIC ONLY — there is no bold or medium cut. Any font-weight
	   above 400 on a serif heading gets the browser's synthetic bold, which
	   smears the face's high-contrast strokes. Set weight 400 and size for
	   emphasis instead. */
	--font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
	--font-base: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
	/* Now the same face as --font-display. Kept as a separate token because 44
	   rules point at it and the hero may want to diverge again later; collapsing
	   them would make that a 44-rule edit rather than a one-line one. */
	--font-hero: 'Instrument Serif', Georgia, 'Times New Roman', serif;
	/* Formal copperplate script, used for the single word above the hero
	   headline and nowhere else. One weight only. Set it in sentence case --
	   script capitals are drawn to start a word, and a run of them is unreadable. */
	--font-script: 'Pinyon Script', 'Snell Roundhand', 'Apple Chancery', cursive;

	--radius-sm: 6px;
	--radius-md: 14px;
	--radius-pill: 999px;

	--container-width: 1320px;
	--section-pad: clamp(48px, 8vw, 104px);
	--gutter: clamp(20px, 4vw, 40px);

	/* Announcement bar height. Both the bar and the header stick to the top,
	   so the header's sticky offset has to match this exactly or the two
	   overlap. Change it here, not on the bar. */
	--announcement-h: 38px;
	/* The header's rendered height (16px padding + 36px icon row + 1px rule). It is
	   the same at every width. The homepage hero is pulled up by exactly this
	   much to sit under the transparent header -- change one, change the other. */
	--header-h: 69px;
}

/* =========================================================
   Reset / base
   ========================================================= */
* { box-sizing: border-box; }
html {
	scroll-behavior: smooth;
	/* Nothing may scroll the page sideways into blank space -- full-bleed bands,
	   marquee tracks and off-screen panels all get clipped at the window edge.
	   'clip' rather than 'hidden' on purpose: hidden would turn the root into a
	   scroll container and break the sticky header. Sections that scroll
	   horizontally on purpose (best sellers, marquees) have their own
	   overflow and are unaffected. */
	overflow-x: clip;
}
body {
	margin: 0;
	font-family: var(--font-base);
	color: var(--color-ink);
	background: var(--color-bg);
	font-size: 16px;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}
/* Pages listed in functions.php (body_class filter) sit on white. */
/* On a white page the page-colour token itself is white, so every block that
   paints itself with var(--color-bg) follows without a rule of its own. */
body.is-white-page { --color-bg: #fff; background: #fff; }
/* The "Behind <brand>" story band on a brand's page uses the deeper soft blue;
   on a white page it joins the page. */
body.is-white-page .brand-story { background: #fff; }
img { max-width: 100%; display: block; height: auto; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p { margin: 0; }
button { font-family: inherit; cursor: pointer; background: none; border: none; padding: 0; color: inherit; }
input { font-family: inherit; }

h1, h2 {
	font-family: var(--font-display);
	/* 400, not 500: Instrument Serif has no medium cut, so 500 rendered as
	   synthetic bold. See the --font-display note in :root. */
	font-weight: 400;
	letter-spacing: -0.01em;
	line-height: 1.04;
}
h1 { font-size: clamp(40px, 5.5vw, 76px); }
h2 { font-size: clamp(28px, 3.4vw, 44px); }
h3 { font-size: 18px; font-weight: 600; }

.container {
	max-width: var(--container-width);
	margin: 0 auto;
	padding: 0 var(--gutter);
}
.section { padding-block: var(--section-pad); }
.section__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: 32px;
}
.section__head h2 { text-transform: lowercase; }

.highlight {
	background: var(--color-accent-soft);
	color: var(--color-accent-dark);
	padding: 0.05em 0.3em;
	border-radius: 0.2em;
}

/* =========================================================
   Buttons
   ========================================================= */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 14px 28px;
	border-radius: var(--radius-pill);
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	border: 1px solid transparent;
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.btn--primary { background: var(--color-ink); color: #fff; }
.btn--primary:hover { background: var(--color-accent-dark); }
.btn--outline { background: transparent; color: var(--color-ink); border-color: var(--color-ink); }
.btn--outline:hover { background: var(--color-ink); color: #fff; }
.btn--outline-light { background: transparent; color: #fff; border-color: rgba(255,255,255,0.6); }
.btn--outline-light:hover { background: rgba(255,255,255,0.12); }
.btn--ghost { background: var(--color-accent-soft); color: var(--color-accent-dark); }
.btn--ghost:hover { background: var(--color-accent); color: #fff; }
.btn--sm { padding: 10px 20px; font-size: 13px; }

/* =========================================================
   Placeholder images
   ========================================================= */
.satueen-img--placeholder { filter: saturate(0.9); }

/* =========================================================
   Announcement bar + Header
   ========================================================= */
.announcement-bar {
	/* Pure black, not --color-ink: the homepage film under the clear header is
	   black at its top edge, and anything lighter shows as a seam between them. */
	background: #000;
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0 var(--gutter);
	/* Sticks along with the header: the bar pins at the very top and the
	   header pins directly beneath it (top: var(--announcement-h)). Sits one
	   above the header so nothing can paint over it as content scrolls under. */
	position: sticky;
	top: 0;
	z-index: 51;
}
.announcement-bar__viewport {
	position: relative;
	flex: 1;
	height: var(--announcement-h);
	overflow: hidden;
}
.announcement-bar__msg {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.03em;
	opacity: 0;
	transition: opacity 0.4s ease;
	pointer-events: none;
}
.announcement-bar__msg.is-active { opacity: 1; }
/* The offer itself -- "10% discount", "free shipping" -- underlined. Thin and
   set off the baseline, so it reads as emphasis rather than as a link. */
.announcement-bar__msg > span,
.announcement-bar__msg u {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
}

.site-header {
	position: sticky;
	/* Parked below the sticky announcement bar rather than at 0, so the two
	   stack instead of overlapping. */
	top: var(--announcement-h);
	z-index: 50;
	background: #fff;
	border-bottom: 1px solid var(--color-border);
}
.site-header__inner {
	/* Full-bleed rather than capped at --container-width, so the nav sits hard
	   left and the icons hard right instead of drifting inward on wide screens. */
	max-width: none;
	margin: 0;
	padding: 16px var(--gutter);
	position: relative;
	display: grid;
	/* Equal side columns with the logo in the middle: the two 1fr tracks are the
	   same width by definition, so the logo stays exactly page-centred, and --
	   unlike the absolutely-positioned version this replaces -- the nav and the
	   icons now have their own space reserved. They can no longer silently paint
	   on top of the logo. */
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 24px;
}
/* Without this the side tracks refuse to shrink below their content and the
   logo gets pushed off centre. */
.site-header__inner > * { min-width: 0; }
.site-logo-text {
	font-size: 22px;
	font-weight: 700;
	letter-spacing: 0.02em;
	font-style: italic;
}
.custom-logo-link { display: inline-flex; align-items: center; }
.custom-logo { height: 30px; width: auto; }
/* The uploaded wordmark is a slate-blue PNG. Flattened to black here rather
   than swapped for another file, so it stays one upload; the homepage's clear
   header turns the same drawing white further down. */
.site-header .custom-logo { filter: brightness(0); }
/* All header items share row 1 so the logo lines up with nav + icons.
   (DOM order places branding before nav, so without an explicit row the
   grid auto-flow would bump nav/icons onto a second row.) */
.site-header__inner .menu-toggle   { grid-row: 1; grid-column: 1; display: none; }
/* Hamburger + bar links share one cell and lay out against each other in flex,
   so the icon sits hard left and the links follow it. */
.site-header__inner .site-header__left {
	grid-row: 1;
	grid-column: 1;
	justify-self: start;
	display: flex;
	align-items: center;
	gap: 28px;
}
.site-header__inner .site-branding {
	grid-row: 1;
	grid-column: 2;
	justify-self: center;
	display: flex;
	align-items: center;
	justify-content: center;
}
.site-header__inner .header-icons  { grid-row: 1; grid-column: 3; justify-self: end; }

/* --- Homepage: see-through header --------------------------------------
   On the front page the header never has a solid ground of its own while it
   is simply sitting there. It has two idle looks, and main.js picks between
   them with one class:

     over the hero      no background at all, everything in it white -- the
                        film runs behind it, at the top of the page and for as
                        long as any of the hero is still under the header;
     .is-past-hero      the rest of the page is pale, so the type goes back to
                        ink and the header becomes frosted glass: a wash of the
                        page blue with a blur behind it. Fully clear here would
                        put dark nav straight on top of whatever dark text is
                        scrolling underneath, and neither could be read.

   It turns into the ordinary solid bar only while it is in use: under a mouse
   (.is-hovered, from main.js -- not :hover, which on a touch screen stays
   stuck to the header after a tap), while a dropdown, the search panel or the
   currency list is open, on keyboard focus, and while the mobile menu is open.
   Every other page keeps the solid bar throughout.

   The header itself is untouched -- still sticky, still 69px in the flow. The
   overlap comes from the hero being pulled up underneath it (see .hero), so
   nothing that measures or pins the header has to know about any of this.

   The idle selector is written out per rule rather than hung on one state
   class: the clear state has to be what the page first paints with, before
   any script has run, or the header flashes solid on every load. A browser
   without :has() drops these rules whole and simply keeps the solid header. */
body.home .site-header {
	transition: background-color 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
body.home .site-header .custom-logo { transition: filter 0.3s ease; }
html:not(.mobile-nav-is-open) body.home .site-header:not(.is-past-hero):not(.is-hovered):not(:has(:focus-visible, .nav-dropdown-panel.is-open, .header-search:not([hidden]), .header-currency[open])) {
	background-color: transparent;
	border-bottom-color: transparent;
	color: #fff;
}
html:not(.mobile-nav-is-open) body.home .site-header:not(.is-past-hero):not(.is-hovered):not(:has(:focus-visible, .nav-dropdown-panel.is-open, .header-search:not([hidden]), .header-currency[open])) :is(.nav-menu a, .menu-panel-toggle, .menu-toggle, .header-icon-btn, .header-currency, .header-currency__code, .site-logo-text) {
	color: #fff;
}
html:not(.mobile-nav-is-open) body.home .site-header:not(.is-past-hero):not(.is-hovered):not(:has(:focus-visible, .nav-dropdown-panel.is-open, .header-search:not([hidden]), .header-currency[open])) .header-currency__caret { color: rgba(255, 255, 255, 0.7); }
/* The wordmark is a navy PNG; flattened to black and inverted it is the same
   drawing in white, without shipping a second file. */
html:not(.mobile-nav-is-open) body.home .site-header:not(.is-past-hero):not(.is-hovered):not(:has(:focus-visible, .nav-dropdown-panel.is-open, .header-search:not([hidden]), .header-currency[open])) .custom-logo { filter: brightness(0) invert(1); }
/* Past the hero. backdrop-filter also makes the header the containing block
   for any position: fixed child -- harmless here only because this rule is
   switched off while the mobile menu (the one fixed panel in the header's
   orbit) is open. Keep that exclusion if this selector is ever rewritten. */
html:not(.mobile-nav-is-open) body.home .site-header.is-past-hero:not(.is-hovered):not(:has(:focus-visible, .nav-dropdown-panel.is-open, .header-search:not([hidden]), .header-currency[open])) {
	/* White glass, not the page's pale blue: the sheet under it starts white,
	   and a blue tint read as a grey band across it. Mostly clear, so whatever
	   passes underneath shows through softened; the heavy saturation is what
	   keeps colour alive through the blur instead of washing to milk. The
	   inset top line is the lit edge of the pane, and the hairline + soft drop
	   underneath are what let the bar still read as a bar on a white page,
	   where the fill alone would disappear. */
	background-color: rgba(255, 255, 255, 0.58);
	border-bottom-color: rgba(19, 19, 19, 0.07);
	-webkit-backdrop-filter: blur(22px) saturate(1.8);
	backdrop-filter: blur(22px) saturate(1.8);
	box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.75), 0 10px 30px -18px rgba(19, 19, 19, 0.22);
}

/* The nav sat almost against the wordmark. Breathing room is added by widening
   the grid's own gap rather than padding the nav, so the two 1fr tracks stay
   equal and the logo stays page-centred. Gated behind a min-width because the
   gap comes straight out of the side tracks (each takes half of it), and the
   left track has to hold the hamburger plus the menu's ~500px natural width
   or the links wrap to two lines. So it runs only from 1400px -- the width at
   which the bar exists at all -- and it has to sit AFTER the base
   .site-header__left rule, which is equally specific and would otherwise win
   on source order. */
@media (min-width: 1400px) {
	.site-header__inner { gap: clamp(36px, 3vw, 96px); }
	/* The room for that gap is bought back from inside the left track: the bar's
	   own spacing drops 28px -> 20px, which frees ~30px across the five links
	   plus the hamburger and keeps the menu on one line down at 1400. */
	.site-header__inner .site-header__left { gap: 20px; }
	.site-header__inner .primary-nav .nav-menu { gap: 20px; }
}

.nav-menu, .mobile-nav__menu { display: flex; gap: 28px; }
.nav-menu a, .mobile-nav__menu a {
	font-size: 13px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.06em;
}
/* Matched to .hero__cta -- 12px at weight 500, where this was 13px at 600. Both
   were already Plus Jakarta Sans, uppercase, tracked at 0.06em, so size and
   weight were the whole difference between the nav and the hero buttons.
   Desktop only: the mobile drawer keeps 13px/600 above, since 12px at weight
   500 is too light for a full-screen touch menu. */
.nav-menu a {
	font-size: 12px;
	font-weight: 500;
}
.nav-menu a:hover { color: var(--color-accent); }

.nav-menu li { position: relative; }
/* Every top-level item is laid out the same way, dropdown or not. Before, only
   the items with a chevron were flex-centred and the plain links sat on the
   text baseline, which left Shops and Brands 1.5px higher than their
   neighbours. */
.nav-menu > li { display: inline-flex; align-items: center; }
.nav-menu > li > a { display: block; }
.nav-menu > .menu-item-has-children > .sub-menu { display: none; }
.nav-menu .menu-item-has-children { display: inline-flex; align-items: center; gap: 2px; }
.nav-dropdown-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
	padding: 4px;
	margin: -4px -4px -4px -2px;
	cursor: pointer;
	color: currentColor;
}
.nav-dropdown-toggle svg {
	width: 12px;
	height: 12px;
	transition: transform 0.2s ease;
}
.nav-menu .menu-item-has-children.is-open .nav-dropdown-toggle svg {
	transform: rotate(180deg);
}

/* Desktop nav dropdowns: click-to-open (see main.js), rendered as a
   full-width panel in normal flow so it pushes page content down rather
   than overlaying it. */
.nav-dropdown-panel {
	display: none;
	/* Overlays the page from under the header instead of sitting in the flow,
	   so opening a dropdown never pushes the hero down. */
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 49;
	width: 100%;
	background: #fff;
	border-top: 1px solid var(--color-border);
	border-bottom: 1px solid var(--color-border);
}
.nav-dropdown-panel.is-open { display: block; }
.nav-dropdown-panel .sub-menu {
	display: flex;
	flex-direction: column;
	gap: 4px;
	/* Full-bleed like the header, so links line up under the nav itself. */
	max-width: none;
	margin: 0;
	padding: 24px var(--gutter) 32px;
}
.nav-dropdown-panel .sub-menu a {
	display: inline-block;
	padding: 6px 0;
	font-size: 15px;
	font-weight: 500;
	text-transform: none;
	letter-spacing: normal;
}
.nav-dropdown-panel .sub-menu a:hover { color: var(--color-accent); }

/* --- Shops dropdown: category tiles ---------------------------------
   One row of full-bleed images with the category name and a line of copy
   set over the foot of each, rather than the plain link list the other
   dropdowns use. */
/* No bottom hairline here. The base panel draws one to separate its own
   background from the page beneath, but this variant has no background left
   showing -- the tiles run edge to edge and butt against the foot -- so the
   border reads as a pale line ruled across the bottom of the photographs.
   The list dropdowns keep theirs; there the panel really does end in flat
   colour and needs the edge. */
.nav-dropdown-panel--tiles {
	background: #fff;
	border-bottom: 0;
}
/* Grid rather than the flex row the other dropdowns use: auto-flow columns
   sized 1fr each divides the full width exactly, whatever the tile count, with
   nothing left over to show as a gap between the frames. */
.nav-dropdown-panel--tiles .sub-menu {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	/* Edge to edge and butted together, matching the reference -- no gutter
	   padding and no gap between the frames. */
	width: 100%;
	margin: 0;
	padding: 0;
	gap: 0;
}
.nav-dropdown-panel--tiles .sub-menu > li { min-width: 0; }

/* Selector carries .sub-menu and the a element on purpose: the generic
   .nav-dropdown-panel .sub-menu a rule above is three classes deep, and
   anything lighter loses to its display: inline-block -- which sizes the tile
   from its own height instead of filling the column, leaving a band of panel
   background either side of every frame. */
.nav-dropdown-panel--tiles .sub-menu a.nav-tile {
	position: relative;
	display: block;
	/* Explicit width and height rather than an aspect ratio: an aspect-ratio box
	   whose height is capped derives its width back from that cap, which is what
	   pulled the frames in off their columns. */
	width: 100%;
	height: min(62vh, 30vw);
	padding: 0;
	overflow: hidden;
	text-decoration: none;
}
.nav-dropdown-panel--tiles .nav-tile__media { position: absolute; inset: 0; display: block; background: var(--color-bg-soft); }
.nav-dropdown-panel--tiles .nav-tile__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.5s ease;
}
.nav-dropdown-panel--tiles .sub-menu a.nav-tile:hover .nav-tile__media img { transform: scale(1.04); }
/* Room Spray: a tall frame cropped to a landscape tile, with the two bottles
   sitting low. Centred, they land behind the caption; biasing the crop down
   lifts them into the clear part of the tile. */
.nav-dropdown-panel--tiles .nav-tile--room-spray .nav-tile__media img {
	object-position: center 72%;
}
/* The thumbnails are not known in advance, so the caption carries its own
   scrim rather than relying on the photograph being dark at the foot. */
.nav-dropdown-panel--tiles .nav-tile__media::after {
	content: '';
	position: absolute;
	inset: auto 0 0 0;
	height: 55%;
	background: linear-gradient(to top, rgba(19, 19, 19, 0.55), rgba(19, 19, 19, 0));
}
.nav-dropdown-panel--tiles .nav-tile__body {
	position: absolute;
	left: 16px;
	right: 16px;
	bottom: clamp(18px, 2.4vw, 34px);
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	color: #fff;
}
.nav-dropdown-panel--tiles .nav-tile__title {
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(19px, 1.7vw, 26px);
	line-height: 1.15;
	letter-spacing: 0;
	text-transform: none;
}

/* Branches collapse. Open, the three of them plus the brand roster ran to
   several screens of list. The caret is the control; the branch's own link
   still navigates. */
.mobile-nav__menu > .menu-item-has-children {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
}
.mobile-nav__menu .sub-menu {
	display: none;
	flex-basis: 100%;
	flex-direction: column;
	gap: 12px;
	margin: 12px 0 0 16px;
}
.mobile-nav__menu > .menu-item-has-children.is-open > .sub-menu { display: flex; }
.mobile-nav__menu .menu-item-has-children > a { font-weight: 600; }
.mobile-nav__menu .nav-dropdown-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 36px, matching every other tap target in the header. */
	width: 36px;
	height: 36px;
	margin: -8px 0;
	padding: 0;
	background: none;
	border: 0;
	color: var(--color-ink);
	cursor: pointer;
}
/* The svg turns, not the button -- same convention as the desktop caret above,
   which is also where the transition on it lives. */
.mobile-nav__menu .nav-dropdown-toggle svg { width: 20px; height: 20px; }
.mobile-nav__menu > .menu-item-has-children.is-open > .nav-dropdown-toggle svg { transform: rotate(180deg); }

.header-icons { display: flex; align-items: center; gap: 14px; }
/* --- Currency switcher -------------------------------------
   A <details> dropdown: flag + code + caret in the summary, the full list of
   currencies beneath. position: relative so the menu can hang off it. */
.header-currency {
	position: relative;
	margin-right: 6px;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	color: var(--color-ink);
	white-space: nowrap;
}
.header-currency__toggle {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 5px 8px;
	border-radius: var(--radius-pill);
	cursor: pointer;
	/* The default disclosure triangle -- Safari needs the -webkit- pseudo as well
	   as list-style, and without display:inline-flex the summary stays a block. */
	list-style: none;
	transition: background 0.2s ease;
}
.header-currency__toggle::-webkit-details-marker { display: none; }
.header-currency__toggle:hover { background: rgba(19, 19, 19, 0.05); }
.header-currency[open] .header-currency__toggle { background: rgba(19, 19, 19, 0.06); }
.header-currency__toggle:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 2px;
}
/* Rounded here rather than with an SVG <clipPath>, which would need an id and
   this markup is printed many times per page. See satueen_currency_flag(). */
.header-currency__flag {
	width: 20px;
	height: 20px;
	flex: 0 0 auto;
	border-radius: 50%;
	overflow: hidden;
	/* The white half of both flags would otherwise dissolve into a white header. */
	box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
}
.header-currency__code { color: var(--color-ink); font-weight: 600; letter-spacing: 0.04em; }
.header-currency__caret {
	width: 14px;
	height: 14px;
	flex: 0 0 auto;
	color: var(--color-ink-soft);
	transition: transform 0.2s ease;
}
.header-currency[open] .header-currency__caret { transform: rotate(180deg); }

.header-currency__menu {
	position: absolute;
	top: calc(100% + 8px);
	right: 0;
	z-index: 60;
	min-width: 218px;
	padding: 6px;
	background: #fff;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
	box-shadow: 0 14px 34px rgba(19, 19, 19, 0.13);
}
.header-currency__opt {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 9px 10px;
	border-radius: calc(var(--radius-md) - 4px);
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0;
	text-transform: none;
	color: var(--color-ink);
	text-decoration: none;
	transition: background 0.15s ease;
}
.header-currency__opt:hover { background: var(--color-bg); }
.header-currency__opt.is-active { background: var(--color-bg); font-weight: 600; }
/* The name takes the free space so the code is pushed hard right in every row. */
.header-currency__name { flex: 1 1 auto; }
.header-currency__opt .header-currency__code {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.06em;
	color: var(--color-ink-soft);
}
.header-currency__opt.is-active .header-currency__code { color: var(--color-ink); }

/* Shown in place of the dropdown when the switcher plugin is off, or when only
   one currency is enabled -- there is nothing to open. */
.header-currency--static {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 5px 8px;
}

/* Mobile-nav copy of the switcher -- the header one is hidden below 980px. */
.header-currency--mobile {
	display: block;
	margin: 18px var(--gutter) 0;
	padding-top: 18px;
	border-top: 1px solid var(--color-border);
}
.header-currency--mobile .header-currency__toggle { padding: 8px 10px; font-size: 13px; }
/* Inside the slide-in nav the dropdown pushes the content below it instead of
   floating: an absolutely positioned menu can end up clipped by the panel. */
.header-currency--mobile .header-currency__menu {
	position: static;
	margin-top: 8px;
	min-width: 0;
	box-shadow: none;
}

.header-icon-btn {
	width: 36px;
	height: 36px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	position: relative;
}
.header-icon-btn:hover { background: var(--color-bg-soft); }
.header-icon-btn svg { width: 19px; height: 19px; }
.cart-count {
	position: absolute;
	top: -2px;
	right: -2px;
	background: var(--color-accent);
	color: #fff;
	font-size: 10px;
	line-height: 1;
	min-width: 16px;
	height: 16px;
	border-radius: 50%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0 3px;
}

/* =========================================================
   Menu panel — the hamburger's slide-in list
   Mirrors the cart drawer's mechanics (fixed panel + dimmed overlay), but
   enters from the left and is sized to the type rather than to a cart.
   ========================================================= */
.menu-panel-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 30px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-ink);
	cursor: pointer;
}
.menu-panel-toggle__bars {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 4px;
	width: 20px;
}
.menu-panel-toggle__bars span {
	display: block;
	height: 1.5px;
	background: currentColor;
	/* The middle rule is short, as in the reference -- three equal rules read as
	   a generic icon, this reads as a mark. */
	transition: width 0.2s ease, transform 0.25s ease, opacity 0.2s ease;
}
.menu-panel-toggle__bars span:nth-child(1) { width: 20px; }
.menu-panel-toggle__bars span:nth-child(2) { width: 13px; }
.menu-panel-toggle__bars span:nth-child(3) { width: 20px; }
.menu-panel-toggle:hover .menu-panel-toggle__bars span { width: 20px; }
/* Open state folds the three rules into a cross, so the button doubles as the
   close control without swapping icons. */
.menu-panel-toggle[aria-expanded="true"] .menu-panel-toggle__bars span:nth-child(1) { width: 20px; transform: translateY(5.5px) rotate(45deg); }
.menu-panel-toggle[aria-expanded="true"] .menu-panel-toggle__bars span:nth-child(2) { opacity: 0; }
.menu-panel-toggle[aria-expanded="true"] .menu-panel-toggle__bars span:nth-child(3) { width: 20px; transform: translateY(-5.5px) rotate(-45deg); }

.menu-panel-overlay {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.4);
	z-index: 1000;
	opacity: 0;
	transition: opacity 0.3s ease;
}
.menu-panel-overlay.is-open { opacity: 1; }

.menu-panel {
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	width: min(340px, 86vw);
	padding: clamp(28px, 4vw, 48px) clamp(28px, 3vw, 44px);
	background: var(--color-bg);
	z-index: 1001;
	display: flex;
	flex-direction: column;
	/* The lists are short, but a small window or a long secondary list should
	   scroll inside the panel rather than clip. */
	overflow-y: auto;
	transform: translateX(-100%);
	transition: transform 0.3s ease;
	box-shadow: 8px 0 24px rgba(0, 0, 0, 0.08);
}
.menu-panel.is-open { transform: translateX(0); }
.menu-panel[hidden] { display: none; }

.menu-panel__close {
	align-self: flex-end;
	width: 32px;
	height: 32px;
	margin-bottom: clamp(24px, 4vw, 44px);
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-ink);
	cursor: pointer;
}
.menu-panel__close svg { width: 20px; height: 20px; display: block; }

.menu-panel__primary,
.menu-panel__secondary {
	list-style: none;
	margin: 0;
	padding: 0;
}
.menu-panel__primary a {
	display: block;
	padding: 7px 0;
	font-family: var(--font-base);
	font-size: 17px;
	font-weight: 500;
	line-height: 1.35;
	color: var(--color-ink);
	text-decoration: none;
}
/* The two groups are separated by space alone, not a rule -- the weight and
   colour shift already does the work of dividing them. */
.menu-panel__secondary { margin-top: clamp(32px, 5vw, 52px); }
.menu-panel__secondary a {
	display: block;
	padding: 5px 0;
	font-family: var(--font-base);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.4;
	color: var(--color-ink-soft);
	text-decoration: none;
}
.menu-panel__primary a:hover,
.menu-panel__secondary a:hover { color: var(--color-accent); }

/* =========================================================
   Cart drawer
   ========================================================= */
.cart-drawer-overlay {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.4);
	z-index: 1000;
	opacity: 0;
	transition: opacity 0.3s ease;
}
.cart-drawer-overlay.is-open { opacity: 1; }
.cart-drawer {
	position: fixed;
	/* Full height. This was 38px -- the announcement bar's height -- which left a
	   strip of dimmed page above the drawer, and was wrong anyway once the page
	   is scrolled and that bar isn't at the top of the viewport any more. */
	top: 0;
	right: 0;
	bottom: 0;
	width: min(420px, 100vw);
	background: var(--color-bg);
	z-index: 1001;
	display: flex;
	flex-direction: column;
	transform: translateX(100%);
	transition: transform 0.3s ease;
	box-shadow: -8px 0 24px rgba(0, 0, 0, 0.08);
}
/* display:flex above beats the hidden attribute, so the closed drawer stayed in
   layout parked off the right edge -- and since it's anchored with right:0 to a
   scroll area its own overflow had just widened, each reflow pushed it further
   out. That runaway width is what let the whole page scroll sideways into empty
   space. Out of layout when closed, no overflow to chase. */
.cart-drawer[hidden] { display: none; }
.cart-drawer.is-open { transform: translateX(0); }
.cart-drawer__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 20px 24px;
	border-bottom: 1px solid var(--color-border);
}
/* Same face as .best-sellers__title -- the display serif at its natural case
   and weight. Only the size differs, since a drawer heading is not a section
   heading. */
.cart-drawer__header h2 {
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: 30px;
	line-height: 1.2;
	display: flex;
	align-items: center;
	gap: 8px;
}
/* Self-contained rather than a modifier on .cart-count -- this span can't carry
   that class without WooCommerce's fragment refresh overwriting it. */
.cart-drawer__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--color-navy);
	color: #fff;
	border-radius: var(--radius-pill);
	font-size: 12px;
	line-height: 1;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
}
.cart-drawer__close { width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; }
.cart-drawer__close svg { width: 18px; height: 18px; }

.widget_shopping_cart_content { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.cart-drawer__empty { padding: 24px; color: var(--color-ink-soft); }

.cart-drawer__list { flex: 1; overflow-y: auto; padding: 8px 24px; }
.cart-drawer__item {
	display: flex;
	gap: 14px;
	padding: 16px 0;
	border-bottom: 1px solid var(--color-border);
}
.cart-drawer__item-thumb { flex-shrink: 0; width: 72px; height: 72px; border-radius: var(--radius-sm); overflow: hidden; }
.cart-drawer__item-thumb img { width: 100%; height: 100%; object-fit: cover; }
.cart-drawer__item-body { flex: 1; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cart-drawer__item-name { font-weight: 600; font-size: 14px; }
.cart-drawer__item-price { font-size: 13px; color: var(--color-ink-soft); }
.cart-drawer__item-body dl.variation,
.cart-drawer__item-body .wc-item-meta { font-size: 12px; color: var(--color-ink-faint); margin: 0; }
.cart-drawer__item-controls { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; gap: 10px; }
.cart-drawer__qty {
	display: inline-flex;
	align-items: stretch;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	overflow: hidden;
}
.cart-drawer__qty .qty-btn { width: 32px; font-size: 14px; }
.cart-drawer__qty-input { width: 36px; border: none; text-align: center; padding: 6px 0; -moz-appearance: textfield; }
.cart-drawer__qty-input::-webkit-outer-spin-button,
.cart-drawer__qty-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cart-drawer__item-remove { width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; color: var(--color-ink-faint); }
.cart-drawer__item-remove:hover { color: var(--color-ink); }
.cart-drawer__item-remove svg { width: 16px; height: 16px; }

.cart-drawer__totals { padding: 16px 24px 0; border-top: 1px solid var(--color-border); }
.woocommerce-mini-cart__total.total { display: flex; align-items: center; justify-content: space-between; font-size: 16px; font-weight: 600; margin: 0 0 6px; }
.free-shipping-bar { margin: 0 0 16px; }
.free-shipping-bar__msg { font-size: 13px; margin: 0 0 10px; }
.free-shipping-bar__track {
	position: relative;
	height: 6px;
	background: var(--color-border);
	border-radius: var(--radius-pill);
}
.free-shipping-bar__fill {
	height: 100%;
	background: var(--color-ink);
	border-radius: var(--radius-pill);
	transition: width 0.3s ease;
}
.free-shipping-bar__icon {
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 26px;
	height: 26px;
	border-radius: 50%;
	background: var(--color-ink);
	color: #fff;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: left 0.3s ease;
}
.free-shipping-bar__icon svg { width: 15px; height: 15px; }
/* Inside the drawer the filled elements are navy rather than near-black, matching
   the badge and the checkout button. Scoped, because this same bar also renders on
   the checkout page, which is still on the near-black scheme. */
.cart-drawer .free-shipping-bar__fill,
.cart-drawer .free-shipping-bar__icon { background: var(--color-navy); }
.woocommerce-checkout .free-shipping-bar { max-width: 480px; margin: 0 0 32px; }

/* Bundle promotion nudge. Deliberately quieter than the free-shipping bar it
   sits beside — that one has a progress track, and two tracks stacked would
   compete. This is a single tinted line: sand while the shopper is short of
   the threshold, green once the discount is actually applied, so "earned" is
   readable without reading the words. */
.bundle-promo-bar {
	margin: 0 0 16px;
	padding: 10px 12px;
	border-radius: var(--radius-sm);
	background: color-mix(in srgb, var(--color-sand) 30%, transparent);
	border-left: 3px solid var(--color-sand);
}
.bundle-promo-bar--earned {
	background: color-mix(in srgb, var(--color-green) 12%, transparent);
	border-left-color: var(--color-green);
}
.bundle-promo-bar__msg { font-size: 13px; line-height: 1.45; margin: 0; }
.bundle-promo-bar--earned .bundle-promo-bar__msg { color: var(--color-green); }
.bundle-promo-bar--earned .bundle-promo-bar__msg strong { color: inherit; }

/* The drawer's own "Estimated total" is get_cart_subtotal(), which excludes
   fees — so this line is what tells the shopper the saving exists before they
   reach the cart page. Matches .woocommerce-mini-cart__total's row shape. */
.bundle-promo-line { color: var(--color-green); }
.bundle-promo-line__amount { font-variant-numeric: tabular-nums; }
.bundle-promo-line .amount { color: inherit; }

.woocommerce-checkout .bundle-promo-bar { max-width: 480px; margin: 0 0 24px; }

/* Bundle promotion, announced OUTSIDE the cart.

   Two placements, one promotion: the note under a product's price (product
   page and Quick View) and the badge on the product card. Both are driven by
   satueen_bundle_promo_deals(), so the wording cannot drift from the
   discount the cart actually applies.

   Deliberately NOT styled like .bundle-promo-bar above. That bar is cart
   feedback -- it reports what this basket has or has not earned, and its sand
   tint reads as a nudge. These are an OFFER being advertised to someone who
   has not decided yet.

   NAVY, and the same navy as .product-card__badge--bundle: one promotion
   should not wear two colours between the card and the page it opens. Never
   terracotta -- that means "reduced from" here, and a bundle is a condition on
   buying two rather than a cut on this one. */
.bundle-note {
	margin: 0 0 20px;
	padding-left: 12px;
	border-left: 2px solid var(--color-navy);
}
.bundle-note__offer {
	display: block;
	font-size: 14px;
	font-weight: 600;
	color: var(--color-navy);
	letter-spacing: -0.005em;
}
.bundle-note__terms {
	display: block;
	font-size: 12.5px;
	color: var(--color-ink-soft);
	margin-top: 2px;
}
/* The modal is a narrower column than the product page, so the note tightens
   rather than carrying the page's spacing into a smaller box. */
.quick-view .bundle-note { margin-bottom: 14px; }
.quick-view .bundle-note__offer { font-size: 13.5px; }
.quick-view .bundle-note__terms { font-size: 12px; }


/* Checkout page — tighten header, drop the oversized serif title, and
   bring the whole block-checkout (which ships its own inline styles) onto
   the theme's sans body font for a uniform look. */
.woocommerce-checkout .page-header { padding-top: 48px; margin-bottom: 24px; }
.woocommerce-checkout .page-header h1 { font-family: var(--font-base); font-size: 28px; font-weight: 600; text-transform: none; }

.wc-block-checkout,
.wc-block-checkout h1,
.wc-block-checkout h2,
.wc-block-checkout h3,
.wc-block-checkout p,
.wc-block-checkout span,
.wc-block-checkout label,
.wc-block-checkout input,
.wc-block-checkout button,
.wc-block-checkout legend {
	font-family: var(--font-base) !important;
}

.wc-block-components-checkout-step__title {
	font-size: 18px;
	font-weight: 600;
	letter-spacing: normal;
	line-height: 1.3;
}
.wc-block-components-checkout-order-summary__title-text { font-size: 18px; font-weight: 600; }

/* Match the left form steps to the right order-summary box: same border,
   radius, and padding, so the page reads as a uniform set of cards instead
   of the right column boxed and the left column floating free. */
.wc-block-components-checkout-step {
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	padding: 24px;
	margin-bottom: 16px;
}
.wc-block-components-checkout-step__heading { margin-bottom: 16px; }
.wc-block-components-sidebar.wc-block-checkout__sidebar { border-radius: var(--radius-sm); }

/* WooCommerce splits the checkout 65/35 between the form and the summary. 35%
   is not enough for a product name, a variation line and a price to sit on one
   row without wrapping, which is what made the column feel cramped even after
   the padding inside it was tightened. 58/42 gives the summary roughly a fifth
   more width and still leaves the form the wider of the two.

   Specificity beats core's (three classes to its two) rather than !important.
   Below 900px the block stacks the two columns to full width on its own -- a
   @container rule, which this must not fight -- so the override is gated above
   that. */
@media (min-width: 900px) {
	.woocommerce-checkout .wc-block-components-sidebar-layout .wc-block-components-main { width: 58%; }
	.woocommerce-checkout .wc-block-components-sidebar-layout .wc-block-components-sidebar { width: 42%; }
}

/* --- Order summary line items -------------------------------------------
   The block checkout's defaults assume a wider column than this layout gives
   it: 24px of left padding on the description, no rule between products, and
   the unit price printed under the product name on top of the line total on
   the right. In a narrow sidebar that adds up to two-word names wrapping,
   "$49.90" appearing twice in a row, and three products running together into
   one block of text with nothing to separate them. */

/* The unit price. It sits under the name and repeats the line total verbatim
   at quantity 1 -- which is most rows in most orders, since WooCommerce
   renders it unconditionally rather than only when quantity is above one. The
   badge on the thumbnail already says how many, and the figure on the right is
   what is actually being charged.
   Trade-off, deliberate: at quantity 2 or more the per-item price is no longer
   shown, only the line total. Delete this rule to get it back. */
.wc-block-components-order-summary-item__individual-prices { display: none; }

.wc-block-components-order-summary-item { align-items: flex-start; }

/* Most of that 24px was clearing the quantity badge, which overhangs the
   thumbnail by half its own width -- 10px. 14px clears it with room to spare
   and buys the product name several more characters before it wraps.
   word-break: normal because core's break-word was splitting names mid-word. */
.wc-block-components-order-summary-item__description {
	padding: 2px 10px 16px 14px;
	word-break: normal;
	overflow-wrap: anywhere;
}
.wc-block-components-order-summary-item .wc-block-components-product-name {
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
}

/* "Volume: 55ml / Type: Eau de Parfum" is supporting detail, not a second
   title -- it was set at nearly the weight of the product name above it. */
.wc-block-components-order-summary-item .wc-block-components-product-metadata {
	margin-top: 5px;
	font-size: 12.5px;
	line-height: 1.45;
	color: var(--color-ink-soft);
}
.wc-block-components-order-summary-item .wc-block-components-product-details { margin: 0; }

/* tabular-nums so the decimals line up down the column, nowrap so a price
   never breaks over two lines to save a few pixels. */
.wc-block-components-order-summary-item__total-price {
	padding-top: 2px;
	font-size: 14px;
	font-weight: 600;
	white-space: nowrap;
	font-variant-numeric: tabular-nums;
}

/* One hairline per product. Adjacent-sibling rather than a border on every
   item, so the first row does not get a rule directly under the "Order
   summary" heading. */
.wc-block-components-order-summary-item + .wc-block-components-order-summary-item {
	border-top: 1px solid var(--color-border);
	padding-top: 16px;
}

/* Order summary should scroll normally with the page, not stay pinned —
   override WooCommerce's own sticky rule for the sidebar. */
.wc-block-checkout__sidebar.is-sticky {
	position: static !important;
	top: auto !important;
}

.wc-block-components-checkout-place-order-button {
	background: var(--color-dark) !important;
	border-color: var(--color-dark) !important;
	color: #fff !important;
}
.wc-block-components-checkout-place-order-button:hover {
	background: var(--color-ink) !important;
}
.cart-drawer__buttons { padding: 0 24px 24px; margin: 0; }
.cart-drawer__checkout {
	display: block;
	width: 100%;
	text-align: center;
	background: var(--color-navy);
	color: #fff;
	border-radius: var(--radius-sm);
	padding: 16px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	font-size: 13px;
}
.cart-drawer__checkout:hover { background: var(--color-accent-dark); }

body.cart-drawer-is-open { overflow: hidden; }

/* Page scroll lock, used while an overlay panel is open so only the panel
   itself scrolls. It sits on <html> and ONLY there: the root carries
   overflow-x: clip (see the top of this file), and a root whose overflow is not
   'visible' no longer inherits the body's overflow for the viewport -- so it is
   the root's own overflow that stops the page. This rule used to hide the
   body's overflow as well, which added nothing to the lock and made <body> a
   scroll container: every position: sticky element (announcement bar, header,
   the homepage's pinned hero) then stuck to a box that never scrolls, and
   jumped off screen whenever a panel opened part-way down the page. The gutter replaces the width the scrollbar gave
   up, so nothing shifts sideways on the way in. */
html.is-scroll-locked {
	overflow: hidden;
}
html.is-scroll-locked {
	padding-right: var(--scroll-lock-gutter, 0px);
}

@media (max-width: 480px) {
	.cart-drawer { width: 100vw; }
}

.menu-toggle__bars,
.menu-toggle__bars::before,
.menu-toggle__bars::after {
	content: '';
	display: block;
	width: 20px;
	height: 1.5px;
	background: currentColor;
	position: relative;
}
.menu-toggle__bars::before { position: absolute; top: -6px; }
.menu-toggle__bars::after { position: absolute; top: 6px; }

/* The search band that drops out from under the header. Not a boxed field: the
   query sits in the display serif on a single hairline rule that runs the width
   of the container, so what you are typing is the largest thing on screen. */
.header-search {
	/* Absolute against the sticky .site-header, so the panel hangs over the page
	   instead of taking part in the flow -- opening it used to push the hero and
	   everything under it down by its own height. */
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	padding: 0 var(--gutter) var(--gutter);
	/* No background of its own: the panel is a card floating over the page, and
	   a full-width band behind it would read as a second header. */
	pointer-events: none;
}
.search-panel {
	pointer-events: auto;
	max-width: 800px;
	margin: 0 auto;
	background: #fff;
	border: 1px solid var(--color-border);
	box-shadow: 0 24px 60px rgba(19, 19, 19, 0.12);
	/* The results list scrolls inside the card rather than growing the card past
	   the fold -- 8 tiles at two rows is taller than a short laptop viewport. */
	max-height: calc(100vh - var(--announcement-h) - 140px);
	display: flex;
	flex-direction: column;
}

/* The field row. */
.header-search__form {
	flex: none;
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 18px 20px;
	border-bottom: 1px solid var(--color-border);
}
.header-search__form input {
	flex: 1;
	min-width: 0;
	border: none;
	outline: none;
	background: none;
	padding: 0;
	font-family: var(--font-base);
	font-size: 16px;
	line-height: 1.4;
	color: var(--color-ink);
}
.header-search__form input::placeholder { color: var(--color-ink-faint); opacity: 1; }
.header-search__form input::-webkit-input-placeholder { color: var(--color-ink-faint); opacity: 1; }
/* Safari draws its own clear button and inner decorations on type=search. */
.header-search__form input::-webkit-search-decoration,
.header-search__form input::-webkit-search-cancel-button { -webkit-appearance: none; }
.header-search__submit,
.header-search__close {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	border: 0;
	background: none;
	padding: 0;
	cursor: pointer;
	color: var(--color-ink);
}
.header-search__close { color: var(--color-ink-faint); }
.header-search__close:hover { color: var(--color-ink); }
.header-search__submit svg,
.header-search__close svg { width: 20px; height: 20px; }

/* The body below the field. */
.search-panel__body {
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
	padding: 20px;
}
.search-panel__section + .search-panel__section { margin-top: 24px; }
.search-panel__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	margin-bottom: 14px;
}
.search-panel__label {
	margin: 0;
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-ink-faint);
}
.search-panel__clear {
	border: 0;
	background: none;
	padding: 0;
	cursor: pointer;
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-ink-faint);
}
.search-panel__clear:hover { color: var(--color-ink); }

.search-panel__results {
	/* NOT .search-results: WordPress puts that exact class on <body> for a search
	   results page, so these grid rules were laying out the whole document. */
	display: grid;
	/* Sized against the card, not the viewport. A media query on the window was
	   wrong twice over: it kept four columns in a card far too narrow for them,
	   and a bare 1fr is minmax(auto, 1fr), whose auto floor is the tile's own
	   min-content -- so the row overflowed and grew a horizontal scrollbar
	   instead of reflowing. minmax(0, …) is what lets a track shrink. */
	grid-template-columns: repeat(auto-fill, minmax(min(140px, 100%), 1fr));
	gap: 20px 16px;
	list-style: none;
	margin: 0;
	padding: 0;
}
.search-result {
	/* A grid item's default min-width: auto would re-impose the min-content
	   floor the track sizing above just removed. */
	min-width: 0;
}
.search-result__link {
	display: block;
	min-width: 0;
	text-decoration: none;
	color: inherit;
}
.search-result__media {
	display: block;
	position: relative;
	/* 3/4, the same portrait card the shop grid, New Arrivals and the
	   best-sellers row use -- a square was the odd one out. */
	aspect-ratio: 3 / 4;
	overflow: hidden;
	background: var(--color-bg-soft);
	margin-bottom: 10px;
}
.search-result__media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
.search-result__placeholder { display: block; width: 100%; height: 100%; }
.search-result__title {
	display: block;
	overflow-wrap: break-word;
	font-size: 14px;
	line-height: 1.35;
	color: var(--color-ink);
}
.search-result__price {
	display: block;
	margin-top: 4px;
	font-size: 14px;
	color: var(--color-ink);
}
.search-result__price del { opacity: 0.5; margin-right: 6px; }
.search-result__price ins { text-decoration: none; color: var(--color-sale); }
.search-result__link:hover .search-result__title { text-decoration: underline; }

.search-panel__empty {
	margin: 0;
	font-size: 14px;
	color: var(--color-ink-faint);
}
.search-panel__more {
	display: flex;
	justify-content: center;
	margin-top: 24px;
}
/* display:flex above beats the hidden attribute on its own -- the same
   collision that once left the closed cart drawer in layout. */
.search-panel__more[hidden] { display: none; }
.search-panel__view-all { min-width: 160px; }

@media (max-width: 700px) {
	.header-search { padding-left: 12px; padding-right: 12px; }
}

/* One button, two glyphs. */
.search-toggle__close { display: none; }
.search-toggle[aria-expanded="true"] .search-toggle__open { display: none; }
.search-toggle[aria-expanded="true"] .search-toggle__close { display: block; }

.mobile-nav {
	display: none;
}

/* =========================================================
   Hero
   ========================================================= */
.hero {
	position: relative;
	/* Fill the viewport minus the announcement bar + header (107px) and the
	   brand marquee band below it (78px), so the marquee sits just above the
	   fold. The extra ~15px is slack: header height shifts a little with
	   browser chrome and zoom, and without it the marquee gets clipped. */
	min-height: max(420px, calc(100vh - 200px));
	overflow: hidden;
	background: var(--color-ink);
}
/* Homepage, from tablet width up: the hero is the whole first screen. It is
   pulled up under the (transparent) header and runs to the bottom of the
   viewport, so the opening view is the announcement bar and the film and
   nothing else -- the brand marquee now starts just below the fold. svh where
   it exists, so a mobile browser's collapsing toolbar cannot leave it short.
   Phones are left at the height in the 700px rule further down, which was
   tuned by hand so the next section shows; they still get the header overlap. */
body.home .hero { margin-top: calc(-1 * var(--header-h)); }
@media (min-width: 701px) {
	body.home .hero {
		min-height: calc(100vh - var(--announcement-h));
		min-height: calc(100svh - var(--announcement-h));
	}
}
/* Pinned hero. On the homepage the film does not scroll away: it holds its
   place under the header and the rest of the page (.home-sheet) slides up over
   it like a sheet of paper, per the reference. sticky rather than fixed so it
   still takes up its own space in the flow and needs no spacer.
   --hero-lift is written by main.js as the page scrolls: the film drifts up at
   a fraction of the scroll speed, which is what gives the sheet its sense of
   passing over something further away. The sheet always travels faster, so
   the gap the drift opens at the hero's bottom edge is never seen. */
body.home .hero {
	position: sticky;
	top: var(--announcement-h);
	z-index: 0;
	transform: translate3d(0, var(--hero-lift, 0px), 0);
}
/* The sheet: opaque, and above the pinned film. flow-root so the first
   section's top margin cannot collapse out through it and open a strip of film
   between hero and sheet. */
.home-sheet {
	position: relative;
	z-index: 1;
	display: flow-root;
	/* The whole homepage below the hero sits on white rather than the site's
	   pale blue. Bands that set their own ground (welcome offer, payday,
	   newsletter) keep it. */
	background: #fff;
}
.hero__slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.9s ease;
	z-index: 1;
}
.hero__slide.is-active { opacity: 1; visibility: visible; z-index: 2; }
/* Black ground under the video. The poster is a still of the video's own first
   frame, so poster and first frame are the same picture -- but the poster is
   still a separate request, and this is what fills the band in the instant
   before it lands rather than the page's pale blue. */
.hero__media { position: absolute; inset: 0; background: #000; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
/* The hero video fills the band exactly as the still did -- cover-cropped from
   the centre, so it never letterboxes whatever the viewport shape. display:block
   kills the inline baseline gap a <video> otherwise carries. */
.hero__video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
.hero__slide::after {
	content: '';
	position: absolute;
	inset: 0;
	background:
		linear-gradient(180deg, rgba(19,19,19,0.42) 0%, rgba(19,19,19,0) 38%),
		linear-gradient(0deg, rgba(19,19,19,0.48) 0%, rgba(19,19,19,0) 52%);
	pointer-events: none;
}
.hero__copy {
	position: absolute;
	left: 50%;
	bottom: clamp(48px, 8vw, 88px);
	transform: translateX(-50%);
	z-index: 3;
	max-width: 640px;
	width: 90%;
	color: #fff;
	text-align: center;
}
/* Oversized display headline, per the reference: near-cap-height leading so the
   two lines lock together, and a touch of negative tracking to stop the serif
   from looking loose at this size. */
.hero__heading {
	font-family: var(--font-hero);
	/* Instrument Serif ships a single weight — 400 is the only real option. */
	font-weight: 400;
	text-transform: none;
	/* Runs large because the face is narrow with a small cap height for its em;
	   at the old Noto Serif sizing it would read a third smaller than the reference. */
	font-size: clamp(38px, 8.4vw, 115px);
	line-height: 0.9;
	letter-spacing: -0.005em;
	color: #fff;
	margin: 0 0 clamp(24px, 3vw, 38px);
}
/* Blocks rather than <br> so the tight line-height applies per line. */
.hero__heading-line { display: block; }
.hero__sub {
	font-family: var(--font-base);
	color: rgba(255,255,255,0.88);
	font-size: 15px;
	max-width: 420px;
	margin: 0 auto 28px;
}
/* The word above the headline, in script: white on the film with nothing
   behind it. It shows as typed in the Customizer (no forced capitals -- see
   --font-script). Sized off the headline so the two scale together; the
   line-height is tight and the bottom margin small because a script's
   descenders already leave air under the baseline. */
.hero__eyebrow {
	font-family: var(--font-script);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(30px, 3.9vw, 54px);
	line-height: 1.1;
	color: #fff;
	margin: 0 0 clamp(4px, 0.6vw, 10px);
}

/* Wide enough for the display headline's longest line; the break points are set
   in the heading text itself now, so nowrap is no longer needed. */
.hero__slide[data-hero-slide="0"] .hero__copy { max-width: 1180px; }
.hero__slide[data-hero-slide="0"] .hero__sub { max-width: 560px; }

.hero__actions {
	display: flex;
	justify-content: center;
	align-items: stretch;
	gap: 14px;
	flex-wrap: wrap;
}

/* Solid white square CTA (no pill radius). */
.hero__cta {
	text-transform: uppercase;
	letter-spacing: 0.06em;
	background: #fff;
	color: var(--color-ink);
	/* Matched to the ghost button's border so both sit at the same height. */
	border: 1px solid #fff;
	border-radius: 0;
	padding: 15px 34px;
	font-size: 12px;
	font-weight: 500;
	transition: background 0.2s ease, color 0.2s ease;
}
.hero__cta:hover {
	background: var(--color-accent-dark);
	color: #fff;
	border-color: var(--color-accent-dark);
}

/* Second, outlined button — transparent with a hairline white border. */
.hero__cta--ghost {
	background: transparent;
	color: #fff;
	border: 1px solid rgba(255,255,255,0.85);
}
.hero__cta--ghost:hover { background: var(--color-accent-dark); color: #fff; border-color: var(--color-accent-dark); }

/* Hand-drawn accent marks on the final word of each headline. */
.hero__accent { position: relative; display: inline-block; font-style: italic; }

.hero__controls {
	position: absolute;
	right: var(--gutter);
	bottom: var(--gutter);
	z-index: 4;
	display: flex;
	align-items: center;
	gap: 16px;
}
.hero__dots { display: flex; align-items: center; gap: 8px; }
.hero__dot {
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: rgba(255,255,255,0.4);
	transition: width 0.25s ease, background 0.25s ease;
}
.hero__dot.is-active { background: #fff; width: 22px; border-radius: 4px; }
.hero__pause {
	width: 32px;
	height: 32px;
	border: 1px solid rgba(255,255,255,0.55);
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #fff;
	flex-shrink: 0;
}
.hero__pause-icon { position: relative; width: 9px; height: 10px; }
.hero__pause-icon::before, .hero__pause-icon::after {
	content: '';
	position: absolute;
	top: 0;
	width: 2.5px;
	height: 10px;
	background: #fff;
}
.hero__pause-icon::before { left: 0; }
.hero__pause-icon::after { left: 6px; }
.hero__pause[aria-pressed="true"] .hero__pause-icon::before,
.hero__pause[aria-pressed="true"] .hero__pause-icon::after { display: none; }
.hero__pause[aria-pressed="true"] .hero__pause-icon {
	width: 0;
	height: 0;
	border-top: 5px solid transparent;
	border-bottom: 5px solid transparent;
	border-left: 8px solid #fff;
}

/* =========================================================
   New arrivals (card treatment only)
   ========================================================= */
/* The section carries .best-sellers as well, which supplies the head row and the
   full-bleed scroller. .new-arrivals exists only for the bare-card photo
   treatment below and this top padding -- the editorial tile and the bespoke
   carousel it used to have are gone. */
.new-arrivals { padding-top: clamp(16px, 2.5vw, 32px); }

/* Bare cards inside New Arrivals only — the shop archive and brand pages
   share .product-card and keep their boxed treatment. */
.new-arrivals .product-card { background: none; border-radius: 0; }
.new-arrivals .product-card__media { background: none; aspect-ratio: 3 / 4; }
.new-arrivals .product-card__media img { object-fit: contain; }
/* Matches Best Sellers: the Quick View bar slides up over the photo, so the
   card's default photo-swap-for-doodle treatment is switched off here too --
   but only on cards with nothing better to swap to. Where the product has a
   second photograph, the hover swap is the point, so the first one still fades
   out from under it. */
.new-arrivals .product-card:hover .product-card__media:not(.product-card__media--has-alt) img { opacity: 1; }
.new-arrivals .product-card__hover-art { display: none; }
.new-arrivals .product-card__info { padding: 18px 0 0; gap: 6px; flex: 1; }
/* Reference order is name → brand → price; the markup is shared, so reorder
   visually rather than forking the partial. */
.new-arrivals .product-card__title { order: 1; font-size: 15px; }
.new-arrivals .product-card__brand { order: 2; }
.new-arrivals .product-card__price { order: 3; }
/* Quick View carries add-to-cart here, same as Best Sellers, so the button
   below the price is redundant. */
.new-arrivals .product-card__add { display: none; }

.product-card {
	display: flex;
	flex-direction: column;
	background: var(--color-bg-soft);
	border-radius: var(--radius-md);
	overflow: hidden;
}

.product-card__media {
	position: relative;
	display: block;
	aspect-ratio: 4 / 5;
	overflow: hidden;
	background: transparent;
}
.product-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease, opacity 0.3s ease; }
.product-card:hover .product-card__media img { transform: scale(1.04); opacity: 0; }
/* The product's second photograph, laid over the first so the two cross-fade in
   place on hover. It is an <img> inside .product-card__media like the first, so
   every context rule above -- object-fit, mix-blend-mode, the aspect-ratio of
   the frame around it -- reaches both, and the pair always match. Rendered by
   template-parts/product-card.php only when the product actually has a second
   photograph; single-photograph products keep the drawn hover art instead.

   Written as img.product-card__media-alt rather than the class alone so it
   outweighs the .product-card:hover .product-card__media img rule directly
   above, which would otherwise fade this one out along with the first. */
.product-card__media img.product-card__media-alt { position: absolute; inset: 0; opacity: 0; }
.product-card:hover .product-card__media img.product-card__media-alt { opacity: 1; }
/* Wraps the media link so the Quick View bar can sit over the photo without
   being nested inside the link. */
.product-card__mediawrap { position: relative; }
.product-card__quick {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 15px 12px;
	border: 0;
	background: var(--color-navy);
	color: #fff;
	font-family: var(--font-base);
	font-size: 14px;
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
	opacity: 0;
	transform: translateY(100%);
	transition: opacity 0.25s ease, transform 0.25s ease;
}
.product-card:hover .product-card__quick,
.product-card__quick:focus-visible {
	opacity: 1;
	transform: translateY(0);
}
/* No hover state to reveal it, and a permanently visible bar would cover the
   photo on every card. */
@media (hover: none) {
	.product-card__quick { display: none; }
}

.product-card__hover-art {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	opacity: 0;
	transition: opacity 0.3s ease;
	background: var(--color-blue);
}
.product-card__hover-art svg { width: 64%; height: 64%; }
.product-card__hover-art circle { fill: none; stroke: var(--color-accent); stroke-width: 1.4; }
.product-card:hover .product-card__hover-art { opacity: 1; }
/* Right-aligned, and that is true of EVERY badge type -- sale, sold out and
   bundle share this one rule, so the corner a badge appears in never depends on
   which kind it is. */
.product-card__badge {
	position: absolute;
	top: 12px;
	right: 12px;
	z-index: 2;
	background: var(--color-sale);
	color: #fff;
	font-size: 11px;
	font-weight: 600;
	padding: 5px 10px;
	border-radius: var(--radius-pill);
	white-space: nowrap;
}
.product-card__badge--soldout { background: var(--color-ink); }
/* Navy, not the terracotta above: on this site terracotta means "reduced
   from", and a bundle is a condition on buying two rather than a price cut on
   this one. Same navy as the note on the product page. */
.product-card__badge--bundle { background: var(--color-navy); }
.product-card__info { display: flex; flex-direction: column; gap: 4px; padding: 16px; }
.product-card__brand { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-ink-faint); }
.product-card__title { font-size: 14px; font-weight: 500; color: var(--color-ink); }
.product-card__title:hover { text-decoration: underline; }
.product-card__price { font-size: 13px; color: var(--color-ink-soft); }
.product-card__price del { opacity: 0.5; margin-right: 6px; text-decoration: line-through; }
.product-card__price ins { text-decoration: none; color: var(--color-sale); font-weight: 600; }
.product-card__add { margin-top: 10px; }
.product-card__add a.button {
	display: block;
	width: 100%;
	text-align: center;
	background: transparent;
	border: 1px solid var(--color-ink);
	color: var(--color-ink);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	padding: 10px 12px;
	border-radius: var(--radius-pill);
	transition: background 0.2s ease, color 0.2s ease;
}
.product-card__add a.button:hover { background: var(--color-ink); color: #fff; }
.product-card__add a.button.loading { opacity: 0.6; pointer-events: none; }
.product-card__add a.added_to_cart {
	display: block;
	margin-top: 8px;
	text-align: center;
	font-size: 12px;
	text-decoration: underline;
}

/* =========================================================
   Category tiles
   ========================================================= */
.category-tiles { padding-bottom: clamp(23px, 3.84vw, 50px); }
.cat-tile-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
}
.cat-tile { position: relative; display: block; overflow: hidden; aspect-ratio: 4 / 5; }
.cat-tile__img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; }
.cat-tile:hover .cat-tile__img { transform: scale(1.05); }
.cat-tile::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0,0,0,0.15) 0%, rgba(0,0,0,0) 35%, rgba(0,0,0,0.45) 100%);
}
.cat-tile__label {
	position: absolute;
	top: 24px;
	left: 24px;
	z-index: 2;
	color: #fff;
	font-family: var(--font-display);
	font-size: 28px;
	line-height: 1;
	writing-mode: vertical-rl;
	transform: rotate(180deg);
}

/* Card variant -- contained 3-up row, copy stacked bottom-left over the photo.
   The tile itself is the flex column (the helper emits eyebrow / label / button
   as siblings, no wrapper), so the image is pulled out of flow behind them. */
.cat-tile-grid--cards {
	gap: var(--gutter);
}
.cat-tile-grid--cards .cat-tile {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-end;
	/* Shallow portrait. */
	aspect-ratio: 5 / 6;
	padding: clamp(20px, 2.2vw, 30px);
	border-radius: var(--radius-md);
}
.cat-tile-grid--cards .cat-tile__img { position: absolute; inset: 0; }
/* Heavier at the foot than the shared gradient: three lines of white copy sit
   here, not just a pill. */
.cat-tile-grid--cards .cat-tile::after {
	background: linear-gradient(180deg, rgba(0,0,0,0) 28%, rgba(0,0,0,0.22) 55%, rgba(0,0,0,0.72) 100%);
}
.cat-tile-grid--cards .cat-tile__eyebrow {
	position: relative;
	z-index: 2;
	color: rgba(255,255,255,0.85);
	font-size: 11px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
}
.cat-tile-grid--cards .cat-tile__label {
	position: relative;
	top: auto;
	left: auto;
	z-index: 2;
	writing-mode: horizontal-tb;
	transform: none;
	font-family: var(--font-base);
	font-size: clamp(17px, 1.5vw, 21px);
	font-weight: 700;
	line-height: 1.2;
	text-transform: none;
	letter-spacing: 0;
}
.cat-tile-grid--cards .cat-tile__btn {
	position: relative;
	left: auto;
	bottom: auto;
	margin-top: 14px;
	border-radius: 0;
	padding: 8px 14px;
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.07em;
}
/* Head row: title + supporting line on the left, CTA pushed to the right,
   with the three cards in a full-width row underneath. */
.category-tiles__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 24px;
	padding-bottom: 0;
	margin-bottom: clamp(24px, 3vw, 40px);
}
.category-tiles__cta { flex-shrink: 0; }
.category-tiles__title {
	margin: 0 0 8px;
	font-family: var(--font-display);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(24px, 2.4vw, 32px);
	line-height: 1.2;
	color: var(--color-ink);
}
.category-tiles__text {
	margin: 0;
	/* Uncapped so it holds one line on desktop; it still wraps once the
	   container is narrower than the sentence. */
	max-width: none;
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}

/* =========================================================
   Scent marquee
   ========================================================= */
.scent-marquee { padding-block: clamp(32px, 4.5vw, 56px) clamp(24px, 4vw, 40px); overflow: hidden; }
/* Centred stack: title, supporting line, then the link beneath them. */
.scent-marquee__head {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	text-align: center;
	margin-bottom: 44px;
}
.scent-marquee__sub {
	margin: 0;
	/* Uncapped so it holds one line on desktop; it still wraps naturally once
	   the container gets narrower than the sentence. */
	max-width: none;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.6;
	color: var(--color-ink-soft);
}
/* The head is a 10px-gap flex column; the CTA wants more air than the gap
   between a title and its sub-line.

   Square-edged rather than the pill the .btn base sets: the tiles below it are
   hard-edged squares, and a rounded pill sitting directly on top of that row
   read as borrowed from somewhere else. Small caps and wide tracking carry the
   emphasis the shape no longer does. */
.scent-marquee__cta {
	margin-top: 14px;
	border-radius: 0;
	padding: 13px 30px;
	font-size: 11.5px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	/* The uppercase tracking adds space after the last letter that the eye
	   reads as the box being off-centre. */
	text-indent: 0.14em;
}
/* Matches the welcome band's serif heading: same face, weight and size. */
.scent-marquee__title {
	margin: 0;
	/* Same display face as the hero headline. Instrument Serif has a small cap
	   height for its em, so this runs ~25% larger than the old Noto Serif sizing it
	   replaces just to read at the same optical size. */
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(26px, 2.9vw, 38px);
	line-height: 1.2;
	color: var(--color-ink);
}
.scent-marquee__link {
	font-size: 14px;
	font-weight: 600;
	color: var(--color-green);
	text-decoration: underline;
	text-underline-offset: 3px;
	white-space: nowrap;
}
.scent-marquee__link:hover { color: var(--color-ink); }
.scent-marquee__viewport { width: 100%; overflow: hidden; mask-image: linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%); }
.scent-marquee__track {
	display: flex;
	width: max-content;
	gap: 16px;
	/* Shorter duration than the wider tiles needed, so the scroll keeps roughly
	   the same pixels-per-second. */
	animation: scent-marquee-scroll 30s linear infinite;
}
.scent-marquee__viewport:hover .scent-marquee__track { animation-play-state: paused; }
.scent-marquee__track .cat-tile {
	flex: 0 0 200px;
	width: 200px;
	aspect-ratio: 1 / 1;
}
/* The scent terms are stored lower-case ("aquatic & marine"); capitalize is a
   display-only fix so the taxonomy data stays untouched — those same names feed
   the product cards and archive titles. */
.scent-marquee__track .cat-tile__label {
	writing-mode: horizontal-tb;
	transform: none;
	top: 14px;
	left: 14px;
	font-family: var(--font-hero);
	font-size: 21px;
	font-weight: 400;
	text-transform: capitalize;
}
/* Plain underlined text rather than the base pill, matching the .edit-band__btn
   CTA. The tile's own bottom gradient (.cat-tile::after) carries the white; the
   text-shadow is for the paler photos where that gradient isn't enough. */
.scent-marquee__track .cat-tile__btn {
	left: 14px;
	bottom: 14px;
	padding: 0;
	background: none;
	border-radius: 0;
	color: #fff;
	font-size: 13px;
	font-weight: 500;
	text-transform: capitalize;
	text-decoration: underline;
	text-underline-offset: 5px;
	text-shadow: 0 1px 10px rgba(0, 0, 0, 0.45);
}
/* The shared .cat-tile hover fills the pill with a dark background — meaningless
   once it is plain text, and it would paint a block behind it again. */
.scent-marquee__track .cat-tile:hover .cat-tile__btn,
.scent-marquee__track .cat-tile:focus-visible .cat-tile__btn {
	background: none;
	color: #fff;
}
.scent-marquee__track .cat-tile__label sup { font-size: 11px; font-weight: 500; opacity: 0.8; }
@keyframes scent-marquee-scroll {
	from { transform: translateX(0); }
	to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
	.scent-marquee__track { animation: none; }
}
/* With JS the row is a real sideways scroller instead of a CSS animation: it
   still drifts on its own (main.js moves scrollLeft), but it can also be
   dragged, swiped or scrolled with a trackpad. Without JS the animation above
   stays as it was. */
.scent-marquee.is-scroller .scent-marquee__track { animation: none; }
.scent-marquee.is-scroller .scent-marquee__viewport {
	overflow-x: auto;
	overflow-y: hidden;
	scrollbar-width: none;
	overscroll-behavior-x: contain;
	cursor: grab;
}
.scent-marquee.is-scroller .scent-marquee__viewport::-webkit-scrollbar { display: none; }
.scent-marquee.is-scroller .scent-marquee__viewport.is-dragging { cursor: grabbing; user-select: none; }
.scent-marquee.is-scroller .scent-marquee__viewport.is-dragging .cat-tile { pointer-events: none; }
/* =========================================================
   Featured brands marquee
   ========================================================= */
.brand-marquee { padding-top: clamp(22px, 3.1vw, 35px); padding-bottom: 12px; overflow: hidden; text-align: center; }
.brand-marquee__viewport { width: 100%; overflow: hidden; mask-image: linear-gradient(90deg, transparent 0, #000 4%, #000 96%, transparent 100%); }
.brand-marquee__track {
	display: flex;
	align-items: center;
	width: max-content;
	/* No gap here on purpose -- see .brand-marquee__logo below. Duration is a
	   starting value only: main.js recomputes it from the final track width so
	   the band always scrolls at the same pixels-per-second. */
	animation: brand-marquee-scroll 25s linear infinite;
}
.brand-marquee:hover .brand-marquee__track { animation-play-state: paused; }
/* One repetition of the logo set, and the unit main.js clones. */
.brand-marquee__group { display: flex; align-items: center; flex: 0 0 auto; }
/* The spacing after each logo belongs to the logo, not to the track. A flex
   gap only applies *between* items, so the join between two groups came out one
   gap narrower than every other interval -- the loop point visibly jumped.
   As a margin the interval is identical everywhere, including across the seam. */
.brand-marquee__logo {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	height: 31px;
	margin-right: clamp(37px, 5.5vw, 74px);
}
.brand-marquee__img {
	max-height: 31px;
	max-width: 97px;
	width: auto;
	height: auto;
	object-fit: contain;
	filter: grayscale(1) opacity(0.55);
	transition: filter 0.25s ease;
}
.brand-marquee__logo:hover .brand-marquee__img { filter: grayscale(0) opacity(1); }
/* Etre alone is height-bound in the shared 31px/97px box (2.27:1 where every
   other mark is 3.9:1 or wider), so it rendered a full 31px tall against a row
   averaging ~18px. Capped to 24px, which puts it just above the widest of the
   width-bound marks (World of Make Scents, ~25px) instead of 25% over all of
   them. Sized here rather than by re-cropping the file -- the artwork is a
   correct 2560x1127 wordmark; only its proportion differs. */
.brand-marquee__logo--etre .brand-marquee__img { max-height: 24px; }

/* U-R THE SCENT hits the same trap harder: 675x303 is 2.23:1, squatter than
   Etre, so it too clamps to the full 31px. Same 24px cap, same reason. Note
   this mark is a bare "u-r" monogram rather than a wordmark -- it sits in a
   row of full brand names without naming its own brand. Capping is a size fix,
   not a legibility one; a proper lockup is what would actually solve that. */
.brand-marquee__logo--u-r-the-scent .brand-marquee__img { max-height: 24px; }

/* Centred "philosophy" block between the brand marquee and New Arrivals:
   heading + supporting paragraph + underlined text link. */
/* Generous air above and below: the paragraph is the one thing on screen while
   its words ink in (see .is-scrub below), and it needs the room to be read as
   a moment of its own rather than a caption under the logo row. */
.statement { padding-top: clamp(64px, 9vw, 140px); padding-bottom: clamp(64px, 9vw, 140px); text-align: center; }
.statement__title {
	font-family: var(--font-display);
	font-size: clamp(22px, 2.2vw, 29px);
	line-height: 1.2;
	margin: 0 0 16px;
	color: var(--color-ink);
}
.statement__text {
	/* The container's full inner width, so the paragraph takes as few lines as
	   the page allows -- four on a desktop at this size. */
	max-width: 1240px;
	margin: 0 auto;
	/* Keeps the lines close to equal length instead of leaving a short
	   orphan line with the italic phrase stranded on it. */
	text-wrap: balance;
	font-family: var(--font-base);
	/* Display-sized for a paragraph. */
	font-size: clamp(21px, 2vw, 29px);
	line-height: 1.55;
	color: var(--color-ink-soft);
}
/* Emphasised phrases sit a shade darker than the surrounding copy as well as
   heavier, so they read as emphasis rather than just a thicker grey. */
.statement__text strong,
.statement__text b { font-weight: 600; color: var(--color-ink); }

/* Scroll-scrubbed inking. main.js splits the paragraph into one span per
   letter and adds .is-scrub; from then on every letter is pale grey until it is
   given .is-lit, which happens in reading order as the paragraph moves up the
   window. Lit letters are full ink throughout -- the bold phrases keep their
   weight, which is now the only thing that sets them apart.

   Keyed to .is-scrub on purpose: with no JS, or under reduced motion (where the
   script stands down), the class never lands and the paragraph simply reads in
   its ordinary colours. The short transition is what turns a letter-by-letter
   switch into a soft leading edge. */
/* Plain inline, not inline-block: a box would let a line break fall between a
   bold phrase and the comma or full stop that follows it. */
.statement__word { white-space: nowrap; }
.statement__text.is-scrub .statement__char {
	color: rgba(19, 19, 19, 0.16);
	transition: color 0.35s ease;
}
.statement__text.is-scrub .statement__char.is-lit { color: var(--color-ink); }
.statement__accent { font-style: italic; }
.statement__link {
	display: inline-block;
	margin-top: clamp(28px, 3vw, 40px);
	font-family: var(--font-base);
	font-size: 15px;
	color: var(--color-ink);
	border-bottom: 1px solid var(--color-ink);
	padding-bottom: 4px;
	transition: color 0.2s ease, border-color 0.2s ease;
}
.statement__link:hover { color: var(--color-accent); border-bottom-color: var(--color-accent); }
@keyframes brand-marquee-scroll {
	from { transform: translateX(0); }
	to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
	.brand-marquee__track { animation: none; }
}
/* =========================================================
   Customer reviews ("Real People, Real Results")
   ========================================================= */
.reviews { padding-top: clamp(19px, 2.88vw, 34px); padding-bottom: clamp(40px, 6vw, 72px); background: var(--color-bg); }
.reviews__head {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 16px;
	margin-bottom: 24px;
}
.reviews__head h2 { margin: 0; }
.reviews__nav { display: flex; align-items: center; gap: 16px; }
.reviews__count { font-size: 14px; color: var(--color-ink-soft); white-space: nowrap; }
.reviews__arrow {
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid var(--color-border);
	background: transparent;
	color: var(--color-ink);
	font-size: 16px;
	cursor: pointer;
	transition: background 0.2s ease, color 0.2s ease;
}
.reviews__arrow:hover { background: var(--color-ink); color: #fff; }
.reviews__viewport {
	width: 100%;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
}
.reviews__viewport::-webkit-scrollbar { display: none; }
.reviews__track {
	display: flex;
	gap: var(--gutter);
	list-style: none;
	margin: 0;
	padding: 0 var(--gutter) 4px 0;
}
.review-card {
	flex: 0 0 calc((100% - 2 * var(--gutter)) / 3);
	min-width: 280px;
	scroll-snap-align: start;
	background: #fff;
	border-radius: var(--radius-md);
	padding: 28px 28px 24px;
	display: flex;
	flex-direction: column;
}
.review-card__name { margin: 0 0 12px; font-weight: 600; }
.review-card__quote { margin: 0; font-size: 14px; line-height: 1.6; color: var(--color-ink-soft); }
.review-card__product {
	margin-top: 24px;
	padding-top: 20px;
	border-top: 1px solid var(--color-border);
	display: flex;
	align-items: center;
	gap: 14px;
}
.review-card__product img {
	width: 48px;
	height: 48px;
	object-fit: cover;
	border-radius: var(--radius-sm);
	background: var(--color-bg-soft);
}
.review-card__product a { font-size: 14px; color: var(--color-ink); text-decoration: none; }
.review-card__product a:hover { text-decoration: underline; }
@media (max-width: 900px) {
	.review-card { flex: 0 0 85%; }
}

.cat-tile__btn {
	position: absolute;
	left: 16px;
	bottom: 16px;
	z-index: 2;
	background: #fff;
	color: var(--color-ink);
	font-size: 12px;
	font-weight: 600;
	text-transform: lowercase;
	padding: 8px 16px;
	border-radius: var(--radius-pill);
	transition: background 0.25s ease, color 0.25s ease;
}
/* The pill is a <span> inside the tile link, so the hover has to come from the
   tile — hovering the pill itself would only cover part of the clickable area. */
.cat-tile:hover .cat-tile__btn,
.cat-tile:focus-visible .cat-tile__btn {
	background: var(--color-accent-dark);
	color: #fff;
}

/* "All Brands" page grid -- square photo tiles, horizontal top-left label */
.brand-tile-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--gutter);
	padding-top: 40px;
	padding-bottom: 64px;
}
/* Square corners, deliberately: no border-radius here. The base .cat-tile carries
   none either, so the cards sit as hard-edged photo tiles. */
.brand-tile-grid .cat-tile { aspect-ratio: 1 / 1; }
.brand-tile-grid .cat-tile__label {
	writing-mode: horizontal-tb;
	transform: none;
	top: 20px;
	left: 20px;
	font-size: 18px;
	font-family: inherit;
	font-weight: 600;
}
.brand-tile-grid .cat-tile__btn {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	background: transparent;
	padding: 0;
	color: #fff;
	text-transform: none;
}
.brand-tile-grid .cat-tile__btn svg { width: 14px; height: 14px; flex-shrink: 0; }
/* These CTAs sit directly on the photograph rather than in a pill, so the
   shared .cat-tile:hover fill (a dark block behind the words) reads as a stray
   highlight. The hover is an underline on the label instead -- the chevron is
   outside the wrapper so the rule stops at the last letter. */
.brand-tile-grid .cat-tile:hover .cat-tile__btn,
.brand-tile-grid .cat-tile:focus-visible .cat-tile__btn {
	background: transparent;
	color: #fff;
}
.brand-tile-grid .cat-tile:hover .cat-tile__btn-label,
.brand-tile-grid .cat-tile:focus-visible .cat-tile__btn-label {
	text-decoration: underline;
	text-underline-offset: 4px;
	text-decoration-thickness: 1px;
}
/* Brand terms are stored in caps already ("AAMODINI"); olfactive families are not
   ("Amber & Oriental"), so the grid sets the case rather than the content. */
.brand-tile-grid--scent .cat-tile__label { text-transform: uppercase; }

/* ---------------------------------------------------------------------------
   Olfactive Families reel. One photograph held in the middle of the screen,
   the roster fixed to its left and that family's note to its right; the page
   scrolls and the strip steps through the families. Per the user's reference
   recording. Hidden until main.js adds .is-live -- without it (no JS, reduced
   motion, a screen too narrow for three columns) the tile grid below is the
   page, and with it the grid steps aside.
   --------------------------------------------------------------------------- */
.family-reel { display: none; }
.family-reel.is-live {
	display: block;
	position: relative;
	/* Square frame: as tall as the screen allows with a neighbour showing above
	   and below, never wider than the middle column can give it. */
	--reel-size: min(46vh, 30vw, 440px);
	--reel-gap: clamp(20px, 3.5vh, 32px);
}
/* The frame is centred in a stage as tall as the screen, which leaves half the
   spare height empty above it -- far too much under the intro. Pull the reel up
   by that spare half, less the gap we do want, so the first photograph starts
   a short step below the intro. The intro stays on top while they overlap. */
.family-reel.is-live {
	margin-top: calc(-1 * max(0px, (100vh - var(--announcement-h, 0px) - var(--header-h) - var(--reel-size)) / 2 - 40px));
}
body.is-white-page .page-intro:has(+ .family-reel.is-live) { position: relative; z-index: 3; }
.family-reel.is-live + .family-grid-fallback { display: none; }
.family-reel__stage {
	position: sticky;
	top: calc(var(--announcement-h, 0px) + var(--header-h));
	height: calc(100vh - var(--announcement-h, 0px) - var(--header-h));
	overflow: hidden;
}
.family-reel__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr) var(--reel-size) minmax(0, 1fr);
	gap: clamp(32px, 5vw, 80px);
	align-items: center;
	height: 100%;
}
.family-reel__list {
	list-style: none;
	margin: 0;
	padding: 0;
	justify-self: end;
	width: min(100%, 250px);
}
.family-reel__name {
	display: flex;
	justify-content: space-between;
	gap: 24px;
	width: 100%;
	padding: 5px 0;
	font-family: var(--font-base);
	font-size: 11.5px;
	font-weight: 500;
	line-height: 1.4;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	text-align: left;
	color: #a3a3a3;
	transition: color 0.25s ease;
}
.family-reel__name:hover,
.family-reel__name.is-active { color: var(--color-ink); }
.family-reel__name.is-active { font-weight: 700; }
.family-reel__count { white-space: nowrap; }
.family-reel__window {
	position: relative;
	height: 100%;
}
.family-reel__strip {
	position: absolute;
	top: 50%;
	left: 0;
	width: 100%;
	margin-top: calc(var(--reel-size) / -2);
	display: flex;
	flex-direction: column;
	gap: var(--reel-gap);
	will-change: transform;
}
.family-reel__frame {
	display: block;
	flex: none;
	width: var(--reel-size);
	height: var(--reel-size);
	background: #f3f3f3;
	overflow: hidden;
}
.family-reel__frame img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
/* The neighbours wash out to the page at the top and bottom of the screen. */
.family-reel__window::before,
.family-reel__window::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	z-index: 1;
	height: 16%;
	pointer-events: none;
}
.family-reel__window::before { top: 0; background: linear-gradient(#fff, rgba(255, 255, 255, 0)); }
.family-reel__window::after { bottom: 0; background: linear-gradient(rgba(255, 255, 255, 0), #fff); }
/* Four corner ticks standing just off the frame that is in the middle. */
.family-reel__brackets {
	position: absolute;
	top: 50%;
	left: 50%;
	z-index: 2;
	width: calc(var(--reel-size) + 18px);
	height: calc(var(--reel-size) + 18px);
	transform: translate(-50%, -50%);
	pointer-events: none;
}
.family-reel__brackets i {
	position: absolute;
	width: 11px;
	height: 11px;
	border: 0 solid var(--color-ink);
}
.family-reel__brackets i:nth-child(1) { top: 0; left: 0; border-top-width: 1px; border-left-width: 1px; }
.family-reel__brackets i:nth-child(2) { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.family-reel__brackets i:nth-child(3) { bottom: 0; left: 0; border-bottom-width: 1px; border-left-width: 1px; }
.family-reel__brackets i:nth-child(4) { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }
/* Every note sits in the same cell, so the column is as tall as the longest
   one and the text does not jump about as they swap. */
.family-reel__notes {
	display: grid;
	align-items: center;
	max-width: 300px;
}
.family-reel__note {
	grid-area: 1 / 1;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0s 0.3s;
}
.family-reel__note.is-active {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.3s ease;
}
.family-reel__text {
	margin: 0 0 18px;
	font-family: var(--font-base);
	font-size: 14px;
	line-height: 1.7;
	color: var(--color-ink);
}
.family-reel__link {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding-bottom: 3px;
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--color-ink);
	border-bottom: 1px solid var(--color-ink);
}
.family-reel__link:hover { border-bottom-color: transparent; }
.family-reel__link svg { width: 14px; height: 14px; flex-shrink: 0; }
/* The scale at either edge of the screen; its marker rides down as the reel
   advances. Only where there is margin to spare for it. */
.family-reel__ruler {
	position: absolute;
	top: 50%;
	width: 12px;
	height: 108px;
	margin-top: -54px;
	background: repeating-linear-gradient(#c9c9c9 0 1px, transparent 1px 6px);
}
.family-reel__ruler--left { left: 22px; }
.family-reel__ruler--right { right: 22px; }
.family-reel__ruler i {
	position: absolute;
	top: 0;
	width: 22px;
	height: 1px;
	background: var(--color-ink);
}
.family-reel__ruler--left i { left: 0; }
.family-reel__ruler--right i { right: 0; }
@media (max-width: 1180px) {
	.family-reel__ruler { display: none; }
}
@media (max-width: 1100px) {
	.brand-tile-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 700px) {
	.brand-tile-grid { grid-template-columns: repeat(2, 1fr); }
	/* Two columns put the CTA in a ~158px tile at phone widths, where the two
	   longest labels ("Shop Green & Aromatic", "Shop Leather & Tobacco") wrapped
	   to a second line and stranded the chevron on its own row. Room is bought
	   back from the inset and the gap first, then the type scales with the
	   viewport rather than dropping to a flat small size -- at 430px and up
	   there is space for the full 12px, so only the narrow end pays for it.
	   Deliberately NOT white-space: nowrap -- .cat-tile is overflow: hidden, so
	   below ~360px a nowrap label would be clipped mid-word. Wrapping is the
	   better failure. */
	.brand-tile-grid .cat-tile__btn {
		left: 12px;
		gap: 6px;
		font-size: clamp(10px, calc(3.6vw - 3.5px), 12px);
	}
	/* Brand names run longer than family names -- "Shop World Of Make Scents"
	   needs 134px where "Shop Citrus" needs 89 -- so the brands grid gets the
	   same technique tuned to its own longest label rather than dragging the
	   families down to a size only one page needs. The chevron gives up 2px
	   here as well. Only two grids use this class, and --scent is the other. */
	.brand-tile-grid:not(.brand-tile-grid--scent) .cat-tile__btn {
		left: 10px;
		gap: 4px;
		font-size: clamp(9px, calc(3.2vw - 2.5px), 12px);
	}
	.brand-tile-grid:not(.brand-tile-grid--scent) .cat-tile__btn svg {
		width: 12px;
		height: 12px;
	}
}

/* =========================================================
   Editorial section
   ========================================================= */
.editorial__grid {
	display: grid;
	grid-template-columns: 0.9fr 1.1fr;
	gap: clamp(32px, 6vw, 80px);
	align-items: center;
}
.editorial__text p { color: var(--color-ink-soft); margin: 20px 0 28px; max-width: 440px; }
.editorial__text h2 { text-transform: lowercase; margin-bottom: 4px; }
.editorial__media { position: relative; display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.editorial__img { border-radius: var(--radius-md); object-fit: cover; }
.editorial__img--1 { grid-column: 1 / 3; aspect-ratio: 16/9; }
.editorial__img--2 { aspect-ratio: 3/4; }
.editorial__img--3 { aspect-ratio: 1/1; align-self: end; }

/* =========================================================
   Welcome offer band (soft grey-to-white gradient, two columns)
   ========================================================= */
.welcome-offer {
	position: relative;
	background: linear-gradient(115deg, #f0f0f0 0%, #f8f8f8 55%, #ffffff 100%);

	color: var(--color-ink);
	padding-top: clamp(48px, 7vw, 104px);
	padding-bottom: clamp(48px, 7vw, 104px);
	overflow: hidden;
}
.welcome-offer__inner {
	--welcome-gap: clamp(32px, 6vw, 80px);
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 1fr 1fr;
	align-items: center;
	gap: var(--welcome-gap);
	text-align: center;
}
/* Hairline divider between the two columns, drawn on the second one so it
   never renders on its own when the layout collapses to a single column.
   Pulled back by half the gap so it lands on the container's true centre —
   the start of the second track sits half a gap to the right of it — with a
   matching pad so the column's own content stays where it was. */
.welcome-offer__col + .welcome-offer__col {
	border-left: 1px solid #d6d6d6;
	margin-left: calc(var(--welcome-gap) / -2);
	padding-left: calc(var(--welcome-gap) / 2);
}
/* Typography follows the founders quote panel: Plus Jakarta Sans throughout,
   near-black copy with the secondary lines stepped back via --color-ink-soft. */
.welcome-offer__eyebrow {
	font-family: var(--font-base);
	text-transform: uppercase;
	letter-spacing: 0.16em;
	font-size: 11.5px;
	font-weight: 700;
	color: var(--color-ink-soft);
	margin: 0 0 22px;
}
.welcome-offer__heading {
	/* Serif display face, like every other section heading. The negative tracking
	   was there to tighten Plus Jakarta Sans at size; Instrument Serif doesn't
	   need it. */
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(28px, 3vw, 40px);
	line-height: 1.25;
	letter-spacing: 0;
	color: var(--color-ink);
	margin: 0 0 26px;
}
.welcome-offer__fineprint {
	font-family: var(--font-base);
	font-size: 13px;
	color: var(--color-ink-soft);
	margin: 0;
}
/* Styled as an eyebrow rather than a heading, matching .welcome-offer__eyebrow
   in the left column — it reads as a label above the supporting copy, not as a
   second display headline competing with the offer. */
.welcome-offer__title {
	font-family: var(--font-base);
	font-weight: 700;
	text-transform: uppercase;
	font-size: 11.5px;
	line-height: 1.25;
	letter-spacing: 0.16em;
	color: var(--color-ink-soft);
	margin: 0 0 16px;
}
.welcome-offer__text {
	font-family: var(--font-base);
	font-size: 14px;
	line-height: 1.6;
	color: var(--color-ink-soft);
	/* Wide enough to hold the line without wrapping. */
	max-width: none;
	margin: 0 auto 22px;
	white-space: nowrap;
}
.welcome-offer__btn {
	background: var(--color-navy);
	color: #fff;
	border: 1px solid var(--color-navy);
	border-radius: 0;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 12px;
	font-weight: 600;
	padding: 16px 34px;
	transition: background 0.2s ease, color 0.2s ease;
}
.welcome-offer__btn:hover { background: transparent; color: var(--color-navy); }
/* The signup field, deliberately the same object as the popup's: a bordered
   white box with the submit as text inside it, not a pill with a round arrow.
   The two are the same offer in two places, so they should look like it. Left
   on .newsletter__form's base so main.js still binds it. */
/* Both classes in the selector, not just the modifier: .newsletter__form is
   defined further down this file and would otherwise win on source order at
   equal specificity, leaving the field a pill with the base font size. The
   popup's equivalent block only escapes this by sitting below .newsletter__form
   -- which is luck, not design. */
.newsletter__form.welcome-offer__form {
	max-width: 420px;
	margin: 0 auto;
	border-radius: 2px;
	padding: 0 0 0 18px;
	gap: 0;
	min-height: 48px;
}
.newsletter__form.welcome-offer__form input { font-size: 15px; }
.newsletter__form.welcome-offer__form input::placeholder { color: var(--color-ink-soft); }
.welcome-offer__submit {
	flex: 0 0 auto;
	align-self: stretch;
	width: auto;
	height: auto;
	padding: 0 22px;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--color-ink);
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	cursor: pointer;
	transition: opacity 0.2s ease;
}
.welcome-offer__submit:hover { opacity: 0.55; background: transparent; }
/* Same narrow-screen adjustment the popup's field gets, at the same breakpoint,
   so the two do not drift apart on a phone. */
@media (max-width: 600px) {
	.newsletter__form.welcome-offer__form { padding-left: 16px; min-height: 50px; }
	.welcome-offer__submit { padding: 0 16px; }
}
/* Centred with the rest of the column, and holding its line whether or not
   there is a message -- .newsletter__status already reserves the height, so the
   band does not jump when the reply arrives. */
.welcome-offer__status { text-align: center; }

@media (max-width: 820px) {
	/* Stack the columns; the divider becomes a horizontal rule between them. */
	.welcome-offer__inner { grid-template-columns: 1fr; gap: 36px; }
	/* The one-line rule is a desktop treatment; let it wrap on narrow screens. */
	.welcome-offer__text { white-space: normal; }
	.welcome-offer__col + .welcome-offer__col {
		border-left: 0;
		border-top: 1px solid var(--color-border);
		/* Undo the desktop half-gap offset — the rule is horizontal here. */
		margin-left: 0;
		padding-left: 0;
		padding-top: 36px;
	}
}

/* =========================================================
   Display band
   ========================================================= */
.display-band {
	position: relative;
	background: var(--color-ink);
	color: #fff;
	text-align: center;
	padding-block: clamp(56px, 10vw, 140px) clamp(48px, 8vw, 100px);
	overflow: hidden;
}
.display-band__circles {
	position: absolute;
	inset: 0;
	z-index: 0;
}
.display-band__circle {
	position: absolute;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.07);
}
.display-band__circle--1 { width: 220px; height: 220px; top: 6%; left: 50%; transform: translateX(-20%); }
.display-band__circle--2 { width: 420px; height: 420px; top: 28%; left: 50%; transform: translateX(-65%); }
.display-band__circle--3 { width: 160px; height: 160px; top: 60%; left: 55%; }
.display-band__text {
	position: relative;
	z-index: 1;
	font-size: clamp(56px, 11vw, 160px);
	font-weight: 800;
	line-height: 0.92;
	letter-spacing: -0.02em;
	text-transform: lowercase;
	margin: 0;
}
.display-band__products {
	position: relative;
	z-index: 1;
	display: flex;
	justify-content: center;
	align-items: flex-end;
	gap: clamp(16px, 3vw, 40px);
	list-style: none;
	margin: clamp(8px, 3vw, 32px) 0 0;
	padding: 0;
}
.display-band__product {
	width: clamp(70px, 9vw, 130px);
	aspect-ratio: 3 / 4;
	overflow: hidden;
	mask-image: radial-gradient(closest-side, #000 78%, transparent 100%);
	-webkit-mask-image: radial-gradient(closest-side, #000 78%, transparent 100%);
}
.display-band__product img {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
	transform: scale(1.6);
	filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.35));
}
.display-band__product:nth-child(3) { width: clamp(90px, 11vw, 160px); }
.display-band__sub {
	position: relative;
	z-index: 1;
	max-width: 620px;
	margin: clamp(32px, 6vw, 56px) auto 0;
	color: rgba(255, 255, 255, 0.75);
	font-size: 15px;
	line-height: 1.6;
}
.display-band__cta {
	position: relative;
	z-index: 1;
	display: inline-block;
	margin-top: 28px;
}

/* =========================================================
   Promo countdown
   ========================================================= */
.promo-countdown {
	position: relative;
	overflow: hidden;
	color: #fff;
	padding-block: clamp(28px, 5vw, 44px);
}
.promo-countdown__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}
.promo-countdown__media .satueen-img,
.promo-countdown__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	filter: brightness(0.55) saturate(1.1);
}
.promo-countdown__media::after {
	content: '';
	position: absolute;
	inset: 0;
	background: rgba(19, 19, 19, 0.35);
}
.promo-countdown__inner {
	position: relative;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: 24px;
}
.promo-countdown__title {
	font-family: var(--font-display);
	font-style: italic;
	font-size: clamp(20px, 2.6vw, 28px);
	margin: 0 0 4px;
}
.promo-countdown__text { margin: 0; font-size: 14px; color: rgba(255, 255, 255, 0.85); }
.promo-countdown__timer {
	display: flex;
	align-items: center;
	gap: clamp(10px, 2vw, 24px);
}
.promo-countdown__unit { text-align: center; min-width: 48px; }
.promo-countdown__value {
	display: block;
	font-family: var(--font-display);
	font-style: italic;
	font-size: clamp(22px, 3vw, 32px);
	line-height: 1;
}
.promo-countdown__label {
	display: block;
	margin-top: 4px;
	font-size: 11px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.7);
}
.promo-countdown__sep { opacity: 0.4; font-size: 20px; }
@media (max-width: 700px) {
	.promo-countdown__inner { justify-content: center; text-align: center; }
}

/* =========================================================
   Payday promo strip (front-page.php, above Best Sellers)
   =========================================================
   A single-row band, unlike the .promo-countdown band above it, which is a tall
   photographic one. Navy, the same --color-navy as the announcement bar, so the
   page's two promotional strips read as one system rather than two unrelated
   interruptions. It was sand before. */
/* Promo band. Was a 22px navy strip; rebuilt as a full photographic section
   on the user's reference. The photograph is the ground and the type sits on
   it, so every rule here is about keeping white text legible over an image
   whose contents we do not control. */
.payday-band {
	position: relative;
	isolation: isolate;
	background: var(--color-navy);
	color: #fff;
	padding: clamp(56px, 7vw, 104px) 0;
	overflow: hidden;
}
/* The flex lives on the inner wrapper, never on the section: the timer hides
   the section with the `hidden` attribute when it runs out, and `display:flex`
   on the element itself would beat `hidden` and leave the band on screen.
   Belt and braces, since that exact collision has bitten the cart drawer and
   the quick-view overlay before. */
.payday-band[hidden] { display: none; }

/* inset:0 + object-fit rather than a background-image, so the photograph goes
   through wp_get_attachment_image() and gets srcset for free. */
.payday-band__media {
	position: absolute;
	inset: 0;
	z-index: -2;
}
.payday-band__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* The scrim is what makes this safe for ANY photograph the Customizer points
   at. Weighted to the left, where the copy sits, and never fully clearing on
   the right -- the countdown needs a ground too. Without it the band is one
   pale upload away from white-on-white. */
.payday-band--has-image::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background:
		linear-gradient(90deg, rgba(28, 40, 54, 0.88) 0%, rgba(28, 40, 54, 0.72) 45%, rgba(28, 40, 54, 0.52) 100%);
}

.payday-band__inner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: clamp(32px, 5vw, 72px);
	flex-wrap: wrap;
}
.payday-band__copy {
	max-width: 46ch;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 14px;
}
.payday-band__eyebrow {
	margin: 0;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.72);
}
/* Instrument Serif at 400: the face ships regular and italic only, so any
   heavier weight here would be the browser's synthetic bold smearing its
   high-contrast strokes. Size carries the emphasis instead. */
.payday-band__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(32px, 4.4vw, 56px);
	line-height: 1.08;
	letter-spacing: -0.01em;
	text-wrap: balance;
}
.payday-band__text {
	margin: 0;
	max-width: 42ch;
	font-size: 15px;
	line-height: 1.55;
	color: rgba(255, 255, 255, 0.86);
}
/* Square and white-on-navy, carried over from the strip: the near-black the
   button once used all but disappears against this ground. */
.payday-band__btn {
	margin-top: 6px;
	display: inline-flex;
	align-items: center;
	padding: 15px 34px;
	border-radius: 0;
	background: #fff;
	color: var(--color-navy);
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	white-space: nowrap;
}
.payday-band__btn:hover { background: var(--color-blue); color: var(--color-navy); }

.payday-band__timer {
	display: flex;
	align-items: flex-start;
	gap: clamp(10px, 1.4vw, 20px);
	/* Tabular figures so the seconds column does not change width as it counts
	   -- with proportional digits the whole row twitches once a second. */
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
}
.payday-band__unit {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	min-width: 2.4ch;
}
.payday-band__value {
	font-size: clamp(34px, 4vw, 52px);
	font-weight: 400;
	line-height: 1;
	letter-spacing: 0.01em;
}
/* The unit name is the point of the redesign -- "108" on its own does not say
   days. Small and letterspaced so it reads as a caption under the figure
   rather than competing with it. */
.payday-band__unit-label {
	font-size: 10.5px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.6);
	white-space: nowrap;
}
/* Aligned to the digits, not the column: the unit is a two-line stack, so a
   centred colon would sit between the number and its label. */
.payday-band__sep {
	font-size: clamp(22px, 2.4vw, 32px);
	line-height: 1;
	opacity: 0.32;
	padding-top: 0.12em;
}

/* The copy and the countdown stop sharing a row well before the photograph
   stops working, so the timer drops under the copy and keeps the left edge
   rather than centring on its own. */
@media (max-width: 1080px) {
	.payday-band__inner { flex-direction: column; align-items: flex-start; }
	.payday-band__copy { max-width: none; }
	.payday-band__timer { align-self: flex-start; }
}
@media (max-width: 560px) {
	.payday-band { padding: 48px 0; }
	.payday-band__btn { width: 100%; justify-content: center; }
	.payday-band__timer { gap: 8px; }
	.payday-band__unit { min-width: 2.2ch; }
	/* The scrim turns vertical on a phone: the layout is a single column, so
	   there is no longer a quiet right-hand side for the gradient to open to. */
	.payday-band--has-image::after {
		background: linear-gradient(180deg, rgba(28, 40, 54, 0.82) 0%, rgba(28, 40, 54, 0.78) 100%);
	}
}

/* =========================================================
   Brand archive banner + intro (taxonomy-brand.php)
   ========================================================= */
.brand-banner {
	position: relative;
	height: clamp(256px, 30.4vw, 448px);
	overflow: hidden;
	background: var(--color-bg);
}
.brand-banner img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
@media (max-width: 820px) {
	.brand-banner { height: clamp(176px, 48vw, 288px); }
}

.brand-intro {
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: 40px;
	padding-block: 40px 24px;
}
.brand-intro h1 { font-size: clamp(28px, 3vw, 38px); margin: 0; }
.brand-intro__logo { height: clamp(28px, 4vw, 44px); width: auto; max-width: 240px; object-fit: contain; }
.brand-intro__desc { color: var(--color-ink-soft); max-width: 560px; font-size: 14px; line-height: 1.6; margin: 0; }
@media (max-width: 700px) {
	.brand-intro { flex-direction: column; gap: 16px; }
}

/* =========================================================
   Commitments
   ========================================================= */
.commitments {
	display: grid;
	grid-template-columns: 1fr 1fr;
	background: var(--color-accent);
	color: #fff;
	padding: 0;
}
.commitments__media { min-height: 420px; }
.commitments__media img { width: 100%; height: 100%; object-fit: cover; }
.commitments__text {
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: clamp(32px, 5vw, 64px);
	gap: 16px;
}
.commitments__text h2 { text-transform: lowercase; }
.commitments__text p { color: rgba(255,255,255,0.85); max-width: 420px; }
.commitments__text .btn { align-self: flex-start; margin-top: 8px; }

/* =========================================================
   Journal
   ========================================================= */
.journal__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--gutter);
}
.journal-card__img { aspect-ratio: 1/1; object-fit: cover; border-radius: var(--radius-md); margin-bottom: 12px; }
.journal-card__title { font-size: 14px; font-weight: 500; }

/* =========================================================
   Newsletter
   ========================================================= */
.newsletter { background: var(--color-band); padding-block: clamp(48px, 7vw, 88px); }
.newsletter__inner { max-width: 620px; text-align: center; margin: 0 auto; }
/* Homepage variant: one centred row — copy, then the field — with the legal
   line beneath it, and the whole band 40% shorter than the stacked version. */
/* A touch more height and side gap to carry the wider field. */
.newsletter--split { padding-block: clamp(34px, 4.8vw, 62px); }
.newsletter--split .newsletter__inner {
	max-width: none;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 16px clamp(28px, 3.4vw, 52px);
	text-align: left;
}
.newsletter--split .newsletter__col--copy { order: -1; }
.newsletter--split .newsletter__inner h2 {
	margin-bottom: 4px;
	font-family: var(--font-hero);
	font-size: clamp(25px, 2.3vw, 32px);
	line-height: 1.2;
}
.newsletter--split .newsletter__inner p { margin-bottom: 0; font-size: 14px; }
/* Wider field so the pill balances the headline beside it rather than reading as
   a small tacked-on control. The width has to sit on the column, not the form:
   the column is a flex item sized to its content, so a percentage width on the
   form inside it resolves against a shrink-to-fit parent and collapses. Width,
   not flex-basis — the row turns into a column under 780px, where a basis would
   set the height instead. */
.newsletter--split .newsletter__col--form { width: min(520px, 100%); }
.newsletter--split .newsletter__form { margin: 0; width: 100%; }
.newsletter--split .newsletter__legal {
	flex-basis: 100%;
	margin-top: 4px;
	text-align: center;
	font-size: 12px;
}
@media (max-width: 780px) {
	/* Stacked and centred: the row can't hold copy and field side by side. */
	.newsletter--split .newsletter__inner { flex-direction: column; text-align: center; }
	.newsletter--split .newsletter__col--form { width: 100%; }
}
.newsletter--new-arrivals .newsletter__inner { max-width: 800px; }
.newsletter--new-arrivals .newsletter__inner h2 { white-space: nowrap; }
@media (max-width: 700px) {
	.newsletter--new-arrivals .newsletter__inner h2 { white-space: normal; }
}
.newsletter__inner h2 { margin-bottom: 12px; }
.newsletter__inner p { color: var(--color-ink-soft); margin-bottom: 28px; }
.newsletter__form {
	display: flex;
	align-items: center;
	gap: 10px;
	background: #fff;
	border-radius: var(--radius-pill);
	padding: 6px 6px 6px 22px;
	border: 1px solid #d6d6d6;
}
.newsletter__form input {
	flex: 1;
	border: none;
	outline: none;
	background: transparent;
	font-size: 14px;
}
.newsletter__submit {
	flex: 0 0 auto;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	border: none;
	background: var(--color-navy);
	color: #fff;
	font-size: 16px;
	cursor: pointer;
	transition: background 0.2s ease;
}
/* --color-accent-dark is the lighter slate a step up from navy, so the hover
   still reads as a lift now that the resting state is navy rather than ink. */
.newsletter__submit:hover { background: var(--color-accent-dark); }
.newsletter__status { font-size: 13px; margin-top: 12px; min-height: 18px; }
.newsletter__status[data-state="error"] { color: #b3261e; }
.newsletter__status[data-state="success"] { color: var(--color-accent-dark); }
.newsletter__legal { font-size: 13px; color: var(--color-ink-faint); margin-top: 16px; }
.newsletter__legal a { color: var(--color-ink-faint); text-decoration: underline; text-underline-offset: 2px; }
.newsletter__legal a:hover { color: var(--color-ink); }

/* =========================================================
   Footer
   ========================================================= */
.site-footer { background: #000; color: rgba(255, 255, 255, 0.92); }
.footer-top {
	max-width: var(--container-width);
	margin: 0 auto;
	padding: clamp(48px, 7vw, 88px) var(--gutter) 56px;
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 48px;
}
.footer-brand {
	flex: 1 1 320px;
	max-width: 520px;
	display: flex;
	flex-direction: column;
	gap: 20px;
}
.footer-logo {
	display: inline-block;
	width: 140px;
	height: 30px;
	background-color: var(--color-bg);
	-webkit-mask-image: var(--footer-logo-src);
	mask-image: var(--footer-logo-src);
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: left center;
	mask-position: left center;
	-webkit-mask-size: contain;
	mask-size: contain;
}
.footer-logo-text {
	font-family: var(--font-display);
	font-size: 22px;
	color: var(--color-bg);
}
.footer-tagline {
	/* Sans, matching the copyright line in the footer bottom — the serif read as
	   a display face in a block that is really supporting text. */
	font-family: var(--font-base);
	font-size: clamp(11px, 1vw, 12px);
	line-height: 1.5;
	color: #fff;
	margin: 0;
}
/* Registered entity and contact details, under the tagline. <address> is
   italic by default in every browser — reset it. */
.footer-address {
	margin: 16px 0 0;
	font-style: normal;
	font-family: var(--font-base);
	font-size: clamp(11px, 1vw, 12px);
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.75);
}
.footer-address__line { display: block; }
.footer-address__email {
	display: inline-block;
	margin-top: 10px;
	color: #fff;
	text-decoration: none;
	border-bottom: 1px solid rgba(255, 255, 255, 0.35);
	transition: border-color 0.2s ease;
}
.footer-address__email:hover { border-bottom-color: #fff; }
.footer-columns {
	flex: 2 1 560px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 32px;
	max-width: 760px;
}
.footer-col h3 { font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 18px; color: rgba(255, 255, 255, 0.55); }
.footer-col ul, .footer-menu { display: flex; flex-direction: column; gap: 10px; list-style: none; margin: 0; padding: 0; }
.footer-col a { font-size: 14px; color: rgba(255, 255, 255, 0.85); }
.footer-col a:hover { color: #fff; }

/* Payment marks. A row of white tiles on the navy footer, sitting above the
   copyright line rather than inside it -- the bottom row is a two-item
   space-between and a third child would push the two apart. */
.payment-marks {
	/* Lives in the footer's brand column, under the email -- so it takes the
	   column's own left edge rather than centring on the page. */
	margin: 26px 0 0;
	padding: 0;
}
.payment-marks__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-start;
	gap: 8px;
}
.payment-marks__tile {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 58px;
	height: 36px;
	padding: 4px 5px;
	background: #fff; /* fallback only -- each slug sets its own below */
	border-radius: 5px;
}
.payment-marks__tile svg {
	display: block;
	width: 100%;
	height: auto;
}

/* Each mark wears its own official badge colour rather than all five sharing
   one white tile. A white tile is still the right ground for UnionPay and
   PayNow -- their artwork is dark and would otherwise vanish into the navy. */
.payment-marks__tile--visa { background: #1434CB; }
.payment-marks__tile--mastercard { background: #000; }
.payment-marks__tile--amex { background: #006FCF; }
.payment-marks__tile--unionpay,
.payment-marks__tile--paynow { background: #fff; }

.footer-bottom {
	max-width: var(--container-width);
	margin: 0 auto;
	padding: 20px var(--gutter);
	border-top: 1px solid rgba(255, 255, 255, 0.14);
	display: flex;
	justify-content: space-between;
	font-size: 12px;
	color: rgba(255, 255, 255, 0.55);
}
@media (max-width: 700px) {
	.footer-columns { grid-template-columns: repeat(2, 1fr); }
}

/* =========================================================
   WooCommerce — shop / archive
   ========================================================= */
/* Centred title over a centred standfirst, with the toolbar as a full-width
   rule beneath -- the archive opens like an editorial page rather than a
   left-aligned index. */
.shop-header { padding-block: 56px 22px; text-align: center; }
.shop-header h1 { font-size: clamp(28px, 3vw, 38px); }
.shop-header__desc {
	color: var(--color-ink-soft);
	max-width: 620px;
	margin: 14px auto 0;
	font-size: 15px;
	line-height: 1.6;
}

.shop-empty { color: var(--color-ink-soft); padding-block: 40px; }

.new-arrivals-promo { margin-top: 32px; }
.new-arrivals-promo .promo-countdown__inner { justify-content: center; text-align: center; }

.new-arrivals-grid { padding-top: 56px; padding-bottom: 64px; }
.new-arrivals-grid ul.products { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 980px) {
	.new-arrivals-grid ul.products { grid-template-columns: repeat(2, 1fr) !important; }
}

/* Single column since the filter sidebar was removed. The .is-filters-hidden
   class is what the product grid keys its four-across rule off, so the archive
   still carries it. */
.shop-layout {
	display: grid;
	grid-template-columns: 1fr;
	padding-bottom: 64px;
	align-items: start;
}

.shop-main { min-width: 0; }
/* Three tracks rather than flex: the outer 1fr columns are equal whatever the
   toggle and the sort control measure, which is what keeps the count centred
   on the page instead of centred in the space they happen to leave. */
.shop-toolbar {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	gap: 16px;
	padding-bottom: 22px;
	margin-bottom: 32px;
	font-size: 13px;
	color: var(--color-ink-soft);
}
.shop-toolbar__count { white-space: nowrap; text-align: center; }
.shop-toolbar__sort {
	display: flex;
	align-items: center;
	gap: 12px;
	justify-self: end;
}
.shop-toolbar__sort-label { white-space: nowrap; }
/* woocommerce_catalog_ordering() emits its own <form>, which would otherwise
   sit as a block and drop the select onto its own line. */
.shop-toolbar__sort .woocommerce-ordering { margin: 0; }
.shop-toolbar select {
	border: 1px solid var(--color-ink);
	border-radius: 0;
	padding: 12px 16px;
	font-size: 14px;
	color: var(--color-ink);
	background: #fff;
}
/* The rule runs the full container width under the whole toolbar, rather than
   only under the product column the toolbar used to live in. */
.shop-layout { border-top: 1px solid var(--color-border); padding-top: 32px; }
/* Below this the count and the sort control no longer fit on one line. */
@media (max-width: 720px) {
	.shop-toolbar {
		grid-template-columns: 1fr;
		justify-items: center;
		gap: 14px;
	}
	/* Stacked, the empty centring track would otherwise add a blank first row. */
	.shop-toolbar > [aria-hidden="true"] { display: none; }
	.shop-toolbar__sort { justify-self: center; }
}

ul.products {
	display: grid !important;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--gutter) !important;
	margin: 0 !important;
	padding: 0 !important;
}
ul.products li.product { list-style: none; }
.shop-layout.is-filters-hidden ul.products { grid-template-columns: repeat(4, 1fr); }

.brand-shop { padding-bottom: clamp(48px, 8vw, 96px); }
.brand-shop ul.products { grid-template-columns: repeat(4, 1fr); }

.woocommerce-pagination { margin-top: 48px; text-align: center; }
.woocommerce-pagination ul { display: inline-flex; gap: 8px; }
.woocommerce-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	font-size: 13px;
}
.woocommerce-pagination .page-numbers.current { background: var(--color-ink); color: #fff; }
.woocommerce-pagination .page-numbers:hover:not(.current) { background: var(--color-bg-soft); }

/* =========================================================
   WooCommerce — single product
   ========================================================= */
.product-page {
	display: grid;
	/* Was 1.1fr 1fr -- the gallery was the wider of the two columns, and since
	   the frame is 3:4 its width sets its height. At that width the photograph
	   ran a long way past the foot of the summary beside it. Narrower than the
	   summary now, so the two columns finish at roughly the same place.

	   0.85 rather than the 0.72 that followed, because 0.72 made the right-hand
	   column half again as wide as the photograph. The block was centred on the
	   page either way -- both gutters measure the same -- but a heavy picture on
	   the left against short lines of type on the right reads as a page that has
	   drifted, and the empty stretch beyond the price is what you see. Closer to
	   even, with the whole thing held to 1240px rather than the site's 1320, and
	   the two sides carry about the same weight.

	   minmax(0, ...) on both tracks is what keeps every product page the same
	   shape. An `fr` track is really minmax(auto, fr), and auto is min-content --
	   so the thumbnail row, which does not wrap, was setting a floor under the
	   gallery column: six thumbs measure 564px, and a six-photograph product got
	   a 564px column and a 752px-tall frame while a five-photograph one got 500
	   and 667. That is why World of Make Scents and Être stood taller than
	   Scentrum, Elaya and Aamodini. With a 0 floor the ratio decides the width
	   on every product, and a row of thumbs too wide for it scrolls instead. */
	grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
	max-width: 1240px;
	gap: clamp(32px, 5vw, 72px);
	padding-block: 48px;
}
.product-gallery { display: flex; flex-direction: column; gap: 16px; position: sticky; top: 100px; height: 100%; }
/* One fixed 3:4 frame for the whole catalogue, so every product page presents
   its photographs at the same size. The shape used to be set inline per product
   from its lead image; that held steady within a strip but not between products
   -- a portrait lead gave a tall frame and a 1024x1024 lead gave a short square
   one, and the two did not match side by side.

   cover, not contain: most of the catalogue is 769x1024, which is exactly 3:4
   and so is untouched, and the square phone shots fill the frame instead of
   sitting letterboxed and visibly smaller than the slide before them. The cost
   is ~12.5% off each side of a square shot -- the bottles are centred, so that
   is edge margin, but a shot with a caption right at the edge will clip. */
.product-gallery__viewport { position: relative; flex: none; min-height: 0; aspect-ratio: 3 / 4; background: transparent; }
.product-gallery__main { border-radius: 0; display: block; width: 100%; height: 100%; object-fit: cover; }
/* The prev/next arrows are gone -- every photograph is already a thumbnail, so
   the arrows were a second control for the same job, and they sat over the
   bottle to offer it. .product-gallery__arrow rules removed with them. */

/* A row of thumbnails under the frame -- where the strip started, and where it
   is back. Centred, and horizontally scrollable if a product ever carries more
   than fit; the thumbs themselves are the only way through the set now that the
   arrows are gone, so none of them may become unreachable.

   "safe" centre matters here, not decoration: with a plain centre and more
   thumbs than fit, the overflow spills equally both ways and the first ones end
   up before the scroll origin, out of reach. safe falls back to flex-start the
   moment the row overflows. */
.product-gallery__thumbs {
	display: flex;
	gap: 12px;
	flex-wrap: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
	justify-content: safe center;
}
.product-gallery__thumbs::-webkit-scrollbar { display: none; }
/* 84px rather than the 56px the strip carried before -- large enough to tell
   the bottle shot from the campaign shot without opening it.
   A basis rather than a fixed width: six thumbs at 84 are 64px wider than the
   frame, and a product with six photographs would either cut the last one off
   or hide it behind a scroll. Allowed to shrink, they simply come out a little
   smaller (six fit at ~73px) and the whole set stays in view. They never grow
   past 84. */
.product-gallery__thumb {
	flex: 0 1 84px;
	min-width: 0;
	aspect-ratio: 1;
	border-radius: 0;
	overflow: hidden;
	border: 1px solid var(--color-border);
	padding: 0;
	transition: border-color 0.15s ease;
}
.product-gallery__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.product-gallery__thumb:hover,
.product-gallery__thumb:focus-visible,
.product-gallery__thumb.is-active { border-color: var(--color-ink); }
/* Five 84px thumbs plus their gaps are wider than a phone, so the basis comes
   down rather than leaving every phone-width row to shrink into the floor. */
@media (max-width: 600px) {
	.product-gallery__thumbs { gap: 8px; }
	.product-gallery__thumb { flex-basis: 60px; }
}

/* .product-summary .woocommerce-breadcrumb removed with the breadcrumb call in
   woocommerce/single-product.php -- nothing renders into it any more. */
.product-brand {
	display: inline-block;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-accent-dark);
	margin-bottom: 10px;
}
.product-brand:hover { text-decoration: underline; }
.product-summary h1 { font-family: var(--font-base); font-weight: 700; font-size: clamp(28px, 3vw, 38px); text-transform: capitalize; margin-bottom: 12px; }
.product-summary .price {
	font-size: 20px;
	color: var(--color-ink);
	display: block;
	margin-bottom: 20px;
}
.product-summary .price del { color: var(--color-ink-faint); opacity: 0.7; margin-right: 8px; }
.product-summary .price ins { text-decoration: none; color: var(--color-accent-dark); }

/* A line of text, not a tinted panel. It was carrying a filled box on a page
   that has no other boxes in the summary column, which gave one shipping note
   more visual weight than the price above it. */
.product-summary__banner {
	color: var(--color-ink);
	font-size: 13px;
	font-weight: 600;
	margin-bottom: 24px;
}
.product-summary .woocommerce-product-details__short-description {
	color: var(--color-ink-soft);
	margin-bottom: 24px;
}
.product-summary .woocommerce-product-details__short-description p:first-child { margin-top: 0; }

form.cart {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-bottom: 28px;
}
/* The quantity stepper and Add to Cart sat flush against each other -- ~4px
   apart on one line, and zero once the button wrapped.
   `form.cart`'s own gap never reached them on a VARIABLE product, which is 181
   of the 193: WooCommerce nests both inside .woocommerce-variation-add-to-cart,
   a plain `display: block` div, so the form's flex gap applies to its own
   children (the variations table and .single_variation_wrap) and stops there.
   The only thing separating the two controls was the whitespace text node
   between them, and a wrapped block has no row-gap at all -- which is why the
   button touched the stepper on phones, where it is width: 100%.
   So the control row is made a flex row wherever it actually lives: inside that
   div for variable products, and on the form itself for the 9 simple ones,
   where the two ARE direct children. 16px rather than the form's 12 -- these are
   43-46px controls sitting side by side, and 12px read as a seam between them
   rather than a gap. Kept identical in both places so the two product types are
   spaced the same. */
.woocommerce-variation-add-to-cart {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 16px;
}
form.cart:not(.variations_form) { gap: 16px; }
form.cart .quantity {
	display: inline-flex;
	align-items: stretch;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	overflow: hidden;
}
form.cart .quantity input.qty {
	width: 48px;
	border: none;
	text-align: center;
	padding: 12px 0;
	-moz-appearance: textfield;
}
form.cart .quantity input.qty::-webkit-outer-spin-button,
form.cart .quantity input.qty::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}
form.cart .qty-btn {
	width: 40px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 16px;
	color: var(--color-ink-soft);
}
form.cart .qty-btn:hover { color: var(--color-ink); background: var(--color-bg); }
form.cart .qty-btn--minus { border-right: 1px solid var(--color-border); }
form.cart .qty-btn--plus { border-left: 1px solid var(--color-border); }
form.cart button.single_add_to_cart_button {
	flex: 1;
	min-width: 200px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	background: var(--color-ink);
	color: #fff;
	border-radius: var(--radius-sm);
	padding: 14px 28px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	font-size: 13px;
}
form.cart button.single_add_to_cart_button::before {
	content: '';
	width: 18px;
	height: 18px;
	flex-shrink: 0;
	background-color: #fff;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5'%3E%3Cpath d='M4 7h16l-1.5 11.5a2 2 0 0 1-2 1.5H7.5a2 2 0 0 1-2-1.5L4 7Z'/%3E%3Cpath d='M8 7V5a4 4 0 0 1 8 0v2'/%3E%3C/svg%3E") center / contain no-repeat;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5'%3E%3Cpath d='M4 7h16l-1.5 11.5a2 2 0 0 1-2 1.5H7.5a2 2 0 0 1-2-1.5L4 7Z'/%3E%3Cpath d='M8 7V5a4 4 0 0 1 8 0v2'/%3E%3C/svg%3E") center / contain no-repeat;
}
form.cart button.single_add_to_cart_button:hover { background: var(--color-accent-dark); }
.variations { width: 100%; margin-bottom: 8px; }
/* :not(.screen-reader-text) is load-bearing. The swatch group keeps a real
   <select> behind it as the accessible control and hides it with
   .screen-reader-text -- but that class only sets width: 1px at one specificity
   point, and a bare `.variations select` here outscored it. The hidden select
   was laid out 100% of the page wide, absolutely positioned beside the swatches,
   and hung ~580px past the right edge: invisible (it is clipped), but enough to
   make the whole document scroll sideways. */
.variations select:not(.screen-reader-text) { width: 100%; padding: 12px 16px; border-radius: var(--radius-sm); border: 1px solid var(--color-border); }

.variations--swatches { display: flex; flex-direction: column; gap: 20px; }
.variation-swatch-group__label {
	display: block;
	font-size: 13px;
	color: var(--color-ink-soft);
	margin-bottom: 10px;
}
.variation-swatch-group__options { display: flex; flex-wrap: wrap; gap: 10px; }
.variation-swatch-group__select { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; }
.variation-swatch {
	padding: 12px 20px;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	background: #fff;
	color: var(--color-ink);
	font-size: 14px;
	transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.variation-swatch:hover { border-color: var(--color-ink); }
.variation-swatch.is-selected {
	background: var(--color-ink);
	border-color: var(--color-ink);
	color: #fff;
}

.product-accordion { border-top: 1px solid var(--color-border); }
.product-accordion__item { border-bottom: 1px solid var(--color-border); }
.product-accordion__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 16px 0;
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
	list-style: none;
}
.product-accordion__summary::-webkit-details-marker { display: none; }
.product-accordion__summary svg {
	width: 16px;
	height: 16px;
	flex-shrink: 0;
	color: var(--color-ink-soft);
	transition: transform 0.2s ease;
}
.product-accordion__item[open] > .product-accordion__summary svg { transform: rotate(180deg); }
.product-accordion__panel {
	padding: 0 0 20px;
	color: var(--color-ink-soft);
	font-size: 14px;
	line-height: 1.7;
}
.product-accordion__panel p:last-child { margin-bottom: 0; }
/* Section titles inside a description ("Scent notes", "Details") read as
   body text, not headings: same size as the copy, set apart by weight and
   by one blank line above. */
.product-accordion__panel :is(h2, h3, h4) {
	margin: 1.7em 0 0;
	font-family: inherit;
	font-size: inherit;
	font-weight: 600;
	line-height: inherit;
	letter-spacing: 0;
	text-transform: none;
	color: inherit;
}
.product-accordion__panel :is(h2, h3, h4):first-child { margin-top: 0; }

.related.products { padding-top: 0; }
.related.products > h2 { text-transform: lowercase; margin-bottom: 24px; }

#reviews h2, #reviews h3 { text-transform: lowercase; margin-bottom: 16px; }
#reviews .comment-form-rating label,
#reviews .comment-form-comment label,
#reviews .comment-form-author label,
#reviews .comment-form-email label {
	display: block;
	font-size: 13px;
	color: var(--color-ink-soft);
	margin-bottom: 6px;
}
#reviews input[type="text"], #reviews input[type="email"], #reviews textarea {
	width: 100%;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	padding: 10px 14px;
	margin-bottom: 16px;
	font-family: var(--font-base);
}
#reviews .comment-form-rating p.stars a { color: var(--color-accent); text-decoration: none; margin-right: 4px; }
#reviews .form-submit input[type="submit"] {
	border-radius: var(--radius-pill);
	background: var(--color-ink);
	color: #fff;
	padding: 12px 26px;
	font-weight: 600;
	border: none;
}
#reviews .form-submit input[type="submit"]:hover { background: var(--color-accent-dark); }

/* Star ratings */
.star-rating { color: var(--color-accent); font-size: 13px; }

/* =========================================================
   Cart / Checkout / My Account (page.php shortcodes)
   ========================================================= */
.page-content table.shop_table { width: 100%; border-collapse: collapse; margin-bottom: 32px; }
.page-content table.shop_table th, .page-content table.shop_table td { padding: 14px 12px; border-bottom: 1px solid var(--color-border); text-align: left; }
.page-content .button { display: inline-flex; padding: 12px 24px; border-radius: var(--radius-pill); background: var(--color-ink); color: #fff; font-weight: 600; }
.page-content .button:hover { background: var(--color-accent-dark); }
.page-content input.input-text, .page-content select, .page-content textarea {
	border: 1px solid var(--color-border);
	border-radius: var(--radius-sm);
	padding: 10px 14px;
	width: 100%;
}
.page-content .woocommerce-form-row { margin-bottom: 16px; }
/* No padding of its own: .section already opens the standard block of space
   above, and the extra 40px on top of it left the title stranded a long way
   down an otherwise empty screen. The gap below is .best-sellers__head's, so
   the title sits the same distance off its copy as the homepage sections do. */
.page-header { padding-top: 0; margin-bottom: clamp(20px, 2.5vw, 32px); }
/* The homepage carousel heading, reused -- .best-sellers__title's face, weight,
   size and leading exactly. It was the display face lowercased at up to 76px,
   which on a page of policy copy read as a banner rather than a title. Case is
   left as typed now, so "Shipping & Returns" keeps its capitals. */
.page-header h1 {
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(27px, 2.7vw, 37px);
	line-height: 1.2;
	color: var(--color-ink);
}

/* Long-form editor copy -- the Shipping & Returns and Terms & Conditions pages,
   and anything else that runs through page.php with real prose in it. There was
   nothing styling this before; the content fell through to browser defaults,
   which is Times at full container width. */
.page-body {
	/* No max-width here. The reading measure lives on .page-content--prose,
	   which page.php adds to every page EXCEPT Cart, Checkout and My Account --
	   so a cap on .page-body could only ever bite on those three, which are the
	   pages that want the whole container. It did: 68ch resolved to roughly
	   480px, and the block checkout, squeezed into that and left-aligned with no
	   auto margin, fell below its own 699px @container breakpoint and stacked
	   the form and the order summary on top of each other in a narrow column
	   against the left edge of a wide page. On the prose pages the cap was dead
	   weight anyway -- .page-content--prose .page-body already reset it to
	   none. */
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.75;
	color: var(--color-ink-soft);
}
/* Section headings inside the copy. Smaller than the page title above and set
   in the body face rather than the display one -- these are signposts through a
   long document, not display type. On the FAQ these are the groups (Account,
   Orders, Shipping); on the policy pages they are the sections. */
.page-body h2 {
	margin: clamp(40px, 5vw, 64px) 0 4px;
	font-family: var(--font-base);
	font-size: 20px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--color-ink);
}
/* The FAQ's individual questions. A step below the group heading above and a
   step above the answer below, so the three levels stay distinguishable. The
   global h3 is 18px, which would have made a question larger than the group it
   sits inside. Tight to its own answer and loose from the previous one, so each
   pair reads as a unit. */
.page-body h3 {
	margin: clamp(24px, 3vw, 32px) 0 6px;
	font-family: var(--font-base);
	font-size: 16px;
	font-weight: 600;
	line-height: 1.45;
	color: var(--color-ink);
}
/* No top margin on the first one -- .page-header already set the space above. */
.page-body > h2:first-child,
.page-body > h3:first-child { margin-top: 0; }
.page-body p { margin: 0 0 16px; }
.page-body ul,
.page-body ol { margin: 0 0 16px; padding-left: 1.35em; }
.page-body li { margin-bottom: 10px; }
.page-body li:last-child { margin-bottom: 0; }
.page-body a { text-decoration: underline; }

/* Prose pages only (see page.php): the column is centred in the container, so
   the margin either side of it is the same. Cart, Checkout and My Account do not
   get this class and keep the full container width.
   
   The measure sits on the wrapper, not on the title and the body separately.
   Capping each of them at 68ch gave two different widths -- ch resolves against
   each element's own font, and .page-body sets 15px where the header inherits
   16px -- so the two centred boxes came out different sizes and their left edges
   did not line up. One box, one measure, one edge. */
.page-content--prose {
	max-width: 68ch;
}
/* The cap is on the wrapper above, not here -- see .page-body. Kept explicit so
   that re-adding a measure to .page-body cannot silently double-cap the copy. */
.page-content--prose .page-body {
	max-width: none;
}

/* =========================================================
   Loyalty Rewards / Partnership landing pages (shared .rewards-* system)
   ========================================================= */
/* =========================================================
   Loyalty Rewards page (hero split, how-it-works, explainer, quote)
   ========================================================= */
/* Masthead: a heading holding the left of the measure against a narrow column of
   supporting copy. The reference's hairlines -- one between the columns, one
   closing the section -- have been dropped; the columns are held apart by the
   gap alone. */
.rewards-intro {
	padding-top: clamp(28px, 4vw, 64px);
	padding-bottom: clamp(32px, 4.5vw, 72px);
}
.rewards-intro__inner {
	display: grid;
	grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
	gap: clamp(28px, 5vw, 88px);
	align-items: start;
}
/* Same size as .about-hero__word, so the two pages open at the same pitch --
   see also .partner-intro__title, which mirrors it for the same reason. 400
   because Instrument Serif ships one weight. */
.rewards-intro__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(24px, 4vw, 59px);
	line-height: 0.95;
	letter-spacing: -0.015em;
	color: var(--color-navy);
}
.rewards-intro__title span { display: block; }

/* A height rather than an aspect ratio, unlike .about-band's 3:1. The band sits
   directly under the masthead, and a ratio grows with the window -- on a wide
   screen 3:1 pushed the foot of the photograph well past the bottom of the
   viewport. Tied to vh instead, the masthead and the band land together in one
   screen at any width, and the cap stops it running away on very tall
   monitors. */
.rewards-band {
	height: clamp(240px, 41vh, 504px);
	overflow: hidden;
	background: var(--color-bg-soft);
}
/* img kept alongside the video: the band carried a photograph before and the
   Customizer setting that fed it is still registered. */
.rewards-band img,
.rewards-band__video {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.rewards-intro__aside {
	padding-top: clamp(6px, 1vw, 14px);
}
.rewards-intro__eyebrow {
	margin: 0;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--color-ink);
}
.rewards-intro__text {
	margin: clamp(14px, 1.6vw, 22px) 0 0;
	max-width: 42ch;
	font-size: clamp(14px, 1.05vw, 15px);
	line-height: 1.6;
	color: var(--color-ink-soft);
}
.rewards-intro__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: clamp(20px, 2.4vw, 32px);
}
/* Square and navy, scoped to this pair rather than changed on .btn itself --
   the pill is the site-wide button and every other page still uses it. */
.rewards-intro__actions .btn { border-radius: 0; }
.rewards-intro__actions .btn--primary {
	background: var(--color-navy);
	border-color: var(--color-navy);
}
.rewards-intro__actions .btn--primary:hover {
	background: var(--color-accent);
	border-color: var(--color-accent);
}
.rewards-intro__actions .btn--outline {
	color: var(--color-navy);
	border-color: var(--color-navy);
}
.rewards-intro__actions .btn--outline:hover {
	background: var(--color-navy);
	color: #fff;
}

.rewards-steps__head { text-align: center; max-width: 640px; margin: 0 auto 48px; }
/* Instrument Serif and navy, the same face and colour as .rewards-intro__title
   above it -- a step down in size, since this opens a section rather than the
   page. */
.rewards-steps__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(26px, 3.2vw, 44px);
	line-height: 1.05;
	letter-spacing: -0.015em;
	color: var(--color-navy);
}
.rewards-steps__sub {
	margin: clamp(8px, 1vw, 14px) 0 0;
	font-size: clamp(14px, 1.05vw, 15px);
	color: var(--color-ink-soft);
}
.rewards-steps__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--gutter);
	text-align: center;
}
/* Was a sand disc with a pale glyph knocked out of it -- the one warm note on an
   otherwise blue page. Now the same treatment as .partner-way__icon: the soft
   accent wash behind an accent-coloured glyph, so the icons belong to the
   palette rather than sitting against it. Smaller, too: at 96px the disc
   outweighed the words under it. */
.rewards-step__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: clamp(96px, 8vw, 116px);
	height: clamp(96px, 8vw, 116px);
	border-radius: 50%;
	background: var(--color-accent-soft);
	color: var(--color-accent);
	margin-bottom: 22px;
}
.rewards-step__icon svg { width: clamp(40px, 3.4vw, 50px); height: clamp(40px, 3.4vw, 50px); }
.rewards-step h3 {
	margin-bottom: 10px;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(24px, 2.2vw, 32px);
	line-height: 1.15;
	letter-spacing: -0.01em;
	color: var(--color-navy);
}
.rewards-step p { color: var(--color-ink-soft); font-size: 14px; line-height: 1.6; margin: 0 auto; max-width: 30ch; }

/* The .rewards-explainer split -- photograph beside a numbered list of earning
   rules -- has gone; those rules are now answers in the .faq accordion at the
   foot of the page. Its Customizer setting, loyalty_explainer_image, stays
   registered so the uploaded photograph is not orphaned. */


@media (max-width: 820px) {
	.rewards-intro__inner { grid-template-columns: minmax(0, 1fr); }
	.rewards-intro__aside { padding-top: clamp(20px, 4vw, 32px); }
	.rewards-steps__grid { grid-template-columns: 1fr; gap: 40px; }
}

/* =========================================================
   Partnership masthead — centred lockup
   Replaces the .partner-hero collage. Everything here is symmetrical about the
   centre line: two display lines, three identical portrait frames, and the
   founding marks holding the space either side of them.
   ========================================================= */
/* The three bands of this page each pull their own space in, because their
   paddings stack: at the old values the masthead's bottom and the folds' top
   put ~160px of empty page between two blocks that belong together. Halved,
   roughly, on both sides of each seam. */
.partner-intro {
	padding-top: clamp(28px, 4vw, 60px);
	padding-bottom: clamp(32px, 4vw, 56px);
}
.partner-intro__inner { text-align: center; }

/* Deliberately the same size, measure and line-height as .about-hero__word, so
   the two pages open at the same pitch -- both are one phrase set on one or two
   lines, and they should not compete. The values are repeated rather than
   shared: the two sit in different sections with different colour, and folding
   them into one selector would tie a later change on either page to the other. */
.partner-intro__title {
	margin: 0;
	margin-inline: auto;
	max-width: 13em;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(24px, 4vw, 59px);
	line-height: 0.95;
	letter-spacing: -0.015em;
	color: var(--color-navy);
}

/* --- Banner, flanked by the marks --- */
/* 1fr either side rather than a fixed inset: the marks centre themselves in
   whatever space is left over, so they drift outward on a wide window and close
   in on a narrow one without ever crowding the photograph. The middle column
   caps at the width the three portrait frames used to span together, so the
   banner keeps the same footprint on the page. */
.partner-intro__gallery {
	margin-top: clamp(32px, 4.5vw, 72px);
	display: grid;
	grid-template-columns: 1fr minmax(0, 940px) 1fr;
	align-items: center;
	column-gap: clamp(10px, 1.4vw, 28px);
}
.partner-intro__mark {
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(18px, 1.9vw, 34px);
	line-height: 1;
	color: var(--color-navy);
	white-space: nowrap;
}
/* Square corners, on purpose: the banner is one wide plate, and a radius on
   something this size reads as a card rather than as a photograph. Same
   treatment .about-band gets. The ratio is the footprint the three portrait
   frames covered together (roughly 940 x 418), so the band sits in the page
   where they did. */
.partner-intro__frame {
	margin: 0;
	aspect-ratio: 9 / 4;
	overflow: hidden;
	background: var(--color-bg-soft);
}
.partner-intro__frame img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Measure and type size taken from .about-hero__intro, so the paragraph under
   this heading sits on the same measure as the one under the About heading. */
.partner-intro__lead {
	margin: clamp(28px, 3.2vw, 46px) auto 0;
	max-width: 66ch;
	font-family: var(--font-base);
	font-size: clamp(14px, 1.1vw, 16px);
	line-height: 1.55;
	color: var(--color-navy);
}
/* Two blocks rather than one run of text -- the first sentence keeps its own
   line, and the paragraph under it opens by less than a full blank line so the
   pair still reads as one piece of copy. */
.partner-intro__lead span { display: block; }
.partner-intro__lead span + span { margin-top: 0.7em; }
/* 600, not the browser's 700: Plus Jakarta Sans at this size goes blocky at bold
   next to the regular it sits in the middle of. Semibold carries the emphasis
   without breaking the line's colour. */
.partner-intro__lead strong { font-weight: 600; }

@media (max-width: 820px) {
	/* The marks are the first thing to go: at this width there is no leftover
	   space for them to sit in, and squeezing them in steals it from the
	   photograph, which is what the row is for. */
	.partner-intro__mark { display: none; }
	.partner-intro__gallery { grid-template-columns: minmax(0, 1fr); }
}

/* =========================================================
   Partnership — Ways to Partner (heading left, folds right)
   ========================================================= */
/* The masthead above closes with its own bottom padding, so this opens tight --
   and closes tight too, over the form, for the same reason. */
.partner-ways {
	padding-top: clamp(16px, 2vw, 30px);
	padding-bottom: clamp(32px, 4vw, 56px);
}
.partner-ways__inner {
	display: grid;
	grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
	gap: clamp(24px, 5vw, 80px);
	align-items: start;
}
/* Same face as the masthead heading -- the two are the only display type on the
   page and reading them as one voice is the point of the request. Smaller than
   the masthead on purpose: this is a section heading under an h1, and matching
   its size would make the page look like it starts twice. The measure is narrow
   so the phrase stacks into short lines beside the folds rather than running
   the full width of its column. */
.partner-ways__title {
	margin: 0 0 14px;
	max-width: 8em;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(30px, 3.6vw, 52px);
	line-height: 1.05;
	letter-spacing: -0.015em;
	text-transform: none;
	color: var(--color-ink);
}
.partner-ways__text {
	margin: 0;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}
/* One sentence per line, held at every width -- no measure cap, because the
   break is set here rather than left to the column to find. */
.partner-ways__text span { display: block; }

/* --- The folds --- */
.partner-way { border-top: 1px solid var(--color-border); }
.partner-way:last-child { border-bottom: 1px solid var(--color-border); }
.partner-way__summary {
	display: flex;
	align-items: center;
	gap: clamp(12px, 1.4vw, 20px);
	padding: 18px 0;
	cursor: pointer;
	list-style: none;
}
/* Safari still paints its own disclosure triangle without this. */
.partner-way__summary::-webkit-details-marker { display: none; }
/* The theme's own accent rather than the sand the old icon circles used: sand
   belongs to the Loyalty page's steps, and on this pale blue ground it read as
   a borrowed colour. Soft accent disc, full accent line-work. */
.partner-way__icon {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background: var(--color-accent-soft);
	color: var(--color-accent);
}
.partner-way__icon svg { width: 21px; height: 21px; }
/* Serif, like the heading -- the fold titles are part of the same voice. */
.partner-way__name {
	flex: 1 1 auto;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(20px, 1.9vw, 27px);
	line-height: 1.2;
	color: var(--color-ink);
}
.partner-way__mark {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	color: var(--color-ink-soft);
}
/* Collapsing the upright to nothing turns the plus into the minus, rather than
   swapping one icon for another. scaleY, so it closes toward the crossbar. */
.partner-way__mark-bar {
	transform-origin: 12px 12px;
	transition: transform 0.2s ease;
}
.partner-way[open] .partner-way__mark-bar { transform: scaleY(0); }
/* Indented to the left edge of the title, past the icon disc, so the paragraph
   hangs under the words it belongs to and not under the mark. */
.partner-way__body {
	margin: 0;
	padding: 0 clamp(24px, 3vw, 52px) 22px calc(44px + clamp(12px, 1.4vw, 20px));
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.7;
	color: var(--color-ink-soft);
}
@media (max-width: 820px) {
	.partner-ways__inner { grid-template-columns: 1fr; }
	.partner-ways__title { max-width: none; }
	.partner-way__body { padding-right: 0; }
}

/* --- Start a Conversation --- */
.partner-form { padding-top: clamp(16px, 2vw, 30px); }
/* Same measure the Contact page's form sits on, so the two are the same object
   at the same width on both pages. */
.partner-form__inner { max-width: 960px; }
/* The section heading above it, repeated: one voice for the whole page. */
.partner-form__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(30px, 3.6vw, 52px);
	line-height: 1.05;
	letter-spacing: -0.015em;
	text-transform: none;
	text-align: center;
	color: var(--color-ink);
}
/* The Contact page opens its form under a block of copy; here it opens under a
   heading alone, which needs less air over it than that gap gives. */
.partner-form .contact-form { margin-top: clamp(32px, 4vw, 52px); }

/* =========================================================
   About Us page — editorial layout
   Display type is --font-hero (Instrument Serif), eyebrows and body are
   --font-base, matching the New Arrivals pairing. Palette is Satueen's own
   pale blue rather than the reference's beige.
   ========================================================= */
/* Even top and bottom. The block is a heading and one paragraph, tight together
   -- it needs air around the pair to read as its own opening rather than as
   something crowded between the header above and the photographic band below. */
.about-hero {
	background: var(--color-bg);
	padding: clamp(56px, 8vw, 112px) var(--gutter);
}
/* Carries the gap between the heading and itself, which .about-hero__display
   used to hold while it was the lower of the two. */
.about-hero__top {
	margin-top: clamp(14px, 1.8vw, 26px);
}
/* Centred on the same axis as the heading above, in place of the two-column row
   this used to be -- the "Satueen." mark held the left column and the intro was
   indented beside it as its caption. With the mark gone there is nothing to
   indent from, so the paragraph sits under the heading rather than off to one
   side. The measure cap keeps it from running wider than the line it sits under. */
.about-hero__intro {
	margin: 0 auto;
	/* Wider than the 52ch this held when the copy was three lines. The paragraph
	   is now roughly twice that length, and at the old measure a centred block
	   that deep is hard to track back to the start of each line. */
	max-width: 66ch;
	font-family: var(--font-base);
	font-size: clamp(14px, 1.1vw, 16px);
	line-height: 1.55;
	text-align: center;
	color: var(--color-ink);
}
/* Opens the section now, so no margin above: the section's own padding is the
   only space over the heading. (No position: relative either -- the scroll arrow
   was the only thing that positioned against it, and it is gone.) */
.about-hero__display {
	margin-top: 0;
}
.about-hero__word {
	margin: 0;
	font-family: var(--font-hero);
	/* 400 because Instrument Serif ships one weight -- anything heavier is
	   synthesised, which shows badly at this size. */
	font-weight: 400;
	/* Sized for a phrase, not the single word this used to hold. The measure cap
	   is what sets the wrap: at the top size the line runs wider than 13em, so it
	   breaks into two rather than being shrunk until it fits on one.
	   line-height is back above 0.9 for the same reason -- the old 0.82 was safe
	   for a single line and would have collided ascenders with descenders here. */
	font-size: clamp(24px, 4vw, 59px);
	line-height: 0.95;
	max-width: 13em;
	margin-inline: auto;
	letter-spacing: -0.015em;
	text-align: center;
	color: var(--color-ink);
}

/* Full-bleed four-up. No gap and no container: the images butt against each
   other and run to both window edges. */
/* One photograph running edge to edge, in place of the four portrait cells this
   band used to hold -- a wide landscape cut into quarter-width portraits loses
   most of itself. For a shallower band, give .about-band an aspect-ratio and the
   image object-fit: cover; on a horizon shot the top and bottom are the parts to
   lose. */
/* Half the height the photograph's own 3:2 would give -- 3:1 rather than 3:2 --
   so the band reads as a cinematic strip instead of a second hero. The crop is
   centred, which on this frame keeps the hands, the linen and the horizon and
   takes the loss out of the empty sky above and the sand below. A different
   photograph may want its own object-position; this one does not. */
.about-band {
	aspect-ratio: 3 / 1;
	overflow: hidden;
	background: var(--color-bg-soft);
}
.about-band img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* ---------------------------------------------------------------------------
   About: the dark scene. Plain panel by default; main.js adds .is-live, makes
   the section tall and drives everything below from the scroll position (the
   --scene-* properties). Per the user's reference recording.
   --------------------------------------------------------------------------- */
.about-scene { background: #fff; }
.about-scene__card {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: clamp(72px, 12vw, 160px) var(--gutter);
	background: #111;
	color: #fff;
	overflow: hidden;
}
.about-scene__mark { display: none; }
.about-scene__copy {
	position: relative;
	z-index: 1;
	/* Wide enough for the lead to set on three lines on a desktop, and still
	   clear of the marks parked either side of it. */
	max-width: 760px;
	text-align: center;
}
.about-scene__eyebrow {
	margin: 0 0 22px;
	font-family: var(--font-base);
	font-size: 11.5px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.6);
}
.about-scene__lead {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(22px, 2.4vw, 36px);
	line-height: 1.18;
	text-wrap: balance;
}
.about-scene__word { opacity: 0.16; transition: opacity 0.25s linear; }
.about-scene__word.is-lit { opacity: 1; }

.about-scene.is-live .about-scene__stage {
	position: sticky;
	top: calc(var(--announcement-h, 0px) + var(--header-h));
	height: calc(100vh - var(--announcement-h, 0px) - var(--header-h));
}
.about-scene.is-live .about-scene__card {
	height: 100%;
	padding-block: 0;
	/* Draws in from full-bleed to a rounded card as the scene ends. */
	margin: calc(var(--scene-inset, 0) * 16px) calc(var(--scene-inset, 0) * 20px) 0;
	height: calc(100% - var(--scene-inset, 0) * 32px);
	border-radius: calc(var(--scene-inset, 0) * 16px);
}
.about-scene.is-live .about-scene__copy { opacity: var(--scene-copy, 0); }
.about-scene.is-live .about-scene__mark {
	display: block;
	position: absolute;
	top: 50%;
	left: 50%;
	width: clamp(120px, 15vw, 220px);
	height: auto;
	aspect-ratio: 300 / 360;
	/* The sheet is rendered on pure black; screened over the panel, black
	   leaves the panel's own colour and only the glass shows. */
	mix-blend-mode: screen;
	transform: translate(-50%, -50%) translateX(calc(var(--scene-spread, 0) * var(--scene-side, 1) * 36vw));
	will-change: transform;
}
.about-scene__mark--left { --scene-side: -1; }
.about-scene__mark--right { --scene-side: 1; }
@media (max-width: 800px) {
	/* No room either side of the text: the marks part vertically instead, one
	   above the lead and one below. */
	.about-scene.is-live .about-scene__mark {
		width: 96px;
		transform: translate(-50%, -50%) translateY(calc(var(--scene-spread, 0) * var(--scene-side, 1) * 34vh));
	}
	.about-scene__lead { font-size: 22px; }
}

/* The paragraph that used to open this section has gone, so the space above the
   statement is this padding alone -- pulled back to the value the split above
   opens with, rather than the deeper one that was holding a whole block. */
.about-statement {
	background: var(--color-bg);
	padding: clamp(56px, 7vw, 96px) 0 clamp(64px, 11vw, 150px);
}
/* All three blocks are one statement -- same face, same size, same measure, no
   gap between them -- so they are styled identically and each simply carries on
   from the one above, as one continuous piece of text. */
.about-statement__text,
.about-statement__sub,
.about-statement__close {
	margin: 0;
	/* No measure cap: the lines run the full container width, so the block
	   reaches across to the right edge rather than stacking in a narrow
	   left-hand column. */
	max-width: none;
	font-family: var(--font-hero);
	font-weight: 400;
	/* Well under what a lone headline would take: three blocks of display type
	   run long, and the middle one is a full paragraph -- at anything like a
	   headline size this section would fill more than a screen on its own. */
	font-size: clamp(20px, 2.3vw, 33px);
	line-height: 1.12;
	color: var(--color-ink);
}

/* The split now follows the editorial block, which ends flush, so it opens its
   own space -- it used to inherit that from the statement's bottom padding. It
   closes flush for the same reason in reverse: the statement below it opens its
   own. */
.about-split {
	background: var(--color-bg);
	padding-top: clamp(56px, 7vw, 96px);
	padding-bottom: 0;
}
.about-split__inner {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(32px, 6vw, 96px);
	align-items: start;
}
/* Stretches to the full height of the row, so the photograph runs from the top
   of the copy down to the "Explore the brands" link instead of stopping short
   and leaving the lower paragraphs beside empty page. align-self overrides the
   align-items: start on the grid, which applies to the copy column only now.
   No aspect-ratio: the copy column sets the height and the crop follows it. A
   fixed ratio here is what made the two columns disagree in the first place. */
.about-split__media {
	align-self: stretch;
	overflow: hidden;
	background: var(--color-bg-soft);
}
/* object-position, not the default 50%: the frame is taller than the founder
   photograph is, so cover trims the sides, and a straight centre crop leaves the
   pair sitting a touch left of the frame with backdrop to their right. Pulling
   the crop window left settles them in the middle. */
.about-split__media img { width: 100%; height: 100%; object-fit: cover; object-position: 44% center; display: block; }
.about-split__para {
	margin: 0 0 18px;
	font-family: var(--font-base);
	font-size: clamp(14px, 1.05vw, 16px);
	line-height: 1.6;
	color: var(--color-ink);
	max-width: 46ch;
}
/* Rules above each row rather than below, so the list closes on the link
   instead of on a dangling hairline. */
.about-facts {
	list-style: none;
	margin: clamp(28px, 4vw, 46px) 0 0;
	padding: 0;
}
.about-fact {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 22px 0;
	border-top: 1px solid var(--color-border);
}
.about-fact__icon { color: var(--color-ink); }
.about-fact__icon svg { width: 30px; height: 30px; display: block; }
.about-fact__label {
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(19px, 1.7vw, 25px);
	line-height: 1.2;
	color: var(--color-ink);
}
.about-split__link {
	display: inline-block;
	margin-top: 24px;
	padding-bottom: 5px;
	font-family: var(--font-hero);
	font-size: clamp(17px, 1.4vw, 21px);
	color: var(--color-ink);
	text-decoration: none;
	border-bottom: 1px solid var(--color-ink);
}
.about-split__link:hover { border-bottom-color: transparent; }

/* Eyebrow in the left margin, the lead running wide beside it, and the closing
   paragraph stepped in under the lead -- the reference's stagger. The Brands
   roster opens with the same block as .page-intro, so both share one set of
   rules and cannot drift apart; only the outer spacing differs, since one
   closes a page and the other opens one. */
.page-intro {
	background: var(--color-bg);
	padding: clamp(48px, 7vw, 96px) 0 clamp(28px, 3.5vw, 48px);
}
body.is-white-page .page-intro { background: #fff; }
/* About Us: every text block on a white page is white too. The photographic
   band keeps its own fill -- that only shows while its image loads. */
body.is-white-page :is(.about-hero, .about-statement, .about-split, .about-editorial) { background: #fff; }
/* For a section that follows a block already carrying its own bottom space. */
.section--tight-top { padding-top: 0; }
/* This block used to close the page, where the section above it supplied the
   space over it; it now sits directly under the photographic band, so it has to
   open its own gap or the eyebrow starts hard against the bottom of the image. */
.about-editorial {
	background: var(--color-bg);
	/* Tight under the photographic band -- the band ends on an image edge, which
	   is a hard enough line that it does not need a lot of air beneath it. Same
	   value the split below uses to open under this block. */
	padding-top: clamp(32px, 4vw, 56px);
	/* Nothing under it: the split that follows opens its own space, and the two
	   paddings stacked put nearly 300px of empty page between the blocks. */
	padding-bottom: 0;
}
.about-editorial__inner,
.page-intro__inner {
	display: grid;
	grid-template-columns: minmax(0, 22%) minmax(0, 1fr);
	gap: clamp(24px, 5vw, 72px);
	align-items: start;
}
.about-editorial__eyebrow,
.page-intro__eyebrow {
	margin: 10px 0 0;
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 600;
	line-height: 1.45;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-ink);
}
.about-editorial__lead,
.page-intro__lead {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(23px, 3vw, 45px);
	line-height: 1.12;
	color: var(--color-ink);
}
/* The landing-page lead (Brands, Olfactive Families) sits a step below the About
   lead: large enough to read as an opening statement, small enough that a
   three-line paragraph does not become a wall of type. Scoped to .page-intro
   so About is untouched. */
.page-intro__lead {
	font-size: clamp(18px, 2.1vw, 30px);
	line-height: 1.2;
}
/* Brands only -- the About page had a paragraph here once, moved to the
   statement section and then dropped altogether. */
.page-intro__body {
	grid-column: 2;
	justify-self: end;
	margin: clamp(28px, 4vw, 56px) 0 0;
	max-width: 42ch;
	font-family: var(--font-base);
	font-size: clamp(13.5px, 1vw, 15px);
	line-height: 1.65;
	color: var(--color-ink);
}
@media (max-width: 900px) {
	/* One column: the photograph sits above the copy rather than beside it. */
	.about-split__inner { grid-template-columns: 1fr; }
	/* Stacked, there is no second column to take its height from, so the frame
	   goes back to a fixed ratio -- the one it used at every width before the
	   two columns were matched up. */
	.about-split__media { aspect-ratio: 1 / 1.08; }
}

@media (max-width: 720px) {
	/* A narrow screen has no room for a phrase at display size; this lands it on
	   three or four short lines rather than one very small one. */
	.about-hero__word { font-size: clamp(22px, 5.5vw, 34px); }
	.about-editorial__inner,
	.page-intro__inner { grid-template-columns: 1fr; }
	.page-intro__body { grid-column: 1; justify-self: start; }
}
/* The boxed .partnership-form rules that used to sit here are gone: the form now
   wears the Contact page's .contact-form, so there is one set of field styles
   for both. .partnership-form__status survives as the JS hook only, and takes
   its appearance from .contact-form__status alongside it. */
.partnership-form__status { min-height: 18px; }

@media (max-width: 720px) {
	.loyalty-tiers { grid-template-columns: 1fr; }
}

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 980px) {
	.cat-tile-grid, .journal__grid { grid-template-columns: repeat(2, 1fr); }
	/* Keep the concentration row 3-up here — it only stacks on phones below.
	   The copy column moves above the cards rather than beside them. */
	.category-tiles .cat-tile-grid--cards { grid-template-columns: repeat(3, 1fr); }
	/* Head row wraps once there isn't room for the CTA beside the copy. */
	.category-tiles__head { flex-direction: column; align-items: flex-start; }
	.editorial__grid, .commitments, .product-page { grid-template-columns: 1fr; }
	.commitments__media { min-height: 280px; }
	ul.products { grid-template-columns: repeat(2, 1fr) !important; }
	.footer-columns { grid-template-columns: repeat(2, 1fr); }
	.product-gallery { position: static; height: auto; }
	/* No frame-shape override here: the base 3:4 is meant to hold at every
	   width, so the gallery reads the same on a phone as on a desktop. */
}

@media (max-width: 980px) {
	/* Not enough room beside the centred logo — the label overlaps it and
	   pushes the cart icon off the edge. */
	.header-currency { display: none; }
	/* …except the copy inside the mobile nav, which is the only way to switch there. */
	.header-currency--mobile { display: flex; }
}

/* Raised from 720px. The bar nav and the centred logo genuinely collide all
   the way up to ~1385px -- "About Us" ran up to 237px into the wordmark on a
   laptop -- so the slide-in menu now takes over for that whole band, not just
   for phones. */
@media (max-width: 1400px) {
	.site-header__inner .primary-nav { display: none; }
	/* The mobile .menu-toggle takes over below this width, so the panel's own
	   trigger would be a second hamburger sitting next to it. */
	.menu-panel-toggle { display: none; }
	.site-header__inner .menu-toggle { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; }
	.mobile-nav[hidden] { display: none; }
	/* The drawer's scroll lock breaks the header's position: sticky (overflow
	   is hidden on <html> for the duration), which would let the header scroll
	   away and expose the page through the strip above the panel. Pinned for as
	   long as the drawer is open. The page cannot scroll behind it anyway, so
	   fixed at the top is exactly where sticky would have held it. */
	/* The bar loses its own sticky for the same reason and would scroll away,
	   leaving a 38px strip of the page showing above the header. It is the first
	   thing on the page, so stuck or unscrolled it is at 0 either way -- no
	   measuring needed here. */
	html.mobile-nav-is-open .announcement-bar {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
	}
	html.mobile-nav-is-open .site-header {
		position: fixed;
		/* Where the header actually was when the drawer opened, not a flat 0:
		   at the top of the page the announcement bar is still on screen above
		   it, and 0 slid the header under the bar (z-index 51 to the header's
		   50), which cut the bar across the middle of it. main.js measures it. */
		top: var(--mobile-nav-header-top, 0px);
		left: 0;
		right: 0;
	}
	/* Fixed, not in the flow. In the flow it expanded above the viewport when
	   opened from partway down a page, so the menu appeared off-screen and had
	   to be scrolled up to. --mobile-nav-top is measured in main.js off the
	   header's own bottom edge, since the announcement bar scrolls away and
	   that edge is not a constant. */
	.mobile-nav {
		display: block;
		position: fixed;
		top: var(--mobile-nav-top, 107px);
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 1001;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior: contain;
		padding: 16px var(--gutter) 32px;
		background: var(--color-blue);
		border-top: 1px solid var(--color-border);
	}
	.mobile-nav__menu { flex-direction: column; gap: 18px; }

	.hero { min-height: 78vh; }
	/* Phones only, cut 30% per request: 78vh on an 812px phone is 633px, which
	   is the whole screen once the header is counted, so nothing below the fold
	   hinted at itself. 78 * 0.7 = 54.6vh (443px at 812). This has to live
	   inside the 1400px block rather than in one of the earlier 700px blocks --
	   both selectors are a bare `.hero`, so at equal specificity the later rule
	   in the file wins and a 700px block at line ~2366 was simply overridden by
	   the 78vh above. Tablets and laptops, which this block also covers, keep
	   78vh. The base `max(420px, ...)` floor is deliberately not reinstated:
	   it would only bind in landscape, where it would undo the cut.
	   Nudged up twice afterwards on request: 54.6 * 1.05 = 57.33vh, then
	   57.33 * 1.2 = 68.8vh (559px at 812) -- a net cut of 11.8% from the
	   original 78vh. */
	@media (max-width: 700px) { .hero { min-height: 68.8vh; } }
	.hero__copy { right: var(--gutter); max-width: none; }
	.hero__controls { top: var(--gutter); bottom: auto; }

	.cat-tile-grid, .journal__grid, ul.products { grid-template-columns: repeat(2, 1fr) !important; }
	/* Three cards don't split 2/1 without an orphan — stack them instead.
	   !important only to beat the blanket .cat-tile-grid rule above. */
	.category-tiles .cat-tile-grid--cards { grid-template-columns: 1fr !important; }
	.footer-columns { grid-template-columns: 1fr 1fr; gap: 24px; }
	form.cart button.single_add_to_cart_button { width: 100%; }
}

/* =========================================================
   Meet the founders
   ========================================================= */
/* No bottom padding: the newsletter band butts straight up against it. */
.founders { padding-bottom: 0; }
.founders__head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: clamp(24px, 3vw, 40px);
}
.founders__title {
	margin: 0 0 8px;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(30px, 3vw, 40px);
	line-height: 1.2;
	color: var(--color-ink);
}
.founders__text { margin: 0; font-size: 15px; line-height: 1.65; color: var(--color-ink-soft); }
/* The arrows float over the slides at either edge, so the scroller needs to be
   the positioning context. */
.founders__carousel { position: relative; }
.founders__arrow {
	position: absolute;
	top: 50%;
	z-index: 2;
	transform: translateY(-50%);
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	border-radius: 50%;
	border: 0;
	background: #fff;
	color: var(--color-ink-soft);
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
	cursor: pointer;
	transition: color 0.2s ease, box-shadow 0.2s ease;
}
.founders__arrow svg { width: 20px; height: 20px; }
.founders__arrow--prev { left: clamp(12px, 2vw, 28px); }
.founders__arrow--next { right: clamp(12px, 2vw, 28px); }
.founders__arrow:hover { color: var(--color-ink); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18); }
/* Full-bleed scroller: the track starts at the container's left edge but is
   free to run off the right, like the reference band. */
.founders__viewport {
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
}
.founders__viewport::-webkit-scrollbar { display: none; }
.founders__track { display: flex; }
.founders__slide {
	flex: 0 0 auto;
	display: grid;
	grid-template-columns: 1fr 1fr;
	width: min(760px, 62vw);
	height: clamp(380px, 34vw, 520px);
	scroll-snap-align: start;
}
/* Same absolute-inset pattern used elsewhere — a percentage-height image
   inside a grid track would collapse. */
.founders__media { position: relative; overflow: hidden; }
.founders__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.founders__panel {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 24px;
	padding: clamp(24px, 2.6vw, 40px);
	background: var(--color-band);
}
.founders__quote {
	margin: 0;
	font-size: 16px; /* Match the Latest Stories article titles. */
	line-height: 1.6;
	color: var(--color-ink);
}
.founders__attribution { margin: 0; }
.founders__name { margin: 0 0 4px; font-size: 14px; font-weight: 600; color: var(--color-ink); }
.founders__role {
	margin: 0;
	font-size: 11px;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--color-ink-soft);
}
.founders__link {
	display: inline-block;
	margin-top: 12px;
	font-size: 13px;
	font-weight: 600;
	color: var(--color-accent-dark);
	text-decoration: underline;
	text-underline-offset: 3px;
}
.founders__link:hover { color: var(--color-ink); }
/* =========================================================
   Concentration edit band
   ========================================================= */
/* Three gapless full-bleed panels — no .section padding, it runs edge to edge. */
.edit-band {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
}
.edit-band__panel {
	position: relative;
	display: block;
	overflow: hidden;
	height: clamp(360px, 38vw, 520px);
	color: #fff;
}
.edit-band__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Per-panel crop tuning. The photographs are near the panel's own aspect, so
	   object-position has almost nothing to slide along -- a transform is the only
	   way to push in on a subject that sits off-centre in its frame.
	   --eb-zoom scales about the centre; --eb-x/--eb-y then shift the subject back
	   to the middle. Defaults are a no-op, so a panel that sets nothing behaves
	   exactly as it did before these variables existed. */
	transform: translate(var(--eb-x, 0), var(--eb-y, 0)) scale(var(--eb-zoom, 1));
	transition: transform 0.6s ease;
}
/* The hover push multiplies whatever base zoom the panel has rather than
   replacing it, otherwise hovering a zoomed panel would shrink it back. */
.edit-band__panel:hover .edit-band__img {
	transform: translate(var(--eb-x, 0), var(--eb-y, 0)) scale(calc(var(--eb-zoom, 1) * 1.04));
}
/* Room Spray: the two bottles sit low and left of centre in a frame with a lot of
   desk around them, so at full frame they read as a small detail. Zooming in and
   shifting up-and-right puts the pair in the middle of the panel, clear of the
   title.
   The zoom and the shift are coupled, and this is the one rule to keep: a
   translate can only move the image by the overflow the zoom created, which is
   (zoom - 1) / 2 on each edge. Ask for more and the photograph's own edge slides
   into frame, leaving a bare strip of page background -- which is exactly what
   1.15 with -9% did (7.5% of headroom against a 9% shift, so 1.5% of white along
   the bottom). 1.24 gives 12% of headroom, clearing both the -9% vertical and the
   6.5% horizontal shift with room to spare. Hover only scales up, so it can never
   reintroduce the gap. */
.edit-band__panel--room-spray {
	--eb-zoom: 1.24;
	--eb-x: 6.5%;
	--eb-y: -9%;
}
/* Scent Tag: a single sachet centred on its backdrop, so unlike the panels around
   it this one needs almost nothing -- the card's bounding box is 22%-85% across
   and 20%-82% down, which the column's crop already contains whole. The only
   nudge is horizontal: the card's centre of mass sits at 54% rather than 50%
   (its drop shadow falls to the right), and matching object-position to that
   keeps an even margin of backdrop down both sides.
   No zoom on purpose. The photograph is a product shot rather than a scene, and
   pushing in far enough to fill the frame would start shaving the card's own
   edges; the band of clear backdrop under the card is where the title sits. */
.edit-band__panel--scent-tag .edit-band__img {
	object-position: 54% center;
}
/* Two of the three photos are pale, so the scrim does the legibility work. */
.edit-band__panel::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0) 35%, rgba(0, 0, 0, 0.15) 55%, rgba(0, 0, 0, 0.6) 100%);
}
.edit-band__copy {
	position: absolute;
	left: 20px;
	right: 20px;
	bottom: clamp(24px, 3vw, 40px);
	z-index: 2;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	text-align: center;
}
.edit-band__title {
	/* Matches the hero and the scent-marquee heading; sized up to compensate for
	   Instrument Serif's small cap height. */
	font-family: var(--font-hero);
	font-size: clamp(23px, 1.9vw, 30px);
	line-height: 1.2;
	text-shadow: 0 1px 12px rgba(0, 0, 0, 0.35);
}
/* Hover reveal: the copy sits low and centred, and the CTA fades up into the
   gap that opens beneath it. */
.edit-band__btn {
	font-size: 13px;
	font-weight: 500;
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 5px;
	opacity: 0;
	/* Negative margin collapses the row the CTA would occupy, so the title sits
	   lower until hover and then rides up as the link appears. */
	margin-top: -34px;
	transition: opacity 0.3s ease, margin-top 0.35s ease;
}
.edit-band__panel:hover .edit-band__btn,
.edit-band__panel:focus-visible .edit-band__btn {
	opacity: 1;
	margin-top: 0;
}
/* Without a real hover (touch), a hidden CTA is just a missing one. */
@media (hover: none) {
	.edit-band__btn { opacity: 1; margin-top: 0; }
}
/* Five across, each panel is a narrow column well before the old three-up
   breakpoint bit. Two-up first, then one, rather than dropping straight from
   five to one and leaving a very tall stack. Five is an odd count, so the last
   row of a two-up grid is left holding a single panel; it spans the full width
   rather than sitting in column one with a hole beside it. :last-child alone
   would stretch the fifth panel even if the band went back to an even number of
   categories, hence the :nth-child(odd) guard. */
@media (max-width: 1100px) {
	.edit-band { grid-template-columns: repeat(2, 1fr); }
	.edit-band__panel { height: clamp(300px, 34vw, 420px); }
	.edit-band__panel:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
/* The orphan slot is twice the width of its siblings, so a zoom tuned for a
   column reads as a close-up in it -- Room Spray's 1.24 blew one bottle up to
   fill a 985px panel the moment it was reordered to the end of the band. Keyed
   off the slot rather than the slug: which category lands there changes with the
   order of $edit_slugs, and the next reorder should not need a CSS edit. Bounded
   below at 621px because the one-up band underneath is not a wide slot -- every
   panel is full width there, so the tuning is wanted again. */
@media (min-width: 621px) and (max-width: 1100px) {
	.edit-band__panel:last-child:nth-child(odd) {
		--eb-zoom: 1;
		--eb-x: 0;
		--eb-y: 0;
	}
}
@media (max-width: 620px) {
	/* Two panels side by side get too narrow to hold the title on one line. */
	.edit-band { grid-template-columns: 1fr; }
	.edit-band__panel { height: clamp(320px, 62vw, 420px); }
	/* Solid Perfume: the charm sits low in the frame, so a landscape crop drops it
	   straight behind the title. Bias the crop down to lift it clear. */
	.edit-band__panel--solid-perfume .edit-band__img { object-position: center 92%; }
}

/* =========================================================
   Product carousel row (Best Sellers, The August Edit)
   ========================================================= */
.best-sellers__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: clamp(20px, 2.5vw, 32px);
}
.best-sellers__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(27px, 2.7vw, 37px);
	line-height: 1.2;
	color: var(--color-ink);
}
/* Title and its line travel together so the arrows stay opposite the pair
   rather than being pushed off by the paragraph. min-width: 0 lets the copy
   shrink before the arrows do, which are a fixed 38px each. */
.best-sellers__copy { min-width: 0; }
/* Same caption treatment as .founders__text and .signatures__text: the body
   face, not the display serif, so it reads under the title rather than
   alongside it. */
.best-sellers__text {
	margin: 6px 0 0;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}
.best-sellers__nav { display: flex; gap: 8px; flex-shrink: 0; }
.best-sellers__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-ink-soft);
	cursor: pointer;
	transition: color 0.2s ease;
}
.best-sellers__arrow svg { width: 22px; height: 22px; }
.best-sellers__arrow:hover { color: var(--color-ink); }
/* Full-bleed scroller: the row starts at the container edge and runs off the
   right, so a partial fifth card hints there's more. */
.best-sellers__viewport {
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	/* Without this the track's off-screen cards still counted toward the
	   document's scrollWidth even though the scroller clips them. */
	contain: paint;
	/* Matches the track's leading padding — without it the browser snaps the
	   first card past that padding on load. */
	scroll-padding-left: max(var(--gutter), calc((100vw - var(--container-width)) / 2 + var(--gutter)));
}
.best-sellers__viewport::-webkit-scrollbar { display: none; }
.best-sellers__track {
	display: flex;
	gap: 2px;
	margin: 0;
	/* Start level with the heading above rather than at the window edge. */
	padding: 0 0 0 max(var(--gutter), calc((100vw - var(--container-width)) / 2 + var(--gutter)));
	list-style: none;
	width: max-content;
}
/* Carousel geometry only — the look of the card itself is the shared block
   below, which the shop grid opts into as well. */
.best-sellers .product-card {
	flex: 0 0 auto;
	width: clamp(230px, 24vw, 340px);
	scroll-snap-align: start;
}

/* ---------------------------------------------------------
   Bare product card: no tile, cut-out bottle sitting straight on the page
   colour, title above brand, no add-to-cart button. Set by Best Sellers and
   The August Edit; the shop grid matches them so a product looks the same
   wherever it appears.
   --------------------------------------------------------- */
.best-sellers .product-card { background: none; }
.best-sellers .product-card,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card { border-radius: 0; }
/* The bottle shots here are cut-out PNGs with a real alpha channel, so the tile
   stays transparent and the section's page background reads straight through —
   no visible box edge around each card. */
.best-sellers .product-card__media,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__media { background: transparent; aspect-ratio: 3 / 4; }
/* The reference keeps the photo on hover and slides a bar over it, so the
   card's default photo-swap-for-doodle treatment is switched off here -- except
   on cards carrying a second photograph, where the swap is wanted and the first
   photo has to clear out from under it. */
.best-sellers .product-card:hover .product-card__media:not(.product-card__media--has-alt) img,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card:hover .product-card__media:not(.product-card__media--has-alt) img { opacity: 1; }
.best-sellers .product-card__hover-art,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__hover-art { display: none; }
.best-sellers .product-card__media img,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__media img { object-fit: contain; }
.best-sellers .product-card__info,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__info { padding: 14px 4px 0; gap: 5px; }
.best-sellers .product-card__title,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__title { order: 1; font-size: 15px; }
.best-sellers .product-card__brand,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__brand { order: 2; }
.best-sellers .product-card__price,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__price { order: 3; }
.best-sellers .product-card__add,
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__add { display: none; }
/* Not every shot in the catalogue is a clean cut-out — a chunk are photographed
   on a white card, which reads as a white box on the page's pale blue once the
   tile behind it is gone. Same 'darken' trick as The August Edit: the per-channel
   minimum against the page colour drops near-white to the background and leaves
   the bottle, and genuinely dark editorial shots, untouched. */
:is(.shop-main, .shop-results, .product-related) ul.products .product-card__media img { mix-blend-mode: darken; }
/* The blend needs a painted backdrop: .product-card has overflow:hidden, so it
   is the card's own background the image blends against. This is the page
   colour, so it reads as no tile at all. */
:is(.shop-main, .shop-results, .product-related) ul.products .product-card { background: var(--color-bg); }
/* The grid is roomier than the carousel, so the rows need a little more air
   between a card's caption and the next row's photo. */
:is(.shop-main, .shop-results, .product-related) ul.products { row-gap: calc(var(--gutter) + 12px) !important; }
/* Four to a row, matching the carousel. Opening the filter sidebar takes the row
   to three. Below 980px the 2-up responsive rules take back over. */
@media (min-width: 981px) {
	.shop-layout.is-filters-hidden .shop-main ul.products {
		grid-template-columns: repeat(4, 1fr) !important;
	}
	.shop-layout .shop-main ul.products {
		grid-template-columns: repeat(3, 1fr) !important;
	}
	/* The carousel sets its cards 2px apart and lets the photo's own margin do the
	   separating, so the grid uses the same figure — with a 40px gutter the card
	   comes out ~28px narrower than the carousel's, which is most of what made the
	   two rows look like different products. Rows keep their own spacing. */
	.shop-layout .shop-main ul.products { column-gap: 2px !important; }
}
/* Two stacked section paddings left a ~200px hole before Meet the Founders. */
.best-sellers { padding-bottom: clamp(28px, 3vw, 40px); }
/* Best Sellers and The August Edit are the same treatment back to back, so the
   second row only needs enough air to read as its own section, not a full band
   gap on top of the first row's remaining padding. */
.best-sellers--august { padding-top: clamp(36px, 4vw, 60px); }
/* This row shows the whole perfume catalogue, and a chunk of those shots are
   photographed on a white card instead of being cut out — they read as white
   boxes floating on the page. 'darken' takes the per-channel minimum
   against the page background, so anything at or near white collapses into the
   background while the bottle itself, being darker, is untouched. Shots on a
   genuinely dark backdrop are darker than the page in every channel too, so they
   also come through unchanged. */
.best-sellers--august .product-card__media img { mix-blend-mode: darken; }
/* The blend needs something to blend against. The viewport's own 'contain: paint'
   makes it a stacking context, and the section paints no background of its own,
   so without this the images blend against transparency and nothing changes --
   the page colour lives further down on the body. */
.best-sellers--august .best-sellers__viewport { background: #fff; }

.founders { padding-top: clamp(32px, 3.4vw, 48px); }

/* =========================================================
   Quick View modal
   ========================================================= */
.quick-view {
	position: fixed;
	inset: 0;
	z-index: 200;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--gutter);
}
/* display:flex above would otherwise beat the hidden attribute, leaving an
   invisible full-screen overlay swallowing every click on the page. */
.quick-view[hidden] { display: none; }
.quick-view__overlay {
	position: absolute;
	inset: 0;
	background: rgba(19, 19, 19, 0.5);
	opacity: 0;
	transition: opacity 0.3s ease;
}
.quick-view.is-open .quick-view__overlay { opacity: 1; }
.quick-view__dialog {
	position: relative;
	display: flex;
	width: min(920px, 100%);
	max-height: min(640px, 90vh);
	overflow: hidden;
	background: #fff;
	opacity: 0;
	transform: translateY(12px);
	transition: opacity 0.3s ease, transform 0.3s ease;
}
.quick-view.is-open .quick-view__dialog { opacity: 1; transform: none; }
.quick-view__close {
	position: absolute;
	top: 12px;
	right: 12px;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border: 0;
	background: rgba(255, 255, 255, 0.85);
	color: var(--color-ink);
	cursor: pointer;
}
.quick-view__close svg { width: 20px; height: 20px; }
.quick-view__body { display: contents; }
.quick-view__loading {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: 320px;
	margin: 0;
	color: var(--color-ink-soft);
}
.quick-view__media {
	flex: 0 0 45%;
	background: var(--color-bg-soft);
}
.quick-view__media img { width: 100%; height: 100%; object-fit: contain; }
.quick-view__info {
	flex: 1 1 auto;
	overflow-y: auto;
	padding: clamp(24px, 3vw, 40px);
}
.quick-view__brand {
	display: block;
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-ink-soft);
}
.quick-view__title {
	margin: 8px 0 0;
	font-family: var(--font-display);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(20px, 2vw, 26px);
	line-height: 1.25;
}
.quick-view__price { margin-top: 10px; font-size: 17px; }
.quick-view__desc {
	margin-top: 14px;
	font-size: 14px;
	line-height: 1.6;
	color: var(--color-ink-soft);
}
.quick-view__info form.cart { margin-top: 20px; }
.quick-view__full {
	display: inline-block;
	margin-top: 18px;
	font-size: 14px;
	color: var(--color-ink);
	text-decoration: underline;
	text-underline-offset: 4px;
}
@media (max-width: 720px) {
	.quick-view__dialog { flex-direction: column; max-height: 88vh; overflow-y: auto; }
	.quick-view__media { flex: 0 0 auto; aspect-ratio: 4 / 5; }
	.quick-view__body { display: contents; }
}

/* =========================================================
   Latest Stories
   ========================================================= */
.stories__head {
	display: flex;
	align-items: baseline;
	gap: 18px;
	margin-bottom: clamp(18px, 2.2vw, 28px);
}
.stories__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(27px, 2.7vw, 37px);
	line-height: 1.2;
	color: var(--color-ink);
}
/* Hairline between the heading and the link, as in the reference. */
.stories__all {
	position: relative;
	padding-left: 19px;
	font-size: 14px;
	color: var(--color-ink);
	text-decoration: none;
}
.stories__all::before {
	content: '';
	position: absolute;
	left: 0;
	top: 50%;
	width: 1px;
	height: 1.15em;
	transform: translateY(-50%);
	background: rgba(19, 19, 19, 0.25);
}
.stories__all:hover { text-decoration: underline; text-underline-offset: 4px; }

.stories__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 2px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.story-card__link {
	display: flex;
	flex-direction: column;
	color: inherit;
	text-decoration: none;
}
.story-card__date {
	padding-right: 14px;
	font-size: 13px;
	color: var(--color-ink-soft);
}
.story-card__title {
	margin: 8px 0 0;
	padding-right: 14px;
	font-family: var(--font-base);
	font-weight: 500;
	text-transform: none;
	letter-spacing: 0;
	font-size: 16px;
	line-height: 1.35;
	color: var(--color-ink);
	/* Two lines fixed, so every card's image starts on the same baseline. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	min-height: calc(2 * 1.35em);
}
.story-card__excerpt {
	margin: 6px 0 0;
	padding-right: 14px;
	font-size: 14px;
	line-height: 1.4;
	color: var(--color-ink-soft);
	display: -webkit-box;
	-webkit-line-clamp: 1;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.story-card__media {
	display: block;
	margin-top: 16px;
	aspect-ratio: 3 / 4;
	overflow: hidden;
}
.story-card__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s ease;
}
.story-card__link:hover .story-card__img { transform: scale(1.04); }
.story-card__link:hover .story-card__title { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 980px) {
	.stories__grid { grid-template-columns: repeat(2, 1fr); gap: 36px 20px; }
}
/* On phones the four cards became a very long column — four full-height
   images to scroll past before the rest of the page. Swiped sideways instead,
   the same gesture the founders row and the product carousels already use.
   display:flex overrides the grid, so grid-template-columns above is inert
   here rather than fighting it. */
@media (max-width: 560px) {
	.stories__grid {
		display: flex;
		gap: 16px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: none;
	}
	.stories__grid::-webkit-scrollbar { display: none; }
	.stories__grid > .story-card {
		flex: 0 0 auto;
		width: 72vw;
		max-width: 300px;
		scroll-snap-align: start;
	}
}

/* Journal index — same card, laid out as a grid. */
.journal__head { margin-bottom: clamp(24px, 3vw, 40px); }
/* --font-hero, matching .stories__title on the homepage: this page is where
   "Latest Stories" sends you, and the two headings were set in different serifs
   -- they are both Instrument Serif now, but this predates that. Size stays larger than the
   homepage's, since this is the page's h1 rather than a section heading. */
.journal__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(28px, 3.4vw, 44px);
	line-height: 1.2;
	color: var(--color-ink);
}
.journal__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(24px, 3vw, 40px);
	margin: 0;
	padding: 0;
	list-style: none;
}
.story-card--grid { width: auto; }
@media (max-width: 980px) { .journal__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 600px) { .journal__grid { grid-template-columns: 1fr; } }

/* =========================================================
   Homepage trust bar
   ========================================================= */
/* Latest Stories above and the FAQ below each already contribute their own
   padding to this band's two edges, so it adds none of its own on top and only
   half below — leaving an even gap on either side instead of a stacked double. */
.trust {
	padding-top: 0;
	padding-bottom: calc(var(--section-pad) / 2);
}

.trust__grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	align-items: start;
}

.trust__col {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding: 0 clamp(16px, 3vw, 44px);
}

/* Hairline rules between columns, not around the outside — a border on every
   column would draw one down each edge of the row too. */
.trust__col + .trust__col { border-left: 1px solid var(--color-border); }

.trust__icon { display: block; color: var(--color-ink); }
.trust__icon svg { display: block; width: 44px; height: 44px; }

.trust__title {
	margin: 20px 0 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(21px, 1.8vw, 25px);
	line-height: 1.3;
	color: var(--color-ink);
}

.trust__text {
	margin: 12px 0 0;
	max-width: 34ch;
	font-size: 14px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}

.trust__btn {
	margin-top: 22px;
	display: inline-block;
	padding: 13px 26px;
	border: 1px solid var(--color-border);
	background: transparent;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--color-ink);
	transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.trust__btn:hover {
	background: var(--color-navy);
	border-color: var(--color-navy);
	color: #fff;
}

@media (max-width: 860px) {
	.trust__grid { grid-template-columns: 1fr; gap: clamp(32px, 6vw, 48px); }
	.trust__col { padding: 0; }
	/* Stacked, the divider has to run along the top of each column instead. */
	.trust__col + .trust__col {
		border-left: 0;
		border-top: 1px solid var(--color-border);
		padding-top: clamp(32px, 6vw, 48px);
	}
}

/* =========================================================
   Homepage FAQ
   ========================================================= */
/* Latest Stories above ends on a full --section-pad, so the FAQ's own equal
   padding stacks with it into roughly double the gap below, where the
   newsletter only contributes its halved padding. Halve the top to even out
   the two visible gaps rather than changing either neighbour. */
.faq { padding-top: calc(var(--section-pad) / 2); }

.faq__inner {
	display: grid;
	grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
	gap: 24px;
	align-items: start;
}
.faq__title {
	margin: 0 0 8px;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(30px, 3vw, 40px);
	line-height: 1.2;
	color: var(--color-ink);
}
.faq__text { margin: 0; font-size: 15px; line-height: 1.65; color: var(--color-ink-soft); }
.faq__item { border-top: 1px solid var(--color-border); }
.faq__item:last-child { border-bottom: 1px solid var(--color-border); }
.faq__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	padding: 18px 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--color-ink);
	cursor: pointer;
	list-style: none;
}
/* Safari still paints its own disclosure triangle without this. */
.faq__q::-webkit-details-marker { display: none; }
.faq__icon { flex-shrink: 0; width: 20px; height: 20px; color: var(--color-ink-soft); transition: transform 0.2s ease; }
.faq__item[open] .faq__icon { transform: rotate(180deg); }
.faq__a { margin: 0; padding: 0 40px 20px 0; font-size: 15px; line-height: 1.7; color: var(--color-ink-soft); }

/* =========================================================
   FAQ page (page-faq.php)
   =========================================================
   The accordion itself is the .faq__item component above, shared with the
   homepage section. Only the page frame and the group headings live here.
   Deliberately wider than .page-content--prose's 68ch: that measure is for
   running prose, and an accordion row is a title with a chevron pinned to its
   far right -- at 68ch the chevron sits just past the text and the row stops
   reading as a full-width control. */
.faq-page { max-width: 900px; }
/* First group sits directly under the page title, so it drops the top margin
   the later groups use to separate themselves from the accordion above. */
.faq-page__group + .faq-page__group { margin-top: clamp(40px, 5vw, 64px); }
/* Matches .page-body h2 exactly -- the group headings are the same signposts
   through the same document, just rendered by this template instead of by the
   editor's raw markup. */
.faq-page__group-title {
	margin: 0 0 12px;
	font-family: var(--font-base);
	font-size: 20px;
	font-weight: 600;
	line-height: 1.35;
	color: var(--color-ink);
}
.faq-page__intro { margin-bottom: clamp(24px, 3vw, 36px); }
.faq-page__group-intro { margin-bottom: 12px; }
/* .faq__a is a bare <p> in the homepage section but a wrapper <div> here, since
   an answer authored in wp-admin may be several paragraphs or carry a list.
   The padding/colour/size come from .faq__a above; these just stop the child
   blocks adding margins that break the row's spacing at its top and bottom. */
.faq__a > * { font-size: inherit; line-height: inherit; color: inherit; }
.faq__a > p { margin: 0 0 12px; }
.faq__a > :first-child { margin-top: 0; }
.faq__a > :last-child { margin-bottom: 0; }
.faq__a a { color: var(--color-ink); text-decoration: underline; }
@media (max-width: 780px) {
	.faq__inner { grid-template-columns: 1fr; }
	.faq__a { padding-right: 0; }
}

@media (max-width: 780px) {
	/* One panel pair per screen, image stacked above the quote. The row was a
	   flat 260px, which on an ~330px-wide slide is a landscape letterbox — and
	   every portrait in here is a 4:5 portrait, so cover() cropped the top of
	   the head off. Let the media keep the source's own aspect instead, and
	   anchor what little cropping remains to the top, where the faces are. */
	.founders__slide {
		grid-template-columns: 1fr;
		grid-template-rows: auto auto;
		width: 88vw;
		height: auto;
	}
	/* Every founder portrait on file is square (800x800), so a square frame
	   crops nothing at all — the old 260px row was a landscape letterbox on a
	   ~330px slide and cut the top of the head off. */
	.founders__media { aspect-ratio: 1 / 1; }
	.founders__head { flex-direction: column; align-items: flex-start; }
}

/* =========================================================
   Home — Singapore Signatures (heading + two photo panels)
   ========================================================= */
/* The heading sits inside the container; the panels below deliberately do not,
   so they run to both viewport edges and meet dead centre with no gutter. */
/* Ranged left off the container's edge, the same opening as Meet the Makers
   further down the page, rather than centred on its own. The panels below stay
   full bleed -- only the head sits in the container. */
.signatures__head {
	text-align: left;
	padding-top: clamp(56px, 7vw, 96px);
	padding-bottom: clamp(28px, 3.5vw, 44px);
}
/* Size, weight, leading and the 8px drop to the line beneath are .founders__title's,
   so the two section openings read as one treatment used twice. */
.signatures__title {
	margin: 0 0 8px;
	font-family: var(--font-hero);
	/* 400 because Instrument Serif ships a single weight -- see the note on
	   .filter-drawer__head h2. Its italic is a real cut, so <em> is safe. */
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(30px, 3vw, 40px);
	line-height: 1.2;
	color: var(--color-ink);
}
.signatures__title em { font-style: italic; }
/* Set in the body face, not the display serif, so it reads as a caption to the
   title rather than competing with it. Matches .founders__text: no measure cap,
   because left-ranged copy this short does not run long enough to need one. */
.signatures__text {
	margin: 0;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}

.signatures__panels {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0;
}
/* The whole panel is the link, not a button inside it -- the reference gives no
   visible affordance, so the entire image has to be the target. */
.signature-panel {
	position: relative;
	display: block;
	overflow: hidden;
	min-height: clamp(420px, 52vw, 780px);
	/* Stands in until a photograph is set, so the white overlay copy is legible
	   against something even on a panel with no image. */
	background: var(--color-navy);
	text-decoration: none;
	isolation: isolate;
}
.signature-panel__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	z-index: -2;
	transition: transform 0.6s ease;
}
.signature-panel:hover .signature-panel__img { transform: scale(1.04); }
/* The overlay copy is white over user-supplied photography. The wash is heaviest
   at the top-left and bottom-right corners, which is exactly where the two blocks
   of type sit -- a flat scrim over the whole frame would dull the image for no
   reason.
   Only one gradient now: all the copy sits in the top-left corner, so the wash
   that used to cover the bottom-right is gone and that half of each photograph is
   clean. The weight is set for light photographs, which is the harder case. */
.signature-panel::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(160deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0) 55%);
}
/* Caption and call to action travel together in the top-left corner, so the
   corner is positioned once here and the two lines stack inside it. */
.signature-panel__copy {
	position: absolute;
	top: clamp(18px, 2.2vw, 32px);
	left: clamp(20px, 2.6vw, 40px);
	right: clamp(20px, 2.6vw, 40px);
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	/* Tight on purpose -- the caption sets line-height: 1, so the visual gap is
	   already wider than this number by the depth of the serif's descenders. */
	gap: clamp(5px, 0.55vw, 9px);
}
/* The reference sets this in a handwriting face. The theme loads no script font,
   so this is Instrument Serif italic -- the same display cut already used for
   the italic word in the heading above, which keeps the block coherent instead
   of introducing a fourth family for two words. */
.signature-panel__script {
	font-family: var(--font-hero);
	font-style: italic;
	font-weight: 400;
	font-size: clamp(22px, 2.5vw, 38px);
	line-height: 1;
	color: #fff;
}
/* A <span>, not a nested <a>: the whole panel is already the link, and a link
   inside a link is invalid. It only has to look like one -- the click it appears
   to offer is the one the panel gives anyway.
   Plain underlined white text, the same CTA treatment as .edit-band__btn, rather
   than the base pill. Unlike that one it does not wait for hover: these two
   panels are the section's only way through to the two categories, so the way
   through should always be visible.
   The text-shadow does what the pill's background used to. Measured over both
   photographs the corner wash alone already clears 4.5:1, but only just (4.6:1
   on the paler one) -- and the images here are swapped from the Customizer, so
   the next one uploaded may not be as kind. Same trick, same reason, as
   .scent-marquee__track .cat-tile__btn. */
.signature-panel__cta {
	font-family: var(--font-base);
	font-size: 13px;
	font-weight: 500;
	line-height: 1;
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 5px;
	text-shadow: 0 1px 10px rgba(0, 0, 0, 0.45);
}

@media (max-width: 720px) {
	/* Side by side, each panel is too narrow for the crop to read. */
	.signatures__panels { grid-template-columns: 1fr; }
	.signature-panel { min-height: 78vw; }
	/* One column makes the panel much wider than tall, so a corner gradient runs
	   out well before it reaches the caption -- measured at 2.7:1 against white on
	   the men's photograph, under the 3:1 large-text minimum. Deeper and longer
	   here brings it to 4.5:1. */
	.signature-panel::after {
		background: linear-gradient(160deg, rgba(0,0,0,0.62) 0%, rgba(0,0,0,0) 72%);
	}
}

/* =========================================================
   Shop archive — banner, filter drawer, sort, results grid
   (main shop page only; product_cat archives keep .shop-header/.shop-layout)
   ========================================================= */

/* --- Banner ------------------------------------------------ */
.shop-banner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	/* Matched to .arrivals-banner so the shop and New Arrivals banners read as
	   the same scale of full-bleed photograph. */
	min-height: clamp(380px, 44vw, 620px);
	padding: clamp(48px, 6vw, 80px) var(--gutter);
	background: var(--color-ink);
	overflow: hidden;
	isolation: isolate;
}
.shop-banner__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: -2;
}
/* The banner copy is white, and the photo behind it is user-supplied — a scrim
   is what keeps the title legible over a light image instead of trusting
   whatever gets uploaded. */
.shop-banner::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0,0,0,0.45), rgba(0,0,0,0.6));
	z-index: -1;
}
.shop-banner--plain::after { background: none; }
/* Scent Tag: the banner photograph is a 904x1200 portrait, and the bloom sits
   in the upper half of it. Left centred, a wide banner slices the flower's head
   off and frames the empty backdrop below it. The source is narrower than
   'satueen-hero' (2400x1400), so WordPress never generated that hard crop and
   the full portrait is what reaches the browser -- which is why this is an
   object-position nudge rather than a baked crop, and why it keeps adapting as
   the band's own aspect ratio changes across breakpoints. */
.term-scent-tag .shop-banner__img { object-position: center 38%; }
/* Powdery: the source is a 1491x1055 landscape, wider than the band but far
   shorter, so a centred cover crop takes a middle slice. The wool the user
   picked is the top of the frame, and -- as with Scent Tag above -- the source
   is smaller than 'satueen-hero' (2400x1400), so no hard crop is generated and
   the whole picture reaches the browser. Anchoring to the top keeps that band
   in view at every breakpoint instead of baking one crop for one width. */
.term-powdery .shop-banner__img { object-position: center top; }
/* Flat blue banner, used where there is no photograph -- the two brand blues
   run corner to corner. Deep enough at both ends that the white copy holds,
   so the scrim above is switched off. */
.shop-banner--gradient {
	background: linear-gradient(135deg, var(--color-navy) 0%, var(--color-accent) 60%, var(--color-accent-dark) 100%);
}
.shop-banner--gradient::after { background: none; }
/* The same idea a few steps lighter, for the shop and category archives. It
   stops at the mid blues rather than going near-navy; any paler and the small
   uppercase breadcrumb stops holding against white. */
.shop-banner--gradient-soft {
	background: linear-gradient(135deg, var(--color-accent) 0%, #6b809b 55%, #55697f 100%);
}
.shop-banner--gradient-soft::after { background: none; }
.shop-banner__inner {
	max-width: 760px;
	text-align: center;
	color: #fff;
}
.shop-banner__crumbs {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	margin-bottom: 18px;
	color: rgba(255, 255, 255, 0.75);
}
.shop-banner__crumbs a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.shop-banner__crumbs a:hover { color: #fff; }
.shop-banner__crumbs [aria-current] { color: #fff; }
.shop-banner__title {
	font-family: var(--font-hero);
	font-size: clamp(38px, 6vw, 72px);
	font-weight: 400;
	line-height: 1.05;
	margin: 0;
	color: #fff;
}
/* Brand archives put the house's own logo where the title type would go. */
.shop-banner__title--logo { display: flex; justify-content: center; }
.shop-banner__logo {
	height: clamp(34px, 4.6vw, 62px);
	width: auto;
	max-width: min(420px, 100%);
	object-fit: contain;
	/* Every brand logo on file is black monochrome artwork on transparency, which
	   would disappear against the dark banner. brightness(0) flattens whatever
	   colour is there to solid black, then invert(1) takes it to solid white --
	   so a logo reads correctly here without anyone having to supply a second
	   white version of it. */
	filter: brightness(0) invert(1);
}
.shop-banner__desc {
	margin: 18px auto 0;
	max-width: 620px;
	font-size: 15px;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.85);
}

/* --- Brand story ------------------------------------------- */
/* The editorial a brand archive can open with in place of .shop-banner above.
   Three bands: a full-bleed photograph with the headline over it, a pale
   statement band, and a collage beside a paragraph. See inc/brand-story.php. */

.brand-story-hero {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	/* Deeper than the banner it replaces: this is a picture being shown, not a
	   strip behind a title. */
	min-height: clamp(320px, 44vw, 560px);
	padding: clamp(56px, 7vw, 96px) var(--gutter);
	background: var(--color-ink);
	overflow: hidden;
	isolation: isolate;
}
.brand-story-hero__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: -2;
}
/* Same reasoning as the banner's scrim: the copy is white and the photograph
   is whatever was uploaded. Lighter in the middle than at the edges so the
   picture is not flattened -- the type sits in the calm centre anyway. */
.brand-story-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0,0,0,0.42), rgba(0,0,0,0.28) 45%, rgba(0,0,0,0.5));
	z-index: -1;
}
.brand-story-hero--plain { background: linear-gradient(135deg, var(--color-navy) 0%, var(--color-accent) 60%, var(--color-accent-dark) 100%); }
/* LUSTRA's story photograph is a 4:5 portrait in a band that is nearer 2.26:1,
   so only about a third of its height is ever on screen and which third is a
   choice. Biased low, to the skirt and the trailing hem rather than the head:
   the band carries the wordmark and the tagline across its middle, and the
   softer lower half of the picture sits under type better than a face does.
   78% lands the window at roughly the image's midpoint and runs it down to
   just above the floor line. Per-brand because it is a property of this one
   photograph, not of the band: a brand that supplies a landscape image needs
   nothing here. */
.term-lustra .brand-story-hero__img { object-position: center 78%; }
.brand-story-hero--plain::after { background: none; }
.brand-story-hero__inner {
	max-width: 900px;
	text-align: center;
	color: #fff;
}
/* Doubles as the reference layout's eyebrow -- it is small caps in the same
   place, and its last item is the brand name. */
.brand-story-hero__crumbs {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: 10px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	margin-bottom: clamp(16px, 2vw, 26px);
	color: rgba(255, 255, 255, 0.72);
}
.brand-story-hero__crumbs a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.brand-story-hero__crumbs a:hover { color: #fff; }
.brand-story-hero__crumbs [aria-current] { color: #fff; }
.brand-story-hero__wordmark {
	display: flex;
	justify-content: center;
	margin-bottom: clamp(14px, 1.8vw, 24px);
}
.brand-story-hero__logo {
	height: clamp(30px, 3.6vw, 52px);
	width: auto;
	max-width: min(360px, 80%);
	object-fit: contain;
	/* Same treatment as .shop-banner__logo, and for the same reason: every brand
	   logo on file is black monochrome artwork, which would vanish against a
	   dark photograph. brightness(0) flattens whatever colour is there to solid
	   black, invert(1) takes it to solid white. */
	filter: brightness(0) invert(1);
}
/* Brands with no wordmark on file set their name instead, at the size the logo
   would have occupied -- without it the small tracked headline below would be
   the only thing in the band and the house would go unnamed. */
.brand-story-hero__name {
	margin: 0;
	font-family: var(--font-display);
	font-size: clamp(26px, 3.4vw, 46px);
	font-weight: 400;
	letter-spacing: 0.06em;
	line-height: 1.1;
	text-transform: uppercase;
	color: #fff;
}
/* The reference sets this headline in wide-tracked sans caps rather than the
   display serif, and that is the whole character of the band -- so it is the
   one heading on the site that is not var(--font-display). It is deliberately
   smaller than the wordmark above it: the house's name leads, and this reads
   as the line underneath it rather than as a competing title. */
.brand-story-hero__title {
	margin: 0;
	font-size: clamp(13px, 1.5vw, 19px);
	font-family: var(--font-base);
	font-weight: 400;
	letter-spacing: 0.08em;
	line-height: 1.4;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.92);
}

.brand-story {
	/* Tight on purpose: statement and collage together are meant to sit inside
	   one screen the way the reference does, so the padding here is nearer a
	   half section than the full --section-pad. */
	padding: clamp(40px, 5vw, 64px) var(--gutter) clamp(40px, 5vw, 68px);
	background: var(--color-bg-soft);
}
.brand-story__split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	align-items: center;
	gap: clamp(28px, 4vw, 64px);
	max-width: var(--container-width);
	/* No top margin: the statement band that used to sit above this is gone, so
	   the band's own padding is the whole of the space over it now. */
	margin: 0 auto;
}
/* The two photographs overlap, so the second is positioned rather than laid
   out: padding on the wrapper reserves the room its offset needs, which is what
   keeps it from spilling over the copy beside it or the band's own edge.
   The whole collage is capped at 560px -- the reference runs it at about 39%
   of the window and the pair has to clear the fold along with the statement
   above it, which a photograph sized off the column alone would not. */
.brand-story__collage {
	position: relative;
	width: 100%;
	max-width: 560px;
	/* 38%: what is left is the first photograph's own width, so the two move
	   together when the cap or the column changes. */
	padding-right: 38%;
}
.brand-story__photo--a {
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 5;
	object-fit: cover;
}
/* An empty photograph slot, standing in until the brand's real pictures are
   uploaded. Dashed, following the same convention the product card's fallback
   category badge uses, so nobody mistakes a slot waiting on an asset for a
   finished design. Both slots keep their real geometry, so dropping the
   photographs in changes nothing about the layout around them. */
.brand-story__photo--placeholder {
	border: 1px dashed rgba(80, 98, 119, 0.45);
	background: var(--color-blue);
	object-fit: contain;
}
/* The stand-in line a brand shows until its story is written. Marked the same
   way as the empty photo frames -- muted and italic rather than dashed, since a
   border around a single line of prose reads as a form field. It is a note to
   whoever is filling the brand in, not copy, so it must never pass for the
   real thing. */
.brand-story__text--placeholder {
	color: rgba(19, 19, 19, 0.45);
	font-style: italic;
}
/* Centred on the first photograph rather than hung off its bottom corner: it
   is what keeps the collage no taller than the picture behind it, which is the
   whole reason the section now fits a screen. */
.brand-story__photo--b {
	position: absolute;
	right: 0;
	top: 50%;
	transform: translateY(-50%);
	width: 48%;
	height: auto;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	/* Lifts it off the photograph behind rather than letting the two read as one
	   flat shape where they meet. */
	box-shadow: 0 18px 44px rgba(19, 19, 19, 0.16);
}
.brand-story__copy { min-width: 0; }
.brand-story__eyebrow {
	margin: 0;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--color-ink-soft);
}
/* Tracked caps to answer the headline over the photograph, so the two headings
   on the page belong to the same voice. */
.brand-story__heading {
	margin: clamp(14px, 1.8vw, 22px) 0 0;
	font-family: var(--font-base);
	font-size: clamp(20px, 2.2vw, 30px);
	font-weight: 700;
	letter-spacing: 0.035em;
	line-height: 1.25;
	text-transform: uppercase;
	color: var(--color-ink);
}
.brand-story__text {
	margin: clamp(18px, 2.2vw, 28px) 0 0;
	max-width: 46ch;
	font-size: 15px;
	line-height: 1.75;
	color: var(--color-ink-soft);
}
/* Paragraphs after the first sit closer than the gap under the heading, so the
   copy reads as one passage rather than as separate blocks. */
.brand-story__text + .brand-story__text { margin-top: 1.1em; }

@media (max-width: 980px) {
	/* Stacked, and the collage goes first -- the picture is the introduction. */
	.brand-story__split { grid-template-columns: 1fr; gap: clamp(24px, 5vw, 40px); }
	/* Stacked, the collage has the full measure to itself, so the first
	   photograph can take more of it than the 38% reserve leaves at desktop. */
	.brand-story__collage { margin: 0 auto; padding-right: 30%; }
	.brand-story__text { max-width: none; }
}

/* --- Toolbar ----------------------------------------------- */
/* Full-bleed, not container-capped: Filters sits hard left and sort hard right,
   matching the header treatment above it. */
.shop-toolbar--bleed {
	max-width: none;
	/* Resets the base .shop-toolbar's 32px margin-bottom, which would otherwise
	   stack on top of .shop-results' own top padding. */
	margin: 0;
	padding: 34px var(--gutter);
	display: flex;
	align-items: center;
	gap: 28px;
	border-bottom: 1px solid var(--color-border);
	font-size: 13px;
	color: var(--color-ink-soft);
}

.filter-toggle,
.shop-sort__toggle {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 11px 20px;
	background: transparent;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-pill);
	font-family: inherit;
	font-size: 14px;
	font-weight: 500;
	color: var(--color-ink);
	cursor: pointer;
	transition: border-color 0.2s ease, background 0.2s ease;
}
.filter-toggle:hover,
.shop-sort__toggle:hover { border-color: var(--color-ink); }
.filter-toggle svg,
.shop-sort__toggle svg { width: 16px; height: 16px; transition: transform 0.2s ease; }
.filter-toggle[aria-expanded="true"] svg,
.shop-sort__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

.filter-toggle__badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
	border-radius: var(--radius-pill);
	background: var(--color-accent);
	color: #fff;
	font-size: 11px;
	font-weight: 700;
}
.filter-toggle__badge[hidden] { display: none; }

/* Two-line count, as in the reference: the label sits quietly above the number. */
.shop-toolbar__count {
	display: flex;
	flex-direction: column;
	line-height: 1.3;
	white-space: nowrap;
	text-align: left;
}
.shop-toolbar__count-label { font-size: 12px; color: var(--color-ink-faint); }
.shop-toolbar__count-value { font-size: 14px; color: var(--color-ink); font-weight: 500; }
/* The term-archive toolbar still uses the old single-line, centred count. */
.shop-toolbar__count--inline { display: block; text-align: center; }

/* --- Sort dropdown ----------------------------------------- */
.shop-sort { position: relative; margin-left: auto; }
.shop-sort__toggle { min-width: 190px; justify-content: space-between; }
.shop-sort__menu {
	position: absolute;
	top: calc(100% + 8px);
	right: 0;
	z-index: 40;
	min-width: 240px;
	margin: 0;
	padding: 8px;
	list-style: none;
	background: #fff;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-md);
	box-shadow: 0 18px 40px rgba(19, 19, 19, 0.12);
}
.shop-sort__menu[hidden] { display: none; }
.shop-sort__opt {
	display: block;
	width: 100%;
	padding: 11px 14px;
	background: none;
	border: none;
	border-radius: var(--radius-sm);
	font-family: inherit;
	font-size: 14px;
	text-align: left;
	color: var(--color-ink);
	cursor: pointer;
	/* On term archives the options are <a> links (a real page load) rather than
	   AJAX buttons, so the underline has to be cleared here too. */
	text-decoration: none;
}
.shop-sort__opt:hover { background: var(--color-bg-soft); }
.shop-sort__opt.is-active { font-weight: 600; background: var(--color-accent-soft); }

/* --- Filter drawer ----------------------------------------- */
.filter-overlay {
	position: fixed;
	inset: 0;
	z-index: 300;
	background: rgba(19, 19, 19, 0.45);
	opacity: 0;
	transition: opacity 0.3s ease;
}
.filter-overlay.is-open { opacity: 1; }
.filter-overlay[hidden] { display: none; }

.filter-drawer {
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	z-index: 301;
	width: min(420px, 92vw);
	background: #fff;
	/* Off-canvas by default and slid in by .is-open, so the panel animates
	   rather than appearing. [hidden] is removed a frame before .is-open lands
	   — see main.js. */
	transform: translateX(-100%);
	transition: transform 0.32s cubic-bezier(0.4, 0, 0.2, 1);
	display: flex;
	flex-direction: column;
}
.filter-drawer.is-open { transform: translateX(0); }
.filter-drawer[hidden] { display: none; }
.filter-drawer__form { display: flex; flex-direction: column; height: 100%; min-height: 0; }

.filter-drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 28px var(--gutter) 20px;
	flex: 0 0 auto;
}
.filter-drawer__head h2 {
	margin: 0;
	/* Same face as the banner title above it (.shop-banner__title), so the two
	   headings on this page read as one voice. Weight 400 because Instrument
	   Serif ships a single weight -- anything heavier gets synthesised. */
	font-family: var(--font-hero);
	font-size: 30px;
	font-weight: 400;
}
.filter-drawer__close {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	background: none;
	border: none;
	color: var(--color-ink);
	cursor: pointer;
}
.filter-drawer__close svg { width: 22px; height: 22px; }

/* The only scrolling region — head and foot stay pinned so Apply is always
   reachable however long the brand list gets. */
.filter-drawer__body {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	padding: 0 var(--gutter);
}

.filter-section { border-top: 1px solid var(--color-border); }
.filter-section:first-child { border-top: none; }
.filter-section__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	padding: 20px 0;
	background: none;
	border: none;
	font-family: inherit;
	font-size: 15px;
	font-weight: 600;
	color: var(--color-ink);
	cursor: pointer;
}
.filter-section__head svg { width: 18px; height: 18px; transition: transform 0.2s ease; }
.filter-section__head[aria-expanded="false"] svg { transform: rotate(180deg); }
.filter-section__head[aria-expanded="false"] + .filter-section__body { display: none; }
.filter-section__body { padding-bottom: 22px; }

.filter-options { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 14px; }
.filter-option[hidden] { display: none; }
.filter-option label {
	display: flex;
	align-items: center;
	gap: 12px;
	cursor: pointer;
	font-size: 14px;
}
/* The real checkbox stays in the accessibility tree and keeps keyboard focus;
   .filter-option__box is what actually gets painted. */
.filter-option input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}
.filter-option__box {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	border: 1.5px solid var(--color-border);
	border-radius: 3px;
	background: #fff;
	position: relative;
	transition: background 0.15s ease, border-color 0.15s ease;
}
.filter-option__box::after {
	content: "";
	position: absolute;
	left: 5px;
	top: 1px;
	width: 5px;
	height: 10px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg) scale(0);
	transition: transform 0.15s ease;
}
.filter-option input:checked + .filter-option__box { background: var(--color-ink); border-color: var(--color-ink); }
.filter-option input:checked + .filter-option__box::after { transform: rotate(45deg) scale(1); }
.filter-option input:focus-visible + .filter-option__box { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.filter-option__label { flex: 1; text-transform: uppercase; font-size: 12px; letter-spacing: 0.05em; }
.filter-option__count { color: var(--color-ink-faint); font-size: 12px; }

.filter-showmore {
	margin-top: 16px;
	padding: 0;
	background: none;
	border: none;
	font-family: inherit;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-ink);
	text-decoration: underline;
	text-underline-offset: 4px;
	cursor: pointer;
}

.filter-price { display: flex; gap: 14px; }
.filter-price__field { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.filter-price__cap {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-ink-faint);
}
.filter-price__input {
	display: flex;
	align-items: center;
	gap: 6px;
	border: 1px solid var(--color-border);
	border-radius: var(--radius-pill);
	padding: 11px 16px;
}
.filter-price__input:focus-within { border-color: var(--color-ink); }
.filter-price__sym { color: var(--color-ink-faint); font-size: 14px; }
.filter-price__input input {
	width: 100%;
	min-width: 0;
	border: none;
	background: none;
	font-family: inherit;
	font-size: 14px;
	color: var(--color-ink);
}
.filter-price__input input:focus { outline: none; }
/* Spinners crowd an already-narrow field. */
.filter-price__input input::-webkit-outer-spin-button,
.filter-price__input input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.filter-price__input input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

.filter-drawer__foot {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 20px var(--gutter) 28px;
	border-top: 1px solid var(--color-border);
	background: #fff;
}
.btn-outline,
.btn-solid {
	display: block;
	width: 100%;
	padding: 15px 24px;
	border-radius: var(--radius-pill);
	font-family: inherit;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-align: center;
	cursor: pointer;
	transition: background 0.2s ease, color 0.2s ease;
}
.btn-outline { background: none; border: 1.5px solid var(--color-ink); color: var(--color-ink); }
.btn-outline:hover { background: var(--color-bg-soft); }
.btn-solid { background: var(--color-ink); border: 1.5px solid var(--color-ink); color: #fff; }
.btn-solid:hover { background: var(--color-accent-dark); border-color: var(--color-accent-dark); }

/* --- Results ----------------------------------------------- */
.shop-results { padding: 40px var(--gutter) 80px; }
/* Fades the outgoing grid while the AJAX request is in flight instead of
   letting the page jump to an empty column. */
.shop-results[aria-busy="true"] .shop-results__grid { opacity: 0.35; pointer-events: none; }
.shop-results__grid { transition: opacity 0.2s ease; }
.shop-results ul.products {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--gutter);
	margin: 0;
	padding: 0;
	list-style: none;
}
@media (min-width: 981px) {
	/* Matches the carousel's tight column gap so a card is the same width
	   wherever it appears — see the note on .shop-layout above. */
	.shop-results ul.products { column-gap: 2px !important; }
}
.shop-results .shop-empty { text-align: center; padding-block: 72px; }
.shop-results__pagination .woocommerce-pagination { margin-top: 56px; }

@media (max-width: 980px) {
	.shop-results ul.products { grid-template-columns: repeat(3, 1fr) !important; }
}
@media (max-width: 720px) {
	.shop-results ul.products { grid-template-columns: repeat(2, 1fr) !important; }
	.shop-toolbar--bleed { flex-wrap: wrap; gap: 16px; }
	.shop-sort { width: 100%; margin-left: 0; }
	.shop-sort__toggle { width: 100%; }
	.shop-sort__menu { left: 0; right: 0; min-width: 0; }
	.shop-banner { min-height: 220px; }
}

/* =========================================================
   Contact Us page
   A quiet, mostly-white page: one full-bleed photograph, a single reading
   column left-aligned inside it, and a form drawn with nothing but baselines.
   The white ground is deliberate and local to this page -- the form's whole
   effect is rules on paper, and the site's pale blue would grey them out.
   ========================================================= */
/* Half the height it opened at (was 5 / 2). The band is a letterbox rather than
   a hero -- doubling the width against the same height is what halves it. */
.contact-band {
	aspect-ratio: 5 / 1;
	overflow: hidden;
	background: var(--color-bg-soft);
}
.contact-band img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.contact-page {
	background: #fff;
	padding: clamp(56px, 8vw, 104px) var(--gutter) 32px;
}
/* Narrower than --container-width on purpose. The form is two fields wide and
   nothing else on the page runs long, so the full container would leave the
   whole block stranded across a very wide measure. */
.contact-page__inner {
	max-width: 960px;
	margin: 0 auto;
}

.contact-intro {
	font-size: clamp(14px, 1.1vw, 16px);
	line-height: 1.6;
	color: var(--color-ink);
}
.contact-intro > :first-child { margin-top: 0; }
.contact-intro > :last-child { margin-bottom: 0; }
.contact-intro a { color: var(--color-accent); }

/* --- Opening hours --- */
.contact-hours { margin-top: clamp(40px, 5vw, 64px); }
.contact-hours__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(34px, 4vw, 52px);
	line-height: 1.1;
	color: var(--color-ink);
}
/* The one bold word on the page. It is a label for the rows under it, not a
   heading in the outline -- the section already has one. */
.contact-hours__label {
	margin: clamp(24px, 3vw, 40px) 0 0;
	font-size: 14px;
	font-weight: 700;
	color: var(--color-ink);
}
.contact-hours__list {
	list-style: none;
	margin: 14px 0 0;
	padding: 0;
	font-size: 14px;
	line-height: 1.6;
	color: var(--color-ink);
}

/* --- Form --- */
.contact-form {
	margin-top: clamp(44px, 5.5vw, 72px);
	display: flex;
	flex-direction: column;
	gap: clamp(28px, 3.2vw, 40px);
}
.contact-form__row {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: clamp(24px, 3vw, 44px);
}

/* Each field is a baseline with a label parked on it. The label is positioned
   rather than stacked above so it can sit in the field's resting state and rise
   out of it once there is something to read -- see the :placeholder-shown rules
   below, which are what make this work without any JavaScript. */
.contact-form__field {
	position: relative;
	padding-top: 22px;
}
.contact-form__field input,
.contact-form__field textarea {
	width: 100%;
	border: 0;
	border-bottom: 1px solid var(--color-ink);
	border-radius: 0;
	background: transparent;
	padding: 4px 0 10px;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.5;
	color: var(--color-ink);
	transition: border-color 0.2s ease;
}
.contact-form__field textarea {
	resize: vertical;
	min-height: 96px;
}
.contact-form__field input:focus,
.contact-form__field textarea:focus {
	outline: none;
	border-bottom-color: var(--color-accent);
}
.contact-form__field label {
	position: absolute;
	left: 0;
	top: 22px;
	font-size: 15px;
	line-height: 1.5;
	color: var(--color-ink-soft);
	pointer-events: none;
	transition: transform 0.2s ease, font-size 0.2s ease, color 0.2s ease;
	transform-origin: 0 0;
}
/* Empty and unfocused is the only state where the label sits on the line. Any
   other state lifts it clear so it cannot overlap what is being typed. */
.contact-form__field input:focus + label,
.contact-form__field textarea:focus + label,
.contact-form__field input:not(:placeholder-shown) + label,
.contact-form__field textarea:not(:placeholder-shown) + label {
	transform: translateY(-22px);
	font-size: 12px;
	color: var(--color-ink-faint);
}

/* --- Select --- */
/* Used on the Partnership page's "Inquiry Type" only; the Contact form has no
   select. A select is never empty, so there is no resting state for its label to
   sit in -- it is parked in the lifted position and stays there. That is also
   why the label comes first in the DOM here: nothing about it is driven by an
   adjacent-sibling rule. */
.contact-form__field--select { position: relative; }
.contact-form__field--select label {
	position: absolute;
	left: 0;
	top: 0;
	font-size: 12px;
	line-height: 1.5;
	color: var(--color-ink-faint);
	pointer-events: none;
}
.contact-form__field--select select {
	width: 100%;
	/* The native control brings its own chrome -- a rounded box on macOS, a
	   background and its own arrow elsewhere. All of it has to go before the
	   field will match the underlined inputs beside it. */
	appearance: none;
	-webkit-appearance: none;
	border: 0;
	border-bottom: 1px solid var(--color-ink);
	border-radius: 0;
	background: transparent;
	/* Right padding is the chevron's lane. */
	padding: 4px 28px 10px 0;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.5;
	color: var(--color-ink);
	cursor: pointer;
	transition: border-color 0.2s ease;
}
.contact-form__field--select select:focus {
	outline: none;
	border-bottom-color: var(--color-accent);
}
/* Ours, since appearance: none took the browser's away. */
.contact-form__select-mark {
	position: absolute;
	right: 0;
	bottom: 12px;
	width: 18px;
	height: 18px;
	color: var(--color-ink-soft);
	pointer-events: none;
}

/* --- Consent --- */
.contact-form__consent {
	display: flex;
	align-items: center;
	gap: 12px;
	font-size: 14px;
	color: var(--color-ink);
	cursor: pointer;
}
/* appearance:none rather than a hidden input plus a drawn box: the control keeps
   its own focus ring and keyboard behaviour, and only the paint changes. */
.contact-form__consent input {
	appearance: none;
	-webkit-appearance: none;
	flex: none;
	width: 20px;
	height: 20px;
	margin: 0;
	border: 1px solid var(--color-border);
	border-radius: 4px;
	background: #f1f1f1;
	cursor: pointer;
	display: grid;
	place-content: center;
	transition: background 0.15s ease, border-color 0.15s ease;
}
.contact-form__consent input::after {
	content: "";
	width: 10px;
	height: 6px;
	border-left: 2px solid #fff;
	border-bottom: 2px solid #fff;
	transform: rotate(-45deg) translate(1px, -1px);
	opacity: 0;
	transition: opacity 0.15s ease;
}
.contact-form__consent input:checked {
	background: var(--color-ink);
	border-color: var(--color-ink);
}
.contact-form__consent input:checked::after { opacity: 1; }
.contact-form__consent input:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 2px;
}

/* --- Submit --- */
/* --color-ink, not #000: it reads as the reference's black against white while
   staying the near-black the rest of the site is set in. */
.contact-form__submit {
	align-self: center;
	min-width: 128px;
	border: 0;
	border-radius: 0;
	padding: 17px 34px;
	background: var(--color-navy);
	color: #fff;
	font-family: var(--font-base);
	font-size: 14px;
	font-weight: 500;
	line-height: 1;
	cursor: pointer;
	transition: background 0.2s ease;
}
/* The lighter slate the navy was derived from, so the hover reads as the same
   colour lifting rather than a second one arriving. */
.contact-form__submit:hover { background: var(--color-accent); }
.contact-form__submit:focus-visible {
	outline: 2px solid var(--color-accent);
	outline-offset: 3px;
}

.contact-form__status {
	margin: 0;
	text-align: center;
	font-size: 13px;
	min-height: 18px;
}
.contact-form__status[data-state="error"] { color: #b0492f; }
.contact-form__status[data-state="success"] { color: var(--color-accent-dark); }

/* The trust band closes the page, so it needs its own air above it -- on the
   homepage it inherits that from the section it follows. Matched as a sibling
   rather than off a body class: page-contact.php is picked by the template
   hierarchy on the slug, which means WordPress still reports the body as
   page-template-default. */
.contact-page + .trust { padding-top: 32px; }
.contact-page .contact-form__status:empty { display: none; }

/* Visible to screen readers only. The Contact page's <h1> uses it -- the page
   opens on a photograph, but the document still needs its heading. */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

@media (max-width: 720px) {
	.contact-band { aspect-ratio: 3 / 1; }
	.contact-form__row { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Single journal article
   --------------------------------------------------------------------------
   Two measures, not one. The copy sits in a narrow column because a line of
   body text stops being readable somewhere past 75 characters, and the whole
   reason the old articles were unreadable is that they ran the full width of
   the window. The featured image is allowed to be wider than the copy -- a
   photograph has no measure to keep.
   ========================================================================== */
.article {
	--article-measure: 680px;
	--article-media: 820px;
	padding-top: clamp(32px, 4vw, 64px);
	padding-bottom: clamp(40px, 5vw, 80px);
}

/* Masthead: centred, and deliberately restrained. The h1 was at display size
   before, which is what made a three-line title swallow the top of the page. */
.article__head {
	max-width: var(--article-media);
	margin: 0 auto;
	padding: 0 var(--gutter);
	text-align: center;
}
.article__date {
	display: block;
	font-size: 13px;
	letter-spacing: 0.02em;
	color: var(--color-ink-soft);
}
.article__title {
	margin: 10px 0 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(26px, 2.9vw, 40px);
	line-height: 1.18;
	letter-spacing: -0.01em;
	color: var(--color-ink);
}

/* Share row. Squared outlines rather than the site's pill .btn -- these are
   utilities sitting beside the copy, not calls to action, and the pill would
   give them more weight than the article. */
.article__share {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 8px;
	margin-top: clamp(20px, 2.4vw, 30px);
}
.article__share-btn {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 8px 14px;
	border: 1px solid var(--color-border);
	background: transparent;
	font-family: var(--font-base);
	font-size: 13px;
	line-height: 1;
	color: var(--color-ink);
	text-decoration: none;
	cursor: pointer;
	transition: border-color 0.2s ease, color 0.2s ease;
}
.article__share-btn svg { width: 15px; height: 15px; flex: none; }
.article__share-btn:hover { border-color: var(--color-navy); color: var(--color-navy); }
.article__share-btn:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.article__media {
	max-width: var(--article-media);
	margin: clamp(28px, 3.4vw, 48px) auto 0;
	padding: 0 var(--gutter);
}
.article__media img { width: 100%; height: auto; display: block; }

/* --- Body ---------------------------------------------------------------
   Everything below is descendant-scoped because it styles what the editor
   produces, which carries no classes of its own. */
.article__body {
	max-width: var(--article-measure);
	margin: clamp(32px, 4vw, 56px) auto 0;
	padding: 0 var(--gutter);
	font-family: var(--font-base);
	font-size: 16px;
	line-height: 1.75;
	color: var(--color-ink);
}
/* The old pages had no paragraph rhythm at all -- every <p> sat directly on
   the next, which is what made the copy read as one block. */
.article__body > * { margin: 0 0 1.4em; }
.article__body > *:last-child { margin-bottom: 0; }
.article__body h2,
.article__body h3,
.article__body h4 {
	font-family: var(--font-hero);
	font-weight: 400;
	line-height: 1.25;
	letter-spacing: -0.01em;
	color: var(--color-ink);
	margin-top: 1.9em;
}
.article__body h2 { font-size: clamp(22px, 2.1vw, 28px); }
.article__body h3 { font-size: clamp(19px, 1.7vw, 23px); }
.article__body h4 { font-size: 18px; }
.article__body a {
	color: var(--color-navy);
	text-decoration: underline;
	text-underline-offset: 3px;
}
.article__body ul,
.article__body ol { padding-left: 1.25em; }
.article__body li { margin-bottom: 0.6em; }
.article__body img { max-width: 100%; height: auto; display: block; }
.article__body figcaption {
	margin-top: 10px;
	font-size: 13px;
	color: var(--color-ink-soft);
}

/* Pull quote. Nothing published uses one yet -- this is here so that the day a
   <blockquote> is added in the editor it lands as the reference's centred
   serif statement rather than a browser-default indented paragraph. The mark
   above it is generated, so the editor never has to type a quote character. */
.article__body blockquote {
	margin: clamp(36px, 4vw, 56px) 0;
	padding: 0;
	border: 0;
	text-align: center;
}
.article__body blockquote::before {
	content: '\201D';
	display: block;
	font-family: var(--font-hero);
	font-size: 44px;
	line-height: 0.6;
	color: var(--color-ink);
}
.article__body blockquote p {
	margin: 18px 0 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(22px, 2.3vw, 30px);
	line-height: 1.3;
	color: var(--color-ink);
}
.article__body blockquote cite {
	display: block;
	margin-top: 16px;
	font-family: var(--font-base);
	font-size: 13px;
	font-style: normal;
	color: var(--color-ink-soft);
}

.article__foot {
	max-width: var(--article-media);
	margin: clamp(36px, 4.5vw, 64px) auto 0;
	padding: 0 var(--gutter);
	text-align: center;
}
.article__meta {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 18px;
	margin: 0;
	font-size: 13px;
	color: var(--color-ink-soft);
}
.article__foot .article__share { margin-top: clamp(16px, 2vw, 24px); }

/* Three cards more often than four -- see the comment in single.php -- so the
   track is told how narrow a card may get rather than how many there are. */
.article-related__grid { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }

@media (max-width: 720px) {
	.article__body { font-size: 15.5px; }
	.article__share { gap: 6px; }
	.article__share-btn { padding: 8px 11px; }
}

/* "You may also like" at the foot of a product page. Was an editorial tile plus
   three cards; now a centred heading over a plain four-up row of the same
   product cards the shop grid uses. */
.product-related__title {
	margin: 0 0 clamp(28px, 3.5vw, 48px);
	text-align: center;
	font-family: var(--font-base);
	font-size: clamp(18px, 1.6vw, 21px);
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--color-ink);
}
/* Four across, overriding ul.products' default three -- and it has to be
   written as ul.products.product-related__grid, not the class on its own: the
   default is set on ul.products, which is one element + one class, so the bare
   class loses the specificity tie and the row silently kept three columns,
   wrapping the fourth product onto a second line. The two-column drop for
   narrow screens is already on ul.products and carries !important, so it still
   wins below its breakpoint. */
ul.products.product-related__grid { grid-template-columns: repeat(4, 1fr); }
/* The cards themselves get the bare treatment -- no tile, cut-out bottle on the
   page colour, title above brand, no add-to-cart -- by joining the shop grid in
   the :is() list further up, so the row cannot drift from the shop. */

/* ---------------------------------------------------------
   NEWSLETTER POPUP
   The timed signup modal (inc/newsletter-popup.php), built to the supplied
   reference: a photograph across the top of a narrow white panel, a two-face
   heading, a squared email field with a text SUBSCRIBE beside it, and a small
   underlined dismiss beneath. Mechanics follow the quick-view modal above --
   fixed layer, dimmed overlay, dialog fading up on .is-open -- so there is one
   modal pattern on the site rather than two.
   --------------------------------------------------------- */
.newsletter-popup {
	position: fixed;
	inset: 0;
	/* Above the cart drawer and menu panel, below nothing: while it is open it
	   is the only thing being asked of the visitor. */
	z-index: 300;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--gutter);
}
/* Same trap as the quick view: display:flex would outrank the hidden attribute
   and leave an invisible sheet over the page eating every click. */
.newsletter-popup[hidden] { display: none; }
.newsletter-popup__overlay {
	position: absolute;
	inset: 0;
	/* The reference dims hard -- the page behind reads as grey, not as a tinted
	   version of itself, which is what keeps the white panel bright. */
	background: rgba(19, 19, 19, 0.55);
	opacity: 0;
	transition: opacity 0.3s ease;
}
.newsletter-popup.is-open .newsletter-popup__overlay { opacity: 1; }
.newsletter-popup__dialog {
	position: relative;
	display: flex;
	flex-direction: column;
	width: min(460px, 100%);
	max-height: 90vh;
	overflow-y: auto;
	/* Square corners, as in the reference. */
	border-radius: 0;
	background: #fff;
	opacity: 0;
	transform: translateY(12px);
	transition: opacity 0.3s ease, transform 0.3s ease;
}
.newsletter-popup.is-open .newsletter-popup__dialog { opacity: 1; transform: none; }
/* A fixed frame, so the modal is the same shape whatever the shop uploads --
   a portrait photograph would otherwise push the form off a short screen. */
.newsletter-popup__media { flex: none; aspect-ratio: 3 / 2; overflow: hidden; }
/* Biased above centre rather than dead centre: a square or portrait upload
   loses its top and bottom to this frame, and in a photograph of people the
   faces sit in the upper half -- centring the crop is what cuts heads off. */
.newsletter-popup__media img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; display: block; }
.newsletter-popup__body { padding: 38px 36px 32px; text-align: center; }
/* The line above the heading, when there is one. Same treatment the rest of the
   site gives an eyebrow -- uppercase Plus Jakarta Sans, tracked out, stepped back
   in colour -- so it introduces the heading rather than competing with it. */
.newsletter-popup__eyebrow {
	font-family: var(--font-base);
	text-transform: uppercase;
	letter-spacing: 0.16em;
	font-size: 11px;
	font-weight: 700;
	color: var(--color-ink-soft);
	margin: 0 0 12px;
}
/* Two faces in one heading: the sans is the base, and the <em> in the copy is
   what switches to the italic serif. Both come from fonts the theme already
   loads -- Instrument Serif carries the italic (ital@0;1 in the Google Fonts
   request), so this costs no extra download. */
.newsletter-popup__title {
	font-family: var(--font-base);
	font-size: clamp(27px, 3.9vw, 37px);
	font-weight: 600;
	line-height: 1.12;
	letter-spacing: -0.01em;
	color: var(--color-ink);
	margin: 0 0 14px;
}
.newsletter-popup__title em,
.newsletter-popup__title i {
	font-family: var(--font-hero);
	/* Instrument Serif runs small next to Plus Jakarta Sans at the same size,
	   and it ships one weight, so the lift here is size, not boldness. */
	font-size: 1.12em;
	font-weight: 400;
	font-style: italic;
}
.newsletter-popup__text {
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-ink-soft);
	margin: 0 0 22px;
}
/* Squared and full-width, overriding the pill the homepage form uses: at this
   size the pill reads as a small control adrift in a large white panel. */
.newsletter-popup__form {
	border-radius: 2px;
	padding: 0 0 0 18px;
	gap: 0;
	min-height: 48px;
}
.newsletter-popup__form input { font-size: 15px; }
.newsletter-popup__form input::placeholder { color: var(--color-ink-soft); }
/* A text control, not a button shape -- the field's own border is the only box
   in the reference. */
.newsletter-popup__submit {
	flex: 0 0 auto;
	align-self: stretch;
	width: auto;
	height: auto;
	padding: 0 22px;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: var(--color-ink);
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	cursor: pointer;
	transition: opacity 0.2s ease;
}
.newsletter-popup__submit:hover { opacity: 0.55; background: transparent; }
.newsletter-popup__status { margin-top: 12px; }
.newsletter-popup__dismiss {
	display: inline-block;
	margin-top: 24px;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-ink);
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	text-decoration: underline;
	text-underline-offset: 5px;
	cursor: pointer;
	transition: opacity 0.2s ease;
}
.newsletter-popup__dismiss:hover { opacity: 0.55; }
@media (max-width: 600px) {
	/* The photograph is the first thing to give up its height on a small screen;
	   the form is what the modal is for. */
	.newsletter-popup__media { aspect-ratio: 2 / 1; }
	.newsletter-popup__body { padding: 32px 24px 28px; }
	.newsletter-popup__form { padding-left: 16px; min-height: 50px; }
	.newsletter-popup__submit { padding: 0 16px; }
}

/* =========================================================
   New Arrivals banner — photographic carousel (3 slides)
   Markup: inc/arrivals-banner.php · behaviour: main.js
   ========================================================= */

/* Full-bleed and self-contained: the slides are stacked absolutely, so the
   section needs its own height rather than taking it from whichever slide
   happens to be in front. */
.arrivals-banner {
	position: relative;
	width: 100%;
	min-height: clamp(380px, 44vw, 620px);
	background: var(--color-ink);
	overflow: hidden;
	isolation: isolate;
}

.arrivals-banner__slide {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	padding: clamp(48px, 6vw, 90px) clamp(28px, 7vw, 110px);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.7s ease, visibility 0.7s ease;
	z-index: 1;
}
.arrivals-banner__slide.is-active { opacity: 1; visibility: visible; z-index: 2; }
/* One slide, no carousel: nothing is stacked, so the section can simply take
   its height from the slide and stop needing the min-height above. */
.arrivals-banner:not(.arrivals-banner--carousel) .arrivals-banner__slide { position: relative; }

/* Where the copy sits in the frame. Set per slide in the Customizer -- the
   three positions alternating is what keeps the carousel from reading as one
   banner reloading. */
.arrivals-banner__slide--left { justify-content: flex-start; }
.arrivals-banner__slide--center { justify-content: center; }
.arrivals-banner__slide--right { justify-content: flex-end; }

/* No photograph yet: a plain blue band stands in, so copy can be written and
   reviewed before the pictures exist. The same band on all three -- the copy
   changing position and the dots are what show the carousel advancing. */
.arrivals-banner__slide--empty {
	background: linear-gradient(135deg, var(--color-navy) 0%, var(--color-accent) 60%, var(--color-accent-dark) 100%);
}

.arrivals-banner__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: -2;
}
/* The copy is white over a photograph nobody has vetted for contrast. The scrim
   is heaviest through the middle band, where the type actually sits, and lets
   the corners of the picture stay closer to their real exposure. */
.arrivals-banner__slide::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(0,0,0,0.28) 0%, rgba(0,0,0,0.42) 45%, rgba(0,0,0,0.32) 100%);
	z-index: -1;
}
/* The blue band is dark enough on its own; a scrim on top only muddies it. */
.arrivals-banner__slide--empty::after { background: none; }

.arrivals-banner__copy {
	position: relative;
	max-width: 780px;
	color: #fff;
	z-index: 2;
}
.arrivals-banner__slide--center .arrivals-banner__copy { text-align: center; }
.arrivals-banner__slide--left .arrivals-banner__copy { text-align: left; }
.arrivals-banner__slide--right .arrivals-banner__copy { text-align: right; }

.arrivals-banner__eyebrow {
	margin: 0 0 clamp(14px, 1.8vw, 22px);
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.24em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.88);
}
/* The homepage hero's face and sizing, so the two banners speak in the same
   voice -- Instrument Serif ships one weight, and it runs large because the
   face is narrow with a small cap height for its em. */
.arrivals-banner__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(40px, 7.4vw, 96px);
	line-height: 0.95;
	letter-spacing: -0.005em;
	text-transform: none;
	color: #fff;
}
/* <em> in the Customizer heading marks the words that lean, the same accent the
   hero puts on its final word. */
.arrivals-banner__title em,
.arrivals-banner__title i {
	font-style: italic;
}

/* --- Controls ---------------------------------------------- */
/* Dots only — no prev/next arrows. They sit above the slides, and render only
   on the carousel; a single-slide banner has no controls at all. */
.arrivals-banner__dots {
	position: absolute;
	left: 50%;
	bottom: clamp(18px, 2.6vw, 32px);
	transform: translateX(-50%);
	z-index: 4;
	display: flex;
	align-items: center;
	gap: 8px;
}
/* Same dot language as the homepage hero: the current one stretches into a bar
   rather than only changing colour, so it survives being looked at quickly. */
.arrivals-banner__dot {
	width: 8px;
	height: 8px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.45);
	cursor: pointer;
	transition: background 0.25s ease, width 0.25s ease, border-radius 0.25s ease;
}
.arrivals-banner__dot:hover { background: rgba(255, 255, 255, 0.75); }
.arrivals-banner__dot.is-active { background: #fff; width: 22px; border-radius: 4px; }

@media (max-width: 782px) {
	.arrivals-banner { min-height: clamp(320px, 62vw, 440px); }
	/* Left and right stop being placements at this width -- there is no room to
	   sit off to one side without the heading breaking into slivers, so all
	   three slides centre and the alternation resumes on wider screens. */
	.arrivals-banner__slide { justify-content: center; padding-left: var(--gutter); padding-right: var(--gutter); }
	.arrivals-banner__copy,
	.arrivals-banner__slide--left .arrivals-banner__copy,
	.arrivals-banner__slide--right .arrivals-banner__copy { text-align: center; }
	.arrivals-banner__eyebrow { letter-spacing: 0.18em; font-size: 11px; }
}

/* Honour the same request the script does: no crossfade, just a cut. */
@media (prefers-reduced-motion: reduce) {
	.arrivals-banner__slide { transition: none; }
}

/* =========================================================
   Category showcase — the For Him page.

   A photograph standing full height beside a heading and a horizontal row of
   products. The section also carries .best-sellers, which is what hands the
   cards the site's bare treatment; only the geometry is set here, and the
   .cat-showcase.best-sellers pairing outranks the Best Sellers card width
   without depending on which rule the stylesheet reaches last.
   ========================================================= */
.cat-showcase {
	display: grid;
	grid-template-columns: minmax(0, 40%) minmax(0, 1fr);
	align-items: stretch;
	min-height: clamp(580px, 58vw, 880px);
	background: var(--color-bg);
	/* .best-sellers carries a bottom padding for the homepage rows that follow
	   it. Here the section is the whole page and the footer comes straight
	   after, so that padding reads as a strip of stray page colour under the
	   photograph. The panel sets its own breathing room instead. */
	padding-bottom: 0;
}

/* --- the photograph --- */
.cat-showcase__editorial {
	position: relative;
	overflow: hidden;
}
/* No photograph uploaded yet: the same blue field the arrivals banner falls
   back to, so an unphotographed page still reads as designed rather than as
   broken. */
.cat-showcase__editorial--empty {
	background: linear-gradient(135deg, var(--color-navy) 0%, var(--color-accent) 60%, var(--color-accent-dark) 100%);
}
.cat-showcase__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
/* Darkens the left-hand edge only, which is where the caption now sits. It
   used to run up from the foot; with the words moved to the middle of the
   picture a bottom scrim would have shaded empty photograph and left the
   type to fend for itself. */
.cat-showcase__editorial::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg, rgba(0, 0, 0, 0.42) 0%, rgba(0, 0, 0, 0.16) 46%, rgba(0, 0, 0, 0) 72%);
	pointer-events: none;
}
.cat-showcase__editorial--empty::after { background: none; }
/* Centred down the picture and held to its left-hand edge. Sized in ch so it
   breaks over two or three lines into a block rather than running the width of
   the photograph as a single line. */
.cat-showcase__caption {
	position: absolute;
	left: clamp(20px, 3vw, 46px);
	top: 50%;
	transform: translateY(-50%);
	max-width: 11ch;
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(21px, 2.1vw, 34px);
	line-height: 1.2;
	color: #fff;
}
/* Same <em> convention as .signatures__title on the homepage. Instrument Serif
   ships a real italic (loaded as ital@0;1), so this is the drawn face, not a
   synthesised slant. */
.cat-showcase__caption em,
.cat-showcase__title em { font-style: italic; }

/* --- the product side --- */
.cat-showcase__panel {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: clamp(22px, 2.6vw, 38px);
	/* No padding on the right: the row is meant to run off the window edge, so a
	   part-cut card shows there is more to scroll to. */
	padding: clamp(40px, 5vw, 86px) 0 clamp(40px, 5vw, 86px) clamp(26px, 4vw, 68px);
	min-width: 0;
}
.cat-showcase__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 24px;
	/* The head is the one thing that does stop short of the edge, so the arrows
	   are not hard against the window. */
	padding-right: clamp(26px, 4vw, 68px);
}
/* Lets the copy shrink before the arrows do, which are a fixed size. */
.cat-showcase__copy { min-width: 0; }
/* The sibling link over the heading. Small caps rather than a button: the
   arrows opposite are the head's working control and this should not compete
   with them. inline-flex so the arrow sits on the text's own baseline row and
   the underline below runs under the label only. */
.cat-showcase__back {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 clamp(10px, 1.2vw, 16px);
	font-family: var(--font-base);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--color-ink-soft);
	text-decoration: none;
	transition: color 0.2s ease;
}
.cat-showcase__back svg {
	width: 14px;
	height: 14px;
	/* Slides toward the destination on hover. transform, not margin, so nothing
	   beside it reflows. */
	transition: transform 0.2s ease;
}
.cat-showcase__back span { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: transparent; transition: text-decoration-color 0.2s ease; }
.cat-showcase__back:hover,
.cat-showcase__back:focus-visible { color: var(--color-ink); }
.cat-showcase__back:hover span,
.cat-showcase__back:focus-visible span { text-decoration-color: currentColor; }
.cat-showcase__back:hover svg { transform: translateX(-3px); }
.cat-showcase__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(32px, 3.6vw, 54px);
	line-height: 1.12;
	color: var(--color-ink);
	/* Holds the heading short of the full panel width so a long one breaks
	   rather than running the whole measure.
	   20ch, not 14: "For Him Collection" and "For Her Collection" are the same
	   count but not the same width -- the italic m is wide enough that For Him
	   fell past 14ch and wrapped while For Her stayed on one line. Both clear
	   20ch, so the pair now reads the same. */
	max-width: 20ch;
}
.cat-showcase__text {
	margin: 10px 0 0;
	font-family: var(--font-base);
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
	max-width: 46ch;
}
.cat-showcase__nav { display: flex; gap: 10px; flex-shrink: 0; }
/* Outlined squares, not the bare glyphs Best Sellers uses: here they are the
   only control on the page, so they need to look like buttons. */
.cat-showcase__arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	padding: 0;
	border: 1px solid rgba(19, 19, 19, 0.18);
	background: none;
	color: var(--color-ink);
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.cat-showcase__arrow svg { width: 20px; height: 20px; }
.cat-showcase__arrow:hover,
.cat-showcase__arrow:focus-visible {
	background: var(--color-ink);
	border-color: var(--color-ink);
	color: #fff;
}

.cat-showcase__viewport {
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	/* Clipped cards otherwise still count toward document.scrollWidth. */
	contain: paint;
}
.cat-showcase__viewport::-webkit-scrollbar { display: none; }
.cat-showcase__track {
	display: flex;
	gap: clamp(14px, 1.6vw, 26px);
	margin: 0;
	/* Trailing padding only, so the last card can be scrolled clear of the
	   window edge. */
	padding: 0 clamp(26px, 4vw, 68px) 0 0;
	list-style: none;
	width: max-content;
}
.cat-showcase.best-sellers .product-card {
	flex: 0 0 auto;
	width: clamp(200px, 16.5vw, 268px);
	scroll-snap-align: start;
}

.cat-showcase__empty {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 20px;
	padding-right: clamp(26px, 4vw, 68px);
}
.cat-showcase__empty p {
	margin: 0;
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}

@media (max-width: 1100px) {
	/* The photograph's share used to narrow from 52% to 46% here, to hand the row
	   more room on a smaller window. At 40% it is already the narrower column, so
	   the 40/60 split now holds all the way down to where the layout stacks. */
	.cat-showcase__title { max-width: none; }
}
/* Stacked: the photograph becomes a band across the top and the row below it
   gets both edges back, since there is no longer a column beside it to run
   off. */
@media (max-width: 980px) {
	.cat-showcase {
		grid-template-columns: 1fr;
		min-height: 0;
	}
	/* Square rather than the old 4:3, and no ceiling on the height: stacked, the
	   photograph is the whole of what is on screen at the top of the page, and a
	   band shorter than it is wide reads as a strip rather than as the picture. */
	.cat-showcase__editorial {
		aspect-ratio: 1 / 1;
	}
	.cat-showcase__panel { padding: clamp(32px, 7vw, 54px) 0 clamp(40px, 8vw, 64px) var(--gutter); }
	.cat-showcase__head,
	.cat-showcase__empty { padding-right: var(--gutter); }
	.cat-showcase__track { padding-right: var(--gutter); }
}
@media (max-width: 560px) {
	.cat-showcase__editorial { aspect-ratio: 3 / 4; }
	.cat-showcase.best-sellers .product-card { width: 62vw; }
}

/* =========================================================
   Exclusive Offer page (page-exclusive-offer.php)
   =========================================================
   Navy, the same --color-navy as the announcement bar and the homepage promo
   strip, so arriving here from that strip reads as following one thread rather
   than landing on an unrelated page. */
.offer-hero {
	position: relative;
	overflow: hidden;
	background: var(--color-navy);
	color: #fff;
	padding: clamp(48px, 7vw, 88px) 0;
	text-align: center;
}
/* Absolute inset rather than a height percentage: this is a grid/flow child,
   and a percentage height on one collapses to zero. The brand banner and the
   rewards explainer both hit that and use this same pattern. */
.offer-hero__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}
.offer-hero__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* The photograph is behind type that has to stay readable at every crop, so it
   carries its own scrim rather than relying on the picture being dark enough. */
.offer-hero--has-image .offer-hero__media::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient( to bottom, rgba(28, 40, 54, 0.82), rgba(28, 40, 54, 0.72) );
}
.offer-hero__inner {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 18px;
}
.offer-hero__eyebrow {
	margin: 0;
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.72);
}
/* Same face and scale as .shop-banner__title, so the offer page's hero reads as
   the same kind of page header as "All Products" rather than a second style. */
.offer-hero__title {
	margin: 0;
	font-family: var(--font-hero);
	font-size: clamp(38px, 6vw, 72px);
	font-weight: 400;
	line-height: 1.05;
}
.offer-hero__lead {
	margin: 0;
	max-width: 56ch;
	font-size: clamp(15px, 1.5vw, 17px);
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.84);
}
.offer-hero__countdown { margin-top: 6px; }
.offer-hero__countdown[hidden] { display: none; }
.offer-hero__countdown-label {
	margin: 0 0 10px;
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.6);
}
.offer-hero__timer {
	display: flex;
	align-items: flex-start;
	justify-content: center;
	gap: 10px;
	margin: 0;
	/* Tabular figures so the seconds column keeps its width as it counts --
	   with proportional digits the whole row twitches once a second. */
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
}
.offer-hero__unit {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 4px;
	min-width: 62px;
}
.offer-hero__value {
	font-size: clamp(30px, 4vw, 46px);
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.02em;
}
.offer-hero__unit-label {
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
}
/* Aligned to the digits, not to the column, which includes the unit caption
   underneath -- centring on the whole unit drops the colon below the numbers. */
.offer-hero__sep {
	font-size: clamp(20px, 2.4vw, 30px);
	line-height: 1;
	opacity: 0.38;
	padding-top: 4px;
}
.offer-hero__code-row { margin: 6px 0 0; }
.offer-hero__code {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	padding: 12px 18px;
	border: 1px dashed rgba(255, 255, 255, 0.45);
	border-radius: var(--radius-sm);
	background: rgba(255, 255, 255, 0.07);
	color: #fff;
	font-family: var(--font-base);
	cursor: pointer;
	transition: background 0.2s ease, border-color 0.2s ease;
}
.offer-hero__code:hover {
	background: rgba(255, 255, 255, 0.14);
	border-color: rgba(255, 255, 255, 0.7);
}
.offer-hero__code-label {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.6);
}
.offer-hero__code-value {
	font-size: 17px;
	font-weight: 700;
	letter-spacing: 0.08em;
}
.offer-hero__code-hint {
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
}
.offer-hero__code.is-copied .offer-hero__code-hint { color: var(--color-sand); }

/* A quiet rule of fine print, not a feature band -- these are exclusions and
   thresholds, and giving them cards would make them look like benefits. */
.offer-terms {
	background: var(--color-bg-soft);
	border-bottom: 1px solid var(--color-border);
}
.offer-terms__list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px clamp(20px, 4vw, 48px);
	margin: 0;
	padding-top: 16px;
	padding-bottom: 16px;
	list-style: none;
}
.offer-terms__item {
	position: relative;
	font-size: 13px;
	line-height: 1.5;
	color: var(--color-ink-soft);
}
.offer-terms__item + .offer-terms__item::before {
	content: "";
	position: absolute;
	left: calc( clamp(20px, 4vw, 48px) / -2 );
	top: 50%;
	width: 3px;
	height: 3px;
	margin-top: -1.5px;
	border-radius: 50%;
	background: var(--color-ink-faint);
}
@media (max-width: 560px) {
	.offer-hero__unit { min-width: 52px; }
	.offer-terms__list { flex-direction: column; align-items: center; gap: 6px; }
	/* The dividers are for a single row; stacked, each one lands beside a line
	   instead of between two. */
	.offer-terms__item + .offer-terms__item::before { display: none; }
}

/* ---------------------------------------------------------------------------
   Makers page + the "View All" CTA beside the homepage "Meet the Makers"
   heading. The CTA repeats .stories__all's hairline treatment rather than
   inventing a second link style for the same job one section further down.
   --------------------------------------------------------------------------- */
.founders__title-row {
	display: flex;
	align-items: baseline;
	gap: 18px;
	margin-bottom: 8px;
}
.founders__title-row .founders__title { margin-bottom: 0; }
.founders__all {
	position: relative;
	padding-left: 19px;
	font-size: 14px;
	color: var(--color-ink);
	text-decoration: none;
	white-space: nowrap;
}
.founders__all::before {
	content: '';
	position: absolute;
	left: 0;
	top: 50%;
	width: 1px;
	height: 1.15em;
	transform: translateY(-50%);
	background: rgba(19, 19, 19, 0.25);
}
.founders__all:hover { text-decoration: underline; text-underline-offset: 4px; }

/* No measure cap: the intro is one sentence and is meant to sit on a single
   line at desktop width. It still wraps on its own once the viewport is too
   narrow to hold it. */
.makers__head { margin-bottom: clamp(28px, 3.4vw, 48px); }
.makers__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(34px, 4.4vw, 56px);
	line-height: 1.1;
	color: var(--color-ink);
}
.makers__intro { margin-top: 14px; font-size: 15px; line-height: 1.7; color: var(--color-ink-soft); }
.makers__intro p:last-child { margin-bottom: 0; }
.makers__empty { font-size: 15px; color: var(--color-ink-soft); }

.makers__grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: clamp(24px, 3vw, 44px) clamp(20px, 2.4vw, 34px);
}
.maker-card__media {
	position: relative;
	aspect-ratio: 3 / 4;
	overflow: hidden;
	background: var(--color-bg-soft);
	margin-bottom: 16px;
}
.maker-card__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}
.maker-card__name {
	margin: 0;
	font-family: var(--font-display);
	font-size: 19px;
	line-height: 1.3;
	color: var(--color-ink);
}
.maker-card__role {
	margin: 4px 0 0;
	font-size: 13px;
	letter-spacing: 0.04em;
	color: var(--color-ink-soft);
}
.maker-card__quote {
	margin: 12px 0 0;
	padding: 0;
	border: 0;
	font-size: 15px;
	line-height: 1.65;
	color: var(--color-ink-soft);
}
/* The quotes differ in length, so left in flow the "Shop the brand" links land
   at three different heights across the row. The card is a full-height column
   and the link takes the leftover space above it, which puts every link on the
   same line whatever the quote does. align-items keeps the underline the width
   of its own text rather than stretching it across the column. */
.maker-card {
	display: flex;
	flex-direction: column;
	height: 100%;
}
.maker-card__body {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
}
.maker-card__link {
	margin-top: auto;
	padding-top: 14px;
	font-size: 14px;
	color: var(--color-ink);
	text-decoration: none;
	border-bottom: 1px solid rgba(19, 19, 19, 0.3);
	padding-bottom: 2px;
}
.maker-card__link:hover { border-bottom-color: var(--color-ink); }

@media (max-width: 980px) {
	.makers__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
	.makers__grid { grid-template-columns: 1fr; }
	/* The heading and the CTA stop sharing a baseline once the heading wraps. */
	.founders__title-row { flex-wrap: wrap; gap: 8px 14px; }
}

/* ---------------------------------------------------------------------------
   Narrow phones: the header's three blocks genuinely do not fit side by side.
   At 375px they measure 36 (hamburger) + 131 (logo) + 136 (icons) + 48 (grid
   gaps) + 40 (gutters) = 391px against a 375px screen, which is why the search
   icon used to sit on top of the wordmark. Tightening the gaps and the logo is
   what makes the row fit; the grid columns above are what stop any future
   overflow from turning back into a silent overlap.
   --------------------------------------------------------------------------- */
@media (max-width: 430px) {
	.site-header__inner { gap: 10px; }
	.header-icons { gap: 8px; }
	.custom-logo { height: 24px; }
	/* Search moves into the slide-in menu here -- see satueen_menu_panel().
	   Dropping it frees the ~44px that let the logo stay truly centred while
	   the remaining icons keep their 36px tap targets. */
	.header-icons .search-toggle { display: none; }
}

/* Search inside the mobile drawer. It is the only search below 430px, where
   the header icon is hidden. It used to sit in .menu-panel, which was the wrong
   drawer -- that panel's toggle is itself hidden below 1400px, so on a phone it
   could not be opened and the search inside it was unreachable. */
.mobile-nav__search {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 28px;
	padding: 10px 14px;
	border: 1px solid var(--color-border);
	border-radius: 999px;
	background: #fff;
}
.mobile-nav__search input[type="search"] {
	flex: 1;
	min-width: 0;
	border: 0;
	background: none;
	padding: 0;
	font-size: 15px;
	color: var(--color-ink);
}
.mobile-nav__search input[type="search"]:focus { outline: none; }
.mobile-nav__search button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	flex: none;
	border: 0;
	background: none;
	padding: 0;
	cursor: pointer;
	color: var(--color-ink);
}
.mobile-nav__search svg { width: 18px; height: 18px; }

/* =========================================================
   My Account — login / register / lost password
   ========================================================= */
/* The forms themselves carry .contact-form, so the fields, the consent
   checkbox and the submit are the Contact page's, not restyled copies of them.
   What is left here is only the page's own frame: how wide the column is, where
   the heading sits, and how the Remember-me row lines up beside the button. */
.account-forms {
	max-width: 460px;
	/* Left-aligned, not centred: the page's own "My account" heading sits at the
	   container's left edge, and a centred form left the two visibly unrelated.
	   The Contact page shares one left edge between its heading and its form. */
	margin: 0 auto 0 0;
	padding-bottom: clamp(56px, 7vw, 96px);
}
/* Two columns only if registration is ever switched on -- it is off today, and
   a lone login form centred at 460px reads far better than one stranded in the
   left half of a split. */
.account-forms--split {
	max-width: var(--container-width);
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
	gap: clamp(40px, 5vw, 72px);
	align-items: start;
}
.account-form__title {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	text-transform: none;
	letter-spacing: 0;
	font-size: clamp(24px, 2.2vw, 30px);
	line-height: 1.2;
	color: var(--color-ink);
}
/* .contact-form's own top margin is sized for a page heading above it; here the
   form follows a small section title, so it is pulled in. */
.account-form .contact-form { margin-top: clamp(24px, 3vw, 34px); }
.account-form__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 16px 24px;
	margin: 0;
}
/* .contact-form__submit centres itself on the Contact page, where it is the only
   thing in its row. Here it shares the row with Remember me. */
.account-form__actions .contact-form__submit { align-self: auto; }
.account-form__note {
	margin: 0;
	font-size: 14px;
	line-height: 1.6;
	color: var(--color-ink-soft);
}
.account-form__link {
	margin: 0;
	font-size: 14px;
}
.account-form__link a { color: var(--color-ink-soft); }
.account-form__link a:hover { color: var(--color-ink); }
/* WooCommerce marks required fields with a red asterisk of its own; the label
   here is already muted and rises out of the way, so the star only needs to
   match it rather than shout. */
.account-form .required {
	color: inherit;
	text-decoration: none;
	border: 0;
}

/* The theme's generic WooCommerce-page form styles (.page-content
   input.input-text, .page-content .button) are a class more specific than
   .contact-form's own rules, so without these the account fields kept their
   boxed white treatment and the pill button while wearing the right markup.
   These re-assert the Contact page's look at a specificity that wins, rather
   than raising .contact-form globally -- the Contact and Partnership pages must
   not move. */
.account-form .contact-form__field input.input-text,
.account-form .contact-form__field input[type="password"] {
	border: 0;
	border-bottom: 1px solid var(--color-ink);
	border-radius: 0;
	background: transparent;
	padding: 4px 0 10px;
	font-size: 15px;
	line-height: 1.5;
	box-shadow: none;
}
.account-form .contact-form__field input.input-text:focus,
.account-form .contact-form__field input[type="password"]:focus {
	outline: none;
	border-bottom-color: var(--color-accent);
	box-shadow: none;
}
.account-form .contact-form__submit,
.account-form .contact-form__submit.button {
	border-radius: 0;
	padding: 17px 34px;
	background: var(--color-navy);
	color: #fff;
	font-size: 14px;
	font-weight: 500;
	line-height: 1;
}
.account-form .contact-form__submit:hover,
.account-form .contact-form__submit.button:hover { background: var(--color-accent); }

/* ---------------------------------------------------------------------------
   Exclusive Offer — running bundle deals
   One card per participating house, rendered by
   satueen_bundle_promo_deals_band(). Auto-fit rather than a fixed column
   count: the number of houses running a deal is data and changes without
   anyone touching this file.
--------------------------------------------------------------------------- */
.offer-deals {
	padding: clamp(36px, 4.4vw, 60px) 0 0;
}
.offer-deals__title {
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(24px, 2.4vw, 32px);
	margin: 0 0 6px;
}
.offer-deals__lead {
	margin: 0 0 clamp(20px, 2.2vw, 28px);
	font-size: 14px;
	color: var(--color-accent);
}
.offer-deals__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	/* auto-FILL, not auto-fit: with a single house running, auto-fit collapses
	   the empty tracks and stretches that one card across the full container,
	   which reads as a banner rather than one deal among several. */
	grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr));
	gap: 16px;
}
.offer-deals__item {
	border: 1px solid rgba(19, 19, 19, 0.12);
	border-radius: var(--radius-md);
	padding: 22px 24px;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 6px;
	/* A grid item's default min-width:auto re-imposes a min-content floor and
	   would overflow the track on a long house name. */
	min-width: 0;
}
.offer-deals__house {
	margin: 0;
	font-size: 11px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--color-accent);
}
.offer-deals__offer {
	margin: 0;
	font-family: var(--font-hero);
	font-weight: 400;
	font-size: clamp(19px, 1.6vw, 23px);
	line-height: 1.25;
	color: var(--color-green);
}
.offer-deals__link {
	margin-top: 8px;
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	border-bottom: 1px solid currentColor;
	padding-bottom: 2px;
}

/* ---------------------------------------------------------------------------
   Homepage intro (inc/intro.php). Timeline, from first paint:
     0.0s  dark cover, the logomark draws its outline and fills
     1.9s  cover lifts over 0.9s; the hero video is already running beneath
     2.3s  eyebrow, headline, buttons rise in one after another
     3.1s  announcement bar and header fade in
   All of it hangs off html.is-intro, which main.js takes away again once the
   last step has finished, so nothing here lingers on the page afterwards.
   --------------------------------------------------------------------------- */
.site-intro { display: none; }
html.is-intro .site-intro {
	display: flex;
	align-items: center;
	justify-content: center;
	position: fixed;
	inset: 0;
	z-index: 10000;
	background: #161616;
	animation: intro-lift 0.9s ease 1.9s forwards;
}
.site-intro__mark { width: 46px; height: auto; overflow: visible; }
.site-intro__mark path {
	stroke: #fff;
	stroke-width: 0.9;
	stroke-dasharray: 1;
	stroke-dashoffset: 1;
	fill: #fff;
	fill-opacity: 0;
	animation: intro-draw 1.5s ease-in-out 0.1s forwards, intro-fill 0.5s ease 1.3s forwards;
}
.site-intro__count {
	position: absolute;
	right: 28px;
	bottom: 22px;
	font-family: var(--font-base);
	font-size: 12px;
	letter-spacing: 0.06em;
	font-variant-numeric: tabular-nums;
	color: rgba(255, 255, 255, 0.5);
}
html.is-intro body.home :is(.hero__eyebrow, .hero__heading, .hero__actions) {
	animation: intro-rise 1s cubic-bezier(0.2, 0.7, 0.2, 1) 2.3s both;
}
html.is-intro body.home .hero__heading { animation-delay: 2.45s; }
html.is-intro body.home .hero__actions { animation-delay: 2.75s; }
html.is-intro body.home :is(.announcement-bar, .site-header) {
	animation: intro-fade 0.8s ease 3.1s both;
}
/* While the announcement bar is still faded out, what shows through its strip
   is the page behind it -- white, which read as a pale band across the top of
   the black hero. Black for the length of the intro; the sheet below the hero
   paints its own white, so nothing else changes. */
html.is-intro body.home { background: #000; }
@keyframes intro-lift { to { opacity: 0; visibility: hidden; } }
@keyframes intro-draw { to { stroke-dashoffset: 0; } }
@keyframes intro-fill { to { fill-opacity: 1; } }
/* Rises from below with its lower part masked, so it reads as coming up from
   behind an edge. The mask ends wider than the box so the script eyebrow's
   flourishes and the italic overhang are not shaved. */
@keyframes intro-rise {
	from { opacity: 0; transform: translateY(55%); clip-path: inset(-30% -30% 100% -30%); }
	to { opacity: 1; transform: none; clip-path: inset(-30% -30% -30% -30%); }
}
@keyframes intro-fade { from { opacity: 0; } to { opacity: 1; } }

/* Brands directory — reference: centered names over a changing dark photograph. */
.brands-directory {
	overflow: clip;
	position: relative;
	isolation: isolate;
	background: #000;
	color: #fff;
	padding-bottom: clamp(48px, 6vw, 96px);
}
.brands-directory__backdrop {
	position: sticky;
	top: calc(var(--announcement-h) + var(--header-h));
	height: calc(100svh - var(--announcement-h) - var(--header-h));
	margin-bottom: calc(-100svh + var(--announcement-h) + var(--header-h));
	pointer-events: none;
	z-index: -1;
	overflow: hidden;
}
.brands-directory__photo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	opacity: 0;
	filter: brightness(.28);
	transition: opacity 450ms ease;
}
.brands-directory__photo.is-visible { opacity: 1; }
.brands-directory__intro {
	position: relative;
	display: grid;
	grid-template-columns: minmax(0, 22%) minmax(0, 1fr);
	gap: clamp(24px, 5vw, 72px);
	padding-top: clamp(56px, 7vw, 104px);
	padding-bottom: clamp(56px, 7vw, 104px);
}
.brands-directory__eyebrow {
	margin: 8px 0 0;
	font-size: 12px;
	letter-spacing: .06em;
	text-transform: uppercase;
}
.brands-directory__lead {
	margin: 0;
	max-width: 850px;
	font-family: var(--font-display);
	font-size: clamp(18px, 2.1vw, 30px);
	font-weight: 400;
	line-height: 1.2;
}
.brands-directory__list { position: relative; }
.brands-directory__link {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: clamp(88px, 7.4vw, 112px);
	padding: 18px 24px;
	border-top: 1px solid rgba(255,255,255,.12);
	color: rgba(255,255,255,.5);
	font-family: var(--font-display);
	font-size: 36px;
	font-weight: 400;
	line-height: 1.12;
	text-align: center;
	text-decoration: none;
	transition: color 200ms ease, border-color 200ms ease;
}
.brands-directory__link:last-child { border-bottom: 1px solid rgba(255,255,255,.12); }
.brands-directory__link:hover,
.brands-directory__link:focus-visible,
.brands-directory__link.is-active {
	color: #fff;
	border-color: rgba(255,255,255,.65);
}
.brands-directory__link:focus-visible { outline: 2px solid #fff; outline-offset: -6px; }
@media (max-width: 600px) {
	.brands-directory__intro { grid-template-columns: 1fr; gap: 24px; }
	.brands-directory__link { min-height: 88px; font-size: 36px; }
}
@media (prefers-reduced-motion: reduce) {
	.brands-directory__photo, .brands-directory__link { transition: none; }
}

/* MASA-style hover: the name rolls upward through a clipped line. */
.brands-directory__name {
	position: relative;
	display: inline-block;
	overflow: hidden;
}
.brands-directory__name-primary,
.brands-directory__name-copy {
	display: block;
	transition: transform 450ms cubic-bezier(.76, 0, .24, 1);
}
.brands-directory__name-copy {
	position: absolute;
	inset: 0;
	transform: translateY(110%);
}
.brands-directory__link:hover .brands-directory__name-primary,
.brands-directory__link:focus-visible .brands-directory__name-primary {
	transform: translateY(-110%);
}
.brands-directory__link:hover .brands-directory__name-copy,
.brands-directory__link:focus-visible .brands-directory__name-copy {
	transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
	.brands-directory__name-primary,
	.brands-directory__name-copy { transition: none; }
	.brands-directory__link:hover .brands-directory__name-primary,
	.brands-directory__link:focus-visible .brands-directory__name-primary { transform: none; }
	.brands-directory__name-copy { display: none; }
}

/* New Arrival — a pinned image opening, covered by the rising white catalog. */
.arrival-experience { position: relative; isolation: isolate; }
.arrival-intro {
	position: sticky;
	top: calc(var(--announcement-h) + var(--header-h));
	height: calc((100svh - var(--announcement-h) - var(--header-h)) / 2);
	min-height: 0;
	overflow: hidden;
	background: #131313;
}
.arrival-intro .arrivals-banner { height: 100%; min-height: 100%; }
.arrival-intro .arrivals-banner__slide::after {
	background: linear-gradient(180deg, rgba(0,0,0,.04) 40%, rgba(0,0,0,.4) 100%);
}
.arrival-intro .arrivals-banner__img {
	transform: scale(var(--arrival-scale, 1));
}
.arrival-intro__copy {
	position: absolute;
	inset: auto var(--gutter) 28px;
	z-index: 3;
	color: #fff;
	transform: translateY(var(--arrival-rise, 0px));
	opacity: var(--arrival-opacity, 1);
}
.arrival-intro__title {
	font-family: var(--font-display);
	font-size: clamp(64px, 8vw, 144px);
	font-weight: 400;
	line-height: .95;
	margin: 0;
}
.arrival-intro__scroll {
	display: inline-flex;
	gap: 14px;
	align-items: center;
	margin-top: 24px;
	font-size: 11px;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: #fff;
	text-decoration: none;
}
.arrival-intro__scroll:focus-visible { outline: 2px solid #fff; outline-offset: 6px; }
.arrival-catalog {
	position: relative;
	z-index: 4;
	background: #fff;
	min-height: 100vh;
	scroll-margin-top: calc(var(--announcement-h) + var(--header-h));
}
@media (max-width: 600px) {
	.arrival-intro { min-height: 0; }
	.arrival-intro__title { font-size: clamp(68px, 17vw, 100px); }
	.arrival-intro__copy { bottom: 32px; }
}
@media (prefers-reduced-motion: reduce) {
	.arrival-intro { position: relative; top: auto; }
	.arrival-intro__copy { transform: none; opacity: 1; }
	.arrival-intro .arrivals-banner__img { transform: none; }
}

/* Fill the opening with its single selected photograph. */
.arrival-intro .arrivals-banner:not(.arrivals-banner--carousel) .arrivals-banner__slide { position: absolute; }

/* Opt-in hover audio, kept quiet and easy to switch off. */
.brands-directory__sound {
	margin-top: 18px;
	padding: 6px 0;
	color: rgba(255,255,255,.7);
	background: transparent;
	border: 0;
	border-bottom: 1px solid rgba(255,255,255,.3);
	font-family: var(--font-base);
	font-size: 11px;
	cursor: pointer;
}
.brands-directory__sound:hover { color: #fff; }
.brands-directory__sound:focus-visible { outline: 2px solid #fff; outline-offset: 4px; }
.brands-directory__sound[hidden] { display: none; }

/* Matching sound control on the white Olfactive Families page. */
.family-sound { color: var(--color-ink-soft); border-bottom-color: var(--color-border); }
.family-sound:hover { color: var(--color-ink); }
.family-sound:focus-visible { outline-color: var(--color-ink); }

/* New Arrival: image-filled type enlarges behind the rising white catalog. */
.arrival-intro--masked { background: #e4e5e6; }
.arrival-intro--masked .arrivals-banner__img { filter: grayscale(1); }
.arrival-intro--masked .arrivals-banner__slide::after { background: rgba(229,230,232,.82); }
.arrival-intro--masked .arrival-intro__copy { inset: 0; display: flex; align-items: center; justify-content: center; transform: none; }
.arrival-intro--masked .arrival-intro__title {
 font-size: clamp(64px, 8vw, 144px); line-height: 1; letter-spacing: -.02em; white-space: nowrap;
 color: #55595e; background-image: linear-gradient(120deg, #51555b 0%, #858a90 24%, #585d63 46%, #a3a7ac 62%, #60656b 80%, #454a50 100%); background-size: cover; background-position: center;
 transform: translateY(var(--arrival-title-rise, 0px)) scale(var(--arrival-title-scale, 1)); transform-origin: center;
 will-change: transform;
}
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
 .arrival-intro--masked .arrival-intro__title { background-clip: text; -webkit-background-clip: text; color: transparent; }
}
.arrival-intro--masked .arrival-intro__scroll { position: absolute; left: var(--gutter); bottom: 28px; color: #302b2a; opacity: var(--arrival-opacity, 1); }
.arrival-intro--masked .arrival-intro__scroll:focus-visible { outline-color: #302b2a; }
@media (max-width: 600px) { .arrival-intro--masked .arrival-intro__title { font-size: clamp(60px, 16vw, 96px); } }
@media (prefers-reduced-motion: reduce) { .arrival-intro--masked .arrival-intro__title { transform: none; will-change: auto; } }

/* All Products blends into the white catalog. */
.arrival-intro--white { background: #fff; }
.arrival-intro--white .arrivals-banner { display: none; }

/* Compact All Products opening. */
.arrival-intro--white { height: clamp(160px, 24svh, 240px); }
.arrival-intro--white .arrival-intro__title { font-size: clamp(44px, 4.5vw, 72px); }

/* Keep compact headings sharp while the catalog covers the pinned opening. */
.arrival-intro--white .arrival-intro__title { transform: none; will-change: auto; }

/* Preserve category descriptions within the compact catalog opening. */
.arrival-intro--white .arrival-intro__copy { flex-direction: column; gap: 6px; padding: 24px var(--gutter); }
.arrival-intro__description { margin: 0; max-width: 680px; text-align: center; color: var(--color-ink-soft); font-size: 15px; line-height: 1.6; }

/* Silver shimmer runs automatically across compact catalog titles. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
 .arrival-intro--white .arrival-intro__title {
  background-image: linear-gradient(110deg, #343a40 0%, #343a40 30%, #90979f 42%, #e0e4e8 50%, #90979f 58%, #343a40 70%, #343a40 100%);
  background-size: 250% 100%;
  animation: arrival-silver-shimmer 3s ease-in-out infinite alternate;
 }
}
@keyframes arrival-silver-shimmer {
 from { background-position: 0% 50%; }
 to { background-position: 100% 50%; }
}
@media (prefers-reduced-motion: reduce) {
 .arrival-intro--white .arrival-intro__title { animation: none; background-position: 50% 50%; }
}

/* A little more breathing room on Shop All, keeping its title size. */
body.post-type-archive-product .arrival-intro--white { height: clamp(190px, 28svh, 280px); }

/* Match the five category openings to Shop All height. */
body.tax-product_cat .arrival-intro--white { height: clamp(190px, 28svh, 280px); }

/* White cart drawer on every page. */
.cart-drawer { --color-bg: #fff; background: #fff; }

/* Quick View image panels match the white product pages. */
.quick-view__media { background: #fff; }

/* White surfaces throughout the remaining pages and interface. */
:root {
 --color-bg: #fff;
 --color-bg-soft: #fff;
 --color-blue: #fff;
 --color-blush: #fff;
 --color-accent-soft: #fff;
 --color-border: #d9d9d9;
}
:is(.cart-drawer__checkout, .welcome-offer__btn, .newsletter__submit,
 .contact-form__submit, .account-form .contact-form__submit,
 .rewards-intro__actions .btn, .product-card__add, .trust__btn):is(*, :hover, :focus-visible) {
 background: #fff; color: var(--color-ink); border: 1px solid var(--color-border);
}
:is(.cart-count, .cart-drawer__count, .product-card__badge--bundle, .shop-filter-count) {
 background: #fff; color: var(--color-ink); border: 1px solid var(--color-border);
}
.cart-drawer .free-shipping-bar__fill,
.cart-drawer .free-shipping-bar__icon { background: #fff; color: var(--color-ink); border: 1px solid var(--color-border); }
.btn--primary:hover, .btn--ghost:hover, .btn-solid:hover,
form.cart button.single_add_to_cart_button:hover,
.page-content .button:hover, #reviews .form-submit input[type="submit"]:hover {
 background: #fff; color: var(--color-ink); border-color: var(--color-border);
}
.filter-toggle__badge { background: #fff; color: var(--color-ink); border: 1px solid var(--color-border); }
.hero__cta:hover, .hero__cta--ghost:hover,
.cat-tile:hover .cat-tile__btn, .cat-tile:focus-visible .cat-tile__btn {
 background: #fff; color: var(--color-ink); border-color: var(--color-border);
}
form.cart button.single_add_to_cart_button:hover::before { background-color: currentColor; }

/* Keep the single-currency flag and code centered in the expanded menu. */
.header-currency--mobile.header-currency--static { display: flex; align-items: center; gap: 8px; }

/* Currency options stack beneath the toggle inside the navigation panel. */
details.header-currency--mobile { display: block; }

/* WooCommerce Blocks changes destination without reloading the PHP offer. */
body.woocommerce-checkout:has(#shipping-country option[value="MY"]:checked) .free-shipping-bar { display: none; }

/* Center the product composition in the wide promotional band. */
.payday-band__media img { object-position: center; }

/* Exclusive Offer follows the compact white catalog title treatment. */
.offer-hero {
 background: #fff;
 color: var(--color-ink);
 padding: clamp(32px, 4vw, 48px) 0;
}
.offer-hero__media { display: none; }
.offer-hero__inner { gap: 12px; }
.offer-hero__title { font-size: clamp(44px, 4.5vw, 72px); color: #343a40; }
.offer-hero__eyebrow, .offer-hero__lead,
.offer-hero__countdown-label, .offer-hero__unit-label,
.offer-hero__code-label, .offer-hero__code-hint { color: var(--color-ink-soft); }
.offer-hero__code { background: #fff; color: var(--color-ink); border-color: var(--color-border); }
.offer-hero__code:hover { background: #f5f5f5; border-color: #90979f; }
.offer-hero__code.is-copied .offer-hero__code-hint { color: var(--color-ink); }
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
 .offer-hero__title {
  background-image: linear-gradient(110deg, #343a40 0%, #343a40 30%, #90979f 42%, #e0e4e8 50%, #90979f 58%, #343a40 70%, #343a40 100%);
  background-size: 250% 100%;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: arrival-silver-shimmer 3s ease-in-out infinite alternate;
 }
}
@media (prefers-reduced-motion: reduce) {
 .offer-hero__title { animation: none; background-position: 50% 50%; }
}

/* Promotion photography and one clear offer, with room to breathe. */
.offer-editorial { padding-top: 16px; padding-bottom: 56px; }
.offer-editorial__row { display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: clamp(28px, 5vw, 72px); }
.offer-editorial__row + .offer-editorial__row { margin-top: 48px; }
.offer-editorial__row--text { grid-template-columns: 1fr; }
.offer-editorial__image { display: block; overflow: hidden; aspect-ratio: 4 / 3; background: #fff; }
.offer-editorial__image img { display: block; width: 100%; height: 100%; object-fit: cover; }
.offer-editorial__copy { padding: 16px 0; }
.offer-editorial__brand { margin: 0 0 18px; font-size: 11px; letter-spacing: .14em; color: var(--color-ink-soft); }
.offer-editorial__title { font-family: var(--font-hero); font-size: clamp(30px, 3vw, 44px); font-weight: 400; line-height: 1.12; margin: 0 0 18px; max-width: 19ch; }
.offer-editorial__price { margin: 0 0 10px; font-size: 17px; color: var(--color-ink); }
.offer-editorial__note { margin: 0 0 28px; font-size: 13px; line-height: 1.6; color: var(--color-ink-soft); }
.offer-editorial__button { display: inline-flex; align-items: center; gap: 24px; padding: 13px 20px; border: 1px solid var(--color-ink); background: #fff; color: var(--color-ink); font-size: 13px; text-decoration: none; }
.offer-editorial__button:hover { background: #f5f5f5; }
@media (max-width: 680px) {
 .offer-editorial__row { grid-template-columns: 1fr; gap: 20px; }
 .offer-editorial__copy { padding: 0; }
 .offer-editorial { padding-bottom: 36px; }
}

/* Full product compositions and quieter promotion headings. */
.offer-editorial__image { aspect-ratio: 1; }
.offer-editorial__title { font-size: clamp(28px, 2.7vw, 38px); }
.offer-editorial__row--gift .offer-editorial__price { margin-bottom: 28px; line-height: 1.6; }

/* AMTHRA gift choice, shared by drawer, cart and checkout. */
.amthra-gift-picker { padding: 18px; margin: 16px 0 24px; border: 1px solid var(--color-border); background: #fff; color: var(--color-ink); }
.amthra-gift-picker p { margin: 0 0 10px; font-size: 13px; line-height: 1.5; }
.amthra-gift-picker p:last-child { margin-bottom: 0; }
.amthra-gift-picker .amthra-gift-picker__title { font-family: var(--font-hero); font-size: 24px; font-weight: 400; }
.amthra-gift-picker label { display: block; font-size: 12px; margin-bottom: 6px; }
.amthra-gift-picker select { width: 100%; background: #fff; border: 1px solid var(--color-border); padding: 10px; color: var(--color-ink); margin-bottom: 10px; }
.amthra-gift-picker button { background: #fff; color: var(--color-ink); padding: 10px 16px; border: 1px solid var(--color-ink); cursor: pointer; font-size: 13px; }
main .amthra-gift-slot { max-width: 620px; }

/* Soft grey clouds travel in different directions behind stationary copy. */
.welcome-offer { isolation: isolate; background: #fafafa; }
.welcome-offer::before,
.welcome-offer::after {
 content: '';
 position: absolute;
 inset: -65%;
 pointer-events: none;
 z-index: 0;
 background: radial-gradient(ellipse at 35% 40%, #c9c9c9 0%, #dfdfdf 18%, transparent 48%),
             radial-gradient(ellipse at 75% 70%, #ffffff 0%, #ffffff 12%, transparent 40%);
 animation: welcome-cloud-flow 13s linear infinite;
 will-change: transform;
}
.welcome-offer::after {
 opacity: .65;
 background: radial-gradient(ellipse at 60% 35%, #dedede 0%, transparent 42%);
 animation: welcome-cloud-flow-secondary 19s linear infinite;
}
@keyframes welcome-cloud-flow {
 0%, 100% { transform: translate(-12%, -5%) rotate(0deg); }
 20% { transform: translate(10%, 9%) rotate(8deg); }
 45% { transform: translate(15%, -10%) rotate(-5deg); }
 70% { transform: translate(-8%, 12%) rotate(6deg); }
 85% { transform: translate(-16%, 3%) rotate(-4deg); }
}
@keyframes welcome-cloud-flow-secondary {
 0%, 100% { transform: translate(12%, 8%) rotate(0deg); }
 25% { transform: translate(-13%, -8%) rotate(-10deg); }
 50% { transform: translate(5%, 14%) rotate(6deg); }
 75% { transform: translate(15%, -12%) rotate(-6deg); }
}
@media (prefers-reduced-motion: reduce) {
 .welcome-offer::before, .welcome-offer::after { animation: none; will-change: auto; }
}


/* Reveal the flowers and upper negative space in AMTHRA's portrait banner. */
.term-amthra .brand-story-hero__img { object-position: center 40%; }

/* Fully sold-out products stay visible but clearly unavailable. */
.product-card--soldout .product-card__media img { filter: opacity(.45); }
.product-card .product-card__quick--soldout,
.product-card:hover .product-card__quick--soldout {
 display: flex; opacity: 1; transform: none; cursor: default;
 background: #ededed; color: #555; pointer-events: none;
}

.product-card__promotion { order: 4; margin-top: 3px; font-size: 12px; line-height: 1.5; color: var(--color-ink-soft); }
.product-card__add { order: 5; }

/* Account forms: stable labels also work with WooCommerce password wrappers. */
.woocommerce .account-forms { max-width: 960px; padding-bottom: 48px; }
.woocommerce .account-forms--split { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 64px; }
.woocommerce .account-form { min-width: 0; }
.woocommerce .account-form .account-form__title { font-family: var(--font-hero); font-size: 30px; font-weight: 400; margin: 0; }
.woocommerce .account-form form.contact-form { display: flex; flex-direction: column; gap: 24px; border: 0; padding: 0; margin: 24px 0 0; }
.woocommerce .account-form .contact-form__field { display: flex; flex-direction: column; padding: 0; margin: 0; }
.woocommerce .account-form .contact-form__field label { position: static; order: -1; transform: none; font-size: 13px; line-height: 1.5; margin: 0 0 8px; color: var(--color-ink-soft); pointer-events: auto; }
.woocommerce .account-form .contact-form__field input.input-text { padding: 9px 0 11px; background: #fff; border-bottom-color: #999; }
.woocommerce .account-form .contact-form__field input:autofill { box-shadow: 0 0 0 1000px #fff inset; -webkit-text-fill-color: var(--color-ink); }
.woocommerce .account-form .contact-form__field .password-input { width: 100%; }
.woocommerce .account-form .account-form__actions { margin: 0; padding: 0; }
.woocommerce .account-form .account-form__actions .contact-form__submit { margin: 0; background: #151515; color: #fff; border: 1px solid #151515; border-radius: 0; padding: 16px 28px; }
.woocommerce .account-form .account-form__link { margin: 0; }
@media (max-width: 700px) { .woocommerce .account-forms--split { grid-template-columns: minmax(0, 1fr); gap: 48px; } }

/* Login and registration have separate views with a clear switch link. */
.woocommerce .account-forms.account-forms--single { display: block; max-width: 460px; }
.woocommerce .account-form__switch { margin: 28px 0 0; font-size: 14px; color: var(--color-ink-soft); }
.woocommerce .account-form__switch a { color: var(--color-ink); text-decoration: underline; text-underline-offset: 3px; }

/* Signed-in account: navigation and content have separate, responsive columns. */
.woocommerce .account-dashboard { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 48px; align-items: start; margin: 0 0 56px; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation { float: none; width: auto; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation ul { list-style: none; padding: 0; margin: 0; border: 1px solid #e5e5e5; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation li { margin: 0; padding: 0; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation li + li { border-top: 1px solid #eeeeee; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation a { display: block; padding: 14px 18px; color: #555; font-size: 14px; line-height: 1.4; text-decoration: none; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation a:hover { background: #f7f7f7; color: #151515; }
.woocommerce .account-dashboard .woocommerce-MyAccount-navigation .is-active a { background: #151515; color: #fff; }
.woocommerce .account-dashboard .woocommerce-MyAccount-content { float: none; width: auto; min-width: 0; padding: 28px 32px; border: 1px solid #e5e5e5; background: #fff; }
.woocommerce .account-dashboard .woocommerce-MyAccount-content > p { margin: 0 0 20px; line-height: 1.8; }
.woocommerce .account-dashboard .woocommerce-MyAccount-content > p:last-child { margin-bottom: 0; }
.woocommerce-account .woocommerce .woocommerce-info,
.woocommerce-account .woocommerce .woocommerce-message { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; padding: 18px 20px; margin: 0 0 24px; border: 1px solid #e5e5e5; background: #f7f7f7; color: #555; line-height: 1.7; }
.woocommerce-account .woocommerce .woocommerce-info::before,
.woocommerce-account .woocommerce .woocommerce-message::before { display: none; }
.woocommerce-account .woocommerce .woocommerce-info .button,
.woocommerce-account .woocommerce .woocommerce-message .button { float: none; flex: 0 0 auto; order: 1; margin: 0; padding: 12px 20px; border-radius: 0; background: #151515; color: #fff; text-decoration: none; line-height: 1.4; }
@media (max-width: 700px) {
    .woocommerce .account-dashboard { grid-template-columns: minmax(0, 1fr); gap: 24px; }
    .woocommerce .account-dashboard .woocommerce-MyAccount-navigation ul { display: flex; flex-wrap: wrap; }
    .woocommerce .account-dashboard .woocommerce-MyAccount-navigation li + li { border-top: 0; }
    .woocommerce .account-dashboard .woocommerce-MyAccount-navigation a { padding: 12px 14px; }
    .woocommerce .account-dashboard .woocommerce-MyAccount-content { padding: 22px 20px; }
}

/* Google's provider button appears only after OAuth setup is verified/enabled. */
.account-social { margin-top: 28px; }
.account-social__separator { display: flex; align-items: center; gap: 16px; margin: 0 0 18px; color: #777; font-size: 11px; letter-spacing: .12em; text-transform: uppercase; }
.account-social__separator::before, .account-social__separator::after { content: ''; flex: 1; height: 1px; background: #e5e5e5; }
.account-social .nsl-container { padding: 0 !important; }
.account-social .nsl-container-buttons { width: 100%; }

/* Quick View: one live price at the top and compact buying information. */
.quick-view .woocommerce-variation-price,
.quick-view .woocommerce-variation-description { display: none; }
.quick-view .bundle-note,
.quick-view .bundle-note__offer,
.quick-view .bundle-note__terms,
.amthra-product-promotion {
 font-size: 12px;
 line-height: 1.55;
}
.amthra-product-promotion { margin: 12px 0 18px; color: var(--color-ink-soft); }
.quick-view .quantity { flex-shrink: 0; }

/* Bundle product notes share AMTHRA's compact promotion typography. */
.bundle-note,
.quick-view .bundle-note {
 margin: 12px 0 18px;
 padding: 0;
 border: 0;
 font-size: 12px;
 line-height: 1.55;
 color: var(--color-ink-soft);
}
.bundle-note .bundle-note__offer,
.bundle-note .bundle-note__terms {
 display: inline;
 font-size: inherit;
 font-weight: 400;
 line-height: inherit;
 color: inherit;
 letter-spacing: normal;
 margin: 0;
}

/* Use uppercase consistently for brand-name labels and navigation links. */
.site-header a[href*="/brand/"],
.mobile-nav a[href*="/brand/"],
.menu-panel a[href*="/brand/"],
.brands-directory__name,
.product-card__brand,
.product-brand,
.quick-view__brand,
.offer-editorial__brand,
.brand-story-hero__name {
 text-transform: uppercase;
}

/* Decorative loyalty media: lightweight poster until desktop playback is ready. */
.rewards-band { position: relative; }
.rewards-band__video { position: absolute; inset: 0; }
.rewards-band__video[hidden] { display: none; }

/* Preserve makers' paragraph breaks and allow complete longer stories. */
.founders__quote, .maker-card__quote { white-space: pre-line; }
@media (min-width: 781px) {
  .founders__slide { height: auto; min-height: clamp(380px, 34vw, 520px); }
}
.founders__media img[alt^="M Athaya Zhafran"], .maker-card__img[alt^="M Athaya Zhafran"] { object-position: center top; filter: grayscale(1); }

/* Compact phone quick view: keep the buying controls close to the product. */
.quick-view .single_add_to_cart_button:disabled { opacity: .5; cursor: not-allowed; }
@media (max-width: 720px) {
  .quick-view__dialog { max-height: 92vh; max-height: 92dvh; }
  .quick-view__media { aspect-ratio: auto; height: clamp(130px, 22vh, 190px); height: clamp(130px, 22dvh, 190px); padding: 8px 42px; }
  .quick-view__info { overflow-y: visible; padding: 16px 20px 20px; flex: 0 0 auto; }
  .quick-view__info form.cart { margin-top: 14px; }
  .quick-view .variations--swatches { gap: 12px; }
  .quick-view .variation-swatch-group__label { margin-bottom: 6px; }
  .quick-view .variation-swatch { padding: 9px 14px; min-height: 44px; }
  .quick-view .single_add_to_cart_button { min-height: 44px; }
  .quick-view .woocommerce-variation-add-to-cart { gap: 10px; }
  .quick-view__full { margin-top: 14px; }
}

/* Fill the directory backdrop while keeping the bottles in the visible crop. */
.brands-directory__photo[src*="/6LUSTRA-BeforeSunrise"] { object-fit: cover; object-position: center 72%; }
.brands-directory__photo[src*="/studio-sable.jpg"] { object-position: center 80%; }

/* WHSPR: bring the low-set bottle into the full-width directory crop. */
.brands-directory__photo[src*="/whspr-scaled.jpg"] { object-position: center 70%; }

/* Lift Athaya slightly to align the portrait with the neighbouring maker. */
.founders__media img[alt^="M Athaya Zhafran"] { transform: scale(1.06); transform-origin: center bottom; }

/* Preserve the reference portrait height independently of smaller quote text. */
@media (min-width: 781px) {
  .founders__slide { min-height: clamp(520px, 39.6vw, 650px); }
}

/* Circle account guidance before checkout; wraps naturally on small screens. */
.circle-checkout-notice {
 margin: 0 0 24px;
 padding: clamp(18px, 3vw, 24px);
 border: 1px solid var(--color-border);
 border-radius: var(--radius-sm);
 background: var(--color-accent-soft);
 color: var(--color-ink);
}
.circle-checkout-notice h2 { margin: 0 0 8px; font-family: var(--font-display); font-weight: 400; font-size: 28px; line-height: 1.2; }
.circle-checkout-notice p { margin: 0; font-size: 14px; line-height: 1.7; }
.circle-checkout-notice__links { display: flex; flex-wrap: wrap; gap: 12px 24px; margin-top: 14px; }
.circle-checkout-notice__links a { font-size: 14px; font-weight: 600; text-decoration: underline; text-underline-offset: 4px; padding: 8px 0; }
.circle-checkout-notice__links a:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }

/* Compact gift confirmation and consistent unlinked cart thumbnails. */
.amthra-gift-picker { padding: 12px 16px; margin: 12px 0 16px; }
.amthra-gift-picker__confirmation { display: flex; align-items: flex-start; gap: 8px; }
.amthra-gift-picker__tick { color: #28734b; font-weight: 600; flex: 0 0 auto; }
.cart-drawer .amthra-gift-picker { margin: 12px 24px 16px; }
.cart-drawer__item-name { overflow-wrap: anywhere; }
.cart-drawer__gift-quantity { font-size: 12px; color: var(--color-ink-soft); }

/* Contact support and explicit enquiry-only consent. */
.contact-support { margin-top: 24px; font-size: 14px; line-height: 1.7; }
.contact-support a, .contact-form__consent a { color: var(--color-accent); text-decoration: underline; text-underline-offset: 4px; }
.contact-support a { display: inline-block; padding: 8px 0; }
.contact-support a:focus-visible, .contact-form__consent a:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 4px; }
#satueen-contact-form .contact-form__consent { align-items: flex-start; line-height: 1.6; }
#satueen-contact-form .contact-form__consent input { margin-top: 2px; }
#satueen-contact-form .contact-form__privacy-note { margin: -12px 0 0; font-size: 13px; line-height: 1.6; color: var(--color-ink-soft); }

/* Keep lazy story photos in their designed frame before they finish loading. */
.brand-story__photo { contain-intrinsic-size: none !important; }

/* ÊTRE founder portrait matches the grayscale Meet the Makers collection. */
.founders__media img[alt^="Tiara & Lygia"], .maker-card__img[alt^="Tiara & Lygia"] { filter: grayscale(1); }

/* Updated Studio Sable/ÊTRE portraits match the makers collection. */
.founders__media img[alt^="Christian"], .maker-card__img[alt^="Christian"],
.founders__media img[alt^="Lygia"], .maker-card__img[alt^="Lygia"] { filter: grayscale(1); }

/* Mobile rewards banner: 30% shorter, lower crop keeps the face outside the frame. */
@media(max-width:768px){
 .rewards-band{height:clamp(168px,28.7vh,352.8px)}
 .rewards-band__poster,.rewards-band__video{object-position:center 65%}
}
