/*
 * Plinth base styles.
 *
 * Cascade layers: reset < base < utilities.
 * Block styles (blocks/{slug}/style.css) are intentionally UNLAYERED so they
 * always win over these layers without specificity fights.
 *
 * Design tokens come from theme.json as --wp--preset--* custom properties —
 * never hardcode colors, font sizes or spacing here.
 */

@layer reset, base, utilities;

/* ---------------------------------------------------------------- reset -- */
@layer reset {
	*,
	*::before,
	*::after {
		box-sizing: border-box;
	}

	* {
		margin: 0;
	}

	html {
		-webkit-text-size-adjust: none;
		text-size-adjust: none;
	}

	body {
		min-height: 100svh;
		-webkit-font-smoothing: antialiased;
	}

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

	input,
	button,
	textarea,
	select {
		font: inherit;
		color: inherit;
	}

	h1,
	h2,
	h3,
	h4,
	h5,
	h6 {
		overflow-wrap: break-word;
		text-wrap: balance;
	}

	p {
		overflow-wrap: break-word;
	}
}

/* ----------------------------------------------------------------- base -- */
@layer base {
	:focus-visible {
		outline: 2px solid var(--wp--preset--color--primary);
		outline-offset: 2px;
	}

	.skip-link:focus {
		position: fixed;
		inset-block-start: var(--wp--preset--spacing--sm);
		inset-inline-start: var(--wp--preset--spacing--sm);
		z-index: 100;
		width: auto;
		height: auto;
		padding: var(--wp--preset--spacing--xs) var(--wp--preset--spacing--sm);
		clip-path: none;
		background: var(--wp--preset--color--secondary);
		color: var(--wp--preset--color--base);
		text-decoration: none;
	}

	/*
	 * Buttons. The primary style (magenta pill) — colours, radius, padding
	 * and type — comes from theme.json (styles.elements.button), which
	 * WordPress prints for .wp-element-button on the front end and in the
	 * editor. Links styled as buttons use <a class="wp-element-button">.
	 * Only the behaviour lives here; variants are unlayered, further down.
	 */
	.wp-element-button {
		display: inline-flex;
		align-items: center;
		gap: var(--wp--preset--spacing--xs);
		cursor: pointer;
		transition: background-color var(--wp--custom--transition--base), color var(--wp--custom--transition--base);
	}

	/*
	 * Block widths (inc/widths.php). Every plinth/* block root carries one
	 * has-width-* class; its __inner container reads two properties:
	 *
	 *   max-width: var(--block-max-width);
	 *   margin-inline: auto;
	 *   padding-inline: var(--block-gutter);
	 *
	 * Widths are content widths — the gutter is added on top, so Standard
	 * shows 1280px of content plus side padding. Each class declares both
	 * properties itself so nested blocks never inherit a parent's width.
	 * :root carries Standard as the default for site chrome.
	 */
	:root,
	.has-width-standard {
		--block-gutter: var(--wp--preset--spacing--gutter);
		--block-max-width: calc(var(--wp--custom--width--standard) + 2 * var(--block-gutter));
	}

	.has-width-narrow {
		--block-gutter: var(--wp--preset--spacing--gutter);
		--block-max-width: calc(var(--wp--custom--width--narrow) + 2 * var(--block-gutter));
	}

	.has-width-wide {
		--block-gutter: var(--wp--preset--spacing--gutter);
		--block-max-width: calc(var(--wp--custom--width--wide) + 2 * var(--block-gutter));
	}

	.has-width-full {
		--block-gutter: 0px;
		--block-max-width: none;
	}

	/*
	 * Content flow.
	 *
	 * Pages are composed of full-bleed Plinth block <section>s that own their
	 * inner width and gutter. Loose core blocks (the editor whitelist) typed
	 * between them are constrained to the theme.json content size instead.
	 * The .is-root-container variant keeps parity inside the editor canvas.
	 */
	:where(.entry-content, .is-root-container) >
	:where(p, h1, h2, h3, h4, h5, h6, ul, ol, .wp-block-image, blockquote, .plinth-embed) {
		max-width: calc(var(--wp--style--global--content-size) + 2 * var(--wp--preset--spacing--gutter));
		margin-inline: auto;
		padding-inline: var(--wp--preset--spacing--gutter);
	}

	/* Flow spacing between loose core blocks only. Plinth block sections sit
	   flush against each other and their neighbours — each one's own Padding
	   control sets the space. */
	:where(.entry-content) > :where(:not([class*="wp-block-plinth-"])) + :where(:not([class*="wp-block-plinth-"])) {
		margin-block-start: var(--wp--preset--spacing--md);
	}

	/* Where a Plinth section meets loose core blocks (e.g. the legal pages'
	   text under the Hero), give the text room on that side. */
	:where(.entry-content) > [class*="wp-block-plinth-"] + :where(:not([class*="wp-block-plinth-"])) {
		margin-block-start: var(--wp--preset--spacing--lg);
	}

	:where(.entry-content) > :where(:not([class*="wp-block-plinth-"])):has(+ [class*="wp-block-plinth-"]) {
		margin-block-end: var(--wp--preset--spacing--lg);
	}

	/* ---- Simple templates (404) ----
	 * Listings (Posts page, archives, search) use assets/css/feed.css. */

	.archive-main {
		max-width: calc(var(--wp--style--global--content-size) + 2 * var(--wp--preset--spacing--gutter));
		margin-inline: auto;
		padding-block: var(--wp--preset--spacing--lg);
		padding-inline: var(--wp--preset--spacing--gutter);
	}

	.archive-header {
		margin-block-end: var(--wp--preset--spacing--lg);
	}

	.entry-header {
		max-width: calc(var(--wp--style--global--content-size) + 2 * var(--wp--preset--spacing--gutter));
		margin-inline: auto;
		padding-block: var(--wp--preset--spacing--lg) 0;
		padding-inline: var(--wp--preset--spacing--gutter);
	}

	.entry-content {
		padding-block: var(--wp--preset--spacing--md) var(--wp--preset--spacing--lg);
	}

	/* A page that starts or ends on a full-bleed Plinth section meets the
	   header / footer flush; the section's own Padding control sets the space. */
	.entry-content:has(> [class*="wp-block-plinth-"]:first-child) {
		padding-block-start: 0;
	}

	.entry-content:has(> [class*="wp-block-plinth-"]:last-child) {
		padding-block-end: 0;
	}

	/* ---- Motion ----
	 * --plinth-motion scales scroll-linked movement (parallax). Block CSS
	 * can't use @media, so it multiplies distances by this instead: 1 by
	 * default, 0 for reduced motion. */

	:root {
		--plinth-motion: 1;
	}

	@media (prefers-reduced-motion: reduce) {
		:root {
			--plinth-motion: 0;
		}

		*,
		*::before,
		*::after {
			animation-duration: 0.01ms !important;
			animation-delay: 0s !important;
			animation-iteration-count: 1 !important;
			transition-duration: 0.01ms !important;
			scroll-behavior: auto !important;
		}
	}
}

/* --------------------------------------------------- button variants -- */
/*
 * Site-wide button styles (see BLOCKS.md §8 "Buttons"):
 *
 *   <a class="wp-element-button">               primary — magenta pill (theme.json)
 *   <a class="wp-element-button is-secondary">  secondary — Deep Forest pill
 *   <a class="wp-element-button is-light">      light — Mint pill, for dark/photo backgrounds
 *   <a class="wp-element-button is-decal">      decal — text + arrow-circle, no pill
 *
 * Render them with plinth_button() (inc/buttons.php), which adds the
 * decal's icon markup.
 *
 * UNLAYERED on purpose, so variants beat theme.json's unlayered button rules.
 */
