/* ==========================================================================
   Dot And Draft — main stylesheet
   --------------------------------------------------------------------------
   1.  Fonts
   2.  Design tokens
   3.  Base / reset
   4.  Shared components (buttons, badges, pills, social buttons, accordion)
   5.  Section layout + section heading
   6.  Header (Menu bar + panel)
   7.  Contact form (the plugin's form, on the home and Contact pages)
   8.  Footer
   9.  Inner pages (index.php fallback)
   10. Animations

   Breakpoints (max-width, desktop-first, same as the original design):
   1439px · 1200px · 810px · 767px · 478px
   ========================================================================== */


/* 1. Fonts
   ========================================================================== */

@font-face {
	font-family: "Inter";
	font-weight: 300;
	font-style: normal;
	font-display: swap;
	src: url("../fonts/inter-300.woff2") format("woff2");
}

@font-face {
	font-family: "Inter";
	font-weight: 400;
	font-style: normal;
	font-display: swap;
	src: url("../fonts/inter-400.woff2") format("woff2");
}

@font-face {
	font-family: "Inter";
	font-weight: 500;
	font-style: normal;
	font-display: swap;
	src: url("../fonts/inter-500.woff2") format("woff2");
}

@font-face {
	font-family: "Inter";
	font-weight: 700;
	font-style: normal;
	font-display: swap;
	src: url("../fonts/inter-700.woff2") format("woff2");
}


/* 2. Design tokens
   ========================================================================== */

:root {
	/* Colours */
	--color-ink: #1b1a19;          /* primary text, dark buttons */
	--color-paper: #e5e5e5;        /* light text on dark, light buttons */
	--color-mist: #eef4f4;         /* pale cards, badges */
	--color-night: #111110;        /* darkest cards */
	--color-orange: #f7931e;
	--color-green: #5ae55a;        /* "available" dot */
	--color-body: #363636;
	--color-line: rgba(0, 0, 0, 0.1);
	--color-line-light: rgba(255, 255, 255, 0.1);
	--color-placeholder: rgba(29, 28, 27, 0.6);

	/* Type */
	--font-sans: "Inter", -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
	--font-system: -apple-system, "system-ui", "Segoe UI", roboto, helvetica, arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";

	/* Spacing scale */
	--space-xs: 5px;
	--space-s: 10px;
	--space-m: 30px;
	--space-l: 50px;
	--space-xl: 80px;
	--space-xxl: 100px;

	/* Page side padding (shrinks per breakpoint below) */
	--gutter: 46px;

	/* Radii */
	--radius: 15px;
	--radius-lg: 20px;
	--radius-pill: 50px;

	/* Shadows — layered, soft (on light surfaces) and deep (on dark) */
	--shadow-soft:
		rgba(158, 158, 158, 0.69) 0 0.706592px 0.706592px -0.583333px,
		rgba(158, 158, 158, 0.68) 0 1.80656px 1.80656px -1.16667px,
		rgba(158, 158, 158, 0.65) 0 3.62176px 3.62176px -1.75px,
		rgba(158, 158, 158, 0.61) 0 6.8656px 6.8656px -2.33333px,
		rgba(158, 158, 158, 0.52) 0 13.6468px 13.6468px -2.91667px,
		rgba(158, 158, 158, 0.3) 0 30px 30px -3.5px;
	--shadow-deep:
		rgba(61, 61, 61, 0.72) 0 0.602187px 1.08394px -1.25px,
		rgba(61, 61, 61, 0.64) 0 2.28853px 4.11936px -2.5px,
		rgba(61, 61, 61, 0.25) 0 10px 18px -3.75px,
		rgba(0, 0, 0, 0.35) 0 0.706592px 0.706592px -0.583333px,
		rgba(0, 0, 0, 0.34) 0 1.80656px 1.80656px -1.16667px,
		rgba(0, 0, 0, 0.33) 0 3.62176px 3.62176px -1.75px,
		rgba(0, 0, 0, 0.3) 0 6.8656px 6.8656px -2.33333px,
		rgba(0, 0, 0, 0.26) 0 13.6468px 13.6468px -2.91667px,
		rgba(0, 0, 0, 0.15) 0 30px 30px -3.5px;
	--shadow-glass: rgba(0, 0, 0, 0.12) 0 8px 30px;

	/* Fluid heading sizes */
	--size-display: 52px;   /* hero headline + watermark */
	--size-title-lg: clamp(42px, -6px + 3.33vw, 58px);  /* section titles */
	--size-title-md: clamp(28px, 16px + 0.83vw, 32px);  /* card titles */
}

@media (max-width: 1439px) {
	:root {
		--gutter: 40px;
		--size-display: 44px;
		--size-title-lg: clamp(38px, 7.72px + 2.52vw, 44px);
		--size-title-md: clamp(25px, 9.87px + 1.26vw, 28px);
	}
}

@media (max-width: 1200px) {
	:root {
		--gutter: 24px;
		--size-display: 38px;
		--size-title-lg: clamp(34px, 25.66px + 1.04vw, 38px);
		--size-title-md: 25px;
	}
}

@media (max-width: 810px) {
	:root {
		--gutter: 20px;
		--size-display: 28px;
		--size-title-md: clamp(21px, 15.21px + 1.2vw, 25px);
	}
}

@media (max-width: 478px) {
	:root {
		--gutter: 16px;
		--size-display: clamp(22px, 1.75px + 6.33vw, 32px);
		--size-title-lg: clamp(21px, 10.87px + 3.17vw, 26px);
		--size-title-md: 21px;
	}
}


