@charset "UTF-8";
/* ==========================================================================
   MARÈS ARQUITECTURA — Design system
   Style:  Swiss Modernism structure, "Warm Mediterranean" art direction
   Author: built for a Mallorca reform + new-build practice

   Contents
   01  Fonts & metric-matched fallbacks
   02  Tokens
   03  Themes (light / dark / manual)
   04  Reset & base
   05  Typography
   06  Layout: container, grid, section
   07  Motion primitives
   08  Header, navigation, language switch
   09  Buttons & links
   10  Hero  ·  10b  Hero stage (scroll-linked expanding video)
   11  Index heading (the signature element)
   12  Projects: cards, index rows, filters
   13  Editorial blocks: figure, quote, stats, process, specs
   14  Accordion
   15  Forms
   16  Footer
   17  Utilities
   18  Reduced motion, forced colours, print
   ========================================================================== */

/* 01 — Fonts ------------------------------------------------------------- */
/* Metric-matched fallbacks. These keep the pre-swap layout the same size as
   the webfont, which is what actually removes the heading reflow (CLS). */
@font-face {
  font-family: "Archivo Fallback";
  src: local("Arial");
  size-adjust: 103%;
  ascent-override: 90%;
  descent-override: 22%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Bodoni Moda Fallback";
  src: local("Didot"), local("Georgia"), local("Times New Roman");
  size-adjust: 92%;
  ascent-override: 100%;
  descent-override: 26%;
  line-gap-override: 0%;
}

/* 02 — Tokens ------------------------------------------------------------ */
:root {
  /* Type families */
  /* Bodoni Moda: a didone with a real optical-size axis, so hairlines refine
     as the type grows. The canonical voice of architecture monographs.
     Archivo for text — a grotesque with more warmth than the usual default. */
  --font-display: "Bodoni Moda", "Bodoni Moda Fallback", Didot, Georgia, serif;
  --font-sans: "Archivo", "Archivo Fallback", system-ui, -apple-system, "Segoe UI", sans-serif;

  /* Fluid type scale — 1.20 at 375px rising to 1.333 at 1440px.
     Body never drops below 16px, so iOS never auto-zooms a form field. */
  --step--2: clamp(0.6875rem, 0.67rem + 0.08vw, 0.75rem);
  --step--1: clamp(0.8125rem, 0.79rem + 0.10vw, 0.875rem);
  --step-0:  clamp(1rem, 0.98rem + 0.09vw, 1.0625rem);
  --step-1:  clamp(1.125rem, 1.07rem + 0.24vw, 1.3125rem);
  --step-2:  clamp(1.3125rem, 1.20rem + 0.48vw, 1.6875rem);
  --step-3:  clamp(1.5rem, 1.29rem + 0.90vw, 2.1875rem);
  --step-4:  clamp(1.75rem, 1.36rem + 1.66vw, 3rem);
  --step-5:  clamp(2rem, 1.34rem + 2.82vw, 4.0625rem);
  --step-6:  clamp(2.375rem, 1.28rem + 4.67vw, 5.75rem);
  --step-7:  clamp(2.75rem, 0.96rem + 7.65vw, 8rem);

  /* Spacing — 4/8 rhythm, spacious end of the scale (density 3/10) */
  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs:  0.75rem;
  --space-s:   1rem;
  --space-m:   1.5rem;
  --space-l:   2rem;
  --space-xl:  3rem;
  --space-2xl: 4rem;
  --space-3xl: 6rem;
  --space-4xl: 8rem;
  --space-5xl: 12rem;
  --space-section: clamp(3.25rem, 6vw, 6.5rem);

  /* Layout */
  --measure: 68ch;
  --container: 84rem;      /* 1344px */
  --container-wide: 96rem; /* 1536px */
  --gutter: clamp(1.25rem, 4vw, 4rem);
  --cols: 12;

  /* Motion */
  --dur-fast: 160ms;
  --dur: 280ms;
  --dur-slow: 480ms;
  --dur-reveal: 900ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-in: cubic-bezier(0.55, 0, 1, 0.45);

  /* Elevation — a fixed 3-step scale. No ad-hoc shadow values anywhere. */
  --shadow-1: 0 1px 2px rgb(23 23 23 / 0.04), 0 2px 8px rgb(23 23 23 / 0.04);
  --shadow-2: 0 2px 4px rgb(23 23 23 / 0.05), 0 8px 24px rgb(23 23 23 / 0.07);
  --shadow-3: 0 4px 8px rgb(23 23 23 / 0.06), 0 20px 56px rgb(23 23 23 / 0.11);

  --radius-0: 0;
  --radius-1: 2px;
  --radius-2: 4px;

  --header-h: 4.5rem;
  --z-header: 100;
  --z-panel: 200;
  --z-skip: 300;
  --z-cursor: 400;
  --z-preloader: 500;
}

/* 03 — Themes ------------------------------------------------------------ */
/* Every colour is defined on bare :root first, so a viewer whose OS is set to
   "no preference" always gets a complete palette. */
:root {
  color-scheme: light;

  --ground:      #FBF8F2;  /* sun-warmed sand */
  --ground-2:    #F5EDE0;  /* alternating band */
  --ground-3:    #EDE0CC;  /* deepest light band */
  --surface:     #FFFFFF;
  --ink:         #2A241D;  /* warm umber, 14.5:1 on ground */
  --ink-soft:    #5C5145;  /* 7.3:1 */
  --ink-faint:   #6E6053;  /* 5.7:1 on --ground, 4.7:1 on --ground-3 (worst case) */
  --accent:      #A94F31;  /* terracotta, 5.2:1 on ground */
  --accent-ink:  #FFFFFF;
  --accent-soft: #F7E7DE;
  --olive:       #4E6046;  /* support tone: rules, icons, quiet marks */
  --rule:        #E0D3BE;
  --rule-strong: #9C8A6E;  /* 3.4:1 on --surface: UI boundaries need 3:1 */
  --danger:      #A3231B;
  --danger-soft: #FBEDEC;
  --success:     #3F6B45;
  --success-soft:#EDF3EE;
  --scrim:       rgb(42 36 29 / 0.55);
  --inverse-ground: #2A241D;
  --inverse-ink:    #FBF8F2;
  /* Accent as it reads ON the inverse ground; flips opposite to --accent. */
  --inverse-accent: #E08A63;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground:      #14110D;
    --ground-2:    #1C1813;
    --ground-3:    #241F18;
    --surface:     #1A1611;
    --ink:         #F5EFE4;
    --ink-soft:    #BCAF9C;
    --ink-faint:   #968875;
    --accent:      #E08A63;
    --accent-ink:  #1C1813;
    --accent-soft: #2C2018;
    --olive:       #8FA862;
    --rule:        #383127;
    --rule-strong: #7A6E5C;
    --danger:      #E4837B;
    --danger-soft: #2A1917;
    --success:     #8FBE97;
    --success-soft:#17231A;
    --scrim:       rgb(0 0 0 / 0.7);
    --inverse-ground: #F5EFE4;
    --inverse-ink:    #14110D;
    --inverse-accent: #A94F31;
    --shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow-2: 0 2px 4px rgb(0 0 0 / 0.4), 0 8px 24px rgb(0 0 0 / 0.36);
    --shadow-3: 0 4px 8px rgb(0 0 0 / 0.4), 0 20px 56px rgb(0 0 0 / 0.5);
  }
}