/* Primary (magenta): no colour change on hover, the button just grows
   slightly. theme.json owns the colours. */
.wp-element-button:not(.is-secondary, .is-light, .is-decal) {
	transition: scale 0.25s cubic-bezier(0.22, 1, 0.36, 1);

	&:hover {
		scale: 1.04;
	}
}

.wp-element-button.is-secondary {
	background: var(--wp--preset--color--secondary);
	color: var(--wp--preset--color--base);

	&:hover {
		background: var(--wp--preset--color--primary);
		color: var(--wp--preset--color--base);
	}
}

.wp-element-button.is-light {
	background: var(--wp--preset--color--tint);
	color: var(--wp--preset--color--secondary);

	&:hover {
		background: var(--wp--preset--color--base);
		color: var(--wp--preset--color--secondary);
	}

	&:focus-visible {
		outline-color: var(--wp--preset--color--tint);
	}
}

/*
 * Button row: keeps a group of buttons side by side on one line, even on a
 * small phone, by scaling their text, padding and gap down with the width of
 * the nearest container (every block root is one). Full size from ~26rem of
 * container width; about 80% at 20rem (a 320px phone). Very long labels can
 * still run out of room, so keep them short.
 *
 *   <div class="plinth-button-row"><a class="wp-element-button">…</a>…</div>
 */
.plinth-button-row {
	display: flex;
	flex-wrap: nowrap;
	align-items: center;
	gap: clamp(var(--wp--preset--spacing--sm), 5cqi, var(--wp--preset--spacing--md));

	& > .wp-element-button {
		flex: none;
		white-space: nowrap;
		font-size: clamp(calc(var(--wp--preset--font-size--sm) * 0.84), 4cqi, var(--wp--preset--font-size--md));
	}

	& > .wp-element-button:not(.is-decal) {
		padding-inline: clamp(var(--wp--preset--spacing--sm), 5cqi, var(--wp--preset--spacing--md));
	}
}

/* ----------------------------------------------------- site header -- */
/*
 * UNLAYERED, like the footer, so the nav's link colours beat theme.json's
 * global link style. Viewport media queries are fine here — this is site
 * chrome, not block CSS. Markup: header.php.
 *
 * A floating pill (.site-header__bar) of light frosted glass, inside an
 * invisible full-width <header> that only positions it. The header is
 * always out of flow, so pinning it on scroll never shifts the page: <main>
 * makes room for it — except on pages that open with a Hero
 * (body.has-hero-header, inc/header.php), where the pill drops its glass
 * and sits with white text on top of the photo, and the hero pads its own
 * copy instead (via --site-header-offset).
 *
 * The pill is a little wider than the content column (by its own start
 * padding), so the logo lines up with the page content beneath it.
 *
 * States, set by assets/js/main.js:
 *   [data-pinned]     scrolling back up, away from the top: fixed, glass
 *   [data-hidden]     pinned, but slid out of view while scrolling down
 *   [data-menu-open]  below 70rem: the pill has expanded into the menu
 *
 * Widths: from 81rem the full bar; between 70rem and 81rem the phone number
 * text hides (the icon stays); below 70rem a menu button takes over.
 */
:root {
	--site-header-bar: 4.5rem;
	--site-header-gap: var(--wp--preset--spacing--xs);
	--site-header-height: calc(var(--site-header-bar) + 2 * var(--site-header-gap));
}

.site-header ~ main {
	margin-block-start: var(--site-header-height);
}

.has-hero-header {
	& .site-header ~ main {
		margin-block-start: 0;
	}

	& .entry-content > :first-child {
		--site-header-offset: var(--site-header-height);
	}
}

.site-header {
	/* Dropdown panels' glass: near-white, more opaque than the pill as
	   there's more to read (the desktop panel, the mobile drill-down). */
	--mega-glass: color-mix(in srgb, var(--wp--preset--color--base) 94%, transparent);
	--bar-pad: calc(var(--wp--preset--spacing--md) + var(--wp--preset--spacing--xxs));
	/* Gap between the pill's edge and the round toggle / CTA it holds. */
	--bar-inset: var(--wp--preset--spacing--xs);

	/* Pill's distance from the screen edges. */
	--bar-side: max(var(--wp--preset--spacing--xs), var(--wp--preset--spacing--gutter) - var(--bar-pad));

	/*
	 * iOS 26 Safari: when a fixed element near the top is wider than about
	 * 85–90% of the screen, Safari treats it as a toolbar and paints the
	 * status-bar area a solid colour, hiding the page scrolling beneath.
	 * (Tested in the iOS 26.4 simulator: 85% wide is ignored, 90% triggers
	 * it; pointer-events and distance from the top make no difference.)
	 *
	 * So the header's own box is only 80% wide (inset 10% each side) and
	 * the pill overflows it to the full width, centred by flexbox: Safari
	 * measures the box, the visitor sees the pill. 125cqi = the full width
	 * the 80% box stands for. The box also starts at the pill rather than
	 * the top edge (the admin bar pushes it down by its own height).
	 */
	position: absolute;
	inset-block-start: calc(var(--wp-admin--admin-bar--height, 0px) + var(--site-header-gap));
	inset-inline: 10%;
	z-index: 100;
	display: flex;
	justify-content: center;
	container-type: inline-size;
	/* Only the pill catches clicks, not the strip of page around it. */
	pointer-events: none;
	transition: translate var(--wp--custom--transition--base);

	&[data-pinned] {
		position: fixed;
	}

	/* Slid fully out of view: past the top edge by the pill's pinned
	   shadow too (shadow--md reaches ~20px below it), so no sliver of shadow
	   is left showing. Keyboard focus inside brings it back. */
	&[data-hidden]:not(:focus-within) {
		translate: 0 calc(-100% - var(--wp-admin--admin-bar--height, 0px) - var(--site-header-gap) - var(--wp--preset--spacing--md));
	}

	& :focus-visible {
		outline-color: currentcolor;
	}
}

.site-header__bar {
	--glass: color-mix(in srgb, var(--wp--preset--color--base) 72%, transparent);
	--glass-blur: blur(6px) saturate(1.6);
	--glass-edge: inset 0 0 0 1px color-mix(in srgb, var(--wp--preset--color--secondary) 8%, transparent);
	/* Hover/current capsule behind links and round buttons, from the text colour. */
	--hover-tint: color-mix(in srgb, currentcolor 10%, transparent);

	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--md);
	flex: none;
	inline-size: calc(125cqi - 2 * var(--bar-side));
	max-width: calc(var(--wp--custom--width--standard) + 2 * var(--bar-pad));
	block-size: var(--site-header-bar);
	padding-inline: var(--bar-pad) var(--bar-inset);
	border-radius: calc(var(--site-header-bar) / 2);
	color: var(--wp--preset--color--secondary);
	pointer-events: auto;
	transition: color var(--wp--custom--transition--base);
	/* Stacking context for the glass layer below the content. */
	position: relative;
	z-index: 0;

	/*
	 * The glass is a layer behind the content, not the bar's own background:
	 * an element with backdrop-filter becomes a "backdrop root", and a
	 * frosted element inside it (the mega menu panel) would then blur only
	 * the bar instead of the page behind it.
	 */
	&::before {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		border-radius: inherit;
		background: var(--glass);
		-webkit-backdrop-filter: var(--glass-blur);
		backdrop-filter: var(--glass-blur);
		box-shadow: var(--glass-edge);
		pointer-events: none;
		transition:
			background-color var(--wp--custom--transition--base),
			box-shadow var(--wp--custom--transition--base),
			-webkit-backdrop-filter var(--wp--custom--transition--base),
			backdrop-filter var(--wp--custom--transition--base);
	}

	.site-header[data-pinned] &::before {
		box-shadow: var(--glass-edge), var(--wp--custom--shadow--md);
	}
}

