/* Cloud Nine Construction: homepage DRAFT 1 (2 Oct 2026). Static, for review before the platform build.
   Palette: graphite / silver / white from the vans and workwear (hex provisional until the van artwork
   arrives from V Signs). Type: Archivo, wide cut for display to echo the CLOUDNINE wordmark.
   Evidence for every section: ../DESIGN-RESEARCH.md. Copy + sources: companies/cloudnine/copy/home.md */
:root {
	--paper: #F5F6F6;
	--white: #FFFFFF;
	--ink: #1D1F21;
	--graphite: #2B2E31;
	--graphite-line: #42464B;
	--silver: #B9BDC1;
	--hairline: #D9DCDE;
	--muted: #5A5F64;
	--on-dark: #ECEEEF;
	--on-dark-muted: #A9AEB3;
	--wide: 125%;
	--gutter: 24px;
}
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font-family: 'Archivo', system-ui, sans-serif;
	font-size: 17px;
	line-height: 1.7;
	font-variation-settings: 'wdth' 100;
}
img { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
.wrap { max-width: 1180px; margin-inline: auto; padding-inline: var(--gutter); }
@media (max-width: 640px) { :root { --gutter: 16px; } body { font-size: 16px; } }

.skip { position: absolute; left: -999px; top: 0; background: var(--white); color: var(--ink); padding: 8px 12px; z-index: 50; }
.skip:focus { left: 8px; top: 8px; }
:focus-visible { outline: 2px solid var(--silver); outline-offset: 3px; }

/* Display type: wide + light, the CLOUDNINE wordmark's stance */
.display { font-stretch: var(--wide); font-variation-settings: 'wdth' 125; font-weight: 300; letter-spacing: -0.01em; line-height: 1.12; }
h2.display { font-size: clamp(28px, 3.4vw, 44px); margin: 0 0 24px; }
.label { font-stretch: 112%; font-variation-settings: 'wdth' 112; font-size: 13px; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; }

/* ── Header (graphite: the van) ───────────────────────── */
.top { background: var(--graphite); color: var(--on-dark); }
.top .wrap { display: flex; align-items: center; justify-content: space-between; gap: 24px; padding-block: 18px; }
.logo img { width: 250px; }
@media (max-width: 640px) { .logo img { width: 200px; } }
.nav { display: flex; align-items: center; gap: 28px; font-size: 15px; }
/* Top-level nav links only: the mega menu lives inside .nav, and these colours (made for the dark
   header) made its hovered names white-on-paper, i.e. invisible. */
.nav > a, .nav .mega-trigger { text-decoration: none; color: var(--on-dark-muted); }
.nav > a:hover, .nav .mega-trigger:hover { color: var(--on-dark); }
.nav > .tel { color: var(--on-dark); font-weight: 600; letter-spacing: 0.02em; }
.btn { display: inline-block; padding: 13px 22px; border-radius: 2px; font-weight: 600; text-decoration: none; font-size: 15px; letter-spacing: 0.01em; cursor: pointer; border: 1px solid transparent; font-family: inherit; }
/* Silver sheen: a soft, wide wash of light drifts across on hover, like light moving over the
   brushed-silver logo on the vans. Slow and low-contrast on purpose: noticed, not shouted.
   Transform/opacity only, once per hover, off for reduced motion. */
.btn { position: relative; overflow: hidden; isolation: isolate; transition: background-color 600ms ease, border-color 600ms ease; }
.btn::after { content: ""; position: absolute; top: 0; bottom: 0; left: 0; width: 70%; z-index: -1; pointer-events: none; opacity: 0;
	background: linear-gradient(105deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.55) 50%, rgba(255,255,255,0) 100%);
	transform: translateX(-110%); }
.btn:hover::after, .btn:focus-visible::after { opacity: 1; transform: translateX(160%);
	transition: transform 1100ms cubic-bezier(.22,.61,.36,1), opacity 300ms ease; }
.btn-line::after { background: linear-gradient(105deg, rgba(236,238,239,0) 0%, rgba(236,238,239,.14) 50%, rgba(236,238,239,0) 100%); }
@media (prefers-reduced-motion: reduce) { .btn::after { display: none; } }
.btn-light { background: var(--on-dark); color: var(--graphite) !important; }
/* hover = true white, NOT var(--white): the dark homepage (.v3) redefines --white as graphite, which
   turned this button dark with dark text on hover (Mark, 18 Oct) */
.btn-light:hover { background: #FFFFFF; }
.btn-line { border-color: var(--graphite-line); color: var(--on-dark) !important; }
.btn-line:hover { border-color: var(--silver); }
.menu-btn { display: none; background: none; border: 1px solid var(--graphite-line); color: var(--on-dark); padding: 10px 14px; font: inherit; font-size: 15px; border-radius: 2px; cursor: pointer; }

/* Off-canvas mobile menu: full page, flat graphite, no image (house default) */
.panel { position: fixed; inset: 0; background: var(--graphite); color: var(--on-dark); transform: translateX(100%); visibility: hidden; transition: transform 320ms ease-out, visibility 0s 320ms; z-index: 40; display: flex; flex-direction: column; padding: 18px var(--gutter) 32px; }
.panel.open { transform: none; visibility: visible; transition: transform 320ms ease-out; }
.panel-head { display: flex; justify-content: space-between; align-items: center; }
.panel nav { margin-top: 48px; display: grid; gap: 4px; }
.panel nav a { text-decoration: none; font-size: 30px; padding-block: 8px; border-bottom: 1px solid var(--graphite-line); }
.panel .panel-tel { margin-top: auto; font-size: 22px; font-weight: 600; text-decoration: none; }
@media (max-width: 900px) { .nav { display: none; } .menu-btn { display: inline-block; } }

/* ── Hero ─────────────────────────────────────────────── */
.hero { background: var(--graphite); color: var(--on-dark); }
.hero .wrap { display: grid; grid-template-columns: 7fr 5fr; gap: 56px; align-items: end; padding-block: 72px 88px; }
.hero h1 { margin: 0; }
.hero h1 .place { display: block; color: var(--on-dark-muted); margin-bottom: 20px; }
.hero h1 .big { display: block; font-size: clamp(36px, 5vw, 66px); }
.hero .lede { max-width: 34em; color: var(--on-dark-muted); margin: 28px 0 32px; font-size: 18px; }
.hero .ctas { display: flex; flex-wrap: wrap; gap: 12px; }
/* Hero photo, treated like a mounted print on a drawing sheet: architect's crop marks in silver at the
   four corners, a graphite fade at the foot (ties it into the hero and softens the site-mud foreground)
   with the caption set inside it, and a light grade towards the graphite/silver palette. */
.hero figure { margin: 0; position: relative; padding: 14px; }
.shot { position: relative; overflow: hidden; border-radius: 1px; }
.shot img { width: 100%; aspect-ratio: 4 / 5; max-height: 52vh; object-fit: cover; object-position: 50% 30%; filter: saturate(.86) contrast(1.05); }
.shot::after { content: ""; position: absolute; inset: auto 0 0 0; height: 46%; pointer-events: none;
	background: linear-gradient(to top, rgba(43,46,49,.92) 0%, rgba(43,46,49,.55) 45%, rgba(43,46,49,0) 100%); }
.shot figcaption { position: absolute; left: 22px; bottom: 18px; z-index: 1; margin: 0; font-size: 15px; color: var(--on-dark); }
.shot figcaption .label { display: block; font-size: 11px; color: var(--silver); margin-bottom: 4px; }
.marks { position: absolute; inset: 0; pointer-events: none; opacity: .8;
	--m: linear-gradient(var(--silver), var(--silver));
	background:
		var(--m) top left / 22px 1px no-repeat, var(--m) top left / 1px 22px no-repeat,
		var(--m) top right / 22px 1px no-repeat, var(--m) top right / 1px 22px no-repeat,
		var(--m) bottom left / 22px 1px no-repeat, var(--m) bottom left / 1px 22px no-repeat,
		var(--m) bottom right / 22px 1px no-repeat, var(--m) bottom right / 1px 22px no-repeat; }
@media (max-width: 900px) {
	.hero .wrap { grid-template-columns: 1fr; gap: 36px; padding-block: 40px 48px; }
	.shot img { aspect-ratio: 3 / 2; max-height: none; }
	.hero figure { padding: 10px; }
}

/* ── Credentials: four facts, divided by hairlines, not boxed ── */
.creds { background: var(--white); }
.creds ul { list-style: none; margin: 0 auto; display: grid; grid-template-columns: 1.7fr 1fr 1fr 1fr; padding-block: 28px; padding-inline: var(--gutter); }
.creds li { padding: 4px 24px; border-left: 1px solid var(--hairline); font-size: 15px; line-height: 1.5; color: var(--muted); }
.creds li:first-child { border-left: 0; padding-left: 0; }
.creds strong { display: block; color: var(--ink); font-weight: 600; margin-bottom: 4px; }
@media (max-width: 900px) {
	.creds ul { grid-template-columns: 1fr 1fr; row-gap: 20px; }
	.creds .has-mark { grid-column: 1 / -1; padding-right: 0; }
	.creds .has-mark + li { border-left: 0; padding-left: 0; }
	.creds li:nth-child(odd) { border-left: 0; padding-left: 0; }
}
@media (max-width: 480px) { .creds ul { grid-template-columns: 1fr; } .creds li { border-left: 0; padding-left: 0; } .creds .has-mark { grid-template-columns: 1fr; gap: 12px; } .creds .fmb-badge { width: 140px; } }

/* ── Why it matters: asymmetric statement + text ─────────── */
/* A full-width statement that answers itself (weight change carries the turn), then the two
   paragraphs side by side, indented under it like a magazine pull-quote. */
.why .wrap { padding-block: 112px 104px; }
.statement { margin: 0; max-width: 21ch; font-size: clamp(34px, 5.2vw, 72px); line-height: 1.08; font-weight: 300; letter-spacing: -0.015em; font-stretch: var(--wide); font-variation-settings: 'wdth' 125; color: var(--muted); }
.statement strong { font-weight: 500; color: var(--ink); }
.why-cols { margin: 56px 0 0 calc(100% / 3); display: grid; grid-template-columns: 1fr 1fr; gap: 40px; padding-top: 24px; --rule-c: var(--hairline); }
.why-cols p { margin: 0; color: var(--muted); }
.why-cols p:first-child { color: var(--ink); }
@media (max-width: 900px) {
	.why .wrap { padding-block: 64px; }
	.why-cols { margin-left: 0; grid-template-columns: 1fr; gap: 16px; margin-top: 36px; }
}

/* ── Services: a numbered schedule, rows not cards ─────── */
.services { background: var(--white); }
/* Side heading: small, in its own narrow column, staying put while the list scrolls past. */
.split .wrap { padding-block: 96px; display: grid; grid-template-columns: 1fr 3fr; gap: 48px; align-items: start; }
.side-head { margin: 0; position: sticky; top: 32px; padding-top: 22px; font-size: 20px; font-weight: 500; line-height: 1.3; font-stretch: var(--wide); font-variation-settings: 'wdth' 125; }
.svc { list-style: none; margin: 0; padding: 0; }
@media (max-width: 900px) {
	.split .wrap { grid-template-columns: 1fr; gap: 20px; padding-block: 64px; }
	.side-head { position: static; padding-top: 0; font-size: 26px; }
}
/* Each service row is ONE link (the heading's link stretches over the row). An arrow slides on hover,
   the name underlines and the rule darkens: obviously clickable, no extra words. */
.svc li { position: relative; display: grid; grid-template-columns: 1fr 1.6fr 48px; gap: 32px; align-items: baseline; padding-block: 28px; border-bottom: 1px solid var(--hairline); transition: border-color 300ms ease; }
.svc h3 { margin: 0; font-size: 22px; font-weight: 500; font-stretch: 112%; font-variation-settings: 'wdth' 112; }
.svc h3 a { text-decoration: none; text-underline-offset: 5px; text-decoration-thickness: 1px; }
.svc h3 a::after { content: ""; position: absolute; inset: 0; }
.svc p { margin: 0; color: var(--muted); }
.svc .go { justify-self: end; font-size: 22px; line-height: 1; color: var(--ink); transition: transform 400ms cubic-bezier(.22,.61,.36,1); }
.svc li:hover { border-bottom-color: var(--ink); }
.svc li:hover h3 a, .svc h3 a:focus-visible { text-decoration: underline; }
.svc li:hover .go { transform: translateX(8px); }
@media (max-width: 760px) { .svc li { grid-template-columns: 1fr 32px; gap: 8px 16px; } .svc p { grid-column: 1; } .svc .go { grid-row: 1; grid-column: 2; } }

/* ── How your project runs: drawn as a build programme ──── */
.prog .wrap { padding-block: 104px; }
.prog .intro { max-width: 40em; color: var(--muted); margin: 0 0 48px; }
.chart { position: relative; }
.row { display: grid; grid-template-columns: minmax(180px, 2.2fr) 5fr; gap: 32px; padding-block: 26px; border-bottom: 1px solid var(--hairline); }
.row h3 { margin: 0 0 6px; font-size: 19px; font-weight: 600; }
.row p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.6; max-width: 32em; }
.track {
	position: relative; height: 12px; margin-top: 10px;
	/* the programme's week grid: faint verticals */
	background: repeating-linear-gradient(to right, var(--hairline) 0 1px, transparent 1px calc(100% / 12));
}
.bar { position: absolute; top: 0; bottom: 0; left: var(--s); width: calc(var(--e) - var(--s)); background: var(--graphite); border-radius: 1px; transform-origin: left center; }
/* "Today" line: a thin silver marker that travels across the programme as you scroll (site.js);
   bars fill up to it. Hidden until the motion script positions it; never shown on phones. */
.today { position: absolute; top: 0; bottom: 0; width: 1px; background: var(--silver); left: 0; opacity: 0; pointer-events: none; }
.today::before { content: "Today"; position: absolute; top: -26px; left: 0; transform: translateX(-50%); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); }
@media (max-width: 760px) { .today { display: none; } }
@media (max-width: 760px) { .row { grid-template-columns: 1fr; gap: 14px; } .track { margin-top: 0; } }

