/*
Theme Name:  Shyft
Description: Custom WordPress theme for Shyft. Hybrid theme — classic PHP templates with a theme.json design-token layer.
Author:      CW Systems
Version:     3.8.0
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.0
*/

/* ============================================================================
   CONTENTS
   1.  Tokens
   2.  Reset & base
   3.  Layout
   4.  Accessibility
   5.  Site header
   6.  Primary navigation — desktop
   7.  Mega panel
   8.  Primary navigation — mobile drawer
   9.  Search overlay
   10. Content
   11. Buttons
   12. Cards, grids & pagination
   13. Site footer
   14. Homepage sections
   15. Content page sections
   16. Edit link
   17. Utilities
   ========================================================================= */


/* ============================================================================
   1. TOKENS

   Colour, type and spacing come from theme.json as --wp--preset--* variables.
   Only values theme.json has no concept of live here.
   ========================================================================= */

:root {
	--shyft-gutter: clamp(1.5rem, 5vw, 4rem);
	--shyft-section-y: clamp(5rem, 10vw, 8.75rem);
	--shyft-section-y-lg: clamp(6rem, 12vw, 11.25rem);

	--shyft-nav-breakpoint: 900px;

	/* Hairlines. Alpha values, so they sit on any background. */
	--shyft-line: rgb(17 17 17 / 12%);
	--shyft-line-soft: rgb(17 17 17 / 6%);
	--shyft-line-invert: rgb(255 255 255 / 8%);
	--shyft-line-invert-strong: rgb(255 255 255 / 25%);

	/*
	 * The hairline a content-page component should currently draw with.
	 * Components read this rather than picking a colour, so dropping a section
	 * onto a dark panel or a photograph re-points every rule inside it at once
	 * — see "Sections on a photograph" in section 15.
	 */
	--shyft-rule: var(--shyft-line);

	--shyft-ease: cubic-bezier(0.23, 1, 0.32, 1);
	--shyft-transition: 300ms var(--shyft-ease);
	--shyft-transition-slow: 500ms var(--shyft-ease);

	/* Square-edged throughout — no corner rounding anywhere. */
	--shyft-radius: 0;
	--shyft-radius-lg: 0;

	--shyft-shadow-lift: 0 30px 60px -32px rgb(17 17 17 / 18%);
	--shyft-shadow-md: 0 8px 24px rgb(0 0 0 / 10%);
	--shyft-shadow-lg: 0 16px 48px rgb(0 0 0 / 16%);

	--shyft-z-header: 100;
	--shyft-z-mega: 90;
	--shyft-z-edit: 80;
	--shyft-z-backdrop: 1000;
	--shyft-z-overlay: 1010;

	--shyft-eyebrow-tracking: 0.21em;

	/* How far the hero device hangs below the dark hero panel. */
	--shyft-hero-overhang: clamp(70px, 15vh, 180px);
}


/* ============================================================================
   2. RESET & BASE
   ========================================================================= */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	/*
	 * Contains the off-canvas drawer, which is parked one viewport to the right
	 * when closed. `clip` on the root propagates to the viewport, so it catches
	 * fixed-position children too — and unlike `hidden` it never creates a
	 * scroll container, which would disable position: sticky page-wide.
	 */
	overflow-x: clip;
}

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

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

body {
	margin: 0;
	text-rendering: optimizeLegibility;
	-webkit-font-smoothing: antialiased;
}

body.no-scroll {
	overflow: hidden;
}

img,
svg,
video,
canvas,
iframe {
	display: block;
	max-width: 100%;
}

img,
video {
	height: auto;
}

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

button {
	cursor: pointer;
}

:where(h1, h2, h3, h4, h5, h6) {
	overflow-wrap: break-word;
	hyphens: none;
	text-wrap: balance;
}

:where(p, li) {
	text-wrap: pretty;
}

:where(a) {
	color: inherit;
}

:where(ul, ol):where(.menu, .mega-links, .post-grid, .page-links) {
	margin: 0;
	padding: 0;
	list-style: none;
}

:focus-visible {
	/* currentcolor so the ring stays legible on light and dark sections alike. */
	outline: 2px solid currentcolor;
	outline-offset: 3px;
}


/* ============================================================================
   3. LAYOUT

   Three levels nest the same full-bleed grid: .site-main > .entry >
   .entry-content. Each spans `full` in its parent, so alignfull still reaches
   the viewport edge three levels down.
   ========================================================================= */

.site {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
	min-height: 100dvh;
}

.site-content {
	flex: 1 0 auto;
}

.site-main,
.entry,
.entry-content {
	--shyft-content: var(--wp--style--global--content-size, 1400px);
	--shyft-wide: var(--wp--style--global--wide-size, 1800px);

	display: grid;
	align-content: start;
	grid-template-columns:
		[full-start] minmax(var(--shyft-gutter), 1fr)
		[wide-start] minmax(0, calc((var(--shyft-wide) - var(--shyft-content)) / 2))
		[content-start] min(100% - (var(--shyft-gutter) * 2), var(--shyft-content)) [content-end]
		minmax(0, calc((var(--shyft-wide) - var(--shyft-content)) / 2)) [wide-end]
		minmax(var(--shyft-gutter), 1fr) [full-end];
}

.site-main > *,
.entry > *,
.entry-content > * {
	grid-column: content;
	min-width: 0;
}

.site-main > .alignwide,
.entry > .alignwide,
.entry-content > .alignwide {
	grid-column: wide;
}

.site-main > .alignfull,
.entry > .alignfull,
.entry-content > .alignfull,
.site-main > .entry,
.entry > .entry-content,
.entry > .hero-image {
	grid-column: full;
}

.alignleft {
	float: left;
	margin: 0 var(--wp--preset--spacing--30) var(--wp--preset--spacing--20) 0;
}

.alignright {
	float: right;
	margin: 0 0 var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
}

.aligncenter {
	margin-inline: auto;
}


/* ============================================================================
   4. ACCESSIBILITY
   ========================================================================= */

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	top: 0;
	left: 0;
	z-index: calc(var(--shyft-z-overlay) + 10);
}

.skip-link:focus {
	position: fixed;
	width: auto;
	height: auto;
	padding: 1rem 1.5rem;
	margin: 0;
	overflow: visible;
	clip-path: none;
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--ink);
	box-shadow: var(--shyft-shadow-md);
}


/* ============================================================================
   5. SITE HEADER

   Sticky and translucent over the page, as per the design. navigation.js adds
   .scrolled to <body> once the page moves, which firms up the bottom hairline.
   ========================================================================= */

.site-header {
	position: sticky;
	top: 0;
	z-index: var(--shyft-z-header);
	border-bottom: 1px solid var(--shyft-line-soft);
	transition: border-color var(--shyft-transition);
}

/*
 * The frosted panel lives on a pseudo-element, not on the header itself.
 *
 * backdrop-filter makes an element a containing block for position: fixed
 * descendants — with it on the header, the off-canvas drawer inside was being
 * sized and clipped to the header's own 84px box instead of the viewport.
 */
.site-header::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: color-mix(in srgb, var(--wp--preset--color--base) 82%, transparent);
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
}

body.scrolled .site-header {
	border-bottom-color: var(--shyft-line);
}

.header-container {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--30);
	padding: 1.375rem var(--shyft-gutter);
}

body.admin-bar .site-header {
	top: 32px;
}

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

/* --- Branding --- */

.site-branding {
	display: flex;
	align-items: center;
	flex-shrink: 0;
}

.site-branding img,
.custom-logo {
	height: 32px;
	width: auto;
}

.site-title {
	margin: 0;
	font-size: 1.1875rem;
	/* Haffer tops out at Medium on the sister site, so the wordmark uses 500. */
	font-weight: 500;
	/* The wordmark is set in caps regardless of how the site name is stored. */
	text-transform: uppercase;
	letter-spacing: 0.02em;
	line-height: 1;
}

.site-title a {
	display: inline-flex;
	align-items: baseline;
	gap: 3px;
	text-decoration: none;
}

.site-title__dot {
	color: var(--wp--preset--color--muted);
	font-size: 1.625rem;
	font-weight: 400;
	line-height: 0;
}

/* --- Header actions --- */

.header-actions {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-shrink: 0;
}

.header-cta {
	display: inline-block;
	padding: 0.7rem 1.375rem;
	border-radius: var(--shyft-radius);
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color var(--shyft-transition);
}

.header-cta:hover {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--white);
}

.floating-search {
	display: inline-grid;
	place-items: center;
	width: 40px;
	height: 40px;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: transparent;
	color: inherit;
	transition: background-color var(--shyft-transition);
}

.floating-search:hover {
	background: var(--wp--preset--color--surface);
}