/* No blur support: near-solid instead, so text stays readable over photos. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
	.site-header__bar {
		--glass: color-mix(in srgb, var(--wp--preset--color--base) 96%, transparent);
	}
}

/* At the top of a Hero page: no pill at all, white text over the photo
   (unless the small-screen menu is open). A dropdown panel opening leaves
   it as it is. */
.has-hero-header .site-header:not([data-pinned], [data-menu-open]) .site-header__bar {
	--glass: transparent;
	--glass-blur: blur(0) saturate(1);
	--glass-edge: inset 0 0 0 1px transparent;
	--hover-tint: color-mix(in srgb, currentcolor 20%, transparent);

	color: var(--wp--preset--color--base);
}

/* Magenta on the glass pill only; over the photo the icon goes white too. */
.has-hero-header .site-header:not([data-pinned], [data-menu-open]) .site-header__phone-icon {
	color: inherit;
}

/* Over a light colour Hero (Mint, Linen, White): Deep Forest text, and the
   phone icon stays magenta as on the glass pill. */
.has-hero-header--light .site-header:not([data-pinned], [data-menu-open]) {
	& .site-header__bar {
		color: var(--wp--preset--color--secondary);
	}

	& .site-header__phone-icon {
		color: var(--wp--preset--color--accent);
	}
}

.site-header__title {
	flex: none;
	color: inherit;
	text-decoration: none;
}

/* Height from Site settings → Logos (header.php sets --logo-height and
   --logo-height-small); the width follows the SVG's shape. */
.site-header__logo {
	display: block;
	inline-size: auto;
	block-size: var(--logo-height, 2.25rem);
}

.site-nav__list {
	display: flex;
	gap: var(--wp--preset--spacing--xxs);
	margin: 0;
	padding: 0;
	list-style: none;

	/* Hover = a soft capsule behind the link, tinted from the text colour
	   (faint white over a hero, faint forest on glass). */
	& > li > a,
	& .site-nav__trigger {
		display: block;
		padding: calc(1.5 * var(--wp--preset--spacing--xxs)) var(--wp--preset--spacing--sm);
		border-radius: var(--wp--custom--radius--pill);
		color: inherit;
		font-weight: 500;
		text-decoration: none;
		transition: background-color var(--wp--custom--transition--fast);

		&[aria-current="page"],
		&[aria-expanded="true"],
		.current-menu-ancestor > & {
			background: var(--hover-tint);
		}
	}

	/* Items with a dropdown (inc/menu.php) are toggle buttons with a
	   down chevron that flips while open. */
	& .site-nav__trigger {
		display: flex;
		align-items: center;
		gap: var(--wp--preset--spacing--xxs);
		border: 0;
		background: none;
		font: inherit;
		font-weight: 500;
		cursor: pointer;

		&::after {
			content: "";
			inline-size: 0.4em;
			block-size: 0.4em;
			margin-block-start: -0.1em;
			border-inline-end: 1.5px solid;
			border-block-end: 1.5px solid;
			rotate: 45deg;
			transition: rotate var(--wp--custom--transition--base), translate var(--wp--custom--transition--base);
		}

		&[aria-expanded="true"]::after {
			rotate: 225deg;
			translate: 0 0.2em;
		}
	}
}

.site-header__phone,
.site-header__call {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--xs);
	color: inherit;
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color var(--wp--custom--transition--fast);
}

.site-header__phone {
	padding: var(--wp--preset--spacing--xxs) var(--wp--preset--spacing--xs);
	border-radius: var(--wp--custom--radius--pill);
}

.site-header__phone-icon {
	flex: none;
	color: var(--wp--preset--color--accent);
	transition: color var(--wp--custom--transition--base);
	inline-size: 1.25rem;
	block-size: 1.25rem;
}

.site-header__cta {
	display: inline-flex;
	align-items: center;
	flex: none;
	min-block-size: calc(var(--site-header-bar) - 2 * var(--bar-inset));
	white-space: nowrap;
}

/* Round, the size of the CTA: two lines that cross into an X when open. */
.site-header__toggle {
	display: grid;
	place-items: center;
	inline-size: calc(var(--site-header-bar) - 2 * var(--bar-inset));
	block-size: calc(var(--site-header-bar) - 2 * var(--bar-inset));
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	color: inherit;
	cursor: pointer;
}

/* Hover-capable pointers only: on touch the tint would stick after a tap. */
@media (hover: hover) {
	.site-nav__list > li > a:hover,
	.site-nav__trigger:hover,
	.site-header__phone:hover,
	.site-header__toggle:hover,
	.site-header__call:hover {
		background: var(--hover-tint);
	}
}

.site-header__toggle-icon,
.site-header__toggle-icon::before {
	display: block;
	inline-size: 1.25rem;
	block-size: 2px;
	border-radius: 1px;
	background: currentcolor;
	transition: translate var(--wp--custom--transition--base), rotate var(--wp--custom--transition--base);
}

.site-header__toggle-icon {
	translate: 0 -3px;

	&::before {
		content: "";
		translate: 0 6px;
	}

	[aria-expanded="true"] > & {
		translate: 0;
		rotate: 45deg;

		&::before {
			translate: 0;
			rotate: -90deg;
		}
	}
}

/* Below 600px the admin bar scrolls away with the page. */
@media (width <= 600px) {
	.site-header[data-pinned] {
		inset-block-start: var(--site-header-gap);
	}
}

/* While the small-screen menu is open the page behind it stops scrolling.
   [data-menu-open] only ever exists below 70rem. */
html:has(.site-header[data-menu-open]) {
	overflow: hidden;
}

/*
 * Small screens: logo | call | menu button, and the pill grows downwards
 * into a rounded card holding the links and the CTA. The panel animates
 * open via a 0fr → 1fr grid row, and is visibility-hidden while closed so
 * its links can't be tabbed to.
 */
@media (width < 70rem) {
	.site-header {
		--bar-pad: var(--wp--preset--spacing--sm);
		/* How far the menu items sit in from the logo's edge. */
		--menu-inset: var(--wp--preset--spacing--xs);
	}

	.site-header__bar {
		display: grid;
		grid-template-columns: 1fr auto auto;
		grid-template-rows: var(--site-header-bar) auto;
		/* No row gap: the closed panel row must add no height. */
		gap: 0 var(--wp--preset--spacing--xxs);
		block-size: auto;
	}

	.site-header__phone {
		display: none;
	}

	.site-header__logo {
		block-size: var(--logo-height-small, var(--logo-height, 2.25rem));
	}

	.site-header__call {
		display: grid;
		place-items: center;
		inline-size: calc(var(--site-header-bar) - 2 * var(--bar-inset));
		block-size: calc(var(--site-header-bar) - 2 * var(--bar-inset));
		border-radius: 50%;
	}

	.site-header__panel {
		display: grid;
		grid-column: 1 / -1;
		grid-template-rows: 0fr;
		visibility: hidden;
		transition:
			grid-template-rows var(--wp--custom--transition--base),
			visibility 0s linear var(--wp--custom--duration--base);

		.site-header[data-menu-open] & {
			grid-template-rows: 1fr;
			visibility: visible;
			transition: grid-template-rows var(--wp--custom--transition--base);
		}
	}

	.site-header__panel-inner {
		display: grid;
		gap: var(--wp--preset--spacing--md);
		min-block-size: 0;
		overflow: hidden;
		padding-inline-end: calc(var(--bar-pad) - var(--bar-inset));
	}

	.site-nav {
		padding-block-start: var(--wp--preset--spacing--xs);
		border-block-start: 1px solid color-mix(in srgb, currentcolor 12%, transparent);
	}

	.site-nav__list {
		flex-direction: column;
		gap: 0;
		/* Pull the capsules out so the link text sits --menu-inset in from
		   the logo's edge (both sides). The drill-down panels inside the list
		   follow suit. */
		margin-inline: calc(var(--menu-inset) - var(--wp--preset--spacing--sm));
		font-size: var(--wp--preset--font-size--lg);

		& > li > a,
		& .site-nav__trigger {
			padding-block: var(--wp--preset--spacing--xs);
		}
	}

	.site-header__cta {
		justify-content: center;
		margin-block-end: var(--bar-pad);
	}
}