/* ── Recent work: one large, two stacked ─────────────────── */
.work { background: var(--white); }
.work .wrap { padding-block: 96px; }
.work-head { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; }
.stack .work-head { margin-bottom: 4px; }
.stack .work-head h2 { margin: 0; }
.work-head a { color: var(--muted); font-size: 15px; }
.grid { display: grid; grid-template-columns: 7fr 5fr; gap: 20px; margin-top: 36px; }
.grid figure { margin: 0; }
.grid img { width: 100%; object-fit: cover; border-radius: 2px; }
.grid .big img { aspect-ratio: 4 / 3; height: 100%; }
.grid .stack { display: grid; gap: 20px; }
.grid .stack img { aspect-ratio: 16 / 10; }
.grid figcaption { margin-top: 10px; font-size: 14px; color: var(--muted); }
.grid figcaption b { color: var(--ink); font-weight: 600; }
@media (max-width: 760px) { .grid { grid-template-columns: 1fr; } }

/* ── Client words ─────────────────────────────────────── */
.words .wrap { padding-block: 104px; display: grid; grid-template-columns: 2fr 9fr; gap: 32px; }
.words blockquote { margin: 0; }
.words blockquote p { margin: 0; font-size: clamp(22px, 2.6vw, 32px); line-height: 1.4; font-weight: 300; font-stretch: 112%; font-variation-settings: 'wdth' 112; max-width: 30em; }
.words cite { display: block; margin-top: 20px; font-style: normal; color: var(--muted); font-size: 15px; }
@media (max-width: 760px) { .words .wrap { grid-template-columns: 1fr; padding-block: 64px; gap: 12px; } }

/* ── Enquiry (graphite again: bookends the page like the van) ── */
/* overflow-x clip: the next question slides in from the right (.in-right) and must not widen the page */
.enquire { background: var(--graphite); color: var(--on-dark); overflow-x: clip; }
.enquire .wrap { display: grid; grid-template-columns: 5fr 7fr; gap: 64px; padding-block: 96px; }
.enquire h2 { color: var(--on-dark); }
.enquire .side p { color: var(--on-dark-muted); max-width: 26em; }
.enquire .direct { margin-top: 32px; display: grid; gap: 6px; }
.enquire .direct a { text-decoration: none; font-size: 20px; color: var(--on-dark); }
form { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 20px; }
.f { display: grid; gap: 6px; }
.f.full { grid-column: 1 / -1; }
.f label, fieldset legend { font-size: 14px; color: var(--on-dark-muted); }
input, select, textarea { font: inherit; font-size: 16px; color: var(--on-dark); background: transparent; border: 0; border-bottom: 1px solid var(--graphite-line); border-radius: 0; padding: 10px 0; width: 100%; }
select { appearance: none; background-image: linear-gradient(45deg, transparent 50%, var(--on-dark-muted) 50%), linear-gradient(135deg, var(--on-dark-muted) 50%, transparent 50%); background-position: calc(100% - 12px) 55%, calc(100% - 7px) 55%; background-size: 5px 5px; background-repeat: no-repeat; }
select option { color: var(--ink); }
input:focus, select:focus, textarea:focus { outline: none; border-bottom-color: var(--on-dark); }
/* min-width: 0, because a fieldset defaults to min-content width and would push a tile grid off the page */
fieldset { border: 0; margin: 0; padding: 0; grid-column: 1 / -1; min-width: 0; }
.choices { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.choices label { display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--graphite-line); border-radius: 2px; padding: 9px 14px; font-size: 15px; color: var(--on-dark); cursor: pointer; }
.choices label:has(input:checked) { border-color: var(--on-dark); background: var(--graphite-line); }
.choices input { width: auto; accent-color: var(--on-dark); margin: 0; }
form .btn { justify-self: start; }
.note { grid-column: 1 / -1; font-size: 13px; color: var(--on-dark-muted); margin: 0; }
@media (max-width: 900px) { .enquire .wrap { grid-template-columns: 1fr; gap: 36px; padding-block: 64px; } }
@media (max-width: 560px) { form { grid-template-columns: 1fr; } }

/* ── Footer ─────────────────────────────────────────── */
.foot { background: var(--ink); color: var(--on-dark-muted); font-size: 14px; line-height: 1.7; }
.foot .wrap { display: grid; grid-template-columns: 1.6fr 1.2fr 1.2fr 0.8fr; gap: 32px; padding-block: 56px 32px; }
.foot strong { color: var(--on-dark); font-weight: 600; display: block; margin-bottom: 6px; }
.foot a { text-decoration: none; }
.foot .fmb { margin: 20px 0 0; color: var(--on-dark); }
.foot .fmb a { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--graphite-line); }
.foot a:hover { color: var(--on-dark); }
.foot .base { grid-column: 1 / -1; border-top: 1px solid var(--graphite-line); padding-top: 20px; display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; font-size: 13px; }
@media (max-width: 1000px) { .foot .wrap { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .foot .wrap { grid-template-columns: 1fr; } }

/* ═══ Added for the full draft (shared components across all pages) ═══════════════════ */

/* Drawn hairline: the top rule of a list/block, drawn in on scroll (site.js animates --rx). */
.ruled { position: relative; }
.ruled::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; background: var(--rule-c, var(--ink)); transform: scaleX(var(--rx, 1)); transform-origin: left center; }

/* Drawing-sheet grid on the grey sections: architect's squared paper, a heavier line every fifth
   square, fading out across the section so it reads as texture, never pattern. Static. */
.grid-paper { position: relative; isolation: isolate; }
.grid-paper::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
	background-image:
		linear-gradient(to right, rgba(43,46,49,.07) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(43,46,49,.07) 1px, transparent 1px),
		linear-gradient(to right, rgba(43,46,49,.035) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(43,46,49,.035) 1px, transparent 1px);
	background-size: 120px 120px, 120px 120px, 24px 24px, 24px 24px;
	-webkit-mask-image: linear-gradient(115deg, #000 0%, rgba(0,0,0,.55) 45%, transparent 85%);
	mask-image: linear-gradient(115deg, #000 0%, rgba(0,0,0,.55) 45%, transparent 85%); }
.why, .prog, .words { background: var(--paper); }

/* Calvin's photo beside the trust statement (v1 + v7, Mark 16 Oct). Only rendered once the photo exists;
   then the section becomes text | portrait. Crop marks as on the hero shot. */
.has-founder .wrap { display: grid; grid-template-columns: minmax(0, 1fr) minmax(240px, 30%); gap: 64px; align-items: end; }
.has-founder .why-cols { margin-left: 0; }
.has-founder .v3-two { margin-left: 0; }
.founder { position: relative; margin: 0; padding: 12px; }
.founder-shot { aspect-ratio: 4 / 5; overflow: hidden; }
.founder-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.founder .marks { position: absolute; inset: 0; pointer-events: none;
	background:
		linear-gradient(currentColor, currentColor) 0 0 / 18px 1px no-repeat, linear-gradient(currentColor, currentColor) 0 0 / 1px 18px no-repeat,
		linear-gradient(currentColor, currentColor) 100% 0 / 18px 1px no-repeat, linear-gradient(currentColor, currentColor) 100% 0 / 1px 18px no-repeat,
		linear-gradient(currentColor, currentColor) 0 100% / 18px 1px no-repeat, linear-gradient(currentColor, currentColor) 0 100% / 1px 18px no-repeat,
		linear-gradient(currentColor, currentColor) 100% 100% / 18px 1px no-repeat, linear-gradient(currentColor, currentColor) 100% 100% / 1px 18px no-repeat;
	color: var(--muted); opacity: .7; }
@media (max-width: 900px) { .has-founder .wrap { grid-template-columns: 1fr; gap: 40px; } .founder { max-width: 420px; } }
/* v7 (Mark, 16 Oct): the drawing-sheet grid on the dark panels too, in light lines. Same sizes, same
   diagonal fade and cursor spotlight as the light pages; only the ink changes. */
.grid-dark .grid-paper::before {
	background-image:
		linear-gradient(to right, rgba(236,238,239,.09) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(236,238,239,.09) 1px, transparent 1px),
		linear-gradient(to right, rgba(236,238,239,.045) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(236,238,239,.045) 1px, transparent 1px); }
.grid-dark .grid-paper::after {
	background-image:
		linear-gradient(to right, rgba(236,238,239,.2) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(236,238,239,.2) 1px, transparent 1px),
		linear-gradient(to right, rgba(236,238,239,.09) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(236,238,239,.09) 1px, transparent 1px); }

/* Split sections (side heading + content), tones */
.tone-white { background: var(--white); }
.tone-paper { background: var(--paper); }
.split .wrap.wide { display: block; }

/* Inner-page head: same graphite band as the home hero, smaller */
.page-head .wrap { padding-block: 48px 72px; align-items: center; }
.page-head.no-photo .wrap { grid-template-columns: 1fr; }
.page-head .big { font-size: clamp(32px, 4.2vw, 56px); max-width: 18ch; }
/* rhythm (Mark, 18 Oct: "too many lines all with the same spacing"): three groups, not five equal steps.
   breadcrumbs (quiet, set apart) | eyebrow + headline + intro (one block) | buttons (their own gap).
   The eyebrow is left out when the headline already names the place (build.mjs pageHead). */
.page-head .crumbs { margin-bottom: 56px; }
.page-head h1 .place { margin-bottom: 12px; }
.page-head .lede { margin: 16px 0 40px; }
.crumbs { font-size: 13px; color: var(--on-dark-muted); margin-bottom: 36px; }
.crumbs a { color: var(--on-dark-muted); text-decoration: none; }
.crumbs a:hover { color: var(--on-dark); }
.crumbs .sep { margin: 0 10px; opacity: .5; }
.crumbs [aria-current] { color: var(--on-dark); }
.nav > a[aria-current="page"], .nav .mega-trigger[aria-current="page"] { color: var(--on-dark); }

/* "What's included" / "How we work": hairline list, heading + line, no numbers */
.incl { list-style: none; margin: 0; padding: 0; }
.incl li { display: grid; grid-template-columns: 1fr 1.6fr; gap: 32px; padding-block: 24px; border-bottom: 1px solid var(--hairline); }
.incl h3 { margin: 0; font-size: 19px; font-weight: 500; }
.incl p { margin: 0; color: var(--muted); }
@media (max-width: 760px) { .incl li { grid-template-columns: 1fr; gap: 6px; } }

/* Project tiles (projects page, service pages): uniform, fixed ratio, fact caption */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 28px 20px; }
.tile { margin: 0; }
.tile img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 2px; }
.tile figcaption { margin-top: 10px; font-size: 14px; color: var(--muted); display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.svc-tag { text-align: right; }
.tile figcaption b { color: var(--ink); font-weight: 600; }
.svc-tag { color: var(--muted); font-size: 13px; white-space: nowrap; }
.reveal { overflow: hidden; border-radius: 2px; }

/* Contact page: address under the direct lines */
.enquire .addr { margin-top: 28px; color: var(--on-dark-muted); font-size: 15px; }

/* FMB marks: official red badge in the credentials strip, white mono logo in the footer.
   STAND-INS from fmb.org.uk for the draft; replace with the member files from their FMB account. */
/* Badge sits BESIDE its text, so all four credential headings stay on one line. */
.creds .has-mark { display: grid; grid-template-columns: auto 1fr; gap: 24px; align-items: start; padding-right: 32px; }
.creds .fmb-badge { display: block; width: 150px; height: auto; margin-top: 4px; } /* top edge level with the heading */
.foot .fmb-logo { display: block; width: 168px; height: auto; margin-top: 22px; opacity: .9; }

/* Grid spotlight: under a mouse, the drawing-sheet grid comes up crisper around the cursor, like a
   torch over a drawing. A second copy of the grid, darker, masked to a soft circle at --mx/--my
   (set by site.js). Hover devices only; invisible (--spot: 0) until the pointer is in the section. */
.grid-paper::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
	background-image:
		linear-gradient(to right, rgba(43,46,49,.26) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(43,46,49,.26) 1px, transparent 1px),
		linear-gradient(to right, rgba(43,46,49,.13) 1px, transparent 1px),
		linear-gradient(to bottom, rgba(43,46,49,.13) 1px, transparent 1px);
	background-size: 120px 120px, 120px 120px, 24px 24px, 24px 24px;
	-webkit-mask-image: radial-gradient(circle 260px at var(--mx, 50%) var(--my, 50%), #000 0%, rgba(0,0,0,.45) 45%, transparent 100%);
	mask-image: radial-gradient(circle 260px at var(--mx, 50%) var(--my, 50%), #000 0%, rgba(0,0,0,.45) 45%, transparent 100%);
	opacity: var(--spot, 0); transition: opacity 600ms ease; }

/* ═══ Services mega menu ═══════════════════════════════════════════════════════════════
   Unrolls down from the header (same graphite, so it reads as one surface). Left: the four services
   in the wide display type; hovering one brightens it and dims the rest. Right: a framed photo (hero
   crop marks) of that service's real job, swapping as you move. Opens on :hover/:focus-within (works
   with JS off); site.js adds .open with a close delay so moving the mouse down doesn't snap it shut. */
.top { position: relative; z-index: 30; }
.has-mega { position: static; }
.mega-trigger { position: relative; padding-block: 30px; margin-block: -30px; padding-right: 16px; } /* hover bridge to the panel */
/* Always-visible down caret, so it reads as a menu BEFORE anyone hovers (Mark, 3 Oct: the hidden
   caret gave no clue). Flips to point up while the panel is open. */
.mega-trigger::after { content: ""; position: absolute; right: 1px; top: 50%; width: 5px; height: 5px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-75%) rotate(45deg); opacity: .8; transition: transform 300ms ease, opacity 300ms ease; }
/* Light panel over the dark page (Mark: graphite on graphite blurred together), with the page behind
   dimmed so the panel clearly sits on top. */
.mega { position: absolute; left: 0; right: 0; top: 100%; background: var(--paper); color: var(--ink);
	border-bottom: 1px solid var(--hairline);
	visibility: hidden; clip-path: inset(0 0 100% 0);
	transition: clip-path 480ms cubic-bezier(.22,.61,.36,1), visibility 0s 480ms; }
.has-mega:hover .mega, .has-mega:focus-within .mega, .has-mega.open .mega { visibility: visible; clip-path: inset(0 0 0 0); transition: clip-path 520ms cubic-bezier(.22,.61,.36,1); }
.has-mega:hover .mega-trigger, .has-mega.open .mega-trigger { color: var(--on-dark); }
.has-mega:hover .mega-trigger::after, .has-mega.open .mega-trigger::after { opacity: 1; transform: translateY(-25%) rotate(225deg); }
/* .top .wrap (the header row) is display:flex; the panel's inner wrap must override it explicitly. */
.top .mega .mega-inner { display: grid; grid-template-columns: 7fr 5fr; gap: 64px; align-items: start; padding-block: 40px 44px; }
/* Page dim behind the panel. On .has-mega (static, so it anchors to .top), NOT inside .mega, whose
   clip-path would clip it away. Comes before .mega in paint order, so the panel sits above it. */
.has-mega::before { content: ""; position: absolute; top: 100%; left: 0; right: 0; height: 100vh; background: rgba(29,31,33,.45); pointer-events: none; opacity: 0; visibility: hidden; transition: opacity 400ms ease, visibility 0s 400ms; }
.has-mega:hover::before, .has-mega:focus-within::before, .has-mega.open::before { opacity: 1; visibility: visible; transition: opacity 400ms ease; }
.has-mega.shut::before { opacity: 0; visibility: hidden; }

.mega-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--ink); }
.mega-list li { border-bottom: 1px solid var(--hairline); opacity: 0; transform: translateY(10px); transition: opacity 400ms ease, transform 500ms cubic-bezier(.22,.61,.36,1); }
.has-mega:hover .mega-list li, .has-mega:focus-within .mega-list li, .has-mega.open .mega-list li { opacity: 1; transform: none; transition-delay: calc(var(--i) * 60ms + 140ms); }
.mega-list a { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: baseline; padding-block: 20px; text-decoration: none; color: var(--ink); transition: opacity 300ms ease; }
.mega-name { font-size: clamp(22px, 2.1vw, 30px); font-weight: 300; line-height: 1.15; font-stretch: var(--wide); font-variation-settings: 'wdth' 125; letter-spacing: -0.01em; }
.mega-go { display: inline-block; margin-left: 14px; font-size: .7em; opacity: 0; transform: translateX(-8px); transition: opacity 300ms ease, transform 400ms cubic-bezier(.22,.61,.36,1); }
.mega-sum { font-size: 14px; color: var(--muted); line-height: 1.5; }
.mega-list:hover a { opacity: .4; }
.mega-list li.mega-all-row { border-bottom: 0; }
.mega-list .mega-all { display: inline-block; padding-top: 18px; font-size: 15px; color: var(--ink); text-underline-offset: 4px; }
.mega-list .mega-all:hover { opacity: 1; }
.mega-list a:hover, .mega-list a:focus-visible { opacity: 1; }
.mega-list a:hover .mega-go, .mega-list a:focus-visible .mega-go { opacity: 1; transform: none; }