body.search-open .floating-search,
body.search-open .mobile-menu {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

/* --- Burger --- */

.mobile-menu {
	display: inline-flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	gap: 5px;
	width: 40px;
	height: 40px;
	padding: 0;
	border: 0;
	background: transparent;
}

.mobile-menu .bar {
	width: 20px;
	height: 1.5px;
	background: currentcolor;
	transition:
		transform var(--shyft-transition),
		opacity var(--shyft-transition);
}

body.nav-open .mobile-menu .bar:nth-child(1) {
	transform: translateY(6.5px) rotate(45deg);
}

body.nav-open .mobile-menu .bar:nth-child(2) {
	opacity: 0;
}

body.nav-open .mobile-menu .bar:nth-child(3) {
	transform: translateY(-6.5px) rotate(-45deg);
}

@media (min-width: 900px) {
	.mobile-menu,
	.nav-close {
		display: none;
	}
}


/* ============================================================================
   6. PRIMARY NAVIGATION — DESKTOP
   ========================================================================= */

@media (min-width: 900px) {

	/*
	 * The nav lives outside the header in the markup (see header.php), so it is
	 * positioned back into the header row here.
	 */
	/*
	 * Centred by pinning both edges and using margin auto, NOT by
	 * translateX(-50%). A transform makes the element a containing block for
	 * every position: fixed descendant — which silently sized the mega panel to
	 * the width of the nav instead of the viewport, so a full-bleed panel could
	 * never be full bleed. Nothing here may reintroduce a transform.
	 */
	.site-navigation {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		width: fit-content;
		margin-inline: auto;
		height: var(--shyft-header-h, 5.25rem);
		display: flex;
		align-items: center;
		/* Above the header bar, so triggers stay hoverable over the mega panel. */
		z-index: calc(var(--shyft-z-header) + 1);
	}

	body.admin-bar .site-navigation {
		top: 32px;
	}

	.site-navigation .menu {
		display: flex;
		align-items: center;
		gap: clamp(1.5rem, 3vw, 2.75rem);
	}

	.site-navigation .menu > li {
		position: relative;
	}

	.site-navigation .menu > li > a {
		display: inline-block;
		padding: 0.375rem 0.125rem;
		font-size: var(--wp--preset--font-size--small);
		font-weight: 400;
		color: color-mix(in srgb, var(--wp--preset--color--ink) 80%, var(--wp--preset--color--base));
		text-decoration: none;
		transition: color var(--shyft-transition);
	}

	.site-navigation .menu > li > a::after {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		bottom: -2px;
		height: 1px;
		background: var(--wp--preset--color--ink);
		transform: scaleX(0);
		transition: transform var(--shyft-transition);
	}

	.site-navigation .menu > li:hover > a,
	.site-navigation .menu > li:focus-within > a {
		color: var(--wp--preset--color--ink);
	}

	.site-navigation .menu > li:hover > a::after,
	.site-navigation .menu > li:focus-within > a::after,
	.site-navigation .menu > li.current-menu-item > a::after,
	.site-navigation .menu > li.current-menu-ancestor > a::after {
		transform: scaleX(1);
	}

	/* Plain (non-mega) dropdowns. */
	.site-navigation .sub-menu {
		position: absolute;
		top: 100%;
		left: 0;
		display: none;
		min-width: 220px;
		padding: 1rem;
		background: var(--wp--preset--color--base);
		border: 1px solid var(--shyft-line);
		box-shadow: var(--shyft-shadow-md);
	}

	.site-navigation .menu > li:hover > .sub-menu,
	.site-navigation .menu > li:focus-within > .sub-menu {
		display: block;
	}
}


/* ============================================================================
   7. MEGA PANEL

   navigation.js pins the panel below the header with an inline `top` and
   toggles .mega-open on the parent <li>.
   ========================================================================= */

@media (min-width: 900px) {

	.mega-dropdown {
		position: fixed;
		inset-inline: 0;
		top: 0;
		z-index: var(--shyft-z-mega);
		/* Equal columns for however many are present — the image column is
		   omitted when the menu item has no featured image. */
		display: grid;
		grid-auto-flow: column;
		grid-auto-columns: 1fr;
		gap: clamp(2rem, 4vw, 4rem);
		/*
		 * Full-bleed band, content on the gutter — the same inset every
		 * .shyft-section uses, so the panel's first column starts exactly where
		 * the page's copy starts underneath it.
		 */
		padding-block: clamp(2rem, 4vw, 3rem);
		padding-inline: var(--shyft-gutter);
		background: var(--wp--preset--color--base);
		border-top: 1px solid var(--shyft-line-soft);
		box-shadow: var(--shyft-shadow-md);
		opacity: 0;
		visibility: hidden;
		transform: translateY(-8px);
		pointer-events: none;
		transition:
			opacity var(--shyft-transition),
			transform var(--shyft-transition),
			visibility 0s linear 300ms;
	}

	.menu > li.mega.mega-open > .mega-dropdown {
		opacity: 1;
		visibility: visible;
		transform: translateY(0);
		pointer-events: auto;
		transition:
			opacity var(--shyft-transition),
			transform var(--shyft-transition),
			visibility 0s;
	}

	/* Invisible bridge so the pointer can cross from the trigger to the panel. */
	.mega-dropdown::before {
		content: "";
		position: absolute;
		inset-inline: 0;
		top: -24px;
		height: 24px;
	}

	.mega-col {
		display: flex;
		flex-direction: column;
		gap: var(--wp--preset--spacing--20);
		min-width: 0;
	}

	.mega-col--image img {
		width: 100%;
		aspect-ratio: 4 / 3;
		object-fit: cover;
		border-radius: var(--shyft-radius);
	}

	.mega-title {
		margin: 0;
		font-size: var(--wp--preset--font-size--x-large);
	}

	.mega-desc {
		margin: 0;
		font-size: var(--wp--preset--font-size--small);
		color: var(--wp--preset--color--muted);
	}

	.mega-links {
		display: flex;
		flex-direction: column;
	}

	.mega-link-item {
		border-bottom: 1px solid var(--shyft-line);
	}

	.mega-link-item:first-child {
		border-top: 1px solid var(--shyft-line);
	}

	.mega-link-item a {
		display: flex;
		flex-direction: column;
		gap: 0.2rem;
		padding: 0.85rem 0;
		text-decoration: none;
		transition: padding-inline-start var(--shyft-transition);
	}

	.mega-link-item a:hover {
		padding-inline-start: 0.5rem;
	}

	.mega-link-title {
		font-size: var(--wp--preset--font-size--medium);
	}

	.mega-link-desc {
		font-size: var(--wp--preset--font-size--x-small);
		color: var(--wp--preset--color--muted);
	}
}


/* ============================================================================
   8. PRIMARY NAVIGATION — MOBILE DRAWER
   ========================================================================= */

@media (max-width: 899px) {

	.site-navigation {
		position: fixed;
		inset: 0;
		/* Above the header and the page — it is a full-screen overlay. */
		z-index: calc(var(--shyft-z-backdrop) - 1);
		background: var(--wp--preset--color--base);
		transform: translateX(100%);
		visibility: hidden;
		overflow: hidden;
		transition:
			transform var(--shyft-transition-slow),
			visibility 0s linear 500ms;
	}

	.site-navigation.is-open {
		transform: translateX(0);
		visibility: visible;
		transition:
			transform var(--shyft-transition-slow),
			visibility 0s;
	}

	/*
	 * Going in: a slight overshoot, so the panel arrives rather than just stops.
	 *
	 * y1 of 1.22 carries the track a little past its target and settles back —
	 * the standard back-out curve is 1.56, which on a full-width panel reads as
	 * a wobble rather than as weight. 360ms because an overshoot needs room to
	 * settle; at the 320ms of a plain slide the bounce lands on top of the
	 * arrival and reads as a stutter.
	 *
	 * Overshooting is only safe here because the panels are transparent and the
	 * drawer behind them is the same colour, so the extra travel shows more of
	 * the same surface instead of a gap. .site-navigation clips the overflow.
	 */
	.mobile-menu-wrapper {
		display: flex;
		height: 100%;
		transition: transform 360ms cubic-bezier(0.34, 1.22, 0.64, 1);
	}

	/*
	 * Coming back: quicker, and no bounce.
	 *
	 * Going in is a reveal and can afford some character; going back is the
	 * interface getting out of the way, and it should simply be done. An
	 * overshoot here would also throw the menu past its resting edge, where
	 * there is nothing behind it to see.
	 */
	.mobile-menu-wrapper.is-returning {
		transition: transform 240ms var(--shyft-ease);
	}

	/*
	 * Promote the track to its own layer only while the drawer is open, rather
	 * than for the life of the page — a permanent will-change holds a layer in
	 * memory for something the visitor may never touch.
	 */
	.site-navigation.is-open .mobile-menu-wrapper {
		will-change: transform;
	}

	.mobile-menu-wrapper > .menu,
	.submenu-panel {
		flex: 0 0 100%;
		height: 100%;
		padding: 7rem var(--shyft-gutter) 3rem;
		overflow-y: auto;
	}

	.site-navigation .menu > li {
		position: relative;
		border-bottom: 1px solid var(--shyft-line);
	}

	.site-navigation .menu > li > a {
		display: block;
		padding: 1rem 3rem 1rem 0;
		font-size: var(--wp--preset--font-size--xx-large);
		font-weight: 300;
		letter-spacing: -0.02em;
		text-decoration: none;
	}

	/* The desktop panel markup is not used on mobile. */
	.site-navigation .mega-dropdown,
	.site-navigation .sub-menu {
		display: none;
	}

	/*
	 * The chevron is drawn on the row, not on a button beside it. A 44px target
	 * at the edge of a full-width row meant the outcome of a tap depended on
	 * where in the row it landed — arrow opened the section, anywhere else
	 * navigated away. The row is one control now, and the section's own page is
	 * the first link inside the panel.
	 */
	.site-navigation .menu > li.mega > a {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 1rem;
	}

	.site-navigation .menu > li.mega > a::after {
		content: "";
		flex: none;
		width: 18px;
		height: 18px;
		background: currentcolor;
		mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' viewBox='0 0 24 24'%3E%3Cpath d='M9 5l7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
		transition: transform 200ms var(--shyft-ease);
	}

	/* The row answers the press, like every other control on the site. */
	.site-navigation .menu > li.mega > a:active {
		transform: scale(0.99);
	}

	.site-navigation .menu > li.mega > a:active::after {
		transform: translateX(3px);
	}

	.submenu-back {
		display: inline-flex;
		align-items: center;
		gap: 0.5rem;
		margin: 0 0 1.5rem -0.125rem;
		padding: 0.5rem 0;
		border: 0;
		background: transparent;
		color: var(--wp--preset--color--muted);
		font-size: var(--wp--preset--font-size--eyebrow);
		font-weight: 500;
		letter-spacing: var(--shyft-eyebrow-tracking);
		text-transform: uppercase;
	}

	.submenu-back::before {
		content: "";
		width: 16px;
		height: 16px;
		background: currentcolor;
		mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' viewBox='0 0 24 24'%3E%3Cpath d='M15 5l-7 7 7 7'/%3E%3C/svg%3E") center / contain no-repeat;
	}

	.submenu-panel__title {
		margin: 0 0 1rem;
		font-size: var(--wp--preset--font-size--xx-large);
		font-weight: 300;
		letter-spacing: -0.02em;
	}

	/* The section's own page, set apart from the pages inside it. */
	.submenu-panel__overview a {
		font-weight: 500;
	}

	.submenu-panel .mega-link-item {
		border-bottom: 1px solid var(--shyft-line);
	}

	/*
	 * Sized and padded like the first level, not like body copy.
	 *
	 * The two panels already share an inset — both are 24px in, on the same
	 * content width. What made the sub level read as crowded against the edge
	 * was scale: the first level is xx-large and these inherited 1rem, so the
	 * same physical margin looked half the size next to type nearly twice as
	 * tall. Matching the row padding and closing most of the type gap makes the
	 * second level a sibling of the first rather than a footnote under it.
	 */
	.submenu-panel .mega-link-item a {
		display: flex;
		flex-direction: column;
		gap: 0.2rem;
		padding: 1rem 3rem 1rem 0;
		font-size: 1.5rem;
		font-weight: 300;
		letter-spacing: -0.015em;
		text-decoration: none;
	}

	/* The description stays quiet — it is the one thing that should read small. */
	.submenu-panel .mega-link-desc {
		font-size: var(--wp--preset--font-size--small);
		font-weight: 300;
		letter-spacing: 0;
		color: var(--wp--preset--color--muted);
	}

	.header-cta {
		display: none;
	}

	/* --- Close control --- */

	.nav-close {
		position: absolute;
		top: 1.375rem;
		right: var(--shyft-gutter);
		z-index: 1;
		display: grid;
		place-items: center;
		width: 44px;
		height: 44px;
		padding: 0;
		border: 0;
		background: transparent;
		color: inherit;
	}

	.nav-close__bar {
		position: absolute;
		width: 22px;
		height: 1.5px;
		background: currentcolor;
		/*
		 * Drawn in when the drawer opens: each bar grows from nothing and
		 * rotates into the cross, so the control arrives rather than appearing.
		 */
		transform: scaleX(0) rotate(0deg);
		transition:
			transform 420ms var(--shyft-ease),
			opacity 260ms var(--shyft-ease);
		opacity: 0;
	}

	.site-navigation.is-open .nav-close__bar {
		opacity: 1;
		transition-delay: 220ms;
	}

	.site-navigation.is-open .nav-close__bar:first-child {
		transform: scaleX(1) rotate(45deg);
	}

	.site-navigation.is-open .nav-close__bar:last-child {
		transform: scaleX(1) rotate(-45deg);
	}

	/* --- Header hides on the way down, returns on the way up --- */

	.site-header {
		transition:
			transform 380ms var(--shyft-ease),
			border-color var(--shyft-transition);
	}

	body.nav-hide .site-header {
		transform: translateY(-100%);
	}

	/* Never hide it out from under an open overlay. */
	body.nav-open .site-header,
	body.search-open .site-header {
		transform: translateY(0);
	}
}


/* ============================================================================
   9. SEARCH OVERLAY
   ========================================================================= */

.nav-overlay {
	position: fixed;
	inset: 0;
	z-index: var(--shyft-z-backdrop);
	background: rgb(26 26 29 / 55%);
	backdrop-filter: blur(8px);
	opacity: 0;
	pointer-events: none;
	transition: opacity var(--shyft-transition);
}

.nav-overlay.is-active {
	opacity: 1;
	pointer-events: auto;
}

/*
 * The `hidden` attribute is toggled by search.js purely to keep the overlay out
 * of the tab order. Both elements are already inert via opacity/visibility, so
 * the display mode is restored here — otherwise display:none would cancel the
 * fade transition.
 */
.nav-overlay[hidden] {
	display: block;
}

.search-overlay[hidden] {
	display: grid;
}

.search-overlay {
	position: fixed;
	inset: 0;
	z-index: var(--shyft-z-overlay);
	display: grid;
	place-items: start center;
	padding: var(--shyft-gutter);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition:
		opacity var(--shyft-transition),
		visibility 0s linear 300ms;
}

.search-overlay.is-open {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transition:
		opacity var(--shyft-transition),
		visibility 0s;
}

.search-overlay__box {
	position: relative;
	width: min(760px, 100%);
	margin-top: clamp(4rem, 14vh, 10rem);
}

.search-overlay__close {
	position: absolute;
	top: -3rem;
	right: 0;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	border: 1px solid var(--shyft-line-invert-strong);
	border-radius: 0;
	background: transparent;
	color: var(--wp--preset--color--white);
}

.search-overlay__form {
	position: relative;
	display: flex;
	align-items: center;
	min-height: 68px;
	padding-inline: 1.5rem 4.5rem;
	border-radius: var(--shyft-radius);
	background: var(--wp--preset--color--base);
	box-shadow: var(--shyft-shadow-lg);
}

.search-overlay__input {
	width: 100%;
	border: 0;
	background: transparent;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 300;
	appearance: none;
}

.search-overlay__input:focus {
	outline: none;
}

.search-overlay__submit {
	position: absolute;
	right: 1rem;
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	border: 0;
	border-radius: 0;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
}

.search-overlay__results {
	margin-top: 1rem;
	max-height: 60vh;
	overflow-y: auto;
}

.search-overlay__list {
	display: grid;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.search-item {
	position: relative;
}

.search-item__link {
	display: grid;
	gap: 0.25rem;
	padding: 1rem 6rem 1rem 1rem;
	border-radius: var(--shyft-radius);
	background: var(--wp--preset--color--base);
	text-decoration: none;
	transition: box-shadow var(--shyft-transition);
}

.search-item__link:hover {
	box-shadow: var(--shyft-shadow-md);
}

.search-item__title {
	font-weight: 500;
}

.search-item__excerpt {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.search-item__pill {
	position: absolute;
	top: 1rem;
	right: 1rem;
	padding: 0.15rem 0.6rem;
	border-radius: 0;
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--eyebrow);
}

.search-overlay__empty,
.search-overlay__summary {
	margin: 1rem 0 0;
	color: var(--wp--preset--color--white);
}


/* ============================================================================
   10. CONTENT
   ========================================================================= */

.site-main {
	padding-block: 0 var(--shyft-section-y);
	row-gap: var(--wp--preset--spacing--30);
}

/*
 * The homepage is built entirely from full-bleed sections that carry their own
 * vertical padding, so the main element adds none of its own.
 */
.home .site-main,
.site-main:has(> .entry > .entry-content > .shyft-section:first-child) {
	padding-block: 0;
	row-gap: 0;
}

.entry,
.entry-content {
	row-gap: var(--wp--preset--spacing--30);
}

/*
 * Sectioned pages — the homepage, and the inner pages built the same way —
 * carry their own vertical rhythm in .shyft-section, so the row gap that
 * separates ordinary blocks would show as a stripe of page background between
 * every band of colour.
 */
.home .entry,
.home .entry-content,
.entry:has(> .entry-content > .shyft-section:first-child),
.entry-content:has(> .shyft-section:first-child) {
	row-gap: 0;
}

/* Row gap owns the vertical rhythm between blocks, so margins would double up. */
.entry-content > * {
	margin-block: 0;
}

.page-header {
	margin-block: var(--shyft-section-y) var(--wp--preset--spacing--40);
}

.page-title,
.entry-title {
	margin: 0 0 var(--wp--preset--spacing--20);
}

.entry-meta,
.entry-terms {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.entry-footer {
	margin-top: var(--wp--preset--spacing--40);
	padding-top: var(--wp--preset--spacing--30);
	border-top: 1px solid var(--shyft-line);
}

/* --- Hero (single posts) --- */

.hero-image {
	position: relative;
	width: 100%;
	height: clamp(360px, 70vh, 720px);
	margin-bottom: var(--wp--preset--spacing--20);
	overflow: hidden;
}

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

.hero-overlay {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	padding: clamp(1.5rem, 5vw, 4rem);
	background: linear-gradient(to top, rgb(0 0 0 / 55%), transparent 60%);
	color: var(--wp--preset--color--white);
}

.hero-title {
	margin: 0;
	max-width: 20ch;
}

/* --- 404 --- */

.error-404 {
	padding-block: var(--shyft-section-y);
	text-align: center;
}

.error-404__code {
	margin: 0;
	font-size: var(--wp--preset--font-size--display);
	font-weight: 300;
	line-height: 1;
	color: var(--wp--preset--color--surface);
}

.error-404__text {
	max-width: 46ch;
	margin-inline: auto;
}

/* --- Search form --- */

.search-form {
	display: flex;
	gap: 0.5rem;
	max-width: 480px;
	margin-block: var(--wp--preset--spacing--30);
}

.error-404 .search-form {
	margin-inline: auto;
}

.search-form__field {
	flex: 1 1 auto;
	min-width: 0;
	padding: 0.75rem 1rem;
	border: 1px solid var(--shyft-line);
	border-radius: var(--shyft-radius);
	background: var(--wp--preset--color--base);
}

.no-results {
	padding-block: var(--wp--preset--spacing--40);
}


/* ============================================================================
   11. BUTTONS

   theme.json styles the default core button (ink fill). These classes cover
   the design's other four treatments and are applied via the block's
   Additional CSS class field — no inline styles anywhere.
   ========================================================================= */

.wp-block-button__link,
.search-form__submit,
.button {
	display: inline-block;
	border: 1px solid transparent;
	border-radius: var(--shyft-radius);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	transition:
		background-color var(--shyft-transition),
		border-color var(--shyft-transition),
		color var(--shyft-transition),
		opacity var(--shyft-transition),
		transform 160ms var(--shyft-ease);
}

.search-form__submit,
.button {
	padding: 0.95rem 1.75rem;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
}

.search-form__submit:hover,
.button:hover {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--white);
}

.wp-block-button__link:active,
.button:active {
	transform: scale(0.97);
}

/* Light fill — primary action on a dark section. */
.shyft-btn--light .wp-block-button__link {
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--ink);
}

.shyft-btn--light .wp-block-button__link:hover {
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--ink);
	opacity: 0.88;
}