@media (width >= 70rem) {
	.site-header__call,
	.site-header__toggle {
		display: none;
	}

	/* The panel's contents join the bar as flex items. */
	.site-header__panel,
	.site-header__panel-inner {
		display: contents;
	}

	/* Push the right-hand group over: the language switcher, phone or CTA,
	   whichever comes first. */
	.site-lang,
	.site-header__phone:not(.site-lang + *),
	.site-header__cta:not(.site-lang + *, .site-header__phone + *) {
		margin-inline-start: auto;
	}
}

@media (70rem <= width < 81rem) {
	.site-header__phone-number {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
	}
}

/* ------------------------------------------------- language switcher -- */
/*
 * WPML languages (markup: header.php, behaviour: assets/js/main.js). From
 * 70rem: a globe + code button in the bar opening a small card of language
 * names below it (also on keyboard focus before main.js has run). Below
 * 70rem: the button goes and the names sit in a row in the menu panel.
 */
.site-lang {
	position: relative;
	flex: none;
}

.site-lang__toggle {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--xxs);
	padding: calc(1.5 * var(--wp--preset--spacing--xxs)) var(--wp--preset--spacing--sm);
	border: 0;
	border-radius: var(--wp--custom--radius--pill);
	background: none;
	color: inherit;
	font: inherit;
	font-weight: 500;
	cursor: pointer;
	transition: background-color var(--wp--custom--transition--fast);

	&[aria-expanded="true"] {
		background: var(--hover-tint);
	}

	/* The menu triggers' chevron. */
	&::after {
		content: "";
		inline-size: 0.4em;
		block-size: 0.4em;
		margin-block-start: -0.1em;
		border-inline-end: 1.5px solid;
		border-block-end: 1.5px solid;
		rotate: 45deg;
		transition: rotate var(--wp--custom--transition--base), translate var(--wp--custom--transition--base);
	}

	&[aria-expanded="true"]::after {
		rotate: 225deg;
		translate: 0 0.2em;
	}
}

.site-lang__icon {
	flex: none;
	inline-size: 1.25rem;
	block-size: 1.25rem;
}

.site-lang__list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-lang__link {
	display: block;
	padding: var(--wp--preset--spacing--xxs) var(--wp--preset--spacing--sm);
	border-radius: var(--wp--custom--radius--pill);
	color: inherit;
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color var(--wp--custom--transition--fast);

	&[aria-current] {
		background: var(--hover-tint);
	}
}

@media (hover: hover) {
	.site-lang__toggle:hover,
	.site-lang__link:hover {
		background: var(--hover-tint);
	}
}

@media (width >= 70rem) {
	.site-lang__list {
		position: absolute;
		inset-block-start: calc(100% + var(--wp--preset--spacing--sm));
		inset-inline-end: 0;
		display: grid;
		gap: 2px;
		min-inline-size: 12rem;
		padding: var(--wp--preset--spacing--xxs);
		border-radius: var(--wp--custom--radius--md);
		background: var(--wp--preset--color--base);
		box-shadow: var(--wp--custom--shadow--md);
		/* Always Deep Forest, also when the bar's text is white over a hero. */
		color: var(--wp--preset--color--secondary);
		--hover-tint: color-mix(in srgb, currentcolor 8%, transparent);
		opacity: 0;
		translate: 0 -0.25rem;
		visibility: hidden;
		transition:
			opacity var(--wp--custom--transition--fast),
			translate var(--wp--custom--transition--fast),
			visibility 0s linear var(--wp--custom--duration--fast);

		.site-lang[data-open] &,
		.site-lang:not([data-ready]):focus-within & {
			opacity: 1;
			translate: 0;
			visibility: visible;
			transition:
				opacity var(--wp--custom--transition--fast),
				translate var(--wp--custom--transition--fast);
		}
	}
}

@media (width < 70rem) {
	.site-lang__toggle {
		display: none;
	}

	/* Line up with the menu links' text (see .site-nav__list). */
	.site-lang__list {
		display: flex;
		flex-wrap: wrap;
		gap: var(--wp--preset--spacing--xxs);
		margin-inline: calc(var(--menu-inset) - var(--wp--preset--spacing--sm));
	}
}

@media (prefers-reduced-motion: reduce) {
	.site-lang__list {
		translate: none;
	}
}

/* ------------------------------------------------------- mega menu -- */
/*
 * Dropdowns on Primary menu items (markup + fields: inc/menu.php,
 * behaviour: assets/js/main.js). Unlayered, like the rest of the header.
 *
 * Mega panels have three columns: pages (icon tile, title, description), a
 * link list with an eyebrow, and a photo card. Simple dropdowns
 * (.site-mega--list) have only the pages, without the tiles. Hover arrows
 * show on hover-capable pointers and on keyboard focus.
 *
 * From 70rem: a frosted glass card just below the pill, fading down into
 * place — the pill's width for a mega panel, sized to its links and lined up
 * under its own item for a simple one. Below 70rem: a drill-down level inside the
 * expanded pill — the top-level list slides out to the left and the panel
 * slides in from the right, its columns stacked (card last). main.js sets
 * the nav's height while a level is open. When a level is taller than the
 * screen allows, its columns scroll under a Back button that stays put.
 *
 * States, set by main.js:
 *   li.has-dropdown[data-open]  this item's dropdown is open
 *   .site-nav[data-sub-open]    below 70rem: a drill-down level is showing
 *   .site-header[data-mega-open] any panel is open (keeps the header in view)
 */
.site-mega {
	--mega-muted: color-mix(in srgb, var(--wp--preset--color--secondary) 72%, transparent);
	--mega-rule: color-mix(in srgb, var(--wp--preset--color--secondary) 12%, transparent);
	color: var(--wp--preset--color--secondary);
	font-size: var(--wp--preset--font-size--md);
	line-height: 1.4;

	& ul {
		margin: 0;
		padding: 0;
		list-style: none;
	}

	& a:not(.wp-element-button) {
		color: inherit;
		text-decoration: none;
	}
}

.site-mega__grid {
	display: grid;
	gap: var(--wp--preset--spacing--md);
}

/* Arrow after a page title (column 1) or list link (column 2). Both share
   one reveal: it fades in and slides right on hover or keyboard focus of
   its link (rules after the columns). */
.site-mega__arrow {
	flex: none;
	inline-size: 1.5em;
	block-size: 1.5em;
	margin-block: -0.25em;
	opacity: 0;
	translate: -0.35em 0;
	transition: opacity var(--wp--custom--transition--fast), translate var(--wp--custom--transition--base);

	/* Bolder than the carousel's own stroke (2), to sit with 500-weight text. */
	& g {
		stroke-width: 3;
	}
}

/* ---- Column 1: pages ---- */

.site-mega__pages {
	display: grid;
	gap: var(--wp--preset--spacing--xxs);
	align-content: start;
}