/* Must stay token-for-token identical to the @media block above. CSS cannot
   share one declaration list between a media query and an attribute
   selector, so build/check.py asserts the two are in sync. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --ground:      #14110D;
  --ground-2:    #1C1813;
  --ground-3:    #241F18;
  --surface:     #1A1611;
  --ink:         #F5EFE4;
  --ink-soft:    #BCAF9C;
  --ink-faint:   #968875;
  --accent:      #E08A63;
  --accent-ink:  #1C1813;
  --accent-soft: #2C2018;
  --olive:       #8FA862;
  --rule:        #383127;
  --rule-strong: #7A6E5C;
  --danger:      #E4837B;
  --danger-soft: #2A1917;
  --success:     #8FBE97;
  --success-soft:#17231A;
  --scrim:       rgb(0 0 0 / 0.7);
  --inverse-ground: #F5EFE4;
  --inverse-ink:    #14110D;
  --inverse-accent: #A94F31;
  --shadow-1: 0 1px 2px rgb(0 0 0 / 0.4);
  --shadow-2: 0 2px 4px rgb(0 0 0 / 0.4), 0 8px 24px rgb(0 0 0 / 0.36);
  --shadow-3: 0 4px 8px rgb(0 0 0 / 0.4), 0 20px 56px rgb(0 0 0 / 0.5);
}

/* 04 — Reset & base ------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
  scrollbar-gutter: stable;
  /* clip, not hidden: `overflow: hidden` would make this a scroll container
     and break `position: sticky` in the hero stage. */
  overflow-x: clip;
}

body {
  font-family: var(--font-sans);
  font-size: var(--step-0);
  font-weight: 400;
  line-height: 1.65;
  color: var(--ink);
  background: var(--ground);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  min-height: 100dvh;
}

body[data-menu-open="true"] { overflow: hidden; }

img, svg, video, canvas { display: block; max-width: 100%; }
img { height: auto; background: var(--ground-2); }

input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

ul, ol { list-style: none; padding: 0; }

a { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.22em; }

::selection { background: var(--accent); color: var(--accent-ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-1);
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  inset-inline-start: var(--space-s);
  top: var(--space-s);
  z-index: var(--z-skip);
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--ground);
  font-size: var(--step--1);
  letter-spacing: 0.04em;
  transform: translateY(-160%);
  transition: transform var(--dur) var(--ease-out);
}
.skip-link:focus { transform: translateY(0); }

/* 05 — Typography -------------------------------------------------------- */
.display, h1, h2, h3 {
  font-family: var(--font-display);
  font-optical-sizing: auto;   /* the whole point of choosing a variable didone */
  font-weight: 500;
  line-height: 0.98;
  letter-spacing: -0.03em;
  text-wrap: balance;
  hanging-punctuation: first last;
}

h1 { font-size: var(--step-6); }
h2 { font-size: var(--step-4); line-height: 1.02; }
h3 { font-size: var(--step-2); line-height: 1.14; letter-spacing: -0.018em; }

h4, h5, h6 {
  font-family: var(--font-sans);
  font-size: var(--step-0);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.005em;
}

p { text-wrap: pretty; }
p + p { margin-top: 1em; }

.t-xl    { font-size: var(--step-5); }
.t-lg    { font-size: var(--step-3); }

.lede {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 46ch;
  text-wrap: pretty;
}

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: var(--space-m); }
.prose p { color: var(--ink-soft); }
.prose strong { color: var(--ink); font-weight: 600; }

/* Small caps label — used for eyebrows, numbers, meta rows */
.eyebrow {
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

.num { font-variant-numeric: tabular-nums lining-nums; }

/* 06 — Layout ------------------------------------------------------------ */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--wide { max-width: var(--container-wide); }
.container--narrow { max-width: 60rem; }

.section { padding-block: var(--space-section); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 5rem); }
.section--band { background: var(--ground-2); }
.section--deep { background: var(--ground-3); }
.section--inverse {
  background: var(--inverse-ground);
  color: var(--inverse-ink);
}
.section--inverse .eyebrow,
.section--inverse .lede,
.section--inverse .prose p { color: color-mix(in oklab, var(--inverse-ink) 68%, transparent); }
.section--inverse .rule { background: color-mix(in oklab, var(--inverse-ink) 22%, transparent); }

.grid {
  display: grid;
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--space-m) var(--gutter);
}

/* Column helpers, mobile-first: everything is full width until 48rem. */
.col-full { grid-column: 1 / -1; }
@media (min-width: 48rem) {
  /* Longhands, never the `grid-column` shorthand.
     `grid-column: span 6` also sets grid-column-end:auto, so a later
     `.start-7` rule would override the start and leave the item spanning a
     SINGLE track — a 1/12-wide column of vertical text. Setting start and end
     separately lets .col-N and .start-N compose correctly.
     `grid-column-start: auto` is required to undo .col-full's start:1. */
  .col-2  { grid-column-start: auto; grid-column-end: span 2; }
  .col-3  { grid-column-start: auto; grid-column-end: span 3; }
  .col-4  { grid-column-start: auto; grid-column-end: span 4; }
  .col-5  { grid-column-start: auto; grid-column-end: span 5; }
  .col-6  { grid-column-start: auto; grid-column-end: span 6; }
  .col-7  { grid-column-start: auto; grid-column-end: span 7; }
  .col-8  { grid-column-start: auto; grid-column-end: span 8; }
  .col-9  { grid-column-start: auto; grid-column-end: span 9; }
  .col-10 { grid-column-start: auto; grid-column-end: span 10; }

  /* Full range: an undefined .start-N silently drops the placement. */
  .start-2  { grid-column-start: 2; }
  .start-3  { grid-column-start: 3; }
  .start-4  { grid-column-start: 4; }
  .start-5  { grid-column-start: 5; }
  .start-6  { grid-column-start: 6; }
  .start-7  { grid-column-start: 7; }
  .start-8  { grid-column-start: 8; }
  .start-9  { grid-column-start: 9; }
  .start-10 { grid-column-start: 10; }
  .start-11 { grid-column-start: 11; }
}