/* Ghost — secondary action on a dark section. */
.shyft-btn--ghost .wp-block-button__link {
	background: transparent;
	border-color: var(--shyft-line-invert-strong);
	color: var(--wp--preset--color--white);
	font-weight: 400;
}

.shyft-btn--ghost .wp-block-button__link:hover {
	background: transparent;
	border-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--white);
}

/* Outline — secondary action on a light section. */
.shyft-btn--outline .wp-block-button__link {
	background: transparent;
	border-color: rgb(17 17 17 / 15%);
	color: var(--wp--preset--color--ink);
}

.shyft-btn--outline .wp-block-button__link:hover {
	background: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
}

/* Inline text link with a nudging arrow. */
.shyft-arrow-link a,
a.shyft-arrow-link {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.02em;
	text-decoration: none;
}

.shyft-arrow-link a::after,
a.shyft-arrow-link::after {
	content: "→";
	display: inline-block;
	/* A margin rather than a space in `content`, which letter-spacing swallows. */
	margin-left: 0.5em;
	transition: transform 320ms var(--shyft-ease);
}

.shyft-arrow-link a:hover::after,
a.shyft-arrow-link:hover::after {
	transform: translateX(5px);
}


/* ============================================================================
   12. CARDS, GRIDS & PAGINATION
   ========================================================================= */

.post-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr));
	gap: var(--wp--preset--spacing--40);
	margin: 0;
	padding: 0;
	list-style: none;
}

.post-card__media {
	margin: 0 0 var(--wp--preset--spacing--20);
	border-radius: var(--shyft-radius-lg);
	overflow: hidden;
}

.post-card__media img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	transition: transform var(--shyft-transition-slow);
}

.post-card:hover .post-card__media img {
	transform: scale(1.04);
}

.post-card__title {
	margin: 0 0 0.5rem;
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 500;
}

.post-card__excerpt {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

.related-posts {
	margin-top: var(--shyft-section-y);
	padding-top: var(--wp--preset--spacing--40);
	border-top: 1px solid var(--shyft-line);
}

.related-posts__title {
	margin: 0 0 var(--wp--preset--spacing--30);
}

.pagination {
	margin-top: var(--wp--preset--spacing--50);
}

.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	align-items: center;
}

.pagination .page-numbers {
	display: grid;
	place-items: center;
	min-width: 44px;
	height: 44px;
	padding-inline: 0.75rem;
	border: 1px solid var(--shyft-line);
	border-radius: var(--shyft-radius);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
}

.pagination .page-numbers.current {
	background: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
}

.pagination .page-numbers.dots {
	border-color: transparent;
}


/* ============================================================================
   13. SITE FOOTER
   ========================================================================= */

.site-footer {
	flex-shrink: 0;
	padding: 5rem var(--shyft-gutter) 2.25rem;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
}

.site-footer a {
	color: inherit;
	text-decoration: none;
	transition: opacity 250ms var(--shyft-ease);
}

.site-footer a:hover {
	color: inherit;
	opacity: 0.55;
}

.site-footer__columns {
	display: grid;
	grid-template-columns: 1.4fr repeat(3, 1fr);
	gap: 2rem;
	margin-bottom: 4rem;
}

@media (max-width: 899px) {
	.site-footer__columns {
		grid-template-columns: repeat(2, 1fr);
		gap: 2.5rem 2rem;
	}
}

@media (max-width: 559px) {
	.site-footer__columns {
		grid-template-columns: 1fr;
	}
}

.site-footer__brand {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding-right: 1.5rem;
}

.site-footer__brand .site-title {
	font-size: 1.125rem;
}

/*
 * The logo is drawn for the light header, so on the ink footer it lands as a
 * dark mark on a dark ground.
 *
 * brightness(0) first flattens it to solid black whatever colours it contains,
 * and invert(1) then lifts that to white. Inverting on its own would return the
 * mark's complement, which is only white by luck — it happens to be true for
 * today's monochrome logo and would not survive it being replaced.
 */
.site-footer__brand .custom-logo {
	filter: brightness(0) invert(1);
}

/* The fallback wordmark inherits white; only its dot names a colour of its own. */
.site-footer__brand .site-title__dot {
	color: var(--wp--preset--color--accent-soft);
}

.site-footer__tagline {
	margin: 0;
	max-width: 28ch;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	line-height: 1.6;
	color: color-mix(in srgb, var(--wp--preset--color--muted-light) 70%, var(--wp--preset--color--ink));
}

.site-footer__column {
	display: flex;
	flex-direction: column;
	gap: 1rem;
}

.site-footer__heading {
	margin: 0;
	font-size: 0.71875rem;
	font-weight: 500;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: color-mix(in srgb, var(--wp--preset--color--muted) 80%, var(--wp--preset--color--ink));
}

.footer-menu {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.footer-menu a {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	color: var(--wp--preset--color--muted-light);
}

.site-footer__bar {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 0.75rem;
	padding-top: 1.75rem;
	border-top: 1px solid var(--shyft-line-invert);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 300;
	color: color-mix(in srgb, var(--wp--preset--color--muted) 80%, var(--wp--preset--color--ink));
}

.site-footer__copyright {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.5rem;
	margin: 0;
}

/* Sits with the copyright but reads as a separate credit, not part of it. */
.site-footer__credit::before {
	content: "";
	display: inline-block;
	width: 1px;
	height: 0.8em;
	margin-right: 1.5rem;
	background: currentcolor;
	opacity: 0.3;
	vertical-align: -0.05em;
}

@media (max-width: 599px) {
	.site-footer__credit::before {
		display: none;
	}
}

.legal-menu {
	display: flex;
	gap: 1.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}


/* ============================================================================
   14. HOMEPAGE SECTIONS

   Every section is a full-width core Group block carrying .shyft-section plus
   a modifier. All spacing, colour and layout is driven from these classes so
   the block markup stays free of inline styles and fully editable.
   ========================================================================= */

.shyft-section {
	padding: var(--shyft-section-y) var(--shyft-gutter);
}

/* Eyebrow — the small tracked label above a section heading. */
.shyft-eyebrow {
	margin: 0;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: var(--shyft-eyebrow-tracking);
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
}

/* Section head — heading on the left, action button on the right. */
.shyft-section__head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: 1.5rem;
	margin-bottom: 5rem;
}

.shyft-section__head > .wp-block-group {
	display: flex;
	flex-direction: column;
	gap: 1.125rem;
	max-width: 640px;
}

.shyft-section__head .wp-block-buttons {
	margin: 0;
}

.shyft-section__head h2 {
	margin: 0;
}

/* --- Hero -----------------------------------------------------------------
 *
 * Two columns: copy on the left, the remote on the right.
 *
 * Scroll animation: navigation.js writes a 0→1 progress value to
 * --shyft-hero-p while the hero is on screen. Everything below reads that one
 * variable, so the whole effect is transform/opacity only — no layout, no
 * paint, and it degrades to the p=0 state if the script never runs.
 * ---------------------------------------------------------------------- */

.shyft-hero {
	--shyft-hero-p: 0;
	--shyft-device-x: -50%;

	/*
	 * Positioned and raised so the device can hang outside the dark panel and
	 * paint over the section beneath. Nothing here may clip: no overflow.
	 */
	position: relative;
	z-index: 1;
	/* The header is sticky and takes flow space, so subtract it to fill one screen. */
	min-height: calc(100svh - var(--shyft-header-h, 5.25rem));
	--shyft-hero-pad: clamp(5rem, 12vh, 9rem);
	padding-block: var(--shyft-hero-pad);
	display: grid;
	grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
	align-items: center;
	gap: clamp(2rem, 5vw, 5rem);
}

/* Clear the overhanging device. */
.shyft-hero + .shyft-section {
	padding-block-start: calc(var(--shyft-section-y) + var(--shyft-hero-overhang) * 0.6);
}

.shyft-hero__text {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 2.75rem;
}

.shyft-hero__text > * {
	margin: 0;
}

.shyft-hero__eyebrow {
	display: flex;
	align-items: center;
	gap: 0.875rem;
	margin: 0;
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--shyft-eyebrow-tracking);
	text-transform: uppercase;
	color: var(--wp--preset--color--muted-light);
}

.shyft-hero__eyebrow::before {
	content: "";
	width: 28px;
	height: 1px;
	background: rgb(255 255 255 / 35%);
	flex: none;
	/* Draws itself out as the hero settles. */
	transform: scaleX(calc(0.2 + (1 - var(--shyft-hero-p)) * 0.8));
	transform-origin: left center;
}