.site-mega__page {
	display: grid;
	grid-template-columns: 3rem 1fr;
	gap: var(--wp--preset--spacing--sm);
	align-items: center;
	padding: var(--wp--preset--spacing--xs);
	border-radius: var(--wp--custom--radius--md);
}

/* Simple dropdowns: no icon tile. */
.site-mega__page--plain {
	grid-template-columns: minmax(0, 1fr);
	padding-inline: var(--wp--preset--spacing--sm);
}

.site-mega__icon {
	display: grid;
	place-items: center;
	inline-size: 3rem;
	aspect-ratio: 1;
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--tint);
	transition: background-color var(--wp--custom--transition--base);

	& img {
		inline-size: 1.75rem;
		block-size: 1.75rem;
		object-fit: contain;
	}
}

.site-mega__page-text {
	display: grid;
	gap: 0.125rem;
}

/* Column 1's title + description and column 2's label + arrow: nudged
   right together on hover (rules after the columns). */
:is(.site-mega__page-text, .site-mega__link-text) {
	transition: translate var(--wp--custom--transition--base);
}

.site-mega__page-title {
	display: flex;
	align-items: center;
	gap: 0.15em;
	font-weight: 500;
}

.site-mega__page-desc {
	color: var(--mega-muted);
	font-size: var(--wp--preset--font-size--sm);
}

/* ---- Column 2: link list ---- */

.site-mega__heading {
	margin: 0 0 var(--wp--preset--spacing--xxs);
	color: var(--mega-muted);
}

.site-mega__link {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--xs);
	padding-block: var(--wp--preset--spacing--xs);
	font-weight: 500;
}

/* Optional icon (e.g. a flag): shown as is, no tile; stays put while the
   text beside it nudges right on hover. */
.site-mega__link-icon {
	flex: none;
	inline-size: 1.5em;
	block-size: 1.5em;
	object-fit: contain;
}

.site-mega__link-text {
	display: inline-flex;
	align-items: center;
	gap: 0.15em;
}

/* ---- Column 3: photo card ---- */

.site-mega__card {
	position: relative;
	isolation: isolate;
	display: flex;
	align-items: flex-end;
	min-block-size: 18rem;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--card-lg);
	background: var(--wp--preset--color--secondary);
	color: var(--wp--preset--color--base);

	/* Darkens the bottom of the photo under the text. */
	&::after {
		content: "";
		position: absolute;
		inset: 0;
		z-index: -1;
		background: linear-gradient(
			to top,
			color-mix(in srgb, var(--wp--preset--color--secondary) 92%, transparent),
			color-mix(in srgb, var(--wp--preset--color--secondary) 55%, transparent) 45%,
			transparent 80%
		);
	}
}

.site-mega__card-image {
	position: absolute;
	inset: 0;
	z-index: -2;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	transition: scale 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}

.site-mega__card-body {
	padding: var(--wp--preset--spacing--md);
}

.site-mega__card-title {
	margin: 0;
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 500;
	line-height: 1.25;
}

.site-mega__card-text {
	margin: var(--wp--preset--spacing--xxs) 0 0;
	font-size: var(--wp--preset--font-size--sm);
	opacity: 0.85;
}

/* A decal button, always shown. Hovering (or focusing) anywhere on the card
   plays the decal's own hover: the circle fills and the arrow nudges right
   (rules mirror .wp-element-button.is-decal:hover). The default
   --decal-knock (Deep Forest) matches the gradient behind it. */
.site-mega__card-button {
	margin-block-start: var(--wp--preset--spacing--sm);

	/* The whole card is the button's click target. */
	&::after {
		content: "";
		position: absolute;
		inset: 0;
	}
}

/* Hover: arrows slide in and the link text nudges right (both columns); in
   column 1 the icon tile deepens; the photo zooms a little. Keyboard focus
   gets the same cues. */
@media (hover: hover) {
	:is(.site-mega__page, .site-mega__link):hover .site-mega__arrow {
		opacity: 1;
		translate: 0 0;
	}

	.site-mega__page:hover .site-mega__icon {
		background: color-mix(in srgb, var(--wp--preset--color--tint), var(--wp--preset--color--primary) 12%);
	}

	.site-mega__page:hover .site-mega__page-text,
	.site-mega__link:hover .site-mega__link-text {
		translate: var(--wp--preset--spacing--xxs) 0;
	}

	.site-mega__card:hover .site-mega__card-image {
		scale: 1.04;
	}
}

.site-mega__card:is(:hover, :focus-within) .site-mega__card-button {
	& .plinth-icon {
		translate: 0.2em 0;
	}

	& .plinth-icon__fill {
		opacity: 1;
	}

	& .plinth-icon__arrow {
		stroke: var(--decal-knock);
	}
}

:is(.site-mega__page, .site-mega__link):focus-visible .site-mega__arrow {
	opacity: 1;
	translate: 0 0;
}

.site-mega__page:focus-visible .site-mega__icon {
	background: color-mix(in srgb, var(--wp--preset--color--tint), var(--wp--preset--color--primary) 12%);
}

.site-mega__page:focus-visible .site-mega__page-text,
.site-mega__link:focus-visible .site-mega__link-text {
	translate: var(--wp--preset--spacing--xxs) 0;
}

/* Back button: only the small-screen drill-down shows it. */
.site-mega__back {
	display: none;
}

@media (width >= 70rem) {
	.site-mega {
		position: absolute;
		inset-inline: 0;
		inset-block-start: calc(100% + var(--site-header-gap));
		max-block-size: calc(100dvh - var(--wp-admin--admin-bar--height, 0px) - var(--site-header-height) - var(--site-header-gap));
		overflow-y: auto;
		overscroll-behavior: contain;
		padding: var(--wp--preset--spacing--md);
		border-radius: var(--wp--custom--radius--lg);
		background: var(--mega-glass);
		-webkit-backdrop-filter: blur(16px) saturate(1.6);
		backdrop-filter: blur(16px) saturate(1.6);
		box-shadow: inset 0 0 0 1px var(--mega-rule), var(--wp--custom--shadow--lg);
		opacity: 0;
		translate: 0 calc(-1 * var(--wp--preset--spacing--xs));
		visibility: hidden;
		/* Hide only once the fade is over. The delay must be a duration token:
		   transition tokens carry an easing too, and a second easing would
		   make the whole declaration invalid (closing instantly). */
		transition:
			opacity var(--wp--custom--transition--base),
			translate var(--wp--custom--transition--base),
			visibility 0s linear var(--wp--custom--duration--base);

		.has-dropdown[data-open] > & {
			opacity: 1;
			translate: 0 0;
			visibility: visible;
			transition: opacity var(--wp--custom--transition--base), translate var(--wp--custom--transition--base);
		}
	}

	/* Bridges the gap between the pill and an open panel, so the pointer
	   can cross it without leaving the item. */
	.has-dropdown[data-open]::after {
		content: "";
		position: absolute;
		inset-inline: 0;
		inset-block-start: 100%;
		block-size: var(--site-header-gap);
	}

	.site-mega__grid {
		grid-template-columns: minmax(0, 1.35fr) minmax(0, 0.85fr) minmax(0, 1fr);
	}

	.site-mega__list {
		padding-inline-start: var(--wp--preset--spacing--md);
		border-inline-start: 1px solid var(--mega-rule);
	}

	.site-mega__card {
		min-block-size: 100%;
	}

	/* Simple dropdowns: a compact card under its own item (main.js sets
	   --drop-x, the item's offset in the pill), one column of pages. */
	.site-mega--list {
		inset-inline: var(--drop-x, 0) auto;
		inline-size: max-content;
		min-inline-size: 16rem;
		max-inline-size: 24rem;
		padding: var(--wp--preset--spacing--xs);

		& .site-mega__grid {
			grid-template-columns: minmax(0, 1fr);
		}
	}
}