.stack > * + * { margin-top: var(--flow, var(--space-m)); }
.cluster { display: flex; flex-wrap: wrap; gap: var(--space-s); align-items: center; }

.rule {
  height: 1px;
  background: var(--rule);
  border: 0;
  width: 100%;
}

/* 07 — Motion primitives ------------------------------------------------- */
/* Everything animates transform/opacity only, so it stays on the compositor
   and never triggers layout. */
/* Reveals only ever hide when scripting is confirmed live: the .js class is
   set by the inline head script. Without it — no JS, a script error, a
   blocked bundle — every element renders in its final state. Content must
   never depend on an animation running. */
.reveal {
  transition:
    opacity var(--dur-reveal) var(--ease-out) var(--delay, 0ms),
    transform var(--dur-reveal) var(--ease-out) var(--delay, 0ms);
}
.js .reveal:not(.is-in) {
  opacity: 0;
  transform: translate3d(0, 1.75rem, 0);
}
.reveal.is-in { opacity: 1; transform: none; }

/* Staggered children: --i is set inline by the generator, not by JS. */
.reveal[style*="--i"] { --delay: calc(var(--i, 0) * 70ms); }

/* Hairline that draws itself left-to-right */
.reveal-rule { transition: transform var(--dur-slow) var(--ease-out) var(--delay, 0ms); }
.js .reveal-rule:not(.is-in) { transform: scaleX(0); transform-origin: left center; }

/* Image mask reveal — a curtain lifting off the picture */
.reveal-img { overflow: hidden; }
.reveal-img > img,
.reveal-img > picture > img {
  transition:
    clip-path var(--dur-reveal) var(--ease-out) var(--delay, 0ms),
    transform 1400ms var(--ease-out) var(--delay, 0ms);
}
.js .reveal-img:not(.is-in) > img,
.js .reveal-img:not(.is-in) > picture > img {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.08);
}


/* Key titles rise line by line from behind a mask. The lines are built by JS
   after layout — where a heading breaks is not knowable server-side — so
   without JS the heading is simply ordinary text. */
.tline { display: block; overflow: hidden; }
.tline__i { display: block; will-change: transform; }
.js .reveal-lines .tline__i {
  transition: transform 900ms var(--ease-out) calc(var(--i, 0) * 90ms);
}
.js .reveal-lines:not(.is-in) .tline__i { transform: translate3d(0, 105%, 0); }

/* The figure counts, then its unit lands. `white-space: pre` keeps the space
   in " %" that an inline-block would otherwise collapse. */
.stat__num { font-variant-numeric: tabular-nums lining-nums; }
.stat__suffix {
  display: inline-block;
  white-space: pre;
  transition: opacity 340ms var(--ease-out), transform 340ms var(--ease-out);
}
.js .stat__value:not(.is-done) .stat__suffix {
  opacity: 0;
  transform: translate3d(-0.3em, 0, 0);
}

/* Scroll-driven parallax. Runs entirely off the main thread where supported;
   silently does nothing where it isn't. No JS, no scroll listener. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 48rem) {
    .parallax > img {
      animation: parallax-drift linear both;
      animation-timeline: view();
      animation-range: entry 0% exit 100%;
      will-change: transform;
    }
    @keyframes parallax-drift {
      from { transform: translate3d(0, -4%, 0) scale(1.10); }
      to   { transform: translate3d(0, 4%, 0) scale(1.10); }
    }
  }
}

/* Cross-document view transitions (progressive enhancement) */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vt-out 220ms var(--ease-in) both;
  }
  ::view-transition-new(root) {
    animation: vt-in 420ms var(--ease-out) both;
  }
  @keyframes vt-out { to { opacity: 0; } }
  @keyframes vt-in  { from { opacity: 0; transform: translate3d(0, 1.25rem, 0); } }
}

/* 08 — Header ------------------------------------------------------------ */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  height: var(--header-h);
  display: flex;
  align-items: center;
  transition:
    transform var(--dur) var(--ease-out),
    background-color var(--dur) var(--ease-out),
    border-color var(--dur) var(--ease-out);
  border-bottom: 1px solid transparent;
}
.site-header[data-scrolled="true"] {
  background: color-mix(in oklab, var(--ground) 86%, transparent);
  border-bottom-color: var(--rule);
}
@supports (backdrop-filter: blur(1px)) {
  .site-header[data-scrolled="true"] { backdrop-filter: blur(14px) saturate(1.4); }
}
.site-header[data-hidden="true"] { transform: translate3d(0, -100%, 0); }
body[data-menu-open="true"] .site-header { transform: none; }

.header__inner {
  width: 100%;
  max-width: var(--container-wide);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 2.75rem;      /* hit area, not visual height */
  text-decoration: none;
  color: var(--ink);
}
.brand svg { width: 1.375rem; height: 1.375rem; color: var(--ink); flex: none; }
.brand__name {
  font-family: var(--font-sans);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
}
.brand__name span { color: var(--ink-faint); font-weight: 400; }

.nav { display: none; }
@media (min-width: 62rem) {
  .nav { display: flex; align-items: center; gap: clamp(1rem, 2.2vw, 2.25rem); }
}
.nav a {
  position: relative;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  color: var(--ink-soft);
  padding-block: 0.5rem;
  transition: color var(--dur-fast) var(--ease-out);
}
.nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0.15rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform var(--dur) var(--ease-out);
}
.nav a:hover { color: var(--ink); }
.nav a:hover::after { transform: scaleX(1); transform-origin: left center; }
.nav a[aria-current="page"] { color: var(--ink); }
.nav a[aria-current="page"]::after { transform: scaleX(1); background: var(--accent); }

.header__actions { display: flex; align-items: center; gap: var(--space-xs); }