.shyft-hero h1 {
	margin: 0;
	max-width: 16ch;
	font-weight: 300;
	letter-spacing: -0.025em;
}

.shyft-hero h1 strong {
	font-weight: 500;
}

.shyft-hero__lede {
	margin: 0;
	max-width: 40ch;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 300;
	line-height: 1.6;
	color: var(--wp--preset--color--muted-light);
}

.shyft-hero .wp-block-buttons {
	gap: 0.875rem;
	margin-top: 0.75rem;
}

/* --- Device --- */

.shyft-hero__media {
	position: relative;
	/* Must span the row, or the absolute device below has no bottom to anchor to. */
	align-self: stretch;
	min-height: 0;
	perspective: 1200px;
}

/*
 * Anchored to the foot of the hero and pulled below it, so the remote breaks
 * out of the dark panel onto the section beneath.
 */
.shyft-hero__device {
	position: absolute;
	left: 40%;
	/* Past the hero's own bottom padding, then the overhang beyond its edge. */
	bottom: calc((var(--shyft-hero-overhang) + var(--shyft-hero-pad)) * -1.2);
	margin: 0;
	width: min(100%, 430px);
	/*
	 * Rises, straightens out of its tilt and grows slightly as the hero
	 * scrolls — the device presenting itself.
	 */
	transform:
		translateX(var(--shyft-device-x))
		translateY(calc(var(--shyft-hero-p) * -56px))
		rotateZ(calc((1 - var(--shyft-hero-p)) * 3deg))
		rotateY(calc((1 - var(--shyft-hero-p)) * -10deg - 4deg))
		scale(calc(1 + var(--shyft-hero-p) * 0.08));
	transform-origin: 50% 88%;
	will-change: transform;
}

/*
 * Light pool behind the remote. Widens with scroll, reading as the device
 * coming forward out of the dark.
 */
.shyft-hero__device::before {
	content: "";
	position: absolute;
	left: 50%;
	top: 42%;
	width: 190%;
	aspect-ratio: 1;
	border-radius: 50%;
	background: radial-gradient(
		circle,
		rgb(255 255 255 / 20%) 0%,
		rgb(255 255 255 / 8%) 40%,
		transparent 66%
	);
	transform:
		translate(-50%, -50%)
		scale(calc(0.85 + var(--shyft-hero-p) * 0.45));
	opacity: calc(0.6 + var(--shyft-hero-p) * 0.4);
	filter: blur(8px);
	pointer-events: none;
}

.shyft-hero__device img {
	position: relative;
	width: 100%;
	height: auto;
	/* Contact shadow, so the cut-out is not floating on nothing. */
	filter: drop-shadow(0 40px 50px rgb(0 0 0 / 45%));
}

/* Copy drifts up slightly slower than the page, and recedes as it leaves. */
.shyft-hero__text {
	transform: translateY(calc(var(--shyft-hero-p) * -34px));
	opacity: calc(1 - var(--shyft-hero-p) * 0.55);
	will-change: transform, opacity;
}

/* --- Scroll cue --- */

.shyft-hero__cue {
	position: absolute;
	left: var(--shyft-gutter);
	bottom: 2.25rem;
	display: flex;
	align-items: center;
	gap: 0.75rem;
	font-size: var(--wp--preset--font-size--eyebrow);
	letter-spacing: var(--shyft-eyebrow-tracking);
	text-transform: uppercase;
	color: var(--wp--preset--color--muted-light);
	/* Fades out the moment the visitor takes the hint. */
	opacity: calc(1 - var(--shyft-hero-p) * 4);
	pointer-events: none;
}

.shyft-hero__cue::before {
	content: "";
	width: 46px;
	height: 1px;
	background: currentcolor;
	transform-origin: left center;
	animation: shyft-cue 2.4s var(--shyft-ease) infinite;
}

@keyframes shyft-cue {
	0%, 100% { transform: scaleX(0.35); opacity: 0.4; }
	50%      { transform: scaleX(1);    opacity: 1; }
}

/* --- Responsive --- */

@media (max-width: 899px) {
	.shyft-hero {
		grid-template-columns: 1fr;
		min-height: 0;
		gap: 2.5rem;
		/* The image sits flush with the bottom of the panel now, not padded off it. */
		padding-block-end: 0;
	}

	.shyft-hero__text {
		max-width: none;
	}

	/*
	 * Back in normal flow below the text, full width, and cropped rather than
	 * shrunk to fit — the screen and nav arrows read fine on their own, and
	 * staying inside the black panel avoids all the overlap problems that came
	 * with pushing it out past the text or off the edge of the screen.
	 *
	 * A literal half (722 × 665.5 of the source's 722 × 1331) actually lands
	 * mid-way through the OPEN button below the screen — checked against the
	 * source file, its screen panel ends around y=550 and the OPEN label
	 * starts around y=571, out of 1331. 722 / 560 crops in that gap: the
	 * screen and its arrow buttons stay whole, and nothing below is cut off
	 * half-visible.
	 *
	 * .shyft-section pads every section in by --shyft-gutter on both sides —
	 * right for a heading or a button row, but it was leaving the image inset
	 * with a strip of bare panel down each side instead of reaching the edges.
	 * Cancelled out here with a matching negative margin, same trick as
	 * alignfull.
	 */
	.shyft-hero__media {
		position: relative;
		aspect-ratio: 722 / 560;
		overflow: hidden;
		margin-inline: calc(var(--shyft-gutter) * -1);
	}

	.shyft-hero__device {
		position: relative;
		left: auto;
		bottom: auto;
		width: 100%;
		margin: 0;
		/* A static crop reads oddly with a tilt fighting the hard edge below it. */
		transform: none;
	}

	.shyft-hero__device img {
		display: block;
	}

	.shyft-hero__cue {
		display: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.shyft-hero__text,
	.shyft-hero__device,
	.shyft-hero__media::before,
	.shyft-hero__eyebrow::before {
		transform: none;
		opacity: 1;
	}

	.shyft-hero__cue::before {
		animation: none;
	}
}

/* --- At a glance: four numbered columns --- */

.shyft-glance__grid {
	gap: 2.75rem;
}

.shyft-glance__grid .wp-block-column {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--shyft-line);
}

.shyft-glance__grid .wp-block-column > * {
	margin: 0;
}

.shyft-num {
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: 0.08em;
	color: var(--wp--preset--color--muted-light);
}

.shyft-glance__grid h3 {
	font-size: 1.125rem;
	font-weight: 500;
}

.shyft-glance__grid p:last-child {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	line-height: 1.65;
	color: var(--wp--preset--color--muted);
}

/* --- Split: text one side, image the other --- */

.shyft-split {
	padding: 0;
}

.shyft-split > .wp-block-columns {
	gap: 0;
	margin: 0;
	align-items: stretch;
}

.shyft-split__text {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 1.625rem;
	padding: var(--shyft-section-y) var(--shyft-gutter);
}

.shyft-split__text > * {
	margin: 0;
}

.shyft-split__text h2 {
	max-width: 14ch;
}

.shyft-split__text p {
	max-width: 46ch;
	font-weight: 300;
	line-height: 1.75;
	color: var(--wp--preset--color--muted);
}

.shyft-split__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1.5rem;
	margin-top: 0.625rem;
}

.shyft-split__actions .wp-block-buttons {
	margin: 0;
}

.shyft-split__media {
	display: flex;
	min-height: 480px;
	overflow: hidden;
	background: var(--wp--preset--color--surface);
}

.shyft-split__media figure,
.shyft-split__media .wp-block-image {
	margin: 0;
	width: 100%;
	height: 100%;
}

.shyft-split__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 800ms var(--shyft-ease);
}

.shyft-split__media:hover img {
	transform: scale(1.04);
}

@media (max-width: 899px) {
	.shyft-split__media {
		min-height: 320px;
	}
}

/* --- Gallery slider ------------------------------------------------------
 *
 * A core Gallery block with the `slider` class, rendered by
 * inc/gallery-slider.php into: a Swiper stage, an optional tab row, and a
 * detail track where only the active description is shown.
 * ---------------------------------------------------------------------- */

.shyft-gallery-slider {
	/*
	 * A plain block, deliberately. As a flex item the slider could resolve its
	 * width from its own content — three slides each asking for 100% — and end
	 * up three times too wide.
	 */
	display: block;
}

/* --- Stage --- */

.shyft-gallery-slider .shyft-slider {
	position: relative;
	width: 100%;
	min-width: 0;
	border-radius: var(--shyft-radius-lg);
	overflow: hidden;
	background: var(--wp--preset--color--white);
}

/* Pin each slide to exactly one container width. */
.shyft-gallery-slider .swiper-slide {
	flex: 0 0 100%;
	width: 100%;
	min-width: 0;
}

.shyft-gslide {
	position: relative;
	margin: 0;
	width: 100%;
}

.shyft-gslide img {
	width: 100%;
	height: clamp(320px, 42vw, 520px);
	object-fit: cover;
}

/*
 * Caption over the foot of the image.
 *
 * The design specifies a 32% black ramp, which assumes a darker photograph.
 * This runs deeper and taller so white text stays legible over a bright or
 * washed-out image too.
 */
.shyft-gslide__overlay {
	position: absolute;
	inset: auto 0 0;
	display: flex;
	flex-direction: column;
	gap: 0.375rem;
	padding: clamp(2.5rem, 6vw, 4.5rem) clamp(1.25rem, 3vw, 2.25rem) clamp(1.25rem, 3vw, 2.25rem);
	background: linear-gradient(to top, rgb(0 0 0 / 62%), rgb(0 0 0 / 28%) 55%, transparent);
	color: var(--wp--preset--color--white);
	text-shadow: 0 1px 12px rgb(0 0 0 / 35%);
	pointer-events: none;
}

.shyft-gslide__tag {
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	opacity: 0.85;
}

.shyft-gslide__label {
	font-size: clamp(1.375rem, 2.4vw, 1.75rem);
	font-weight: 500;
	letter-spacing: -0.01em;
	line-height: 1.15;
}

/* --- Tabs --- */

.shyft-gallery-slider__tabs {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 1fr;
	/* Gap between tabs, so neighbouring indicator lines read as separate rather
	   than one continuous rule broken only by colour. */
	column-gap: 1.25rem;
	/* Breathing room between the image and the tab rules beneath it. */
	margin-top: 2rem;
}

.shyft-gtab {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.5rem;
	padding: 1.375rem 1.5rem;
	border: 0;
	border-top: 2px solid var(--shyft-line);
	background: transparent;
	text-align: left;
	transition: border-color var(--shyft-transition);
}

.shyft-gtab:hover {
	border-top-color: rgb(17 17 17 / 40%);
}

/*
 * Active tab: fills in over the grey rule above, exactly the width of this
 * one tab rather than the full row, so it doubles as the autoplay progress
 * indicator instead of sitting beside a separate one.
 *
 * Sitting still, `.is-active` alone fills it in one jump — the pre-autoplay
 * behaviour, and what a click, a non-autoplay slider, or reduced motion (autoplay
 * never starts there — see the `gallery` preset in sliders.js) still get. Once
 * autoplay is running, `--shyft-progress` — set on the tab row from Swiper's
 * own `autoplayTimeLeft` tick, see sliders.js — grows it over the real dwell
 * time instead. No separate timer: the two states share one property, and
 * when Swiper's clock pauses (hover), the variable just stops changing and
 * the line holds still on its own.
 */
.shyft-gtab::before {
	content: "";
	position: absolute;
	top: -2px;
	left: 0;
	width: 100%;
	height: 2px;
	background: var(--wp--preset--color--ink);
	transform-origin: left;
	transform: scaleX(1);
	opacity: 0;
}

.shyft-gtab.is-active::before {
	opacity: 1;
}

.shyft-gallery-slider__tabs.is-autoplaying .shyft-gtab.is-active::before {
	transform: scaleX(var(--shyft-progress, 0));
}

.shyft-gtab .shyft-num {
	letter-spacing: 0.13em;
	transition: color var(--shyft-transition);
}

.shyft-gtab.is-active .shyft-num {
	color: var(--wp--preset--color--accent);
}

.shyft-gtab__label {
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 300;
	color: var(--wp--preset--color--muted);
	transition: color var(--shyft-transition);
}

.shyft-gtab.is-active .shyft-gtab__label {
	font-weight: 500;
	color: var(--wp--preset--color--ink);
}

/* --- Dots, used when no slide has a label --- */

.shyft-gallery-slider__dots {
	position: static;
	display: flex;
	justify-content: center;
	gap: 0.5rem;
	margin-top: 1.5rem;
}