@media (width < 70rem) {
	/* The expanded menu (top level and drill-down levels) takes the
	   dropdown's lighter glass; the ::before glass layer fades between them. */
	.site-header[data-menu-open] .site-header__bar {
		--glass: var(--mega-glass);
	}

	.site-nav__list {
		position: relative;
		transition: translate var(--wp--custom--transition--base);

		.site-nav[data-sub-open] & {
			translate: -100% 0;
		}

		/* Slid-away items leave the tab order once the slide is done. */
		.site-nav[data-sub-open] & > li > :is(a, .site-nav__trigger) {
			visibility: hidden;
			transition: visibility 0s linear var(--wp--custom--duration--base);
		}
	}

	.site-nav {
		transition: block-size var(--wp--custom--transition--base);
	}

	/* A › chevron: the item opens a level rather than dropping down. */
	.site-nav__list .site-nav__trigger {
		justify-content: space-between;
		inline-size: 100%;
		text-align: start;

		&::after,
		&[aria-expanded="true"]::after {
			rotate: -45deg;
			translate: 0;
			margin-inline-end: var(--wp--preset--spacing--xxs);
		}
	}

	.site-mega {
		position: absolute;
		inset-block-start: 0;
		inset-inline-start: 100%;
		inline-size: 100%;
		/* Back stays put at the top; only the columns below it scroll. */
		display: flex;
		flex-direction: column;
		/* Header bar, the CTA row under the nav and some breathing room. */
		max-block-size: calc(100dvh - var(--wp-admin--admin-bar--height, 0px) - var(--site-header-height) - 8rem);
		padding-inline: var(--wp--preset--spacing--sm);
		color: inherit;
		visibility: hidden;
		transition: visibility 0s linear var(--wp--custom--duration--base);

		.has-dropdown[data-open] > & {
			visibility: visible;
			transition: none;
		}
	}

	.site-mega__grid {
		min-block-size: 0;
		overflow-y: auto;
		overscroll-behavior: contain;
		/* 4px of room so focus rings at the edges aren't clipped by the
		   scroll box; the negative margin keeps the content aligned. */
		margin-inline: -4px;
		padding: 0 4px var(--wp--preset--spacing--xs);
	}

	/* Back: the top-level chevron (.site-nav__trigger::after), pointing left. */
	.site-mega__back {
		flex: none;
		display: flex;
		align-items: center;
		gap: var(--wp--preset--spacing--xs);
		margin-block-end: var(--wp--preset--spacing--xs);
		padding: var(--wp--preset--spacing--xs) 0;
		border: 0;
		background: none;
		color: inherit;
		font: inherit;
		font-size: var(--wp--preset--font-size--lg);
		font-weight: 500;
		cursor: pointer;
	}

	.site-mega__back::before {
		content: "";
		inline-size: 0.4em;
		block-size: 0.4em;
		margin-inline-start: 0.15em;
		border-inline-end: 1.5px solid;
		border-block-end: 1.5px solid;
		rotate: 135deg;
	}

	.site-mega__page {
		padding-inline: 0;
	}

	.site-mega__list {
		padding-block-start: var(--wp--preset--spacing--md);
		border-block-start: 1px solid var(--mega-rule);
	}

	.site-mega__card {
		min-block-size: 16rem;
	}
}

.wp-element-button.is-decal {
	/* Arrow colour while the circle is filled on hover: the colour behind the
	   button. Override on light backgrounds (e.g. var(--wp--preset--color--base)). */
	--decal-knock: var(--wp--preset--color--secondary);
	--decal-ease: cubic-bezier(0.22, 1, 0.36, 1); /* Ease-out: quick start, soft landing. */
	background: none;
	color: inherit;
	padding-inline: 0;
	border-radius: var(--wp--custom--radius--sm); /* Shapes the focus ring only. */

	& .plinth-icon {
		flex-shrink: 0;
		inline-size: 1.25em;
		block-size: 1.25em;
		overflow: visible;
		transition: translate 0.45s var(--decal-ease);
	}

	/* The fill fades in and out with the arrow's colour change. */
	& .plinth-icon__fill {
		opacity: 0;
		transition: opacity 0.35s ease;
	}

	& .plinth-icon__arrow {
		transition: stroke 0.35s ease;
	}

	&:hover {
		background: none;
		color: inherit;

		& .plinth-icon {
			translate: 0.2em 0;
		}

		& .plinth-icon__fill {
			opacity: 1;
		}

		& .plinth-icon__arrow {
			stroke: var(--decal-knock);
		}
	}
}

/* --------------------------------------------------------- eyebrow -- */
/*
 * The small uppercase label over a heading, led by a brand marker. Render it
 * with plinth_eyebrow() (inc/eyebrow.php); markers are --square, --diamond,
 * --circle and --shapes (all three). One marker size everywhere.
 *
 * In @layer base, so a block's own (unlayered) CSS can position, space and
 * colour its eyebrow, and animate .plinth-eyebrow__marker. Blocks never
 * restyle the shapes themselves.
 */
@layer base {
	.plinth-eyebrow {
		display: flex;
		align-items: center;
		gap: var(--wp--preset--spacing--xs);
		font-size: var(--wp--preset--font-size--sm);
		letter-spacing: 0.04em;
		text-transform: uppercase;
	}

	.plinth-eyebrow__marker {
		display: flex;
		align-items: center;
		gap: 0.3em;
		flex-shrink: 0;

		& > span {
			inline-size: 0.7em;
			block-size: 0.7em;
			background: var(--wp--preset--color--accent);
		}
	}

	/* Diamonds are scaled so they look the same size as the square. */
	.plinth-eyebrow--diamond .plinth-eyebrow__marker > span,
	.plinth-eyebrow--shapes .plinth-eyebrow__marker > span:nth-child(2) {
		rotate: 45deg;
		scale: 0.8;
	}

	.plinth-eyebrow--circle .plinth-eyebrow__marker > span,
	.plinth-eyebrow--shapes .plinth-eyebrow__marker > span:nth-child(3) {
		border-radius: 50%;
	}
}

/* -------------------------------------------------------- carousel -- */
/*
 * Scroll-snap carousels (Feature Carousel, Industries Bento on phones,
 * Blog Feed).
 *
 *   <div class="plinth-carousel__track"> <div class="plinth-carousel__slide"
 *     role="group" aria-roledescription="slide" aria-label="1 of 3">…
 *   (A slide's group role replaces an <li>'s listitem role, so a <ul> track
 *   must be role="presentation" while it is a carousel — see Industries Bento.)
 *   + plinth_carousel_controls() (inc/carousel.php): prev / next arrows and
 *     indicator bars, wired by assets/js/carousel.js.
 *
 * The track bleeds to the edges of the block, and its padding keeps the
 * resting slide on the content edge, so slides enter and leave at the screen
 * edge. Each slide is the content width less --carousel-peek (and the gap),
 * so that much of the next one shows; the last slide snaps to its end, flush
 * with the content edge on the right. Bleeding assumes the content fills the
 * block, as it does wherever a block shows its arrows under the slides.
 *
 * The block places the controls (e.g. with grid areas) and may size the bars
 * with --dot-min / --dot-max. In @layer base, so a block's own (unlayered)
 * CSS can place, size and override all of it.
 */
