/**
 * Main stylesheet.
 *
 * Table of contents:
 * 1. Fonts
 * 2. Color tokens
 * 3. Typography / type scale
 * 4. Layout
 * 5. Nav menu
 * 6. Intro
 * 7. Clients
 * 8. About
 * 9. Client overlay
 * 10. Footer
 */

/* ------------------------------------------------------------------ */
/* 1. Fonts                                                            */
/* Font files live in ../assets/fonts/ (paths below are relative to    */
/* this file, build/main.css).                                        */
/* ------------------------------------------------------------------ */

@font-face {
	font-family: 'Post Grotesk';
	src: url('../assets/fonts/PostGrotesk-Book.eot');
	src: url('../assets/fonts/PostGrotesk-Book.eot?#iefix') format('embedded-opentype'),
		url('../assets/fonts/PostGrotesk-Book.woff2') format('woff2'),
		url('../assets/fonts/PostGrotesk-Book.woff') format('woff'),
		url('../assets/fonts/PostGrotesk-Book.ttf') format('truetype');
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Post Grotesk';
	src: url('../assets/fonts/PostGrotesk-Bold.eot');
	src: url('../assets/fonts/PostGrotesk-Bold.eot?#iefix') format('embedded-opentype'),
		url('../assets/fonts/PostGrotesk-Bold.woff2') format('woff2'),
		url('../assets/fonts/PostGrotesk-Bold.woff') format('woff'),
		url('../assets/fonts/PostGrotesk-Bold.ttf') format('truetype');
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

/* ------------------------------------------------------------------ */
/* 2. Color tokens                                                     */
/* Black and white are the brand anchors; the three in-between steps   */
/* are linear interpolations between them, lightest step named        */
/* closest to white.                                                   */
/* ------------------------------------------------------------------ */

:root {
	--color-black: #1b1c1c;
	--color-black-2: #515252;
	--color-black-3: #888888;
	--color-black-4: #bebebe;
	--color-white: #f4f4f4;

	--font-family-base: 'Post Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
}

/* ------------------------------------------------------------------ */
/* 3. Typography / type scale                                          */
/* Base (p) is 16px, scale factor 1.75. Larger sizes get progressively */
/* tighter letter-spacing and line-height (tracking/leading tighten as */
/* type gets bigger); body copy stays open and loose for readability.  */
/* ------------------------------------------------------------------ */

:root {
	--font-size-p: 1rem; /* 16px */
	--font-size-h4: 1.75rem; /* 28px */
	--font-size-h3: 3.0625rem; /* 49px */
	--font-size-h2: 5.3594rem; /* ~85.75px */
	--font-size-h1: 9.3789rem; /* ~150px */

	--line-height-p: 1.6;
	--line-height-h4: 1.3;
	--line-height-h3: 1.2;
	--line-height-h2: 1.15;
	--line-height-h1: 1.05;

	--letter-spacing-p: 0;
	--letter-spacing-h4: -0.01em;
	--letter-spacing-h3: -0.02em;
	--letter-spacing-h2: -0.03em;
	--letter-spacing-h1: -0.04em;
}

html {
	box-sizing: border-box;
	overflow-x: hidden;
}

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

body {
	color: var(--color-black);
	background-color: var(--color-white);
	font-family: var(--font-family-base);
	font-weight: 400;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

a:visited {
	color: inherit;
}

/* text-shadow instead of -webkit-text-stroke: the stroke property
   always draws centered on the glyph outline (eating into the fill,
   which reads as ugly/too thick), whereas stacked shadows sit outside
   the glyph itself and can be made much thinner. */
a:hover {
	color: var(--color-white);
	text-shadow:
		-0.5px -0.5px 0 var(--color-black),
		0.5px -0.5px 0 var(--color-black),
		-0.5px 0.5px 0 var(--color-black),
		0.5px 0.5px 0 var(--color-black),
		0 -0.5px 0 var(--color-black),
		0 0.5px 0 var(--color-black),
		-0.5px 0 0 var(--color-black),
		0.5px 0 0 var(--color-black);
}

/* The header is fixed and out of flow, so #page needs matching top
   padding to keep from starting underneath it. build/main.js measures
   the header's real height into --header-height; the 6rem fallback
   covers the instant before that runs. */
#page {
	padding-top: var(--header-height, 6rem);
}

h1,
h2,
h3,
h4,
.h1,
.h2,
.h3,
.h4 {
	font-family: var(--font-family-base);
	font-weight: 700;
	margin: 0;
}

p {
	margin: 0;
}

h1,
.h1 {
	font-size: var(--font-size-h1);
	line-height: var(--line-height-h1);
	letter-spacing: var(--letter-spacing-h1);
}

h2,
.h2 {
	font-size: var(--font-size-h2);
	line-height: var(--line-height-h2);
	letter-spacing: var(--letter-spacing-h2);
}

h3,
.h3 {
	font-size: var(--font-size-h3);
	line-height: var(--line-height-h3);
	letter-spacing: var(--letter-spacing-h3);
}

h4,
.h4 {
	font-size: var(--font-size-h4);
	line-height: var(--line-height-h4);
	letter-spacing: var(--letter-spacing-h4);
}

p,
.p {
	font-size: var(--font-size-p);
	line-height: var(--line-height-p);
	letter-spacing: var(--letter-spacing-p);
	font-weight: 400;
}

/* ------------------------------------------------------------------ */
/* 4. Layout                                                            */
/* ------------------------------------------------------------------ */

.container {
	width: 100%;
	max-width: 90rem;
	margin-inline: auto;
	padding-inline: 2rem;
}

/* ------------------------------------------------------------------ */
/* 5. Nav menu                                                          */
/* ------------------------------------------------------------------ */

.site-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 30;
	padding-block: 1.5rem;
	background-color: transparent;
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
}