/* 3. Base / reset
   ========================================================================== */

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

html {
	line-height: 1.15;
	scroll-behavior: smooth;
	scroll-padding-top: 50px;
	overflow-x: hidden;
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
}

/* Lenis (smooth scrolling, main.js) animates the scroll itself, so the
   browser's own smooth scrolling must be off while it's running. */
html.lenis {
	scroll-behavior: auto;
}

/* The scrollbar's space is always kept, and while the page is locked (the
   open menu stops Lenis) it's locked with "hidden", which keeps that space,
   instead of Lenis's "clip", which drops the scrollbar — so the page behind
   doesn't jump sideways when the menu opens or closes. */
html {
	scrollbar-gutter: stable;
}

/* The dim layer can't reach that kept scrollbar space: the browser paints
   it with the body's background (white). While the menu is open the body
   gets the dimmed colour instead — the page backdrop (#d1d1d1 on screen)
   under the 45% ink dim layer — fading at the same speed. (It has to be the
   body, not html: a background on html would stop the body's showing
   through, and the white body would then cover the page backdrop.) */
body {
	transition: background-color 0.5s;
}

html.has-menu-open body {
	background-color: color-mix(in srgb, var(--color-ink) 45%, #d1d1d1);
}

html.lenis.lenis-stopped:not(.lenis-autoToggle) {
	overflow: hidden;
}

/* While the page glides, cards passing under a still mouse don't trigger
   their hover effects (each one repaints). After a wheel or trackpad scroll
   they stay off until the mouse moves (main.js, is-hover-paused), so the
   card under a still pointer doesn't lift just after the page stops. Opt
   back in with data-hover-while-scrolling. */
html.lenis-scrolling main,
html.is-hover-paused main {
	pointer-events: none;
}

html.lenis-scrolling [data-hover-while-scrolling],
html.is-hover-paused [data-hover-while-scrolling] {
	pointer-events: auto;
}

body {
	margin: 0;
	padding: 0;
	overflow-x: hidden;
	overflow-x: clip; /* Clips like hidden, but keeps position: sticky working. */
	background-color: #fff;
	color: var(--color-body);
	font-family: var(--font-system);
	font-size: 15px;
	line-height: 1.7;
	-webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
h6 {
	margin: 0;
	line-height: 1.4;
	text-rendering: optimizeLegibility;
}

h1 a,
h2 a,
h3 a,
h4 a,
h5 a,
h6 a {
	color: currentColor;
}

p {
	margin: 0;
}

a {
	color: inherit;
	text-decoration: none;
}

img {
	max-width: 100%;
	height: auto;
	border-style: none;
	vertical-align: middle;
}

svg {
	overflow: visible;
}

button,
input,
textarea,
select {
	margin: 0;
	font-family: inherit;
	font-size: 100%;
	line-height: 1.15;
	text-align: inherit;
}

button {
	padding: 0;
	border: none;
	background: none;
	color: inherit;
	cursor: pointer;
	text-transform: none;
}

:focus-visible {
	outline: auto;
}

.text-muted {
	opacity: 0.6;
}

.skip-link {
	position: absolute;
	top: 0;
	left: 0;
	z-index: 1000;
	height: 1px;
	padding: 5px 10px;
	overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	border-bottom-right-radius: 8px;
	background: #000;
	color: #fff;
	font-weight: 700;
}

.skip-link:focus {
	height: auto;
	overflow: visible;
	clip: auto;
}

.icon {
	display: inline-block;
	width: auto;
	height: 1em;
	flex-shrink: 0;
}

/* Fixed textured backdrop behind the whole page. */
.page-backdrop {
	position: fixed;
	top: 0;
	left: 0;
	z-index: -1;
	width: 100%;
	height: 100vh;
	background-color: var(--color-paper);
	background-image: url("../images/ui/page-texture.webp");
	background-size: cover;
	background-blend-mode: hard-light;
	pointer-events: none;
}

/* Hero background (dd_hero_dots(), on every page with a hero): a fine dot
   grid with a few orange dots softly twinkling, on top of the backdrop and
   behind the content — from the top of the page to about the middle of the
   screen, fading out. */
.hero-dots {
	--dot-ink: color-mix(in srgb, var(--color-ink) 14%, transparent);
	--dot-orange: color-mix(in srgb, var(--color-orange) 70%, transparent);
	position: absolute;
	top: 0;
	right: 0;
	left: 0;
	z-index: -1;
	height: min(75vh, 760px);
	overflow: hidden;
	pointer-events: none;
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 25%, transparent 100%);
	mask-image: linear-gradient(to bottom, #000 0%, #000 25%, transparent 100%);
}

.hero-dots::before,
.hero-dots::after {
	content: "";
	position: absolute;
	inset: 0;
}

.hero-dots::before {
	background-image: radial-gradient(circle, var(--dot-ink) 1.4px, transparent 1.8px);
	background-size: 22px 22px;
	background-position: center top;
}

/* Orange dots on much wider, offset grids — so only a scattered few. */
.hero-dots::after {
	background-image:
		radial-gradient(circle, var(--dot-orange) 2.6px, transparent 3.2px),
		radial-gradient(circle, var(--dot-orange) 2.6px, transparent 3.2px);
	background-size: 154px 132px, 198px 176px;
	background-position: calc(50% + 11px) 11px, calc(50% - 77px) 99px;
	-webkit-mask-image: radial-gradient(ellipse 60% 70% at 50% 0%, #000, transparent);
	mask-image: radial-gradient(ellipse 60% 70% at 50% 0%, #000, transparent);
	animation: dd-dots-twinkle 4s ease-in-out infinite alternate;
	will-change: opacity; /* Twinkle on the graphics card, not a repaint per frame. */
}

@keyframes dd-dots-twinkle {
	to {
		opacity: 0.35;
	}
}

@media (prefers-reduced-motion: reduce) {
	.hero-dots::after {
		animation: none;
	}
}

@media (max-width: 810px) {
	html {
		scroll-padding-top: 30px;
	}
}


/* 4. Shared components
   ========================================================================== */

/* Buttons ---------------------------------------------------------------- */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	height: 40px;
	padding: 0.5em 1em;
	border: 0;
	border-radius: var(--radius-pill);
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: -0.5px;
	text-align: center;
	text-transform: uppercase;
	cursor: pointer;
}

.btn--dark {
	background-color: var(--color-ink);
	box-shadow: var(--shadow-deep);
	color: var(--color-paper);
}

.btn--mist {
	background-color: var(--color-mist);
	box-shadow: var(--shadow-soft);
	color: var(--color-ink);
}

.btn--paper {
	background-color: var(--color-paper);
	box-shadow: var(--shadow-soft);
	color: var(--color-ink);
}

/* Button hover — every page. Light buttons go dark, dark buttons go light,
   with a 5px lift and a shadow change (the same feel as the team cards'
   social icons). The lift uses the separate `translate` property, because
   some buttons (hero, header) keep a `transform` from their entrance
   animation that would otherwise cancel a transform-based lift. */
.btn {
	transition:
		background-color 0.3s,
		color 0.3s,
		box-shadow 0.3s,
		translate 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}

.btn--mist:hover,
.btn--paper:hover,
.btn--mist:focus-visible,
.btn--paper:focus-visible {
	background-color: var(--color-ink);
	box-shadow: var(--shadow-deep);
	color: var(--color-paper);
	translate: 0 -5px;
}

.btn--dark:hover,
.btn--dark:focus-visible {
	background-color: var(--color-paper);
	box-shadow: var(--shadow-soft);
	color: var(--color-ink);
	translate: 0 -5px;
}

/* Pressed */
.btn:active {
	translate: 0 -2px;
}

@media (prefers-reduced-motion: reduce) {
	.btn:hover,
	.btn:focus-visible,
	.btn:active {
		translate: none;
	}
}

/* Status badge ("● AVAILABLE FOR WORK") ---------------------------------- */

.status-badge {
	display: flex;
	align-items: center;
	column-gap: var(--space-s);
	height: 30px;
	padding: 0 var(--space-s);
	border-radius: var(--radius-pill);
	background-color: var(--color-mist);
	box-shadow: var(--shadow-soft);
}

.status-badge__dot {
	position: relative;
	display: inline-block;
	flex-shrink: 0;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background-color: var(--color-green);
}

/* The pulse is a ring that grows and fades. Only transform + opacity are
   animated, so the graphics card does it without repainting the page
   (animating box-shadow repainted every frame and made fast scrolling
   show blank areas). */
.status-badge__dot::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background-color: rgba(34, 197, 94, 0.6);
	animation: dd-pulse 1.8s ease-in-out infinite;
	pointer-events: none;
}

/* Not available (every availability badge, when slots are off in
   Settings: dd_status_badge()): a coral dot and pulse. */
.status-badge--busy .status-badge__dot {
	background-color: #ff7a3b;
}

.status-badge--busy .status-badge__dot::after {
	background-color: rgba(255, 122, 59, 0.6);
}

.status-badge__text {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 10px;
	font-weight: 400;
	line-height: 1.4;
	text-transform: uppercase;
}

/* Pills (project tags / year) --------------------------------------------- */

.pill {
	display: inline-flex;
	align-items: center;
	padding: var(--space-xs) var(--space-s);
	border-radius: var(--radius-pill);
	box-shadow: var(--shadow-deep);
	font-family: var(--font-sans);
	font-size: 12px;
	font-weight: 400;
	letter-spacing: -0.5px;
	line-height: 1;
}

.pill--light {
	background-color: var(--color-mist);
	color: var(--color-ink);
}

.pill--dark {
	background-color: var(--color-ink);
	color: var(--color-paper);
}

/* Round social buttons ---------------------------------------------------- */

.social-button {
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: var(--radius-pill);
	background-color: var(--color-paper);
	box-shadow: var(--shadow-soft);
	list-style: none;
}

.social-button a {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	padding: 15px;
	color: var(--color-ink);
	font-size: 20px;
}

.social-button--hover {
	transition: background-color 0.3s, transform 0.3s, box-shadow 0.3s;
}

.social-button--hover a {
	transition: color 0.3s;
}

.social-button--hover:hover {
	transform: translateY(-5px);
	background-color: var(--color-ink);
	box-shadow: var(--shadow-deep);
}

.social-button--hover:hover a {
	color: var(--color-paper);
}

@media (max-width: 478px) {
	.social-button a {
		width: 45px;
		height: 45px;
	}
}

/* Accordion (services "whole list" + FAQ) --------------------------------- */

.accordion {
	display: flex;
	flex-direction: column;
	width: 100%;
}

.accordion--light {
	gap: var(--space-s);
}

.accordion__item {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	width: 100%;
}

.accordion__heading {
	margin: 0;
	font-size: inherit;
}

.accordion__toggle {
	display: flex;
	flex-flow: row;
	align-items: center;
	justify-content: space-between;
	width: 100%;
	min-height: 75px;
	padding: 0 0 0 var(--space-m);
	overflow: clip;
	border-radius: var(--radius);
	font-family: var(--font-sans);
	font-size: 20px;
	text-align: left;
	user-select: none;
	transition: 0.15s;
}

.accordion__title {
	font-family: var(--font-sans);
	font-size: 20px;
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.2;
	opacity: 0.6;
}

.accordion__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	align-self: center;
	width: 75px;
	height: 75px;
	border-radius: var(--radius);
	font-size: 20px;
	opacity: 0.6;
	transition: transform 0.5s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s;
}

.accordion__toggle:hover .accordion__icon {
	opacity: 1;
}

.accordion__toggle[aria-expanded="true"] .accordion__icon {
	opacity: 1;
	transform: rotate(90deg);
}

.accordion__panel {
	display: flex;
	flex-direction: row;
	align-items: stretch;
	margin-top: var(--space-s);
	overflow: hidden;
	border-radius: var(--radius);
}

.accordion__panel[hidden] {
	display: none;
}

/*
 * Animated open/close (once main.js has set the accordion up — without JS the
 * panels simply use the hidden attribute above).
 * The panel's single grid row animates from 0fr to 1fr, so the height eases
 * to the content's real height; the gap above, the fade and the content's
 * small slide-down all run on the same curve, and a second click mid-way
 * smoothly reverses it.
 */
.accordion.is-animated .accordion__panel {
	--accordion-speed: 0.55s;
	--accordion-ease: cubic-bezier(0.22, 1, 0.36, 1);
	display: grid;
	grid-template-rows: 0fr;
	margin-top: 0;
	opacity: 0;
	transition:
		grid-template-rows var(--accordion-speed) var(--accordion-ease),
		margin-top var(--accordion-speed) var(--accordion-ease),
		opacity 0.35s ease;
}

.accordion.is-animated .accordion__item.is-open .accordion__panel {
	grid-template-rows: 1fr;
	margin-top: var(--space-s);
	opacity: 1;
}

/* Wrapper added by main.js: clips the content while the row is collapsing. */
.accordion__clip {
	display: flex;
	min-height: 0;
	overflow: hidden;
}

.accordion__clip > * {
	transform: translateY(-12px);
	transition: transform var(--accordion-speed, 0.55s) var(--accordion-ease, ease);
}

.accordion__item.is-open .accordion__clip > * {
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.accordion.is-animated .accordion__panel,
	.accordion__clip > *,
	.accordion__icon {
		transition: none;
	}
}

.accordion__panel-inner {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	width: 100%;
	padding: var(--space-m);
}

/* Dark variant (services list) */
.accordion--dark .accordion__toggle {
	background-color: var(--color-ink);
	box-shadow: var(--shadow-deep);
	color: var(--color-paper);
}

.accordion--dark .accordion__title {
	color: var(--color-paper);
}

.accordion--dark .accordion__icon {
	border: 1px solid var(--color-line-light);
	background-color: var(--color-night);
	color: var(--color-paper);
}

.accordion--dark .accordion__panel {
	background-color: var(--color-ink);
	box-shadow: var(--shadow-deep);
}

/* Light variant (FAQ) */
.accordion--light .accordion__toggle {
	background-color: var(--color-paper);
	box-shadow: var(--shadow-soft);
	color: var(--color-ink);
}

.accordion--light .accordion__title {
	color: var(--color-ink);
}

.accordion--light .accordion__icon {
	border: 1px solid var(--color-line);
	background-color: var(--color-mist);
	color: var(--color-ink);
}

.accordion--light .accordion__panel {
	background-color: var(--color-paper);
	box-shadow: var(--shadow-soft);
}

.accordion__answer {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 15px;
	font-weight: 300;
	letter-spacing: -0.5px;
	line-height: 1.2;
	opacity: 0.6;
}

@media (max-width: 1200px) {
	.accordion__title,
	.accordion--light .accordion__toggle {
		font-size: 18px;
	}
}

@media (max-width: 810px) {
	.accordion__title {
		font-size: 14px;
	}

	.accordion--dark .accordion__title {
		text-align: center;
	}

	.accordion--light .accordion__panel-inner {
		padding: var(--space-m) var(--space-s);
	}

	.accordion__answer {
		font-size: 14px;
	}
}

@media (max-width: 478px) {
	.accordion__toggle {
		padding-left: var(--space-s);
	}

	.accordion--dark .accordion__title {
		text-align: left;
	}

	.accordion--light .accordion__title {
		width: 300px;
	}

	.accordion--light .accordion__panel-inner {
		padding: var(--space-s);
	}
}


/* 5. Section layout + section heading
   ========================================================================== */

.site-main {
	position: relative;
	display: flow-root; /* The first section's top margin stays inside, so the
	                       hero background starts at the very top of the page. */
	width: 100%;
}

.section {
	display: flex;
	flex-direction: column;
	align-items: center;
	row-gap: var(--space-xl);
	width: 100%;
	max-width: 1920px;
	margin: 0 auto var(--space-xl);
	padding: 0 var(--gutter);
}

/* Bordered column that holds a section's heading + content. */
.section__inner {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--space-l);
	width: 100%;
	margin-top: var(--space-l);
	border-top: 1px solid var(--color-line);
}