/* Language switch — a real one: each option is a link to a translated URL. */
.lang {
  display: none;
  align-items: center;
  gap: 0.125rem;
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
@media (min-width: 48rem) { .lang { display: inline-flex; } }
.lang a {
  padding: 0.4rem 0.5rem;
  text-decoration: none;
  color: var(--ink-faint);
  transition: color var(--dur-fast) var(--ease-out);
  min-height: 2.75rem;
  min-width: 2.75rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.lang a:hover { color: var(--ink); }
.lang a[aria-current="true"] { color: var(--ink); }
.lang span[aria-hidden] { color: var(--rule-strong); }

.icon-btn {
  width: 2.75rem;
  height: 2.75rem;
  display: inline-grid;
  place-items: center;
  color: var(--ink-soft);
  border-radius: var(--radius-2);
  transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.icon-btn:hover { color: var(--ink); background: var(--ground-2); }
.icon-btn svg { width: 1.125rem; height: 1.125rem; }

.theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-sun  { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .icon-sun  { display: none; }
}

.menu-btn { display: inline-grid; }
@media (min-width: 62rem) { .menu-btn { display: none; } }
.menu-btn__bars { width: 1.125rem; height: 0.75rem; position: relative; }
.menu-btn__bars i {
  position: absolute; left: 0; right: 0; height: 1.5px; background: currentColor;
  transition: transform var(--dur) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.menu-btn__bars i:nth-child(1) { top: 0; }
.menu-btn__bars i:nth-child(2) { top: 50%; margin-top: -0.75px; }
.menu-btn__bars i:nth-child(3) { bottom: 0; }
.menu-btn[aria-expanded="true"] i:nth-child(1) { transform: translateY(0.36rem) rotate(45deg); }
.menu-btn[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.menu-btn[aria-expanded="true"] i:nth-child(3) { transform: translateY(-0.36rem) rotate(-45deg); }

/* Mobile menu panel */
.menu-panel {
  position: fixed;
  inset: 0;
  z-index: var(--z-panel);
  background: var(--ground);
  padding: calc(var(--header-h) + var(--space-l)) var(--gutter) var(--space-2xl);
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, -1.5rem, 0);
  transition:
    opacity var(--dur) var(--ease-out),
    transform var(--dur) var(--ease-out),
    visibility 0s linear var(--dur);
}
.menu-panel[data-open="true"] {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition-delay: 0s;
}
@media (min-width: 62rem) { .menu-panel { display: none; } }

.menu-panel__list { border-top: 1px solid var(--rule); }
.menu-panel__list a {
  display: flex;
  align-items: baseline;
  gap: var(--space-s);
  padding: var(--space-m) 0;
  border-bottom: 1px solid var(--rule);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--step-3);
  letter-spacing: -0.02em;
  text-decoration: none;
  opacity: 0;
  transform: translate3d(0, 0.75rem, 0);
}
.menu-panel[data-open="true"] .menu-panel__list a {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-slow) var(--ease-out) calc(80ms + var(--i, 0) * 55ms),
    transform var(--dur-slow) var(--ease-out) calc(80ms + var(--i, 0) * 55ms);
}
.menu-panel__list a .eyebrow { font-size: var(--step--2); }
.menu-panel__foot { margin-top: auto; padding-top: var(--space-xl); }

/* 09 — Buttons & links --------------------------------------------------- */
.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--ground);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 3rem;
  padding: 0.875rem 1.75rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-1);
  overflow: hidden;
  isolation: isolate;
  transition: color var(--dur) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
/* Wipe fill — transform-only, so no repaint of the whole button */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: bottom center;
  transition: transform var(--dur) var(--ease-out);
}
.btn:hover::before { transform: scaleY(1); }
.btn:hover { color: var(--accent-ink); }
.btn:active { transform: translateY(1px); }
.btn svg { width: 1rem; height: 1rem; flex: none; }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
}
.btn--ghost:hover { color: var(--accent-ink); }

.btn--light { --btn-bg: var(--ground); --btn-fg: var(--ink); }

.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
  cursor: not-allowed;
}

/* Arrow link — the workhorse tertiary action */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-height: 2.75rem;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  padding-block: 0.35rem;
}
.link-arrow .line {
  width: 1.75rem;
  height: 1px;
  background: var(--accent);
  transform-origin: left center;
  transition: transform var(--dur) var(--ease-out);
}
.link-arrow:hover .line { transform: scaleX(1.45); }
.link-arrow:hover { color: var(--accent); }

/* 10 — Hero -------------------------------------------------------------- */
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-l);
  align-items: baseline;
}
.hero__media {
  position: relative;
  margin-top: clamp(2rem, 5vw, 4rem);
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--ground-2);
}
@media (min-width: 62rem) { .hero__media { aspect-ratio: 21 / 9; } }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }

@keyframes scroll-hint {
  0%   { transform: translateY(-100%); }
  60%  { transform: translateY(250%); }
  100% { transform: translateY(250%); }
}

/* 09b — Reactive cursor ---------------------------------------------------- */
/* Only ever exists for a primary pointer that can hover, with motion allowed.
   Touch, stylus, keyboard-only and reduced-motion never see it, and it is
   `pointer-events: none` so it can never eat a click. */
.cursor { display: none; }

html.has-cursor,
html.has-cursor body { cursor: none; }
/* Text affordances are not decoration: the I-beam stays. */
html.has-cursor input,
html.has-cursor textarea,
html.has-cursor select,
html.has-cursor [contenteditable] { cursor: auto; }

html.has-cursor .cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-cursor);
  display: grid;
  place-items: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 200ms var(--ease-out);
  will-change: transform;

  /* --ink is the same colour as --inverse-ground in BOTH themes, so a ring
     drawn in --ink is exactly invisible over the hero, the CTA band and the
     footer. Two independent defences: the ring flips to the inverse pair over
     those sections, and it always carries a 1px halo of the opposite tone so
     it survives photographs too. */
  --cursor-ink: var(--ink);
  --cursor-halo: var(--ground);
}
html.has-cursor .cursor[data-invert="true"] {
  --cursor-ink: var(--inverse-ink);
  --cursor-halo: var(--inverse-ground);
}
html.has-cursor .cursor[data-ready="true"] { opacity: 1; }
html.has-cursor .cursor[data-state="field"],
html.has-cursor .cursor[data-hidden="true"] { opacity: 0; }

/* Everything that changes is transform or colour, so state changes stay on
   the compositor and never trigger layout. */
.cursor__ring {
  grid-area: 1 / 1;
  width: 2rem;
  height: 2rem;
  margin: -1rem 0 0 -1rem;
  border: 1px solid var(--cursor-ink);
  border-radius: 50%;
  background: transparent;
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--cursor-halo) 55%, transparent);
  transition:
    transform 320ms var(--ease-out),
    background-color 320ms var(--ease-out),
    border-color 320ms var(--ease-out),
    box-shadow 320ms var(--ease-out);
}
.cursor[data-state="link"] .cursor__ring {
  transform: scale(0.1875);          /* 32px -> 6px */
  background: var(--cursor-ink);
  border-color: var(--cursor-ink);
}
.cursor[data-state="card"] .cursor__ring {
  transform: scale(2.375);           /* 32px -> 76px */
  background: var(--accent);
  border-color: var(--accent);
}

.cursor__label {
  grid-area: 1 / 1;
  margin: -1rem 0 0 -1rem;
  width: 2rem;
  display: grid;
  place-items: center;
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--accent-ink);
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 200ms var(--ease-out), transform 320ms var(--ease-out);
}
.cursor[data-state="card"] .cursor__label { opacity: 1; transform: none; }

