/* ==========================================================================
   Mouse-tracked "grid spotlight" — a cursor-following grid/glow effect used
   on the Services, Our Work, About, and Contact heroes in the source.
   Params are set per-instance via inline custom properties on the host el.
   ========================================================================== */
.mouse-grid-spotlight {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.3s ease;
	background-image:
		linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
	background-size: 30px 30px;
	-webkit-mask-image: radial-gradient(var(--spot-radius, 700px) circle at var(--mx, 50%) var(--my, 50%), black 0%, rgba(0,0,0,0.5) 40%, transparent 80%);
	mask-image: radial-gradient(var(--spot-radius, 700px) circle at var(--mx, 50%) var(--my, 50%), black 0%, rgba(0,0,0,0.5) 40%, transparent 80%);
}
.mouse-grid-spotlight.is-hovering { opacity: var(--spot-opacity, 0.8); }
.mouse-grid-spotlight--light {
	background-image:
		linear-gradient(rgba(0,0,0,0.08) 1px, transparent 1px),
		linear-gradient(90deg, rgba(0,0,0,0.08) 1px, transparent 1px);
}
.mouse-grid-spotlight__tint {
	position: absolute;
	inset: 0;
	mix-blend-mode: screen;
	opacity: 0.5;
	background: linear-gradient(135deg, var(--spot-from, #0000ff) 0%, var(--spot-to, #7000ff) 60%, transparent 100%);
}
.mouse-grid-spotlight--light .mouse-grid-spotlight__tint { mix-blend-mode: multiply; opacity: 0.7; }
.mouse-grid-spotlight__highlight {
	position: absolute;
	inset: 0;
	mix-blend-mode: overlay;
	background: radial-gradient(circle at center, rgba(255,255,255,0.06) 0%, transparent 50%);
}
.mouse-grid-spotlight--light .mouse-grid-spotlight__highlight {
	mix-blend-mode: normal;
	background: radial-gradient(circle at center, rgba(70,100,255,0.15) 0%, transparent 50%);
}

@media (prefers-reduced-motion: reduce) {
	.mouse-grid-spotlight { display: none; }
}

/* ==========================================================================
   Design tokens — ported from the React source's theme.css
   ========================================================================== */
:root {
	--font-inter: 'Inter', sans-serif;
	--font-aeroport: 'Aeroport', sans-serif;
	--font-montserrat: 'Montserrat', sans-serif;
	--font-tt-commons: 'TT Commons Pro', sans-serif;

	--color-black: #000000;
	--color-white: #ffffff;
	--color-primary: #F5A623;
	--color-primary-hover: #FFB845;
	--color-primary-active: #E98827;
	--color-primary-active-hover: #F2993D;
	--color-info: #2B5DA2; /* brand blue, used for headings/accents */
	--color-muted: #9ca3af;
	--color-border: rgba(0, 0, 0, 0.1);
	--color-border-dark: rgba(255, 255, 255, 0.1);

	--radius: 10px;
	--radius-lg: 16px;
	--radius-xl: 28px;
	--radius-full: 9999px;

	--container-max: 1290px;

	--header-height: 96px;

	--ease-reveal: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ==========================================================================
   Scroll-reveal animations — ports the React source's word-by-word
   staggered headings and fade/slide-up section entrances.
   Elements start hidden; main.js adds .is-visible via IntersectionObserver.
   ========================================================================== */
/* Scoped to span deliberately. brickweb_reveal_words() emits a
   <span class="reveal-words"> INSIDE a heading, where inline is the natural
   default anyway. Block-editor patterns instead put this class ON the heading
   so main.js can split it at runtime — and an unscoped `display: inline` there
   turns the heading into an inline box, silently dropping its vertical
   margins. That went unnoticed on pages with one heading per container and
   broke visibly on Contact, whose title is two consecutive headings. */
span.reveal-words { display: inline; }
.reveal-word {
	display: inline-block;
	/* React spaces these with mr-[0.25em] and no whitespace between the spans.
	   Relying on a literal space instead gave ~0.17em, which wrapped these
	   headings a word earlier than the original. */
	margin-right: 0.25em;
	opacity: 0;
	transform: translateY(20px);
	transition: opacity 0.7s var(--ease-reveal), transform 0.7s var(--ease-reveal);
	transition-delay: calc(var(--i, 0) * 60ms);
	will-change: transform, opacity;
}
.reveal-words.is-visible .reveal-word { opacity: 1; transform: translateY(0); }

.reveal-up, .reveal-fade, .reveal-left, .reveal-right, .reveal-scale {
	opacity: 0;
	transition: opacity 0.8s var(--ease-reveal), transform 0.8s var(--ease-reveal);
	will-change: transform, opacity;
}
.reveal-up { transform: translateY(30px); }
.reveal-left { transform: translateX(-60px); }
.reveal-right { transform: translateX(60px); }
.reveal-scale { transform: scale(0.92) translateY(16px); }
.reveal-fade { transform: none; }

.reveal-up.is-visible, .reveal-fade.is-visible,
.reveal-left.is-visible, .reveal-right.is-visible, .reveal-scale.is-visible {
	opacity: 1;
	transform: translate(0, 0) scale(1);
}

/* Stagger children of a reveal group: each direct child gets a small extra delay */
.reveal-group.is-visible > * { transition-delay: calc(var(--i, 0) * 100ms); }

@media (prefers-reduced-motion: reduce) {
	.reveal-word, .reveal-up, .reveal-fade, .reveal-left, .reveal-right, .reveal-scale {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
}

/* ==========================================================================
   Reset & base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
	margin: 0;
	font-family: var(--font-inter);
	color: var(--color-black);
	background: var(--color-white);
	-webkit-font-smoothing: antialiased;
}
/* React's app shell is `<div class="min-h-screen overflow-x-hidden">` wrapping
   its <main>, which clips horizontal bleed so the page never grows a horizontal
   scrollbar. WordPress had no equivalent, so two kinds of bleed reached the
   document: the `.reveal-*` elements' pre-reveal `translateX(±60px)` (measured
   404px of scroll width against a 360px viewport at 375px, until each element
   scrolled into view) and the decorative `.service-block` gradient blobs, whose
   rotated bounding boxes are far wider than the section on a tall mobile
   layout (measured 470px against the same 360px viewport).

   `overflow-x: clip` rather than `hidden`: clip does not make this element a
   scroll container, so `.work-filter-bar`'s `position: sticky` keeps working
   and vertical bleed still shows, which is what React's root does too (it only
   clips the X axis). Specificity 1-0-0; nothing else in this file targets
   #main-content. */
#main-content { overflow-x: clip; }

img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
ul { margin: 0; padding: 0; list-style: none; }

h1, h2, h3, h4 {
	font-family: var(--font-aeroport);
	font-weight: 700;
	line-height: 1.1;
	margin: 0;
}

/*
 * Mirrors React's Container: max-w-[1290px] mx-auto px-4, so 1258px of content
 * at any viewport past the cap. The 1.5rem override this rule used to carry at
 * >=1024px made every grid built on .container 1242px wide and 8px further
 * right than the original -- measured on Home, Services, About and Our Work.
 */
.container {
	max-width: var(--container-max);
	margin-inline: auto;
	padding-inline: 1rem;
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-height: 56px;
	padding: 0 24px;
	border-radius: var(--radius-full);
	font-family: var(--font-inter);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0.025em;
	border: 1px solid transparent;
	transition: background-color 0.3s ease, transform 0.2s ease, border-color 0.3s ease;
	white-space: nowrap;
}
.btn:hover { transform: translateY(-2px); }

.btn--primary {
	background: var(--color-primary-active);
	color: var(--color-white);
	box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1);
}
.btn--primary:hover { background: var(--color-primary-active-hover); }

.btn--secondary {
	background: var(--color-black);
	color: var(--color-white);
	padding: 0 32px;
	font-weight: 700;
	border-color: var(--color-border-dark);
	box-shadow: 0 4px 14px 0 rgba(0,0,0,0.39);
}
.btn--secondary:hover { background: rgba(0, 0, 0, 0.8); border-color: rgba(255, 255, 255, 0.2); }

/* ==========================================================================
   Site header / primary nav
   ========================================================================== */
.site-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 50;
	padding: 16px 0;
	background: transparent;
	transition: background-color 0.3s ease, padding 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease;
}

.site-header__inner {
	max-width: 1920px;
	margin-inline: auto;
	padding-inline: 1.5rem;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
}

@media (min-width: 1024px) {
	.site-header__inner { padding-inline: 4rem; }
}

/* Keep the fixed header below the WP admin toolbar when logged in. */
body.admin-bar .site-header { top: 32px; }
@media screen and (max-width: 782px) {
	body.admin-bar .site-header { top: 46px; }
}

.site-header__logo { display: block; width: 160px; flex-shrink: 0; color: var(--color-white); transition: color 0.3s ease; }
.site-header__logo .bw-logo { display: block; width: 100%; height: auto; }

.site-header__nav { display: none; }
.site-header__cta { display: none; }

@media (min-width: 1024px) {
	.site-header__nav { display: flex; align-items: center; gap: 2.5rem; }
	.site-header__cta { display: block; }
}

.nav-menu { display: flex; align-items: center; gap: 2.5rem; }
.nav-menu a {
	position: relative;
	display: inline-block;
	padding-bottom: 4px;
	font-family: var(--font-aeroport);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	font-size: 16px;
	color: var(--color-white);
	transition: color 0.3s ease;
}
@media (min-width: 1920px) { .nav-menu a { font-size: 18px; } }
.nav-menu a:hover { color: var(--color-primary); }
.nav-menu .current-menu-item > a::after {
	content: '';
	position: absolute;
	bottom: 0; left: 0; right: 0;
	height: 2px;
	background: var(--color-primary);
}

.is-light-hero .site-header:not(.is-scrolled) .nav-menu a,
.is-light-hero .site-header:not(.is-scrolled) .site-header__logo { color: var(--color-black); }

.site-header__cta .btn { min-height: 46px; color: var(--color-black); }
.is-light-hero .site-header:not(.is-scrolled) .site-header__cta .btn { color: var(--color-white); }

/* Scrolled state (JS-toggled) */
.site-header.is-scrolled {
	background: rgba(0, 0, 0, 0.85);
	backdrop-filter: blur(12px);
	padding: 8px 0;
	box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2), 0 4px 6px -2px rgba(0, 0, 0, 0.1);
}
.site-header.is-scrolled .nav-menu a,
.site-header.is-scrolled .site-header__logo { color: var(--color-white); }
.site-header.is-scrolled .site-header__cta .btn { color: var(--color-black); }
.site-header.is-hidden { transform: translateY(-120%); }

/* Mobile toggle */
.site-header__toggle {
	display: flex;
	flex-direction: column;
	gap: 6px;
	width: 40px;
	height: 40px;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
}
.site-header__toggle span {
	width: 24px;
	height: 2px;
	background: var(--color-white);
	transition: background-color 0.3s ease;
}
.is-light-hero .site-header:not(.is-scrolled) .site-header__toggle span { background: var(--color-black); }

/* The mobile overlay is solid black and sits BELOW the header (z-index 40 vs
   50), so on a light page the black toggle and logo would vanish into it the
   moment the menu opened -- leaving no visible way to close it. */
.is-light-hero.nav-open .site-header:not(.is-scrolled) .site-header__logo { color: var(--color-white); }
.is-light-hero.nav-open .site-header:not(.is-scrolled) .site-header__toggle span { background: var(--color-white); }

@media (min-width: 1024px) {
	.site-header__toggle { display: none; }
}

/* Mobile nav overlay */
.mobile-nav {
	position: fixed;
	inset: 0;
	z-index: 40;
	background: var(--color-black);
	display: none;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
.mobile-nav.is-open { display: flex; }
.mobile-nav__inner { display: flex; flex-direction: column; align-items: center; gap: 2.5rem; }
.mobile-nav__menu { display: flex; flex-direction: column; align-items: center; gap: 2.5rem; }
.mobile-nav__menu a {
	position: relative;
	display: inline-block;
	padding-bottom: 8px;
	font-size: 1.75rem;
	letter-spacing: 0.15em;
	color: var(--color-white);
	font-family: var(--font-aeroport);
}
.mobile-nav__menu a:hover { color: var(--color-primary); }
.mobile-nav__menu .current-menu-item > a::after {
	content: '';
	position: absolute;
	bottom: 0; left: 0; right: 0;
	height: 4px;
	background: var(--color-primary);
}
.mobile-nav__cta.btn { min-height: 50px; color: var(--color-black); }

body.nav-open { overflow: hidden; }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
	background: var(--color-black);
	color: var(--color-white);
	padding: 45px 1.5rem 20px;
}
@media (min-width: 768px) { .site-footer { padding-inline: 3rem; } }
@media (min-width: 1024px) { .site-footer { padding-inline: 76px; } }
.site-footer__inner {
	max-width: 56rem;
	margin-inline: auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 40px;
}
.site-footer__logo { width: 196px; }
/* display:block removes the inline descender gap under the SVG, which made
   the logo row 81px against React's fixed 77px. */
.site-footer__logo .bw-logo { display: block; width: 100%; height: auto; }
.site-footer__tagline {
	max-width: 720px;
	color: var(--color-muted);
	font-size: 0.875rem;
	line-height: 1.8;
	/* React's tagline carries mb-[32px] on top of the column's 40px gap. */
	margin: 0 0 32px;
}
@media (min-width: 768px) { .site-footer__tagline { font-size: 0.9375rem; } }

/*
 * Two menu rows, as in React's Footer.tsx: the primary links in white bold,
 * then the legal links small and muted. The theme previously had one row and
 * pointed it at the legal menu, so the site navigation was missing from the
 * footer entirely — that row plus the tagline margin was the whole 96px the
 * footer measured short.
 */
.footer-nav-menu {
	display: flex;
	flex-wrap: wrap;
	column-gap: 2.5rem;
	row-gap: 1rem;
	justify-content: center;
	align-items: center;
	/* Each li's line box is set by its own strut, not by the link. React's
	   inherits the 16px/1.5 body text, giving a 24px row; without this the
	   row collapsed to the link's own 21px. */
	line-height: 1.5;
}
@media (min-width: 768px) { .footer-nav-menu { column-gap: 3.5rem; } }
.footer-nav-menu a {
	position: relative;
	/* Left inline, as React's is: inline-block would make the 4px padding
	   occupy layout and push the row from 24px to 29px. */
	padding: 4px 0;
	font-weight: 700;
	font-size: 14px;
	line-height: 1.5;
	letter-spacing: 0.025em;
	color: var(--color-white);
	transition: color 0.3s ease;
}
.footer-nav-menu a:hover { color: var(--color-primary); }
.footer-nav-menu .current-menu-item > a::after {
	content: '';
	position: absolute;
	bottom: 0; left: 0; right: 0;
	height: 2px;
	background: var(--color-primary);
}

.footer-legal-menu {
	display: flex;
	flex-wrap: wrap;
	column-gap: 2rem;
	row-gap: 0.5rem;
	justify-content: center;
	/* Sized on the list so the strut matches the links, as React's wrapper
	   div does; sizing only the anchors left an oversized line box. */
	font-size: 0.75rem;
	line-height: 1.5;
	letter-spacing: 0.025em;
}
@media (min-width: 768px) { .footer-legal-menu { font-size: 0.8125rem; } }
.footer-legal-menu a {
	color: #6b7280;
	transition: color 0.3s ease;
}
.footer-legal-menu a:hover { color: var(--color-primary); }

.site-footer__copyright {
	color: #6b7280;
	font-size: 0.75rem;
	line-height: 1.5;
	letter-spacing: 0.025em;
	margin: 0;
}
@media (min-width: 768px) { .site-footer__copyright { font-size: 0.8125rem; } }

/* ==========================================================================
   Scroll-to-top floating button
   ========================================================================== */
.scroll-top {
	position: fixed;
	bottom: 24px;
	right: 24px;
	z-index: 100;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(11, 12, 16, 0.8);
	backdrop-filter: blur(20px);
	-webkit-backdrop-filter: blur(20px);
	border: 1px solid rgba(255, 255, 255, 0.1);
	box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 8px 10px -6px rgba(0, 0, 0, 0.3);
	color: var(--color-white);
	cursor: pointer;
	padding: 0;
	opacity: 0;
	visibility: hidden;
	transform: scale(0.5) rotate(-10deg);
	transition: opacity 0.3s ease, transform 0.3s ease, border-color 0.3s ease, background-color 0.3s ease;
}
@media (min-width: 1024px) {
	.scroll-top { width: 56px; height: 56px; bottom: 40px; right: 40px; }
}
.scroll-top.is-visible { opacity: 1; visibility: visible; transform: scale(1) rotate(0deg); }
.scroll-top:hover { transform: translateY(-4px); border-color: rgba(239, 142, 38, 0.4); background-color: #0b0c10; }

.scroll-top__ring {
	position: absolute;
	inset: -4px;
	width: calc(100% + 8px);
	height: calc(100% + 8px);
	transform: rotate(-90deg);
	pointer-events: none;
}
.scroll-top__ring-bg { fill: none; stroke: rgba(255, 255, 255, 0.05); stroke-width: 2; }
.scroll-top__ring-progress {
	fill: none;
	stroke: #ef8e26;
	stroke-width: 2;
	stroke-linecap: round;
	stroke-dasharray: 289.03;
	stroke-dashoffset: 289.03;
	transition: stroke-dashoffset 0.1s linear;
}

.scroll-top__arrow {
	position: relative;
	z-index: 1;
	display: flex;
	width: 20px;
	height: 20px;
	color: #ef8e26;
	animation: scroll-top-bounce 2s ease-in-out infinite;
}
@media (min-width: 1024px) { .scroll-top__arrow { width: 24px; height: 24px; } }
@keyframes scroll-top-bounce {
	0%, 100% { transform: translateY(0); }
	50% { transform: translateY(-4px); }
}

@media (prefers-reduced-motion: reduce) {
	.scroll-top__arrow { animation: none; }
}

/* ==========================================================================
   Marquee animation (client logos + portfolio rows)
   ========================================================================== */
@keyframes marquee {
	from { transform: translate3d(0, 0, 0); }
	to { transform: translate3d(-50%, 0, 0); }
}
@keyframes marquee-reverse {
	from { transform: translate3d(-50%, 0, 0); }
	to { transform: translate3d(0, 0, 0); }
}
.animate-marquee { animation: marquee 150s linear infinite; }
.animate-marquee-reverse { animation: marquee-reverse 150s linear infinite; }
.pause-on-hover:hover { animation-play-state: paused; }

/* ==========================================================================
   Home hero
   ========================================================================== */
.home-bg {
	background-image: url('../images/home-bg.png');
	background-attachment: fixed;
	background-size: 1290px;
	background-position: center;
	background-repeat: no-repeat;
}
.hero-home {
	position: relative;
	background: var(--color-black);
	color: var(--color-white);
	/* No side padding: React's hero section has none, the Container supplies
	   the gutter. Doubling it made the text column 32px narrower than the
	   original at every width below the 1290px cap. */
	padding: 8rem 0 5rem;
	text-align: center;
	overflow: hidden;
	min-height: 750px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
@media (min-width: 768px) { .hero-home { padding-top: 12.5rem; padding-bottom: 7rem; } }
@media (min-width: 1024px) { .hero-home { padding-bottom: 8rem; } }
.hero-home .container { position: relative; z-index: 2; }
.hero-home__title {
	font-family: var(--font-aeroport);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: -0.05em;
	font-size: 65px;
	line-height: 1;
	/*
	 * No cap, as React's. .hero-home is a centred flex column, so .container
	 * shrinks to its widest child -- a 900px cap here shrank the whole hero
	 * text column to 900 and wrapped the headline onto a fourth line. Without
	 * it the container shrink-to-fit hits its own 1290px max instead, giving
	 * React's 1258px column and a three-line headline.
	 */
	/* React steps these: mb-8 md:mb-10. */
	margin: 0 auto 2rem;
}
@media (min-width: 768px) { .hero-home__title { margin-bottom: 2.5rem; } }
.hero-home__title .accent { background: linear-gradient(to right, var(--color-primary-active), #60a5fa); -webkit-background-clip: text; background-clip: text; color: transparent; }
.hero-home__subtitle {
	font-family: var(--font-inter);
	color: rgba(255,255,255,0.7);
	font-weight: 500;
	max-width: 800px;
	/* React steps these: mb-10 md:mb-12. */
	margin: 0 auto 2.5rem;
	font-size: clamp(16px, 1.1vw, 20px);
	line-height: 1.6;
}
@media (min-width: 768px) { .hero-home__subtitle { margin-bottom: 3rem; } }
.hero-home__actions { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; align-items: center; max-width: 42rem; margin: 0 auto 3rem; }
@media (min-width: 640px) { .hero-home__actions { gap: 1.5rem; } }
.hero-home__avatars { display: inline-flex; margin-left: 0.5rem; }
.hero-home__avatars img { width: 36px; height: 36px; border-radius: 50%; border: 2.5px solid #0c2461; object-fit: cover; margin-left: -8px; }
.hero-home__avatars img:first-child { margin-left: 0; }
.hero-home__trust { color: rgba(255,255,255,0.4); font-weight: 500; text-transform: uppercase; letter-spacing: 0.02em; font-size: clamp(12px, 0.9vw, 14px); line-height: 1.5; margin: 0; }

/* ==========================================================================
   Client logos marquee
   ========================================================================== */
.client-logos {
	position: relative;
	overflow: hidden;
	padding: 4rem 0;
}
@media (min-width: 768px) { .client-logos { padding: 6rem 0; } }
.client-logos__track { display: flex; width: max-content; gap: 3rem; align-items: center; }
@media (min-width: 768px) { .client-logos__track { gap: 6rem; } }
.client-logos__item {
	flex: none;
	/* React: h-[40px] md:h-[60px] with a uniform p-2. The 48px tile and wider
	   side padding rendered the marks at 32px against the original's 44px. */
	height: 40px;
	background: var(--color-white);
	border-radius: 8px;
	padding: 0.5rem;
	display: flex;
	align-items: center;
	justify-content: center;
	opacity: 0.6;
	transition: opacity 0.4s ease;
}
@media (min-width: 768px) { .client-logos__item { height: 60px; } }
.client-logos__item:hover { opacity: 1; }
.client-logos__item img { height: 100%; width: auto; object-fit: contain; mix-blend-mode: multiply; }

/* ==========================================================================
   Teams / "Meet the team" section
   ========================================================================== */
/* React: py-16 md:py-24. A flat 4rem left each of these sections 32px short at the top and bottom. */
.teams-section { padding: 4rem 0; }
@media (min-width: 768px) { .teams-section { padding: 6rem 0; } }
.teams-section__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 3rem;
	align-items: center;
}
@media (min-width: 1024px) {
	.teams-section__grid { grid-template-columns: 1fr 1fr; gap: 5rem; }
}
.teams-section__images { position: relative; width: 100%; aspect-ratio: 1.1 / 1; max-width: 580px; margin-inline: auto; }
.teams-section__img-1 { position: absolute; top: -16.73%; left: 6.9%; width: 72%; height: 68%; border-radius: 16px; overflow: hidden; }
.teams-section__img-2 { position: absolute; top: 35.2%; right: 0; width: 48%; height: 75%; border-radius: 16px; overflow: hidden; z-index: 20; }
.teams-section__img-1 img, .teams-section__img-2 img { width: 100%; height: 100%; object-fit: cover; }
.teams-section__img-2 img { transform: scaleX(-1); }
.teams-section__logo-mark { position: absolute; bottom: 18.5%; right: 10.65%; width: 55%; aspect-ratio: 1 / 1; z-index: 10; pointer-events: none; }
.teams-section__logo-mark .bw-logo { width: 100%; height: 100%; }
.teams-section__text { text-align: center; }
@media (min-width: 1024px) { .teams-section__text { text-align: left; } }
.teams-section__eyebrow {
	color: var(--color-info);
	font-weight: 700;
	font-size: 0.875rem;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	margin: 0 0 1rem;
}
.teams-section__title { font-size: 30px; text-transform: uppercase; margin-bottom: 1.5rem; }
@media (min-width: 768px) { .teams-section__title { font-size: 36px; } }
@media (min-width: 1024px) { .teams-section__title { font-size: 50px; } }
.teams-section__title .accent { color: var(--color-info); }
.teams-section__body { color: rgba(0,0,0,0.7); max-width: 36rem; font-size: 1.125rem; line-height: 1.625; margin: 0 0 2rem; }

/* ==========================================================================
   Stats section
   ========================================================================== */
.stats-section { padding: 5rem 1rem; }
.stats-section__grid {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2rem;
	font-family: var(--font-aeroport);
}
@media (min-width: 768px) {
	.stats-section__grid { flex-direction: row; justify-content: space-around; align-items: flex-start; }
}
.stat-item { display: flex; align-items: flex-start; position: relative; padding-left: 0; }
@media (min-width: 768px) {
	.stat-item { padding-left: 4rem; }
	.stat-item:first-child { padding-left: 0; }
	.stat-item:not(:first-child)::before {
		content: '';
		position: absolute;
		left: 0;
		top: 50%;
		transform: translateY(-50%);
		width: 1px;
		height: 160px;
		background: #c6c6c6;
	}
}
.stat-item__number-row { display: flex; align-items: flex-end; line-height: 0.75; }
.stat-item__number { font-size: 100px; font-weight: 400; letter-spacing: -0.06em; color: #101010; margin: 0; }
@media (min-width: 640px) { .stat-item__number { font-size: 140px; } }
@media (min-width: 1024px) { .stat-item__number { font-size: 200px; } }
.stat-item__plus { font-size: 30px; font-weight: 300; margin-left: 0.5rem; color: #101010; }
@media (min-width: 640px) { .stat-item__plus { font-size: 40px; } }
@media (min-width: 1024px) { .stat-item__plus { font-size: 50px; } }
.stat-item__labels { display: flex; flex-direction: column; margin-left: 1rem; }
.stat-item__labels p { margin: 0; font-size: clamp(14px, 1.25vw, 20px); color: #101010; letter-spacing: -0.4px; }
.stat-item__labels .em { font-style: italic; font-family: serif; margin-top: 0.25rem; }
.stats-section__grid > .stat-item:nth-child(2) { transition-delay: 0.1s; }
.stats-section__grid > .stat-item:nth-child(3) { transition-delay: 0.2s; }

/* ==========================================================================
   Services grid (home teaser)
   ========================================================================== */
.services-teaser { padding: 4rem 0; }
@media (min-width: 768px) { .services-teaser { padding: 6rem 0; } }
/* React: mb-16 md:mb-24 lg:mb-[6vw]. */
.services-teaser__header { max-width: 900px; margin: 0 auto 4rem; text-align: center; }
@media (min-width: 768px) { .services-teaser__header { margin-bottom: 6rem; } }
@media (min-width: 1024px) { .services-teaser__header { margin-bottom: 6vw; } }
.services-teaser__label { color: var(--color-info); font-weight: 700; font-size: 14px; text-transform: uppercase; margin: 0 0 1rem; }
@media (min-width: 768px) { .services-teaser__label { font-size: 16px; } }
.services-teaser__title { color: var(--color-info); text-transform: uppercase; font-size: 40px; }
@media (min-width: 768px) { .services-teaser__title { font-size: 56px; } }
@media (min-width: 1024px) { .services-teaser__title { font-size: 72px; } }
.services-teaser__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 1.5rem;
	max-width: 600px;
	margin-inline: auto;
}
@media (min-width: 768px) {
	.services-teaser__grid {
		grid-template-columns: repeat(3, 1fr);
		max-width: none;
		align-items: start;
	}
}
@media (min-width: 1024px) {
	/* React: gap-6 lg:gap-[2.6vw]. A flat 1.5rem left the cards ~17px wider
	   than the original at 1920. */
	.services-teaser__grid { gap: 2.6vw; }
	/* Masonry stagger: column 2 drops 4.42vw, column 3 drops 8.85vw (matches the source's waterfall layout) */
	.services-teaser__grid > :nth-child(3n+2) { margin-top: 4.42vw; }
	.services-teaser__grid > :nth-child(3n+3) { margin-top: 8.85vw; }
	.services-teaser__grid.wp-block-post-template > li:nth-child(3n+2) > .service-card { margin-top: 4.42vw; }
	.services-teaser__grid.wp-block-post-template > li:nth-child(3n+3) > .service-card { margin-top: 8.85vw; }
}
.service-card {
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	padding: 2rem;
	min-height: 420px;
	border-radius: 8px;
	transition: transform 0.4s ease, box-shadow 0.4s ease;
}
@media (min-width: 768px) { .service-card { padding: 2.5rem; } }
@media (min-width: 1024px) { .service-card { padding: 2.5vw; min-height: 22vw; } }
.service-card:hover { transform: translateY(-8px); }
.service-card--dark { background: var(--color-info); color: var(--color-white); }
.service-card--light { background: var(--color-white); color: var(--color-info); border: 1px solid rgba(43,93,162,0.1); box-shadow: 0 10px 30px rgba(43,93,162,0.05); }
.service-card__id {
	display: inline-block;
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	padding: 0.4rem 1rem;
	border-radius: 999px;
	margin-bottom: 1.25rem;
}
.service-card--dark .service-card__id { background: rgba(255,255,255,0.1); color: var(--color-white); }
.service-card--light .service-card__id { background: rgba(43,93,162,0.05); color: var(--color-info); }
.service-card__title { font-size: 28px; margin-bottom: 1.25rem; }
@media (min-width: 768px) { .service-card__title { font-size: 32px; } }
@media (min-width: 1024px) { .service-card__title { font-size: 1.8vw; } }
.service-card__desc { font-size: 16px; line-height: 1.6; margin: 0; }
@media (min-width: 768px) { .service-card__desc { font-size: 17px; } }
.service-card--dark .service-card__desc { color: rgba(255,255,255,0.7); }
.service-card--light .service-card__desc { color: #475569; }
.service-card__arrow {
	align-self: flex-end;
	width: 48px; height: 48px;
	border-radius: 50%;
	display: flex; align-items: center; justify-content: center;
	margin-top: 2rem;
	transition: background-color 0.3s ease;
}
.service-card--dark .service-card__arrow { background: rgba(255,255,255,0.1); color: var(--color-white); }
.service-card--light .service-card__arrow { background: rgba(43,93,162,0.05); color: var(--color-info); }
.service-card:hover .service-card__arrow { background: var(--color-primary-active); color: var(--color-white); }

/* Query Loop wraps each item in a <li>; flatten it so .service-card stays
   a direct grid child exactly like the pre-block-editor markup. */
.services-teaser__grid.wp-block-post-template { list-style: none; margin: 0; padding: 0; }
.services-teaser__grid.wp-block-post-template > li { display: contents; }

/* Whole-card click without wrapping the card in one <a> (core blocks can't
   compose a Group as a link) — the bound title becomes a stretched link. */
.service-card { position: relative; }
.service-card__title-link.stretched-link::after { content: ""; position: absolute; inset: 0; }

/* ==========================================================================
   Portfolio marquee (home)
   ========================================================================== */
.portfolio-marquee { background: var(--color-black); padding: 4rem 0; overflow: hidden; }
@media (min-width: 768px) { .portfolio-marquee { padding: 6rem 0; } }
.portfolio-marquee__title {
	text-align: center;
	color: var(--color-info);
	font-size: 36px;
	/* React's text-4xl/text-5xl carry leading-none here; 1.1 made the row 5px
	   taller than the original. */
	line-height: 1;
	text-transform: uppercase;
	margin-bottom: 4rem;
}
@media (min-width: 768px) { .portfolio-marquee__title { font-size: 48px; } }
.portfolio-marquee__row { display: flex; width: max-content; gap: 1rem; margin-bottom: 1rem; }
.portfolio-card {
	position: relative;
	display: block;
	/* React: max-w-[520px] on a w-full card. */
	width: 520px;
	max-width: 90vw;
	aspect-ratio: 520 / 365.92;
	border-radius: 8px;
	overflow: hidden;
	border: 1px solid rgba(255,255,255,0.05);
	flex: none;
}
.portfolio-card img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease-reveal); }
.portfolio-card:hover img { transform: scale(1.05); }
.portfolio-card__overlay {
	position: absolute; inset: 0;
	display: flex; align-items: center; justify-content: center;
	background: rgba(0,0,0,0.4);
	opacity: 0;
	transition: opacity 0.3s ease;
}
.portfolio-card:hover .portfolio-card__overlay { opacity: 1; }

/* ==========================================================================
   CTA / "success" section (reused across pages)
   ========================================================================== */
/* SuccessSection is py-2 -- its 520px inner supplies the height. The
   case-study variant overrides this with React's py-24 further down. */
.cta-section { background: var(--color-black); padding: 0.5rem 1rem; }
.cta-section__inner {
	max-width: 72rem;
	margin-inline: auto;
	min-height: 520px;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	position: relative;
	padding: 3rem 0;
}
.cta-section__pattern {
	position: absolute;
	top: 50%; left: 50%;
	transform: translate(-50%, -50%);
	width: 90%; height: 90%;
	object-fit: contain;
	mix-blend-mode: screen;
	pointer-events: none;
	z-index: 1;
}
.cta-section__glow {
	position: absolute; inset: 0;
	background: radial-gradient(ellipse at center, rgba(14,165,233,0.35) 0%, rgba(30,64,175,0.3) 35%, transparent 75%);
	filter: blur(80px);
	pointer-events: none;
}
/* React's CTA content block is px-6 in both variants; without it the heading
   measured 343px wide on mobile against React's 295 and wrapped one line
   shorter. */
/* No max-width: the content is a flex item in a centred row, so it shrinks
   to fit exactly as React's does, bounded by the 72rem inner. The 640px cap
   wrapped Home's CTA heading onto a third line where React uses two. */
.cta-section__content { position: relative; z-index: 1; margin-inline: auto; padding-inline: 1.5rem; }
/* SuccessSection's heading words use mr-[0.2em], not the 0.25em elsewhere. */
.cta-section__title .reveal-word { margin-right: 0.2em; }
.cta-section__title {
	color: var(--color-white);
	font-size: 36px;
	text-transform: uppercase;
	margin-bottom: 1.5rem;
	line-height: 1.1;
	/* Both React CTA variants carry tracking-tight; without it the heading
	   ran 28px wider across "SCALE & PERFORMANCE?" at 56px. */
	letter-spacing: -0.025em;
}
@media (min-width: 768px) { .cta-section__title { font-size: 48px; } }
@media (min-width: 1024px) { .cta-section__title { font-size: 56px; } }
.cta-section__subtitle { color: rgba(255,255,255,0.75); margin-bottom: 3rem; font-size: 16px; line-height: 1.5; font-weight: 500; max-width: 36rem; margin-inline: auto; }
@media (min-width: 768px) { .cta-section__subtitle { font-size: 18px; line-height: 1.5556; } }
.cta-section__actions { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }

/* React has TWO CTA variants sharing this skeleton: SuccessSection on Home,
   Services, About and the Our Work archive, and ProjectCTA on case-study
   detail only. They differ in heading size, subtitle size and button metrics,
   so the values above stay correct for every other page and the case-study
   variant is scoped to the single-project body class. Only min-height is
   shared -- both React variants use 520px. */
.single-project .cta-section__title { font-size: 30px; }
@media (min-width: 640px) { .single-project .cta-section__title { font-size: 36px; } }
@media (min-width: 768px) { .single-project .cta-section__title { font-size: 48px; } }
@media (min-width: 1024px) { .single-project .cta-section__title { font-size: 56px; } }
@media (min-width: 1024px) { .single-project .cta-section__subtitle { font-size: 22px; line-height: 1.5556; } }
/* React's ProjectCTA buttons carry no tracking; the theme's .btn adds
   0.025em, which widened them by ~12px. */
.single-project .cta-section { padding-block: 6rem; }
/* ProjectCTA's content block is py-20; SuccessSection's is py-12, which is
   what the shared 3rem above encodes. On narrow screens the taller padding is
   what lets React's CTA box grow past its 520px floor. */
.single-project .cta-section__inner { padding-block: 5rem; }
.single-project .cta-section__actions .btn { font-size: 15px; padding: 0 40px; min-height: 55px; letter-spacing: normal; }
.single-project .cta-section__actions .btn:first-child { font-weight: 700; }
.single-project .cta-section__actions .btn:last-child { font-weight: 500; }

/* ==========================================================================
   Generic dark hero (Services / About / Our Work shared shell)
   ========================================================================== */
.page-hero {
	position: relative;
	background: var(--color-black);
	color: var(--color-white);
	/*
	 * React sizes these against the viewport, not by breakpoint: the top is
	 * max(110px, 11vw) everywhere, and the bottom differs per page rather than
	 * per width -- 4vw on About, 5vw on Services. Stepping them at 768/1024
	 * instead put the hero 29px too low at 1920 and the wrong height at every
	 * width in between.
	 * The section itself carries no side padding -- the .container inside
	 * supplies React's px-4. Setting it here too gave the hero a double
	 * gutter, 32px narrower than React's below ~1322px wide, which wrapped
	 * the About title onto two extra lines on a phone.
	 */
	padding: max(110px, 11vw) 0 max(40px, 4vw);
	text-align: center;
	overflow: hidden;
}
.page-hero--services { padding-bottom: max(60px, 5vw); }
.page-hero--light { background: var(--color-white); color: var(--color-black); }
.page-hero__eyebrow { color: var(--color-info); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 700; font-size: 15px; line-height: 1.5; margin: 0 0 1.5rem; }
/* Services' eyebrow sits tighter to its title than About's. */
.page-hero--services .page-hero__eyebrow { line-height: 1.6; margin-bottom: 1rem; }
.page-hero__title { font-family: var(--font-inter); font-weight: 600; line-height: 1.15; max-width: 800px; margin: 0 auto 2rem; }
.page-hero--light .page-hero__title { color: #1a1a1a; }
/* React's hero subtitle leads into the page with clamp(40px, 6vw, 80px) of
   space: 40px on phones, 6vw through the middle widths, capped at 80px. A flat
   value is wrong at both ends. Our Work has none at all. */
.page-hero__subtitle { font-family: var(--font-inter); max-width: 860px; margin: 0 auto clamp(40px, 6vw, 80px); line-height: 1.625; color: #9ca3af; }
.page-hero--work .page-hero__subtitle { margin-bottom: 0; }
.page-hero--light .page-hero__subtitle { color: #4b5563; }

/* Services hero: text-[36px] md:text-[52px] (no lg step) */
.page-hero--services .page-hero__title { font-size: 36px; letter-spacing: -0.03em; }
@media (min-width: 768px) { .page-hero--services .page-hero__title { font-size: 52px; } }
.page-hero--services .page-hero__subtitle { font-size: clamp(18px, 1.25vw, 24px); }

/* Block-editor Services hero: the old template put `position:relative;
   z-index:2` inline on .container and a 0.5s transition-delay inline on the
   subtitle. Neither can survive core/group's and core/paragraph's save(), so
   both live here now — mirroring the `.hero-home .container` rule added
   during the Home pilot. The subtitle rule is given class-pair specificity
   (0-2-0) deliberately: `.reveal-fade` above sets the `transition`
   SHORTHAND, which resets transition-delay to 0s. */
.page-hero .container { position: relative; z-index: 2; }
.page-hero--services .page-hero__subtitle.reveal-fade { transition-delay: 0.5s; }

/* About hero: fluid clampFont(50,64,80) / clampFont(20,22,28); title has no max-width in source */
.page-hero--about .page-hero__title { font-size: clamp(50px, 3.3333vw, 80px); max-width: none; line-height: 1.1; }
.page-hero--about .page-hero__subtitle { font-size: clamp(20px, 1.1458vw, 28px); }
/* Block-editor conversion of the About hero. The accent line is now its own
   heading block (className "page-hero__title page-hero__title--accent")
   instead of a <span> carrying an inline `color: var(--color-info)`, so it
   needs a rule that actually beats `.page-hero--light .page-hero__title`'s
   #1a1a1a: same 0-2-0 specificity, placed after it. */
.page-hero__title.page-hero__title--accent { color: var(--color-info); }
/* The title is two adjacent heading blocks (one per bound field) standing in
   for the original single <h1>, which flowed the accent phrase INLINE after
   the main title — as the React source does too — rather than starting it on
   its own line. Rendering the pair inline reproduces that wrapping, and the
   2rem that separated title from subtitle moves to their wrapper, since
   inline boxes can't carry vertical margins.
   The wrapper repeats the title's own typography deliberately: the
   whitespace BETWEEN the two inline headings is a text node belonging to the
   wrapper, so it's the wrapper's font that sets how wide that word space is —
   left at the body's 16px it renders as a 4px sliver and the accent phrase
   crowds the word before it. Scoped to .page-hero--about so no other hero
   (nor Contact's deliberately stacked title) is affected. */
.page-hero--about .page-hero__title-lines { font-family: var(--font-inter); font-weight: 600; font-size: clamp(50px, 3.3333vw, 80px); line-height: 1.1; max-width: none; margin: 0 auto 2rem; }
.page-hero--about .page-hero__title { display: inline; margin: 0; }
/* The old template put transition-delay:0.5s inline on the About subtitle.
   Class-pair specificity (0-2-0) deliberately: `.reveal-fade` sets the
   transition SHORTHAND, which resets transition-delay to 0s. */
.page-hero--about .page-hero__subtitle.reveal-fade { transition-delay: 0.5s; }

/* Our Work archive hero: text-[40px] md:text-[52px] (no lg step); title max-width is 900px in source */
.page-hero--work .page-hero__title { font-size: 40px; max-width: 900px; }
@media (min-width: 768px) { .page-hero--work .page-hero__title { font-size: 52px; } }
.page-hero--work .page-hero__subtitle { font-size: clamp(18px, 1.25vw, 22px); }

/* About hero background: soft radial gradient, not flat white */
.page-hero--about { background: radial-gradient(ellipse at top, #faf5ff 0%, #ffffff 60%, #ffffff 100%); }

/* ── Hero background gradient blobs (behind content, above bg) ── */
.hero-blobs { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 0; max-width: 1920px; margin-inline: auto; }
.hero-blob { position: absolute; filter: blur(120px); border-radius: 60% 40% 70% 30% / 40% 50% 60% 70%; }

/* Services and case-study hero blobs — always visible, blur-120.
   The original uses the identical layer on both: same positions, sizes,
   opacities, rotations and gradients, down to the border-radius. They share
   one rule rather than being duplicated, and the case-study hero keeps its
   own modifier so the class on the page still reads as what it is. */
.hero-blobs--services .hero-blob-1,
.hero-blobs--project .hero-blob-1 { top: 26%; left: 7%; width: 70%; height: 40%; opacity: 0.25; transform: rotate(214deg); background: linear-gradient(135deg, #0000FF 0%, #8A2BE2 50%, #FF4500 100%); }
.hero-blobs--services .hero-blob-2,
.hero-blobs--project .hero-blob-2 { top: 14%; right: 0; width: 60%; height: 45%; opacity: 0.18; transform: rotate(-38deg); background: linear-gradient(110deg, #001AFF 0%, #7000FF 45%, #FF4D00 100%); }

/* Terms and Privacy blobs. Both pages use the shared .hero-blobs base — the
   original's legal blobs blur at 120px, which is what .hero-blob already
   does — and each carries its own palette and geometry. Like every other
   blob layer here they are static: the original drifts them on a 25-32s
   loop, and this theme has consistently rendered that as a still gradient.
   .hero-blob's base border-radius is already Terms' first shape, so only
   the other three override it. */
.hero-blobs--terms .hero-blob-1 {
	top: 10%; left: -10%; width: 50%; height: 50%;
	opacity: 0.2; transform: rotate(15deg);
	background: linear-gradient(135deg, #001AFF 0%, #7000FF 40%, #e98827 100%);
}
.hero-blobs--terms .hero-blob-2 {
	bottom: 0; right: -5%; width: 40%; height: 50%;
	opacity: 0.15; transform: rotate(-20deg);
	border-radius: 40% 60% 30% 70% / 60% 40% 50% 50%;
	background: linear-gradient(110deg, #1049de 0%, #7000FF 50%, #FF4D00 100%);
}
.hero-blobs--privacy .hero-blob-1 {
	top: 20%; right: -10%; width: 50%; height: 50%;
	opacity: 0.15; transform: rotate(-15deg);
	border-radius: 50% 50% 60% 40% / 40% 60% 40% 60%;
	background: linear-gradient(135deg, #7000FF 0%, #001AFF 40%, #e98827 100%);
}
.hero-blobs--privacy .hero-blob-2 {
	bottom: 10%; left: -5%; width: 40%; height: 50%;
	opacity: 0.2; transform: rotate(10deg);
	border-radius: 30% 70% 40% 60% / 50% 50% 60% 40%;
	background: linear-gradient(110deg, #e98827 0%, #FF4D00 50%, #7000FF 100%);
}

/* Our Work archive hero blobs — hidden below 640px */
.hero-blobs--work { display: none; }
@media (min-width: 640px) {
	.hero-blobs--work { display: block; }
	.hero-blobs--work .hero-blob-1 { top: 0; left: 9.7vw; width: 70.3vw; height: 40.6vw; opacity: 0.25; transform: rotate(214deg); background: linear-gradient(135deg, #0000FF 0%, #8A2BE2 50%, #FF4500 100%); }
	.hero-blobs--work .hero-blob-2 { top: 0; right: 14%; width: 24.29vw; height: 36.46vw; opacity: 0.18; transform: rotate(61deg); background: linear-gradient(110deg, #001AFF 0%, #7000FF 45%, #FF4D00 100%); }
}

/* About hero blobs — blur-80, hidden below 640px */
.hero-blobs--about { display: none; }
@media (min-width: 640px) {
	.hero-blobs--about { display: block; }
	.hero-blobs--about .hero-blob { filter: blur(80px); }
	.hero-blobs--about .hero-blob-1 { top: 0; left: 6.25vw; width: 70.3vw; height: 40.6vw; opacity: 0.25; transform: rotate(214deg); background: linear-gradient(135deg, #0000FF 0%, #8A2BE2 50%, #FF4500 100%); z-index: -1; }
	.hero-blobs--about .hero-blob-2 { top: 23%; left: 40%; width: 50%; height: 48%; opacity: 0.14; transform: rotate(147deg); background: linear-gradient(110deg, #001AFF 0%, #7000FF 45%, #FF4D00 100%); z-index: -1; }
}

/* ── Corner decoration images (Services + About heroes) ── */
.hero-corner { position: absolute; display: none; pointer-events: none; z-index: 2; }
@media (min-width: 1024px) { .hero-corner { display: block; } }
.hero-corner img { width: 100%; height: auto; object-fit: contain; }
.hero-corner--right { top: 50%; right: 0; width: 10.53vw; transform: translateY(-50%); }
.hero-corner--left { bottom: 0; left: 0; width: 13.75vw; z-index: 1; }
.hero-corner--left img { transform: translateY(130px); }

.hero-corner--about-left { display: none; bottom: -10.7%; left: 0; width: 13.75vw; transform: translateY(10%) translateX(-10%); z-index: 2; }
@media (min-width: 768px) { .hero-corner--about-left { display: block; } }
.hero-corner--about-right { display: none; top: 50%; right: 0; width: 10.53vw; transform: translateY(-50%) translateX(20%); z-index: 2; }
@media (min-width: 768px) { .hero-corner--about-right { display: block; } }

/* ==========================================================================
   Services page — service category blocks
   ========================================================================== */
.service-block { position: relative; padding: 3rem 0; scroll-margin-top: var(--header-height); }
/* React: py-12 md:py-16. */
@media (min-width: 768px) { .service-block { padding: 4rem 0; } }
.service-block__header { margin: 0 auto 2rem; text-align: center; }
/* `leading-tight`, not the theme's 1.1 heading default. */
.service-block__title { font-size: 40px; line-height: 1.25; margin-bottom: 1rem; }
@media (min-width: 768px) { .service-block__title { font-size: 56px; } }
@media (min-width: 1024px) { .service-block__title { font-size: 72px; } }
.service-block__desc { font-family: var(--font-inter); font-weight: 500; font-size: 20px; max-width: 48rem; margin: 0 auto; line-height: 1.4; }
@media (min-width: 768px) { .service-block__desc { font-size: 28px; } }
.service-block__tech-row { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; margin: 0 0 3rem; }
/* These pills stay in Inter, like the rest of the theme, and the row is
   allowed to wrap. React's pill carries no font class, so it inherits
   Tailwind's default ui-sans-serif/system-ui stack; Inter runs ~3% wider, and
   on the eight-pill block that is enough to push the row past the 1258px
   container onto a second line where React's fits on one. Matching React would
   mean an OS-dependent font here. Deliberate -- do not "fix" the wrap by
   trimming the padding or switching the family. */
.tech-pill { padding: 12px 24px; font-size: 14px; line-height: 1.5; background: #f5f5f7; border: 1px solid #e5e7eb; border-radius: 999px; font-weight: 500; color: #374151; }
@media (min-width: 768px) { .tech-pill { padding: 16px 40px; font-size: 16px; } }
.service-block__body {
	display: grid;
	grid-template-columns: 1fr;
	gap: 2rem;
	max-width: 1240px;
	margin: 0 auto 3rem;
	font-family: var(--font-inter);
}
@media (min-width: 768px) {
	.service-block__body { grid-template-columns: 1.2fr 1fr; gap: 4rem; }
}
.service-block__features h3 { font-size: 2rem; line-height: 1.5; margin-bottom: 2rem; }
.service-block__features ul { display: flex; flex-direction: column; gap: 1rem; }
.service-block__features li { display: flex; align-items: center; gap: 0.75rem; font-size: 1.125rem; font-weight: 500; }
.service-block__features li::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--color-black); flex-shrink: 0; }
.service-block__paragraphs { color: #374151; line-height: 1.6; font-size: 17px; display: flex; flex-direction: column; justify-content: center; gap: 1.5rem; }
/* The column already spaces its paragraphs with `gap`, but each <p> also keeps
   its default 1em top and bottom margin, which at 18px adds 72px of dead space
   per service section (measured: body grid 326px in WordPress vs 254px in
   React, which resets p margins in its preflight). Every other card rule in
   this file already zeroes them — `.mini-project-card p`, `.why-card p`,
   `.value-card p`; this one was missed. Specificity 0-1-1 so it beats any bare
   `p` rule. */
.service-block__paragraphs p { margin: 0; }
@media (min-width: 768px) { .service-block__paragraphs { font-size: 18px; } }
.service-block__projects { display: grid; grid-template-columns: 1fr; gap: 2rem; }
/* React is `grid-cols-1 md:grid-cols-2 lg:grid-cols-3`; jumping straight to
   three at 768 dropped a whole card row on tablets. */
@media (min-width: 768px) { .service-block__projects { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .service-block__projects { grid-template-columns: repeat(3, 1fr); } }
.mini-project-card { display: block; }
.mini-project-card__img { aspect-ratio: 1 / 1; border-radius: 4px; overflow: hidden; margin-bottom: 1rem; background: #f3f4f6; }
.mini-project-card__img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--ease-reveal); }
.mini-project-card:hover .mini-project-card__img img { transform: scale(1.06); }
.mini-project-card h4 { font-size: 1.5rem; line-height: 1.5; margin-bottom: 0.5rem; }
.mini-project-card p { color: #4b5563; font-size: 0.9375rem; line-height: 1.5; margin: 0; }
.service-block__cta { text-align: center; margin-top: 3rem; }
.service-block__cta button, .service-block__cta a.btn-cta {
	display: inline-flex;
	background: var(--color-primary);
	color: var(--color-white);
	font-weight: 600;
	padding: 14px 3rem;
	border-radius: 999px;
	font-size: 11px;
	line-height: 1.5;
	border: none;
}
@media (min-width: 768px) { .service-block__cta button, .service-block__cta a.btn-cta { font-size: 15px; } }

/* Decorative blurred gradient blobs behind every service section, ported from
   the React reference's ServiceCategorySection — the two absolutely-positioned
   divs inside its `absolute inset-0 pointer-events-none z-0` wrapper. Without
   them the WordPress service sections read as flat white against React's faint
   blue/violet/orange wash. Pseudo-elements rather than markup, because the
   divs are purely decorative and the section is server-rendered.

   This is deliberately NOT `.home-bg`: React applies that fixed background
   image to the home page only.

   Specificity note: `.service-block` above is the only rule that touches this
   element's `position`, and nothing else in this file styles
   `.service-block::before/::after` or `.service-block > .container`, so no
   later rule can outrank these. */
.service-block::before,
.service-block::after {
	content: '';
	position: absolute;
	top: 0;
	z-index: 0;
	pointer-events: none;
	opacity: 0.12;
	border-radius: 60% 40% 70% 30% / 40% 50% 60% 70%;
}
.service-block::before {
	left: 0;
	width: 89%;
	height: 27%;
	background: linear-gradient(135deg, #0000FF 0%, #8A2BE2 50%, #FF4500 100%);
	filter: blur(100px);
	transform: rotate(-153deg);
}
.service-block::after {
	right: 10%;
	width: 41%;
	height: 17%;
	background: linear-gradient(110deg, #001AFF 0%, #7000FF 45%, #FF4D00 100%);
	filter: blur(120px);
	transform: rotate(138deg);
}
/* React's <Container className="relative z-10"> — keeps the real content
   above the blobs. */
.service-block > .container { position: relative; z-index: 1; }

/* ==========================================================================
   Why Choose Us
   ========================================================================== */
.why-choose-us { background: var(--color-black); color: var(--color-white); padding: 4rem 1rem; }
.why-choose-us__header { max-width: 48rem; margin: 0 auto 3rem; text-align: center; }
.why-choose-us__title { font-size: 40px; font-weight: 600; font-family: var(--font-inter); margin-bottom: 1.5rem; }
@media (min-width: 768px) { .why-choose-us__title { font-size: 52px; } }
.why-choose-us__subtitle { font-size: 22px; color: rgba(255,255,255,0.7); line-height: 1.6; }
.why-choose-us__grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; max-width: 1290px; margin: 0 auto; }
@media (min-width: 768px) { .why-choose-us__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .why-choose-us__grid { grid-template-columns: repeat(3, 1fr); } }
/* React puts `min-h-[360px]` on an INNER div, wrapped in a card with
   `p-8 md:p-10` and a 1px border, so the card's own height is
   360 + padding + border: 426px under 768px, 442px at and above it. Setting
   `min-height: 360px` on this border-box card instead left its content area
   only 280px tall — an 82px shortfall at 1280px. The calc() keeps the CONTENT
   box at 360px at both widths, which is the number React actually pins. */
.why-card {
	background: var(--color-white);
	color: var(--color-black);
	border-radius: 12px;
	border: 1px solid rgba(255, 255, 255, 0.1);
	box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
	padding: 2rem;
	min-height: calc(360px + 4rem + 2px);
	display: flex;
	flex-direction: column;
}
@media (min-width: 768px) {
	.why-card { padding: 2.5rem; min-height: calc(360px + 5rem + 2px); }
}
.why-card img { width: 48px; margin-bottom: 3rem; }
.why-card h3 { font-size: 24px; margin-top: auto; margin-bottom: 1rem; }
@media (min-width: 768px) { .why-card h3 { font-size: 28px; } }
.why-card p { color: #1f2937; font-weight: 500; line-height: 1.6; margin: 0; font-size: 14px; }
@media (min-width: 768px) { .why-card p { font-size: 15px; } }

/* Reveal stagger for the why-cards and the subtitle. Inline styles in the
   old template; they can't survive core/group's / core/paragraph's save(),
   so they are :nth-child / class-pair rules here instead — the same
   treatment the Home stats' stagger got. The core/image block wraps each
   icon in a <figure class="wp-block-image">, whose 1em bottom margin would
   otherwise add to the img's own 3rem; the figure is neutralised so the
   card's spacing matches the pre-conversion markup exactly. */
.why-choose-us__subtitle.reveal-fade { transition-delay: 0.2s; }
.why-choose-us__grid > .why-card:nth-child(2) { transition-delay: 0.12s; }
.why-choose-us__grid > .why-card:nth-child(3) { transition-delay: 0.24s; }
.why-card .wp-block-image { display: block; margin: 0; }

/* ==========================================================================
   About — team / founders / process
   ========================================================================== */
/* React's team section carries no padding of its own -- the heading block
   inside supplies it, which .about-team__heading already does. */
.about-team { background: linear-gradient(to bottom right, #111827, #000000); color: var(--color-white); padding: 0; overflow: hidden; }
.about-team__heading { text-align: center; font-size: 10.5vw; letter-spacing: -0.04em; line-height: 0.9; white-space: nowrap; padding: clamp(32px, 10vw, 48px) 5% clamp(16px, 5vw, 24px); margin: 0; }
/* React's heading block leads with ~6vw of space above it, not a flat 4rem;
   at 1920 that is 115px against the theme's 64. */
@media (min-width: 768px) { .about-team__heading { font-size: clamp(48px, 6vw, 116px); line-height: 0.95; white-space: normal; padding: 6vw 1rem 2rem; } }
/* The team heading is two adjacent heading blocks (one per bound field)
   standing in for the original single <h2> whose two lines were separated by a
   <br>. Collapse the inner seam so the pair keeps that single heading's outer
   padding instead of doubling it in the middle. Specificity 0-3-0 so these
   beat the min-width:768px padding shorthand above, at every width. */
.about-team .about-team__heading:not(:last-of-type) { padding-bottom: 0; }
.about-team .about-team__heading + .about-team__heading { padding-top: 0; }
.founders { display: flex; flex-direction: column; gap: 5rem; padding: 1.5rem 0 5rem; }
@media (min-width: 768px) { .founders { gap: 7rem; padding-bottom: 8rem; } }
.founder { position: relative; display: flex; flex-direction: column; align-items: center; gap: 2.5rem; text-align: center; }
@media (min-width: 768px) {
	.founder { flex-direction: row; text-align: left; gap: 4rem; }
	.founder--reversed { flex-direction: row-reverse; }
}
.founder__number {
	display: none;
	pointer-events: none;
	user-select: none;
}
@media (min-width: 768px) {
	.founder__number {
		display: block;
		position: absolute;
		top: -4rem;
		left: 2rem;
		z-index: 0;
		font-family: var(--font-aeroport);
		font-weight: 700;
		line-height: 1;
		font-size: clamp(90px, 12vw, 200px);
		color: transparent;
		-webkit-text-stroke: 1.5px rgba(255,255,255,0.08);
	}
	.founder--reversed .founder__number { left: auto; right: 2rem; }
}
.founder-photo-wrap { position: relative; z-index: 1; flex-shrink: 0; }
.founder-photo-glow { position: absolute; inset: -2rem; border-radius: 48px; filter: blur(64px); opacity: 0.5; pointer-events: none; z-index: 0; }
.founder-photo { position: relative; z-index: 1; overflow: hidden; aspect-ratio: 696 / 1130; width: clamp(200px, 22vw, 300px); border-radius: 28px; border: 1px solid rgba(255,255,255,0.1); transform: rotate(-3deg); }
.founder--reversed .founder-photo { transform: rotate(3deg); }
.founder-photo img { position: absolute; top: 0; height: 100%; width: auto; max-width: none; }
.founder-photo--right img { left: -100%; }
.founder-photo--left img { left: 0; }
/* The text column fills the row; without flex:1 it collapsed to the bio's
   36rem cap, leaving the copy 318px narrower than React's. */
.founder__text { flex: 1; min-width: 0; }
.founder__eyebrow { text-transform: uppercase; letter-spacing: 0.2em; font-size: 0.75rem; line-height: 1.333; font-weight: 700; margin: 0 0 0.75rem; }
.founder h3 { font-size: 30px; line-height: 1.2; margin-bottom: 0.75rem; }
/* `md:text-5xl` is the leading-none one; `text-3xl` below it is 30px/36px. */
@media (min-width: 768px) { .founder h3 { font-size: 48px; line-height: 1; } }
.founder__title { display: inline-flex; align-items: center; gap: 0.5rem; border-radius: 999px; padding: 0.4rem 1rem; margin-bottom: 1.25rem; border: 1px solid; font-size: 0.875rem; font-weight: 600; }
.founder p.founder__bio { color: #9ca3af; max-width: 36rem; font-size: clamp(14px, 1vw, 17px); line-height: 1.625; margin: 0; }

.how-we-operate__label { text-align: center; color: var(--color-info); font-family: var(--font-montserrat); font-weight: 700; font-size: clamp(24px, 24px, 32px); line-height: 1.5; text-transform: uppercase; margin-bottom: 2.5rem; }
.how-we-operate__grid { display: grid; grid-template-columns: 1fr; gap: clamp(16px, 1.67vw, 32px); padding-bottom: clamp(48px, 6.67vw, 128px); }
@media (min-width: 640px) { .how-we-operate__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .how-we-operate__grid { grid-template-columns: repeat(4, 1fr); } }
/* Block-editor conversion of the process steps. The grid is now the <ul> that
   core/post-template emits (the className is on post-template, NOT on the
   core/query wrapper — that mistake makes the grid a single-column stack of
   one <ul> child), so it needs the list chrome reset while keeping the
   original bottom padding. */
.how-we-operate__grid.wp-block-post-template { list-style: none; margin: 0; padding-top: 0; padding-left: 0; padding-right: 0; padding-bottom: clamp(48px, 6.67vw, 128px); }
/* Each card now sits inside an <li> track item; `display: grid` on the <li>
   stretches the card to the full track height, exactly as the card did when it
   was the direct grid item. */
.how-we-operate__grid > li { display: grid; counter-increment: process-step; }
/* A Query Loop exposes no index variable, so the step number that used to be
   PHP's $index + 1 is a CSS counter; the .process-step__num block is empty. */
.how-we-operate__grid { counter-reset: process-step; }
.process-step__num::before { content: counter(process-step); }
/* ...and the per-step transition-delay that used to be inline. Specificity
   0-3-0 beats `.reveal-up`'s transition shorthand, which resets the delay. */
.how-we-operate__grid > li:nth-child(2) .process-step { transition-delay: 0.1s; }
.how-we-operate__grid > li:nth-child(3) .process-step { transition-delay: 0.2s; }
.how-we-operate__grid > li:nth-child(4) .process-step { transition-delay: 0.3s; }
/* React's process cards are p-10. */
.process-step { background: rgba(43,93,162,0.05); border: 1px solid rgba(255,255,255,0.05); border-radius: 16px; padding: 2rem; }
@media (min-width: 768px) { .process-step { padding: 2.5rem; } }
.process-step__num { width: 40px; height: 40px; border-radius: 50%; background: rgba(43,93,162,0.1); color: var(--color-info); display: flex; align-items: center; justify-content: center; font-family: var(--font-aeroport); font-weight: 700; margin-bottom: 1.5rem; }
.process-step h3 { font-size: clamp(16px, 1.04vw, 20px); line-height: 1.5; margin-bottom: clamp(8px, 0.83vw, 16px); font-family: var(--font-inter); }
.process-step p { color: #9ca3af; font-size: clamp(12px, 0.73vw, 14px); line-height: 1.625; margin: 0; }

/* ==========================================================================
   About — Core Values
   ========================================================================== */
/* React: py-12 md:py-20, symmetric. */
.core-values { background: var(--color-black); color: var(--color-white); padding: 3rem 0; }
@media (min-width: 768px) { .core-values { padding: 5rem 0; } }
.core-values__title { text-align: center; font-size: 28px; line-height: 1.5; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 2.5rem; }
@media (min-width: 768px) { .core-values__title { font-size: 32px; } }
.core-values__layout { display: flex; flex-direction: column; gap: 1.5rem; }
@media (min-width: 1024px) { .core-values__layout { flex-direction: row; } }
.core-values__left { display: flex; flex-direction: column; gap: 1.5rem; }
@media (min-width: 1024px) { .core-values__left { width: 62%; } }
.core-values__bottom-row { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 768px) { .core-values__bottom-row { grid-template-columns: 1fr 1fr; } }
.value-card { background: #0e0f14; padding: 2rem; border-radius: 16px; border: 1px solid rgba(255,255,255,0.04); }
.value-card--lg { min-height: 280px; display: flex; flex-direction: column; justify-content: center; }
.value-card img { margin-bottom: 1.5rem; }
/* React's value headings sit on a 1.5 line box, not the theme's heading 1.1. */
.value-card h3 { font-size: 20px; line-height: 1.5; margin-bottom: 1rem; }
/* React hard-codes a <br> in both small-card headings, so they always occupy
   two lines. A post title cannot carry a <br> (WordPress strips it out of
   `title_save_pre`), so the card reserves the second line instead: two 30px
   line boxes. Without it the cards -- and the whole left column -- run 30px
   short of React's. */
.core-values__bottom-row .value-card h3 { min-height: 3.75rem; }
.value-card--lg h3 { font-size: 22px; }
@media (min-width: 768px) { .value-card--lg h3 { font-size: 24px; } }
.value-card p { color: #9ca3af; line-height: 1.7; font-size: 14px; margin: 0; }
@media (min-width: 768px) { .value-card p { font-size: 15px; } }
.value-card--lg p { font-size: 15px; }
.core-values__right { position: relative; background: var(--color-info); border-radius: 16px; overflow: hidden; }
@media (min-width: 1024px) { .core-values__right { width: 38%; } }
/* React steps this panel's padding three times
   (`px-6 pt-8 pb-[220px] sm:px-8 sm:pt-10 sm:pb-[260px] md:px-10 md:pt-12
   md:pb-[320px]`); only the smallest step was here. The bottom padding is what
   keeps the copy clear of the photo anchored to the panel's foot. */
.core-values__right-content { position: relative; z-index: 1; padding: 2rem 1.5rem 220px; }
@media (min-width: 640px) { .core-values__right-content { padding: 2.5rem 2rem 260px; } }
@media (min-width: 768px) { .core-values__right-content { padding: 3rem 2.5rem 320px; } }
/* React writes this heading with two <br>s, so it always occupies three lines.
   A post title cannot carry a <br> (WordPress strips it out of
   `title_save_pre`), so the heading reserves the third line instead -- 3.45em
   is three 1.15 line boxes, which holds at every font size below. Same
   reservation as `.core-values__bottom-row .value-card h3`. */
.core-values__right-content h3 { font-size: 28px; line-height: 1.15; min-height: 3.45em; margin-bottom: 2rem; }
@media (min-width: 768px) { .core-values__right-content h3 { margin-bottom: 2.5rem; } }
@media (min-width: 640px) { .core-values__right-content h3 { font-size: 32px; } }
@media (min-width: 768px) { .core-values__right-content h3 { font-size: 38px; } }
/* React leaves this word white and draws an orange stroke beneath it, rather
   than colouring the word itself. */
.core-values__right-content h3 .accent { position: relative; display: inline-block; }
.core-values__right-content h3 .accent__underline { position: absolute; left: 0; bottom: -4px; width: 100%; height: 8px; color: var(--color-primary); overflow: visible; }
.core-values__right-content p { display: flex; align-items: flex-start; gap: 1rem; padding-bottom: 1.25rem; font-size: 0.875rem; line-height: 1.7; color: #eff6ff; margin: 0; }
.core-values__right-content p::before { content: ''; width: 5px; height: 5px; margin-top: 9px; border-radius: 50%; background: var(--color-white); flex-shrink: 0; }
/* React steps the photo's height at every breakpoint
   (`h-[240px] sm:h-[280px] md:h-[340px] lg:h-[380px]`). */
.core-values__right-img { position: absolute; bottom: 0; left: 0; width: 100%; height: 240px; }
@media (min-width: 640px) { .core-values__right-img { height: 280px; } }
@media (min-width: 768px) { .core-values__right-img { height: 340px; } }
@media (min-width: 1024px) { .core-values__right-img { height: 380px; } }
.core-values__right-img img { width: 100%; height: 100%; object-fit: cover; object-position: center; }

/* ==========================================================================
   Legal pages (Terms / Privacy)
   ========================================================================== */
.legal-page { position: relative; overflow: hidden; background: var(--color-black); color: var(--color-white); padding: 128px 1rem 5rem; }
/* The mouse spotlight is absolutely positioned at z-index 1, so the section
   has to establish the containing block and the copy has to stack above it --
   the same pairing as `.hero-home .container`. React gives these two wrappers
   `relative z-10`. */
.legal-page__intro,
.legal-sections,
.legal-page__updated { position: relative; z-index: 2; }
/* React's container is px-4 md:px-0, so the gutter disappears from 768px up.
   Keeping 1rem there made the cards 32px narrower than the original at
   viewports below the 896px cap, wrapping a paragraph an extra line. */
@media (min-width: 768px) { .legal-page { padding-top: 160px; padding-inline: 0; } }
.legal-page__intro { max-width: 56rem; margin: 0 auto 4rem; }
/* React: text-4xl md:text-6xl tracking-tight. text-4xl carries a 40px line
   box, text-6xl leading-none — so the ratio steps at the breakpoint. */
.legal-page__title { font-size: 36px; font-weight: 900; line-height: 1.111; margin-bottom: 1.5rem; letter-spacing: -0.025em; }
@media (min-width: 768px) { .legal-page__title { line-height: 1; } }
@media (min-width: 768px) { .legal-page__title { font-size: 60px; } }
.legal-page__title .accent { color: var(--color-primary-active); }
/* React: max-w-2xl leading-relaxed, and no paragraph margin — the intro
   block's own mb-16 does the spacing. */
.legal-page__lede { color: rgba(255,255,255,0.5); font-size: 18px; max-width: 42rem; line-height: 1.625; margin: 0; }
@media (min-width: 768px) { .legal-page__lede { font-size: 20px; } }
/* `minmax(0, 1fr)`, not the implicit `minmax(auto, 1fr)`: each `.legal-section`
   is a flex row (number + text) whose min-content width is 369.6px, so with an
   `auto` minimum the track ignored the 328px column at 375px and every card
   bled 41.6px past the page gutter. React's card measures exactly its 328px
   column there. Desktop is unaffected — the 896px track is already wider than
   the card's min-content. */
.legal-sections { max-width: 56rem; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
/* React: gap-6 md:gap-8. */
@media (min-width: 768px) { .legal-sections { gap: 2rem; } }
.legal-section {
	background: rgba(10,11,16,0.4);
	border: 1px solid rgba(255,255,255,0.05);
	border-radius: 28px;
	/* React is `p-8 md:p-10`: 32px on mobile, 40px from 768px up. A flat 2.5rem
	   was 8px too much on each side of a 375px screen. */
	padding: 2rem;
	display: flex;
	/* React: flex-col md:flex-row with gap-6 md:gap-10 — the number sits above
	   the text on mobile, beside it from 768px. */
	flex-direction: column;
	gap: 1.5rem;
}
@media (min-width: 768px) { .legal-section { padding: 2.5rem; flex-direction: row; gap: 2.5rem; } }
/* Tabular figures so 01..06 are all the same width. React's render uniformly
   at 21px; Inter's proportional digits varied 21-25px here, and the narrower
   text column that left was enough to wrap one section a line longer. */
/* React styles this span font-aeroport, which resolves to the generic sans
   fallback since neither codebase ships that face. Letting it inherit Inter
   made the number ~3px wider, and the narrower text column that left wrapped
   one Terms paragraph onto a fourth line. Tabular figures keep 01..06 even. */
.legal-section__num { color: var(--color-primary-active); font-family: var(--font-aeroport); font-weight: 700; font-size: 0.875rem; letter-spacing: 0.2em; font-variant-numeric: tabular-nums; opacity: 0.6; flex-shrink: 0; }
/* React's text-2xl carries a 32px line-height; 1.1 lost 6px per section. */
.legal-section h2 { color: var(--color-white); font-size: 20px; line-height: 1.333; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 1.5rem; }
@media (min-width: 768px) { .legal-section h2 { font-size: 24px; } }
/* React: text-base md:text-lg. The body stayed at 16px, which is most of
   the 213px these pages were short. */
.legal-section p { color: rgba(255,255,255,0.6); font-size: 1rem; line-height: 1.8; font-weight: 300; margin: 0; }
@media (min-width: 768px) { .legal-section p { font-size: 1.125rem; } }
.legal-section a { color: var(--color-primary-active); text-decoration: underline; }
/* React: mt-20 pt-12. */
.legal-page__updated { max-width: 56rem; margin: 5rem auto 0; padding-top: 3rem; border-top: 1px solid rgba(255,255,255,0.1); text-align: center; }
.legal-page__updated p { color: rgba(255,255,255,0.4); font-style: italic; font-size: 0.875rem; line-height: 1.43; text-transform: uppercase; letter-spacing: 0.025em; margin: 0; }
.legal-page__title .accent--info { color: var(--color-info); }
.legal-page--privacy .legal-section__num { color: var(--color-info); }

/* ==========================================================================
   Contact page
   ========================================================================== */
.contact-page { position: relative; overflow: hidden; background: var(--color-black); color: var(--color-white); padding: 128px 1rem 8rem; }
@media (min-width: 640px) { .contact-page { padding-left: 2rem; padding-right: 2rem; } }
@media (min-width: 768px) { .contact-page { padding-top: 160px; padding-left: 3rem; padding-right: 3rem; } }
@media (min-width: 1024px) { .contact-page { padding-left: 76px; padding-right: 76px; } }

.contact-page__blobs { position: absolute; inset: 0; max-width: 1920px; margin-inline: auto; pointer-events: none; z-index: 0; }
.contact-page__blob { position: absolute; filter: blur(140px); border-radius: 60% 40% 70% 30% / 40% 50% 60% 70%; }
.contact-page__blob-1 {
	top: 10%; left: 10%; width: 60%; height: 60%;
	opacity: 0.3; transform: rotate(15deg);
	background: linear-gradient(135deg, #001AFF 0%, #7000FF 40%, #e98827 100%);
}
.contact-page__blob-2 {
	bottom: 10%; right: 0; width: 50%; height: 60%;
	opacity: 0.25; transform: rotate(-25deg);
	border-radius: 40% 60% 30% 70% / 60% 40% 50% 50%;
	background: linear-gradient(110deg, #1049de 0%, #7000FF 50%, #FF4D00 100%);
}

/* max-width without the container's 16px padding rendered 1290 of content
   at x=307 instead of React's 1258 at x=323 — the same gap the case-study
   grids had. */
/* `minmax(0, 1fr)`, not the implicit `minmax(auto, 1fr)`: the form column's
   min-content width exceeds the track on a phone, so an `auto` minimum grew
   the track to 385px inside a 311px column and .contact-page's overflow:hidden
   quietly clipped the heading and the form. Same failure the legal sections
   had. */
.contact-page__grid { position: relative; z-index: 1; max-width: var(--container-max); margin-inline: auto; padding-inline: 1rem; display: grid; grid-template-columns: minmax(0, 1fr); gap: 4rem; align-items: center; }
@media (min-width: 1024px) { .contact-page__grid { grid-template-columns: 1fr 1fr; gap: 6rem; } }
/* React's title sits on a 1.25 line box, not the theme's heading 1.1. */
.contact-page__title { font-size: 36px; line-height: 1.25; margin-bottom: 1.5rem; }
@media (min-width: 640px) { .contact-page__title { font-size: 48px; } }
@media (min-width: 1024px) { .contact-page__title { font-size: 64px; } }
.contact-page__title .accent { color: var(--color-primary-active); }
/* Block-editor conversion: the accent line is now its own heading block
   (className "contact-page__title contact-page__title--accent") rather than
   a nested <span class="accent">, so the descendant rule above never
   matches it. Same specificity (0-2-0) as that rule, kept directly after it,
   using the same --color-primary-active token so the accent color matches
   the original markup exactly. */
.contact-page__title.contact-page__title--accent { color: var(--color-primary-active); }
/* The title is two adjacent heading blocks (one per bound field) standing in
   for the original single <h1> with a <br>, and React likewise renders it as
   one heading. Drop the first line's bottom margin so the two lines sit on
   consecutive line boxes instead of 24px apart; the last line keeps its margin
   to separate the title from the lede below. */
.contact-page__title:not(:last-of-type) { margin-bottom: 0; }
.contact-page__lede { color: rgba(255,255,255,0.7); max-width: 28rem; margin-bottom: 3rem; font-size: 1.125rem; line-height: 1.556; }
.contact-page__email-row { display: flex; align-items: center; gap: 1.25rem; }
.contact-page__email-icon { width: 48px; height: 48px; border-radius: 50%; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--color-primary-active); }
.contact-page__email-row h4 { font-family: var(--font-aeroport); font-weight: 600; letter-spacing: 0.02em; font-size: 1.125rem; margin-bottom: 0.25rem; }
.contact-page__email-row a { color: rgba(255,255,255,0.6); }
.contact-page__email-row a:hover { color: var(--color-primary-active); }

.contact-form-card {
	position: relative;
	background: rgba(10,11,16,0.5);
	backdrop-filter: blur(4px);
	-webkit-backdrop-filter: blur(4px);
	border: 1px solid rgba(255,255,255,0.1);
	border-radius: 32px;
	box-shadow: 0 25px 50px -12px rgba(0,0,0,0.5);
	padding: 2rem 1rem;
}
@media (min-width: 640px) { .contact-form-card { padding: 3rem; } }

/* Fluent Forms.
   The two-column rows (company/email, phone/service, budget/timeline) are
   real Fluent Forms container elements built by `wp brickweb seed-contact-form`,
   so the column layout is the plugin's own and this stylesheet must not impose
   a competing grid. An earlier version did exactly that — a `fieldset` grid
   with hard-coded nth-of-type spans, written when the page still rendered
   Fluent Forms' stock 5-field demo form. Once the real containers arrived it
   put Full Name beside the company/email row and squeezed each container into
   half width. Left as normal flow on purpose.
   Metrics below match the React reference: 50px controls, 8px label gap,
   24px between rows, 150px textarea. */
.contact-form-card fieldset {
	display: block;
	border: 0;
	margin: 0;
	padding: 0;
}
/* Rows are either a plain group or a two-column container, and only the
   container carries the row spacing — the groups nested inside one must stay
   flush or the two columns drift apart vertically. */
.contact-form-card .ff-el-group,
.contact-form-card .ff-t-container { margin-bottom: 1.5rem; }
/* Below Fluent Forms' column breakpoint the two cells stack, so the first of
   the pair still needs the row gap; side by side it must be flush or the two
   columns drift apart vertically. */
.contact-form-card .ff-t-cell:last-child .ff-el-group { margin-bottom: 0; }
@media (min-width: 768px) {
	.contact-form-card .ff-t-container .ff-el-group { margin-bottom: 0; }
}
.contact-form-card .ff_submit_btn_wrapper { margin-bottom: 0; }

.contact-form-card .ff-el-form-control,
.contact-form-card select.ff-el-form-control,
.contact-form-card textarea.ff-el-form-control {
	background: rgba(255,255,255,0.05) !important;
	border: 1px solid rgba(255,255,255,0.1) !important;
	color: var(--color-white) !important;
	border-radius: 12px !important;
	padding: 0.75rem 1rem !important;
	min-height: 50px;
}
.contact-form-card textarea.ff-el-form-control { min-height: 122px; }
.contact-form-card .ff-el-form-control::placeholder { color: rgba(255,255,255,0.3) !important; }
/* .ff-el-input--label is the WRAPPER div Fluent Forms puts around the <label>,
   not the label itself — a `label.ff-el-input--label` selector matches nothing
   here, which is how an earlier version of this block silently did nothing. */
.contact-form-card .ff-el-input--label { margin-bottom: 0.5rem !important; }
.contact-form-card .ff-el-input--label label {
	color: rgba(255,255,255,0.8) !important;
	font-weight: 500 !important;
	font-size: 0.875rem !important;
	line-height: 1.43 !important;
	display: block;
	margin: 0;
}
.contact-form-card .ff_submit_btn_wrapper { padding-top: 1rem; }
.contact-form-card .ff-btn-submit {
	background: var(--color-primary) !important;
	border-radius: 999px !important;
	font-weight: 700 !important;
	width: 100%;
	min-height: 56px;
	padding: 0.9rem !important;
}

/* ==========================================================================
   Our Work archive
   ========================================================================== */
.work-filter-bar { position: sticky; top: 0; z-index: 30; background: var(--color-white); border-bottom: 1px solid rgba(0,0,0,0.08); overflow-x: auto; }
.work-filter-bar__inner { display: flex; gap: 2.5rem; justify-content: center; padding: 0.75rem 2rem; width: max-content; margin-inline: auto; }
.work-filter-btn { background: none; border: none; padding: 1rem 0; font-family: var(--font-montserrat); font-weight: 700; font-size: 14px; color: rgba(0,0,0,0.6); white-space: nowrap; border-bottom: 3px solid transparent; }
@media (min-width: 768px) { .work-filter-btn { font-size: 18px; } }
.work-filter-btn.is-active { color: #e98827; border-bottom-color: #e98827; }
.work-grid-section { background: var(--color-black); padding: 4rem 0; }
/* React's grid is 96px between rows, 48px between columns. */
.work-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 6rem 3rem; }
@media (min-width: 768px) { .work-grid { grid-template-columns: 1fr 1fr; } }
.work-card { display: block; }
.work-card__img { aspect-ratio: 1 / 1; border-radius: 4px; overflow: hidden; margin-bottom: 2rem; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); }
.work-card__img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease-reveal); }
.work-card:hover .work-card__img img { transform: scale(1.05); }
/* React's card title sits on a 1.25 line box, not the theme's heading 1.1. */
.work-card h3 { color: var(--color-white); font-family: var(--font-montserrat); font-size: 24px; line-height: 1.25; margin-bottom: 1rem; }
@media (min-width: 768px) { .work-card h3 { font-size: 32px; } }
.work-card p { color: rgba(255,255,255,0.6); max-width: 32rem; line-height: 1.625; margin-bottom: 1rem; }
.work-card__tags { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.work-card__tags span { padding: 0.5rem 1.25rem; border: 1px solid rgba(255,255,255,0.2); border-radius: 999px; font-size: 0.6875rem; line-height: 1.5; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: rgba(255,255,255,0.8); }
.work-card.is-hidden { display: none; }

/* ==========================================================================
   Single project (case study)
   ========================================================================== */
.project-hero { position: relative; overflow: hidden; background: var(--color-black); color: var(--color-white); padding: 180px 1rem 10rem; text-align: center; }
.project-hero > .container { position: relative; z-index: 2; }
.project-hero__eyebrow { color: #3273f6; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; font-size: 13px; line-height: 1.5; margin-top: 0; margin-bottom: 1.5rem; }
@media (min-width: 768px) { .project-hero__eyebrow { font-size: 14px; } }
.project-hero__title { font-size: 36px; font-weight: 700; margin-bottom: 2rem; line-height: 1.1; }
@media (min-width: 768px) { .project-hero__title { font-size: 48px; } }
@media (min-width: 1024px) { .project-hero__title { font-size: 56px; } }
.project-hero__summary { color: #e2e2e2; font-weight: 500; max-width: 700px; margin-inline: auto; margin-block: 0; font-size: 16px; line-height: 1.6; }
@media (min-width: 768px) { .project-hero__summary { font-size: 18px; } }
@media (min-width: 1024px) { .project-hero__summary { font-size: 20px; } }

/* React puts the hero image in a wrapper whose bottom half is white, so the
   image straddles the black/white boundary at its own midpoint. The theme
   previously pulled the image up 4rem into the black hero instead, which put
   the boundary 64px below the image top -- measured, not inferred. The
   gradient reproduces the original without extra markup beyond the band. */
.project-hero-image-band { background: linear-gradient(to bottom, var(--color-black) 50%, var(--color-white) 50%); }
.project-hero-image { max-width: var(--container-max); margin-inline: auto; padding: 0 1rem; position: relative; z-index: 1; }
/* React sets explicit heights per breakpoint (h-[300px] md:h-[500px]
   lg:h-[650px]) rather than a ratio. An earlier fix here used aspect-ratio
   16/10 clamped at 650px, which only agrees with the original at container
   widths near 1040px and above: at 390px it rendered 215px against React's
   300px. Explicit heights match at every width. */
.project-hero-image__frame { position: relative; width: 100%; height: 300px; border-radius: 16px; overflow: hidden; box-shadow: 0 20px 50px rgba(0,0,0,0.4); }
@media (min-width: 768px) { .project-hero-image__frame { height: 500px; } }
@media (min-width: 1024px) { .project-hero-image__frame { height: 650px; } }
.project-hero-image__frame img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s ease; }
.project-hero-image__frame:hover img { transform: scale(1.03); }

.project-body { background: var(--color-white); color: var(--color-black); padding: 4rem 1rem; }
@media (min-width: 768px) { .project-body { padding: 6rem 1rem; } }
@media (min-width: 1024px) { .project-body { padding: 8rem 1rem; } }
.project-tech-heading { text-align: center; font-weight: 500; font-size: 1.125rem; line-height: 1.5; margin-top: 0; margin-bottom: 2rem; }
.project-tech-pills { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; margin-bottom: 6rem; }
.project-tech-pills span { padding: 0.75rem 1.5rem; border: 1px solid #d1d5db; border-radius: 999px; font-size: 0.9375rem; line-height: 1.5; letter-spacing: 0.025em; font-weight: 500; color: #1f2937; }
.project-content-grid { display: grid; grid-template-columns: 1fr; gap: 4rem; max-width: var(--container-max); margin: 0 auto; padding-inline: 1rem; }
@media (min-width: 1024px) { .project-content-grid { grid-template-columns: 1fr 1fr; gap: 6rem; } }
.project-summary-col p { font-size: 18px; line-height: 1.8; color: #1f2937; margin-top: 0; margin-bottom: 3rem; }
@media (min-width: 768px) { .project-summary-col p { font-size: 20px; } }
.project-summary-col .external-link-label { text-transform: uppercase; font-size: 0.8125rem; font-weight: 700; color: #6b7280; letter-spacing: 0.05em; margin-bottom: 1rem; }
.project-summary-col hr { border: none; border-top: 1px solid #e5e7eb; margin-bottom: 1rem; }
.project-summary-col .btn-external { display: inline-flex; background: var(--color-black); color: var(--color-white); padding: 0.75rem 1.5rem; border-radius: 999px; font-size: 0.9375rem; }
/* Case-study bodies come from the_content() now, so the headings and
   paragraphs are FLAT SIBLINGS rather than one wrapper div per section. The
   container's 3rem flex gap therefore applied between a heading and its own
   paragraph as well as between sections, and flex margins do not collapse:
   measured 81px inside a section against 65px between them, which inverted the
   grouping. Spacing is set per adjacency instead. React renders 16px from a
   heading to its body and 48px between sections. The `> * + *` default also
   covers lists, images and quotes, which a case-study body can now contain. */
.project-sections { display: flex; flex-direction: column; gap: 0; }
.project-sections > * { margin-top: 0; margin-bottom: 0; }
.project-sections > * + * { margin-top: 1rem; }
.project-sections > * + h3 { margin-top: 3rem; }
.project-sections h3 { font-size: 1.375rem; line-height: 1.5; color: var(--color-info); }
.project-sections p { color: #4b5563; line-height: 1.7; font-size: 1.0625rem; }

.project-gallery { max-width: var(--container-max); margin: 6rem auto 0; padding: 0 1rem; }
.project-gallery__grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
@media (min-width: 768px) { .project-gallery__grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1024px) { .project-gallery__grid { gap: 2rem; } }
.project-gallery__grid img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: 16px; transition: transform 0.6s ease; }
.project-gallery__grid img:hover { transform: scale(1.03); }
/* Same half-and-half band as the hero image, inverted: white above the
   midpoint, black below, with the image flush to the wrapper. */
.project-gallery--wide { background: linear-gradient(to bottom, var(--color-white) 50%, var(--color-black) 50%); padding: 0 1rem; }
.project-gallery--wide img { width: 100%; aspect-ratio: 21/9; object-fit: cover; border-radius: 16px; max-width: calc(var(--container-max) - 2rem); margin-inline: auto; display: block; }

.project-testimonial { background: var(--color-black); color: var(--color-white); text-align: center; padding: 5rem 1rem 6rem; }
@media (min-width: 768px) { .project-testimonial { padding-top: 7rem; } }
.project-testimonial__label { color: #3273f6; text-transform: uppercase; letter-spacing: 0.2em; font-weight: 700; font-size: 0.875rem; margin-bottom: 2.5rem; }
.project-testimonial blockquote { font-family: var(--font-aeroport); font-style: italic; font-size: 24px; max-width: 50rem; margin: 0 auto 3rem; line-height: 1.4; }
@media (min-width: 768px) { .project-testimonial blockquote { font-size: 36px; } }
@media (min-width: 1024px) { .project-testimonial blockquote { font-size: 42px; } }
.project-testimonial__author { color: #3273f6; font-weight: 700; font-size: 1.125rem; }
.project-testimonial__role { color: #9ca3af; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; }

.related-projects { background: var(--color-white); padding: 6rem 1rem; }
.related-projects h3 { text-align: center; color: var(--color-info); text-transform: uppercase; font-weight: 700; letter-spacing: 0.1em; font-size: 1.125rem; line-height: 1.5; margin-bottom: 4rem; }
.related-projects__grid { display: grid; grid-template-columns: 1fr; gap: 2rem; max-width: var(--container-max); margin: 0 auto; padding-inline: 1rem; }
@media (min-width: 768px) { .related-projects__grid { grid-template-columns: repeat(3, 1fr); } }
.related-card__img { aspect-ratio: 1/1; border-radius: 12px; overflow: hidden; margin-bottom: 1.5rem; background: #f3f4f6; }
.related-card__img img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s ease; }
.related-card:hover .related-card__img img { transform: scale(1.1); }
.related-card h4 { font-size: 1.25rem; line-height: 1.5; color: #111827; }

/* ==========================================================================
   404
   ========================================================================== */
.error-404-page { min-height: 100vh; background: var(--color-black); color: var(--color-white); display: flex; align-items: center; padding: 2rem; }
.error-404-page__inner { max-width: 48rem; margin: 0 auto; text-align: center; }
.error-404-page__eyebrow { color: var(--color-info); text-transform: uppercase; letter-spacing: 0.2em; font-weight: 700; font-size: 0.875rem; margin-bottom: 1.5rem; }
.error-404-page h1 { font-size: 36px; margin-bottom: 1.5rem; line-height: 1; }
@media (min-width: 640px) { .error-404-page h1 { font-size: 48px; } }
@media (min-width: 1024px) { .error-404-page h1 { font-size: 72px; } }
.error-404-page p { color: rgba(255,255,255,0.7); font-size: 1.125rem; max-width: 42rem; margin: 0 auto 2.5rem; line-height: 1.6; }
.error-404-page__actions { display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }

/* ==========================================================================
   Cookie consent banner
   Ported from the React source's CookieConsent.tsx. Rendered hidden; the
   analytics script reveals it and runs the slide-up.
   ========================================================================== */
.cookie-consent {
	position: fixed;
	bottom: 1.5rem;
	left: 1.5rem;
	right: 1.5rem;
	z-index: 9999;
	display: flex;
	justify-content: center;
	pointer-events: none;
	opacity: 0;
	transform: translateY(100px);
	transition: opacity 0.5s cubic-bezier(0.16, 1, 0.3, 1), transform 0.5s cubic-bezier(0.16, 1, 0.3, 1);
}
.cookie-consent.is-visible { opacity: 1; transform: translateY(0); }
.cookie-consent__panel {
	position: relative;
	overflow: hidden;
	pointer-events: auto;
	width: 100%;
	max-width: 56rem;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: space-between;
	gap: 1.5rem;
	padding: 1.5rem;
	border-radius: 24px;
	background: rgba(10, 11, 16, 0.9);
	backdrop-filter: blur(12px);
	border: 1px solid rgba(255, 255, 255, 0.1);
	box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
}
.cookie-consent__accent {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 1px;
	background: linear-gradient(to right, transparent, rgba(233, 136, 39, 0.4), transparent);
}
.cookie-consent__copy { flex: 1; }
.cookie-consent__title {
	font-family: var(--font-aeroport);
	color: var(--color-white);
	font-weight: 700;
	font-size: 1.125rem;
	line-height: 1.5;
	margin: 0 0 0.5rem;
}
.cookie-consent__text {
	font-family: var(--font-inter);
	color: rgba(255, 255, 255, 0.6);
	font-size: 0.875rem;
	line-height: 1.625;
	margin: 0;
}
.cookie-consent__text a { color: #e98827; }
.cookie-consent__text a:hover { text-decoration: underline; }
.cookie-consent__actions {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 1rem;
	width: 100%;
	flex-shrink: 0;
}
.cookie-consent__decline,
.cookie-consent__accept {
	flex: 1;
	border-radius: 12px;
	font-size: 0.875rem;
	cursor: pointer;
	transition: all 0.2s ease;
}
.cookie-consent__decline {
	padding: 0.75rem 1.5rem;
	font-family: var(--font-inter);
	font-weight: 500;
	color: rgba(255, 255, 255, 0.5);
	background: transparent;
	border: 1px solid transparent;
}
.cookie-consent__decline:hover {
	color: var(--color-white);
	background: rgba(255, 255, 255, 0.05);
	border-color: rgba(255, 255, 255, 0.1);
}
.cookie-consent__accept {
	padding: 0.75rem 2rem;
	font-family: var(--font-aeroport);
	font-weight: 700;
	color: var(--color-black);
	background: #e98827;
	border: none;
	box-shadow: 0 10px 15px -3px rgba(233, 136, 39, 0.2);
}
.cookie-consent__accept:hover { transform: scale(1.02); }
.cookie-consent__accept:active { transform: scale(0.98); }

@media (min-width: 768px) {
	.cookie-consent__panel { flex-direction: row; padding: 2rem; }
	.cookie-consent__text { font-size: 1rem; }
	.cookie-consent__actions { width: auto; }
	.cookie-consent__decline,
	.cookie-consent__accept { flex: none; }
}

@media (prefers-reduced-motion: reduce) {
	.cookie-consent { transition: opacity 0.01ms; transform: none; }
	.cookie-consent__accept:hover,
	.cookie-consent__accept:active { transform: none; }
}

/* ==========================================================================
   Blog — grid and cards
   ========================================================================== */
.blog-section { padding: 4rem 0 6rem; }
.post-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem; }
@media (min-width: 768px) { .post-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1024px) { .post-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.post-card { background: var(--color-white); border: 1px solid var(--color-border); border-radius: var(--radius-lg); overflow: hidden; display: flex; }
.post-card__link { display: flex; flex-direction: column; width: 100%; color: inherit; text-decoration: none; }

/* The artwork is generated from the post ID, so every post has a visual
   anchor without anyone sourcing an image. A featured image replaces it. */
.post-card__art { position: relative; aspect-ratio: 16 / 10; background: linear-gradient(135deg, var(--art-from, #F5A623), var(--art-to, #E98827)); }
.post-card__art--photo { background: #f3f4f6; }
.post-card__art--photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-card__art::after { content: ''; position: absolute; inset: 0; background-image: url('../images/logo/corner-left.png'); background-repeat: no-repeat; background-position: center; background-size: 55%; opacity: 0.12; }
.post-card__art--photo::after { content: none; }
.post-card__art--v1::after { transform: rotate(45deg); }
.post-card__art--v2::after { transform: rotate(90deg); }
.post-card__art--v3::after { transform: rotate(135deg); }
.post-card__art--v4::after { transform: rotate(180deg); }
.post-card__art--v5::after { transform: rotate(225deg); }

.post-card__body { padding: 1.5rem; display: flex; flex-direction: column; gap: 0.5rem; flex: 1; }
.post-card__eyebrow { font-family: var(--font-montserrat); font-size: 0.75rem; font-weight: 700; line-height: 1.333; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-info); margin: 0; }
/* Long unbroken titles (a URL, a class name) must wrap rather than widen the
   card and push the page into horizontal scroll at 390px. */
.post-card__title { font-family: var(--font-aeroport); font-size: 1.25rem; line-height: 1.3; margin: 0; overflow-wrap: anywhere; }
.post-card__excerpt { font-size: 0.9375rem; line-height: 1.625; color: #4b5563; margin: 0; }
.post-card__meta { margin: auto 0 0; padding-top: 0.75rem; font-size: 0.8125rem; line-height: 1.5; color: var(--color-muted); display: flex; gap: 0.5rem; align-items: center; }
.post-card:hover .post-card__title { color: var(--color-info); }
.blog-empty { text-align: center; color: var(--color-muted); padding: 4rem 0; }

/* Blog — filter bar and pagination */
.blog-filter-bar { border-bottom: 1px solid var(--color-border); }
.blog-filter-bar__inner { max-width: var(--container-max); margin: 0 auto; padding: 0 1rem; display: flex; gap: 0.5rem; overflow-x: auto; }
.blog-filter-btn { padding: 1rem 1.25rem; font-family: var(--font-montserrat); font-size: 0.875rem; font-weight: 600; line-height: 1.5; color: var(--color-muted); text-decoration: none; white-space: nowrap; border-bottom: 2px solid transparent; }
.blog-filter-btn:hover { color: var(--color-black); }
.blog-filter-btn.is-active { color: var(--color-info); border-bottom-color: var(--color-info); }

.blog-pagination { margin-top: 4rem; }
.blog-pagination .nav-links { display: flex; gap: 0.5rem; justify-content: center; flex-wrap: wrap; }
.blog-pagination .page-numbers { display: inline-flex; align-items: center; justify-content: center; min-width: 44px; height: 44px; padding: 0 0.75rem; border: 1px solid var(--color-border); border-radius: var(--radius); font-size: 0.9375rem; line-height: 1.5; color: var(--color-black); text-decoration: none; }
.blog-pagination .page-numbers.current { background: var(--color-info); border-color: var(--color-info); color: var(--color-white); }

/* ==========================================================================
   Blog — single post
   ========================================================================== */
.post-single__header { padding: max(110px, 11vw) 0 2rem; text-align: center; }
.post-single__eyebrow { font-family: var(--font-montserrat); font-size: 0.8125rem; font-weight: 700; line-height: 1.5; letter-spacing: 0.08em; text-transform: uppercase; margin: 0 0 1rem; }
.post-single__eyebrow a { color: var(--color-info); text-decoration: none; }
.post-single__title { font-family: var(--font-aeroport); font-size: clamp(32px, 4vw, 56px); line-height: 1.15; letter-spacing: -0.02em; max-width: 900px; margin: 0 auto 1.5rem; overflow-wrap: anywhere; }
.post-single__meta { display: flex; gap: 0.5rem; justify-content: center; align-items: center; flex-wrap: wrap; font-size: 0.9375rem; line-height: 1.5; color: var(--color-muted); margin: 0; }

/* The artwork is generated from the post ID, so every post has a visual
   anchor without anyone sourcing an image. A featured image replaces it.
   The brand-mark overlay is scoped to ::after, so we need position: relative
   and the overlay rules themselves to replicate the card's rotated marks. */
.post-single__art { position: relative; aspect-ratio: 16 / 9; border-radius: var(--radius-lg); overflow: hidden; margin: 0 auto 3rem; max-width: 900px; background: linear-gradient(135deg, var(--art-from, #F5A623), var(--art-to, #E98827)); }
.post-single__art::after { content: ''; position: absolute; inset: 0; background-image: url('../images/logo/corner-left.png'); background-repeat: no-repeat; background-position: center; background-size: 55%; opacity: 0.12; }
.post-single__art--photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.post-single__art--photo::after { content: none; }
.post-card__art--v1.post-single__art::after { transform: rotate(45deg); }
.post-card__art--v2.post-single__art::after { transform: rotate(90deg); }
.post-card__art--v3.post-single__art::after { transform: rotate(135deg); }
.post-card__art--v4.post-single__art::after { transform: rotate(180deg); }
.post-card__art--v5.post-single__art::after { transform: rotate(225deg); }

/* The reading column is capped well below the container: long-form body text
   past roughly 75 characters a line is measurably harder to read. */
.post-body { max-width: 720px; margin: 0 auto; font-size: 1.125rem; line-height: 1.625; color: #1f2937; }
.post-body > * + * { margin-top: 1.5rem; }
.post-body h2 { font-family: var(--font-aeroport); font-size: 2rem; line-height: 1.25; margin-top: 3rem; }
.post-body h3 { font-family: var(--font-aeroport); font-size: 1.5rem; line-height: 1.3; margin-top: 2.5rem; }
.post-body h4 { font-family: var(--font-inter); font-size: 1.25rem; line-height: 1.4; margin-top: 2rem; }
.post-body ul, .post-body ol { padding-left: 1.5rem; }
.post-body li + li { margin-top: 0.5rem; }
.post-body a { color: var(--color-info); text-underline-offset: 3px; }
.post-body blockquote { border-left: 3px solid var(--color-primary); padding-left: 1.5rem; font-size: 1.25rem; line-height: 1.5; color: #374151; margin-left: 0; }
.post-body code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9em; background: #f3f4f6; padding: 0.15em 0.4em; border-radius: 4px; }
.post-body pre { background: #0e0f14; color: #e5e7eb; padding: 1.25rem; border-radius: var(--radius); overflow-x: auto; font-size: 0.9375rem; line-height: 1.6; }
.post-body pre code { background: none; padding: 0; color: inherit; }
.post-body img { max-width: 100%; height: auto; border-radius: var(--radius); }
.post-body figcaption { font-size: 0.875rem; line-height: 1.5; color: var(--color-muted); text-align: center; margin-top: 0.75rem; }

.related-posts { padding: 5rem 0 2rem; }
.related-posts__title { font-family: var(--font-aeroport); font-size: 1.75rem; line-height: 1.25; margin: 0 0 2rem; }
@media (min-width: 768px) { .post-single__header { padding-bottom: 2.5rem; } }