.site-header__inner {
	position: relative;
	z-index: 2;
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 2rem;
	padding-inline: 2rem;
}

.site-branding__link {
	color: var(--color-black);
	text-decoration: none;
}

/* Overrides the global a:hover text-shadow stroke (see a:hover) —
   plain grey fill, no shadow, instead of the white/stroke treatment. */
.site-branding__link:hover {
	color: var(--color-black-3);
	text-shadow: none;
}

.site-branding__name {
	font-family: var(--font-family-base);
	font-weight: 700;
	font-size: 1.25rem;
	letter-spacing: -0.01em;
	white-space: nowrap;
	flex-shrink: 0;
}

/* Positioned independently rather than as a flex child of
   .site-header__inner, since it now lives outside .site-header (see
   header.php) — needs its own fixed placement to visually sit where
   the header row used to put it. */
.main-navigation {
	position: fixed;
	top: 0;
	right: 0;
	z-index: 30;
	width: auto;
	padding: 1.5rem 2rem;
}

.main-navigation .menu-toggle {
	display: none;
}

.main-navigation ul#primary-menu,
.main-navigation ul.menu {
	display: flex;
	align-items: center;
	gap: 2rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.main-navigation ul#primary-menu li,
.main-navigation ul.menu li {
	margin: 0;
}

.main-navigation a {
	color: var(--color-black);
	text-decoration: none;
	font-size: 0.9375rem;
	letter-spacing: 0;
}

/* Overrides the global a:hover text-shadow stroke — too heavy for
   this thin, small nav type — with a plain color change instead. */
.main-navigation a:hover,
.main-navigation a:focus {
	color: var(--color-black-3);
	text-shadow: none;
}

/* Mega menu — revealed on hover/focus of the "We Back" nav link via
   :has(), so it works with the fallback nav or an admin-managed menu
   without needing extra markup on the trigger itself. */
.megamenu {
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	z-index: 2;
	padding: 2rem;
	background-color: var(--color-white);
	opacity: 0;
	visibility: hidden;
	transform: translateY(-8px);
	transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0.25s, background-color 0.3s ease;
}

/* Backdrop blurring the rest of the page behind the open mega menu —
   everything below the header, not the header itself. It's a sibling
   of .site-header (not nested inside it): .site-header's own
   backdrop-filter makes it a containing block for fixed-position
   descendants in most browsers, which was trapping this backdrop
   inside the header's own box instead of covering the viewport. */
.megamenu-backdrop {
	position: fixed;
	top: var(--header-height, 6rem);
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 10;
	background-color: rgba(27, 28, 28, 0.15);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}

/* #page rather than .site-header: nav lives outside the header now
   (see header.php), so the shared ancestor that can see both the
   trigger and the menu moved up a level. */
#page:has(
	.main-navigation a[href="#clients"]:hover,
	.main-navigation a[href="#clients"]:focus,
	.megamenu:hover
) .megamenu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
	transition: opacity 0.25s ease, transform 0.25s ease, visibility 0s linear 0s;
}