.shyft-gallery-slider__dots .swiper-pagination-bullet {
	width: 7px;
	height: 7px;
	margin: 0;
	background: var(--wp--preset--color--ink);
	opacity: 0.22;
	transition: opacity var(--shyft-transition);
}

.shyft-gallery-slider__dots .swiper-pagination-bullet-active {
	opacity: 1;
}

/* --- Detail --- */

.shyft-gallery-slider__detail {
	display: grid;
	padding-top: 2.25rem;
}

/*
 * All descriptions occupy the same grid cell, so the block keeps the height of
 * the tallest and nothing shifts when slides change.
 */
.shyft-gdetail {
	grid-area: 1 / 1;
	margin: 0;
	max-width: 62ch;
	font-size: 0.96875rem;
	font-weight: 300;
	line-height: 1.75;
	color: var(--wp--preset--color--muted);
	opacity: 0;
	visibility: hidden;
	transition:
		opacity var(--shyft-transition),
		visibility 0s linear 300ms;
}

.shyft-gdetail.is-active {
	opacity: 1;
	visibility: visible;
	transition:
		opacity var(--shyft-transition),
		visibility 0s;
}

/*
 * Before Swiper initialises, the track would show every slide side by side.
 * Clip it to the first.
 */
.shyft-js .shyft-slider:not(.swiper-initialized) > .swiper-wrapper {
	overflow: hidden;
}

@media (max-width: 719px) {
	.shyft-gallery-slider__tabs {
		column-gap: 0.75rem;
	}

	.shyft-gtab {
		padding: 1rem 0.75rem;
	}

	.shyft-gtab__label {
		font-size: var(--wp--preset--font-size--small);
	}

	.shyft-gallery-slider .swiper-button-prev,
	.shyft-gallery-slider .swiper-button-next {
		display: none;
	}
}
/* --- Matter --- */

.shyft-matter > .wp-block-columns {
	gap: 4rem;
	align-items: center;
	margin: 0;
}

.shyft-matter__text {
	display: flex;
	flex-direction: column;
	gap: 1.5rem;
}

.shyft-matter__text > * {
	margin: 0;
}

.shyft-matter__text .shyft-eyebrow {
	color: var(--wp--preset--color--accent-soft);
}

.shyft-matter__text p {
	max-width: 46ch;
	font-weight: 300;
	line-height: 1.75;
	color: var(--wp--preset--color--muted-light);
}

.shyft-matter__text .wp-block-buttons {
	gap: 0.75rem;
	margin-top: 0.5rem;
}

/* Platform rows — a plain core list, styled into a table-like stack. */
.shyft-platforms {
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: 0;
	list-style: none;
}

.shyft-platforms li {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	min-width: 0;
	padding: 1.25rem 0;
	border-bottom: 1px solid var(--shyft-line-invert);
	font-size: 0.96875rem;
	font-weight: 400;
	transition: padding-left 320ms var(--shyft-ease);
}

.shyft-platforms li:hover {
	padding-left: 12px;
}

.shyft-platforms__label {
	display: flex;
	align-items: center;
	gap: 0.875rem;
	min-width: 0;
}

.shyft-platforms__icon {
	display: block;
	flex: none;
	width: 20px;
	height: 20px;
	/* The list sits on the dark panel, so the icons take the lighter grey. */
	color: var(--wp--preset--color--muted-light);
	transition: color var(--shyft-transition);
}

.shyft-platforms__icon svg {
	width: 100%;
	height: 100%;
}

.shyft-platforms li:hover .shyft-platforms__icon {
	color: inherit;
}

/* The "SUPPORTED" tag is the emphasised half of each list item. */
.shyft-platforms li em {
	font-size: 0.71875rem;
	font-style: normal;
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.shyft-matter__note {
	margin-top: 1.5rem;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 300;
	color: var(--wp--preset--color--muted);
}

/* --- Remote & feedback: sticky feature list ------------------------------
 *
 * A Gallery block with the `feature-list` class, rendered by
 * inc/feature-list.php. The image column is pinned with position: sticky, so
 * it stays put until the last feature has scrolled past — no JavaScript is
 * involved in the pinning, only in swapping which image is showing.
 * ---------------------------------------------------------------------- */

.shyft-remote__head {
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
	max-width: 600px;
	margin-bottom: 4.375rem;
}

.shyft-remote__head > * {
	margin: 0;
}

.shyft-remote__head p {
	font-weight: 300;
	line-height: 1.75;
	color: var(--wp--preset--color--muted);
}

.shyft-featurelist {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	align-items: start;
	gap: clamp(2rem, 5vw, 4rem);
}

/* --- Pinned media --- */

.shyft-featurelist__media {
	position: sticky;
	/* Clear of the sticky header, with a little air. */
	top: calc(var(--shyft-header-h, 5.25rem) + 2rem);
}

/*
 * Fills its half of the grid. The height comes from the column width, not the
 * viewport, so the frame stays portrait at every screen size — capped so it
 * still fits below the header while pinned.
 */
.shyft-featurelist__frame {
	position: relative;
	width: 100%;
	aspect-ratio: 4 / 5;
	max-height: calc(100svh - var(--shyft-header-h, 5.25rem) - 5rem);
	overflow: hidden;
	background: var(--wp--preset--color--surface);
}

/*
 * All images stacked in the same box; only the active one is opaque. Swapping
 * is a cross-fade rather than a reflow, so nothing shifts.
 */
.shyft-featurelist__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transform: scale(1.02);
	transition:
		opacity 520ms var(--shyft-ease),
		transform 700ms var(--shyft-ease);
}

.shyft-featurelist__img.is-active {
	opacity: 1;
	transform: scale(1);
}

/* --- Features --- */

.shyft-featurelist__items {
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: 0;
	list-style: none;
	/*
	 * Lead-in and trailing space.
	 *
	 * The lead-in drops the first feature to the middle of the image, so each
	 * feature in turn arrives at the same point. The trailing space is what
	 * decides how far the image can stay pinned — sized so it lets go exactly as
	 * the last feature reaches that middle.
	 *
	 * Both depend on the height of the image and of the last row, neither of
	 * which CSS can see, so feature-list.js measures them and writes these two
	 * values. The fallbacks are close enough to look right before it runs.
	 */
	padding-top: var( --shyft-list-lead, 38vh );
	padding-bottom: var( --shyft-list-tail, 30vh );
}

.shyft-featurelist__item {
	position: relative;
	padding: 2rem 0;
	border-top: 1px solid var(--shyft-line);
	cursor: pointer;
	/* The row that is not in play recedes; the current one comes forward. */
	opacity: 0.42;
	transition:
		opacity 450ms var(--shyft-ease),
		padding-left 320ms var(--shyft-ease);
}

.shyft-featurelist__item.is-active {
	opacity: 1;
}

.shyft-featurelist__item:last-child {
	border-bottom: 1px solid var(--shyft-line);
}

.shyft-featurelist__item > * {
	margin: 0;
}

/* The rule that fills in beside the active feature. */
.shyft-featurelist__item::after {
	content: "";
	position: absolute;
	left: 0;
	top: -1px;
	width: 100%;
	height: 1px;
	background: var(--wp--preset--color--ink);
	transform: scaleX(0);
	transform-origin: left center;
	transition: transform 420ms var(--shyft-ease);
}

.shyft-featurelist__item.is-active::after {
	transform: scaleX(1);
}

.shyft-featurelist__item.is-active {
	padding-left: 0.5rem;
}

.shyft-featurelist__title {
	font-size: 1.03125rem;
	font-weight: 500;
	letter-spacing: 0;
	color: var(--wp--preset--color--muted);
	transition: color var(--shyft-transition);
}

.shyft-featurelist__item.is-active .shyft-featurelist__title {
	color: var(--wp--preset--color--ink);
}

.shyft-featurelist__desc {
	margin-top: 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	line-height: 1.65;
	color: var(--wp--preset--color--muted);
}