@layer base {
	.plinth-carousel__track {
		--carousel-peek: 0.5rem;
		--carousel-gap: var(--wp--preset--spacing--sm);

		display: flex;
		gap: var(--carousel-gap);
		margin-block: 0;
		margin-inline: calc(-1 * var(--block-gutter));
		padding-block: 0;
		padding-inline: var(--block-gutter);
		list-style: none;
		overflow-x: auto;
		overscroll-behavior-x: contain;
		scroll-padding-inline: var(--block-gutter);
		scroll-snap-type: x mandatory;
		scrollbar-width: none;

		&::-webkit-scrollbar {
			display: none;
		}

		&:focus-visible {
			outline-offset: -2px;
		}
	}

	/* 100% is the track's content box: the content width. */
	.plinth-carousel__slide {
		flex: 0 0 calc(100% - var(--carousel-peek) - var(--carousel-gap));
		scroll-snap-align: start;
		scroll-snap-stop: always;

		&:last-child {
			scroll-snap-align: end;
		}

		/* Paged carousels: only the slide starting each page snaps. */
		&[data-carousel-skip] {
			scroll-snap-align: none;
		}
	}

	/* Controls carousel.js can't use (everything fits, or a dot past the
	   last resting place). */
	:is(.plinth-carousel__arrow, .plinth-carousel__dots, .plinth-carousel__dot)[hidden] {
		display: none;
	}

	.plinth-carousel__arrow {
		display: grid;
		place-items: center;
		inline-size: 3.125rem;
		block-size: 3.125rem;
		padding: 0;
		border: 1px solid currentcolor;
		border-radius: var(--wp--custom--radius--md);
		background: transparent;
		color: inherit;
		cursor: pointer;
		transition: background-color var(--wp--custom--transition--fast), opacity var(--wp--custom--transition--fast);

		&:hover:not(:disabled) {
			background: color-mix(in srgb, currentcolor 8%, transparent);
		}

		&:disabled {
			opacity: 0.3;
			cursor: default;
		}
	}

	.plinth-carousel__arrow-icon {
		inline-size: 100%;
		block-size: 100%;
	}

	.plinth-carousel__arrow--prev .plinth-carousel__arrow-icon {
		scale: -1 1;
	}

	/* Each dot's --t (0–1) is how "current" it is; carousel.js sets it from
	   the scroll position, so the bars open and close as the slides move. */
	.plinth-carousel__dots {
		display: flex;
		justify-content: center;
		gap: var(--wp--preset--spacing--xs);
	}

	.plinth-carousel__dot {
		--t: 0;

		inline-size: calc(var(--dot-min, 1.5rem) + (var(--dot-max, 4rem) - var(--dot-min, 1.5rem)) * var(--t));
		padding: var(--wp--preset--spacing--xs) 0;
		border: 0;
		background: none;
		cursor: pointer;

		&:first-child {
			--t: 1;
		}

		&::before {
			content: "";
			display: block;
			block-size: 0.25rem;
			border-radius: var(--wp--custom--radius--pill);
			background: var(--wp--preset--color--accent);
			opacity: calc(0.2 + 0.8 * var(--t));
		}

		&:focus-visible {
			outline-offset: 0;
		}
	}
}

/* ------------------------------------------------------- post card -- */
/*
 * The shared post card (plinth_post_card(), inc/feed.php): the Posts page /
 * archive grid (template-parts/feed.php) and the Blog Feed block.
 *
 *   <article class="plinth-post-card">
 *     <div class="plinth-post-card__media"> img + .plinth-post-badges </div>
 *     <h3 class="plinth-post-card__title"><a class="plinth-post-card__link">
 *     <p class="plinth-post-byline plinth-post-card__byline">
 *
 * The title leads in the source; the byline shows above it. The title
 * link covers the whole card; hovering zooms the photo (as Split · Image).
 * The badges and byline are shared with the featured post.
 *
 * UNLAYERED, so the title's size beats theme.json's global h3 rule.
 */
.plinth-post-card {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	inline-size: 100%;
}

.plinth-post-card__media {
	position: relative;
	inline-size: 100%;
	aspect-ratio: 16 / 9;
	margin-block-end: var(--wp--preset--spacing--md);
	overflow: clip;
	border-radius: var(--wp--custom--radius--card-lg);
	background: var(--wp--preset--color--neutral);
}

/* --plinth-motion is 0 for reduced motion, so the photo stays still. */
.plinth-post-card__image {
	position: absolute;
	inset: 0;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	transition: scale 0.4s cubic-bezier(0.33, 1, 0.68, 1);
}

.plinth-post-card__byline {
	order: 1;
}

.plinth-post-card__title {
	order: 2;
	margin-block-start: var(--wp--preset--spacing--xs);
	color: inherit;
	font-size: var(--wp--preset--font-size--xl);
	text-wrap: pretty;
}

.plinth-post-card__link {
	color: inherit;
	text-decoration: none;

	&::after {
		content: "";
		position: absolute;
		inset: 0;
		border-radius: var(--wp--custom--radius--card-lg);
	}

	&:focus-visible {
		outline: none;

		&::after {
			outline: 2px solid var(--wp--preset--color--accent);
			outline-offset: 4px;
		}
	}
}

@media (hover: hover) {
	.plinth-post-card:hover .plinth-post-card__image {
		scale: calc(1 + 0.05 * var(--plinth-motion, 1));
	}
}

/* Byline: "James Dillon on 2 September 2026", the name in Magenta. */
.plinth-post-byline {
	margin: 0;
	font-size: var(--wp--preset--font-size--sm);

	& .plinth-post-byline__author {
		color: var(--wp--preset--color--accent);
	}
}

/* Badges over the image's top-left corner: the category (Forest) and, for
   video posts, a square play badge (Magenta) of the same height. */
.plinth-post-badges {
	position: absolute;
	inset-block-start: var(--wp--preset--spacing--sm);
	inset-inline-start: var(--wp--preset--spacing--sm);
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--xxs);
	max-inline-size: calc(100% - 2 * var(--wp--preset--spacing--sm));
}

.plinth-post-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-block-size: 2.125rem;
	padding: var(--wp--preset--spacing--xxs) var(--wp--preset--spacing--sm);
	border-radius: var(--wp--custom--radius--sm);
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 500;
	line-height: 1.2;
}

.plinth-post-badge--video {
	inline-size: 2.75rem;
	padding: 0;
	background: var(--wp--preset--color--accent);

	& .plinth-icon {
		inline-size: 0.875rem;
		block-size: 0.875rem;
	}
}

/* ------------------------------------------------------- team card -- */
/*
 * The shared team card and grid (plinth_team_card() / plinth_team_grid(),
 * inc/team.php): the Team Grid block and the person page's colleagues row.
 *
 *   <ul class="plinth-team-grid"><li class="plinth-team-grid__item">
 *     <article class="plinth-team-card">
 *       <div class="plinth-team-card__media"> img | initials </div>
 *       <h3 class="plinth-team-card__name"><a class="plinth-team-card__link">
 *       <p class="plinth-team-card__job">
 *
 * A square photo over the name and job title, on the surrounding
 * background. The name's link covers the whole card; hovering zooms the
 * photo (as the post card) and turns the name Magenta. Columns come from
 * --team-cols, set by the block or template around the grid.
 *
 * UNLAYERED, so the name's size beats theme.json's global h3 rule.
 */
.plinth-team-grid {
	display: grid;
	grid-template-columns: repeat(var(--team-cols, 2), minmax(0, 1fr));
	gap: var(--wp--preset--spacing--lg) var(--team-gap, var(--wp--preset--spacing--sm));
	margin: 0;
	padding: 0;
	list-style: none;
}

.plinth-team-grid__item {
	display: grid;
	margin: 0;
}

.plinth-team-card {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	inline-size: 100%;
}

/* A soft wash of the text colour stands in for a missing or loading photo,
   on any background. */