#page:has(
	.main-navigation a[href="#clients"]:hover,
	.main-navigation a[href="#clients"]:focus,
	.megamenu:hover
) .megamenu-backdrop {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.25s ease, visibility 0s linear 0s;
}

.megamenu__grid {
	display: flex;
	gap: 2rem;
	overflow-x: auto;
}

.megamenu__item {
	display: block;
	flex: 0 0 auto;
	width: 20rem;
	color: var(--color-black);
	text-decoration: none;
}

.megamenu__image {
	aspect-ratio: 4 / 3;
	overflow: hidden;
	background-color: var(--color-black-4);
	margin-bottom: 1rem;
	border-radius: 8px;
}

.megamenu__image img,
.megamenu__image-placeholder {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	filter: grayscale(0%);
	transition: filter 0.4s ease;
}

/* Hovering any item desaturates every other item's image, leaving the
   hovered one in full color — same pattern as the clients grid. */
.megamenu:hover .megamenu__item:not(:hover) .megamenu__image img {
	filter: grayscale(100%);
}

.megamenu__title {
	font-family: var(--font-family-base);
	font-weight: 700;
	font-size: var(--font-size-p);
	margin-bottom: 0.5rem;
}

/* Smaller than the global a:hover stroke (0.5px) — this title is
   bold/bigger, so it reads thick at the same offset. */
.megamenu__item:hover .megamenu__title {
	text-shadow:
		-0.35px -0.35px 0 var(--color-black),
		0.35px -0.35px 0 var(--color-black),
		-0.35px 0.35px 0 var(--color-black),
		0.35px 0.35px 0 var(--color-black),
		0 -0.35px 0 var(--color-black),
		0 0.35px 0 var(--color-black),
		-0.35px 0 0 var(--color-black),
		0.35px 0 0 var(--color-black);
}

/* ------------------------------------------------------------------ */
/* 6. Intro                                                             */
/* ------------------------------------------------------------------ */

/* Headline + lede are normal in-flow content now (see .intro__headline
   and .intro__lede below) — centered here instead of each being its
   own position: fixed overlay, so they scroll off with the rest of
   the page like anything else instead of docking into the header. */
.intro {
	position: relative;
	height: 100dvh;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}

/* Flush from top to bottom of the viewport, centered — width: auto
   lets it scale to match, keeping its aspect ratio, instead of being
   width-driven. */
.intro__mark {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	z-index: -1;
	width: auto;
	height: 100vh;
	overflow: visible;
	pointer-events: none;
}

/* Solid fill at a very low opacity reads as a faint tonal field
   rather than a line — the previous 1px stroke crossed the headline
   at the vertex and read as a stray guideline/texture noise rather
   than a mark. */
.intro__mark path {
	fill: var(--color-black);
	fill-opacity: 0.04;
	stroke: none;
}

/* "The Future," and the flip word always stack as two rows —
   flex-direction: column, not wrap, so the row gap is a real, direct
   value (gap: 0, letting each row's own line-height set the rhythm)
   instead of an accident of what happens to fit on one line. */
.intro__headline {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0;
	margin: 0;
	width: 100%;
	max-width: calc(100vw - 4rem);
	font-size: var(--font-size-h1);
	line-height: var(--line-height-h1);
	letter-spacing: var(--letter-spacing-h1);
	text-transform: capitalize;
	text-align: center;
	color: var(--color-black);
}

/* Flip word: a masked vertical slide ("departure board" style)
   through the word list — see build/main.js. .intro__flip-mask is the
   clip window (overflow: hidden); .intro__flip-track holds every word
   stacked in a column and is translated to bring the active one into
   view, sliding the outgoing word up and out while the incoming one
   enters from below. flex-direction: column + width: fit-content
   sizes the mask to the widest word automatically (no JS measurement)
   so nothing next to it reflows as words change.

   The mask's own height deliberately does NOT match each word's slot
   height in the track — those used to be the same value, which forced
   a straight tradeoff between two bugs: tight enough to keep the row
   gap normal (see --line-height-h1 below) and a glyph's own
   ascender/descender overshoot peeking through from the *next* word's
   slot, stacked directly below it, into the mask at rest. Decoupled
   instead: the mask stays tight (row gap reads normal), while each
   word gets a taller slot in the track — the extra space is
   half-leading padding around the glyph (plain CSS line-height
   centers text within a line box via half-leading automatically),
   pushing the next slot's content that much further from the mask's
   edge before it can bleed in. build/main.js's FLIP_SLOT/FLIP_MASK
   must match these two heights, and centers the mask's window on
   each slot (not aligned to the slot's own top) to actually land in
   that middle buffer zone. */