@media (max-width: 899px) {
	/*
	 * Block, not grid.
	 *
	 * A grid item's sticky containing block is its own row, so the image would
	 * have nowhere to travel. In normal flow its containing block is the whole
	 * section, which lets it pin while the features scroll past underneath.
	 */
	.shyft-featurelist {
		display: block;
	}

	.shyft-featurelist__media {
		position: sticky;
		top: 0;
		z-index: 2;
		/*
		 * Padded clear of the header and painted with the page colour, so
		 * features pass behind the image rather than appearing above it.
		 */
		padding-top: calc(var(--shyft-header-h, 5.25rem) + 0.75rem);
		padding-bottom: 1.5rem;
		background: var(--wp--preset--color--base);
		transition: top 380ms var(--shyft-ease);
	}

	/*
	 * When the header slides away, that reserved strip is dead space. Lifting
	 * the sticky offset by the header's height carries the image up with it and
	 * takes the empty band off the top of the screen.
	 *
	 * Done with `top` rather than padding: the element still occupies its
	 * original height in flow, so nothing below it shifts.
	 */
	body.nav-hide .shyft-featurelist__media {
		top: calc(var(--shyft-header-h, 5.25rem) * -1);
	}

	/* Landscape and short, so the list still has room to read. */
	.shyft-featurelist__frame {
		aspect-ratio: 4 / 3;
		max-height: 32svh;
	}

	.shyft-featurelist__items {
		padding-top: 1.25rem;
		padding-bottom: 3rem;
	}

	/* The measured desktop values do not apply to the stacked layout. */
	.shyft-featurelist__items {
		--shyft-list-lead: 1.25rem;
		--shyft-list-tail: 3rem;
	}

	.shyft-featurelist__item,
	.shyft-featurelist__item.is-active {
		padding-left: 2.5rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.shyft-featurelist__img {
		transform: none;
	}
}
/* --- Help: two panels split by a hairline --- */

.shyft-help > .wp-block-columns {
	gap: 0;
	margin: 0;
	align-items: stretch;
}

.shyft-help__panel {
	display: flex;
	flex-direction: column;
	gap: 1.375rem;
	padding: 0.5rem 3.5rem 0.5rem 0;
	transition: padding var(--shyft-transition-slow);
}

.shyft-help__panel > * {
	margin: 0;
}

.shyft-help__panel + .shyft-help__panel {
	padding: 0.5rem 0 0.5rem 3.5rem;
	border-left: 1px solid var(--shyft-line);
}

.shyft-help__panel h3 {
	font-size: 1.3125rem;
	font-weight: 500;
}

.shyft-help__panel p {
	max-width: 42ch;
	font-size: 0.9375rem;
	font-weight: 300;
	line-height: 1.7;
	color: var(--wp--preset--color--muted);
}

.shyft-help__panel .shyft-arrow-link {
	margin-top: 0.5rem;
}

@media (max-width: 899px) {
	.shyft-help__panel,
	.shyft-help__panel + .shyft-help__panel {
		padding: 2rem 0;
		border-left: 0;
	}

	.shyft-help__panel + .shyft-help__panel {
		border-top: 1px solid var(--shyft-line);
	}
}

/* --- Final CTA --- */

.shyft-cta {
	padding-block: var(--shyft-section-y-lg);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1.25rem;
	text-align: center;
}

.shyft-cta > * {
	margin: 0;
}

.shyft-cta p {
	max-width: 48ch;
	font-weight: 300;
	color: var(--wp--preset--color--muted-light);
}

.shyft-cta .wp-block-buttons {
	gap: 0.875rem;
	margin-top: 1rem;
	justify-content: center;
}

/*
 * Reveal on scroll — .is-in is applied by navigation.js.
 *
 * Gated behind .shyft-js, which header.php sets before first paint. Without
 * scripting the sections simply render, rather than staying invisible.
 */
.shyft-js .shyft-section {
	opacity: 0;
	transform: translateY(20px);
	transition:
		opacity 900ms var(--shyft-ease),
		transform 900ms var(--shyft-ease);
}

.shyft-js .shyft-section.is-in {
	opacity: 1;
	transform: none;
}

/*
 * Heroes are above the fold — never hide one waiting for an observer. The
 * inner-page hero runs its own entrance instead, in section 15.
 */
.shyft-js .shyft-hero,
.shyft-js .shyft-page-hero {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.shyft-js .shyft-section {
		opacity: 1;
		transform: none;
	}
}

/* --- Responsive: stack the multi-column sections --- */

@media (max-width: 899px) {
	.shyft-section__head {
		margin-bottom: 3rem;
	}

	.shyft-remote__head {
		margin-bottom: 3rem;
	}

	.shyft-matter > .wp-block-columns,
	.shyft-remote > .wp-block-columns {
		gap: 2.5rem;
	}
}


/* ============================================================================
   15. CONTENT PAGE SECTIONS

   The inner pages are built the same way as the homepage — full-width core
   Group blocks carrying .shyft-section plus a modifier — but they have to read
   as a content page rather than as the front door. Three things do that work:

     - The hero is light and only as tall as its copy, where the homepage hero
       is a full screen of charcoal with the remote hanging out of it.
     - It is closed by a hairline rather than by a change of colour, so the
       page reads as one document rather than a stack of pitches.
     - Everything below it is set on a hairline grid: information laid out to
       be read and compared, not scrolled past.
   ========================================================================= */

/* --- Inner page hero ------------------------------------------------------
 *
 * Eyebrow, title, lede. The eyebrow names the page — it is the label the
 * navigation uses — so the title is free to be a sentence rather than a slug.
 * ---------------------------------------------------------------------- */

.shyft-page-hero {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.75rem;
	/* Shorter than a section: a title block, not a screen of its own. */
	padding-block: clamp(4rem, 9vw, 7rem) clamp(3.5rem, 7vw, 5.5rem);
	border-bottom: 1px solid var(--shyft-rule);
}

.shyft-page-hero > * {
	margin: 0;
}

/* The rule before the label echoes the homepage hero's eyebrow, in ink. */
.shyft-page-hero__eyebrow {
	display: flex;
	align-items: center;
	gap: 0.875rem;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: var(--shyft-eyebrow-tracking);
	text-transform: uppercase;
	color: var(--wp--preset--color--accent);
}

.shyft-page-hero__eyebrow::before {
	content: "";
	flex: none;
	width: 28px;
	height: 1px;
	background: currentcolor;
	opacity: 0.45;
}

.shyft-page-hero h1 {
	max-width: 19ch;
	font-weight: 300;
	letter-spacing: -0.025em;
}

.shyft-page-hero__lede {
	max-width: 52ch;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 300;
	line-height: 1.7;
	color: var(--wp--preset--color--muted);
}

/*
 * The hero is on screen before any observer could fire, so it settles on load
 * instead of on scroll. Gated behind .shyft-js like every other effect, so
 * without scripting the three lines simply render.
 */
.shyft-js .shyft-page-hero > * {
	opacity: 0;
	transform: translateY(14px);
	animation: shyft-hero-rise 800ms var(--shyft-ease) forwards;
}

.shyft-js .shyft-page-hero > :nth-child(1) { animation-delay: 40ms; }
.shyft-js .shyft-page-hero > :nth-child(2) { animation-delay: 130ms; }
.shyft-js .shyft-page-hero > :nth-child(3) { animation-delay: 220ms; }
.shyft-js .shyft-page-hero > :nth-child(4) { animation-delay: 310ms; }

@keyframes shyft-hero-rise {
	to {
		opacity: 1;
		transform: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.shyft-js .shyft-page-hero > * {
		opacity: 1;
		transform: none;
		animation: none;
	}
}

/* --- Hairline grid --------------------------------------------------------
 *
 * The shared mechanism behind the two grids below. Borders live on the cells
 * (right and bottom) with the container closing the top and left edge, so the
 * table stays complete at any column count — which matters, because the count
 * is a variable the media queries reset.
 * ---------------------------------------------------------------------- */

.shyft-grid {
	--shyft-grid-cols: 3;

	display: grid;
	grid-template-columns: repeat(var(--shyft-grid-cols), minmax(0, 1fr));
	gap: 0;
	margin: 0;
	border-top: 1px solid var(--shyft-rule);
	border-left: 1px solid var(--shyft-rule);
}

.shyft-grid > * {
	display: flex;
	flex-direction: column;
	margin: 0;
	padding: clamp(1.5rem, 2.4vw, 2.25rem);
	border-right: 1px solid var(--shyft-rule);
	border-bottom: 1px solid var(--shyft-rule);
}

.shyft-grid > * > * {
	margin: 0;
}

/*
 * Column-count modifiers. Match the count to the number of items: a four-item
 * set in a three-column grid leaves a fourth cell that is empty but still
 * drawn, which reads as something failing to load.
 */
.shyft-grid--4 {
	--shyft-grid-cols: 4;
}

.shyft-grid--2 {
	--shyft-grid-cols: 2;
}

/* --- The problem: copy beside a dark panel of promises --- */

/*
 * Nothing here lays the columns out, deliberately — see the note above
 * .shyft-specs. Column widths, the gap between them and vertical alignment are
 * all native Columns block controls, and a section that overrides them in CSS
 * is a section that needs new CSS every time it is reused.
 */

.shyft-problem__text {
	display: flex;
	flex-direction: column;
	gap: 1.5rem;
}

.shyft-problem__text > * {
	margin: 0;
}

.shyft-problem__text h2 {
	max-width: 15ch;
}

.shyft-problem__text p {
	max-width: 48ch;
	font-weight: 300;
	line-height: 1.8;
	color: var(--wp--preset--color--muted);
}

/* The remote, sized off the row rather than pinned to a pixel height. */
.shyft-problem__media {
	margin: 0;
}

.shyft-problem__media img {
	width: auto;
	max-height: clamp(20rem, 42vw, 33rem);
	margin-inline: auto;
}

/* The four promises, ticked off. */
.shyft-promises {
	display: flex;
	flex-direction: column;
	gap: 1.125rem;
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
}

.shyft-promises li {
	display: flex;
	align-items: baseline;
	gap: 0.875rem;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 300;
	line-height: 1.35;
}

/*
 * The tick is a mask, not an <img> or an inline <svg>. Two things fall out of
 * that: it paints in currentcolor, so the same list reads correctly on the
 * light page and on the charcoal panel without a second rule; and it stays out
 * of the block content, so there is nothing in the editor to delete by
 * accident and adding a promise is still just adding a list item.
 *
 * Square caps rather than round — the rest of the theme has no corner radius
 * anywhere, and a rounded tick reads as borrowed from somewhere else.
 */
.shyft-promises li::before {
	content: "";
	flex: none;
	width: 0.85em;
	height: 0.85em;
	/* Baseline alignment sits the box ON the baseline; drop it to optical centre. */
	transform: translateY(0.08em);
	background: currentcolor;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 8.6 6.1 12.7 14 4' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --- Why choose SHYFT: six reasons on the hairline grid --- */

.shyft-reasons__head {
	max-width: 20ch;
	margin: 0 0 3.5rem;
}

.shyft-reasons__grid > * {
	gap: 0.875rem;
	transition: background-color var(--shyft-transition);
}

/*
 * On surface, a cell lifts towards the page ground. The fill is a variable
 * because an opaque one cannot follow the section onto a photograph — it would
 * paint over the image and take the light text with it.
 */
.shyft-reasons__grid > :hover {
	background: var(--shyft-cell-hover, var(--wp--preset--color--base));
}

.shyft-reasons__grid h3 {
	font-size: 1.125rem;
	font-weight: 500;
}

.shyft-reasons__grid p {
	max-width: 34ch;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	line-height: 1.7;
	color: var(--wp--preset--color--muted);
}

/*
 * Whole-card links.
 *
 * This grid does double duty: plain informational cards on Why SHYFT's six
 * reasons, real destinations on Support's format picker. :has() tells the two
 * apart without a modifier class — only a cell whose heading actually wraps a
 * link gets the pointer cursor and the stretched hit area, so a card with
 * nowhere to go never pretends otherwise. A card with its own inline links
 * instead (Downloads, three separate PDFs in one paragraph) is left alone
 * here on purpose — a stretched link on top of those would swallow the
 * clicks meant for the specific one under the pointer.
 */
.shyft-reasons__grid > *:has(> h3 > a) {
	position: relative;
	cursor: pointer;
}

.shyft-reasons__grid h3 a {
	color: inherit;
	text-decoration: none;
}

.shyft-reasons__grid h3 a::after {
	content: "";
	position: absolute;
	inset: 0;
}

.shyft-reasons__grid h3 a:focus-visible {
	outline: 2px solid currentcolor;
	outline-offset: 4px;
}

/* --- Technical proof: a specification list beside its heading -------------
 *
 * Deliberately not another hairline grid. The reasons above are already a wall
 * of bordered cells, and a second one directly under it reads as the same
 * section repeated — the eye files it as decoration and stops reading. Rows
 * instead of cells, with the heading moved alongside, so the page changes its
 * rhythm at the same point it changes its subject.
 *
 * The two-column arrangement is a plain Columns block with nothing overriding
 * it. Widths, gap and vertical alignment stay editor controls: the section
 * styles what its contents look like, never how the row is divided. That is
 * what lets the same section be rebuilt on another page without new CSS.
 * ---------------------------------------------------------------------- */

.shyft-proof__head {
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
}

.shyft-proof__head > * {
	margin: 0;
}

.shyft-proof__head h2 {
	max-width: 20ch;
}

/*
 * Authored exactly like .shyft-platforms — a plain core list, with the caveat
 * in an <em> — so anyone who has edited the Matter list already knows how to
 * add a line here.
 */
.shyft-specs {
	margin: 0;
	padding: 0;
	list-style: none;
}

.shyft-specs li {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1.5rem;
	min-width: 0;
	padding: 1.0625rem 0;
	border-bottom: 1px solid var(--shyft-rule);
	transition: padding-left 320ms var(--shyft-ease);
}

.shyft-specs li:first-child {
	border-top: 1px solid var(--shyft-rule);
}

.shyft-specs li:hover {
	padding-left: 12px;
}

.shyft-specs em {
	flex: none;
	font-size: var(--wp--preset--font-size--x-small);
	font-style: normal;
	font-weight: 300;
	color: var(--wp--preset--color--muted);
}

/* --- Explore: the three applications, centred --- */

.shyft-explore {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2rem;
	text-align: center;
}

.shyft-explore > * {
	margin: 0;
}

/*
 * Wide enough that the line only breaks when it genuinely has to — the
 * heading is a single short sentence and reads badly split in two.
 */
.shyft-explore h2 {
	max-width: 34ch;
}

.shyft-explore .wp-block-buttons {
	gap: 0.875rem;
	justify-content: center;
}

/* --- Specification table --------------------------------------------------
 *
 * A plain core Table block. The motor tables are the densest thing on the site
 * and the only place a real table is the right answer — everything else that
 * looks tabular is .shyft-specs or .shyft-grid.
 *
 * It scrolls inside its own container rather than squeezing: seven columns of
 * measurements have a floor below which they stop being readable, and a page
 * that scrolls sideways as a whole is worse than a table that does.
 * ---------------------------------------------------------------------- */

.shyft-table {
	margin: 0;
	overflow-x: auto;
	/* Fades the right edge while there is more table to reach. */
	overscroll-behavior-x: contain;
}

/*
 * Room above, but only when the table follows something.
 *
 * Where the head sits beside the table the column gap already separates them;
 * where it sits above — the Applications and Matter tables — there was nothing
 * between the lede and the header row at all. On the table rather than on the
 * head, so any table gets the space from whatever precedes it.
 */
.shyft-table:not(:first-child) {
	margin-top: clamp(2rem, 4vw, 3rem);
}

/*
 * Wide enough that the seven-column motor table stops wrapping "Lithium-ion"
 * and "240V AC" onto two lines. Below this it scrolls, which is the point.
 */
.shyft-table table {
	width: 100%;
	min-width: 54rem;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--small);
}

.shyft-table th,
.shyft-table td {
	padding: 1rem 1.25rem;
	border: 0;
	border-bottom: 1px solid var(--shyft-rule);
	text-align: left;
	vertical-align: top;
}

.shyft-table thead th {
	background: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	white-space: nowrap;
}

/*
 * The motor name is the row's subject — everything else is a measurement. It
 * does not get `nowrap`: table-layout: fixed splits the 864px table into seven
 * equal ~123px columns, and a name like "Curtain Battery 1.2Nm" does not fit
 * that box. Held to one line it does not shrink to fit — nowrap only stops a
 * box from wrapping, it does not widen the box — so the text visibly spilled
 * into the Application column beside it. Letting it wrap, like every other
 * column already does, keeps it inside its own cell.
 */
.shyft-table tbody th,
.shyft-table tbody td:first-child {
	width: 15%;
	font-weight: 500;
}

.shyft-table tbody td {
	color: var(--wp--preset--color--muted);
}

.shyft-table tbody tr {
	transition: background-color var(--shyft-transition);
}

.shyft-table tbody tr:hover {
	background: var(--shyft-cell-hover, var(--wp--preset--color--base));
}

.shyft-table__note {
	margin: 1.25rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 300;
	color: var(--wp--preset--color--muted);
}

/* --- FAQ ------------------------------------------------------------------
 *
 * Core Details blocks. The open/close is the browser's own — no script, keyboard
 * accessible for free, and findable by the browser's in-page search even while
 * collapsed, which a JavaScript accordion breaks.
 * ---------------------------------------------------------------------- */

.shyft-faq {
	border-top: 1px solid var(--shyft-rule);
}

.shyft-faq .wp-block-details {
	margin: 0;
	border-bottom: 1px solid var(--shyft-rule);
}

.shyft-faq summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.5rem 0;
	cursor: pointer;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 400;
	list-style: none;
	transition: padding-left 320ms var(--shyft-ease);
}

.shyft-faq summary::-webkit-details-marker {
	display: none;
}

.shyft-faq summary:hover {
	padding-left: 12px;
}

/* A plus that becomes a minus — one glyph, rotated, so nothing can desync. */
.shyft-faq summary::after {
	content: "";
	flex: none;
	width: 14px;
	height: 14px;
	background: currentcolor;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M7 0v14M0 7h14' stroke='%23000' stroke-width='1.4'/%3E%3C/svg%3E") center / contain no-repeat;
	transition: transform 320ms var(--shyft-ease);
}

.shyft-faq [open] summary::after {
	transform: rotate(45deg);
}

.shyft-faq .wp-block-details > :not(summary) {
	margin: 0 0 1.5rem;
	max-width: 68ch;
	font-weight: 300;
	line-height: 1.75;
	color: var(--wp--preset--color--muted);
}

/* --- Legal pages: plain long-form prose --- */

.shyft-legal {
	display: flex;
	flex-direction: column;
	gap: 1.25rem;
	max-width: 68ch;
}

.shyft-legal > * {
	margin: 0;
}

.shyft-legal h2 {
	margin-top: 1rem;
	font-size: 1.25rem;
	font-weight: 500;
}

.shyft-legal p,
.shyft-legal li {
	font-weight: 300;
	line-height: 1.75;
	color: var(--wp--preset--color--muted);
}

.shyft-legal ul {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	padding-left: 1.25rem;
}

/* --- Numbered steps --- */

.shyft-steps {
	margin: 0;
	padding: 0;
	list-style: none;
	counter-reset: shyft-step;
}

.shyft-steps li {
	display: flex;
	align-items: baseline;
	gap: 1.25rem;
	padding: 1.0625rem 0;
	border-bottom: 1px solid var(--shyft-rule);
}

/* Generated, so inserting a step in the editor renumbers the rest. */
.shyft-steps li::before {
	counter-increment: shyft-step;
	content: counter(shyft-step, decimal-leading-zero);
	flex: none;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: 0.08em;
	color: var(--wp--preset--color--muted);
}

/* --- Category cards: an image, a title over it --------------------------- */

.shyft-cards {
	display: grid;
	grid-template-columns: repeat(var(--shyft-cards-cols, 3), minmax(0, 1fr));
	gap: 1px;
	margin: 0;
}

.shyft-cards .wp-block-image,
.shyft-cards figure {
	margin: 0;
}

/*
 * Charcoal underneath, so a card whose image has not been set yet is still a
 * legible card rather than white text on the page background.
 */
.shyft-cards > * {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	min-height: clamp(22rem, 42vw, 34rem);
	/* Core's flow layout margins every child but the first, which inside a grid
	 * pushes cards 2 and 3 down their own cells and knocks the row out of line. */
	margin: 0;
	padding: 2rem;
	overflow: hidden;
	background: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--white);
}