.section__inner--wide-gap {
	row-gap: var(--space-xxl);
}

.section-head {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	row-gap: var(--space-l);
	width: 100%;
	padding-top: var(--space-s);
	border-top: 1px solid var(--color-line);
}

.section-head__meta {
	display: flex;
	flex-direction: row;
	justify-content: space-between;
	width: 100%;
}

.section-head__index,
.section-head__label {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 10px;
	font-weight: 500;
	line-height: 1.4;
	text-transform: uppercase;
}

.section-head__body {
	display: flex;
	flex-direction: row;
	align-items: flex-end;
	justify-content: space-between;
	width: 100%;
}

.section-head__title {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: var(--size-title-lg);
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.1;
}

.section-head__intro {
	flex-shrink: 0;
	width: 320px;
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 15px;
	font-weight: 300;
	letter-spacing: -0.5px;
	line-height: 1.2;
	opacity: 0.6;
}

@media (max-width: 1200px) {
	.section__inner--wide-gap {
		row-gap: var(--space-l);
	}

	.section-head {
		row-gap: var(--space-m);
	}

	.section-head__intro {
		width: 225px;
		text-align: left;
	}
}

@media (max-width: 810px) {
	.section-head__body {
		flex-direction: column;
		align-items: flex-start;
		row-gap: var(--space-s);
	}

	.about .section-head__title {
		white-space: normal;
	}

	.section-head__intro {
		width: 100%;
		font-size: 14px;
	}
}