.mega-frame { position: relative; padding: 12px; }
.mega-frame .marks { --m: linear-gradient(var(--muted), var(--muted)); opacity: .55; }
.mega-shots { position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: 1px; }
.mega-shot { position: absolute; inset: 0; margin: 0; opacity: 0; transition: opacity 450ms ease; }
.mega-shot.on { opacity: 1; }
.mega-shot img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.86) contrast(1.05); transform: scale(1.04); transition: transform 1200ms cubic-bezier(.22,.61,.36,1); }
.mega-shot.on img { transform: none; }
.mega-shot::after { content: ""; position: absolute; inset: auto 0 0 0; height: 45%; background: linear-gradient(to top, rgba(43,46,49,.9), rgba(43,46,49,0)); }
.mega-shot .cap { position: absolute; left: 18px; bottom: 14px; z-index: 1; font-size: 14px; color: var(--on-dark); }
.mega-shot .cap .label { display: block; font-size: 10px; color: var(--silver); margin-bottom: 3px; }

@media (max-width: 900px) { .mega { display: none; } }
@media (prefers-reduced-motion: reduce) { .mega, .mega-list li, .mega-shot, .mega-shot img, .mega-go { transition: none !important; } }

/* Mobile panel: the services listed under "Services" */
.panel nav .panel-sub { display: grid; padding: 4px 0 12px 16px; border-bottom: 1px solid var(--graphite-line); }
.panel nav .panel-sub a { font-size: 17px; padding-block: 7px; border-bottom: 0; color: var(--on-dark-muted); }
.has-mega.shut .mega { visibility: hidden; clip-path: inset(0 0 100% 0); } /* Esc closes even with focus inside */

/* Choice groups now carry all four questions (no native <select>s): keep them full width. */
.enquire fieldset + fieldset { margin-top: 4px; }

/* Drawings upload: appears only when planning is approved/applied for (pure CSS, works with JS off). */
.drawings { display: none; }
form:has(input[name="planning"][value="Approved"]:checked) .drawings,
form:has(input[name="planning"][value="Applied for"]:checked) .drawings { display: grid; animation: drop-in 420ms cubic-bezier(.22,.61,.36,1) backwards; }
@keyframes drop-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .drawings { animation: none !important; } }
.drop-legend { font-size: 14px; color: var(--on-dark-muted); }
.drop { position: relative; display: flex; align-items: center; gap: 16px; padding: 22px; border: 1px dashed var(--graphite-line); border-radius: 2px; color: var(--on-dark-muted); cursor: pointer; transition: border-color 250ms ease, background-color 250ms ease; }
.drop:hover, .drop.drag, .drop:focus-within { border-color: var(--silver); color: var(--on-dark); background: rgba(236,238,239,.03); }
.drop.drag { border-style: solid; }
.drop-input { position: absolute; width: 1px; height: 1px; opacity: 0; } /* still focusable + submittable */
.drop-text { display: grid; gap: 4px; }
.drop-text b { font-weight: 600; color: var(--on-dark); }
.drop-text small { font-size: 13px; }
.drop-touch { display: none; }
@media (hover: none) { .drop-mouse { display: none; } .drop-touch { display: inline; } }
.drop-list { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 8px; }
.drop-list li { display: grid; grid-template-columns: 48px 1fr auto; gap: 14px; align-items: center; padding: 8px; border: 1px solid var(--graphite-line); border-radius: 2px; font-size: 14px; }
.drop-list img, .drop-list .doc { width: 48px; height: 48px; object-fit: cover; border-radius: 1px; background: var(--graphite-line); display: grid; place-items: center; font-size: 11px; letter-spacing: .06em; color: var(--on-dark-muted); }
.drop-list .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--on-dark); }
.drop-list .size { display: block; color: var(--on-dark-muted); font-size: 12px; }
.drop-list button { background: none; border: 1px solid var(--graphite-line); color: var(--on-dark-muted); font: inherit; font-size: 13px; padding: 6px 10px; border-radius: 2px; cursor: pointer; }
.drop-list button:hover { color: var(--on-dark); border-color: var(--silver); }

/* "All services" in the mega menu: a real link with the same sliding arrow, never dimmed away. */
.mega-list .mega-all { display: inline-flex; align-items: baseline; gap: 10px; padding-top: 20px; font-size: 16px; font-weight: 600; color: var(--ink); text-decoration: none; }
.mega-list:hover .mega-all { opacity: .6; }
/* underline the words only, never the arrow (Mark, 18 Oct) */
.mega-list .mega-all:hover, .mega-list .mega-all:focus-visible { opacity: 1; }
.mega-list .mega-all:hover .mega-all-t, .mega-list .mega-all:focus-visible .mega-all-t { text-decoration: underline; text-underline-offset: 5px; }
.mega-list .mega-all .mega-go { margin-left: 0; font-size: 1em; }
.mega-list .mega-all:hover .mega-go, .mega-list .mega-all:focus-visible .mega-go { opacity: 1; transform: none; }

/* The mosaic: all four services' jobs, tiles settling in one after another. */
.mega-mosaic { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; gap: 6px; background: var(--paper); }
.mega-mosaic::after { display: none; }
.mega-mosaic .tile-m { position: relative; overflow: hidden; opacity: 0; transform: scale(.94); transition: opacity 380ms ease, transform 520ms cubic-bezier(.22,.61,.36,1); }
.mega-mosaic.on .tile-m { opacity: 1; transform: none; transition-delay: calc(var(--j) * 70ms); }
.mega-mosaic img { width: 100%; height: 100%; object-fit: cover; filter: saturate(.86) contrast(1.05); transform: none; }
.mega-mosaic .tile-l { position: absolute; left: 10px; bottom: 8px; font-size: 12px; color: var(--on-dark); text-shadow: 0 1px 2px rgba(0,0,0,.5); }
.mega-mosaic .tile-m::after { content: ""; position: absolute; inset: auto 0 0 0; height: 50%; background: linear-gradient(to top, rgba(43,46,49,.75), rgba(43,46,49,0)); }
.mega-mosaic .tile-l { z-index: 1; }
@media (prefers-reduced-motion: reduce) { .mega-mosaic .tile-m { transition: none; } }

/* ═══ Conversational enquiry form ═══════════════════════════════════════════════════════
   With JS (.stepped): one question at a time. Tapping an answer slides it out to the left and the
   next question in from the right. Answers collect as tags you can tap to go back. Without JS, every
   question shows at once (the plain form above), and it still submits. */
.convo .step { grid-column: 1 / -1; }
.convo-head, .step-back, .step-q { display: none; }
.step-actions { display: none; }
.convo.stepped .step:not(.current) { display: none !important; }
.convo.stepped .step.current { display: block; }
.convo.stepped .drawings.current { display: grid; }
.convo.stepped .step-details.current { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 20px; }
.step-details .f.full, .step-details .btn, .step-details .step-q { grid-column: 1 / -1; }
.step-details .btn { justify-self: start; }
.convo.stepped .convo-head { display: block; grid-column: 1 / -1; }
.convo.stepped .step-q { display: block; margin: 0; font-size: 20px; color: var(--on-dark); }
.convo.stepped .step-actions { display: flex; align-items: center; gap: 18px; margin-top: 6px; }
.convo.stepped legend { font-size: 20px; color: var(--on-dark); margin-bottom: 6px; }
.convo-trail { display: flex; flex-wrap: wrap; gap: 8px; min-height: 0; }
.convo-trail button { font: inherit; font-size: 13px; color: var(--on-dark); background: transparent; border: 1px solid var(--graphite-line); border-radius: 2px; padding: 6px 10px; cursor: pointer; }
.convo-trail button:hover { border-color: var(--silver); }
.convo-trail button span { color: var(--on-dark-muted); margin-right: 6px; }
.convo-bar { height: 1px; background: var(--graphite-line); margin-top: 14px; }
.convo-bar span { display: block; height: 1px; width: 0; background: var(--on-dark); transition: width 500ms cubic-bezier(.22,.61,.36,1); }
.step-skip, .step-back { font: inherit; font-size: 14px; color: var(--on-dark-muted); background: none; border: 0; padding: 6px 0; cursor: pointer; text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--graphite-line); }
.step-skip:hover, .step-back:hover { color: var(--on-dark); }
.convo.stepped .step-back:not([hidden]) { display: inline-block; grid-column: 1 / -1; justify-self: start; }
/* Slide: out to the left as you answer, in from the right; reversed when going back. */
.convo .step.in-right { animation: step-in-right 460ms cubic-bezier(.22,.61,.36,1) both; }
.convo .step.in-left { animation: step-in-left 460ms cubic-bezier(.22,.61,.36,1) both; }
@keyframes step-in-right { from { opacity: 0; transform: translateX(40px); } }
@keyframes step-in-left { from { opacity: 0; transform: translateX(-40px); } }
@media (prefers-reduced-motion: reduce) { .convo .step.in-right, .convo .step.in-left { animation: none; } .convo-bar span { transition: none; } }
@media (max-width: 560px) { .convo.stepped .step-details.current { grid-template-columns: 1fr; } }

/* "Not yet" planning path: architect introduction + an opt-in check-in (unticked by default). */
.nurture { display: none; }
form:has(input[name="planning"][value="Not yet"]:checked) .nurture { display: grid; gap: 14px; }
.convo.stepped .nurture.current { display: grid; gap: 14px; }
.nurture fieldset { border: 0; margin: 0; padding: 0; }
.optin { display: flex; gap: 10px; align-items: flex-start; font-size: 15px; color: var(--on-dark-muted); cursor: pointer; }
.optin input { width: auto; margin-top: 4px; accent-color: var(--on-dark); }

/* Menu photos are links too (to that service; mosaic tiles to theirs). Only the visible one can be
   clicked: the stacked, faded-out photos underneath must not catch the click. Keyboard users get the
   same links in the list, so the photo links are skipped in tab order (tabindex -1, aria-hidden). */
.mega-shot { display: block; text-decoration: none; color: inherit; pointer-events: none; }
.mega-shot.on { pointer-events: auto; }
.mega-shot img, .mega-mosaic img { transition: filter 400ms ease, transform 1200ms cubic-bezier(.22,.61,.36,1); }
.mega-shot.on:hover img { filter: saturate(1) contrast(1.05); }
.mega-mosaic .tile-m { display: block; text-decoration: none; }
.mega-mosaic .tile-m:hover img { filter: saturate(1) contrast(1.05); }
.mega-mosaic .tile-m:hover .tile-l { text-decoration: underline; text-underline-offset: 3px; }
.mega-shot.mega-mosaic { display: grid; } /* beats the generic .mega-shot { display: block } above */

/* Form progress: "Step 2 of 6" above the progress line; answered tags sit under it. */
.convo-count { margin: 0 0 10px; font-size: 13px; letter-spacing: .04em; color: var(--on-dark-muted); }
.convo.stepped .convo-trail:not(:empty) { margin-top: 16px; }
.convo .convo-bar { margin-top: 0; }

