/* =========================================================
   KEIBI — main stylesheet
   Self-hosted fonts, design tokens, base, layout, components.
   Single file by design: fewer HTTP requests = faster TTFB/LCP.

   Design language: restrained — black/white with a single accent
   used as full-bleed colour blocks (not scattered across buttons),
   sharp edges, plain text links instead of pill buttons, and a bold
   display face for headings. Motion is limited to on-scroll reveals
   (opacity/transform via IntersectionObserver) — no scroll-jacking,
   no custom cursor. The homepage is the one exception: a brand intro
   (see the "Homepage hero intro" section below and initHeroIntro() in
   main.js) plays inline in the hero before the header/tagline reveal.
   ========================================================= */

/* ---- Fonts (self-hosted, Latin subset only — covers EN/ES/CAT) ---- */
@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/inter-400-std.woff2') format('woff2');
}
@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/inter-500-std.woff2') format('woff2');
}
@font-face {
	font-family: 'Inter';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/inter-600-std.woff2') format('woff2');
}
@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/archivo-700-std.woff2') format('woff2');
}
@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 800;
	font-display: swap;
	src: url('../fonts/archivo-800-std.woff2') format('woff2');
}
@font-face {
	font-family: 'Archivo';
	font-style: normal;
	font-weight: 900;
	font-display: swap;
	src: url('../fonts/archivo-900-std.woff2') format('woff2');
}
@font-face {
	font-family: 'Anton';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/anton-400-std.woff2') format('woff2');
}