/* 10a — Preloader --------------------------------------------------------- */
/* Three independent ways out, because a loading screen that fails to lift is
   a website nobody can read:
     1. It only EXISTS when scripting is confirmed (.js, set inline in <head>).
     2. A CSS animation hides it at 4.5s whether or not any script runs.
     3. The script dismisses it on load, with its own 3.5s hard timeout.
   It also shows once per session, not on all 39 page navigations. */
.preloader {
  position: fixed;
  inset: 0;
  z-index: var(--z-preloader);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.15rem;
  background: var(--inverse-ground);
  color: var(--inverse-ink);
  animation: preloader-safety 4.5s linear forwards;
}
.js .preloader { display: flex; }
:root.preloaded .preloader { display: none; }

.preloader__mark { display: block; width: 3rem; height: 3rem; color: var(--inverse-accent); }
.preloader__mark svg { width: 100%; height: 100%; }
.preloader__mark path {
  fill: none;
  stroke: currentColor;
  stroke-linecap: square;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.preloader__block { stroke-width: 2.5; animation: preloader-draw 1.1s var(--ease-out) forwards; }
.preloader__arch  { stroke-width: 2;   animation: preloader-draw 0.8s 0.34s var(--ease-out) forwards; }

.preloader__word {
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.34em;
  text-indent: 0.34em;          /* offsets the trailing letter-space */
  text-transform: uppercase;
  opacity: 0;
  animation: preloader-rise 0.8s 0.48s var(--ease-out) forwards;
}
.preloader__rule {
  width: min(8rem, 38vw);
  height: 1px;
  background: color-mix(in oklab, var(--inverse-ink) 34%, transparent);
  transform: scaleX(0);
  transform-origin: center;
  animation: preloader-rule 1.5s var(--ease-out) forwards;
}

/* Dismissing cancels the safety animation and hands over to the transition. */
.preloader.is-done {
  animation: none;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-1.5%);
  transition:
    opacity 700ms var(--ease-out),
    transform 700ms var(--ease-out),
    visibility 0s linear 700ms;
}

@keyframes preloader-draw { to { stroke-dashoffset: 0; } }
@keyframes preloader-rule { to { transform: scaleX(1); } }
@keyframes preloader-rise {
  from { opacity: 0; transform: translateY(0.55rem); }
  to   { opacity: 1; transform: none; }
}
@keyframes preloader-safety {
  0%, 92% { opacity: 1; visibility: visible; }
  100%    { opacity: 0; visibility: hidden; }
}

@media (prefers-reduced-motion: reduce) {
  .preloader { display: none !important; }
}

/* 10b — Hero stage: scroll-linked expanding video ------------------------ */
/* Scroll-LINKED, not scroll-jacked. A tall runway pins its contents and maps
   real scroll position onto --p (0 -> 1). Wheel, keyboard, find-in-page and
   the scrollbar all behave exactly as usual. */
@property --p {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

.hero-stage {
  --p: 0;
  /* At rest the frame matches the source footage's 16:9, so nothing is
     cropped and the whole composition reads. Independent width/height values
     produced a portrait box that sliced a vertical strip out of a landscape
     clip. Capped so a short, wide viewport cannot overflow. */
  --w0: 62vw;
  --ar: 0.5625;
  --h0: min(calc(var(--w0) * var(--ar)), 62svh);
  --corner: 4px;
  position: relative;
  /* Runway = height - 100vh, so 220vh is ~1.2 screens of scrolling to open. */
  height: 220vh;
  background: var(--inverse-ground);
}
@media (max-width: 47.99rem) {
  .hero-stage { --w0: 88vw; --corner: 3px; height: 200vh; }
  /* A phone cannot give a 16:9 card enough height to sit the headline on top
     of it, so at rest the copy drops below the card and rises into the centre
     as the video takes the screen. */
  .hero-stage__copy { transform: translateY(calc(21svh * (1 - var(--p)))); }
}

.hero-stage__pin {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-items: center;
  overflow: clip;
  isolation: isolate;
}

/* Poster plate behind everything; fades out as the video takes over. */
.hero-stage__bg { position: absolute; inset: 0; z-index: 0; opacity: calc(1 - var(--p)); }
.hero-stage__bg img { width: 100%; height: 100%; object-fit: cover; }
.hero-stage__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--inverse-ground) 66%, transparent),
    color-mix(in oklab, var(--inverse-ground) 80%, transparent));
}

/* The frame is genuinely sized, not clipped.
   A clip-path over a full-bleed video shows a magnified centre crop at rest
   instead of the whole composition, and a composited video layer punches
   square corners through a clipped parent. Sizing the frame and putting the
   radius on the video element itself fixes both. */
.hero-stage__frame {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  width: calc(var(--w0) + (100vw - var(--w0)) * var(--p));
  height: calc(var(--h0) + (100svh - var(--h0)) * var(--p));
  transform: translate3d(-50%, -50%, 0);
  border-radius: calc(var(--corner) * (1 - var(--p)));
  overflow: hidden;
  background: var(--inverse-ground);
  box-shadow: 0 32px 90px rgb(0 0 0 / calc(0.45 * (1 - var(--p))));
}
.hero-stage__frame video,
.hero-stage__frame > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: inherit;     /* the actual corner fix */
}
.hero-stage__scrim {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--inverse-ground);
  opacity: calc(0.58 - var(--p) * 0.46);
}

.hero-stage__copy {
  position: relative;
  z-index: 2;
  display: grid;
  justify-items: center;
  gap: clamp(0.9rem, 2vw, 1.6rem);
  text-align: center;
  padding-inline: var(--gutter);
  opacity: clamp(0, calc((0.74 - var(--p)) / 0.28), 1);
}
.hero-stage__title {
  display: grid;
  justify-items: center;
  gap: 0.015em;
  color: var(--inverse-ink);
  font-family: var(--font-display);
  font-size: var(--step-7);
  /* 600 rather than the 500 used elsewhere: a didone's hairlines thin out as
     optical sizing kicks in at display sizes, and these sit over moving
     footage where a contrast ratio alone does not guarantee legibility. */
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.035em;
  text-shadow: 0 2px 44px color-mix(in oklab, var(--inverse-ground) 62%, transparent);
}
.hero-stage__word { display: block; will-change: transform; }
.hero-stage__word--a { transform: translate3d(calc(var(--p) * -44vw), 0, 0); }
.hero-stage__word--b { transform: translate3d(calc(var(--p) * 44vw), 0, 0); }

.hero-stage__eyebrow {
  color: color-mix(in oklab, var(--inverse-ink) 82%, transparent);
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}