@media (max-width: 478px) {
	.section {
		row-gap: var(--space-l);
	}
}


/* 6. Header
   ==========================================================================
   A compact dark bar fixed at the top: "☰ Menu" · logo · Contact Us — the
   N9 design (template-parts/header/site-header.php; behaviour in main.js,
   initSiteHeader). Panel: pages on an orange card · what we do · a
   "Got a project?" card.

   Opening: the bar stretches sideways (to 1000px at most), then opens
   downward to the height the script measures (--panel-h), then the cards
   fade up — each with a soft elastic settle. Closing runs it backwards,
   smoothly (no bounce). Scrolling down shrinks the bar a little and the logo
   collapses to the orange dot. */

.site-header {
	--nav-ease: cubic-bezier(0.65, 0, 0.35, 1);
	--nav-out: cubic-bezier(0.22, 1, 0.36, 1);
	--nav-spring: cubic-bezier(0.34, 1.32, 0.64, 1); /* soft elastic: a small overshoot, then settles */
	position: fixed;
	top: 12px;
	right: 0;
	left: 0;
	z-index: 998;
	height: 56px;
	padding: 0 var(--gutter);
	font-family: var(--font-sans); /* Everything in the header uses Inter (body is the system font). */
	pointer-events: none; /* Only the bar itself takes clicks. */
}