.intro__flip-mask {
	display: inline-block;
	overflow: hidden;
	height: calc( var( --line-height-h1 ) * 1em );
	line-height: var( --line-height-h1 );
	vertical-align: baseline;
}

.intro__flip-track {
	display: flex;
	flex-direction: column;
	width: fit-content;
	transition: transform 0.45s cubic-bezier( 0.4, 0, 0.2, 1 );
}

@media ( prefers-reduced-motion: reduce ) {
	.intro__flip-track {
		transition: none;
	}
}

.intro__flip-word {
	height: 1.4em;
	line-height: 1.4;
	white-space: nowrap;
}

.intro__lede {
	margin: 0;
	max-width: 36rem;
	text-align: center;
	color: var(--color-black-2);
}

/* ------------------------------------------------------------------ */
/* 7. Clients                                                           */
/* ------------------------------------------------------------------ */

.clients {
	padding-block: 6rem;
}

.clients__heading {
	max-width: 100%;
	margin-bottom: 3rem;
	font-size: var(--font-size-h2);
	line-height: var(--line-height-h2);
	letter-spacing: var(--letter-spacing-h2);
	overflow-wrap: break-word;
}

.clients__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 3rem 2rem;
}

.clients__item {
	position: relative;
}

/* Pops above .clients__hover-overlay while it's hovered, so the rest
   of the grid dims but this item's own image stays visible on top. */
.clients__item:hover {
	z-index: 16;
}

.clients__link {
	display: block;
	color: var(--color-black);
	text-decoration: none;
}

.clients__image-wrap {
	position: relative;
	overflow: hidden;
	border-radius: 16px;
	margin-bottom: 1.25rem;
}

.clients__image {
	aspect-ratio: 4 / 3;
	overflow: hidden;
	background-color: var(--color-black-4);
	border-radius: 16px;
}

/* Logo reveal on hover: no white fill — just a blurred backdrop
   (same transparent + backdrop-filter treatment as the header/footer
   glass) in the card's own rectangular shape, inset smaller than the
   card. The blur is on ::before alone (not the whole scrim) so it
   doesn't also blur the logo sitting on top of it. */
.clients__logo-scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 3rem;
	opacity: 0;
	pointer-events: none;
}

.clients__logo-scrim::before {
	content: '';
	position: absolute;
	inset: 1.5rem;
	border-radius: 16px;
	background: rgba(255, 255, 255, 0.15);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
}

.clients__item:hover .clients__logo-scrim {
	opacity: 1;
}

.clients__image img,
.clients__image-placeholder {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	filter: grayscale(0%);
	transition: filter 0.4s ease;
}

/* Hovering any project desaturates every other project's image,
   leaving the hovered one in full color. */
.clients__grid:hover .clients__item:not(:hover) .clients__image img {
	filter: grayscale(100%);
}

/* Lightbox: dims the rest of the viewport (below the header) in a
   color set per-project via the "Project Color" meta box, shown on
   hover of a client (see build/main.js). */
.clients__hover-overlay {
	position: fixed;
	top: var(--header-height, 6rem);
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 15;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}

.clients__hover-overlay.is-active {
	opacity: 0.5;
	visibility: visible;
	transition: opacity 0.3s ease, visibility 0s linear 0s;
}

.clients__title {
	font-size: var(--font-size-h4);
	line-height: var(--line-height-h4);
	letter-spacing: var(--letter-spacing-h4);
}

/* Overrides the global a:hover text-shadow stroke (see a:hover) —
   both the stacked sub-pixel offsets and a vector stroke read wrong
   at this heading's size (scattered, then too thick). Plain white
   fill with a small drop shadow instead, just enough to separate it
   from a light background. */
.clients__item:hover .clients__title {
	color: var(--color-white);
	text-shadow: 0 2px 8px rgba( 0, 0, 0, 0.35 );
}

.clients__press {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-top: 0.75rem;
}

.clients__press-pill {
	padding: 0.4rem 0.9rem;
	border: 1px solid var(--color-black-4);
	border-radius: 999px;
	font-size: 0.8125rem;
	letter-spacing: 0.01em;
	color: var(--color-black-2);
	text-decoration: none;
	transition: color 0.2s ease, border-color 0.2s ease;
}

/* Overrides the global a:hover text-shadow stroke (see a:hover) —
   too heavy for this small pill type — with a plain color change. */