/* Footer additions: socials, partners, cookie settings */
.foot-social { margin: 14px 0 0; }
.partners ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.partners li a { color: var(--on-dark); }
.partners li span { display: block; font-size: 12px; color: var(--on-dark-muted); }
.cookie-settings-link { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
.cookie-settings-link:hover { color: var(--on-dark); }
.cookie-settings-link.inline { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.fmb-badge-link { display: block; }

/* Sponsorships: prominent band of their own (graphite, like the van), statement + two cards */
.sponsor { background: var(--graphite); color: var(--on-dark); }
.sponsor .wrap { padding-block: 104px; }
.sponsor .statement { color: var(--on-dark-muted); max-width: 18ch; }
.sponsor .statement strong { color: var(--on-dark); }
.sponsor-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0; margin: 56px 0 0 calc(100% / 3); border-top: 1px solid var(--graphite-line); }
.sponsor-card { padding: 26px 32px 6px 0; }
.sponsor-card + .sponsor-card { padding-left: 32px; border-left: 1px solid var(--graphite-line); }
.sponsor-card h3 { margin: 0 0 8px; font-size: 20px; font-weight: 500; font-stretch: 112%; font-variation-settings: 'wdth' 112; }
.sponsor-card p { margin: 0; color: var(--on-dark-muted); }
@media (max-width: 760px) { .sponsor .wrap { padding-block: 64px; } .sponsor-grid { margin-left: 0; grid-template-columns: 1fr; } .sponsor-card + .sponsor-card { padding-left: 0; border-left: 0; border-top: 1px solid var(--graphite-line); } }
/* .statement's per-letter colour fill is tuned for the light sections; on graphite keep it static */
.sponsor .statement { --fill-off: 1; }

/* People: framed portraits (hero crop marks); initial in the display type until photos arrive */
.people { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 40px; }
.person { margin: 0; }
.person-photo { position: relative; aspect-ratio: 4 / 5; padding: 12px; }
.person-initial { display: grid; place-items: center; width: 100%; height: 100%; background: var(--graphite); color: var(--silver); font-size: 96px; font-weight: 300; font-stretch: var(--wide); font-variation-settings: 'wdth' 125; border-radius: 1px; }
.person-photo .marks { --m: linear-gradient(var(--muted), var(--muted)); opacity: .5; }
.person figcaption { margin-top: 14px; }
.person b { font-size: 20px; font-weight: 500; }
.person-role { display: block; color: var(--muted); font-size: 14px; margin-top: 2px; }
.person p { margin: 10px 0 0; color: var(--muted); font-size: 15px; }

/* Accreditations: a grid of marks, hairline-divided (no boxes) */
.acc-grid { display: grid; grid-template-columns: 1fr 1fr; border-top: 1px solid var(--ink); }
.acc-card { padding: 36px 40px 40px 0; border-bottom: 1px solid var(--hairline); }
.acc-card:nth-child(even) { padding-left: 40px; border-left: 1px solid var(--hairline); }
.acc-mark { height: 56px; display: flex; align-items: center; margin-bottom: 22px; }
.acc-mark img { height: 48px; width: auto; }
.acc-word { font-size: 30px; font-weight: 300; font-stretch: var(--wide); font-variation-settings: 'wdth' 125; letter-spacing: -0.01em; }
.acc-card h3 { margin: 0 0 8px; font-size: 20px; font-weight: 500; }
.acc-card p { margin: 0 0 14px; color: var(--muted); max-width: 34em; }
.acc-card a { font-size: 15px; color: var(--ink); text-underline-offset: 4px; }
@media (max-width: 760px) { .acc-grid { grid-template-columns: 1fr; } .acc-card, .acc-card:nth-child(even) { padding-left: 0; border-left: 0; } }

/* Policy pages: readable prose */
.legal .wrap { padding-block: 72px 96px; }
.legal-body { max-width: 44em; }
.legal-body h2 { font-size: 22px; font-weight: 500; margin: 40px 0 10px; }
.legal-body h2:first-child { margin-top: 0; }
.legal-body p, .legal-body li { color: #3a3e42; }
.legal-body ul { padding-left: 20px; }
.legal-body li { margin-bottom: 8px; }
.legal-body a { color: var(--ink); text-underline-offset: 3px; }
.legal-body code { font-size: 14px; background: var(--paper); padding: 1px 5px; border-radius: 2px; }
.table-wrap { overflow-x: auto; }
.legal-body table { width: 100%; border-collapse: collapse; font-size: 15px; }
.legal-body th, .legal-body td { text-align: left; padding: 10px 12px 10px 0; border-bottom: 1px solid var(--hairline); vertical-align: top; }
.legal-body th { font-weight: 600; border-bottom-color: var(--ink); }

/* Cookie consent: a quiet bar at the foot of the screen, graphite like the header. Reject is as easy
   as Accept (ICO). Hidden until site.js decides it's needed. */
.consent { position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 60; background: var(--graphite); color: var(--on-dark); border: 1px solid var(--graphite-line); border-radius: 2px; max-width: 760px; margin-inline: auto; }
.consent[hidden] { display: none; }
.consent-inner { padding: 20px 22px; display: grid; gap: 14px; }
.consent-text { margin: 0; font-size: 15px; line-height: 1.6; color: var(--on-dark); }
.consent-text a { color: var(--on-dark); text-underline-offset: 3px; }
.consent-more { display: grid; gap: 10px; }
.consent-more[hidden] { display: none; }
.consent-row { display: flex; gap: 12px; align-items: flex-start; font-size: 14px; color: var(--on-dark-muted); }
.consent-row b { color: var(--on-dark); margin-right: 6px; }
.consent-row input { width: auto; margin-top: 4px; accent-color: var(--on-dark); }
.consent-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.consent-toggle { font: inherit; font-size: 14px; background: none; border: 0; color: var(--on-dark-muted); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; padding: 6px 4px; }
.consent-toggle:hover { color: var(--on-dark); }

/* Buttons: a <button> must not keep the browser's default grey (it made .btn-line text invisible),
   and the [hidden] attribute must win over .btn's display. */
button.btn { background: transparent; }
button.btn.btn-light { background: var(--on-dark); }
.btn[hidden] { display: none; }
.consent .btn { padding: 11px 20px; }

/* Light sponsorship band (Partners page, where the dark band would run into the dark enquiry form) */
.sponsor.light { background: var(--paper); color: var(--ink); }
.sponsor.light .statement { color: var(--muted); }
.sponsor.light .statement strong { color: var(--ink); }
.sponsor.light .sponsor-grid { border-top-color: var(--ink); }
.sponsor.light .sponsor-card + .sponsor-card { border-left: 1px solid var(--hairline); }
.sponsor.light .sponsor-card p { color: var(--muted); }
/* Accreditation cards without a logo start with their heading */
.acc-card h3:first-child { margin-top: 4px; }

/* Phones: FMB badge ABOVE its text (Mark). Must come after the base .has-mark rule, which it
   overrides; the earlier 480px version sat above that rule and never applied. */
@media (max-width: 640px) {
	.creds .has-mark { grid-template-columns: 1fr; gap: 12px; padding-right: 0; }
	.creds .fmb-badge { width: 150px; margin-top: 0; }
}

/* Partners page: teams we back, each with a framed pitch plan (stand-in for the team's photo/crest) */
.teams { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; }
.team { margin: 0; }
.team-frame { position: relative; padding: 12px; }
.team-frame .pitch { display: block; width: 100%; height: auto; aspect-ratio: 400 / 260; background: var(--graphite); color: var(--silver); padding: 18px; box-sizing: border-box; border-radius: 1px; }
.team-frame .marks { --m: linear-gradient(var(--muted), var(--muted)); opacity: .55; }
.team h3 { margin: 16px 0 6px; font-size: 20px; font-weight: 500; font-stretch: 112%; font-variation-settings: 'wdth' 112; }
.team p { margin: 0; color: var(--muted); }
@media (max-width: 760px) { .teams { grid-template-columns: 1fr; } }

/* Page heads with no intro line (the policy pages): the buttons get the same gap the intro line's
   margins give on every other page, instead of sitting against the heading. */
.hero h1 + .ctas { margin-top: 40px; }

/* ═══ Homepage banner, concept B (/v2/, 3 Oct) ═════════════════════════════════════════════
   A finished job fills the screen under a charcoal overlay; the header floats over it. The photo is
   pulled back towards the graphite palette (less saturation, a touch darker) so a phone shot of
   orange brick in low sun reads as considered rather than a snapshot, and the darkest part of the
   overlay sits over the busy bottom edge (wheelbarrow, paint tin). The hero crop marks move to the
   screen corners; a drawing title block names the job, as in the corner of an architect's sheet. */
.top.over-photo { position: absolute; top: 0; left: 0; right: 0; background: transparent; }
.top.over-photo .nav > a, .top.over-photo .nav .mega-trigger { color: rgba(236, 238, 239, .84); }
.hero-photo { position: relative; isolation: isolate; overflow: hidden; display: flex; align-items: flex-end;
	min-height: 100vh; min-height: 100svh; background: var(--ink); color: var(--on-dark); }
.hero-bg { position: absolute; inset: 0; z-index: -2; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; object-position: 46% 42%;
	filter: saturate(.74) contrast(1.08) brightness(.9); transform-origin: 50% 70%; }
.hero-photo::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
	background:
		linear-gradient(180deg, rgba(29, 31, 33, .74) 0%, rgba(29, 31, 33, .16) 24%, rgba(29, 31, 33, .26) 52%, rgba(29, 31, 33, .95) 100%),
		linear-gradient(90deg, rgba(29, 31, 33, .78) 0%, rgba(29, 31, 33, .35) 45%, rgba(29, 31, 33, 0) 70%),
		rgba(43, 46, 49, .2); }
.marks-screen { inset: 24px; opacity: .55; }
.hero-photo-body { width: 100%; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 56px; align-items: end; padding-block: 168px 72px; }
.hero-photo h1 { margin: 0; }
.hero-photo h1 .place { display: block; color: var(--silver); margin-bottom: 22px; }
.hero-photo h1 .big { display: block; font-size: clamp(36px, 4.4vw, 66px); max-width: 17em; }
.hero-photo .lede { max-width: 34em; color: rgba(236, 238, 239, .86); margin: 28px 0 34px; font-size: 18px; }
.hero-photo .ctas { display: flex; flex-wrap: wrap; gap: 12px; }
.hero-photo .btn-line { border-color: rgba(236, 238, 239, .5); }
.title-block { margin: 0; min-width: 250px; border: 1px solid rgba(236, 238, 239, .4); font-size: 14px; }
.title-block > div { display: grid; grid-template-columns: 78px 1fr; gap: 12px; align-items: baseline; padding: 10px 14px; }
.title-block > div + div { border-top: 1px solid rgba(236, 238, 239, .4); }
.title-block dt { margin: 0; font-size: 10.5px; color: var(--silver); }
.title-block dd { margin: 0; color: var(--on-dark); }
@media (max-width: 900px) {
	.hero-photo-body { grid-template-columns: 1fr; gap: 28px; padding-block: 128px 40px; }
	.hero-bg img { object-position: 40% 40%; }
	/* On a phone the copy spans the whole width, so the whole photo needs the darker veil. */
	.hero-photo::after { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none; background: rgba(29, 31, 33, .32); }
	.title-block { justify-self: start; min-width: 0; width: 100%; max-width: 340px; }
	.marks-screen { inset: 12px; }
}

/* ═══ Homepage concept C (/v3/, 3 Oct): the whole page as a dark gallery ═══════════════════════
   Evidence: high-end architect/builder sites default to monochrome, dark and image-first with little
   text (createtoday architect examples; HostAdvice monochrome roundup, 2026); graphite/silver/white
   is already the Cloud Nine livery. One wrapper flips the palette tokens, so the shared sections
   (programme, credentials, sponsors, client words) render dark without their own copies.
   Photos are black and white until scrolled into view or hovered (.in-colour, set by site.js), which
   evens out mixed phone shots. With JS off they simply stay in colour (the filter needs html.js-mono). */
.v3 {
	--paper: #141618;
	--white: #1A1D20;
	--ink: #ECEEEF;
	--hairline: #2C3034;
	--muted: #969CA2;
	--graphite: #0F1112;
	--graphite-line: #2F3337;
	background: var(--paper);
	color: var(--ink);
}
.v3 .split, .v3 .tone-white, .v3 .tone-paper, .v3 .creds, .v3 .words, .v3 .prog, .v3 .sponsor { background: transparent; color: var(--ink); }

.v3 .sponsor { background: var(--white); }
.v3 strong { color: var(--ink); }
/* Light sections inside the dark homepage (the 18 Oct "mixed" rhythm): re-point the tokens to the
   light palette so every component in the section just follows. */
.v3 .lt { --paper: #F5F6F6; --white: #FFFFFF; --ink: #1D1F21; --hairline: #D9DCDE; --muted: #5A5F64; --graphite: #2B2E31; --graphite-line: #42464B; background: var(--paper); color: var(--ink); }
.v3 .lt.lt-white { background: var(--white); }
.v3 .lt .bar { background: var(--graphite); }
.v3 .lt .v3-work-head a, .v3 .lt .go { color: var(--muted); }
.v3 .lt .marks { --m: linear-gradient(var(--muted), var(--muted)); }

/* Monochrome → colour. Grayscale with lifted contrast reads as print, not as a dull photo. */
.js-mono .v3 [data-colour] img { filter: grayscale(1) contrast(1.12) brightness(.86); transition: filter 1400ms cubic-bezier(.22, .61, .36, 1); }
.js-mono .v3 [data-colour].in-colour img,
.js-mono .v3 [data-colour]:hover img { filter: grayscale(0) contrast(1.04) brightness(.96); }
@media (prefers-reduced-motion: reduce) { .js-mono .v3 [data-colour] img { transition: none; } }

/* Banner: the darkest of the three concepts. Black and white photo, a heavy charcoal veil, a fine
   film grain so the flat dark areas don't band, and the headline set large across the bottom. */
.v3-hero { position: relative; isolation: isolate; overflow: hidden; min-height: 100vh; min-height: 100svh; display: flex; align-items: flex-end; color: #ECEEEF; background: #141618; }
/* Clipped 8px above the bottom (where the veil is already solid page colour): the scroll-scaled photo
   otherwise bled a 1px hairline at the very edge, which read as a line between sections. */
.v3-hero-bg { position: absolute; inset: 0 0 8px 0; z-index: -3; overflow: hidden; }
.v3-hero-bg img { width: 100%; height: 100%; object-fit: cover; object-position: 46% 42%; filter: grayscale(1) contrast(1.22) brightness(.62); transform-origin: 50% 70%; }
.v3-hero::before { content: ""; position: absolute; inset: 0; z-index: -2; pointer-events: none;
	background:
		/* vignette in the PAGE colour: tinted darker, it made the banner end darker than the next section */
		radial-gradient(120% 85% at 70% 35%, rgba(20, 22, 24, 0) 0%, rgba(20, 22, 24, .55) 70%, rgba(20, 22, 24, .85) 100%),
		linear-gradient(180deg, rgba(11, 12, 13, .7) 0%, rgba(11, 12, 13, .15) 28%, rgba(16, 18, 20, .5) 50%, rgba(20, 22, 24, .9) 76%, rgb(20, 22, 24) 91%, rgb(20, 22, 24) 100%); }
/* live homepage (Mark, 18 Oct): lighter wash low down so the drawing shows nearer the bottom, then
   pulled back halfway ("too far the other way"); still
   solid at the very bottom edge so the banner runs into the next section */
.mixed .v3-hero::before { background:
		radial-gradient(120% 85% at 70% 35%, rgba(20, 22, 24, 0) 0%, rgba(20, 22, 24, .5) 70%, rgba(20, 22, 24, .78) 100%),
		linear-gradient(180deg, rgba(11, 12, 13, .7) 0%, rgba(11, 12, 13, .15) 28%, rgba(16, 18, 20, .44) 50%, rgba(20, 22, 24, .74) 75%, rgba(20, 22, 24, .9) 88%, rgb(20, 22, 24) 96%); }
.v3-hero::after { content: ""; position: absolute; inset: 0; z-index: -1; -webkit-mask-image: linear-gradient(180deg, #000 70%, transparent 100%); mask-image: linear-gradient(180deg, #000 70%, transparent 100%); pointer-events: none; opacity: .09; 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='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.v3-hero .marks-screen { opacity: .4; inset: 24px 24px 96px; }
.v3-hero-body { width: 100%; padding-block: 170px 64px; }
.v3-place { color: var(--silver); margin: 0 0 26px; }
.v3-h1 { margin: 0; font-size: clamp(40px, 6.4vw, 104px); line-height: 1.02; max-width: 13em; }
.v3-h1 span { color: var(--silver); }
/* v7: place line + headline in one h1 (looks the same as the p + h1 pair). */
.v3-h1-group { margin: 0; font: inherit; }
.v3-h1-group > span { display: block; }
.v3-hero-foot { display: grid; grid-template-columns: minmax(0, 34em) auto; justify-content: space-between; align-items: end; gap: 40px; margin-top: 44px; padding-top: 28px; border-top: 1px solid rgba(236, 238, 239, .22); }
.v3-hero .lede { margin: 0; font-size: 18px; color: rgba(236, 238, 239, .78); }
.v3-hero .ctas { display: flex; flex-wrap: wrap; gap: 12px; }
.v3-hero .btn-line { border-color: rgba(236, 238, 239, .45); }
.v3-caption { position: absolute; right: calc(var(--gutter) + 24px); top: 50%; margin: 0; font-size: 13px; color: rgba(236, 238, 239, .7); writing-mode: vertical-rl; transform: rotate(180deg); letter-spacing: .04em; }
.v3-caption .label { color: var(--silver); margin-bottom: 12px; font-size: 10.5px; }

/* Statement: big type, two short paragraphs, nothing else. */
.v3-statement { padding-block: 140px 120px; }
.v3-statement .statement { max-width: 18em; }
.v3-two { display: grid; grid-template-columns: 1fr 1fr; gap: 48px; margin-top: 56px; max-width: 900px; margin-left: auto; color: var(--muted); }

/* Services as a typographic index; on a mouse, the service's photo follows on the right. */
.v3-index { padding-block: 40px 120px; }
.v3-kicker { color: var(--muted); margin: 0 0 28px; font-size: 13px; }
.v3-index ul { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--hairline); }
.v3-index li { position: relative; border-bottom: 1px solid var(--hairline); }
.v3-index a { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) auto; gap: 40px; align-items: center; padding-block: 34px; text-decoration: none; color: var(--ink); }
.v3-ix-name { font-size: clamp(28px, 3.6vw, 52px); font-weight: 300; line-height: 1.08; font-stretch: var(--wide); font-variation-settings: 'wdth' 125; transition: transform 500ms cubic-bezier(.22, .61, .36, 1); }
.v3-ix-sum { color: var(--muted); font-size: 15px; max-width: 30em; }
.v3-index .go { font-size: 22px; color: var(--silver); transition: transform 400ms ease; }
.v3-ix-img { position: absolute; right: 120px; top: 50%; width: 260px; aspect-ratio: 4 / 3; object-fit: cover; translate: 0 -50%; opacity: 0; pointer-events: none; transition: opacity 400ms ease; z-index: 2; }
@media (hover: hover) {
	.v3-index li:hover .v3-ix-img { opacity: 1; }
	.v3-index li:hover .v3-ix-name { transform: translateX(14px); }
	.v3-index li:hover .go { transform: translateX(6px); }
	.v3-index li:hover .v3-ix-sum { opacity: 0; }
}

/* Work: big alternating photos, each with its drawing title block. */
.v3-work { padding-block: 40px 140px; }
.v3-work-head { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; margin-bottom: 56px; }
.v3-work-head h2 { margin: 0; font-size: clamp(32px, 4vw, 56px); }
.v3-work-head a { color: var(--silver); }
.v3-job { margin: 0 0 96px; display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 3fr); gap: 48px; align-items: end; }
.v3-job:nth-of-type(even) { grid-template-columns: minmax(0, 3fr) minmax(0, 7fr); }
.v3-job:nth-of-type(even) .v3-job-img { order: 2; }
.v3-job-img { overflow: hidden; }
.v3-job-img img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.v3-job .title-block { border-color: var(--hairline); min-width: 0; }
/* a headline above each project's title block (Mark, 18 Oct) */
.v3-job-h { margin: 0 0 22px; font-size: clamp(24px, 2.4vw, 34px); font-weight: 500; line-height: 1.15; letter-spacing: -0.02em; color: var(--ink); max-width: 14ch; }
.v3-job .title-block > div + div { border-top-color: var(--hairline); }
.v3-job .title-block dt { color: var(--muted); }
.v3-job .title-block dd { color: var(--ink); }
.v3-job .title-block dd a { color: inherit; text-decoration: none; }
.v3-job .title-block dd a span { display: inline-block; margin-left: 4px; transition: transform 400ms cubic-bezier(.22, .61, .36, 1); }
.v3-job .title-block dd a:hover { text-decoration: underline; text-underline-offset: 4px; }
.v3-job .title-block dd a:hover span { transform: translateX(4px); text-decoration: none; }

@media (max-width: 900px) {
	.v3-hero-body { padding-block: 130px 40px; }
	.v3-hero-foot { grid-template-columns: 1fr; gap: 24px; margin-top: 28px; }
	.v3-hero::before { background: linear-gradient(180deg, rgba(11, 12, 13, .72) 0%, rgba(11, 12, 13, .45) 35%, rgba(16, 18, 20, .72) 58%, rgba(20, 22, 24, .94) 80%, rgb(20, 22, 24) 92%, rgb(20, 22, 24) 100%); }
	.v3-caption { display: none; }
	.v3-statement { padding-block: 88px 72px; }
	.v3-two { grid-template-columns: 1fr; gap: 20px; margin-top: 32px; }
	.v3-index a { grid-template-columns: 1fr auto; gap: 8px 20px; padding-block: 24px; }
	.v3-ix-sum { grid-column: 1; grid-row: 2; }
	.v3-index .go { grid-row: 1 / 3; grid-column: 2; }
	.v3-ix-img { display: none; }
	.v3-job, .v3-job:nth-of-type(even) { grid-template-columns: 1fr; gap: 20px; margin-bottom: 64px; }
	.v3-job:nth-of-type(even) .v3-job-img { order: 0; }
}
/* Concept C: the programme bars are graphite on a light page; on the dark page they'd vanish. */
.v3 .bar { background: var(--silver); }
.v3 .today { background: var(--ink); }

/* ── v7 programme, sketched (Mark, 16 Oct: "less straight boring lines, more character") ──────
   Same programme, drawn the way the hero is: each stage pencilled in as a hand-drawn outline (the
   plan, drawn on as it scrolls in), then hatched in like a section drawing as "Today" passes it
   (built). A milestone diamond at each stage's end fills when it's done. The week grid becomes a
   drawing's scale bar: a tall tick per period, a short one halfway. site.js draws the lines
   at real pixel size (.sk-ready); until then, or with JS off, the plain bars show. */
.sketchy .track {
	height: 22px; margin-top: 4px;
	background:
		repeating-linear-gradient(to right, var(--hairline) 0 1px, transparent 1px calc(100% / 12)),
		repeating-linear-gradient(to right, var(--hairline) 0 1px, transparent 1px calc(100% / 24)) left bottom / 100% 5px no-repeat;
}
.sketchy .hatch {
	position: absolute; top: 3px; bottom: 3px; left: var(--s); width: calc(var(--e) - var(--s));
	background: repeating-linear-gradient(-55deg, color-mix(in srgb, var(--silver) 70%, transparent) 0 1px, transparent 1px 6px);
	clip-path: inset(0 100% 0 0); display: none;
}
.sketchy .sk, .sketchy .sk-today { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; display: none; }
.sketchy .sk path, .sketchy .sk-today path { fill: none; stroke: var(--silver); stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; }
.sketchy .sk .p2 { opacity: .45; stroke-width: .8; }
.sketchy .sk .ms { fill: transparent; transition: fill .4s ease; }
.sketchy .sk .ms.done { fill: var(--silver); }
.sketchy .sk .draw { stroke-dasharray: 1 1; stroke-dashoffset: 1; transition: stroke-dashoffset 1.4s cubic-bezier(.45, .05, .25, 1); }
.sketchy.sk-in .sk .draw { stroke-dashoffset: 0; }
.sketchy.sk-in .row:nth-child(2) .sk .draw { transition-delay: .25s; }
.sketchy.sk-in .row:nth-child(3) .sk .draw { transition-delay: .5s; }
.sketchy.sk-in .row:nth-child(4) .sk .draw { transition-delay: .75s; }
.sketchy.sk-ready .bar { display: none; }
.sketchy.sk-ready .hatch, .sketchy.sk-ready .sk { display: block; }
.sketchy.sk-ready .today { background: transparent; width: 9px; margin-left: -4px; }
.sketchy.sk-ready .today::before { left: 4px; }
.sketchy.sk-ready .sk-today { display: block; }
.sketchy .sk-today path { stroke: var(--ink); stroke-width: 1.2; }
/* ═══ v10 (Mark, 16 Oct): the bottom three sections redesigned ═══════════════════════════════ */
/* 1. Quote: centred, full width, inside the hero's crop marks; letters fill on scroll (.statement). */
.words-big .wrap { display: block; padding-block: 120px; }
.wb-frame { position: relative; margin: 0 auto; max-width: 1040px; padding: 72px clamp(24px, 6vw, 88px) 60px; text-align: center; }
.wb-frame .marks { opacity: .6; }
.words-big blockquote { margin: 0; }
.words-big .wb-q { max-width: none; margin: 0 auto; font-size: clamp(26px, 3.4vw, 46px); line-height: 1.22; }
.wb-frame figcaption { margin-top: 32px; color: var(--muted); }

/* 2. Form: one centred column, the question big, answers as large tiles, progress bar like a programme bar. */
.enquire-focus .wrap { display: block; max-width: 820px; margin-inline: auto; text-align: center; padding-block: 120px; }
.enquire-focus .side { margin-bottom: 48px; }
.enquire-focus .side h2 { font-size: clamp(32px, 4vw, 52px); }
.enquire-focus .side p { margin-inline: auto; }
.enquire-focus .direct { display: flex; justify-content: center; gap: 28px; flex-wrap: wrap; margin-top: 20px; }
.enquire-focus .direct a { font-size: 16px; color: var(--on-dark-muted); }
.enquire-focus .direct a:hover { color: var(--on-dark); }
.enquire-focus form { grid-template-columns: 1fr; text-align: left; }
.enquire-focus .convo-head { text-align: center; }
.enquire-focus .convo-bar { height: 6px; }
.enquire-focus .convo.stepped legend, .enquire-focus .convo.stepped .step-q, .enquire-focus .drop-legend { display: block; width: 100%; text-align: center; font-size: clamp(22px, 2.6vw, 32px); font-weight: 300; color: var(--on-dark); font-stretch: var(--wide); font-variation-settings: 'wdth' 125; margin-bottom: 22px; }
.enquire-focus .choices { justify-content: center; gap: 10px; }
.enquire-focus .choices label { padding: 16px 22px; font-size: 16px; }
.enquire-focus .step-actions, .enquire-focus .convo.stepped .step-back:not([hidden]) { justify-self: center; }
.enquire-focus .convo-trail { justify-content: center; }
/* v10 (Mark, 16 Oct): no intro line, no phone/email row, and the first question's visible text removed:
   the heading above already asks it. Kept for screen readers (a fieldset needs its legend). */
.enquire-focus [data-step="type"] legend { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; margin: 0; }
.enquire-focus .side { margin-bottom: 36px; }
/* v10 answer tiles with hand-drawn line icons (tools/form-icons.mjs): icon above the words, radio dot
   hidden (the tile shows the choice). The icon re-inks itself on hover / when chosen; no timer motion. */
/* fluid: 5 across in the wide centred form, fewer in the two-column form beside the contact details */
.choices-ico { display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: 10px; }
.choices-ico label { flex-direction: column; justify-content: flex-start; gap: 10px; padding: 18px 10px 14px; text-align: center; line-height: 1.3; min-width: 0; overflow-wrap: anywhere; }
.enquire-focus .choices-ico label { position: relative; flex-direction: column; justify-content: flex-start; gap: 12px; padding: 22px 12px 18px; text-align: center; line-height: 1.3; font-size: 15px; }
.choices-ico input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choices-ico label:has(input:focus-visible) { outline: 2px solid var(--on-dark); outline-offset: 2px; }
/* "Pick one" under the icon tiles (Mark, 18 Oct): says plainly what to do with them */
.pick-hint { margin: 16px 0 0; font-size: 14px; color: var(--on-dark-muted); }
.enquire-focus .pick-hint { text-align: center; }
/* Hugeicons (20 Oct): stroke icons sized in CSS, coloured by the text (currentColor) */
.opt-ico .hi { display: block; width: 40px; height: 40px; color: var(--silver); stroke-width: 1.3; transition: color .3s ease, transform .4s cubic-bezier(.22, .61, .36, 1); }
.choices-ico label:hover .opt-ico .hi { color: var(--on-dark); transform: translateY(-2px); }
.choices-ico label:has(input:checked) .opt-ico .hi { color: var(--on-dark); }

@media (max-width: 760px) { .choices-ico { grid-template-columns: repeat(2, minmax(0, 1fr)); } .choices-ico label:last-child { grid-column: 1 / -1; } }
.opt-ico { display: block; }
.enquire-focus .step-details .btn { justify-self: center; }

/* 3. Footer: the normal columns, plus the name across the full width, cut off by the page bottom.
   Typed in the site font for now, not their logo lettering (see build.mjs footer). */
.foot-mark { overflow: hidden; }
.sheet-name { margin: 24px 0 0; font-weight: 700; font-size: 13.2vw; line-height: .74; letter-spacing: -0.02em; text-align: center; white-space: nowrap; color: var(--graphite-line); font-stretch: var(--wide); font-variation-settings: 'wdth' 125; transform: translateY(14%); user-select: none; }

/* ── v12: "How your project runs" as a photo journey (Mark, 18 Oct: the chart felt sterile) ──────
   Four stages side by side, each a real moment (photo), its dot on a line that fills as you scroll. */
.journey .wrap { padding-block: 104px 112px; }
.journey .intro { max-width: 40em; color: var(--muted); margin: 0 0 56px; }
.jr-steps { position: relative; list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 32px; }
.jr-line { position: absolute; left: 6px; right: calc((100% - 96px) / 4 - 7px); top: 6px; height: 1px; background: var(--hairline); }
.jr-line span { position: absolute; inset: 0; background: var(--ink); transform-origin: left center; transform: scaleX(0); }
.jr-step { position: relative; }
.jr-dot { display: block; width: 13px; height: 13px; border-radius: 50%; border: 1px solid var(--muted); background: var(--paper); margin-bottom: 26px; position: relative; z-index: 1; transition: background .5s ease, border-color .5s ease, transform .5s cubic-bezier(.22, .61, .36, 1); }
.jr-step.on .jr-dot { background: var(--ink); border-color: var(--ink); transform: scale(1.15); }
/* landscape: keeps the people in the first-visit shot */
.jr-photo { margin: 0 0 22px; aspect-ratio: 4 / 3; overflow: hidden; background: var(--hairline); }
.jr-photo img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s cubic-bezier(.22, .61, .36, 1); }
.jr-step h3 { margin: 0 0 8px; font-size: 20px; font-weight: 600; }
.jr-step p { margin: 0; color: var(--muted); font-size: 15px; line-height: 1.6; max-width: 26em; }
/* the black-and-white to colour treatment, on this light section too */
.js-mono .jr-photo[data-colour] img { filter: grayscale(1) contrast(1.08); transition: filter 1400ms cubic-bezier(.22, .61, .36, 1), transform 1.2s cubic-bezier(.22, .61, .36, 1); }
.js-mono .jr-photo[data-colour].in-colour img, .js-mono .jr-step:hover .jr-photo img { filter: none; }
@media (max-width: 900px) { .jr-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 48px; } .jr-line { display: none; } .jr-dot { display: none; } }
@media (max-width: 520px) { .jr-steps { grid-template-columns: 1fr; } }