.shyft-cards > * > * {
	position: relative;
	z-index: 2;
	margin: 0;
}

.shyft-cards img {
	position: absolute;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--shyft-transition-slow);
}

/* Reads the title whatever the photograph is doing behind it. */
.shyft-cards > *::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(to top, rgb(17 17 17 / 78%) 0%, rgb(17 17 17 / 30%) 45%, rgb(17 17 17 / 8%) 100%);
}

.shyft-cards > :hover img {
	transform: scale(1.04);
}

.shyft-cards h3 {
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 300;
	letter-spacing: -0.02em;
}

/*
 * theme.json colours links ink, which is right everywhere except on top of a
 * photograph — there it put a near-black title on a near-black card. The card
 * sets the colour; the link takes it.
 */
.shyft-cards a {
	color: inherit;
	text-decoration: none;
}

/* The title is the only hit area, so it has to look like one. */
.shyft-cards a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 3;
}

.shyft-cards a:hover {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.18em;
}

.shyft-cards p {
	margin-top: 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	color: var(--wp--preset--color--muted-light);
}

/* --- Band: a closing line and its action, side by side --- */

.shyft-band {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 2rem;
}

.shyft-band__text {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	max-width: 46ch;
}

.shyft-band__text > * {
	margin: 0;
}

.shyft-band__text p {
	font-weight: 300;
	color: var(--wp--preset--color--muted-light);
}

.shyft-band .wp-block-buttons {
	margin: 0;
}

/* --- Platform guide --------------------------------------------------------
 *
 * Rendered by inc/platform-guide.php from a Group of Details blocks. Cards
 * across the top, one instruction panel below them.
 *
 * The cards are deliberately the loudest thing in the section: choosing a
 * platform is the only decision on this part of the page, and everything below
 * depends on having made it. They are sized and weighted to be read as buttons
 * from across the room, not as a row of links.
 * ---------------------------------------------------------------------- */

/*
 * Same hairline mechanism as .shyft-grid: borders on the cells, container
 * closing the top and left. A 1px gap over a coloured container would have
 * worked on the light page, but the cards are translucent on a photograph and
 * the container's own hairline colour showed straight through them.
 */
.shyft-guide__cards {
	display: grid;
	grid-template-columns: repeat(var(--shyft-guide-cols, 4), minmax(0, 1fr));
	gap: 0;
	margin-bottom: clamp(2.5rem, 5vw, 4rem);
	border-top: 1px solid var(--shyft-rule);
	border-left: 1px solid var(--shyft-rule);
}

/*
 * Both fills are variables so the cards follow the guide onto a dark panel or a
 * Cover without a second set of rules — see "Sections on a photograph".
 */
.shyft-guide__card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.75rem;
	padding: clamp(1.5rem, 2.6vw, 2.25rem);
	border: 0;
	border-right: 1px solid var(--shyft-rule);
	border-bottom: 1px solid var(--shyft-rule);
	border-radius: 0;
	background: var(--shyft-card-bg, var(--wp--preset--color--base));
	color: inherit;
	font: inherit;
	text-align: left;
	text-decoration: none;
	cursor: pointer;
	transition:
		background-color var(--shyft-transition),
		color var(--shyft-transition);
}

.shyft-guide__card:hover {
	background: var(--shyft-card-bg-hover, var(--wp--preset--color--surface-soft));
	color: inherit;
}

/*
 * The chosen card inverts. A tint would be ambiguous next to the hover state —
 * this has to be readable at a glance from anywhere on the page, because it is
 * the only thing saying which set of instructions is on screen.
 */
.shyft-guide__card.is-active,
.shyft-guide__card.is-active:hover {
	background: var(--shyft-card-bg-active, var(--wp--preset--color--ink));
	color: var(--shyft-card-fg-active, var(--wp--preset--color--white));
}

.shyft-guide .shyft-platforms__icon {
	width: 40px;
	height: 40px;
	color: var(--wp--preset--color--accent);
	transition: color var(--shyft-transition);
}

.shyft-guide__card.is-active .shyft-platforms__icon {
	color: inherit;
}

/*
 * Before the script runs — and for good if it never does — the guide is the
 * native accordion the server sent. The summary still gets the icon and the
 * two-part label, laid out as a row rather than a card.
 */
.shyft-guide summary {
	display: flex;
	align-items: center;
	gap: 0.875rem;
	padding: 1.25rem 0;
	border-bottom: 1px solid var(--shyft-rule);
	cursor: pointer;
	list-style: none;
}

.shyft-guide summary::-webkit-details-marker {
	display: none;
}

.shyft-guide summary .shyft-guide__meta {
	margin-left: auto;
}

.shyft-guide__name {
	font-size: 1.0625rem;
	font-weight: 500;
	line-height: 1.3;
}

.shyft-guide__meta {
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 300;
	line-height: 1.45;
	color: var(--wp--preset--color--muted);
	transition: color var(--shyft-transition);
}

.shyft-guide__card.is-active .shyft-guide__meta {
	color: var(--wp--preset--color--muted-light);
}

/* --- Panels --- */

/*
 * The platform's mark at size in its own column, instructions beside it. The
 * mark is the fastest confirmation that the steps on screen are the ones asked
 * for — faster than re-reading the selected card — and it fills a column the
 * instructions were never going to use.
 */
.shyft-guide__panel {
	display: grid;
	grid-template-columns: minmax(0, clamp(22rem, 38vw, 32rem)) minmax(0, 1fr);
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
}

/* `hidden` has to beat the grid display above. */
.shyft-guide__panel[hidden] {
	display: none;
}

/*
 * Landscape rather than square. At this width a 1:1 tile stands a good deal
 * taller than the instructions beside it, which leaves the column it was meant
 * to balance looking short instead. 4:3 lands close to the height of a typical
 * set of steps, and is the ratio a real photograph would most likely arrive in.
 */
.shyft-guide__panel-media {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 4 / 3;
	border: 1px solid var(--shyft-rule);
	background: var(--shyft-media-bg, var(--wp--preset--color--surface-soft));
}

.shyft-guide__panel-media .shyft-platforms__icon {
	width: 40%;
	height: auto;
	aspect-ratio: 1;
	color: inherit;
}

/*
 * Each mark publishes its own weight as --shyft-icon-sw, in its own viewBox
 * units, because the marks do not share a viewBox — see shyft_platform_icon().
 * Scaling that number rather than setting an absolute one is what lets a single
 * rule thin every mark by the same proportion at seven times the size, where a
 * stroke that scaled with the artwork would draw like a marker pen.
 */
.shyft-guide__panel-media svg {
	stroke-width: calc(var(--shyft-icon-sw, 1.4) * 0.45);
}

.shyft-guide__panel-body > * {
	margin-block: 0 1.25rem;
	max-width: 60ch;
}

.shyft-guide__panel-body > :last-child {
	margin-bottom: 0;
}

/* Focus lands here on selection; it should not draw a ring for a mouse user. */
.shyft-guide__panel:focus {
	outline: none;
}

@media (max-width: 899px) {
	.shyft-guide__cards {
		--shyft-guide-cols: 2;
	}

	/*
	 * The mark stops being a column and becomes a band above the steps. A square
	 * tile the width of a phone would push the instructions off the screen.
	 */
	.shyft-guide__panel {
		grid-template-columns: minmax(0, 1fr);
		gap: 2rem;
	}

	.shyft-guide__panel-media {
		aspect-ratio: auto;
		height: 8rem;
	}

	.shyft-guide__panel-media .shyft-platforms__icon {
		width: auto;
		height: 60%;
		aspect-ratio: 1;
	}
}

@media (max-width: 479px) {
	.shyft-guide__cards {
		--shyft-guide-cols: 1;
	}
}

/* --- Section nav ----------------------------------------------------------
 *
 * Printed under the hero of any page that has siblings, by
 * shyft_add_section_nav(). Two jobs: name the section you are in and get you
 * back up to it, and put the sibling pages one tap away.
 * ---------------------------------------------------------------------- */

.shyft-section-nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1.25rem;
	margin-top: 0.75rem;
}

/* Reads as "up a level", which is what the arrow direction is doing. */
.shyft-section-nav__parent {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: var(--shyft-eyebrow-tracking);
	text-transform: uppercase;
	text-decoration: none;
	color: var(--wp--preset--color--muted);
	transition: color 200ms var(--shyft-ease);
}

.shyft-section-nav__parent::before {
	content: "←";
	transition: transform 200ms var(--shyft-ease);
}

@media (hover: hover) and (pointer: fine) {
	.shyft-section-nav__parent:hover {
		color: var(--wp--preset--color--ink);
	}

	.shyft-section-nav__parent:hover::before {
		transform: translateX(-4px);
	}
}

/* The page you are already on: shown, but not offered as somewhere to go. */
.shyft-chips li.is-current {
	background: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
	cursor: default;
}

@media (max-width: 599px) {
	.shyft-section-nav {
		gap: 1rem;
	}

	/* Siblings stay side by side here — they are two words each, not a list. */
	.shyft-section-nav .shyft-chips li {
		flex: 0 1 auto;
	}
}

/* --- Chips: a set of quick entry points ----------------------------------
 *
 * For a run of short links that are destinations rather than things to be
 * compared — support topics, filters, categories. Deliberately not the hairline
 * grid: a grid says "read these cells against each other", and twelve support
 * topics are a list you scan for the one you came for.
 *
 * Authored like the rest of the theme's lists — a plain core list, link first,
 * tag in an <em>.
 * ---------------------------------------------------------------------- */

.shyft-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.625rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The list item is the chip, not the link. That keeps the authoring identical
 * to every other list in the theme — `<li>Label <em>tag</em></li>`, with the
 * link only around the label — while the whole chip stays clickable via the
 * stretched pseudo-element below.
 */