.clients__press-pill:hover {
	color: var(--color-black);
	border-color: var(--color-black-2);
	text-shadow: none;
}

/* ------------------------------------------------------------------ */
/* 8. About                                                             */
/* ------------------------------------------------------------------ */

.about {
	padding-block: 6rem;
}

.about__copy {
	max-width: 42rem;
	margin-inline: auto;
	margin-bottom: 12rem;
	text-align: center;
}

/* Founders stack one below the other (not side by side) — each one's
   own image + body run horizontal instead (see .about__founder). */
.about__founders {
	display: flex;
	flex-direction: column;
	gap: 4rem;
}

/* width: fit-content + margin-inline: auto — sized to its own content
   (image + gap + the body's own 45ch, not stretched to the container's
   full width) so the pair centers as one block instead of the image
   sitting pinned to the left edge. */
.about__founder {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	gap: 4rem;
	width: fit-content;
	max-width: 100%;
	margin-inline: auto;
}

.about__founder-image {
	flex: 0 0 420px;
}

.about__founder-image img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: 16px;
}

.about__founder-body {
	flex: 0 1 auto;
	min-width: 0;
	max-width: 45ch;
}

.about__founder-name {
	font-family: var(--font-family-base);
	font-weight: 700;
	font-size: var(--font-size-h4);
	line-height: var(--line-height-h4);
	letter-spacing: var(--letter-spacing-h4);
}

.about__founder-role {
	color: var(--color-black-3);
	margin-bottom: 0.75rem;
}

.about__founder-bio {
	color: var(--color-black-2);
}

.about__founder-bio + .about__founder-bio {
	margin-top: 1em;
}


.client-logo,
.wp-block-image.client-logo {
	position: relative;
	z-index: 1;
	max-width: 100%;
	max-height: 100%;
	width: auto;
}

/* ------------------------------------------------------------------ */
/* 9. Footer                                                            */
/* ------------------------------------------------------------------ */

.site-footer {
	position: relative;
	margin-top: 8rem;
	height: 100vh;
	display: flex;
	flex-direction: column;
}

/* .intro__mark is position: fixed and anchored to the viewport (see
   the Intro section above), so it still sits faintly behind the
   footer too as the page scrolls past it — no separate mark rendered
   here. */

/* Independent of .site-footer__meta's flex row on purpose — that row
   space-betweens two paragraphs of very different lengths, so tying
   this to it made alignment inconsistent. Absolutely positioned dead
   center of the (position:relative, min-height:100vh) footer instead. */
/* Plain, explicit colors below (not mix-blend-mode: difference
   auto-inverting against whatever's behind it) — that trick already
   needed disabling once on mobile for the same reason, and Safari
   hitting the identical failure (the blend silently not applying,
   leaving literal white text on the page's white background —
   invisible) confirmed it's too unreliable cross-browser to keep,
   not just a mobile quirk. The mark behind it is only ever 4% opacity
   anyway, so there was never a real dark background to invert against
   in practice. */
.site-footer__contact {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	text-align: center;
	padding: 3rem;
	background-color: transparent;
	border-radius: 16px;
}

.site-footer__contact-label {
	margin: 0;
	font-size: 0.8125rem;
	font-weight: 400;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-black-3);
}

/* Mask for the value's rise-in reveal — the link translates from
   below and this clips it out of view until it does. */
.site-footer__contact-value {
	margin: 0;
	overflow: hidden;
	font-size: var(--font-size-h4);
	line-height: var(--line-height-h4);
	letter-spacing: var(--letter-spacing-h4);
	font-weight: 700;
}

.site-footer__contact-value a {
	display: inline-block;
	color: var(--color-black);
	text-decoration: none;
}

.site-footer__contact-value a:focus {
	color: var(--color-black-4);
}

/* Overrides the global a:hover text-shadow stroke (see a:hover) —
   plain grey fill, no shadow, instead of the white/stroke treatment. */
.site-footer__contact-value a:hover {
	color: var(--color-black-3);
	text-shadow: none;
}

.site-footer__meta {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 2rem;
	padding-inline: 2rem;
	padding-bottom: 1.5rem;
	margin-top: auto;
}

.site-info {
	margin: 0;
	color: var(--color-black-3);
	font-size: var(--font-size-p);
}

/* ------------------------------------------------------------------ */
/* Mobile overrides                                                     */
/* Placed last so these reliably win the cascade against every         */
/* component rule above, regardless of where each one is defined.      */
/* ------------------------------------------------------------------ */