.hero-stage__cue {
  position: absolute;
  z-index: 2;
  bottom: max(var(--space-l), env(safe-area-inset-bottom));
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  color: color-mix(in oklab, var(--inverse-ink) 74%, transparent);
  font-size: var(--step--2);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  white-space: nowrap;
  opacity: clamp(0, calc((0.26 - var(--p)) / 0.26), 1);
}
.hero-stage__cue i {
  display: block;
  width: 1px;
  height: 2.5rem;
  background: linear-gradient(to bottom, currentColor 35%, transparent);
  position: relative;
  overflow: hidden;
}
.hero-stage__cue i::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  height: 40%;
  background: var(--inverse-accent);
  animation: scroll-hint 2.4s var(--ease-in-out) infinite;
}

/* Header sits over the dark hero: light text, no plate, until the stage ends */
body[data-over-hero="true"] .site-header {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
}
body[data-over-hero="true"] .site-header .brand,
body[data-over-hero="true"] .site-header .nav a,
body[data-over-hero="true"] .site-header .icon-btn,
body[data-over-hero="true"] .site-header .lang a { color: var(--inverse-ink); }
body[data-over-hero="true"] .site-header .brand__name span,
body[data-over-hero="true"] .site-header .lang span[aria-hidden] {
  color: color-mix(in oklab, var(--inverse-ink) 62%, transparent);
}
body[data-over-hero="true"] .site-header .nav a[aria-current="page"]::after { background: var(--inverse-accent); }

@media (prefers-reduced-motion: reduce) {
  /* No runway, no pin, no motion: the video sits full-bleed behind a fixed
     scrim strong enough to keep the headline readable. */
  .hero-stage { height: auto; --p: 1; }
  .hero-stage__pin { position: relative; height: 86svh; }
  .hero-stage__bg { display: none; }
  .hero-stage__frame {
    width: 100%; height: 100%;
    border-radius: 0; box-shadow: none;
  }
  .hero-stage__scrim { opacity: 0.58; }
  .hero-stage__copy { opacity: 1; }
  .hero-stage__word--a, .hero-stage__word--b { transform: none; }
  .hero-stage__cue { display: none; }
}


/* 11 — Index heading (signature element) --------------------------------- */
/* Every major section is numbered like a drawing register. This is the one
   motif carried across all pages. */
.idx {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: auto 1fr;
  align-items: center;
  margin-bottom: var(--space-xl);
  /* It is an <h2>; neutralise the display-heading type so the children rule. */
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: normal;
}
.idx__num {
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.2em;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.idx__label {
  font-family: var(--font-sans);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}
.idx__line { height: 1px; background: var(--rule); grid-column: 1 / -1; }
@media (min-width: 48rem) {
  .idx { grid-template-columns: auto auto 1fr; }
  .idx__line { grid-column: auto; }
}

/* 12 — Projects ---------------------------------------------------------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs);
  padding-block: var(--space-s);
  border-block: 1px solid var(--rule);
}
.filters__btn {
  min-height: 2.75rem;
  padding: 0.5rem 1rem;
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
  border-radius: var(--radius-2);
  transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}
.filters__btn:hover { color: var(--ink); background: var(--ground-2); }
.filters__btn[aria-pressed="true"] { color: var(--accent-ink); background: var(--ink); }
.filters__count { color: var(--ink-faint); font-size: var(--step--1); margin-inline-start: auto; align-self: center; }

.projects {
  display: grid;
  gap: var(--space-xl) var(--gutter);
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) { .projects { grid-template-columns: repeat(2, 1fr); } }

.card {
  container-type: inline-size;
  display: block;
  text-decoration: none;
  color: inherit;
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
.card[hidden] { display: none; }
.card__media {
  position: relative;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: var(--ground-2);
}
.card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--ease-out);
}
.card:hover .card__media img { transform: scale(1.045); }
.card__tag {
  position: absolute;
  left: 0; top: 0;
  padding: 0.45rem 0.85rem;
  background: var(--ground);
  color: var(--ink);
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.card__body {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-s);
  padding-top: var(--space-s);
  border-top: 1px solid var(--rule);
  margin-top: var(--space-s);
  transition: border-color var(--dur) var(--ease-out);
}
.card:hover .card__body { border-top-color: var(--accent); }
.card__title {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--step-2);
  line-height: 1.15;
  letter-spacing: -0.018em;
}
.card__meta { color: var(--ink-faint); font-size: var(--step--1); }
.card__arrow {
  flex: none;
  width: 1.25rem; height: 1.25rem;
  color: var(--ink-faint);
  transition: transform var(--dur) var(--ease-out), color var(--dur) var(--ease-out);
}
.card:hover .card__arrow { transform: translate3d(0.3rem, -0.3rem, 0); color: var(--accent); }
@container (min-width: 30rem) { .card__title { font-size: var(--step-3); } }

/* Featured card spans both columns */
.card--wide { grid-column: 1 / -1; }
.card--wide .card__media { aspect-ratio: 16 / 9; }
@media (min-width: 62rem) { .card--wide .card__media { aspect-ratio: 21 / 9; } }

/* Compact index row — used on the home page */
.row-list { border-top: 1px solid var(--rule); }
.row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-s) var(--space-m);
  padding-block: var(--space-m);
  border-bottom: 1px solid var(--rule);
  text-decoration: none;
  color: inherit;
  position: relative;
  transition: padding-inline var(--dur) var(--ease-out);
}
.row::before {
  content: "";
  position: absolute;
  inset: 0 -1rem;
  background: var(--ground-2);
  opacity: 0;
  transition: opacity var(--dur) var(--ease-out);
  z-index: -1;
}
.row:hover::before { opacity: 1; }
.row:hover { padding-inline: 1rem; }
.row__num { color: var(--accent); font-size: var(--step--2); letter-spacing: 0.12em; font-variant-numeric: tabular-nums; }
.row__title { font-family: var(--font-display); font-weight: 500; font-size: var(--step-2); letter-spacing: -0.018em; }
.row__meta { display: none; color: var(--ink-faint); font-size: var(--step--1); }
@media (min-width: 48rem) {
  .row { grid-template-columns: auto 1fr auto auto; }
  .row__meta { display: block; }
}
.row__arrow { width: 1.1rem; height: 1.1rem; color: var(--ink-faint); transition: transform var(--dur) var(--ease-out), color var(--dur) var(--ease-out); }
.row:hover .row__arrow { transform: translateX(0.35rem); color: var(--accent); }

/* Empty state for the filter */
.empty {
  padding: var(--space-3xl) 0;
  text-align: center;
  color: var(--ink-soft);
}
.empty h3 { margin-bottom: var(--space-xs); }

/* 13 — Editorial blocks -------------------------------------------------- */
figure { margin: 0; }
.figure__media { overflow: hidden; background: var(--ground-2); }
.figure__media img { width: 100%; height: auto; }
figcaption {
  margin-top: var(--space-s);
  padding-top: var(--space-xs);
  border-top: 1px solid var(--rule);
  font-size: var(--step--1);
  color: var(--ink-faint);
  max-width: 42ch;
}