.shyft-chips li {
	position: relative;
	display: inline-flex;
	align-items: baseline;
	gap: 0.625rem;
	padding: 0.8125rem 1.125rem;
	border: 1px solid var(--shyft-rule);
	background: var(--shyft-chip-bg, var(--wp--preset--color--base));
	font-size: 0.9375rem;
	/*
	 * Named properties, never `all` — and the press is quicker than the hover,
	 * because the press is the interface answering and the hover is only it
	 * noticing. --shyft-ease is already the strong ease-out curve.
	 */
	transition:
		background-color 200ms var(--shyft-ease),
		border-color 200ms var(--shyft-ease),
		color 200ms var(--shyft-ease),
		transform 160ms var(--shyft-ease);
}

.shyft-chips a {
	color: inherit;
	text-decoration: none;
}

/* Makes the whole chip the hit area without nesting the tag inside the link. */
.shyft-chips a::after {
	content: "";
	position: absolute;
	inset: 0;
}

/*
 * Gated: a touch device fires hover on tap, so an ungated hover state sticks
 * to the last chip tapped and reads as a wrong selection.
 */
@media (hover: hover) and (pointer: fine) {
	.shyft-chips li:hover {
		background: var(--wp--preset--color--ink);
		border-color: var(--wp--preset--color--ink);
		color: var(--wp--preset--color--white);
	}

	.shyft-chips li:hover em {
		color: var(--wp--preset--color--muted-light);
	}
}

/* The chip has to answer the press, not wait for the page to load. */
.shyft-chips li:active {
	transform: scale(0.97);
}

/* The ring belongs on the chip, not on the few words of label inside it. */
.shyft-chips li:has(a:focus-visible) {
	outline: 2px solid currentcolor;
	outline-offset: 3px;
}

.shyft-chips a:focus-visible {
	outline: none;
}

.shyft-chips em {
	font-size: var(--wp--preset--font-size--eyebrow);
	font-style: normal;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	white-space: nowrap;
	color: var(--wp--preset--color--muted);
	transition: color 200ms var(--shyft-ease);
}

@media (max-width: 599px) {
	/* Full width once two no longer fit on a line — a ragged half-row reads as broken. */
	.shyft-chips li {
		flex: 1 1 100%;
		justify-content: space-between;
	}
}

/* --- Video cards: click-to-play YouTube thumbnails -------------------------
 *
 * inc/video-embed.php turns any YouTube Embed block into one of these — the
 * poster is a plain <img> from YouTube's static image host, so nothing else
 * loads from YouTube until a visitor actually presses play; see
 * assets/js/video-embed.js for what the click then does.
 *
 * A single embed needs nothing else. `shyft-videos` is only for laying
 * several out as a compact grid instead of one full-width card after another
 * — put it on whatever wraps them (typically a Group), and it takes over from
 * that block's own layout the way `shyft-grid` does elsewhere in the theme.
 * ---------------------------------------------------------------------- */

.shyft-videos {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 1.75rem 1.5rem;
}

.shyft-video {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	margin: 0;
}

.shyft-video__thumb {
	position: relative;
	display: block;
	width: 100%;
	aspect-ratio: 16 / 9;
	padding: 0;
	border: 0;
	background: var(--wp--preset--color--charcoal);
	cursor: pointer;
}

.shyft-video__poster {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: opacity 200ms var(--shyft-ease);
}

.shyft-video__thumb:hover .shyft-video__poster {
	opacity: 0.8;
}

/* A CSS triangle, not an icon font or an SVG — one shape, no extra request. */
.shyft-video__play {
	position: absolute;
	inset: 0;
	margin: auto;
	width: 3rem;
	height: 3rem;
	border-radius: 50%;
	background: rgb(255 255 255 / 92%);
	transition: transform 200ms var(--shyft-ease);
}

.shyft-video__play::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 54%;
	width: 0;
	height: 0;
	transform: translate(-50%, -50%);
	border-style: solid;
	border-width: 0.5rem 0 0.5rem 0.85rem;
	border-color: transparent transparent transparent var(--wp--preset--color--ink);
}

.shyft-video__thumb:hover .shyft-video__play {
	transform: scale(1.08);
}

.shyft-video__thumb:focus-visible {
	outline: 2px solid var(--wp--preset--color--ink);
	outline-offset: 4px;
}

.shyft-video__title {
	font-size: 0.9375rem;
	font-weight: 500;
	line-height: 1.4;
}

/* --- Video modal -----------------------------------------------------------
 *
 * Opened by assets/js/video-embed.js on a card click. Same shape as the
 * search overlay above: a dim backdrop plus a dialog, both starting hidden,
 * `is-open` added a frame later so the fade has somewhere to animate from.
 * ---------------------------------------------------------------------- */

.video-modal[hidden] {
	display: flex;
}

.video-modal {
	position: fixed;
	inset: 0;
	z-index: var(--shyft-z-overlay);
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--shyft-gutter);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition:
		opacity var(--shyft-transition),
		visibility 0s linear 300ms;
}

.video-modal.is-open {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transition:
		opacity var(--shyft-transition),
		visibility 0s;
}

.video-modal__box {
	position: relative;
	width: min(960px, 100%);
}

.video-modal__close {
	position: absolute;
	top: -3rem;
	right: 0;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	border: 1px solid var(--shyft-line-invert-strong);
	border-radius: 0;
	background: transparent;
	color: var(--wp--preset--color--white);
}

.video-modal__frame {
	aspect-ratio: 16 / 9;
	background: var(--wp--preset--color--charcoal);
	box-shadow: var(--shyft-shadow-lg);
}

.video-modal__iframe {
	width: 100%;
	height: 100%;
	border: 0;
}

/* --- Contact --- */

.shyft-contact__panel {
	padding: clamp(1.75rem, 3vw, 2.5rem);
	background: var(--shyft-media-bg, var(--wp--preset--color--surface-soft));
}

.shyft-contact__panel > * {
	margin: 0;
}

.shyft-contact__panel .shyft-eyebrow {
	margin-bottom: 1.25rem;
}

.shyft-contact__details {
	margin: 0;
	padding: 0;
	list-style: none;
}

.shyft-contact__details li {
	padding: 0.75rem 0;
	border-bottom: 1px solid var(--shyft-rule);
	font-size: var(--wp--preset--font-size--small);
}

.shyft-contact__details li:last-child {
	border-bottom: 0;
}

.shyft-contact__details strong {
	display: block;
	margin-bottom: 0.125rem;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 500;
	letter-spacing: var(--shyft-eyebrow-tracking);
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

/* --- Sections on a photograph -------------------------------------------
 *
 * Drop any content-page section inside a Cover block and it re-points itself
 * for light-on-dark: hairlines flip to the inverted set, the cell hover becomes
 * a translucent wash instead of an opaque fill, and secondary text lightens.
 *
 * Keyed off `.wp-block-cover` rather than a class you have to remember, because
 * a Cover is dimmed by default — a section inside one is on a dark ground by
 * definition. `shyft-on-media` is there for the same treatment without a Cover,
 * over a dark panel of your own.
 *
 * The scrim itself is the Cover's own overlay, set from the block's Overlay
 * panel. Nothing here draws one: a second, CSS-side scrim the editor could not
 * see would fight whatever you chose there.
 * ---------------------------------------------------------------------- */

/*
 * The Cover itself, not a section inside it. An earlier version required the
 * section to be a *descendant*, so putting the class straight onto the Cover —
 * the obvious thing to do — left it light-on-dark and unreadable. Custom
 * properties and colour both inherit, so claiming the Cover covers every case:
 * section inside cover, section that IS the cover, and anything nested deeper.
 */
.wp-block-cover,
.shyft-on-media {
	--shyft-rule: var(--shyft-line-invert-strong);
	--shyft-cell-hover: rgb(255 255 255 / 7%);

	/*
	 * The platform cards follow the same switch. Selected goes to white-on-ink
	 * rather than the light version's ink-on-white — inverting towards ink on a
	 * dark ground would make the chosen card the one you cannot see.
	 */
	--shyft-card-bg: rgb(255 255 255 / 6%);
	--shyft-card-bg-hover: rgb(255 255 255 / 12%);
	--shyft-card-bg-active: var(--wp--preset--color--white);
	--shyft-card-fg-active: var(--wp--preset--color--ink);
	--shyft-media-bg: rgb(255 255 255 / 6%);
	--shyft-chip-bg: rgb(255 255 255 / 6%);

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

/*
 * Secondary text has to lighten too — `muted` is a grey chosen against the page
 * background and is close to unreadable over a dimmed photograph.
 */
.wp-block-cover .shyft-reasons__grid p,
.wp-block-cover .shyft-specs em,
.wp-block-cover .shyft-page-hero__lede,
.wp-block-cover .shyft-table__note,
.shyft-on-media .shyft-reasons__grid p,
.shyft-on-media .shyft-specs em,
.shyft-on-media .shyft-page-hero__lede,
.shyft-on-media .shyft-table__note {
	color: var(--wp--preset--color--muted-light);
}

.wp-block-cover .shyft-eyebrow,
.shyft-on-media .shyft-eyebrow {
	color: var(--wp--preset--color--accent-soft);
}

/*
 * The Cover supplies the full-bleed band, so the section inside must not add a
 * second one — its own left and right padding is the gutter, and the Cover's
 * would sit outside it.
 */
.wp-block-cover > .wp-block-cover__inner-container > .shyft-section {
	margin-inline: 0;
}

/* --- Responsive: fewer columns, never a squeezed one --- */

@media (max-width: 899px) {
	.shyft-reasons__grid {
		--shyft-grid-cols: 2;
	}

	.shyft-reasons__head {
		margin-bottom: 2.5rem;
	}
}

@media (max-width: 899px) {
	.shyft-cards {
		--shyft-cards-cols: 1;
	}
}

@media (max-width: 599px) {
	.shyft-reasons__grid {
		--shyft-grid-cols: 1;
	}

	/* Two lines rather than one squeezed row once the caveat has nowhere to go. */
	.shyft-specs li {
		flex-direction: column;
		align-items: flex-start;
		gap: 0.25rem;
	}

	.shyft-band {
		align-items: flex-start;
	}
}


/* ============================================================================
   16. EDIT LINK

   Fixed shortcut back into the editor, shown only to users who can edit what
   they are looking at. Printed by shyft_render_edit_link() in
   inc/template-functions.php.
   ========================================================================= */

.shyft-edit-link {
	position: fixed;
	right: var(--shyft-gutter);
	bottom: 1.5rem;
	z-index: var(--shyft-z-edit);
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.7rem 1.125rem;
	/*
	 * The button floats over whatever section scrolls past. The ink fill
	 * carries it on light backgrounds; the light ring keeps its edge readable
	 * on the dark ones, where the fill is nearly the same colour.
	 */
	border: 1px solid rgb(255 255 255 / 22%);
	border-radius: 0;
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	line-height: 1;
	text-decoration: none;
	box-shadow: var(--shyft-shadow-lg);
	transition:
		background-color var(--shyft-transition),
		transform var(--shyft-transition),
		opacity var(--shyft-transition);
}

.shyft-edit-link:hover {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--white);
	transform: translateY(-2px);
}

.shyft-edit-link svg {
	flex: none;
}

/* Stay out of the way while an overlay owns the screen. */
body.nav-open .shyft-edit-link,
body.search-open .shyft-edit-link {
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
}

/* Collapse to the icon on small screens, where it would cover content. */
@media (max-width: 599px) {
	.shyft-edit-link {
		padding: 0.75rem;
	}

	.shyft-edit-link__label {
		position: absolute !important;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}
}

@media print {
	.shyft-edit-link {
		display: none;
	}
}


/* ============================================================================
   17. UTILITIES
   ========================================================================= */

.is-hidden {
	display: none !important;
}

/* --- Spacing overrides ----------------------------------------------------
 *
 * Applied from a block's *Additional CSS class* field, to any block — a group,
 * a column, an image. Use them to close the gap where two sections meet and
 * their padding doubles up, which is the one case the section rhythm cannot
 * predict on its own.
 *
 * `!important` is deliberate here, and is the reason these are utilities rather
 * than components. They have to beat two things: `.shyft-section`'s own
 * padding, and the inline style core writes onto a block whenever padding is
 * set in the editor's Dimensions panel — which no selector can outrank. A
 * utility that silently loses to a value someone set in the sidebar is worse
 * than no utility at all.
 *
 * Keep this list short. Anything needed on more than a couple of pages is a
 * component, and belongs in a section above with a name that says what it is.
 * ---------------------------------------------------------------------- */

.shyft-pt-0 {
	padding-top: 0 !important;
}

.shyft-pb-0 {
	padding-bottom: 0 !important;
}

.shyft-py-0 {
	padding-block: 0 !important;
}