/* ═══ Inner pages, 18 Oct (Mark: "more images, less lists with line separators") ═══════════════ */
/* Service cards: their own job photo, the name, a line; no rules. */
.svc-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 36px 24px; }
/* 4 = 2 x 2, 3 = one row: never a lone card on its own row */
.svc-cards[data-n="4"], .svc-cards[data-n="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.svc-cards[data-n="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 760px) { .svc-cards[data-n] { grid-template-columns: 1fr; } }
.svc-card { display: grid; gap: 10px; align-content: start; text-decoration: none; color: var(--ink); }
.svc-card-img { display: block; aspect-ratio: 4 / 3; overflow: hidden; border-radius: 2px; background: var(--hairline); }
.svc-card-img img { width: 100%; height: 100%; object-fit: cover; }
.svc-card-name { margin-top: 6px; font-size: 21px; font-weight: 500; line-height: 1.25; }
.svc-card .go { display: inline-block; transition: transform 400ms cubic-bezier(.22, .61, .36, 1); }
.svc-card:hover .go { transform: translateX(6px); }
.svc-card-sum { color: var(--muted); font-size: 15px; line-height: 1.6; }

/* Feature split: a big photo in crop marks beside the points, set as a loose grid. */
.feat .wrap { padding-block: 104px; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: 72px; align-items: start; }
.feat-flip .feat-photo { order: 2; }
.feat-photo { position: sticky; top: 96px; margin: 0; padding: 12px; }
.feat-photo img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; display: block; }
.feat-photo .marks { --m: linear-gradient(var(--muted), var(--muted)); opacity: .6; }
.feat-h { font-size: clamp(30px, 3.4vw, 46px); margin: 12px 0 40px; }
.feat-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px 36px; }
.feat-item h3 { margin: 0 0 8px; font-size: 19px; font-weight: 600; }
.feat-item p { margin: 0; color: var(--muted); }
@media (max-width: 900px) { .feat .wrap { grid-template-columns: 1fr; gap: 40px; padding-block: 72px; } .feat-photo { position: static; order: 0 !important; max-width: 520px; } }
@media (max-width: 560px) { .feat-grid { grid-template-columns: 1fr; gap: 28px; } }