.quote { max-width: 24ch; }
.quote blockquote {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--step-4);
  line-height: 1.14;
  letter-spacing: -0.022em;
  text-wrap: balance;
}
.quote blockquote::before { content: "\201C"; margin-inline-start: -0.4em; }
.quote blockquote::after { content: "\201D"; }
.quote figcaption { border-top-color: var(--accent); max-width: none; }

/* Studio fact panel. The same information the loose label row carried, but
   ruled and labelled, so the column resolves instead of floating. */
.facts { border-top: 1px solid var(--rule); }
.facts > div {
  display: grid;
  gap: 0.3rem;
  padding-block: var(--space-s);
  border-bottom: 1px solid var(--rule);
}
.facts dt {
  font-size: var(--step--2);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.facts dd {
  margin: 0;
  font-size: var(--step-0);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  text-wrap: pretty;
}

/* A lede that has to carry a whole column on its own */
.lede--lead {
  font-size: var(--step-2);
  line-height: 1.42;
  color: var(--ink);
  max-width: 32ch;
  letter-spacing: -0.01em;
}

.stats {
  display: grid;
  gap: var(--space-l) var(--gutter);
  grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 62rem) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stat { border-top: 1px solid var(--rule); padding-top: var(--space-s); }
.stat__value {
  font-family: var(--font-display);
  font-size: var(--step-5);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums lining-nums;
  display: block;
}
.stat__label { margin-top: var(--space-2xs); color: var(--ink-soft); font-size: var(--step--1); }

.steps { counter-reset: step; }
.step {
  display: grid;
  gap: var(--space-xs) var(--space-l);
  padding-block: var(--space-l);
  border-bottom: 1px solid var(--rule);
}
.step:first-child { border-top: 1px solid var(--rule); }
@media (min-width: 48rem) { .step { grid-template-columns: 4rem 1fr 1.2fr; align-items: start; } }
.step__num { color: var(--accent); font-size: var(--step--2); letter-spacing: 0.12em; font-variant-numeric: tabular-nums; padding-top: 0.4em; }
.step__title { font-family: var(--font-display); font-weight: 500; font-size: var(--step-2); letter-spacing: -0.018em; }
.step__body { color: var(--ink-soft); }

.spec { width: 100%; border-collapse: collapse; text-align: left; }
.spec th, .spec td {
  padding: var(--space-s) 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
  font-size: var(--step--1);
}
.spec th {
  font-weight: 500;
  color: var(--ink-faint);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: var(--step--2);
  width: 42%;
  padding-inline-end: var(--space-s);
}
.spec td { color: var(--ink); font-variant-numeric: tabular-nums; }

.gallery { display: grid; gap: var(--gutter); grid-template-columns: 1fr; }
@media (min-width: 48rem) { .gallery { grid-template-columns: repeat(2, 1fr); } }
.gallery__item--full { grid-column: 1 / -1; }

.cta-band { text-align: left; }
.cta-band h2 { max-width: 18ch; }

/* Full-bleed image band — an editorial breather between dense sections.
   Sits outside any container so it runs the full viewport width. */
.bleed {
  position: relative;
  width: 100%;
  overflow: hidden;
  aspect-ratio: 3 / 2;
  background: var(--ground-2);
}
@media (min-width: 48rem) { .bleed { aspect-ratio: 21 / 9; } }
.bleed > img { width: 100%; height: 100%; object-fit: cover; }
.bleed__caption {
  margin: var(--space-s) auto 0;
  max-width: var(--container-wide);
  padding-inline: var(--gutter);
  font-size: var(--step--1);
  color: var(--ink-faint);
}

/* Logo / credential row */
.creds {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-m) var(--space-xl);
  align-items: center;
  color: var(--ink-faint);
  font-size: var(--step--1);
}
.creds li { display: flex; align-items: center; gap: 0.5rem; }
.creds svg { width: 1rem; height: 1rem; color: var(--accent); flex: none; }

/* 14 — Accordion --------------------------------------------------------- */
.acc { border-top: 1px solid var(--rule); }
.acc__item { border-bottom: 1px solid var(--rule); }
.acc__btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-m);
  padding-block: var(--space-m);
  min-height: 3.5rem;
  text-align: left;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: var(--step-2);
  letter-spacing: -0.018em;
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease-out);
}
.acc__btn:hover { color: var(--accent); }
.acc__icon { flex: none; width: 1rem; height: 1rem; position: relative; }
.acc__icon::before, .acc__icon::after {
  content: ""; position: absolute; inset: 50% 0 auto 0;
  height: 1px; background: currentColor;
  transition: transform var(--dur) var(--ease-out);
}
.acc__icon::after { transform: rotate(90deg); }
.acc__btn[aria-expanded="true"] .acc__icon::after { transform: rotate(0deg); }
.acc__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-slow) var(--ease-out);
}
.acc__panel[data-open="true"] { grid-template-rows: 1fr; }
.acc__panel > div { overflow: hidden; }
.acc__panel .prose { padding-bottom: var(--space-m); max-width: 60ch; }

/* 15 — Forms ------------------------------------------------------------- */
.form { display: grid; gap: var(--space-m); }
.form__grid { display: grid; gap: var(--space-m); grid-template-columns: 1fr; }
@media (min-width: 48rem) { .form__grid { grid-template-columns: repeat(2, 1fr); } }

.field { display: grid; gap: 0.4rem; }
.field--full { grid-column: 1 / -1; }

.field label {
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.field .req { color: var(--accent); margin-inline-start: 0.15em; }
.field .hint { font-size: var(--step--1); color: var(--ink-faint); }

.input {
  width: 100%;
  min-height: 3.25rem;
  padding: 0.875rem 1rem;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-1);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
  appearance: none;
}
textarea.input { min-height: 9rem; resize: vertical; line-height: 1.6; }
select.input {
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.15rem) calc(50% + 1px), calc(100% - 0.8rem) calc(50% + 1px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
  padding-inline-end: 2.5rem;
}
.input::placeholder { color: var(--ink-faint); opacity: 1; }
.input:hover { border-color: var(--ink-faint); }
.input:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 22%, transparent);
}
.input[aria-invalid="true"] {
  border-color: var(--danger);
  background: var(--danger-soft);
}
.input[aria-invalid="true"]:focus-visible {
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--danger) 22%, transparent);
}
.input:disabled { opacity: 0.5; cursor: not-allowed; }
.input[readonly] { background: var(--ground-2); border-style: dashed; }

.field__error {
  display: none;
  align-items: center;
  gap: 0.4rem;
  font-size: var(--step--1);
  color: var(--danger);
}
.field__error svg { width: 0.95rem; height: 0.95rem; flex: none; }
.field[data-invalid="true"] .field__error { display: flex; }