.admin-bar .site-header {
	top: calc(var(--wp-admin--admin-bar--height, 32px) + 12px);
}

/* The page dims behind the open menu. */
.site-header__scrim {
	position: fixed;
	inset: 0;
	z-index: 997;
	background-color: var(--color-ink);
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.5s;
}

.has-menu-open .site-header__scrim {
	opacity: 0.45;
	pointer-events: auto;
}

.site-header__box {
	position: absolute;
	top: 0;
	/* Centred with auto margins, not left: 50% + translate: -50% — while the
	   width animates, half of it is a fraction of a pixel, and the translate
	   made the logo shimmer from frame to frame. */
	right: 0;
	left: 0;
	width: min(640px, calc(100% - 2 * var(--gutter)));
	margin-inline: auto;
	overflow: hidden;
	border-radius: var(--radius);
	background-color: var(--color-ink);
	box-shadow: var(--shadow-deep);
	color: var(--color-paper);
	pointer-events: auto;
	/* Closing: wait for the panel to fold up, then narrow (no bounce). */
	transition: width 0.5s var(--nav-ease) 0.45s;
}

/* Opening: stretches out to 1000px at most, with a soft elastic settle. */
.site-header.is-open .site-header__box {
	width: min(1000px, calc(100% - 2 * var(--gutter)));
	transition: width 0.75s var(--nav-spring) 0s;
}

.site-header__bar {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	align-items: center;
	height: 56px;
	padding: 0 var(--space-xs) 0 var(--space-m);
	transition: height 0.4s var(--nav-out);
}

.site-header__toggle {
	display: inline-flex;
	align-items: center;
	justify-self: start;
	gap: var(--space-s);
	padding: var(--space-xs) 0;
	border: 0;
	background: none;
	color: var(--color-paper);
	font-family: var(--font-sans);
	font-size: 15px;
	font-weight: 500;
	letter-spacing: -0.5px;
	cursor: pointer;
}

/* Two lines that cross into an ×. */
.site-header__burger {
	position: relative;
	width: 18px;
	height: 10px;
}

.site-header__burger i {
	position: absolute;
	left: 0;
	width: 100%;
	height: 2px;
	border-radius: 2px;
	background-color: currentColor;
	transition: top 0.3s var(--nav-out), rotate 0.3s var(--nav-out);
}

.site-header__burger i:first-child {
	top: 0;
}

.site-header__burger i:last-child {
	top: 8px;
}

.site-header.is-open .site-header__burger i:first-child {
	top: 4px;
	rotate: 45deg;
}

.site-header.is-open .site-header__burger i:last-child {
	top: 4px;
	rotate: -45deg;
}

.site-header__logo {
	position: relative;
	display: grid;
	place-items: center;
	/* Held at the top of the bar where centring puts it at full height
	   ((56 - 25) / 2); when the bar shrinks to 48px it glides up 4px with
	   `translate` (smooth, on the graphics card) instead of being
	   re-centred by layout, which moved it in whole-pixel jumps. */
	align-self: start;
	margin-top: 15.5px;
	color: var(--color-paper);
	transition: translate 0.4s var(--nav-out);
}