@media (max-width: 40em) {
	.site-main {
		width: 100%;
		overflow-x: hidden;
		margin: 0;
	}

	.clients__heading {
		font-size: clamp( 2.5rem, 12vw, 5.3594rem );
	}

	.container,
	.site-header__inner {
		padding-inline: 1.5rem;
	}

	/* Site title stays put in the header; the nav detaches into its
	   own fixed bar pinned to the bottom of the screen instead, so
	   it's always reachable like a persistent mobile nav bar. */
	.main-navigation {
		position: fixed;
		top: auto;
		left: 1.5rem;
		right: 1.5rem;
		bottom: 1.5rem;
		z-index: 30;
		padding: 1rem;
		background-color: transparent;
		backdrop-filter: blur(16px);
		-webkit-backdrop-filter: blur(16px);
		border-radius: 16px;
	}

	.main-navigation ul#primary-menu,
	.main-navigation ul.menu {
		justify-content: center;
	}

	.clients__grid,
	.about__founders {
		display: block;
	}

	.about__copy {
		margin-inline: 0;
		text-align: left;
	}

	.clients__item + .clients__item,
	.about__founder + .about__founder {
		margin-top: 3rem;
	}

	/* Row layout (see the base rule) is desktop-only — image stacked
	   above the body here instead, like it was before. */
	.about__founder {
		flex-direction: column;
	}

	.about__founder-image {
		flex: initial;
		margin-bottom: 1.25rem;
	}

	/* Stacked and centered, lifted clear of the fixed bottom nav bar
	   (nav is ~48px tall + 1.5rem inset — 4rem covers it with room to
	   spare). */
	.site-footer__meta {
		flex-direction: column;
		align-items: center;
		gap: 0;
		text-align: center;
		margin-top: 2rem;
		margin-bottom: 4rem;
	}

	/* Pulled up out of dead-center (flex-start + a modest push down for
	   the fixed header, instead of justify-content: center) — the
	   headline+lede block was centered in the full 100dvh section,
	   which left a lot of empty space above it before the mark ever
	   started. height: auto (not the base rule's 100dvh) on top of
	   that — the section no longer force-fills the viewport, so it
	   doesn't leave a second, even larger gap below the lede either,
	   between the end of its own text and wherever the Portfolio
	   section happens to start. */
	.intro {
		height: auto;
		justify-content: flex-start;
		padding-top: 10vh;
	}

	/* Left-aligned, ragged right, rather than centered — the rag
	   naturally absorbs however long "The Future," or the flip word
	   happen to be, instead of fighting to keep them centered. One
	   static font-size for the whole h1 (both rows together, not
	   fit independently) is then solved in build/main.js, sized to
	   whichever single word — checked across "The Future," and every
	   flip word, not just whatever's currently active — is the widest
	   thing it will ever need to show, so nothing it ever displays can
	   overflow. font-size here is only the pre-JS/no-JS fallback; JS
	   overrides it with a computed px value. */
	.intro__headline {
		align-items: flex-start;
		width: 100%;
		max-width: 100%;
		padding-inline: 1.5rem;
		font-size: clamp( 2.5rem, 21vw, 9.3789rem );
	}

	/* Flex items default to min-width: auto, which lets their content
	   refuse to shrink below its natural size and push past the
	   parent's own width — this overrides that so width: 100% above
	   actually has final say (matters most before JS has run). */
	.intro__headline-word,
	.intro__flip {
		min-width: 0;
		width: 100%;
		text-align: left;
		overflow-wrap: break-word;
	}

	/* Extra safety margin on top of the base rule's fit-content: with
	   a single shared font-size (see .intro__headline above) sized to
	   the list's widest word, every *shorter* word's own fit-content
	   box is narrower than the container by construction — fine on
	   its own — but pins these to 100% anyway as a hard ceiling in
	   case of any sub-pixel rounding in that JS measurement. */
	.intro__flip-mask,
	.intro__flip-track {
		width: 100%;
	}

	.intro__lede {
		width: 100%;
		max-width: 100%;
		padding-inline: 1.5rem;
		text-align: left;
	}

	/* top: 50%, matching desktop — vertically centered in the viewport,
	   not offset toward the top. */
	.intro__mark {
		position: fixed;
		top: 50%;
		left: 50%;
		transform: translate(-50%, -50%);
		z-index: -1;
		width: min(95vw, 74rem);
		height: auto;
		overflow: visible;
		pointer-events: none;
	}
}