/* Choice chips — budget / timeline bands */
.chips { display: flex; flex-wrap: wrap; gap: var(--space-2xs); }
.chips input { position: absolute; opacity: 0; pointer-events: none; }
.chips label {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0.55rem 1.1rem;
  font-size: var(--step--1);
  font-weight: 400;
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-1);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.chips label:hover { border-color: var(--ink-faint); background: var(--ground-2); }
.chips input:checked + label {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--ground);
  font-weight: 500;
}
.chips input:focus-visible + label {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Multi-step enquiry */
.steps-bar { display: grid; gap: var(--space-2xs); grid-auto-flow: column; grid-auto-columns: 1fr; margin-bottom: var(--space-l); }
.steps-bar li { display: grid; gap: 0.5rem; }
.steps-bar i {
  display: block; height: 2px; background: var(--rule);
  transform-origin: left center;
  transition: background-color var(--dur) var(--ease-out);
}
.steps-bar span { font-size: var(--step--2); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-faint); }
.steps-bar li[data-state="done"] i,
.steps-bar li[data-state="current"] i { background: var(--accent); }
.steps-bar li[data-state="current"] span { color: var(--ink); }

.fieldset { border: 0; padding: 0; margin: 0; display: grid; gap: var(--space-m); }
.fieldset legend { font-size: var(--step-1); font-family: var(--font-display); font-weight: 500; letter-spacing: -0.018em; margin-bottom: var(--space-2xs); }
.fieldset[hidden] { display: none; }

.form__foot { display: flex; flex-wrap: wrap; gap: var(--space-s); align-items: center; justify-content: space-between; }

.form__status {
  display: none;
  padding: var(--space-s) var(--space-m);
  border-inline-start: 2px solid currentColor;
  font-size: var(--step--1);
}
.form__status[data-state="error"]   { display: block; color: var(--danger); background: var(--danger-soft); }
.form__status[data-state="success"] { display: block; color: var(--success); background: var(--success-soft); }
.form__status-item { display: flex; gap: 0.6rem; align-items: flex-start; }
.form__status-item[hidden] { display: none; }
.form__status svg { width: 1.05rem; height: 1.05rem; flex: none; margin-top: 0.15em; }

/* Checkbox — shares the .input class so validation picks it up, but resets
   the box geometry the text-input styles would otherwise impose. */
.input--check {
  width: 1.15rem;
  height: 1.15rem;
  min-height: 0;
  padding: 0;
  flex: none;
  margin-top: 0.25em;
  accent-color: var(--accent);
  border-radius: var(--radius-1);
  appearance: auto;
}

/* Loading state on submit */
.btn[data-loading="true"] { pointer-events: none; }
.btn[data-loading="true"] .btn__label { opacity: 0.55; }
.btn__spinner { display: none; width: 1rem; height: 1rem; }
.btn[data-loading="true"] .btn__spinner { display: block; animation: spin 700ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.honeypot {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap;
}

/* 16 — Footer ------------------------------------------------------------ */
.site-footer {
  background: var(--inverse-ground);
  color: var(--inverse-ink);
  padding-block: var(--space-3xl) var(--space-l);
}
.site-footer a { color: inherit; text-decoration: none; }
.site-footer .eyebrow { color: color-mix(in oklab, var(--inverse-ink) 55%, transparent); }
.footer__grid { display: grid; gap: var(--space-xl) var(--gutter); grid-template-columns: 1fr; }
@media (min-width: 48rem) { .footer__grid { grid-template-columns: 1.6fr 1fr 1fr; } }
.footer__links li + li { margin-top: 0.6rem; }
.footer__links a {
  display: inline-block;
  opacity: 0.72;
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.footer__links a:hover { opacity: 1; transform: translateX(3px); }

/* On touch devices the footer list gets full-size targets with an 8px gap.
   Pointer devices keep the tighter typographic rhythm. */
@media (any-pointer: coarse) {
  .footer__links li + li { margin-top: 0.5rem; }
  .footer__links a {
    display: inline-flex;
    align-items: center;
    min-height: 2.75rem;
    min-width: 2.75rem;
  }
}

/* Links sitting inline within a sentence keep the WCAG 2.5.8 inline
   exception, but still get a little vertical room. */
.footer__bottom a { display: inline-block; padding-block: 0.35rem; }
.footer__mark { font-family: var(--font-display); font-weight: 500; font-size: var(--step-4); letter-spacing: -0.025em; max-width: 14ch; }
.footer__bottom {
  margin-top: var(--space-3xl);
  padding-top: var(--space-m);
  border-top: 1px solid color-mix(in oklab, var(--inverse-ink) 18%, transparent);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s) var(--space-l);
  justify-content: space-between;
  font-size: var(--step--1);
  color: color-mix(in oklab, var(--inverse-ink) 60%, transparent);
}
.footer__bottom a { text-decoration: underline; text-underline-offset: 0.2em; }

/* 17 — Utilities --------------------------------------------------------- */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%);
  white-space: nowrap; border: 0;
}
.text-soft { color: var(--ink-soft); }
.text-faint { color: var(--ink-faint); }
.text-accent { color: var(--accent); }
.mt-0 { margin-top: 0; }
.mt-2xs { margin-top: var(--space-2xs); }
.mt-s { margin-top: var(--space-s); }
.mt-m { margin-top: var(--space-m); }
.mt-l { margin-top: var(--space-l); }
.mt-xl { margin-top: var(--space-xl); }
.mt-2xl { margin-top: var(--space-2xl); }
.mt-3xl { margin-top: var(--space-3xl); }
.mb-l { margin-bottom: var(--space-l); }
.mb-xl { margin-bottom: var(--space-xl); }

/* 18 — Reduced motion, forced colours, print ----------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Reveals must land on their final state, not stay hidden. */
  .reveal { opacity: 1; transform: none; }
  .reveal-rule { transform: scaleX(1); }
  .tline__i { transform: none; }
  .stat__suffix { opacity: 1; transform: none; }
  .reveal-img > img, .reveal-img > picture > img { clip-path: none; transform: none; }
  .menu-panel[data-open="true"] .menu-panel__list a { opacity: 1; transform: none; }
    @view-transition { navigation: none; }
}

@media (forced-colors: active) {
  .btn, .input, .chips label { border: 1px solid ButtonText; }
  .rule, .idx__line { background: CanvasText; }
  .card__arrow, .row__arrow { forced-color-adjust: auto; }
}

@media print {
  .site-header, .menu-panel, .hero-stage__cue, .filters, .btn, .theme-toggle { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .section { padding-block: 1.5rem; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #555; }
  .reveal, .reveal-img > img { opacity: 1; transform: none; clip-path: none; }
}