/* Full-width photo band between sections. */
.band { position: relative; margin: 0; }
.band img { width: 100%; height: clamp(280px, 42vw, 560px); object-fit: cover; display: block; }
.band figcaption { position: absolute; left: var(--gutter); bottom: 18px; color: #ECEEEF; text-shadow: 0 1px 10px rgba(0,0,0,.6); }

/* Partner cards (no rules). */
.partner-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 20px; }
.partner-card { display: grid; gap: 8px; padding: 28px; background: var(--paper); border-radius: 2px; text-decoration: none; color: var(--ink); transition: background .3s ease; }
.partner-card:hover { background: var(--hairline); }
.partner-name { font-size: 21px; font-weight: 500; }
.partner-role { color: var(--muted); font-size: 15px; }

/* Heading-on-top sections (18 Oct), to break up the side-heading layout. */
.stack .wrap { padding-block: 104px; }
.stack-h { font-size: clamp(30px, 3.6vw, 52px); margin: 0 0 18px; max-width: 18ch; }
.stack-lede { margin: 0 0 48px; max-width: 40em; color: var(--muted); font-size: 18px; }
.stack-h + .tiles, .stack-h + .svc-cards, .stack-h + .partner-cards, .stack-h + .people, .stack-h + .teams { margin-top: 44px; }
.stack .tiles { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 32px 24px; }
.tone-dark { background: var(--graphite); color: var(--on-dark); --ink: #ECEEEF; --muted: #A9AEB3; --hairline: #42464B; }
.tone-dark .stack-h { color: var(--on-dark); }
.tone-dark .svc-card { color: var(--on-dark); }

/* v7 homepage CTA (replaces the form; Mark, 16 Oct): full-bleed photo under a graphite veil */
.v3-cta { position: relative; isolation: isolate; overflow: hidden; color: #ECEEEF; }
.v3-cta-bg { position: absolute; inset: 0; z-index: -2; }
.v3-cta-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.v3-cta::after { content: ""; position: absolute; inset: 0; z-index: -1; background: radial-gradient(ellipse 70% 80% at 50% 50%, rgba(15,17,18,.86) 0%, rgba(15,17,18,.66) 100%); }
.v3-cta .wrap { text-align: center; }
.v3-cta h2 { margin-inline: auto; }
.v3-cta-lede { margin-inline: auto; }
.v3-cta-actions { justify-content: center; }
.v3-cta .wrap { padding-block: 140px; }
.v3-cta .label { color: #B9BDC1; margin: 0 0 22px; }
.v3-cta h2 { margin-block: 0; font-size: clamp(36px, 5vw, 72px); line-height: 1.04; max-width: 14ch; color: #ECEEEF; }
.v3-cta-lede { margin-block: 24px 0; max-width: 34em; color: #C9CDD1; font-size: 18px; line-height: 1.6; }
.v3-cta-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 36px; }
@media (max-width: 760px) { .v3-cta .wrap { padding-block: 88px; } .v3-cta::after { background: rgba(15,17,18,.8); } }

@media (prefers-reduced-motion: reduce) { .sketchy .sk .draw { stroke-dashoffset: 0; transition: none; } .sketchy .hatch { clip-path: none; } }

/* ═══ Homepage concept D (/v4/, 3 Oct): v3 plus a colour lens ═════════════════════════════════
   A colour copy of each photo sits over the black and white one and shows only inside a soft circle
   that follows the cursor (--lx/--ly, eased in site.js) and grows/shrinks on enter/leave (--lr,
   transitioned). Hover devices only; phones keep v3's colour-on-scroll. Motion on hover, never a timer. */
@property --lr { syntax: '<length>'; inherits: true; initial-value: 0px; }
.lens-mode .v3-hero, .lens-mode .v3-job-img { --lr: 0px; transition: --lr 650ms cubic-bezier(.22, .61, .36, 1); }
.lens-mode .lens { position: absolute; inset: 0; pointer-events: none; overflow: hidden;
	-webkit-mask-image: radial-gradient(circle var(--lr) at var(--lx, 50%) var(--ly, 50%), #000 0%, #000 42%, transparent 100%);
	mask-image: radial-gradient(circle var(--lr) at var(--lx, 50%) var(--ly, 50%), #000 0%, #000 42%, transparent 100%); }
/* Banner: above the charcoal veil (so the colour is seen), below the words; fades out before the
   bottom so the seamless join into the next section stays clean. */
.v3-hero .lens { inset: 0 0 8px 0; z-index: -1;
	-webkit-mask-image: radial-gradient(circle var(--lr) at var(--lx, 50%) var(--ly, 50%), #000 0%, #000 42%, transparent 100%), linear-gradient(180deg, #000 55%, transparent 90%);
	-webkit-mask-composite: source-in;
	mask-image: radial-gradient(circle var(--lr) at var(--lx, 50%) var(--ly, 50%), #000 0%, #000 42%, transparent 100%), linear-gradient(180deg, #000 55%, transparent 90%);
	mask-composite: intersect; }
.v3-hero .lens img { width: 100%; height: 100%; object-fit: cover; object-position: 46% 42%; transform-origin: 50% 70%; filter: saturate(1.05) contrast(1.05) brightness(.8); }
.lens-mode .v3-job-img { position: relative; }
.v3-job-img .lens { z-index: 1; }
.v3-job-img .lens img { width: 100%; height: 100%; object-fit: cover; }
@media (hover: none), (pointer: coarse) { .lens-mode .lens { display: none; } }
@media (prefers-reduced-motion: reduce) { .lens-mode .v3-hero, .lens-mode .v3-job-img { transition: none; } }
/* Lens as ink (3 Oct, round 2): the shape is drawn by site.js on .lens-blob (five merging soft
   blobs), so the outer .lens no longer carries the circle. The banner's .lens keeps only the fade
   towards the bottom, so the colour never reaches the seamless join. */
.lens-mode .lens { -webkit-mask-image: none; mask-image: none; }
.v3-hero.v3-hero .lens { -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 90%); mask-image: linear-gradient(180deg, #000 55%, transparent 90%); }
.lens-blob { position: absolute; inset: 0; opacity: 0; transition: opacity 300ms ease; }
.lens-blob img { width: 100%; height: 100%; object-fit: cover; }
.v3-hero .lens-blob img { object-position: 46% 42%; transform-origin: 50% 70%; }
/* Richer colour inside the lens: at brightness .8 the brick read as mud against the grey. */
.v3-hero .lens img { filter: saturate(1.12) contrast(1.06) brightness(.92); }
/* Liquid reveal (3 Oct, round 3, after landonorris.com): site.js paints the colour photo onto
   .lens-canvas through a thresholded, noise-edged trail. .lens-src is only the canvas's source (the
   browser still picks its size from srcset), so it's invisible. */
.lens-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; transform-origin: 50% 70%; }
.lens-src { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; pointer-events: none; }
.v3-hero .lens-canvas { filter: saturate(1.1) contrast(1.06) brightness(.84); }

/* Concept D, round 5 (3 Oct): DRAWING → BUILT. Colouring was the wrong idea (Mark): the reveal now
   says something. On a mouse, the banner is a pen drawing of the house (traced from the photo by
   tools/drawing.mjs); the liquid trail reveals the real, finished building through it, in v3's
   black and white. All three layers sit under the charcoal veil so they're lit alike. Phones (no
   cursor to reveal with) simply get v3's photo banner. */
.v3-draw { position: absolute; inset: 0 0 8px 0; z-index: -3; overflow: hidden; }
.v3-draw img { width: 100%; height: 100%; object-fit: cover; object-position: 46% 42%; transform-origin: 50% 70%; }
.lens-mode .v3-hero .lens { z-index: -3; }
.v3-hero .lens-canvas { filter: grayscale(1) contrast(1.22) brightness(.62); }
@media (hover: none), (pointer: coarse) { .v3-draw { display: none; } }

/* ═══ Dark mega menu (v5, Mark 3 Oct: "a dark version of this menu") ═══════════════════════
   Same panel, layout and motion; only the colours flip. A hairline on top separates it from the
   header, which floats over the dark hero. */
/* It unrolls from the very top of the screen (Mark, 3 Oct): pulled up by the header's height (--top-h, set
   by site.js; 0 without JS, so it then opens under the header) and padded back down, with the logo and
   nav lifted above it. */
.mega-dark .mega { background: var(--ink); color: var(--on-dark); border-bottom-color: var(--graphite-line); top: calc(100% - var(--top-h, 0px)); padding-top: var(--top-h, 0px); z-index: 1; }
.mega-dark .logo, .mega-dark .nav > a, .mega-dark .mega-trigger { position: relative; z-index: 2; }
.mega-dark .mega-list { border-top-color: var(--silver); }
.mega-dark .mega-list li { border-bottom-color: var(--graphite-line); }
.mega-dark .mega-list a, .mega-dark .mega-list .mega-all { color: var(--on-dark); }
.mega-dark .mega-sum { color: var(--on-dark-muted); }
.mega-dark .mega-frame .marks { --m: linear-gradient(var(--silver), var(--silver)); opacity: .5; }
.mega-dark .mega-mosaic { background: var(--ink); }
.mega-dark .has-mega::before { background: rgba(10, 11, 12, .6); }

/* ═══ v6 font trial: headings in Hanken Grotesk medium (Mark, 3 Oct) ══════════════════════
   Only the headings change; labels, body, nav and buttons stay Archivo. Undoes Archivo's width axis,
   sets medium weight and tight tracking on the big sizes, a lighter touch on the small ones. */
.f-hanken :is(h1, h2, h3, .display, .statement, .side-head, .mega-name, .v3-ix-name, .acc-word):not(.label) {
	font-family: 'Hanken Grotesk', 'Archivo', system-ui, sans-serif; font-stretch: normal; font-variation-settings: normal; font-weight: 500; letter-spacing: -0.012em; }
.f-hanken :is(.display, .statement, .v3-ix-name, .mega-name, .acc-word):not(.label) { letter-spacing: -0.035em; }

/* ═══ v7: the reveal in COLOUR (Mark, 3 Oct: "same as now but in colour") ════════════════════
   Same drawing and liquid trail as v5/v6; the real building comes through in its own colours instead
   of v3's black and white (still a touch darker so it sits under the veil with the drawing). */
.reveal-colour .v3-hero .lens-canvas { filter: saturate(1.05) contrast(1.06) brightness(.82); }
/* v7 (Mark, 3 Oct: "I'd like the lower part to also be reactive"): the reveal was under the charcoal
   veil, which goes near-solid over the bottom fifth (that's how the banner blends into the next
   section), and its own mask faded it out from halfway down. Here it sits ABOVE the veil with its own
   even darkening, and fades only over the last few percent, so the join into the next section stays
   seamless while the whole banner, words and buttons included, answers the cursor. */
.lens-mode.reveal-colour .v3-hero .lens { z-index: -1; }
.reveal-colour .v3-hero.v3-hero .lens { -webkit-mask-image: linear-gradient(180deg, #000 86%, transparent 99%); mask-image: linear-gradient(180deg, #000 86%, transparent 99%); }
.reveal-colour .v3-hero .lens-canvas { filter: saturate(1.05) contrast(1.06) brightness(.6); }

/* ═══ v9: the drawing BUILT by scroll (Mark, 4 Oct, option A) ═════════════════════════════════
   No photo at all, on any device. The live SVG (tools/house.mjs → img/house-build-za-hand.svg)
   replaces the finished drawing once it loads; js/site.js "Concept H" moves each part's rise clip. */
.v3-build { position: absolute; inset: 0 0 8px 0; z-index: -3; overflow: hidden; will-change: transform; }
.v3-build > img, .v3-build > svg { display: block; width: 100%; height: 100%; object-fit: cover; }
.v3-hero-bg[hidden] { display: none; }
/* The hero holds while the house is built: 70% of a screen of scrolling, native sticky (no scroll
   hijack), then it scrolls away as normal. */
.v3-pin { height: calc(100vh + 70vh); height: calc(100svh + 70svh); }
.v3-pin > .v3-hero { position: sticky; top: 0; }
@media (prefers-reduced-motion: reduce) { .v3-pin { height: auto; } .v3-pin > .v3-hero { position: relative; } }

/* ═══ Cut corners (Mark, 18 Oct): one 45° corner cut off, like a roof slope or a chamfered edge ═════
   Images, buttons, tiles and cards: the TOP-RIGHT corner. Dark sections: the BOTTOM-RIGHT corner, so
   the next section's colour shows through the cut (the dark section overlaps the next one by the cut
   size; the next one gets that much extra top padding back). One corner only, same angle everywhere.
   The whole system hangs off html.cuts (set in head()); remove that class to switch it all off. */
.cuts { --cut-img: clamp(16px, 2.2vw, 30px); --cut-img-lg: clamp(30px, 5vw, 72px); --cut-ui: 14px; --cut-sec: clamp(36px, 5vw, 72px); }
.cuts :is(.shot, .svc-card-img, .tile img, .jr-photo, .feat-photo img, .founder-shot, .v3-job-img, .person-initial, .team-frame, .partner-card, .acc-card) {
	clip-path: polygon(0 0, calc(100% - var(--cut-img)) 0, 100% var(--cut-img), 100% 100%, 0 100%);
}
.cuts :is(.btn, .choices label) {
	border-radius: 0;
	clip-path: polygon(0 0, calc(100% - var(--cut-ui)) 0, 100% var(--cut-ui), 100% 100%, 0 100%);
}
/* outlined ones: a TRUE outline that follows the cut (Mark, 18 Oct). The element's own border is
   hidden; ::before is a 1px ring traced round the same cut shape (outer path, then the inner path the
   other way round, so the middle is a hole), filled with the border colour. */
.cuts :is(.btn-line, .choices label) { --bc: var(--graphite-line); position: relative; border-color: transparent !important; }
.cuts :is(.btn-line, .choices label)::before { content: ""; position: absolute; inset: 0; background: var(--bc); pointer-events: none; transition: background-color 600ms ease;
	clip-path: polygon(0 0, calc(100% - var(--cut-ui)) 0, 100% var(--cut-ui), 100% 100%, 0 100%, 0 0, 1px 1px, 1px calc(100% - 1px), calc(100% - 1px) calc(100% - 1px), calc(100% - 1px) calc(var(--cut-ui) + .42px), calc(100% - var(--cut-ui) - .42px) 1px, 1px 1px); }
.cuts .btn-line:hover { --bc: var(--silver); }
.cuts :is(.v3-hero, .hero-photo) .btn-line { --bc: rgba(236, 238, 239, .45); }
.cuts :is(.v3-hero, .hero-photo) .btn-line:hover { --bc: rgba(236, 238, 239, .8); }
.cuts .choices label:hover { --bc: var(--silver); }
.cuts .choices label:has(input:checked) { --bc: var(--on-dark); }
/* Section cuts (Mark, 18 Oct: "slightly randomise it so it's not in the same area of each section"):
   js/site.js finds every boundary between a light and a dark section and gives it ONE cut, on a corner
   taken from a shuffled sequence (bottom-right, top-left, bottom-left, top-right; a different starting
   point per page). The cut is a triangle in the NEIGHBOURING section's colour laid over the corner, so
   nothing overlaps and the layout never shifts. */
/* 1px past the section edge: covers the anti-aliased seam a fractional-pixel boundary leaves (Mark, 18 Oct) */
.sec-cut { position: absolute; width: var(--cut-sec); height: calc(var(--cut-sec) + 1px); background: var(--cut-fill); pointer-events: none; z-index: 1; }
.sec-cut-br { right: 0; bottom: -1px; clip-path: polygon(100% 0, 100% 100%, 0 100%); }
.sec-cut-bl { left: 0; bottom: -1px; clip-path: polygon(0 0, 100% 100%, 0 100%); }
.sec-cut-tr { right: 0; top: -1px; clip-path: polygon(0 0, 100% 0, 100% 100%); }
.sec-cut-tl { left: 0; top: -1px; clip-path: polygon(0 0, 100% 0, 0 100%); }
/* Mega menu (Mark, 18 Oct): the panel lands with its bottom-right corner cut. Open and closed are the
   SAME five-point polygon (closed = squashed to the top edge), so the unroll still animates. */
.cuts .mega { clip-path: polygon(0 0, 100% 0, 100% 0, 100% 0, 0 0); }
/* no bottom border on the panel: the cut ends it (Mark, 18 Oct) */
.cuts .mega, .cuts .mega-dark .mega { border-bottom: 0; }
.cuts :is(.has-mega:hover, .has-mega:focus-within, .has-mega.open) .mega { clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut-sec)), calc(100% - var(--cut-sec)) 100%, 0 100%); }
.cuts .has-mega.shut .mega { clip-path: polygon(0 0, 100% 0, 100% 0, 100% 0, 0 0); }
.cuts :is(.mega-shots, .mega-mosaic) { clip-path: polygon(0 0, calc(100% - var(--cut-img)) 0, 100% var(--cut-img), 100% 100%, 0 100%); }
/* Crop marks round a cut photo: no top-right mark, the cut already makes that corner (Mark, 18 Oct).
   Same three marks as .marks, minus top right. (The quote frame has no cut, so it keeps all four.) */
.cuts :is(.shot-frame, .feat-photo, .mega-frame, .person-photo, .team-frame) .marks { background:
		var(--m) top left / 22px 1px no-repeat, var(--m) top left / 1px 22px no-repeat,
		var(--m) bottom left / 22px 1px no-repeat, var(--m) bottom left / 1px 22px no-repeat,
		var(--m) bottom right / 22px 1px no-repeat, var(--m) bottom right / 1px 22px no-repeat; }
.cuts .founder .marks { --m: linear-gradient(currentColor, currentColor); background:
		var(--m) top left / 22px 1px no-repeat, var(--m) top left / 1px 22px no-repeat,
		var(--m) bottom left / 22px 1px no-repeat, var(--m) bottom left / 1px 22px no-repeat,
		var(--m) bottom right / 22px 1px no-repeat, var(--m) bottom right / 1px 22px no-repeat; }
/* the BIG photos get a bigger cut, in proportion (Mark, 18 Oct: "cut more off the bigger images"): recent
   work, the framed header photos, the What's-included photos, the team photo, the big 2-up work photos */
.cuts :is(.v3-job-img, .shot, .feat-photo img, .founder-shot, .stack .tile img) {
	clip-path: polygon(0 0, calc(100% - var(--cut-img-lg)) 0, 100% var(--cut-img-lg), 100% 100%, 0 100%);
}
@media (max-width: 760px) { .cuts { --cut-sec: 28px; --cut-img: 14px; --cut-img-lg: 26px; } }


/* RULE (Mark, 18 Oct): never a thin line BETWEEN sections. Sections are told apart by colour, space
   and the cut corners; borders inside sections (list rows, tables) are fine. */
main section, main figure.band { border-top: 0 !important; border-bottom: 0 !important; }

/* Line-rise masks (GSAP SplitText mask: "lines") clip at one line-height, which cut off descenders (the g
   in "managed") on tight headings (Mark, 19 Oct). Room below each mask, cancelled by a negative margin so
   the line spacing is unchanged. */
[data-anim="lines"] > div { padding-bottom: .18em; margin-bottom: -.18em; }

/* ═══ Hugeicons, site-wide (Mark, 20 Oct: "use them everywhere") ═══════════════════════════════════
   .hi = 1em square, follows the text colour. .hi-l = sits left of a label. */
.hi { width: 1em; height: 1em; flex: none; vertical-align: -0.14em; }
.hi-l { margin-right: .5em; }
.btn .hi-l { width: 1.1em; height: 1.1em; vertical-align: -0.2em; }
.go .hi, .mega-go .hi, .sb-arrow .hi { vertical-align: -0.12em; }
.ico-line { display: flex; align-items: flex-start; gap: 0; }
.ico-line .hi-l { margin-top: .28em; }
.ico-pad { padding-left: 1.5em; }
.foot .ico-line { margin-bottom: 4px; }
.foot-social { display: flex; gap: 18px; flex-wrap: wrap; }
.soc { display: inline-flex; align-items: center; }
.soc .hi-l { margin-right: .4em; }
/* credential icons sit LEFT of the title so all four items stay top-aligned with the FMB one */
.creds li:has(> .cred-ico) { position: relative; padding-left: 60px; }
.cred-ico { position: absolute; left: 24px; top: 4px; width: 24px; height: 24px; color: var(--muted); stroke-width: 1.3; }
@media (max-width: 900px) { .creds li:has(> .cred-ico) { padding-left: 36px; } .cred-ico { left: 0; } }
.drop-icon.hi { width: 30px; height: 30px; }

/* ═══ Bold programme (Mark, 20 Oct: "bolder line graphs") ═══════════════════════════════════════════
   A staircase of thick bars across the full width. Pale bar = the plan; graphite fill = done, swept in
   as the Today line passes (site.js). Cut top-right corner like the rest of the site. */
.bprog .intro { margin-bottom: 64px; }
.bp-chart { position: relative; padding-top: 34px; }
.bp-scale { position: absolute; left: 0; right: 0; top: 0; height: 14px; border-bottom: 2px solid var(--ink);
	background: repeating-linear-gradient(to right, var(--ink) 0 2px, transparent 2px calc(100% / 12)) left bottom / 100% 14px no-repeat,
		repeating-linear-gradient(to right, var(--muted) 0 1px, transparent 1px calc(100% / 48)) left bottom / 100% 7px no-repeat; }
.bp-row { position: relative; margin-left: var(--s); width: calc(var(--e) - var(--s)); padding-block: 30px 6px; }
.bp-title { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; font-size: clamp(19px, 1.7vw, 24px); font-weight: 600; white-space: nowrap; }
.bp-ico { width: 1.25em; height: 1.25em; stroke-width: 1.5; }
.bp-bar { position: relative; height: 34px; background: color-mix(in srgb, var(--ink) 12%, transparent);
	clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%); }
.bp-fill { position: absolute; inset: 0; background: var(--ink); clip-path: inset(0 100% 0 0); }
.bp-desc { margin: 12px 0 0; max-width: 30em; color: var(--muted); font-size: 15px; line-height: 1.55; }
/* narrow bars: let the words run past the bar; late bars: anchor the words to the bar's right end */
.bp-row .bp-desc { width: max(100%, 22em); }
.bp-end .bp-title { justify-content: flex-end; }
.bp-end .bp-desc { margin-left: auto; text-align: right; position: relative; right: 0; float: right; }
.bp-end::after { content: ""; display: block; clear: both; }
.bp-today { position: absolute; top: 0; bottom: 0; left: 0; width: 2px; background: var(--ink); opacity: 0; pointer-events: none; z-index: 2; }
.bp-today span { position: absolute; top: -26px; left: 0; transform: translateX(-50%); font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink); background: var(--paper); padding: 2px 6px; }
@media (max-width: 760px) {
	.bp-row { margin-left: 0; width: 100%; }
	.bp-end .bp-title { justify-content: flex-start; }
	.bp-end .bp-desc { float: none; text-align: left; margin-left: 0; }
	.bp-row .bp-desc { width: auto; }
	.bp-today { display: none; }
}
@media (prefers-reduced-motion: reduce) { .bp-fill { clip-path: none; } }
/* words sit above the Today line; a paper halo keeps them readable where it crosses */
.bp-title, .bp-desc { position: relative; z-index: 3; text-shadow: 0 0 3px var(--paper), 0 0 3px var(--paper), 0 0 6px var(--paper); }
.bp-today { z-index: 1; }
/* Sticky ruler (Mark, 20 Oct): the scale + "Today" pin to the top of the screen while the chart scrolls
   past, so the lower stages (Handover) still read against Today. The strip is opaque so bars slide under
   it; it carries its own short Today marker, which joins up with the full-height line below. */
.bp-chart { padding-top: 0; }
.bp-scale { position: sticky; top: 0; z-index: 4; height: 52px; margin-bottom: 4px; background-color: var(--paper); }
.bp-now { position: absolute; top: 0; bottom: -2px; left: 0; width: 2px; opacity: 0; }
.bp-now::before { content: ""; position: absolute; left: 0; width: 2px; top: 26px; bottom: 0; background: var(--ink); }
.bp-now span { position: absolute; top: 6px; left: 1px; transform: translateX(-50%); font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--ink); white-space: nowrap; }
@media (max-width: 760px) { .bp-scale { position: relative; } .bp-now { display: none; } }

/* ═══ Work slider (Mark, 20 Oct: "a fancy looking slider with arrows") ═══════════════════════════════
   Scroll-snap track; each slide is 82% wide so the next one peeks in. With JS (.sl-on) the slides you
   aren't on dim back, and solid cut-corner arrow buttons + a big 01 / 03 count drive it. */
.stack-h + .sl { margin-top: 44px; }
.sl-track { display: grid; grid-auto-flow: column; grid-auto-columns: 82%; gap: 24px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; overscroll-behavior-x: contain; outline-offset: 6px; }
.sl-track::-webkit-scrollbar { display: none; }
.sl-slide { margin: 0; scroll-snap-align: start; transition: opacity .6s ease; }
.sl-img { overflow: hidden; }
.sl-img img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; transform: scale(1.06); transition: transform 1.2s cubic-bezier(.22, .61, .36, 1); }
.cuts .sl-img { clip-path: polygon(0 0, calc(100% - var(--cut-img-lg)) 0, 100% var(--cut-img-lg), 100% 100%, 0 100%); }
.sl-slide figcaption { margin-top: 18px; display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 16px; }
.sl-slide figcaption b { font-size: clamp(19px, 1.7vw, 24px); font-weight: 600; color: var(--ink); }
.sl-slide figcaption span { font-size: 14px; color: var(--muted); }
.sl-on .sl-slide:not(.is-on) { opacity: .35; }
.sl-on .sl-slide.is-on .sl-img img, .sl:not(.sl-on) .sl-img img { transform: scale(1); }
.sl-ui { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 28px; }
.sl:not(.sl-on) .sl-ui { display: none; }
.sl-count { margin: 0; font-variant-numeric: tabular-nums; color: var(--muted); font-size: 16px; }
.sl-count b { font-size: clamp(34px, 3.4vw, 48px); font-weight: 600; color: var(--ink); letter-spacing: -.02em; }
.sl-btns { display: flex; gap: 10px; }
.sl-btn { width: 60px; height: 60px; display: grid; place-items: center; border: 0; padding: 0; cursor: pointer; background: var(--ink); color: var(--paper); font-size: 22px; clip-path: polygon(0 0, calc(100% - var(--cut-ui)) 0, 100% var(--cut-ui), 100% 100%, 0 100%); transition: opacity .3s ease, background-color .3s ease; }
.sl-btn .hi { transition: transform .35s cubic-bezier(.22, .61, .36, 1); }
.sl-prev .hi { transform: scaleX(-1); }
.sl-next:hover .hi { transform: translateX(4px); }
.sl-prev:hover .hi { transform: scaleX(-1) translateX(4px); }
.sl-btn:disabled { opacity: .25; cursor: default; }
.sl-btn:disabled .hi { transform: none; }
.sl-prev:disabled .hi { transform: scaleX(-1); }
.sl-btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (max-width: 760px) {
	.sl-track { grid-auto-columns: 88%; gap: 14px; }
	.sl-img img { aspect-ratio: 4 / 3; }
	.sl-btn { width: 52px; height: 52px; }
}
@media (prefers-reduced-motion: reduce) { .sl-img img { transform: none !important; transition: none; } .sl-slide { transition: none; } }

/* last word + arrow stay together (build.mjs tailArrow) */
.nowrap { white-space: nowrap; }
/* slider, round 2 (Mark, 20 Oct): mouse drag + click a neighbour to go to it; arrow buttons are plain
   squares (no cut corner) */
.sl-btn { clip-path: none; }
@media (pointer: fine) { .sl-on .sl-track { cursor: grab; } }
.sl-track.is-drag { scroll-snap-type: none; cursor: grabbing; user-select: none; }
.sl-on .sl-slide:not(.is-on) { cursor: pointer; }
.sl-img img { -webkit-user-drag: none; }
/* only the NEXT button keeps the cut top-right corner (Mark, 20 Oct) */
.sl-next { clip-path: polygon(0 0, calc(100% - var(--cut-ui)) 0, 100% var(--cut-ui), 100% 100%, 0 100%); }
/* small headings were inheriting the body's 1.7 line-height, so a wrapped title read as two lines
   (Mark, 20 Oct: "line spacing of these headings should be tighter"). Element-level, so any heading
   that already sets its own line-height keeps it. */
h3 { line-height: 1.3; }
.feat-item h3 { margin-bottom: 10px; }
/* ═══ Form progress as a brick wall (Mark, 20 Oct: "stylise these steps as a brick by brick visual") ═══
   Built by site.js: 2 courses, stretcher bond, bottom course drawn last in the DOM order (column-reverse)
   so it sits at the bottom. Empty slots are faint; laid bricks drop in, one after another. */
.convo-wall { display: flex; flex-direction: column-reverse; gap: 4px; }
.wall-course { display: flex; gap: 4px; }
.wall-course span { flex-basis: 0; height: 14px; border-radius: 1px; background: var(--on-dark); opacity: .07; }
.wall-course span.laid { opacity: var(--shade); animation: brick-lay 420ms cubic-bezier(.22, .61, .36, 1) both; }
.wall-course span.no-anim { animation: none; }
@keyframes brick-lay { from { opacity: 0; transform: translateY(-14px); } }
@media (max-width: 560px) { .wall-course span { height: 11px; } }
@media (prefers-reduced-motion: reduce) { .wall-course span.laid { animation: none; } }
/* Form panel on the two-column enquiry (inner pages; Mark, 20 Oct): a slightly darker box groups the
   form into one task beside the contact details (common region). Site's cut top-right corner, no
   outline. align-content:start stops the grid sharing the taller left column's spare height between
   its rows (that was the big gap under the brick wall). Homepage's centred focus form stays open. */
.enquire:not(.enquire-focus) form.convo { align-self: start; align-content: start; background: #232629; padding: clamp(24px, 3.4vw, 44px); clip-path: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%); }
/* inside the panel the five answer tiles still fit on one row on desktop */
.enquire:not(.enquire-focus) .choices-ico { grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 8px; }
.enquire:not(.enquire-focus) .choices-ico label { padding-inline: 6px; }
/* while a service photo shows on hover, ALL the descriptions fade, not just that row's, so the photo
   never sits on top of the next row's words (Mark, 20 Oct) */
.v3-ix-sum { transition: opacity 300ms ease; }
/* (Mark: "just fade them slightly so they are not so prominent") the other rows dim, the hovered row's own
   words stay hidden under its photo */
@media (hover: hover) { .v3-index ul:has(li:hover) li:not(:hover) .v3-ix-sum { opacity: .3; } }
.cuts .v3-ix-img { clip-path: polygon(0 0, calc(100% - var(--cut-img)) 0, 100% var(--cut-img), 100% 100%, 0 100%); }
.preview-note { margin: 14px 0 0; font-size: 15px; color: var(--on-dark); max-width: 34em; }
/* honeypot (handleLead's contact_ref): off-screen, never display:none (some bots skip hidden fields) */
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.drop-note { margin: 8px 0 0; font-size: 14px; color: var(--on-dark); }
.drop-note:empty { display: none; }
/* platform enquiry states (rendered by the platform's tenants/cloudnine/render.ts after the
   zero-JS post): the thank-you panel replaces the form; the error line sits above it */
.convo-sent { padding: clamp(24px, 3.4vw, 44px); background: #232629; color: var(--on-dark); clip-path: polygon(0 0, calc(100% - 28px) 0, 100% 28px, 100% 100%, 0 100%); }
.convo-sent p { margin: 0; color: var(--on-dark-muted); }
.convo-sent .convo-sent-h { margin: 0 0 10px; font-size: clamp(20px, 2vw, 26px); color: var(--on-dark); }
.enquire-focus .convo-sent { text-align: center; }
.convo-error { margin: 0 0 18px; color: var(--on-dark); font-weight: 600; }
/* upload refused (too big): said INSIDE the zone's space, not as a small grey line under it */
.drop.is-error { border-style: solid; border-color: var(--on-dark); }
.drop-note { margin: 10px 0 0; padding: 12px 14px; font-size: 15px; font-weight: 600; line-height: 1.45; color: var(--on-dark); background: rgba(236,238,239,.09); border-radius: 2px; }
.drop.is-busy { opacity: .6; cursor: progress; }
/* the enquiry went but the file didn't (server-side refusal): said on the thank-you, with the limit */
.convo-sent .convo-sent-file { margin: 16px 0 0; padding: 12px 14px; font-size: 15px; font-weight: 600; line-height: 1.45; color: var(--on-dark); background: rgba(236,238,239,.09); border-radius: 2px; text-align: left; }
/* socials beside the enquiry form: spaced like the footer's, not a single space apart (Mark, 20 Oct) */
.enquire .addr.social { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 24px; }

/* ═══ Mark's phone check, 20 Oct (MOBILE-FIXES.md) ═══════════════════════════════════════════════════ */

/* 7b. inline CTA after the work (all sizes) */
.inline-cta { margin-top: 48px; padding: clamp(24px, 3.4vw, 40px); background: var(--graphite); color: var(--on-dark); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 18px 32px; }
.cuts .inline-cta { clip-path: polygon(0 0, calc(100% - var(--cut-ui) * 2) 0, 100% calc(var(--cut-ui) * 2), 100% 100%, 0 100%); }
.inline-cta-h { margin: 0; font-size: clamp(20px, 2vw, 26px); color: var(--on-dark); line-height: 1.25; }
.f-hanken .inline-cta-h { font-family: 'Hanken Grotesk', 'Archivo', system-ui, sans-serif; font-weight: 500; letter-spacing: -0.02em; }
.inline-cta .ctas { display: flex; flex-wrap: wrap; gap: 12px; margin: 0; }

/* 5a. slide caption wraps tight (it is a <b>, so the h3 fix didn't reach it) */
.sl-slide figcaption b { line-height: 1.25; }

/* 8. photo-band caption: a dark fade under it, so it reads over a light, busy photo (all sizes) */
.band::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 45%; background: linear-gradient(to top, rgba(29,31,33,.82), rgba(29,31,33,0)); pointer-events: none; }
.band figcaption { z-index: 1; text-shadow: 0 1px 2px rgba(0,0,0,.5), 0 1px 12px rgba(0,0,0,.45); }

/* 7a. phone call bar (hidden above 760px) */
.mbar { display: none; }

@media (max-width: 760px) {
	/* 1. the hero's screen crop marks frame the whole phone screen, so their corners land on the
	   logo, Menu, title and button: on phones there is no framed composition left, so they go */
	.v3-hero .marks-screen { display: none; }

	/* 2. one phone rhythm: 64px a section (desktop's 104–140px left screen-tall gaps) */
	.stack .wrap, .prog .wrap, .words-big .wrap, .enquire .wrap, .why .wrap, .feat .wrap { padding-block: 64px; }
	.enquire-focus .wrap { padding-block: 64px; }
	.v3-statement { padding-block: 64px 56px; }
	.v3-index { padding-block: 40px 56px; }
	.v3-work { padding-block: 40px 64px; }
	.bprog .intro { margin-bottom: 36px; }
	.stack-h + .tiles, .stack-h + .svc-cards, .stack-h + .partner-cards, .stack-h + .people, .stack-h + .teams, .stack-h + .sl { margin-top: 28px; }

	/* 5. slider photos: portrait on phones, so the photo owns the screen (next slide still peeks) */
	.sl-img img { aspect-ratio: 4 / 5; }

	/* 6. credentials: every item stacks the same way (icon or FMB badge on top, then title, text),
	   so all four share one left edge */
	.creds .has-mark { grid-template-columns: 1fr; gap: 12px; }
	.creds li:has(> .cred-ico) { padding-left: 0; }
	.creds .cred-ico { position: static; display: block; margin: 0 0 10px; }

	/* 10. menu phone: space above, a full-width tap target, room for the phone's home bar */
	.panel { overflow-y: auto; padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
	.panel .panel-tel { margin-top: auto; padding-top: 32px; }
	.panel .panel-tel.btn { display: flex; align-items: center; justify-content: center; margin-top: 32px; padding: 16px 20px; font-size: 18px; }
	.panel nav + .panel-tel.btn { margin-top: 32px; }

	/* 7a. phone call bar */
	.mbar { display: grid; grid-template-columns: 1fr 1.4fr; position: fixed; left: 0; right: 0; bottom: 0; z-index: 30; background: var(--graphite); border-top: 1px solid var(--graphite-line); padding-bottom: env(safe-area-inset-bottom); transform: translateY(110%); transition: transform 300ms ease; }
	.mbar.on { transform: none; }
	.mbar a { display: flex; align-items: center; justify-content: center; min-height: 56px; font-weight: 600; font-size: 16px; text-decoration: none; color: var(--on-dark); }
	.mbar .mbar-go { background: var(--on-dark); color: var(--graphite); }
	body { padding-bottom: calc(56px + env(safe-area-inset-bottom)); }

	/* 7b. inline CTA stacks on phones */
	.inline-cta { flex-direction: column; align-items: stretch; }
	.inline-cta .ctas .btn { flex: 1 1 100%; text-align: center; }

	/* 3 + 4. programme on phones: each bar fills as it passes up the screen; a TODAY flag rides the
	   fill edge of the furthest bar (site.js) */
	.bp-flag { position: absolute; left: 0; width: 2px; background: var(--ink); opacity: 0; pointer-events: none; z-index: 3; transition: opacity .25s ease; }
	.bp-flag span { position: absolute; top: 50%; transform: translateY(-50%); font-size: 10px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
	.bp-flag:not(.inside) span { left: 8px; color: var(--ink); }
	.bp-flag.inside span { right: 8px; color: var(--paper); }
}
@media (prefers-reduced-motion: reduce) { .mbar { transition: none; } }

/* platform rule 17: token override, beats the platform :root regardless of load order */
html:root {
	--paper: #F5F6F6;
	--white: #FFFFFF;
	--ink: #1D1F21;
	--graphite: #2B2E31;
	--graphite-line: #42464B;
	--silver: #B9BDC1;
	--hairline: #D9DCDE;
	--muted: #5A5F64;
	--on-dark: #ECEEEF;
	--on-dark-muted: #A9AEB3;
	--wide: 125%;
	--gutter: 24px;
}