.site-header__full {
	display: inline-flex;
	grid-area: 1 / 1;
	align-items: center;
	gap: 5px;
	transition: opacity 0.3s, scale 0.4s var(--nav-out);
}

.site-header__logo .site-logo__mark {
	width: auto;
	height: 25px;
}

/* The mark's letters are dark: light on the dark bar. */
.site-header__logo .logo-mark__bowl,
.site-header__logo .logo-mark__stem path {
	fill: var(--color-paper);
}

.site-header__name {
	font-size: 15px;
	font-weight: 700;
	letter-spacing: -0.5px;
	line-height: 1;
	text-transform: uppercase;
	white-space: nowrap;
}

/* Scrolled: just the orange dot, centred. */
.site-header__dot {
	grid-area: 1 / 1;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background-color: var(--color-orange);
	opacity: 0;
	scale: 0;
	transition: opacity 0.3s, scale 0.5s var(--nav-out);
}

.site-header__cta {
	display: inline-flex;
	align-items: center;
	justify-self: end;
	height: 40px;
	padding: 0 var(--space-m);
	border-radius: var(--radius-pill);
	background-color: var(--color-orange);
	color: var(--color-ink);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: -0.5px;
	text-transform: uppercase;
	white-space: nowrap;
	transition: background-color 0.3s, color 0.3s, height 0.4s var(--nav-out);
}

.site-header__cta:hover,
.site-header__cta:focus-visible,
.site-header__cta[aria-current="page"] {
	background-color: var(--color-paper);
}

/* Shrink on scroll: a little shorter, the logo down to the orange dot.
   (Opening the menu brings the full logo back.) */
.site-header.is-scrolled .site-header__bar {
	height: 48px;
}

.site-header.is-scrolled .site-header__logo {
	translate: 0 -4px;
}

.site-header.is-scrolled .site-header__cta {
	height: 35px;
}

.site-header.is-scrolled:not(.is-open) .site-header__full {
	opacity: 0;
	scale: 0.6;
}

.site-header.is-scrolled:not(.is-open) .site-header__dot {
	opacity: 1;
	scale: 1;
}

/* The panel: opens downward to --panel-h; folds up first when closing. */
.site-header__panel {
	height: 0;
	overflow: hidden;
	transition: height 0.5s var(--nav-ease) 0s;
}

.site-header.is-open .site-header__panel {
	height: var(--panel-h, auto);
	transition: height 0.8s var(--nav-spring) 0.35s;
}

.site-header__clip {
	overflow: hidden;
	border-top: 1px solid transparent;
	transition: border-color 0.3s;
}

.site-header.is-open .site-header__clip {
	max-height: var(--panel-h, calc(100svh - 120px));
	border-top-color: var(--color-line-light);
}

/* Scrolls only once it has finished opening, and only when the content
   doesn't fit (the script adds .is-scrollable) — no scrollbar flash. */
.site-header.is-scrollable .site-header__clip {
	overflow-y: auto;
	overscroll-behavior: contain;
}

.site-header__cards {
	display: grid;
	/* The middle one (what we do) a touch wider for its longest name. */
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr) minmax(0, 1fr);
	gap: var(--space-s);
	padding: var(--space-s);
}

/* The cards fade up once the panel is open, one after another. */
.site-header__cards > *,
.site-header__foot {
	opacity: 0;
	translate: 0 12px;
	transition: opacity 0.25s, translate 0.25s;
}

.site-header.is-open .site-header__cards > *,
.site-header.is-open .site-header__foot {
	opacity: 1;
	translate: 0 0;
	transition: opacity 0.5s var(--nav-out), translate 0.7s var(--nav-spring);
	transition-delay: 0.6s;
}

.site-header.is-open .site-header__cards > :nth-child(2) {
	transition-delay: 0.68s;
}

.site-header.is-open .site-header__cards > :nth-child(3) {
	transition-delay: 0.76s;
}

.site-header__card {
	display: flex;
	flex-direction: column;
	gap: var(--space-s);
	padding: var(--space-l);
	border-radius: var(--radius);
	background-color: var(--color-night);
}

/* No background, so it can sit closer to its edges (room for the
   longest service name plus its hover arrow on one line). */
.site-header__card--plain {
	padding-right: var(--space-s);
	padding-left: var(--space-m);
	background-color: transparent;
}

/* The pages, on orange (dark type, dark lines, a dark underline). */
.site-header__card--orange {
	background-color: var(--color-orange);
	color: var(--color-ink);
}

.site-header__label {
	font-size: 12px;
	font-weight: 500;
	text-transform: uppercase;
	opacity: 0.6;
}

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

.site-header__links li + li {
	border-top: 1px solid var(--color-line-light);
}

.site-header__link {
	display: flex;
	align-items: center;
	gap: var(--space-s);
	padding: var(--space-s) 0;
	color: var(--color-paper);
	font-size: var(--size-title-md);
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.1;
}

/* Hover (the N3 style): the word slides a little to the right and an arrow
   slides in at the end of the row. The page you're on keeps its arrow. */
.site-header__word {
	flex: 1;
	white-space: nowrap;
	transition: translate 0.4s var(--nav-out);
}

.site-header__go {
	display: inline-flex;
	color: var(--color-orange);
	opacity: 0;
	translate: -10px 0;
	transition: opacity 0.3s, translate 0.4s var(--nav-out);
}

.site-header__link:hover .site-header__word,
.site-header__link:focus-visible .site-header__word {
	translate: 8px 0;
}