.plinth-team-card__media {
	position: relative;
	inline-size: 100%;
	aspect-ratio: 1;
	margin-block-end: var(--wp--preset--spacing--sm);
	overflow: clip;
	border-radius: var(--wp--custom--radius--card-lg);
	background: color-mix(in srgb, currentColor 10%, transparent);
}

/* --plinth-motion is 0 for reduced motion, so the photo stays still. */
.plinth-team-card__image {
	position: absolute;
	inset: 0;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	transition: scale 0.4s cubic-bezier(0.33, 1, 0.68, 1);
}

.plinth-team-card__initials {
	display: grid;
	place-items: center;
	block-size: 100%;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--xxl);
	color: color-mix(in srgb, currentColor 45%, transparent);
}

.plinth-team-card__name {
	margin: 0;
	color: inherit;
	font-size: var(--wp--preset--font-size--lg);
	line-height: 1.2;
	text-wrap: balance;
}

.plinth-team-card__link {
	color: inherit;
	text-decoration: none;
	transition: color var(--wp--custom--transition--fast);

	&::after {
		content: "";
		position: absolute;
		inset: 0;
		border-radius: var(--wp--custom--radius--card-lg);
	}

	&:focus-visible {
		outline: none;

		&::after {
			outline: 2px solid var(--wp--preset--color--accent);
			outline-offset: 4px;
		}
	}
}

.plinth-team-card__job {
	margin: var(--wp--preset--spacing--xxs) 0 0;
	font-size: var(--wp--preset--font-size--sm);
	line-height: 1.4;
	color: color-mix(in srgb, currentColor 75%, transparent);
}

@media (hover: hover) {
	.plinth-team-card:hover {
		& .plinth-team-card__image {
			scale: calc(1 + 0.05 * var(--plinth-motion, 1));
		}

		& .plinth-team-card__link {
			color: var(--team-highlight, var(--wp--preset--color--accent));
		}
	}
}

/* ----------------------------------------------------- site footer -- */
/*
 * Site footer (footer.php). UNLAYERED on purpose: theme.json's global
 * link, heading and button styles are unlayered too, and would otherwise
 * beat anything in @layer base. Mobile first: brand, then the two link
 * columns side by side, then socials + newsletter. From 48rem the brand
 * and newsletter share the top row; from 72rem it is four columns.
 */
.site-footer {
	--footer-text: var(--wp--preset--color--tint);
	--footer-muted: color-mix(in srgb, var(--wp--preset--color--tint) 80%, transparent);
	--footer-line: color-mix(in srgb, var(--wp--preset--color--tint) 20%, transparent);

	background: var(--wp--preset--color--secondary);
	color: var(--footer-muted);
	font-size: var(--wp--preset--font-size--sm);

	& :focus-visible {
		outline-color: var(--footer-text);
	}

	& a {
		color: inherit;
		text-decoration: none;
		transition: color var(--wp--custom--transition--fast);

		&:hover {
			color: var(--footer-text);
		}
	}
}

.site-footer__inner {
	max-width: var(--block-max-width);
	margin-inline: auto;
	padding-block: var(--wp--preset--spacing--xl) var(--wp--preset--spacing--lg);
	padding-inline: var(--wp--preset--spacing--gutter);
}

.site-footer__main {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	grid-template-areas:
		"brand brand"
		"col1 col2"
		"connect connect";
	gap: var(--wp--preset--spacing--lg) var(--wp--preset--spacing--md);
	padding-block-end: var(--wp--preset--spacing--lg);
}

.site-footer__brand { grid-area: brand; }
.site-footer__col--footer-resources { grid-area: col1; }
.site-footer__col--footer-legal { grid-area: col2; }
.site-footer__connect { grid-area: connect; }

@media (width >= 48rem) {
	.site-footer__main {
		grid-template-areas:
			"brand connect"
			"col1 col2";
	}
}

@media (width >= 72rem) {
	.site-footer__main {
		grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.75fr);
		grid-template-areas: "brand col1 col2 connect";
	}
}

.site-footer__logo {
	display: block;
	inline-size: min(100%, 13rem);
	color: var(--wp--preset--color--base);

	&:hover {
		color: var(--wp--preset--color--base);
	}
}

/* A height from Site settings → Logos (footer.php sets --logo-height and
   --logo-height-small): the logo keeps it, its width follows the SVG's
   shape, capped at the column's width. */
.site-footer__logo--sized {
	inline-size: fit-content;
	max-inline-size: 100%;

	& svg {
		inline-size: auto;
		block-size: var(--logo-height);
	}
}

@media (width < 48rem) {
	.site-footer__logo--sized svg {
		block-size: var(--logo-height-small, var(--logo-height));
	}
}

.site-footer__tagline {
	margin-block-start: var(--wp--preset--spacing--md);
}

.site-footer__contact {
	display: grid;
	gap: var(--wp--preset--spacing--xxs);
	margin-block-start: var(--wp--preset--spacing--lg);

	& div {
		display: flex;
		flex-wrap: wrap;
		gap: var(--wp--preset--spacing--xxs);
	}

	& dt {
		font-weight: 500;
		color: var(--footer-text);
	}
}

.site-footer__heading {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--md);
	font-weight: 500;
	line-height: 1.3;
	color: var(--footer-text);
}

.site-footer__links {
	display: grid;
	gap: var(--wp--preset--spacing--xxs);
	margin-block-start: var(--wp--preset--spacing--md);
	padding: 0;
	list-style: none;
}

.site-footer__connect {
	display: grid;
	align-content: start;
	gap: var(--wp--preset--spacing--lg);
}

.site-footer__socials {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--xs);
	padding: 0;
	list-style: none;
}

.site-footer__social {
	display: grid;
	place-items: center;
	inline-size: 2.75rem;
	block-size: 2.75rem;
	border-radius: var(--wp--custom--radius--pill);
	background: color-mix(in srgb, var(--wp--preset--color--tint) 6%, transparent);
	color: var(--footer-text);
	transition: background-color var(--wp--custom--transition--fast);

	&:hover {
		background: color-mix(in srgb, var(--wp--preset--color--tint) 14%, transparent);
	}

	& svg {
		inline-size: 1.25rem;
		block-size: 1.25rem;
		fill: currentcolor;
	}
}

.site-footer__newsletter-row {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--xs);
	margin-block-start: var(--wp--preset--spacing--sm);
}

/* The input soaks up the free space; once the button wraps onto its own
   line it grows to full width instead. */
.site-footer__input {
	flex: 999 1 15rem;
	min-inline-size: 0;
	padding: var(--wp--preset--spacing--xs) var(--wp--preset--spacing--md);
	border: 1px solid var(--footer-muted);
	border-radius: var(--wp--custom--radius--pill);
	background: transparent;
	color: var(--footer-text);
	/* iOS Safari zooms the page when focusing a field under 16px, and the
	   footer's sm size is 15px; md keeps the input at 16px or more. */
	font-size: var(--wp--preset--font-size--md);

	&::placeholder {
		color: var(--footer-text);
		opacity: 1;
	}
}

.site-footer__submit.wp-element-button {
	flex: 1 0 auto;
	justify-content: center;
	border: 0;
	font-size: inherit;
}

.site-footer__bottom {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--sm) var(--wp--preset--spacing--md);
	padding-block-start: var(--wp--preset--spacing--md);
	border-block-start: 1px solid var(--footer-line);
}

.site-footer__bottom-links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--xs) var(--wp--preset--spacing--md);
	padding: 0;
	list-style: none;
}

/* ------------------------------------------------------------ utilities -- */
@layer utilities {
	.screen-reader-text {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}
}