/* ---- Design tokens ---- */
:root {
	--color-orange: #ff4000;
	--color-orange-dark: #cc3300;
	/* Static warm mesh — three soft blobs (orange/red/amber) layered over
	   the flat orange fill. Deliberately static: a WebGL version proved
	   unreliable. */
	--mesh-warm-blobs:
		radial-gradient(circle at 28% 32%, #d77300 0%, transparent 42%),
		radial-gradient(circle at 74% 24%, #d70000 0%, transparent 42%),
		radial-gradient(circle at 50% 78%, #ff4000 0%, transparent 50%);
	--color-red: #c4000a;
	--color-green: #097f00;
	--color-teal: #2c5c6a;
	--color-black: #141212;
	--color-ink: #221f1d;
	--color-body: #4a4542;
	--color-white: #ffffff;
	--color-offwhite: #f7f6f4;
	--color-line: #e7e2dd;

	--font-display: 'Archivo', 'Arial Black', sans-serif;
	--font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

	--container-w: 1240px;
	--gutter: clamp(1.25rem, 4vw, 3rem);
	--radius: 2px;
	--radius-sm: 2px;

	--ease: cubic-bezier(0.16, 1, 0.3, 1);
	--speed: 0.5s;
}

/* ---- Reset & base ---- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	*, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
}
body {
	margin: 0;
	font-family: var(--font-body);
	font-size: 1rem;
	line-height: 1.6;
	color: var(--color-body);
	background: var(--color-white);
	-webkit-font-smoothing: antialiased;
}
img, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 {
	font-family: var(--font-display);
	font-weight: 800;
	color: var(--color-ink);
	line-height: 1.02;
	margin: 0 0 0.5em;
	letter-spacing: -0.01em;
}
h1 { font-size: clamp(2.75rem, 7vw, 6rem); font-weight: 900; }
h2 { font-size: clamp(1.75rem, 3.5vw, 2.75rem); }
h3 { font-size: 1.15rem; }
p { margin: 0 0 1em; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button { font: inherit; cursor: pointer; background: none; border: 0; color: inherit; }
input, textarea { font: inherit; }

.container { max-width: var(--container-w); margin-inline: auto; padding-inline: var(--gutter); }

.screen-reader-text, .skip-link:not(:focus) {
	position: absolute !important;
	width: 1px; height: 1px;
	overflow: hidden;
	clip: rect(1px,1px,1px,1px);
	white-space: nowrap;
}
.skip-link:focus {
	position: fixed; top: 1rem; left: 1rem; z-index: 9999;
	background: var(--color-ink); color: var(--color-white);
	padding: 0.75em 1.25em;
}

:focus-visible { outline: 2px solid var(--color-orange); outline-offset: 3px; }

/* ---- Buttons / links ----
   No filled pill buttons anywhere — plain, bold text links with a
   sliding arrow, same register as the primary nav. */
.button {
	display: inline-flex; align-items: center; gap: 0.5em;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1rem;
	color: var(--color-ink);
	padding-bottom: 0.15em;
	border-bottom: 1px solid currentColor;
}
.button::after {
	content: '\2192';
	display: inline-block;
	transition: transform 0.3s var(--ease);
}
.button:hover::after, .button:focus-visible::after { transform: translateX(4px); }
.button:hover, .button:focus-visible { color: var(--color-orange); }
.button--outline { border-bottom-color: currentColor; }
.button--small { font-size: 0.85rem; }
.button--large { font-size: 1.15rem; }

/* ---- Header ---- */
.site-header {
	position: sticky; top: 0; z-index: 500;
	border-bottom: 1px solid var(--color-line);
}
/* The blur lives on a pseudo-element, not .site-header itself, because
   backdrop-filter on an ancestor creates a CSS containing block for any
   position:fixed descendant (like the mobile nav below) — that traps it
   inside the header's own box instead of the viewport. */
.site-header::before {
	content: '';
	position: absolute; inset: 0; z-index: -1;
	background: rgba(255,255,255,0.92);
	backdrop-filter: blur(10px);
}
.site-header__inner { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1.5rem; padding-block: 1rem; }
.site-header__logo { justify-self: start; }
.primary-nav { justify-self: center; }
.site-logo { display: inline-flex; }
.site-logo img { height: 36px; width: auto; }
.primary-nav__list { display: flex; gap: 2rem; }
.primary-nav__list a { font-weight: 400; font-size: 0.95rem; }
.primary-nav__list a:hover { color: var(--color-orange); }
.site-header__meta { justify-self: end; display: flex; align-items: center; gap: 1.5rem; }

.menu-toggle { display: flex; flex-direction: column; gap: 5px; padding: 0.5em; }
.menu-toggle__bar { width: 22px; height: 2px; background: var(--color-ink); transition: transform 0.3s var(--ease), opacity 0.3s; }
@media (min-width: 900px) { .menu-toggle { display: none; } }

@media (max-width: 899px) {
	/* justify-self: stretch overrides the desktop .primary-nav rule's
	   justify-self: center — without it, this fixed full-screen overlay
	   stays sized/centered to its old auto-placed grid-track content
	   width (a narrow column in the middle of .site-header__inner's grid)
	   instead of stretching to the viewport, even though inset: 0 sets
	   left/right to 0. Caught testing on a real mobile viewport. */
	.primary-nav { position: fixed; inset: 0; top: 72px; justify-self: stretch; background: var(--color-white); padding: 2rem var(--gutter); transform: translateY(-8px); opacity: 0; visibility: hidden; transition: opacity 0.3s var(--ease), transform 0.3s var(--ease), visibility 0.3s; }
	.primary-nav.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
	.primary-nav__list { flex-direction: column; gap: 1.5rem; font-size: 1.5rem; }
}

/* ---- Language switcher (pill slider — the one deliberately rounded,
   playful element, since it's a control, not a CTA) ---- */
.lang-switch {
	position: relative;
	display: inline-flex;
	background: var(--color-offwhite);
	border-radius: 100px;
	padding: 4px;
	gap: 2px;
}
.lang-switch__option {
	position: relative; z-index: 1;
	padding: 0.35em 0.85em;
	font-size: 0.75rem; font-weight: 700; letter-spacing: 0.04em;
	color: var(--color-body);
	border-radius: 100px;
	transition: color 0.3s var(--ease);
}
.lang-switch__option.is-active { color: var(--color-white); }
.lang-switch__thumb {
	/* width/left set in px by initLanguageSwitcher() to match the active
	   option's own rendered box — "EN"/"CAT"/"ES" aren't equal width, so
	   a fixed one-third share left the thumb mismatched with the text on
	   at least one of them. These are just pre-JS/no-JS fallbacks. */
	position: absolute; top: 4px; left: 4px; bottom: 4px;
	width: calc((100% - 8px) / 3);
	background: var(--color-orange);
	border-radius: 100px;
	transition: left 0.35s var(--ease), width 0.35s var(--ease);
	z-index: 0;
}

/* ---- Sections shared ---- */
section { padding-block: clamp(3rem, 8vw, 7rem); }
.section-heading { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.5rem; margin-bottom: 2.5rem; }
.section-eyebrow { font-size: 0.85rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-orange); margin-bottom: 1.5rem; }

/* Text reveals: a gentle rise + fade. */
[data-reveal] { opacity: 0; transform: translateY(28px); transition: opacity 0.8s var(--ease), transform 0.8s var(--ease); }
[data-reveal].is-visible { opacity: 1; transform: translateY(0); }
.reduce-motion [data-reveal] { opacity: 1 !important; transform: none !important; }

/* Image/card reveals: a slightly slower scale + fade, distinct from the
   text rise above — this is the "reveal" moment for photos and videos. */
[data-reveal-img] { opacity: 0; transform: scale(0.96); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
[data-reveal-img].is-visible { opacity: 1; transform: scale(1); }
.reduce-motion [data-reveal-img] { opacity: 1 !important; transform: none !important; }

/* Directional reveals: used where a group of images should enter from
   different sides (e.g. outer columns from above, centre from below). */
[data-reveal-top] { opacity: 0; transform: translateY(-64px); transition: opacity 1.2s var(--ease), transform 1.2s var(--ease); }
[data-reveal-top].is-visible { opacity: 1; transform: translateY(0); }
[data-reveal-top].is-leaving { opacity: 0; transform: translateY(64px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
[data-reveal-bottom] { opacity: 0; transform: translateY(64px); transition: opacity 1.2s var(--ease), transform 1.2s var(--ease); }
[data-reveal-bottom].is-visible { opacity: 1; transform: translateY(0); }
[data-reveal-bottom].is-leaving { opacity: 0; transform: translateY(-64px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.reduce-motion [data-reveal-top], .reduce-motion [data-reveal-bottom] { opacity: 1 !important; transform: none !important; }
/* Horizontal directional reveals: the two-rectangle "What We Do" layout —
   the top piece enters from the right and keeps moving left on exit, the
   bottom piece enters from the left and keeps moving right on exit. */
/* Property order in these transition lists — opacity, transform, top,
   height, margin-top — matters: the "meet in the middle" override further
   down changes ONLY the "top" slot's duration/delay via the longhand
   transition-duration/transition-delay (not the `transition` shorthand,
   which would replace this whole list instead of adjusting one slot),
   and lines up with it positionally. Keep them in this order, or update
   both places together. */
[data-reveal-right] { opacity: 0; transform: translateX(64px); top: 0; transition: opacity 1.2s var(--ease), transform 1.2s var(--ease), top 1.2s var(--ease), height 1.2s var(--ease), margin-top 1.2s var(--ease); }
[data-reveal-right].is-visible { opacity: 1; transform: translateX(0); }
[data-reveal-right].is-leaving { opacity: 0; transform: translateX(-64px); transition: opacity 1.2s var(--ease), transform 1.2s var(--ease), top 1.2s var(--ease), height 1.2s var(--ease), margin-top 1.2s var(--ease); }
[data-reveal-left] { opacity: 0; transform: translateX(-64px); top: 0; transition: opacity 1.2s var(--ease), transform 1.2s var(--ease), top 1.2s var(--ease), height 1.2s var(--ease), margin-top 1.2s var(--ease); }
[data-reveal-left].is-visible { opacity: 1; transform: translateX(0); }
[data-reveal-left].is-leaving { opacity: 0; transform: translateX(64px); transition: opacity 1.2s var(--ease), transform 1.2s var(--ease), top 1.2s var(--ease), height 1.2s var(--ease), margin-top 1.2s var(--ease); }
.reduce-motion [data-reveal-right], .reduce-motion [data-reveal-left] { opacity: 1 !important; transform: none !important; }
/* Stagger cards across a grid so they cascade in rather than pop together. */
.portfolio-grid > *:nth-child(1), .team-grid > *:nth-child(1), .partners__list > *:nth-child(1) { transition-delay: 0s; }
.portfolio-grid > *:nth-child(2), .team-grid > *:nth-child(2), .partners__list > *:nth-child(2) { transition-delay: 0.08s; }
.portfolio-grid > *:nth-child(3), .team-grid > *:nth-child(3), .partners__list > *:nth-child(3) { transition-delay: 0.16s; }
.portfolio-grid > *:nth-child(4), .team-grid > *:nth-child(4), .partners__list > *:nth-child(4) { transition-delay: 0.24s; }

/* ---- Background patterns (utility classes, pure CSS/no JS) ----
   Drop any of these on a section to give it a living background —
   none of them need a build step, a library, or a <canvas>, so they
   stay within the theme's one-CSS-file/one-JS-file rule.

   .bg-flow    warm animated gradient mesh (brand colours drifting
               through each other), good for a full section background.
   .bg-aurora  two blurred, slowly drifting glow layers over a dark
               base — a softer, moodier alternative to .bg-flow.
   .bg-grain   an additive film-grain texture; pair it WITH .bg-flow
               or .bg-aurora (or any other background) rather than
               using it alone — it has no background colour of its own.

   All three already respect prefers-reduced-motion, and the sitewide
   .reduce-motion class (set from the Customizer toggle) turns them
   off too, matching every other animation in the theme. */
.bg-flow {
	background: linear-gradient(-45deg, var(--color-orange), #d70000, #d77300, #ffad1f);
	background-size: 400% 400%;
	animation: bg-flow-move 18s ease infinite;
}
@keyframes bg-flow-move {
	0% { background-position: 0% 50%; }
	50% { background-position: 100% 50%; }
	100% { background-position: 0% 50%; }
}
.reduce-motion .bg-flow { animation: none; background-position: 50% 50%; }

.bg-aurora {
	position: relative;
	overflow: hidden;
	background: #1a0800;
}
.bg-aurora::before,
.bg-aurora::after {
	content: '';
	position: absolute;
	inset: -25%;
	pointer-events: none;
}
.bg-aurora::before {
	background: linear-gradient(180deg, transparent 0%, rgba(255, 64, 0, 0.4) 30%, rgba(255, 173, 31, 0.22) 50%, transparent 72%);
	filter: blur(60px);
	animation: bg-aurora-drift-1 16s ease-in-out infinite;
}
.bg-aurora::after {
	background: linear-gradient(180deg, transparent 0%, rgba(215, 0, 0, 0.32) 40%, rgba(255, 64, 0, 0.16) 62%, transparent 82%);
	filter: blur(80px);
	animation: bg-aurora-drift-2 22s ease-in-out infinite;
}
@keyframes bg-aurora-drift-1 {
	0%, 100% { transform: translateX(-12%) skewX(-4deg); }
	50% { transform: translateX(12%) skewX(4deg); }
}
@keyframes bg-aurora-drift-2 {
	0%, 100% { transform: translateX(12%) skewX(3deg); }
	50% { transform: translateX(-12%) skewX(-3deg); }
}
.reduce-motion .bg-aurora::before,
.reduce-motion .bg-aurora::after { animation: none; }

.bg-grain { position: relative; }
.bg-grain::after {
	content: '';
	position: absolute;
	inset: -10%;
	pointer-events: none;
	opacity: 0.05;
	mix-blend-mode: overlay;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	animation: bg-grain-shift 0.6s steps(4) infinite;
}
@keyframes bg-grain-shift {
	0% { transform: translate(0, 0); }
	25% { transform: translate(-2%, 2%); }
	50% { transform: translate(2%, -1%); }
	75% { transform: translate(-1%, -2%); }
	100% { transform: translate(0, 0); }
}
.reduce-motion .bg-grain::after { animation: none; }

@media (prefers-reduced-motion: reduce) {
	.bg-flow,
	.bg-aurora::before, .bg-aurora::after,
	.bg-grain::after { animation: none !important; }
}

/* ---- Homepage hero intro (see initHeroIntro() in main.js) ----
   Plays the K_B → KEIBI Lottie draw-on animation directly inside
   .hero__logo — the same box that holds the resting logo for the rest of
   the page's life — instead of a separate preloader overlay with its own
   logo asset: nothing is ever swapped or measured against a second
   element, so there's no way for the logo's size or position to drift.
   The animation's own final frame is pixel-identical to the static PNG
   fallback (same source artwork), so once it completes the rendered SVG
   just stays on that last frame; it never swaps to the PNG on success.
   The header and hero tagline stay hidden until initHeroIntro() starts
   removing body.is-intro partway through the final draw-on segment (or
   immediately as a fallback if Lottie can't load) — started early and
   given a longer transition here so the slide/fade still lands exactly
   when the logo settles, just slower and smoother rather than snapping
   in right at the end. The <noscript> override in header.php covers
   JS-disabled visitors, per the sitewide "degrades to fully visible"
   rule.

   .hero's -70px margin-top (matching .site-header's own ~70px height:
   1rem+1rem padding-block + the 36px logo + 1px border) pulls it up to
   start at the very top of the page, underneath the header, instead of
   in the gap below it. The header already renders as a semi-transparent
   blurred bar over whatever's behind it (see .site-header::before), so
   this costs nothing once it's visible — but it also means there's no
   separate "bar" space for a mismatched colour to ever show through
   during the intro: it's the hero's own correctly-scaled gradient, full
   height, top to bottom, with the header floating over it once revealed. */
.hero { margin-top: -70px; }

.site-header { transition: opacity 1.1s var(--ease), transform 1.1s var(--ease); }
body.is-intro .site-header { opacity: 0; transform: translateY(-100%); }

.hero__ticker { transition: opacity 1.15s var(--ease); }
body.is-intro .hero__ticker { opacity: 0; }

.reduce-motion .site-header,
.reduce-motion .hero__ticker,
.reduce-motion .hero__logo { transition: none; }

.hero__logo {
	position: relative;
	width: min(68.7vw, 600px);
	aspect-ratio: 1500 / 850;
	opacity: 0;
	transform: scale(0.85);
	transition: opacity 1.4s var(--ease), transform 1.4s var(--ease);
}
.hero__logo.is-visible { opacity: 1; transform: scale(1); }
.hero__logo-static,
.hero__logo-lottie { position: absolute; inset: 0; width: 100%; height: 100%; }
.hero__logo-lottie svg { display: block; }

/* ---- Hero ---- */
.hero {
	position: relative;
	overflow: hidden;
	min-height: 100vh;
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	text-align: center; gap: 2rem;
	background: var(--mesh-warm-blobs), var(--color-orange);
	color: var(--color-white);
}
/* WebGL mesh background (see initHeroMesh() in main.js) — an animated,
   cursor-reactive version of the same warm blob mesh the static
   .hero background above approximates. Sits between .hero's own
   background and its foreground content, so it covers the static
   fallback once rendered but a canvas that fails to initialise (no
   WebGL, JS disabled) is simply removed by the script and the static
   gradient above shows through untouched. */
.hero__mesh { position: absolute; inset: 0; width: 100%; height: 100%; display: block; z-index: 0; }
.hero__inner { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 2rem; }
/* overflow: hidden clips the tagline's slide-in/out (see .hero__tagline
   below) so the off-screen position mid-transition doesn't widen the
   page's own scroll area — the exact bug fixed on .wwd__images/
   .about-intro__images elsewhere in this file for the same reason.
   min-height reserves room for the tallest phrase (3 lines, the most
   any of the 4 rotating phrases wraps to at this box's width) so the
   box's own height — and with it the logo above, since both sit in the
   same centered flex column — stays constant whether the current
   phrase happens to wrap to 2 lines or 3, instead of the whole hero
   silently re-centering itself and shifting the logo on every phrase
   change. font-size/line-height live here (not on .hero__tagline
   itself) so the `em` in that min-height resolves against the same
   value the text actually renders at. */
.hero__ticker { width: 100%; max-width: 36ch; overflow: hidden; font-size: clamp(1.1rem, 2vw, 1.4rem); line-height: 1.3; min-height: calc(3 * 1.3em); display: flex; flex-direction: column; justify-content: center; }
/* font-size/line-height repeated here (not just inherited from
   .hero__ticker) because the sitewide `h1 { font-size: clamp(2.75rem,
   7vw, 6rem); }` rule below is a same-or-higher-specificity match on
   this element itself, which beats mere inheritance from an ancestor —
   without this, the tagline rendered at that generic heading size
   instead of the hero's own small one. */
.hero__tagline { color: var(--color-white); font-size: clamp(1.1rem, 2vw, 1.4rem); line-height: 1.3; font-weight: 500; margin: 0; transition: transform 0.7s var(--ease), opacity 0.7s var(--ease); }
/* Both push the phrase off-screen — right for the exit, left for the
   next phrase's silent (transition: none, see initHeroTicker()) starting
   position before it slides back in — so the motion always reads as
   moving rightward, never reversing. */
.hero__tagline.is-ticker-offscreen-left { transform: translateX(-100%); opacity: 0; }
.hero__tagline.is-ticker-offscreen-right { transform: translateX(100%); opacity: 0; }
.reduce-motion .hero__tagline.is-ticker-offscreen-left, .reduce-motion .hero__tagline.is-ticker-offscreen-right { transform: none !important; opacity: 1 !important; }

/* ---- Philosophy statement (big stacked condensed headline, left-
   aligned in the same .about-statement-section/.about-statement style
   as the other pages' big statement headings — see the shared rule
   further down) ---- */
/* Shared "big display statement" look — Anton, uppercase, tightly leaded,
   scales from 2.75rem to 6.5rem. Used wherever a section wants the same
   visual weight as the homepage philosophy statement (About page intro,
   final CTA heading); each context then only sets its own color/alignment. */
.display-statement {
	font-family: 'Anton', var(--font-display);
	font-weight: 400;
	text-transform: uppercase;
	line-height: 0.95;
	font-size: clamp(2.75rem, 7vw, 6.5rem);
	margin: 0;
}
.philosophy__more { margin-top: 2.5rem; }

/* ---- "What We Do" tabs (homepage) ---- */
/* Gap from "More about us" above: cut to 20% of the sitewide default
   padding-top, then increased 50% from that (0.6/1.6vw/1.4rem × 1.5) —
   the other half of this gap is #philosophy's own scoped padding-bottom
   override below (kept separate from the shared
   .about-statement-section--tight rule so this doesn't also change the
   Creative/Contact pages that reuse that class). */
.wwd.wwd--tight-top { padding-top: clamp(0.9rem, 2.4vw, 2.1rem); }
/* Anton (same face as .display-statement), uppercase — sized 25% bigger
   than the original 1rem body-font label, then doubled (1.25rem × 2 =
   2.5rem), then increased a further 25% (2.5rem × 1.25 = 3.125rem). */
.wwd__eyebrow { display: flex; align-items: center; gap: 0.6em; font-family: 'Anton', var(--font-display); font-weight: 400; text-transform: uppercase; font-size: 3.125rem; margin-bottom: 2.5rem; }
.wwd__eyebrow-icon { width: 12px; height: 12px; background: var(--color-ink); flex-shrink: 0; }
.wwd__tabs { display: flex; gap: 1.5rem; margin-bottom: clamp(2.5rem, 6vw, 4.5rem); border-bottom: 1px solid var(--color-line); padding-bottom: 1.5rem; }
.wwd__tab {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.1rem;
	color: var(--color-line);
	padding-bottom: 0.4em;
	border-bottom: 2px solid transparent;
	transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.wwd__tab:hover { color: var(--color-body); }
.wwd__tab[aria-selected="true"] { color: var(--color-ink); border-bottom-color: var(--color-orange); }
.wwd__grid { display: grid; grid-template-columns: minmax(260px, 420px) 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
/* Both wrappers stack their children in the same grid cell so the
   outgoing and incoming panel/image-set can overlap mid-crossfade
   instead of the incoming one being pushed below in normal flow. */
.wwd__content { display: grid; grid-template-columns: 1fr; }
.wwd__content > .wwd__panel { grid-area: 1 / 1; }
/* overflow: hidden clips the two rectangles' pre-reveal position — they
   slide in from off-screen via [data-reveal-right]/[data-reveal-left]
   (transform: translateX(±64px)) — so that off-screen offset doesn't
   widen the page's own scrollable area before the section has scrolled
   into view. Found causing real horizontal scroll at a 768px viewport;
   harmless once settled, since both rectangles sit well inside this box
   at translateX(0). Same fix applied to the identical pattern on the
   About page's .about-intro__images below. */
.wwd__images { display: grid; grid-template-columns: 1fr; overflow: hidden; }
.wwd__images > .wwd__image-set { grid-area: 1 / 1; }
.wwd__panel[hidden], .wwd__image-set[hidden] { display: none !important; }
/* Scoped reveal for this section only — doesn't affect the default
   [data-reveal] speed/direction used elsewhere on the site. Enters by
   moving down (from above) instead of the sitewide up-motion, and
   fades/moves further down again on exit when switching tabs. Duration
   matches EXIT_MS/ENTER_MS in main.js so the crossfade timing stays in sync. */
.wwd__panel[data-reveal] { transform: translateY(-28px); transition-duration: 0.9s; }
/* Same specificity as the sitewide [data-reveal].is-visible rule, so
   without this the panel's own translateY(-28px) above would always win
   on source order and the panel would never actually settle at rest. */
.wwd__panel[data-reveal].is-visible { transform: translateY(0); }
.wwd__panel[data-reveal].is-leaving { opacity: 0; transform: translateY(28px); transition: opacity 0.9s var(--ease), transform 0.9s var(--ease); }
.wwd__panel h3 { font-size: clamp(2rem, 3.5vw, 2.75rem); margin-bottom: 1rem; }
/* 1.155rem = 1.05rem + 10% — Option 3 from the size compare, picked and finalized. */
.wwd__panel p { font-size: 1.155rem; max-width: 40ch; }
.wwd__image-set {
	--wwd-gap: clamp(5px, 0.75vw, 9px);
	--wwd-half-gap: clamp(2.5px, 0.375vw, 4.5px);
	display: flex;
	flex-direction: column;
	gap: var(--wwd-gap);
	container-type: inline-size;
	transition: gap 0.4s var(--ease);
}
.reduce-motion .wwd__image-set { transition: none; }
.wwd__image { position: relative; width: 82%; aspect-ratio: 2.8/1; overflow: hidden; background: var(--color-offwhite); }
/* Staggered stack: the top rectangle sits flush against the right edge,
   the bottom one flush against the left, so each is offset by the
   remaining 18% — a diagonal-feeling pair rather than two full-width bars. */
.wwd__image--top { align-self: flex-end; }
.wwd__image--bottom { align-self: flex-start; }
/* "Meet in the middle" — once the two rectangles have settled,
   merge()/scheduleInitialMerge() in main.js toggle .is-merged *before*
   the entrance transition starts, and each rectangle moves on `top` to
   close the gap. `top` is kept in the [data-reveal-right]/[data-reveal-
   left] transition list above (a property separate from the lateral
   slide's `transform`, so the two can run on independent timings without
   fighting over one property). The override below sets ONLY
   transition-duration/transition-delay (the LONGHANDS, not the
   `transition` shorthand — the shorthand would replace this whole list,
   silently dropping the opacity/transform transitions and making the
   lateral slide-in snap instead of animate) for the "top" slot specifically,
   which is what makes the lateral slide (on `transform`, 1.2s, no delay)
   run first, with the vertical "meet in the middle" move flowing in as
   the lateral move is finishing — one fluid gesture, lateral leading into
   vertical. On exit/unmerge, this override no longer applies, so `top`
   falls back to the base list's un-delayed duration, alongside the
   lateral exit slide — a clean, undiluted lateral move, unchanged. */
.wwd__image-set.is-merged .wwd__image--top { top: var(--wwd-half-gap); transition-duration: 1.2s, 1.2s, 0.6s, 1.2s, 1.2s; transition-delay: 0s, 0s, 0.75s, 0s, 0s; }
.wwd__image-set.is-merged .wwd__image--bottom { top: calc(var(--wwd-half-gap) * -1); transition-duration: 1.2s, 1.2s, 0.6s, 1.2s, 1.2s; transition-delay: 0s, 0s, 0.75s, 0s, 0s; }
.wwd__image img { width: 100%; height: 100%; object-fit: cover; }
/* Both rectangles show one uploaded photo, sliced top/bottom. The photo
   layer is sized/positioned as if it were one image behind the full
   (unstaggered) width of the set, not each rectangle's own 82% box —
   otherwise the same photo would visibly jump sideways between the two
   windows, since they sit at different horizontal offsets. */
.wwd__image-bg {
	position: absolute;
	top: 0;
	width: calc(100% / 0.82);
	height: 200%;
	background-repeat: no-repeat;
	background-size: cover;
	background-position: center;
}
.wwd__image--top .wwd__image-bg { right: 0; top: 0; }
.wwd__image--bottom .wwd__image-bg { left: 0; top: -100%; }
@media (max-width: 900px) {
	.wwd__grid { grid-template-columns: 1fr; }
	.wwd__tabs { flex-wrap: wrap; gap: 1rem; }
}

/* ---- Video modal (opened by any element with data-video-modal-trigger) ---- */
.video-modal { position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center; padding: var(--gutter); }
.video-modal[hidden] { display: none; }
.video-modal__backdrop { position: absolute; inset: 0; background: rgba(17,15,14,0.9); }
.video-modal__inner { position: relative; width: 100%; max-width: 1100px; max-height: 85vh; }
/* No fixed aspect-ratio — the Creative page's portfolio videos are a mix
   of 16:9 and 9:16, so forcing one ratio would crop the other orientation
   badly (object-fit: cover cutting most of a vertical video away to fill
   a horizontal box). Letting the box size itself from the video's own
   intrinsic dimensions (capped by max-height so a tall 9:16 clip can't
   overflow a short viewport) handles both correctly; object-fit: contain
   only kicks in once that cap actually constrains it, letterboxing
   instead of cropping. */
.video-modal__inner video { display: block; width: 100%; max-height: 85vh; object-fit: contain; background: var(--color-black); }
.video-modal__close { position: absolute; top: -3rem; right: 0; color: var(--color-white); font-size: 2rem; line-height: 1; }

/* ---- Contact modal ("Let's talk", opened from the final CTA band) ---- */
.contact-modal { position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center; padding: var(--gutter); overflow-y: auto; }
.contact-modal[hidden] { display: none; }
.contact-modal__backdrop { position: fixed; inset: 0; background: rgba(17,15,14,0.9); }
.contact-modal__inner { position: relative; width: 100%; max-width: 560px; background: var(--color-white); padding: 3rem; margin-block: auto; }
.contact-modal__close { position: absolute; top: 1rem; right: 1.25rem; font-size: 2rem; line-height: 1; color: var(--color-ink); }
.contact-modal__heading { margin-top: 0; margin-bottom: 1.5rem; }
.contact-modal .contact-form { max-width: none; margin-inline: 0; }

/* "Book a call" popup — same treatment as the contact popup (darkened page,
   centred white panel with sharp corners, page scroll locked). The panel is
   padding-free because the calendar page inside the iframe has its own. */
.booking-modal { position: fixed; inset: 0; z-index: 1100; display: flex; align-items: center; justify-content: center; padding: var(--gutter); overflow-y: auto; }
.booking-modal[hidden] { display: none; }
.booking-modal__backdrop { position: fixed; inset: 0; background: rgba(17,15,14,0.9); }
.booking-modal__inner { position: relative; width: 100%; max-width: 520px; background: var(--color-white); margin-block: auto; min-height: 320px; }
.booking-modal__close { position: absolute; top: 0.75rem; right: 1.1rem; z-index: 2; font-size: 2rem; line-height: 1; color: var(--color-ink); }
.booking-modal__close:hover, .booking-modal__close:focus-visible { color: var(--color-orange); }
.booking-modal__loading { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; margin: 0; color: var(--color-body); }
.booking-modal__frame { position: relative; z-index: 1; display: block; width: 100%; height: 640px; max-height: calc(100vh - 2 * var(--gutter)); border: 0; background: transparent; }

/* The bare calendar page that loads inside the popup. Wappointment draws a
   small rounded, shadowed card in its own orange; here it is restyled to
   the theme — sharp corners, no shadow, theme orange, black on hover, the
   same heading style as the contact popup — by overriding the plugin's
   colour variables and its hard-coded button rules (scoped to this page). */
body.booking-embed { margin: 0; padding: 2.25rem 2rem 1.75rem; background: var(--color-white); color: var(--color-ink); }
@media (max-width: 600px) { body.booking-embed { padding: 2.25rem 1rem 1.25rem; } }
.booking-embed__heading { margin: 0 0 0.35rem; font-size: clamp(2rem, 6vw, 2.6rem); line-height: 1; text-align: left; }
.booking-embed__lede { margin: 0 0 1.5rem; color: var(--color-body); }
body.booking-embed .wap-front {
	--wappo-pri-bg: #ff4000;
	--wappo-pri-tx: #ffffff;
	--wappo-sec-bg: #f7f6f4;
	--wappo-sec-tx: #4a4542;
	--wappo-sec-sel-bg: #141212;
	--wappo-sec-sel-tx: #ffffff;
	--wappo-body-tx: #221f1d;
	--wappo-body-bg: #ffffff;
	--wappo-input-bor: #e7e2dd;
	--wappo-input-box-s: rgba(255,64,0,0.2);
	font-family: var(--font-body);
}
body.booking-embed .wap-front .wappo_module { justify-content: stretch; }
body.booking-embed .wap-front .wap-wid,
body.booking-embed .wap-front .wap-bf { width: 100%; max-width: 100%; border-radius: 0; box-shadow: none; border: 0; background: transparent; }
body.booking-embed .wap-front .wap-head { display: none; }
body.booking-embed .wap-front .wap-form-body { padding: 0; background: transparent; border-radius: 0; }
body.booking-embed .wap-front .wsummary-section { border-bottom: 1px solid var(--color-line); }
body.booking-embed .wap-front .wbtn,
body.booking-embed .wap-front .badge,
body.booking-embed .wap-front [class*="wbadge"] { border-radius: 0 !important; }
body.booking-embed .wap-front .wbtn.wbtn-primary,
body.booking-embed .wap-front .wbtn-primary:not(:disabled):not(.disabled):active,
body.booking-embed .wap-front .wbtn-primary:not(:disabled):not(.disabled).active,
body.booking-embed .wap-front .wbtn-primary.disabled,
body.booking-embed .wap-front .wbtn-primary:disabled {
	background: var(--color-orange) !important; background-color: var(--color-orange) !important;
	border-color: var(--color-orange) !important; color: var(--color-white) !important; box-shadow: none !important;
}
body.booking-embed .wap-front .wbtn.wbtn-primary:hover,
body.booking-embed .wap-front .wbtn.wbtn-primary:focus-visible {
	background: var(--color-black) !important; background-color: var(--color-black) !important; border-color: var(--color-black) !important; box-shadow: none !important;
}
body.booking-embed .wap-front .wbtn.wbtn-primary-light { background: #ffe4da !important; border-color: #ffe4da !important; color: var(--color-ink) !important; box-shadow: none !important; }
/* Note under the date selector: shown while picking a date/time, tucked away
   on the later form/confirmation steps (browsers without :has() just keep it). */
.booking-embed__note { margin: 1.25rem 0 0; font-size: 0.9rem; line-height: 1.5; color: var(--color-body); }
.booking-embed__note a { color: var(--color-orange); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
body.booking-embed:has(.wap-wid:not(.step-BookingCalendar)) .booking-embed__note { display: none; }
/* The widget reserves 62px above the form for its (hidden) header. */
body.booking-embed .wap-front .wap-form-body { margin-top: 0; }
/* "Service" / "Where" tags: square, light, ink text (were rounded salmon pills). */
body.booking-embed .wap-front .wselected { border-radius: 0; background: #f7f6f4; border: 1px solid var(--color-line); }
body.booking-embed .wap-front .wselected,
body.booking-embed .wap-front .wselected * { color: var(--color-ink) !important; fill: currentColor; }
/* Calendar days: light squares, black when chosen, orange on hover. */
body.booking-embed .wap-front .wbtn.dayselected { background: var(--color-black) !important; background-color: var(--color-black) !important; border-color: var(--color-black) !important; }
body.booking-embed .wap-front .wbtn.dayselected,
body.booking-embed .wap-front .wbtn.dayselected * { color: var(--color-white) !important; }
body.booking-embed .wap-front .wbtn-secondary.avail:not(.dayselected):hover { background: var(--color-orange) !important; border-color: var(--color-orange) !important; }
body.booking-embed .wap-front .wbtn-secondary.avail:not(.dayselected):hover,
body.booking-embed .wap-front .wbtn-secondary.avail:not(.dayselected):hover * { color: var(--color-white) !important; }

/* ---- GDPR cookie consent: dims the whole page behind a bottom-left
   panel and blocks scroll (see initCookieConsent() in main.js) until
   the visitor accepts, rejects, or saves custom preferences. Sits above
   everything else (including the two modals above) since it can appear
   on top of either. ---- */
.cookie-overlay { position: fixed; inset: 0; z-index: 1400; background: rgba(17,15,14,0.55); opacity: 0; transition: opacity 0.5s var(--ease); }
.cookie-overlay[hidden] { display: none; }
.cookie-overlay.is-visible { opacity: 1; }

.cookie-consent { position: fixed; left: 1.5rem; bottom: 1.5rem; z-index: 1401; width: 100%; max-width: 400px; background: var(--color-white); padding: 1.75rem; box-shadow: 0 12px 40px rgba(17,15,14,0.25); opacity: 0; transform: translateY(16px); transition: opacity 0.5s var(--ease), transform 0.5s var(--ease); }
.cookie-consent[hidden] { display: none; }
.cookie-consent.is-visible { opacity: 1; transform: translateY(0); }
.reduce-motion .cookie-overlay, .reduce-motion .cookie-consent { transition: none; }

.cookie-consent__view--settings[hidden] { display: none; }

.cookie-consent__text { font-size: 0.92rem; line-height: 1.55; margin: 0 0 1.25rem; }
.cookie-consent__link { text-decoration: underline; color: var(--color-ink); }
.cookie-consent__link:hover { color: var(--color-orange); }

.cookie-consent__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1rem; }
.cookie-consent__primary-actions { display: flex; gap: 0.75rem; margin-left: auto; }

.cookie-consent__btn { font-family: var(--font-display); font-weight: 700; font-size: 0.82rem; letter-spacing: 0.01em; padding: 0.75em 1.4em; border: 1px solid transparent; cursor: pointer; }
.cookie-consent__btn--accept { background: var(--color-orange); color: var(--color-white); }
.cookie-consent__btn--accept:hover, .cookie-consent__btn--accept:focus-visible { background: var(--color-black); }
.cookie-consent__btn--reject { background: transparent; color: var(--color-ink); border-color: var(--color-ink); }
.cookie-consent__btn--reject:hover, .cookie-consent__btn--reject:focus-visible { background: var(--color-ink); color: var(--color-white); }
.cookie-consent__btn--back { background: transparent; color: var(--color-body); border-color: var(--color-line); }
.cookie-consent__btn--back:hover, .cookie-consent__btn--back:focus-visible { border-color: var(--color-ink); color: var(--color-ink); }
.cookie-consent__btn--settings { background: none; border: none; padding: 0.4em 0; color: var(--color-body); font-family: var(--font-body); font-weight: 400; font-size: 0.85rem; text-decoration: underline; }
.cookie-consent__btn--settings:hover, .cookie-consent__btn--settings:focus-visible { color: var(--color-orange); }

.cookie-consent__settings-title { margin: 0 0 1rem; font-size: 1.05rem; }
.cookie-consent__category { padding-block: 0.9rem; border-top: 1px solid var(--color-line); }
.cookie-consent__category:first-of-type { border-top: none; padding-top: 0; }
.cookie-consent__category-head { display: flex; align-items: center; justify-content: space-between; font-family: var(--font-display); font-weight: 700; font-size: 0.9rem; color: var(--color-ink); }
.cookie-consent__always-on { font-family: var(--font-body); font-weight: 400; font-size: 0.75rem; color: var(--color-body); text-transform: uppercase; letter-spacing: 0.04em; }
.cookie-consent__category-desc { margin: 0.35rem 0 0; font-size: 0.82rem; color: var(--color-body); line-height: 1.5; }

.cookie-consent__switch { display: flex; align-items: center; justify-content: space-between; gap: 1rem; width: 100%; cursor: pointer; }
.cookie-consent__toggle { position: absolute; opacity: 0; width: 1px; height: 1px; }
.cookie-consent__slider { position: relative; flex-shrink: 0; width: 38px; height: 22px; background: var(--color-line); border-radius: 999px; transition: background 0.25s var(--ease); }
.cookie-consent__slider::before { content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; background: var(--color-white); border-radius: 50%; transition: transform 0.25s var(--ease); }
.cookie-consent__toggle:checked + .cookie-consent__slider { background: var(--color-orange); }
.cookie-consent__toggle:checked + .cookie-consent__slider::before { transform: translateX(16px); }
.cookie-consent__toggle:focus-visible + .cookie-consent__slider { outline: 2px solid var(--color-orange); outline-offset: 2px; }

@media (max-width: 600px) {
	.cookie-consent { left: 1rem; right: 1rem; bottom: 1rem; max-width: none; padding: 1.5rem; }
	.cookie-consent__actions { flex-direction: column; align-items: stretch; }
	.cookie-consent__primary-actions { margin-left: 0; }
	.cookie-consent__primary-actions .cookie-consent__btn { flex: 1; text-align: center; }
}

/* ---- Portfolio grid / cards ---- */
.portfolio-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.75rem; }
.portfolio-card__link { position: relative; display: block; }
.portfolio-card__media { position: relative; display: block; overflow: hidden; aspect-ratio: 4/5; background: var(--color-offwhite); }
.portfolio-card__image, .portfolio-card__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.portfolio-card__image { transition: transform 0.6s var(--ease); }
.portfolio-card__link:hover .portfolio-card__image { transform: scale(1.04); }
.portfolio-card__video { opacity: 0; transition: opacity 0.4s; }
.portfolio-card__link:hover .portfolio-card__video,
.portfolio-card__link:focus-visible .portfolio-card__video { opacity: 1; }
.portfolio-card__play { position: absolute; bottom: 1rem; right: 1rem; width: 40px; height: 40px; border-radius: 50%; background: rgba(255,255,255,0.9); }
.portfolio-card__play::after { content: ''; position: absolute; top: 50%; left: 56%; transform: translate(-50%,-50%); border-style: solid; border-width: 7px 0 7px 11px; border-color: transparent transparent transparent var(--color-orange); }
.portfolio-card__meta { display: block; padding-top: 1rem; }
.portfolio-card__title { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; color: var(--color-ink); }
.portfolio-card__sub { display: block; font-size: 0.85rem; color: var(--color-body); margin-top: 0.2rem; }
.portfolio-grid--archive { margin-top: 1rem; }

/* ---- Portfolio grid (Creative page) — a true masonry (variable card
   sizes/column-spans by orientation) read as uneven and messy with this
   much of a mix between 16:9, 9:16 and square footage, so this is a
   uniform grid instead: every card is the same box (same treatment as
   .portfolio-card__media elsewhere — 4:5, object-fit: cover), which
   keeps rows aligned regardless of each thumbnail's real aspect ratio.
   Class names keep the "masonry" prefix for continuity with the PHP/JS
   that reference them, even though the layout itself no longer is one. */
.masonry-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.75rem; margin-top: 1rem; }
.masonry-card__media { position: relative; display: block; width: 100%; aspect-ratio: 4/5; padding: 0; border: 0; background: var(--color-offwhite); overflow: hidden; cursor: pointer; }
.masonry-card__media img { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.masonry-card__media:hover img { transform: scale(1.06); }
.masonry-card__media:hover .showreel__play { transform: translate(-50%, -50%) scale(1.08); background: var(--color-orange); }
.masonry-card__meta { display: block; padding-top: 1rem; }
.masonry-card__title { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; color: var(--color-ink); }
.masonry-card__sub { display: block; font-size: 0.85rem; color: var(--color-body); margin-top: 0.2rem; }
@media (max-width: 900px) {
	.masonry-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
	.masonry-grid { grid-template-columns: 1fr; }
}

/* ---- Filter tabs ---- */
.filter-tabs { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-bottom: 3rem; }
.filter-tabs__item { font-weight: 400; font-size: 0.9rem; padding-bottom: 0.2em; border-bottom: 1px solid transparent; }
.filter-tabs__item.is-active, .filter-tabs__item:hover { border-bottom-color: var(--color-orange); color: var(--color-orange); }

/* ---- Client showcase (three-row logo marquee) ----
   Middle row: full opacity, scrolls right (marquee-reverse).
   Top/bottom rows: dimmed, scroll left (marquee) — same duration as the
   middle row, so with identical (duplicated) content per row they all
   move at the same speed. */
/* The radial mask fades all three rows out toward the edges (an "oval"
   vignette) — the main row's own logos included, not just the dimmed
   rows — so the centre reads as a spotlit focal point rather than a
   flat, evenly-lit strip. */
.client-showcase { overflow: hidden; padding-block: clamp(3.5rem, 8vw, 6rem); display: flex; flex-direction: column; gap: clamp(3rem, 9vw, 6.5rem); -webkit-mask-image: radial-gradient(ellipse 55% 80% at 50% 50%, black 15%, transparent 85%); mask-image: radial-gradient(ellipse 55% 80% at 50% 50%, black 15%, transparent 85%); }
.client-showcase__row { overflow: hidden; }
.client-showcase__row--dim { opacity: 0.3; }
.client-showcase__track { display: flex; width: max-content; animation: marquee 90s linear infinite; }
.client-showcase__track--right { animation-name: marquee-reverse; }
/* Offsets the bottom dimmed row's animation phase so it isn't showing
   the exact same logo directly above/below the top dimmed row at any
   given moment — a small, fixed, non-cycle-aligned offset (rather than
   e.g. exactly half the duration) keeps the two from ever re-aligning
   in an obviously-timed way. */
.client-showcase__row:nth-child(3) .client-showcase__track { animation-delay: -17s; }
.reduce-motion .client-showcase__track { animation: none; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes marquee-reverse { from { transform: translateX(-50%); } to { transform: translateX(0); } }
.client-showcase__group { display: flex; align-items: center; gap: clamp(5rem, 13vw, 11rem); padding-inline: clamp(2.5rem, 6vw, 5.5rem); }
.client-showcase__logo img { height: 30px; width: auto; opacity: 0.8; transition: opacity 0.3s var(--ease); }
.client-showcase__row--main .client-showcase__logo img { height: 38px; opacity: 1; }
.client-showcase__logo:hover img { opacity: 1; }

/* ---- Showreel ---- */
.showreel { position: relative; overflow: hidden; padding-block: clamp(4rem, 10vw, 7rem); text-align: center; }
.showreel__inner { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; }
/* The stage is sized to exactly the card (aspect-ratio: 16/9, no extra
   height of its own), so the background wordmark — pinned to the
   stage's own top/bottom — stays centred on the card specifically, not
   dragged down by the reflection/CTA below it. */
.showreel__stage { position: relative; width: min(100%, 780px); }
.showreel__bgtext { position: absolute; top: 0; bottom: 0; left: 50%; width: 100vw; transform: translateX(-50%); display: flex; align-items: center; overflow: hidden; pointer-events: none; z-index: 0; }
.showreel__bgtrack { display: flex; width: max-content; animation: marquee 52s linear infinite; }
.reduce-motion .showreel__bgtrack { animation: none; }
.showreel__bggroup { display: flex; align-items: center; }
.showreel__bgitem { font-family: var(--font-display); font-weight: 800; text-transform: uppercase; font-size: clamp(3rem, 9vw, 7rem); line-height: 1; color: var(--color-offwhite); white-space: nowrap; padding-inline: 0.4em; }
.showreel__bgitem--dot { color: var(--color-line); }
/* Buttons keep their UA default padding (~1px 6px) unless reset — left
   in place, that padding sat between the card's own edge and the poster
   filling it, exposing slivers of the card's dark background down the
   sides as what looked like black bars. */
.showreel__card { position: relative; z-index: 1; display: block; width: 100%; aspect-ratio: 16/9; padding: 0; border-radius: 20px; overflow: hidden; background: var(--color-ink); }
/* Scaled up slightly even at rest — the source footage isn't cropped
   tight to the frame, so filling the box with object-fit: cover alone
   still left a sliver of the surrounding footage/black edge visible;
   this pushes just past that. Hover pushes in a bit further still. */
.showreel__poster { width: 100%; height: 100%; object-fit: cover; display: block; transform: scale(1.06); transition: transform 0.6s var(--ease); }
.showreel__card:hover .showreel__poster { transform: scale(1.12); }
.showreel__play { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 120px; height: 120px; border-radius: 50%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.35rem; background: rgba(17,15,14,0.55); backdrop-filter: blur(6px); color: var(--color-white); font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; transition: transform 0.3s var(--ease), background 0.3s var(--ease); }
.showreel__card:hover .showreel__play { transform: translate(-50%, -50%) scale(1.08); background: var(--color-orange); }
.showreel__play-icon { width: 0; height: 0; border-style: solid; border-width: 7px 0 7px 11px; border-color: transparent transparent transparent var(--color-white); margin-left: 3px; }
/* The reflection ("shadow") is its own stage so the CTA can be overlaid
   dead-centre on it via inset:0 + flex centring, and rounded on all four
   corners like the card above it (not just the bottom two — cut corners
   read as a mismatched shape next to the fully-rounded card). */
.showreel__shadow { position: relative; width: min(100%, 780px); margin-top: 8px; }
.showreel__reflection { width: 100%; aspect-ratio: 16/9; overflow: hidden; border-radius: 20px; opacity: 0.55; -webkit-mask-image: linear-gradient(to bottom, rgba(0,0,0,0.4), transparent 70%); mask-image: linear-gradient(to bottom, rgba(0,0,0,0.4), transparent 70%); }
.showreel__reflection img { width: 100%; height: 100%; object-fit: cover; display: block; transform: scaleY(-1); }
.showreel__cta { position: absolute; top: 28%; left: 50%; transform: translate(-50%, -50%); color: var(--color-orange); border-bottom-color: var(--color-orange); font-size: 1.33rem; }
.showreel__cta:hover, .showreel__cta:focus-visible { color: var(--color-ink); border-bottom-color: var(--color-ink); }
.showreel__cta--standalone { position: static; top: auto; left: auto; transform: none; margin-top: 2.5rem; }

/* ---- CTA band — the one full-bleed block of accent colour on the page ---- */
.cta-band { background: var(--color-orange); color: var(--color-black); }
.cta-band__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2rem; }
/* .display-statement supplies the type styling and margin: 0 — the
   margin reset also fixes the global h1-h4 bottom margin being counted in
   the flex row's cross size, which otherwise centered .cta-band__actions
   against that phantom space instead of the visible text. */
.cta-band__heading { color: var(--color-black); }
.cta-band__actions { display: flex; flex-direction: column; align-items: flex-start; gap: 1rem; }
.cta-band .button { color: var(--color-white); border-bottom-color: var(--color-white); font-size: 1.33rem; }
.cta-band .button:hover { color: var(--color-black); border-bottom-color: var(--color-black); }

/* ---- Footer — single row: logo, copyright + social icons ---- */
.site-footer {
	background: var(--color-orange);
	color: var(--color-white);
	padding-block: 1.75rem;
	border-top: 1px solid rgba(255,255,255,0.25);
}
.site-footer a:hover { opacity: 0.75; }
.site-footer__inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 1.5rem; }
.site-footer__logo img { height: 40px; width: auto; }
.site-footer__meta { display: flex; align-items: center; gap: 1.75rem; flex-wrap: wrap; }
.site-footer__copyright { font-size: 0.9rem; }
.site-footer__cookie-link { background: none; border: none; padding: 0; margin: 0; color: inherit; opacity: 0.75; font: inherit; font-size: 0.9rem; text-decoration: underline; cursor: pointer; }
.site-footer__cookie-link:hover, .site-footer__cookie-link:focus-visible { opacity: 1; }
.site-footer__social { display: flex; align-items: center; gap: 0.6rem; }
.site-footer__social a {
	display: inline-flex; align-items: center; justify-content: center;
	width: 34px; height: 34px;
}
.site-footer__social svg { display: block; }
@media (max-width: 640px) {
	.site-footer__inner { flex-direction: column; align-items: flex-start; }
	.site-footer__meta { flex-direction: column; align-items: flex-start; gap: 1rem; }
}

/* ---- Generic page hero / content ---- */
.page-hero { padding-block: clamp(3rem, 10vw, 6rem) 2rem; }
.page-hero__eyebrow { font-weight: 700; color: var(--color-orange); text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.85rem; }
.page-hero__lede { max-width: 60ch; font-size: 1.15rem; }
.page-content { max-width: 75ch; margin-inline: auto; }

/* Long-form prose (currently just the Cookie Policy page) — headings and
   lists inside .page-content otherwise inherit the sitewide ul/ol reset
   (no bullets, no indent) and the heading defaults meant for section
   titles, neither of which reads well in a wall of policy text. */
.page-content h2 { font-size: 1.4rem; margin: 2.2em 0 0.6em; }
.page-content h2:first-child { margin-top: 0; }
.page-content h3 { font-size: 1.1rem; margin: 1.6em 0 0.5em; }
.page-content ul { list-style: disc; padding-left: 1.4em; margin: 0 0 1em; }
.page-content li { margin-bottom: 0.4em; }
.page-content li:last-child { margin-bottom: 0; }

.about-statement { color: var(--color-orange); }

/* Creative page intro: match the statement heading's full container width
   instead of the sitewide .page-content 75ch reading column, so the two
   intro paragraphs wrap into fewer, wider lines under the (also
   full-width) statement heading above them. Also cuts the gaps on both
   sides of this section to 20% of the sitewide default (an 80%
   reduction) — heading-to-paragraph and paragraph-to-thumbnails, both
   tighter than the rest of the site by request. */
.page-content--wide { max-width: var(--container-w); margin-inline: auto; padding-top: clamp(0.6rem, 1.6vw, 1.4rem); padding-bottom: clamp(0.6rem, 1.6vw, 1.4rem); }
.page-content--wide p { font-size: 1.1rem; }
/* FAQ page: match the statement heading's full container width instead
   of the sitewide .page-content 75ch reading column — width only, no
   other changes (unlike .page-content--wide above, which also bumps
   padding/font-size for the Creative page specifically). */
.page-content--faq { max-width: var(--container-w); margin-inline: auto; }
/* FAQ category headings: 1.4rem sitewide .page-content h2 size + 20%, in
   the Keibi orange instead of the default ink colour — FAQ page only. */
.page-content--faq h2 { font-size: 1.68rem; color: var(--color-orange); }

/* FAQ accordion: native <details>/<summary> so the page loads with just
   the questions visible, but every answer stays in the DOM and readable
   to search engines and AI crawlers even while collapsed (Google indexes
   content inside closed <details> the same as visible content). */
.faq-item { border-top: 1px solid var(--color-line); padding-block: 0.9rem; }
.faq-item:first-of-type { border-top: none; }
.faq-item__question { cursor: pointer; list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.faq-item__question::-webkit-details-marker { display: none; }
.faq-item__question h3 { margin: 0; }
.faq-item__question::after {
	content: '+';
	flex-shrink: 0;
	font-size: 1.4rem;
	line-height: 1;
	color: var(--color-orange);
	transition: transform 0.25s var(--ease);
}
.faq-item[open] > .faq-item__question::after { transform: rotate(45deg); }
.faq-item__answer { padding-top: 0.6rem; }
.faq-item__answer p { margin: 0 0 0.75em; }
.faq-item__answer p:last-child { margin-bottom: 0; }

/* Other half of the heading-to-paragraph gap (the statement section's own
   padding-bottom) — scoped to this Creative-only modifier class so the
   About page's identical heading markup keeps the sitewide spacing. */
.about-statement-section.about-statement-section--tight { padding-bottom: clamp(0.28rem, 0.75vw, 0.66rem); }
/* Other half of the paragraph-to-thumbnails gap (the grid section's own
   padding-top). */
.portfolio-archive.portfolio-archive--tight { padding-top: clamp(0.6rem, 1.6vw, 1.4rem); }
/* Homepage philosophy section's own half of the "More about us" → "What
   We Do" gap: the shared --tight value above (0.28/0.75vw/0.66rem),
   increased 50%. #philosophy overrides the shared class here rather
   than changing it directly, so the Creative/Contact pages that reuse
   .about-statement-section--tight keep their own value. */
#philosophy.about-statement-section--tight { padding-bottom: clamp(0.42rem, 1.13vw, 0.99rem); }

/* Contact page: centered statement heading, and the same 20%-of-default
   (80% reduction) gap treatment as the Creative page above — here between
   the heading/lede and the lede/form instead of heading/thumbnails. Kept
   as its own modifiers (not .page-content--wide, which also widens the
   column) since the Contact lede stays in the narrower 75ch column. */
.about-statement--center { text-align: center; }
.page-content--tight { padding-top: clamp(0.6rem, 1.6vw, 1.4rem); padding-bottom: clamp(0.34rem, 0.91vw, 0.8rem); }
.page-content--tight p { font-size: 1.1rem; }
/* Description-to-form gap: 5% further cut (0.6rem/1.6vw/1.4rem × 0.95),
   then a further 40% off that (× 0.6) after comparing against 10%/20%
   options — the lede-to-form side only, not the heading-to-lede side
   above it. */
.contact-form-section.contact-form-section--tight { padding-top: clamp(0.34rem, 0.91vw, 0.8rem); }

/* ---- About page intro: text left, static photo pair right — same
   grid proportions as .wwd__grid (narrow text column, image column takes
   the rest) so the image comes out the same size as the homepage "What We
   Do" images, and reuses that section's staggered-rectangle merge
   animation (.wwd__image-set/.wwd__image-bg — same one-photo-sliced-
   across-two-windows trick, same is-merged transition, same scroll-reveal
   trigger via [data-reveal-right]/[data-reveal-left] in initScrollReveal(),
   which plays once and unobserves, so it settles and stays put). Plain
   image, not a video trigger — no play button, nothing clickable. */
/* Override .page-content's 75ch centered column — this grid needs the
   same width/centering as the sitewide .container (--container-w capped,
   --gutter margins either side, both responsive) so .about-intro__text
   lines up flush-left with the statement heading above it and the image
   gets the same safe-zone margins as the rest of the site, instead of
   sitting in a narrower 75ch inset column. */
.page-content:has(.about-intro__grid) { max-width: var(--container-w); margin-inline: auto; }
/* TRIAL — the sitewide section padding is clamp(3rem, 8vw, 7rem) per
   side. This block:
   - sets the gap above the statement heading (space to the header) to
     clamp(2.27rem, 6.05vw, 5.3rem) — the sitewide clamp(3rem, 8vw, 7rem)
     scaled down to ~75.7% throughout (min/preferred/max all scaled
     together, same ratios as the default), landing at 62px at our
     1024px test width but leveling off at small/large viewports like
     every other clamped spacing value on the site, instead of scaling
     linearly without bound;
   - shrinks the gap between the statement heading and the intro section
     to 47% of the sitewide default (still responsive, still clamped).
   To revert, delete this block and both gaps go back to the sitewide
   default padding. */
.about-statement-section { padding-top: clamp(2.27rem, 6.05vw, 5.3rem); padding-bottom: clamp(1.41rem, 3.76vw, 3.29rem); }
.page-content:has(.about-intro__grid) { padding-top: clamp(1.41rem, 3.76vw, 3.29rem); }
/* TRIAL — cuts the gap between the intro section and "Meet the team" to
   60% of the sitewide default (clamp(3rem, 8vw, 7rem) scaled to
   clamp(1.8rem, 4.8vw, 4.2rem) on both sides that face each other). To
   revert, delete these two lines. */
.page-content:has(.about-intro__grid) { padding-bottom: clamp(1.8rem, 4.8vw, 4.2rem); }
.team-teaser { padding-top: clamp(1.8rem, 4.8vw, 4.2rem); }
.about-intro__grid { display: grid; grid-template-columns: minmax(260px, 420px) 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.about-intro__text p { font-size: 1.155rem; }
/* See the matching comment on .wwd__images above — same reveal pattern,
   same off-screen-pre-reveal overflow risk. */
.about-intro__images { overflow: hidden; }
@media (max-width: 900px) {
	.about-intro__grid { grid-template-columns: 1fr; }
}

.team-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 2rem; }
/* Matches the team photos' own real dimensions (600x921) exactly, so
   object-fit: cover below has nothing to crop — the photos are already
   framed correctly at source. Was 4/5 with per-photo object-position
   fixes to compensate for a mismatched ratio; no longer needed now the
   images themselves are the right shape. */
.team-card__media { position: relative; overflow: hidden; aspect-ratio: 600/921; margin-bottom: 1rem; background: var(--color-offwhite); }

/* Hamburger-in-a-circle hint on each team photo — signals "hover for
   more" for the team-hover bio reveal. The middle bar is the pseudo-
   element itself; box-shadow draws the top/bottom bars without needing
   two more elements. */
.team-hover__hint { position: absolute; top: 1rem; left: 1rem; width: 40px; height: 40px; border-radius: 50%; background: rgba(255, 64, 0, 0.6); pointer-events: none; }
.team-hover__hint::before { content: ''; position: absolute; top: 50%; left: 50%; width: 18px; height: 2px; background: var(--color-white); transform: translate(-50%, -50%); box-shadow: 0 -6px 0 var(--color-white), 0 6px 0 var(--color-white); }
.team-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.6s var(--ease); }
.team-card:hover .team-card__media img { transform: scale(1.04); }
.team-card__name { font-size: 1.4375rem; margin-bottom: 0.24em; }
.team-card__role { color: var(--color-orange); font-weight: 600; font-size: 1.125rem; }
.team-card__bio { font-size: 0.9rem; }
.team-card__footer { display: flex; justify-content: space-between; align-items: center; font-size: 0.8rem; margin-top: 0.75rem; }

/* ---- Team hover-reveal bios (About page): the photo grid up top, and
   below it one full-width slot where every person's bio is stacked in the
   exact same grid cell (grid-row/column overlap, not position: absolute)
   so they crossfade via opacity without any layout jump. initTeamBios()
   in main.js toggles .is-active on mouseenter/focus per person. */
/* TRIAL — vs. the defaults (2.5rem / 3rem) from .section-heading and
   this component's own base margin: heading-to-images now 60% of 2.5rem
   (1.5rem); images-to-descriptions now 40% of 3rem (1.2rem). To
   revert, delete the margin-bottom below and change 1.2rem back to 3rem. */
.team-teaser .section-heading { margin-bottom: 1.5rem; }
.team-hover__grid { cursor: pointer; }
.team-hover__bios { display: grid; margin-top: 1.2rem; }
.team-hover__bio { grid-area: 1 / 1; opacity: 0; visibility: hidden; transition: opacity 0.6s var(--ease), visibility 0.6s; pointer-events: none; }
.team-hover__bio.is-active { opacity: 1; visibility: visible; }
.team-hover__bio p { font-size: 1.155rem; margin-bottom: 0.75em; }
.reduce-motion .team-hover__bio { transition: none; }

.odd-bunch { text-align: center; font-family: var(--font-display); font-weight: 800; font-size: 1.25rem; padding-block: 2rem 5rem; }

/* ---- Partners (About page client list) ---- */
.partners__list { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 2rem; }
.partners__item { padding: 2rem; background: var(--color-black); }
.partners__logo { height: 32px; width: auto; margin-bottom: 1.25rem; filter: brightness(0) invert(1); }
.partners__name { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.1rem; margin-bottom: 1.25rem; color: var(--color-white); }
.partners__services li { padding-block: 0.3em; border-top: 1px solid rgba(255,255,255,0.15); font-size: 0.85rem; color: rgba(255,255,255,0.75); }
.partners__services li:first-child { border-top: 0; }

.project-single__media { margin-block: 2rem; overflow: hidden; }
.project-single__media img, .project-single__media video { width: 100%; }

.not-found { text-align: center; padding-block: 8rem; }
.not-found__code { font-family: var(--font-display); font-size: 6rem; font-weight: 900; color: var(--color-orange); margin: 0; }

.insights-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 2rem; }
.insight-card__media { display: block; overflow: hidden; aspect-ratio: 4/3; margin-bottom: 1rem; }
.insight-card__meta { font-size: 0.8rem; color: var(--color-orange); font-weight: 600; }
.insight-card__title { display: block; font-family: var(--font-display); font-weight: 700; font-size: 1.2rem; margin-block: 0.3em; }
.insight-card__excerpt { font-size: 0.9rem; }

.contact-form { max-width: 640px; margin-inline: auto; display: flex; flex-direction: column; gap: 1.25rem; }
.contact-form__honeypot { position: absolute; left: -9999px; }
.form-field { display: flex; flex-direction: column; gap: 0.4rem; }
.form-field label { font-weight: 600; font-size: 0.9rem; }
.form-field input, .form-field textarea { padding: 0.85em 1em; border: 1px solid var(--color-line); background: transparent; }
.form-field input:focus, .form-field textarea:focus { border-color: var(--color-orange); outline: none; }
.form-notice { padding: 1em 1.25em; margin-bottom: 1.5rem; text-align: center; }
.form-notice--success { background: #e8f5e6; color: var(--color-green); }
.form-notice--error { background: #fbe6e6; color: var(--color-red); }
/* Standalone Contact page's submit only — a filled button rather than
   the sitewide plain text-link .button style, orange as standard,
   black on hover. Sharp corners to match the sitewide no-border-radius
   rule (the language-switcher pill is the one deliberate exception). */
.contact-form__submit { justify-content: center; align-self: flex-start; background: var(--color-orange); color: var(--color-white); padding: 0.9em 1.75em; border: none; }
.contact-form__submit:hover, .contact-form__submit:focus-visible { background: var(--color-black); color: var(--color-white); }

/* ---- Freelancer Database page: the WPForms form, restyled to match the
   theme's own .contact-form (same 640px column, 1.25rem rhythm, bold small
   labels, hairline inputs, orange filled submit with sharp corners). WPForms
   (modern render) is themed through CSS custom properties, so those are set
   first; the direct rules below catch anything the variables don't reach.
   The anti-spam honeypot fields WPForms injects are absolutely positioned
   by the plugin itself, so nothing here touches their layout. ---- */
.freelancer-lede { text-align: center; }
.freelancer-form { max-width: 640px; margin-inline: auto; }
.freelancer-form .wpforms-container {
	--wpforms-field-border-radius: 0px;
	--wpforms-field-border-color: var(--color-line);
	--wpforms-field-background-color: transparent;
	--wpforms-field-text-color: var(--color-ink);
	--wpforms-field-size-input-height: auto;
	--wpforms-label-color: var(--color-ink);
	--wpforms-label-sublabel-color: var(--color-body);
	--wpforms-button-border-radius: 0px;
	--wpforms-button-background-color: var(--color-orange);
	--wpforms-button-text-color: var(--color-white);
	--wpforms-button-border-color: var(--color-orange);
	--wpforms-page-break-color: var(--color-orange);
	margin: 0; padding: 0; max-width: none;
}
.freelancer-form .wpforms-form .wpforms-field-container { display: flex; flex-direction: column; gap: 1.25rem; }
.freelancer-form .wpforms-form .wpforms-field { padding: 0; margin: 0; }
.freelancer-form .wpforms-form .wpforms-field-label,
.freelancer-form .wpforms-form legend.wpforms-field-label { font-weight: 600; font-size: 0.9rem; line-height: 1.4; margin: 0 0 0.4rem; color: var(--color-ink); }
.freelancer-form .wpforms-required-label { color: var(--color-orange); }
.freelancer-form .wpforms-form input[type="text"],
.freelancer-form .wpforms-form input[type="email"],
.freelancer-form .wpforms-form input[type="tel"],
.freelancer-form .wpforms-form input[type="url"],
.freelancer-form .wpforms-form textarea {
	width: 100%; max-width: 100%; box-sizing: border-box; padding: 0.85em 1em; font: inherit; color: var(--color-ink);
	border: 1px solid var(--color-line); border-radius: 0; background: transparent; box-shadow: none; height: auto;
}
.freelancer-form .wpforms-form .wpforms-field-medium,
.freelancer-form .wpforms-form .wpforms-field-large { max-width: 100%; width: 100%; }
.freelancer-form .wpforms-form input:focus,
.freelancer-form .wpforms-form textarea:focus { border-color: var(--color-orange); outline: none; box-shadow: none; }
/* Yes / No checkbox groups sit side by side rather than stacked. */
.freelancer-form .wpforms-form .wpforms-field-checkbox ul { list-style: none; margin: 0; padding: 0; display: flex !important; flex-wrap: wrap; grid-template-columns: none !important; gap: 0.5rem 1.75rem; }
.freelancer-form .wpforms-form .wpforms-field-checkbox li { margin: 0; padding: 0; display: flex; align-items: center; gap: 0.5rem; }
.freelancer-form .wpforms-form .wpforms-field-checkbox input[type="checkbox"] { width: 1.1rem; height: 1.1rem; margin: 0; accent-color: var(--color-orange); }
.freelancer-form .wpforms-form .wpforms-field-label-inline { font-weight: 400; font-size: 1rem; margin: 0; line-height: 1.2; }
.freelancer-form .wpforms-form label.wpforms-error,
.freelancer-form .wpforms-form em.wpforms-error { display: block; margin-top: 0.35rem; font-size: 0.85rem; font-weight: 400; color: var(--color-red); }
.freelancer-form .wpforms-form .wpforms-submit-container { margin: 1.25rem 0 0; padding: 0; }
.freelancer-form .wpforms-form button.wpforms-submit {
	display: inline-flex; justify-content: center; align-items: center; background: var(--color-orange) !important; color: var(--color-white) !important;
	padding: 0.9em 1.75em; border: none !important; border-radius: 0; font: inherit; font-weight: 600; cursor: pointer; height: auto; box-shadow: none;
}
.freelancer-form .wpforms-form button.wpforms-submit:hover,
.freelancer-form .wpforms-form button.wpforms-submit:focus-visible { background: var(--color-black) !important; color: var(--color-white) !important; }
.freelancer-form .wpforms-confirmation-container-full,
.freelancer-form .wpforms-confirmation-container { background: #e8f5e6; color: var(--color-green); border: none; border-radius: 0; padding: 1em 1.25em; margin: 0 0 1.5rem; text-align: center; }
.freelancer-form__note { margin: 2rem 0 0; text-align: center; font-size: 0.9rem; color: var(--color-body); }
.freelancer-form__note a { color: inherit; }

.pagination ul { display: flex; gap: 0.5rem; justify-content: center; margin-top: 3rem; }
.pagination a, .pagination span { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--color-line); }
.pagination .current { background: var(--color-orange); color: var(--color-white); border-color: var(--color-orange); }

.comments-area { max-width: 75ch; margin: 3rem auto; }
.comment-list { display: flex; flex-direction: column; gap: 1.5rem; }