.site-header__link:hover .site-header__go,
.site-header__link:focus-visible .site-header__go,
.site-header__link.is-current .site-header__go {
	opacity: 1;
	translate: 0 0;
}

.site-header__card--orange .site-header__link,
.site-header__card--orange .site-header__go {
	color: var(--color-ink);
}

.site-header__card--orange .site-header__links li + li {
	border-top-color: var(--color-line);
}

/* "Got a project?": a dark card with the light rays. */
.site-header__contact {
	justify-content: space-between;
	padding-right: var(--space-m);
	padding-left: var(--space-m);
	background-color: var(--color-night);
	background-image: url("../images/ui/dark-light-rays.webp");
	background-position: right top;
	background-blend-mode: soft-light;
}

.site-header__contact-title {
	font-size: var(--size-title-md);
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.1;
}

.site-header__contact-title .text-muted {
	color: var(--color-paper);
	opacity: 0.5;
}

.site-header__contact-actions {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-s);
}

.site-header__contact-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-s);
	width: 100%;
	height: 40px;
	padding: 0 var(--space-m);
	border-radius: var(--radius-pill);
	background-color: var(--color-paper);
	color: var(--color-ink);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: -0.5px;
	text-transform: uppercase;
	white-space: nowrap;
	transition: background-color 0.3s;
}

.site-header__contact-btn:hover,
.site-header__contact-btn:focus-visible {
	background-color: var(--color-orange);
}

.site-header__chat {
	display: inline-flex;
	align-items: center;
	gap: var(--space-s);
	color: var(--color-paper);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: -0.5px;
}

.site-header__chat-icon {
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background-color: var(--color-ink);
	transition: background-color 0.3s, color 0.3s;
}

.site-header__chat:hover .site-header__chat-icon,
.site-header__chat:focus-visible .site-header__chat-icon {
	background-color: var(--color-orange);
	color: var(--color-ink);
}

/* Bottom buttons: phones only. */
.site-header__foot {
	display: none;
}

/* The WhatsApp bubble steps aside while the menu is open. */
.has-menu-open .ddc-wa {
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.3s;
}

@media (max-width: 1200px) {
	.site-header__cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.site-header__card {
		padding: var(--space-m);
	}

	/* The contact card runs along the bottom. */
	.site-header__contact {
		grid-column: 1 / -1;
		flex-direction: row;
		flex-wrap: wrap;
		align-items: center;
		gap: var(--space-m);
	}

	.site-header__contact .site-header__label {
		display: none;
	}

	.site-header__contact-actions {
		flex-direction: row;
		align-items: center;
	}

	.site-header__contact-btn {
		width: auto;
	}
}

@media (max-width: 810px) {
	.site-header {
		top: var(--space-s);
	}

	.admin-bar .site-header {
		top: calc(var(--wp-admin--admin-bar--height, 46px) + var(--space-s));
	}

	.site-header__box,
	.site-header.is-open .site-header__box {
		width: calc(100% - 2 * var(--gutter));
	}

	.site-header__bar {
		padding: 0 var(--space-xs) 0 var(--space-s);
	}

	.site-header__name {
		display: none;
	}

	.site-header__cta {
		height: 35px;
		padding: 0 var(--space-s);
		font-size: 12px;
	}

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

	.site-header__card {
		padding: var(--space-m) var(--space-m) var(--space-s);
	}

	.site-header__card--plain {
		padding-top: var(--space-s);
	}

	.site-header__link {
		font-size: 20px;
	}

	/* Phones: the WhatsApp button below does the contact card's job. */
	.site-header__contact {
		display: none;
	}

	.site-header__foot {
		display: grid;
		gap: var(--space-xs);
		padding: 0 var(--space-s) var(--space-s);
	}

	.site-header__foot-btn {
		display: flex;
		align-items: center;
		justify-content: center;
		height: 45px;
		border-radius: var(--radius-pill);
		background-color: var(--color-night);
		color: var(--color-paper);
		font-size: 14px;
		font-weight: 700;
		letter-spacing: -0.5px;
		text-transform: uppercase;
	}

	.site-header__foot-btn--accent {
		background-color: var(--color-orange);
		color: var(--color-ink);
	}
}

@media (prefers-reduced-motion: reduce) {
	.site-header *,
	.site-header__scrim {
		transition-duration: 0.01ms !important;
		transition-delay: 0s !important;
	}
}


/* 7. Contact form
   ========================================================================== */

/* The form markup comes from the Dot And Draft Core plugin. */
.contact-form {
	display: flex;
	flex-direction: column;
	width: 100%;
}

.contact-form__row {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	column-gap: var(--space-m);
	width: 100%;
}

.contact-form__label {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 20px;
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.2;
	white-space: nowrap;
}

.contact-form__field {
	width: 100%;
	padding: 0 0 20px;
}

.contact-form__input {
	display: block;
	width: 100%;
	padding: 5px 10px;
	border: 0;
	border-bottom: 1px solid var(--color-line);
	border-radius: 0;
	outline: none;
	background-color: var(--color-paper);
	box-shadow: none;
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 20px;
	font-weight: 400;
	letter-spacing: -0.5px;
	line-height: 1.1;
	transition: all 0.2s;
}

.contact-form__input:focus-visible {
	border-bottom-color: var(--color-ink);
}

textarea.contact-form__input {
	height: auto;
	min-height: 90px;
	font-size: 16px;
	font-weight: 300;
	line-height: 1.7;
	resize: vertical;
}

.contact-form__input::placeholder {
	color: var(--color-placeholder);
	font-family: var(--font-sans);
	font-size: 16px;
	font-weight: 300;
	letter-spacing: -0.5px;
	line-height: 1.1;
	opacity: 1;
}

.contact-form__input.is-invalid {
	border-bottom-color: #d44747;
}

.contact-form__submit-row {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	width: 100%;
}

.contact-form__submit {
	width: 260px;
	padding: 0 var(--space-m);
	line-height: 1;
}

.contact-form__submit[disabled] {
	cursor: progress;
	opacity: 0.7;
}

.contact-form__status {
	width: 100%;
	margin-top: 20px;
	padding: 12px 16px;
	border-radius: var(--radius);
	color: rgba(5, 5, 5, 0.6);
	font-family: var(--font-sans);
	font-size: 16px;
	font-weight: 300;
	letter-spacing: -0.5px;
	line-height: 1.1;
}

.contact-form__status:empty {
	display: none;
}

.contact-form__status.is-success {
	background-color: var(--color-line);
}

.contact-form__status.is-error {
	background-color: rgba(255, 0, 0, 0.16);
	color: rgba(0, 0, 0, 0.6);
}

/* Honeypot: hidden from people, visible to bots. */
.contact-form__trap {
	position: absolute !important;
	left: -9999px !important;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

@media (max-width: 1200px) {
	.contact-form__row {
		flex-direction: column;
	}

	.contact-form__label {
		font-size: 18px;
	}

	.contact-form__field {
		padding: 10px 0 20px;
	}

	.contact-form__input {
		font-size: 18px;
	}

	.contact-form__input::placeholder {
		font-size: 15px;
	}

	.contact-form__submit-row {
		margin-top: var(--space-s);
	}

	.contact-form__status {
		font-size: 15px;
	}
}

@media (max-width: 810px) {
	.contact-form__label {
		font-size: 14px;
	}

	.contact-form__field {
		padding: 5px 0 10px;
	}

	.contact-form__input,
	.contact-form__input::placeholder {
		font-size: 14px;
	}

	textarea.contact-form__input {
		font-size: 16px;
	}

	.contact-form__submit {
		width: 213px;
		height: 45px;
		padding: 0 var(--space-s);
		font-size: 12px;
	}
}

@media (max-width: 478px) {
	.contact-form__label {
		width: 300px;
	}

	.contact-form__status {
		font-size: 14px;
	}

	.contact-form__submit {
		width: 100%;
		height: 45px;
	}
}


/* 8. Footer
   ========================================================================== */

.site-footer {
	position: relative;
	flex-shrink: 0;
	width: 100%;
	margin-top: auto;
}

.site-footer__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 100%;
	max-width: 1920px;
	margin: 0 auto;
	padding: 0 var(--gutter);
}

.site-footer__rule {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	width: 100%;
	margin: var(--space-m) 0;
	border-top: 1px solid var(--color-line);
}

.site-footer__row {
	display: flex;
	flex-direction: row;
	align-items: flex-start;
	justify-content: space-between;
	row-gap: var(--space-l);
	width: 100%;
	padding-top: var(--space-s);
	border-top: 1px solid var(--color-line);
}

.site-footer__links {
	display: flex;
	flex-direction: row;
	column-gap: var(--space-l);
}

.site-footer__text {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 20px;
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.1;
	text-align: left;
}

@media (max-width: 1200px) {
	.site-footer__row {
		row-gap: var(--space-m);
	}

	.site-footer__text {
		font-size: 18px;
	}
}

@media (max-width: 810px) {
	.site-footer__row {
		flex-direction: column;
	}

	.site-footer__links {
		flex-direction: column;
		align-items: flex-start;
		align-self: flex-start;
		column-gap: 0;
		row-gap: var(--space-s);
	}

	.site-footer__text {
		font-size: 14px;
	}
}

@media (max-width: 478px) {
	.site-footer__inner {
		margin-bottom: var(--space-s);
	}

	.site-footer__rule {
		margin: var(--space-s) 0;
	}
}


/* 9. Inner pages (index.php fallback)
   ========================================================================== */

.site-main--inner {
	padding: 160px var(--gutter) var(--space-xl);
}

.content-area {
	width: 100%;
	max-width: 860px;
	margin: 0 auto;
}

.entry + .entry {
	margin-top: var(--space-xl);
}

.entry__title {
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: var(--size-title-lg);
	font-weight: 500;
	letter-spacing: -0.5px;
	line-height: 1.1;
}

.entry__content {
	margin-top: var(--space-m);
	color: var(--color-ink);
	font-family: var(--font-sans);
	font-size: 16px;
	font-weight: 300;
	line-height: 1.6;
}

.entry__content > * + * {
	margin-top: 1em;
}

.entry__content a {
	text-decoration: underline;
}


/* 10. Animations
   ========================================================================== */

/* Heading reveal (main.js § 4): until a heading scrolls in, its words are
   hidden; then each fades in from a blur, 0.03s after the one before. */
.reveal-heading:not(.is-in) .reveal-word {
	opacity: 0;
}

.reveal-heading.is-in .reveal-word {
	animation: dd-word-in 0.5s ease-out calc(var(--w) * 0.03s) both;
}

@keyframes dd-word-in {
	from {
		opacity: 0;
		filter: blur(6px);
	}
}

/* Same look as before (a 12px ring around the 8px dot = 4x its size). */
@keyframes dd-pulse {
	0% {
		opacity: 1;
		transform: scale(1);
	}

	50% {
		opacity: 0;
		transform: scale(4);
	}

	100% {
		opacity: 0;
		transform: scale(1);
	}
}

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

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