/* ==========================================================================
   NESTED SOCIAL
   Story-led content for places worth discovering.
   --------------------------------------------------------------------------
   1.  Tokens
   2.  Reset & base
   3.  Texture (grain / paper)
   4.  Typography
   5.  Layout & sections
   6.  Buttons & links
   7.  Header & navigation
   8.  Images & placeholder system
   9.  Stamp / roundel
   10. Components
   11. Footer
   12. Motion & reveal
   13. Responsive
   ========================================================================== */

/* ==========================================================================
   1. TOKENS
   ========================================================================== */

/* ==========================================================================
   0. FONTS
   Self-hosted. Elza Medium carries the body, DaisyWheel — a typewriter face —
   does the headings and anything highlighted.
   ========================================================================== */

@font-face {
  font-family: "Elza";
  src: url("../fonts/elza-medium.otf") format("opentype");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "DaisyWheel";
  src: url("../fonts/daisywheel.otf") format("opentype");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* -- Palette ---------------------------------------------------------- */
  --cream:  #FAF4EA;   /* page background */
  --mist:   #B6C2CA;   /* cool blue-grey — the big contrast blocks */
  /* ⚠ Cream text on #B6C2CA measures 1.66:1, far below the 4.5:1 needed to be
     readable — those blocks will look like faint ghost text. To keep the
     light-on-blue look and make it legible, swap the line above for this
     deeper slate: same family, 4.8:1 against cream.
       --mist: #58696F;                                                     */
  --rust:   #9E4C33;   /* hero colour, and the accent throughout */
  --brown:  #61413F;   /* the ink — all text */
  --moss:   #584726;   /* olive-brown */
  --navy:   #1F2435;   /* kept in the palette, no longer used for large areas */

  /* Legacy token names, repointed at the new palette so every existing rule
     keeps working. Change a value here and it updates site-wide. */
  --canvas:   var(--cream);
  --oat:      #F1E7D8;   /* cream knocked back — alternating sections */
  --stone:    var(--mist);
  --olive:    var(--moss);
  --clay:     var(--rust);
  --charcoal: var(--brown);   /* text ink is warm brown, not navy */

  /* Rust variants. The hero rust manages 5.5:1 on cream, but only 3.3:1 on the
     mist ground, so small text uses a deepened version that clears both. */
  --clay-ink:  #7A3A26;   /* small text — 7.6:1 on cream, 4.7:1 on mist */
  --clay-deep: var(--rust);
  --clay-soft: #F4E5D6;   /* soft rust wash */

  /* Semantic accent — rust leads, moss is the occasional second voice. */
  --accent:      var(--rust);
  --accent-ink:  var(--clay-ink);

  /* The blue, made readable. --mist itself is a pale wash meant for big blocks;
     as TEXT on cream it measures about 1.7:1 and would be near-invisible. This
     is the same blue-grey family taken deep enough to read: 5.2:1 on cream.
     Use it for small type that should be blue rather than rust. */
  --blue-ink: #58696F;

  /* Rust lifted for use as a drawn line over photography. The flat --rust
     (#9E4C33) is too dark to read as a 2px line on a darkened image. */
  --accent-soft: #C86A45;

  /* Derived tones — all mixed from the brown ink now */
  --charcoal-80: rgba(97, 65, 63, 0.84);
  --charcoal-60: rgba(97, 65, 63, 0.70);
  --charcoal-40: rgba(97, 65, 63, 0.55);
  --charcoal-14: rgba(97, 65, 63, 0.20);
  --charcoal-08: rgba(97, 65, 63, 0.11);
  --canvas-70:   rgba(250, 244, 234, 0.76);
  --canvas-40:   rgba(250, 244, 234, 0.44);
  --canvas-16:   rgba(250, 244, 234, 0.20);
  --clay-20:     rgba(158, 76, 51, 0.26);
  --clay-10:     rgba(158, 76, 51, 0.12);
  --ink-20:      rgba(97, 65, 63, 0.22);

  /* -- Type -------------------------------------------------------------
     DaisyWheel for anything highlighted — headings, statements, numbers.
     Elza for reading. Elza ships in a single Medium weight, so hierarchy comes
     from size, colour and spacing rather than from weight. */
  --font-display: "DaisyWheel", "Courier New", ui-monospace, monospace;
  --font-body:    "Elza", "Avenir Next", "Helvetica Neue", system-ui, sans-serif;
  --font-accent:  "DaisyWheel", "Courier New", ui-monospace, monospace;
  /* Handwriting for the margin notes. One hand throughout — quick, sketched
     and genuinely uneven. Fine-stroked on purpose: the pencil texture below
     only reads properly on a thin line. */
  --font-hand:  "Nothing You Could Do", "Bradley Hand", cursive;
  --pencil:     #5A4E48;   /* graphite, 7.2:1 on cream */

  /* Fluid scale — 320px → 1600px */
  --t-xs:   clamp(0.688rem, 0.66rem + 0.14vw, 0.75rem);
  --t-sm:   clamp(0.813rem, 0.78rem + 0.16vw, 0.875rem);
  --t-base: clamp(0.975rem, 0.94rem + 0.18vw, 1.063rem);
  --t-md:   clamp(1.063rem, 1.00rem + 0.32vw, 1.25rem);
  --t-lg:   clamp(1.25rem, 1.12rem + 0.64vw, 1.625rem);
  --t-xl:   clamp(1.625rem, 1.36rem + 1.32vw, 2.5rem);
  --t-2xl:  clamp(2.125rem, 1.60rem + 2.62vw, 3.75rem);
  --t-3xl:  clamp(2.625rem, 1.72rem + 4.52vw, 5.25rem);
  --t-4xl:  clamp(3.125rem, 1.52rem + 8.02vw, 7.5rem);

  /* -- Space ------------------------------------------------------------ */
  --sp-1:  0.25rem;
  --sp-2:  0.5rem;
  --sp-3:  0.75rem;
  --sp-4:  1rem;
  --sp-5:  1.5rem;
  --sp-6:  2rem;
  --sp-7:  3rem;
  --sp-8:  4rem;
  --sp-9:  6rem;
  --sp-10: 8rem;

  --section-y: clamp(5.25rem, 11vw, 12rem);
  --gutter:    clamp(1.25rem, 4.5vw, 4rem);
  --measure:   68ch;

  /* -- Structure -------------------------------------------------------- */
  --wrap:      1440px;
  --wrap-tight: 1120px;
  --wrap-text:  760px;
  --header-h:  clamp(68px, 8vw, 92px);
  --radius:    3px;

  /* -- Motion ----------------------------------------------------------- */
  --ease:      cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-soft: cubic-bezier(0.33, 0, 0.15, 1);
  --dur:       0.6s;
  --dur-slow:  1.1s;
}

/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */

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

* { margin: 0; padding: 0; }

/* Author display rules (.logo, .brand__mark and friends) otherwise beat the
   UA stylesheet's [hidden] rule, so hiding an element in JS silently fails. */
[hidden] { display: none !important; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  background: var(--canvas);
  color: var(--charcoal);
  font-family: var(--font-body);
  font-size: var(--t-base);
  font-weight: 400;
  line-height: 1.78;
  letter-spacing: 0.002em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, svg, video { display: block; max-width: 100%; height: auto; }

button, input, textarea, select { font: inherit; color: inherit; }

button { background: none; border: 0; cursor: pointer; }

ul, ol { list-style: none; }

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

::selection { background: var(--accent); color: var(--canvas); }

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

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; top: 0; left: 50%;
  transform: translate(-50%, -110%);
  background: var(--charcoal); color: var(--canvas);
  padding: 0.75rem 1.5rem; z-index: 200;
  font-size: var(--t-xs); letter-spacing: 0.16em; text-transform: uppercase;
  transition: transform 0.2s var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

/* ==========================================================================
   3. TEXTURE — the lived-in layer
   ========================================================================== */

/* Paper, in two layers.
   The fine layer is the tooth of the sheet — a close, even grain. The broad
   layer is the mottle you get when light falls across uncoated stock: soft,
   cloudy, and much larger in scale. Neither reads as "noise" on its own;
   together they stop flat colour looking like a screen. */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 900;
  pointer-events: none;
  opacity: 0.062;
  mix-blend-mode: multiply;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='t'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23t)'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='680' height='680'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.035' numOctaves='5' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");
  background-size: 220px 220px, 680px 680px;
}

/* A faint warm wash, so the sheet isn't perfectly even edge to edge */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 899;
  pointer-events: none;
  background:
    radial-gradient(125% 90% at 10% 0%,    rgba(158, 76, 51, 0.05), transparent 58%),
    radial-gradient(115% 85% at 100% 100%, rgba(97, 65, 63, 0.055), transparent 60%);
}

/* Heavier tooth for panels that should feel like pressed card */
.texture-card {
  position: relative;
  isolation: isolate;
}
.texture-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.07;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.5' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");
}

/* ==========================================================================
   4. TYPOGRAPHY
   ========================================================================== */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.2;
  letter-spacing: 0;
  text-wrap: balance;
}

/* DaisyWheel is a typewriter face — already wide and characterful, so it wants
   sentence case and tight tracking rather than the spaced-out caps a geometric
   sans needs. Left as it falls: a little uneven, which is the point. */
.display-1 { font-size: clamp(2.1rem, 1.1rem + 4.9vw, 4.4rem); line-height: 1.1;  letter-spacing: -0.015em; }
.display-2 { font-size: clamp(1.75rem, 1.1rem + 3.3vw, 3.3rem); line-height: 1.14; letter-spacing: -0.012em; }
.display-3 { font-size: clamp(1.4rem, 1.0rem + 2.0vw, 2.35rem);  line-height: 1.2;  letter-spacing: -0.008em; }
.display-4 { font-size: var(--t-xl); line-height: 1.3; letter-spacing: -0.004em; }

/* Highlighted words. DaisyWheel has no true italic, so emphasis is carried by
   colour and a hand-drawn underline rather than a synthesised slant. */
.display-1 em, .display-2 em, .display-3 em, .display-4 em,
.serif-em {
  font-family: var(--font-display);
  font-style: normal;
  font-weight: 400;
  color: var(--accent);
  position: relative;
  white-space: nowrap;
}
/* On the dark and rust grounds the rust ink disappears — go light instead. */
.bg-clay :is(.display-1, .display-2, .display-3, .display-4) em,
.bg-clay .serif-em,
.bg-clay .statement em,
.hero em { color: var(--cream); }

/* Kept for markup that still asks for it — DaisyWheel is sentence case anyway */
.display-plain { text-transform: none; letter-spacing: -0.008em; }

/* Small caps label — the stamped ink line */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  font-family: var(--font-display);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent-ink);
  line-height: 1;
}
/* The little rust rule that used to sit before every eyebrow is gone — the
   labels read cleaner on their own. .eyebrow--bare is kept as a no-op so the
   older pages that still ask for it don't need touching. */
.eyebrow--clay { color: var(--clay); }
.eyebrow--light { color: var(--stone); }
.hero .eyebrow--light { color: var(--cream); }

/* Numbered index, e.g. 01 — */
.index-num {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
}

.lede {
  font-size: var(--t-md);
  line-height: 1.65;
  color: var(--charcoal-80);
  max-width: 58ch;
}

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: 1.15em; }
.prose p { color: var(--charcoal-80); }
.prose h3 {
  font-size: var(--t-lg);
  margin-top: 2em;
  letter-spacing: -0.01em;
}
.prose a {
  color: var(--charcoal);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  text-decoration-color: var(--stone);
  transition: text-decoration-color 0.3s var(--ease);
}
.prose a:hover { text-decoration-color: var(--accent); }
.prose blockquote {
  border-left: 1px solid var(--accent);
  padding-left: var(--sp-5);
  font-family: var(--font-accent);
  font-style: italic;
  font-size: var(--t-lg);
  line-height: 1.4;
  color: var(--charcoal);
  margin: 2em 0;
}
.prose ul { padding-left: 1.1em; }
.prose ul li {
  position: relative;
  padding-left: 1.2em;
  color: var(--charcoal-80);
  margin-top: 0.5em;
}
.prose ul li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.72em;
  width: 0.4em; height: 1px;
  background: var(--accent);
}

.text-center { text-align: center; }
.text-muted  { color: var(--charcoal-60); }
.text-olive  { color: var(--accent); }
.text-clay   { color: var(--clay); }

/* Hand-set underline that sits a little low and slightly off */
.mark-under {
  background-image: linear-gradient(to right, var(--accent), var(--accent));
  background-repeat: no-repeat;
  background-size: 100% 1px;
  background-position: 0 92%;
  padding-bottom: 0.06em;
}

/* ==========================================================================
   5. LAYOUT & SECTIONS
   ========================================================================== */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--tight { max-width: var(--wrap-tight); }
.wrap--text  { max-width: var(--wrap-text); }
.wrap--full  { max-width: none; padding-inline: 0; }

.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: clamp(3rem, 6vw, 6rem); }
.section--top-0 { padding-top: 0; }
.section--bot-0 { padding-bottom: 0; }

.bg-oat      { background: var(--oat); }
.bg-stone    { background: var(--stone); }
.bg-tint     { background: var(--clay-soft); }
/* The mist blocks carry cream text, as requested. See README — cream on mist
   is a low-contrast pairing; the deeper slate noted there fixes it if wanted. */
.bg-charcoal { background: var(--mist); color: var(--cream); }
.bg-charcoal .lede,
.bg-charcoal .prose p,
.bg-charcoal .statement,
.bg-charcoal h1, .bg-charcoal h2, .bg-charcoal h3, .bg-charcoal h4,
.bg-charcoal .stat dt,
.bg-charcoal .stat dd,
.bg-charcoal .step p,
.bg-charcoal .pillar p,
.bg-charcoal .form__note,
.bg-charcoal .faq__q,
.bg-charcoal .faq__a p,
.bg-charcoal .note { color: var(--cream); }
.bg-charcoal .eyebrow,
.bg-charcoal .eyebrow--light,
.bg-charcoal .index-num,
.bg-charcoal .form__note a { color: var(--cream); }
.bg-charcoal .rule,
.bg-charcoal .faq,
.bg-charcoal .faq__item,
.bg-charcoal .step,
.bg-charcoal .pillar { border-color: rgba(247, 235, 218, 0.45); }
.bg-charcoal .rule { background: rgba(247, 235, 218, 0.45); }
.bg-clay     { background: var(--clay-deep); color: var(--canvas); }

/* Both dark grounds share the same treatment for text and rules. */
.bg-clay .lede,
.bg-clay .prose p { color: var(--canvas-70); }

/* Terracotta is a lighter ground than charcoal, so secondary text has to sit
   nearer full canvas to stay legible — canvas on --clay-deep is 4.9:1, where
   the 70% tint used on charcoal would only manage 3.3:1. */
.bg-clay .lede,
.bg-clay .prose p,
.bg-clay .eyebrow,
.bg-clay .quote figcaption,
.bg-clay .stat dd,
.bg-clay .pillar p,
.bg-clay .step p,
.bg-clay .marquee__group li { color: var(--canvas); }
.bg-clay .rule,
.bg-clay .pillar,
.bg-clay .step,
.bg-clay .marquee,
.bg-clay .link::before { border-color: rgba(248, 246, 241, 0.3); background-color: transparent; }
.bg-clay .rule { background: rgba(248, 246, 241, 0.3); }
.bg-clay .link::before { background: rgba(248, 246, 241, 0.3); }
.bg-clay .link::after { background: var(--canvas); }

/* --- Mist sections: cream text, per the brief -----------------------------
   Buttons and marks that assumed a dark ground stay light here; the colour
   rules live in the block further up. */
.bg-charcoal .stamp--light { color: var(--cream); }
.bg-charcoal .logo--onDark img,
.bg-charcoal .brand__mark.is-light img { filter: brightness(0) invert(1); opacity: 0.95; }
.bg-charcoal .btn--light {
  color: var(--cream);
  border-color: rgba(247, 235, 218, 0.55);
}
.bg-charcoal .btn--light::after { background: var(--cream); }
.bg-charcoal .btn--light:hover { color: var(--clay-deep); border-color: var(--cream); }

/* Rules */
.rule {
  height: 1px;
  background: var(--charcoal-14);
  border: 0;
}
.bg-clay .rule { background: var(--canvas-16); }

/* Section head: eyebrow + heading + optional lede, with a hanging index */
.sec-head {
  display: grid;
  gap: var(--sp-5);
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
}
.sec-head__top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.sec-head h2 { max-width: 20ch; }
.sec-head--center {
  justify-items: center;
  text-align: center;
}
.sec-head--center h2 { max-width: 24ch; }
.sec-head--split {
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  align-items: end;
  gap: clamp(2rem, 5vw, 5rem);
}
/* A quieter line under a section heading: a step down from body size so it
   reads as a subtitle to the heading and not as the start of the section.
   No margin-top — it sits directly on the .sec-head grid, so the gap there
   does the spacing and a margin would double it. */
.sec-head__sub {
  font-size: var(--t-sm);
  line-height: 1.68;
  color: var(--charcoal-60);
  /* 50ch, not 46: at 46 the current line came a single pixel short of fitting
     and dropped "there." onto a line by itself. balance keeps the lines even
     if a longer subtitle ever does wrap. */
  max-width: 50ch;
  text-wrap: balance;
}

/* Generic grids */
.grid { display: grid; gap: var(--sp-6); }
.grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid--metrics { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .grid--metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .grid--metrics { grid-template-columns: 1fr; } }
.grid--gap-lg { gap: clamp(2rem, 4vw, 4rem); }

/* Two-column editorial split: media + text */
.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2rem, 6vw, 6rem);
  align-items: center;
}
.split--top { align-items: start; }
/* Bottom-aligned: the media sits on the same baseline as the last line of the
   text, taking the slack as space above the image rather than below it. */
.split--bottom { align-items: end; }
.split__text { max-width: 46ch; }
.split--reverse .split__media { order: 2; }

/* ==========================================================================
   6. BUTTONS & LINKS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.65em;
  padding: 1.05em 2.2em;
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: none;
  line-height: 1;
  border: 1px solid var(--clay-deep);
  background: var(--clay-deep);
  color: var(--canvas);
  border-radius: var(--radius);
  position: relative;
  overflow: hidden;
  transition: color 0.45s var(--ease), border-color 0.45s var(--ease);
  isolation: isolate;
}
.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--charcoal);
  transform: translateY(101%);
  transition: transform 0.5s var(--ease-soft);
}
.btn:hover::after, .btn:focus-visible::after { transform: translateY(0); }
.btn:hover { color: var(--canvas); border-color: var(--charcoal); }

.btn--ghost {
  background: transparent;
  color: var(--charcoal);
  border-color: var(--clay-20);
}
.btn--ghost::after { background: var(--clay-deep); }
.btn--ghost:hover { color: var(--canvas); border-color: var(--clay-deep); }

.btn--light {
  background: transparent;
  color: var(--canvas);
  border-color: var(--canvas-40);
}
.btn--light:hover { color: var(--charcoal); border-color: var(--canvas); }
.btn--light::after { background: var(--canvas); }

.btn--dark { background: var(--charcoal); border-color: var(--charcoal); }
.btn--dark::after { background: var(--clay-deep); }

.btn--block { display: flex; width: 100%; }

/* Understated text link with a rule that draws in */
.link {
  display: inline-flex;
  align-items: center;
  gap: 0.55em;
  font-size: var(--t-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1;
  padding-bottom: 0.55em;
  position: relative;
  color: var(--charcoal);
  white-space: nowrap;
}
.link::before {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--charcoal-14);
}
.link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease-soft);
}
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); }
.link .arw { transition: transform 0.4s var(--ease); }
.link:hover .arw { transform: translateX(4px); }

.bg-clay .link { color: var(--canvas); }
.bg-clay .link::before { background: var(--canvas-16); }
.bg-clay .link::after { background: var(--stone); }

/* ==========================================================================
   7. HEADER & NAVIGATION
   ========================================================================== */

.header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  transition: background-color 0.5s var(--ease), border-color 0.5s var(--ease),
              color 0.4s var(--ease), transform 0.5s var(--ease);
  border-bottom: 1px solid transparent;
  color: var(--charcoal);
}
.header__inner {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
}

/* Solid state (default on inner pages, and on scroll everywhere) */
.header.is-solid {
  background: rgba(248, 246, 241, 0.90);
  -webkit-backdrop-filter: blur(14px) saturate(1.1);
  backdrop-filter: blur(14px) saturate(1.1);
  border-bottom-color: var(--charcoal-08);
}
.header.is-hidden { transform: translateY(-101%); }

/* Overlay state — transparent, light text, sitting on the hero */
body[data-header="overlay"] .header:not(.is-solid) { color: var(--canvas); }
body[data-header="overlay"] .header:not(.is-solid) .nav__link::after { background: var(--canvas); }
body[data-header="overlay"] .header:not(.is-solid) .header__cta {
  border-color: var(--canvas-40);
  color: var(--canvas);
}
body[data-header="overlay"] .header:not(.is-solid) .header__cta::after { background: var(--canvas); }
body[data-header="overlay"] .header:not(.is-solid) .header__cta:hover { color: var(--charcoal); }
body[data-header="overlay"] .header:not(.is-solid) .burger span { background: var(--canvas); }

/* Wordmark */
.brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex: none;
  z-index: 2;
}
.brand__mark {
  width: clamp(34px, 3.8vw, 44px);
  height: auto;
  flex: none;
}
.brand__mark img { width: 100%; height: auto; }

/* Over the hero photo the terracotta bird would sit too dark against the
   image, so it turns cream in step with the rest of the overlay header. */
body[data-header="overlay"] .header:not(.is-solid) .brand__mark img {
  filter: brightness(0) invert(1);
  opacity: 0.94;
}
.brand__type {
  display: flex;
  flex-direction: column;
  line-height: 1;
}
.brand__name {
  font-family: var(--font-display);
  font-size: clamp(0.95rem, 1.15vw, 1.1rem);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.2em;
}
.brand__sub {
  font-size: 0.56rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  white-space: nowrap;
  /* deep rust, not the hero rust — at 9px it has to clear 4.5:1 on the mist
     footer as well as on cream */
  color: var(--accent-ink);
  margin-top: 0.34em;
}
body[data-header="overlay"] .header:not(.is-solid) .brand__sub { color: var(--stone); }

/* Desktop nav */
.nav { display: flex; align-items: center; gap: clamp(1.5rem, 2.6vw, 2.75rem); }
.nav__link {
  position: relative;
  font-size: var(--t-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  padding-block: 0.4em;
  white-space: nowrap;
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--charcoal);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.45s var(--ease-soft);
}
.nav__link:hover::after,
.nav__link:focus-visible::after,
.nav__link[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }

.header__actions { display: flex; align-items: center; gap: var(--sp-4); flex: none; }
.header__cta {
  padding: 0.85em 1.6em;
  font-size: var(--t-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1;
  border: 1px solid var(--clay-20);
  color: var(--charcoal);
  border-radius: var(--radius);
  position: relative;
  overflow: hidden;
  isolation: isolate;
  transition: color 0.4s var(--ease), border-color 0.4s var(--ease);
  white-space: nowrap;
}
.header__cta::after {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: var(--clay-deep);
  transform: translateY(101%);
  transition: transform 0.5s var(--ease-soft);
}
.header__cta:hover { color: var(--canvas); border-color: var(--clay-deep); }
.header__cta:hover::after { transform: translateY(0); }

/* Burger */
.burger {
  display: none;
  width: 30px;
  height: 16px;
  position: relative;
  z-index: 2;
  flex: none;
}
.burger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background: var(--charcoal);
  transition: transform 0.45s var(--ease), opacity 0.25s var(--ease), background-color 0.3s var(--ease);
}
.burger span:nth-child(1) { top: 2px; }
.burger span:nth-child(2) { bottom: 2px; }
.burger[aria-expanded="true"] span { background: var(--charcoal); }
.burger[aria-expanded="true"] span:nth-child(1) { top: 50%; transform: translateY(-50%) rotate(15deg); }
.burger[aria-expanded="true"] span:nth-child(2) { bottom: 50%; transform: translateY(50%) rotate(-15deg); }

/* Mobile menu overlay */
.menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--canvas);
  padding: calc(var(--header-h) + var(--sp-7)) var(--gutter) var(--sp-7);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--sp-7);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-1.5rem);
  transition: opacity 0.5s var(--ease), transform 0.6s var(--ease-soft), visibility 0.5s;
  overflow-y: auto;
}
.menu.is-open { opacity: 1; visibility: visible; transform: translateY(0); }

.menu__nav { display: flex; flex-direction: column; }
.menu__link {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 6.5vw, 2.25rem);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1.3;
  padding-block: 0.16em;
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity 0.5s var(--ease), transform 0.6s var(--ease-soft), color 0.3s var(--ease);
}
.menu.is-open .menu__link { opacity: 1; transform: translateY(0); }
.menu__link:hover { color: var(--accent); }
.menu__link span {
  font-family: var(--font-body);
  font-size: 0.68rem;
  letter-spacing: 0.2em;
  color: var(--charcoal-40);
}
.menu__logo {
  margin-inline: auto;
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity 0.6s var(--ease) 0.45s, transform 0.7s var(--ease-soft) 0.45s;
}
.menu.is-open .menu__logo { opacity: 1; transform: none; }
/* On short screens the nav links matter more than the flourish */
@media (max-height: 700px) { .menu__logo { display: none; } }

.menu__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4) var(--sp-6);
  justify-content: space-between;
  align-items: flex-end;
  padding-top: var(--sp-5);
  border-top: 1px solid var(--charcoal-14);
  font-size: var(--t-sm);
  color: var(--charcoal-60);
}

/* ==========================================================================
   8. IMAGES & PLACEHOLDER SYSTEM
   --------------------------------------------------------------------------
   Every image lives in a .img wrapper. Until the real file is dropped into
   /images, the wrapper shows a labelled block with the exact filename it is
   waiting for. Name the file, drop it in, done.
   ========================================================================== */

.img {
  position: relative;
  overflow: hidden;
  background: var(--oat);
  border-radius: var(--radius);
  isolation: isolate;
}
.img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  /* Film-stock warmth. Nothing HDR, nothing crunchy. */
  filter: saturate(0.94) contrast(1.02) brightness(1.01);
  transition: transform 1.4s var(--ease-soft), opacity 1s var(--ease);
}
.img.is-loaded img { opacity: 1; }

/* Grain over photography so it sits in the same world as the paper */
.img::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* Aspect ratios */
.img--sq      { aspect-ratio: 1 / 1; }
.img--4x5     { aspect-ratio: 4 / 5; }
.img--3x4     { aspect-ratio: 3 / 4; }
.img--2x3     { aspect-ratio: 2 / 3; }
.img--4x3     { aspect-ratio: 4 / 3; }
.img--3x2     { aspect-ratio: 3 / 2; }
.img--16x9    { aspect-ratio: 16 / 9; }
.img--21x9    { aspect-ratio: 21 / 9; }
.img--tall    { aspect-ratio: 5 / 7; }

/* Zoom on hover for interactive cards */
.zoom:hover .img img,
a:hover > .img img { transform: scale(1.035); }

/* -- Empty state ----------------------------------------------------------
   Applied by js/main.js when the image file isn't there yet. */
.img.is-empty {
  background:
    repeating-linear-gradient(
      -45deg,
      transparent 0 11px,
      rgba(46, 45, 43, 0.028) 11px 22px
    ),
    var(--oat);
  box-shadow: inset 0 0 0 1px var(--stone);
}
.img.is-empty img { opacity: 0; }
.img.is-empty::before {
  content: attr(data-file);
  position: absolute;
  inset: auto 8% 50% 8%;
  transform: translateY(50%);
  text-align: center;
  font-family: var(--font-body);
  font-size: clamp(0.6rem, 1.1vw, 0.72rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1.7;
  color: var(--charcoal-40);
  word-break: break-word;
  z-index: 2;
}
.img.is-empty[data-note]::before { content: attr(data-note) " — " attr(data-file); }

/* Full-bleed divider band — the breathing space between chapters */
.media-band { width: 100%; }
.media-band .img { border-radius: 0; aspect-ratio: 21 / 9; }
@media (max-width: 700px) { .media-band .img { aspect-ratio: 4 / 3; } }

/* A plain side-by-side pair. Nothing overlaps; both images sit in full view. */
.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 2.5vw, 2rem);
  align-items: start;
}
.pair__a, .pair__b { grid-column: auto; grid-row: auto; margin-top: 0; }

/* ==========================================================================
   9. STAMP / ROUNDEL
   ========================================================================== */

/* The circular stamp is now the real designed asset rather than generated type.
   Left static on purpose — the wordmark inside it is meant to be read. */
.stamp {
  width: clamp(104px, 12vw, 152px);
  aspect-ratio: 1;
  flex: none;
}
.stamp img { width: 100%; height: 100%; object-fit: contain; }

/* Shared behaviour for every placed logo asset */
.logo { display: block; flex: none; }
.logo img { width: 100%; height: auto; }

.logo--stack  { width: clamp(120px, 16vw, 200px); }
.logo--poster { width: clamp(180px, 26vw, 300px); }
.logo--block  { width: clamp(110px, 13vw, 165px); }
.logo--birdstar { width: clamp(130px, 18vw, 210px); }

/* The logo files are solid terracotta silhouettes, so on the dark grounds they
   are recoloured to cream rather than swapped for a second set of assets. */
.logo--onDark img { filter: brightness(0) invert(1); opacity: 0.92; }
/* The footer is a light ground now, so its mark keeps its own colour. */
.brand__mark.is-light img { filter: none; opacity: 1; }

/* If any exported PNG turns out to have a white background rather than
   transparency, uncomment this and the white will drop out on light grounds:
   .logo img, .stamp img, .brand__mark img { mix-blend-mode: multiply; } */

/* A tilted paper tag / pressed seal */
.seal {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  padding: 0.55em 1.1em;
  border: 1px solid currentColor;
  border-radius: 100px;
  font-size: var(--t-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1;
  color: var(--accent-ink);
  transform: rotate(-1.2deg);
}
.seal::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
}

/* ==========================================================================
   10. COMPONENTS
   ========================================================================== */

/* -- Hero ------------------------------------------------------------------ */
.hero {
  position: relative;
  min-height: clamp(560px, 92svh, 1000px);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--charcoal);
}
.hero__media { position: absolute; inset: 0; }
.hero__media .img { width: 100%; height: 100%; border-radius: 0; }
.hero__media .img img {
  /* The houses sit in the upper third of a 3:2 frame and the headline sits low,
     so the crop has to keep them apart. 55% rather than `bottom`: it drops the
     houses to just under the header and still leaves still water behind the
     type. `bottom` pinned them tight to the top edge — and on a wide, short
     window (1920x720, say) it cropped them out of the picture altogether,
     leaving nothing but upside-down reflections. A percentage tracks the
     viewport ratio; a fixed px offset does not, and a calc() offset here
     resolves against negative free space, which moves it the wrong way. */
  object-position: center 55%;
  transform: scale(1.06);
  animation: hero-settle 2.6s var(--ease-soft) forwards;
}
@keyframes hero-settle { to { transform: scale(1); } }

.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(to top,
      rgba(58, 40, 38, 0.74) 0%,
      rgba(58, 40, 38, 0.46) 38%,
      rgba(58, 40, 38, 0.24) 62%,
      rgba(58, 40, 38, 0.34) 100%);
  pointer-events: none;
  transition: opacity 0.6s var(--ease);
}
/* While the hero photo is still a placeholder, lift the scrim so the
   filename label underneath stays readable. */
.hero:has(.img.is-empty) .hero__scrim { opacity: 0.62; }
.hero:has(.img.is-empty) .img.is-empty::before { color: var(--charcoal-60); }
.hero__inner {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-block: clamp(2rem, 3.5vw, 3rem);
  color: var(--canvas);
  /* No text-shadow: she asked for it off (22 Sep 2026). The type is legible on
     the current hero because .hero__scrim is doing the work, darkest exactly
     where the type sits. If the hero photograph is ever swapped for a lighter
     one, check the headline again and either deepen the scrim or put this back:
       text-shadow: 0 1px 18px rgba(38, 26, 25, 0.34);                        */
}
/* Sized in em so the measure tracks the display size — uppercase runs much
   wider than the ch unit suggests, and the hero lines are hard-broken. */
.hero h1 { color: var(--canvas); max-width: 12em; }
.hero__sub {
  /* Same treatment as the .eyebrow labels ("Who we are"), one size up.
     No leading rule — that reads as a label mark, and this is a sentence. */
  margin-top: 0;
  /* caps + 0.18em tracking run far wider than the ch unit suggests, so the
     measure has to be generous to keep this to two balanced lines */
  max-width: 62ch;
  text-wrap: balance;
  color: rgba(248, 246, 241, 0.9);
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  line-height: 1.85;
}
.hero__row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-6);
  flex-wrap: wrap;
  margin-top: clamp(0.5rem, 1vw, 0.9rem);
}
.hero__actions { display: flex; gap: var(--sp-4); flex-wrap: wrap; }

/* Page hero — shorter, for inner pages */
.hero--page { min-height: clamp(420px, 62svh, 660px); }
.hero--page h1 { max-width: 14em; }

/* Text-only page header on canvas */
.page-head {
  padding-top: calc(var(--header-h) + clamp(3rem, 8vw, 7rem));
  padding-bottom: clamp(2.5rem, 5vw, 4.5rem);
}
.page-head h1 { max-width: 16ch; }
.page-head .lede { margin-top: var(--sp-5); }

/* Scroll cue */
.scroll-cue {
  display: inline-flex;
  align-items: center;
  gap: 0.75em;
  font-size: var(--t-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(248, 246, 241, 0.7);
}
.scroll-cue i {
  display: block;
  width: 1px;
  height: 34px;
  background: currentColor;
  position: relative;
  overflow: hidden;
}
.scroll-cue i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--canvas);
  animation: cue 2.4s var(--ease-soft) infinite;
}
@keyframes cue {
  0%   { transform: translateY(-100%); }
  55%  { transform: translateY(0); }
  100% { transform: translateY(100%); }
}

/* -- Statement (big pull quote / manifesto) -------------------------------- */
.statement {
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: clamp(1.6rem, 1.1rem + 2.4vw, 2.9rem);
  line-height: 1.24;
  letter-spacing: -0.004em;
  max-width: 22ch;
  text-wrap: balance;
}
.statement--wide { max-width: 30ch; }
.statement em { font-style: italic; font-variation-settings: var(--serif-soft); color: var(--accent-ink); }

/* -- Service / offer cards ------------------------------------------------- */
.offer {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--charcoal-14);
}
/* The service cards are text-only — no photography for them yet. Kept in case
   images come back later. */
.offer .img { margin-bottom: var(--sp-2); }
.offer h3 { font-size: var(--t-lg); letter-spacing: -0.012em; }
.offer p { color: var(--charcoal-60); font-size: var(--t-sm); line-height: 1.68; }
.offer__list { display: grid; gap: 0.4em; margin-top: auto; padding-top: var(--sp-3); }
.offer__list li {
  position: relative;
  padding-left: 1.1em;
  font-size: var(--t-sm);
  color: var(--charcoal-60);
}
.offer__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.72em;
  width: 0.45em; height: 1px;
  background: var(--accent);
}

/* -- Pillars (numbered rows) ----------------------------------------------- */
.pillar {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: var(--sp-5);
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
  border-top: 1px solid var(--charcoal-14);
  align-items: start;
}
.pillar:last-child { border-bottom: 1px solid var(--charcoal-14); }
.bg-clay .pillar { border-color: var(--canvas-16); }
.pillar h3 { font-size: var(--t-xl); }
.pillar__body { display: grid; gap: var(--sp-3); grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); align-items: start; column-gap: clamp(1.5rem, 4vw, 4rem); }
.pillar p { color: var(--charcoal-60); max-width: 46ch; }
.bg-clay .pillar p { color: var(--canvas-70); }

/* -- Work cards ------------------------------------------------------------ */
.work-card { display: block; }
.work-card .img { margin-bottom: var(--sp-4); }
.work-card__meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--charcoal-14);
}
.work-card h3 { font-size: var(--t-lg); letter-spacing: -0.012em; }
.work-card__tag {
  font-size: var(--t-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--charcoal-40);
  white-space: nowrap;
}
.work-card p { margin-top: var(--sp-2); color: var(--charcoal-60); font-size: var(--t-sm); }

/* -- Marquee (who we work with) -------------------------------------------- */
.marquee {
  position: relative;
  overflow: hidden;
  padding-block: clamp(1.5rem, 3vw, 2.5rem);
  border-block: 1px solid var(--charcoal-14);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.bg-clay .marquee { border-color: var(--canvas-16); }
.marquee__track {
  display: flex;
  width: max-content;
  animation: marquee 46s linear infinite;
}
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee__group {
  display: flex;
  align-items: center;
  flex: none;
  padding-right: 0;
}
.marquee__group li {
  display: flex;
  align-items: center;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  padding-inline: clamp(0.875rem, 2vw, 1.75rem);
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  white-space: nowrap;
  color: var(--charcoal-80);
}
.bg-clay .marquee__group li { color: var(--canvas-70); }
.marquee__group li::after {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}
@keyframes marquee { to { transform: translateX(-50%); } }

/* -- Testimonial ----------------------------------------------------------- */
.quote { display: grid; gap: var(--sp-6); justify-items: center; text-align: center; }
.quote blockquote {
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: clamp(1.35rem, 1.0rem + 1.7vw, 2.25rem);
  line-height: 1.38;
  letter-spacing: -0.002em;
  max-width: 24ch;
  text-wrap: balance;
}
.quote figcaption {
  font-size: var(--t-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--charcoal-40);
}
.bg-clay .quote figcaption { color: var(--stone); }

/* -- Numbered process steps ------------------------------------------------ */
.step {
  display: grid;
  gap: var(--sp-3);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--charcoal-14);
}
.bg-clay .step { border-color: var(--canvas-16); }
.step h3 { font-size: var(--t-lg); }
.step p { color: var(--charcoal-60); font-size: var(--t-sm); }
.bg-clay .step p { color: var(--canvas-70); }

/* -- Package / pricing panels ---------------------------------------------- */
.package {
  display: flex;
  flex-direction: column;
  gap: var(--sp-4);
  padding: clamp(1.75rem, 3.5vw, 2.75rem);
  background: var(--canvas);
  border: 1px solid var(--stone);
  border-radius: var(--radius);
  position: relative;
}
/* -- Coloured price cards, one brand colour each (21 Sep 2026) -------------
   Rust, mist and ink, in that order across the three.

   Text colour is not a free choice here. Cream reads on rust (5.4:1) and on
   ink (8.2:1), but measures 1.66:1 on mist, which is the same trap the big
   mist blocks have — so the mist card takes the brown ink instead (4.9:1).

   Two knock-ons worth knowing: --canvas-70 drops small type to 3.5:1 on rust,
   under the 4.5:1 it needs, so the dark cards run their text at full cream and
   let size carry the hierarchy. And .package__list dashes default to --accent
   (rust), which is invisible on both the rust and ink grounds, so every card
   restates them. */
.package--rust { background: var(--rust);  border-color: var(--rust);  color: var(--canvas); }
.package--ink  { background: var(--brown); border-color: var(--brown); color: var(--canvas); }
.package--mist { background: var(--mist);  border-color: var(--mist);  color: var(--charcoal); }

.package--rust .index-num,
.package--rust .package__for,
.package--rust .package__price,
.package--rust .package__list li,
.package--ink .index-num,
.package--ink .package__for,
.package--ink .package__price,
.package--ink .package__list li { color: var(--canvas); }

.package--rust .package__list li::before,
.package--ink .package__list li::before { background: var(--canvas); }

/* --accent-ink (#7A3A26) is the deepened rust picked for exactly this ground:
   4.7:1 on mist, where the flat --rust manages only 3.3:1. */
.package--mist .package__for,
.package--mist .package__list li { color: var(--charcoal); }
.package--mist .index-num,
.package--mist .package__price { color: var(--accent-ink); }
.package--mist .package__list li::before { background: var(--accent-ink); }
.package__ribbon {
  position: absolute;
  top: 0; right: clamp(1.25rem, 3vw, 2rem);
  transform: translateY(-50%);
  background: var(--clay-deep);
  color: var(--canvas);
  padding: 0.5em 0.95em;
  font-size: 0.6rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1;
}
/* The heading is sized off the CARD, not the viewport. At --t-xl "Two days a
   week" overflowed its column by 37px and "One day a week" by 16, so both broke
   onto two lines while "By the hour" sat on one. A vw-based size can't fix that
   on its own: the three-column band runs from about 900px up, and at 950px the
   column is only 195px of usable width against 281px at 1340px, so any single
   vw curve is either too big at the bottom of the band or too small at the top.
   Container units track the column directly, which is the thing that actually
   decides whether the line fits. Left wrapping rather than nowrap on purpose:
   if this is ever a pixel short it should wrap, not spill out of the card. */
.package { container-type: inline-size; }
.package h3 { font-size: clamp(1.4rem, 8.8cqi, 2.1rem); }
.package__for { font-size: var(--t-sm); color: var(--charcoal-60); }
.package__price {
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--accent-ink);
}
.package__list { display: grid; gap: 0.55em; margin-top: var(--sp-2); }
.package__list li {
  position: relative;
  padding-left: 1.3em;
  font-size: var(--t-sm);
  color: var(--charcoal-80);
  line-height: 1.6;
}
.package__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.66em;
  width: 0.55em; height: 1px;
  background: var(--accent);
}
.package .btn { margin-top: auto; }

/* -- The pricing small print ----------------------------------------------
   Three separate points, so they read as a list rather than one dense
   paragraph. The block is centred under the three cards but the bullets are
   left-ranged, because centred body text with hanging dashes reads badly.
   Colour is --charcoal-80, not the --charcoal-40 the old paragraph used:
   that measures 2.7:1 on cream, which is too faint for the one place on the
   page that says what a job will actually cost you. This clears 5.4:1. */
.price-notes {
  display: grid;
  gap: 0.6em;
  max-width: 64ch;
  margin: clamp(2rem, 4vw, 2.75rem) auto 0;
  text-align: left;
}
.price-notes li {
  position: relative;
  padding-left: 1.3em;
  font-size: var(--t-sm);
  line-height: 1.65;
  color: var(--charcoal-80);
}
.price-notes li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.72em;
  width: 0.55em; height: 1px;
  background: var(--accent);
}
.price-notes__cta { text-align: center; margin-top: clamp(1.5rem, 3vw, 2rem); }

/* -- Journal cards --------------------------------------------------------- */
.post .img { margin-bottom: var(--sp-4); }
.post__meta {
  display: flex; gap: 0.75em; align-items: center;
  font-size: var(--t-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--charcoal-40);
  margin-bottom: var(--sp-3);
}
.post__meta span { display: inline-block; width: 3px; height: 3px; border-radius: 50%; background: var(--stone); }
.post h3 { font-size: var(--t-lg); letter-spacing: -0.012em; }
.post p { margin-top: var(--sp-2); color: var(--charcoal-60); font-size: var(--t-sm); }

.post--feature { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
.post--feature .img { margin-bottom: 0; }
.post--feature h3 { font-size: var(--t-2xl); }
.post--feature p { font-size: var(--t-base); max-width: 42ch; }

/* -- Stat row -------------------------------------------------------------- */
.stat { display: grid; gap: var(--sp-2); }
/* Each animating number reserves its final width, so the layout doesn't
   jitter while the digits climb. */
.count {
  display: inline-block;
  text-align: left;
  font-variant-numeric: tabular-nums;
  min-width: var(--count-w, auto);
}
.stat dt {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 1.3rem + 2.6vw, 3.1rem);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1;
  color: var(--charcoal);
  font-variant-numeric: tabular-nums;
}
.bg-clay .stat dt { color: var(--canvas); }
.stat dd {
  font-size: var(--t-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--charcoal-40);
  max-width: 22ch;
}
.bg-clay .stat dd { color: var(--stone); }

/* -- CTA band -------------------------------------------------------------- */
.cta-band { position: relative; overflow: hidden; }
.cta-band__inner {
  display: grid;
  gap: var(--sp-6);
  justify-items: center;
  text-align: center;
  padding-block: clamp(4rem, 9vw, 8.5rem);
}
.cta-band h2 { max-width: 18ch; }

/* -- FAQ / accordion ------------------------------------------------------- */
.faq { border-top: 1px solid var(--charcoal-14); }
.faq__item { border-bottom: 1px solid var(--charcoal-14); }
.faq__q {
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-5);
  padding-block: clamp(1.25rem, 2.5vw, 1.75rem);
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.01em;
  transition: color 0.3s var(--ease);
}
.faq__q:hover { color: var(--accent); }
.faq__icon { position: relative; width: 14px; height: 14px; flex: none; margin-top: 0.45em; }
.faq__icon::before, .faq__icon::after {
  content: "";
  position: absolute;
  background: currentColor;
  transition: transform 0.4s var(--ease-soft), opacity 0.3s var(--ease);
}
.faq__icon::before { top: 50%; left: 0; width: 100%; height: 1px; transform: translateY(-50%); }
.faq__icon::after  { left: 50%; top: 0; height: 100%; width: 1px; transform: translateX(-50%); }
.faq__q[aria-expanded="true"] .faq__icon::after { transform: translateX(-50%) rotate(90deg); opacity: 0; }
.faq__a {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s var(--ease-soft);
}
.faq__q[aria-expanded="true"] + .faq__a { grid-template-rows: 1fr; }
.faq__a > div { overflow: hidden; }
.faq__a p {
  color: var(--charcoal-60);
  max-width: 60ch;
  padding-bottom: clamp(1.25rem, 2.5vw, 1.75rem);
  font-size: var(--t-sm);
}

/* -- Forms ----------------------------------------------------------------- */
.form { display: grid; gap: var(--sp-5); }
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-5); }
.field { display: grid; gap: 0.6rem; }
.field label {
  font-size: var(--t-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--charcoal-60);
}
.field input,
.field textarea,
.field select {
  width: 100%;
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--stone);
  padding: 0.75rem 0 0.85rem;
  font-size: var(--t-base);
  font-weight: 400;
  color: var(--charcoal);
  border-radius: 0;
  transition: border-color 0.35s var(--ease);
  -webkit-appearance: none;
  appearance: none;
}
.field select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%232E2D2B' stroke-width='1'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.25rem center;
  padding-right: 2rem;
  cursor: pointer;
}
.field textarea { resize: vertical; min-height: 8rem; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: var(--charcoal-40); }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-bottom-color: var(--accent);
}
.field.has-error input,
.field.has-error textarea,
.field.has-error select { border-bottom-color: var(--clay); }
.field__error {
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  color: var(--clay);
  display: none;
}
.field.has-error .field__error { display: block; }

.checkline { display: flex; gap: 0.75rem; align-items: flex-start; font-size: var(--t-sm); color: var(--charcoal-60); }
.checkline input { margin-top: 0.35em; accent-color: var(--accent); width: 15px; height: 15px; flex: none; }

.form__note { font-size: var(--t-sm); color: var(--charcoal-40); }

.form-status {
  padding: var(--sp-4) var(--sp-5);
  border: 1px solid var(--accent);
  background: rgba(162, 154, 82, 0.09);
  font-size: var(--t-sm);
  display: none;
}
.form-status.is-visible { display: block; }
.form-status.is-error { border-color: var(--clay); background: rgba(177, 124, 99, 0.1); }

/* Honeypot */
.hp { position: absolute !important; left: -9999px; opacity: 0; height: 0; width: 0; }

/* -- Contact detail list --------------------------------------------------- */
.detail { display: grid; gap: 0.35rem; padding-block: var(--sp-4); border-top: 1px solid var(--charcoal-14); }
.detail dt { font-size: var(--t-xs); letter-spacing: 0.2em; text-transform: uppercase; color: var(--charcoal-40); }
.detail dd { font-size: var(--t-base); font-family: var(--font-display); font-weight: 400; letter-spacing: 0.02em; }
.detail dd a { transition: color 0.3s var(--ease); }
.detail dd a:hover { color: var(--accent); }

/* -- Logo strip ------------------------------------------------------------ */
.logos { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: clamp(2rem, 6vw, 5rem); }
.logos .img {
  width: clamp(90px, 12vw, 140px);
  aspect-ratio: 5 / 2;
  background: transparent;
  box-shadow: none;
  opacity: 0.55;
  transition: opacity 0.4s var(--ease);
}
.logos .img img { object-fit: contain; filter: grayscale(1) contrast(0.9); }
.logos .img:hover { opacity: 1; }

/* -- Timeline (the road here) ---------------------------------------------- */
.timeline { display: grid; }
.tl {
  display: grid;
  grid-template-columns: 9.5rem minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 2.5rem);
  padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
  border-top: 1px solid var(--charcoal-14);
}
.tl:last-child { border-bottom: 1px solid var(--charcoal-14); }
.tl__when {
  font-family: var(--font-display);
  font-size: var(--t-sm);
  letter-spacing: 0.04em;
  color: var(--accent-ink);
  padding-top: 0.2em;
}
.tl__body { max-width: 56ch; }
.tl h3 { font-size: var(--t-lg); }
.tl__where {
  font-size: var(--t-sm);
  color: var(--charcoal-40);
  margin: 0.3rem 0 0.9rem;
}
.tl p { color: var(--charcoal-60); font-size: var(--t-sm); }
.tl__links { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; margin-top: 1rem; }
.tl__links a {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  letter-spacing: 0.05em;
  color: var(--accent-ink);
  padding-bottom: 0.2em;
  border-bottom: 1px solid var(--clay-20);
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}
.tl__links a:hover { border-bottom-color: var(--accent); color: var(--charcoal); }

/* -- Hand-signed sign-off -------------------------------------------------- */
/* --- "Who's behind it" ---
   The mark sits above the label, and the type runs a step smaller than the rest
   of the page so a long personal bio stays a comfortable read rather than a
   wall. Body copy is capped at a narrower measure for the same reason. */
/* The mark shares a line with the "Who's behind it" label rather than sitting
   stacked above it: label ranged left, mark ranged right against the outer
   edge of the column. Aligned to flex-end so the label sits on the bird's
   baseline and reads straight into the heading below; centred, it floated at
   the bird's midpoint with a gap underneath. The mark keeps margin-left:auto
   so it stays right even if the label is ever removed. */
.bio__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(1rem, 3vw, 2rem);
}
.bio__mark { margin-left: auto; }
.bio .lede {
  font-size: clamp(1rem, 0.94rem + 0.28vw, 1.16rem);
  line-height: 1.6;
  max-width: 44ch;
}
.bio .prose { max-width: 50ch; }
.bio .prose p {
  font-size: var(--t-sm);
  line-height: 1.7;
}
.bio .prose > * + * { margin-top: 0.95em; }

/* The portrait next to the bio is cropped low on purpose. Squaring it off a
   4:5 with the default centre crop cut Lily off at the chest; pushing the
   frame down to 82% brings the camera and more of her into shot. 100% shows
   the most but crowds her head against the top edge. */
.split__media .img--sq img { object-position: center 82%; }

.signoff { margin-top: clamp(2rem, 4vw, 2.75rem); }
.signoff__name {
  font-family: var(--font-display);
  font-size: var(--t-xl);
  color: var(--accent);
  line-height: 1;
  transform: rotate(-1.5deg);
  transform-origin: left center;
}
.signoff__where {
  font-size: var(--t-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--charcoal-40);
  margin-top: 0.8rem;
}


/* -- Instagram grid --------------------------------------------------------
   A hand-curated grid rather than a live embed — no third-party script, no
   cookie banner, nothing that breaks when an API key expires. Swap the six
   files whenever you want; see README.md for making it live instead. */
.ig-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(0.5rem, 1.2vw, 1rem);
}
.ig-tile { display: block; }
.ig-tile .img { border-radius: var(--radius); }
.ig-foot {
  display: grid;
  justify-items: center;
  text-align: center;
  margin-top: clamp(2rem, 4vw, 3rem);
}
@media (max-width: 900px) { .ig-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 480px) { .ig-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* -- The road here: timeline + metrics -------------------------------------
   One spine down the middle. Each stop puts the role on one side and its own
   numbers directly across from it, so the metrics belong to a place rather
   than floating in a grid of their own. Sides alternate as you descend.

   The spine draws itself in as you scroll — see initRoad() in js/main.js.
   -------------------------------------------------------------------------- */
.road { position: relative; }

/* the faint full-length track */
.road::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--charcoal-14);
  transform: translateX(-50%);
}

/* the rust line that fills as you go */
.road__fill {
  position: absolute;
  left: 50%;
  top: 0;
  width: 1px;
  height: 100%;
  background: var(--accent);
  transform: translateX(-50%) scaleY(var(--road-progress, 0));
  transform-origin: top center;
  will-change: transform;
}

.road__item {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(7rem, 11vw, 9.5rem) minmax(0, 1fr);
  align-items: start;
  padding-block: clamp(2.25rem, 5vw, 4.5rem);
}
.road__item:first-child { padding-top: 0; }
.road__item:last-child  { padding-bottom: 0; }

/* --- the spine column --- */
.road__spine {
  grid-column: 2;
  display: grid;
  justify-items: center;
  gap: 0.85rem;
  padding-top: 0.35rem;
}
.road__node {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--canvas);
  border: 1px solid var(--charcoal-40);
  transition: background-color 0.45s var(--ease), border-color 0.45s var(--ease), transform 0.45s var(--ease-soft);
}
.road__node.is-lit {
  background: var(--accent);
  border-color: var(--accent);
  transform: scale(1.25);
}
.road__when {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  /* Deep clay when unlit — 7.6:1 on cream. Deliberately NOT a faded grey: the
     dates are content, and with JS off they never light, so the resting state
     has to be readable on its own. The lit state earns its attention from the
     fill, not from dimming everything else. */
  color: var(--accent-ink);
  background: var(--canvas);
  border: 1px solid var(--clay-20);
  border-radius: 100px;
  padding: 0.45em 0.9em;
  line-height: 1;
  transition: background-color 0.45s var(--ease), border-color 0.45s var(--ease),
              color 0.45s var(--ease);
}
.bg-oat .road__when, .bg-tint .road__when { background: inherit; }

/* Each stop's date fills terracotta as the drawn line reaches it, in step with
   its node, so the dates are what catch the eye on the way down. Placed after
   the .bg-oat rule above deliberately: that one resets the pill background, and
   equal specificity means source order decides which wins. Cream on rust is
   5.4:1, so the lit state stays readable. */
.road__when.is-lit {
  color: var(--canvas);
  background: var(--accent);
  border-color: var(--accent);
}

/* --- role and metrics, either side ---
   All three children are pinned to row 1. Without that, grid's sparse
   auto-placement quietly breaks the even stops: the children come in source
   order spine, role, figures, so on an even stop the role takes row 1 column 3,
   the placement cursor runs off the end of that row, and the figures — asking
   for column 1, which is *behind* the cursor — get pushed down to row 2. The
   numbers then float a couple of hundred pixels below the job title they
   belong to. Odd stops only looked right by luck: the role asks for column 1
   first, which wraps everything to row 2 together. */
.road__spine, .road__role, .road__figures { grid-row: 1; }

.road__role    { grid-column: 1; text-align: right; }
.road__figures { grid-column: 3; }
.road__item:nth-of-type(even) .road__role    { grid-column: 3; text-align: left; }
.road__item:nth-of-type(even) .road__figures { grid-column: 1; text-align: right; }
.road__item:nth-of-type(even) .road__figures .stat dd { margin-left: auto; }

.road__role h3 { font-size: var(--t-lg); }
/* Scoped to .road__role deliberately. A bare .road__where is one class (0,1,0)
   and loses to the `.road__role p` rule below it (0,1,1) — which is why the
   colour set here never actually applied before. */
.road__role .road__where {
  font-size: var(--t-sm);
  /* Blue rather than faded brown, so the employer and place read as their own
     line instead of disappearing under the job title. 5.2:1 on cream. */
  color: var(--blue-ink);
  letter-spacing: 0.02em;
  /* margin-block, NOT the margin shorthand. This selector outranks the
     `.road__role > p { margin-left: auto }` rule that ranges these lines
     against the spine, so a shorthand here silently resets that to 0 and the
     line drifts back to the far side of the column. */
  margin-block: 0.35rem 0.9rem;
}
.road__role p { color: var(--charcoal-60); font-size: var(--t-sm); max-width: 46ch; }
/* Body paragraphs are the unclassed ones; the reset zeroes every margin, so
   consecutive ones need their own gap. Matching on :not([class]) keeps
   .road__where and .road__links out of it — both already carry their own. */
.road__role > p:not([class]) + p:not([class]) { margin-top: 0.9rem; }
/* Every paragraph, .road__where included. It used to be excluded here, which
   left it stuck at the left of the column: its text was right-aligned but
   inside a 46ch box pinned to the wrong edge, so the line ended ~180px short of
   where the job title above it ended. */
.road__role > p { margin-left: auto; }
.road__item:nth-of-type(even) .road__role > p { margin-left: 0; margin-right: auto; }

.road__links { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; margin-top: 1rem; justify-content: flex-end; }
.road__item:nth-of-type(even) .road__links { justify-content: flex-start; }
.road__links a {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  letter-spacing: 0.05em;
  color: var(--accent-ink);
  padding-bottom: 0.2em;
  border-bottom: 1px solid var(--clay-20);
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}
.road__links a:hover { border-bottom-color: var(--accent); color: var(--charcoal); }

/* --- the numbers --- */
.road__figures { display: grid; gap: clamp(1.1rem, 2vw, 1.6rem); padding-top: 0.2rem; }
.road__figures .stat dt {
  font-size: clamp(1.5rem, 1.05rem + 1.6vw, 2.35rem);
  line-height: 1;
}
.road__figures .stat dd {
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  max-width: 28ch;
}
.road__aside {
  font-size: var(--t-sm);
  color: var(--charcoal-40);
  max-width: 30ch;
  padding-top: 0.4rem;
}

/* --- metrics grouped by platform ---
   A stop can carry four channels' worth of numbers, so each one gets its own
   labelled block. Without the label a column of big figures is just a pile of
   numbers with no way to tell which belongs to what. The headline figures stay
   large and animate; the supporting detail sits small and still underneath. */
.road__figures--multi { gap: clamp(1.6rem, 2.6vw, 2.4rem); }

.plat { display: grid; gap: 0.7rem; }

.plat__name {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent-ink);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--clay-20);
}

/* Smaller than a lone headline stat — there are up to four of these stacked. */
.road__figures--multi .stat dt { font-size: clamp(1.35rem, 1rem + 1.15vw, 1.95rem); }
.road__figures--multi .stat { gap: var(--sp-1); }

.plat__more {
  font-size: var(--t-xs);
  line-height: 1.65;
  letter-spacing: 0.01em;
  color: var(--charcoal-40);
  max-width: 34ch;
}

/* Everything ranges off the spine: whatever sits in the left column is
   right-aligned and whatever sits in the right column is left-aligned, so the
   line reads as the centre both sides work outwards from. Text-align handles
   the lines themselves; these two need margin help because they carry a
   max-width, which would otherwise leave the block itself parked on the left
   however its text is aligned. */
.road__item:nth-of-type(even) .road__figures .plat__more { margin-left: auto; }

/* --- one column on narrow screens, spine to the left --- */
@media (max-width: 900px) {
  .road::before, .road__fill { left: 5px; transform: none; }
  .road__fill { transform: scaleY(var(--road-progress, 0)); }
  .road__item {
    grid-template-columns: 1fr;
    padding-left: 2.25rem;
    gap: 1.5rem;
  }
  .road__spine {
    /* grid-column must be cleared: an absolutely positioned grid child takes
       its GRID AREA as the containing block, so leaving it on column 2 parks
       the node in a phantom column off to the right. */
    grid-column: auto;
    grid-row: auto;
    position: absolute;
    left: 0; top: clamp(2.25rem, 5vw, 4.5rem);
    justify-items: start;
    gap: 0;
    padding-top: 0;
  }
  .road__item:first-child .road__spine { top: 0; }
  .road__node { position: relative; left: 0; }
  .road__when { position: absolute; left: 1.6rem; top: -0.35rem; }
  /* One column here, so the row pinning above has to go or everything would
     land on top of itself. */
  .road__role,
  .road__figures,
  .road__item:nth-of-type(even) .road__role,
  .road__item:nth-of-type(even) .road__figures {
    grid-column: 1;
    grid-row: auto;
    text-align: left;
  }
  .road__item:nth-of-type(even) .road__figures .stat dd,
  .road__item:nth-of-type(even) .road__figures .plat__more { margin-left: 0; }
  .road__role { margin-top: 2rem; }
  .road__role > p, .road__item:nth-of-type(even) .road__role > p { margin-left: 0; margin-right: 0; }
  .road__links, .road__item:nth-of-type(even) .road__links { justify-content: flex-start; }
  .road__figures { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Platform blocks carry a label and a paragraph each, so two to a row is too
     tight to read on a phone. */
  .road__figures--multi { grid-template-columns: 1fr; }
}
@media (max-width: 520px) {
  .road__figures { grid-template-columns: 1fr; }
}

/* -- Handwritten notes -----------------------------------------------------
   Pencil on paper, not a font sitting in a box. Three things do the work:

   1. A fine, genuinely irregular hand — thick marker faces read as
      decoration, thin ones read as handwriting.
   2. A turbulence mask that erodes the stroke unevenly, so the line breaks up
      the way graphite does across a textured sheet.
   3. Rotation and position that ignore the grid. Notes ride over the edges of
      the blocks they sit beside rather than centring inside them.
   -------------------------------------------------------------------------- */
.note {
  font-family: var(--font-hand);
  font-weight: 400;
  font-size: clamp(1.05rem, 0.85rem + 0.95vw, 1.5rem);
  line-height: 1.55;
  letter-spacing: 0.01em;
  color: var(--pencil);
  max-width: 26ch;
  text-wrap: balance;
  transform: rotate(-2.4deg);
  transform-origin: left center;

  /* graphite grain — the stroke is eaten into, never solid */
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1.05 1.05 1.05 0 -0.62'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1.05 1.05 1.05 0 -0.62'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)'/%3E%3C/svg%3E");
  -webkit-mask-size: 180px 180px;
  mask-size: 180px 180px;
}

/* Every note leans differently. Nothing here should look set. */
.note--a { transform: rotate(-1.4deg); }
.note--b { transform: rotate(1.9deg); }
.note--c { transform: rotate(-3.1deg); }
.note--d { transform: rotate(2.6deg); }

.note--right  { margin-left: auto; text-align: right; transform-origin: right center; }
.note--center { margin-inline: auto; text-align: center; transform-origin: center; }
.note--big    { font-size: clamp(1.15rem, 0.92rem + 1.15vw, 1.75rem); max-width: 34ch; }
.note--moss   { color: var(--moss); }
.note--rust   { color: var(--accent-ink); }
:is(.bg-clay, .hero) .note { color: var(--cream); }

/* --- Notes that ride over the blocks --------------------------------------
   Placed at the top of a section and pulled upward, so the note straddles the
   boundary and sits on the block above. It works because a section paints
   after the one before it, so its children land on top without any z-index
   juggling. */
.note-edge {
  position: absolute;
  z-index: 6;
  top: 0;
  left: var(--gutter);
  right: var(--gutter);
  /* Lifted with margin, not transform — the reveal system sets
     `transform: none` when an element comes in, which would wipe it. */
  margin-top: clamp(-4.5rem, -5vw, -2.25rem);
  display: flex;
  pointer-events: none;
}
.note-edge > .note { max-width: min(30ch, 76vw); }
.note-edge--right  { justify-content: flex-end; }
.note-edge--indent { justify-content: flex-start; padding-left: clamp(0rem, 9vw, 8rem); }

/* A note laid over a photograph, hanging off one corner */
.note-over {
  position: absolute;
  z-index: 6;
  max-width: min(24ch, 70vw);
  pointer-events: none;
}
.note-over--bl { left: clamp(-1rem, -2vw, 0rem); bottom: clamp(-2.5rem, -4vw, -1.25rem); }
.note-over--tr { right: clamp(-1rem, -2vw, 0rem); top: clamp(-2.75rem, -4vw, -1.5rem); }

/* Hand-drawn arrow, pointing from a note to whatever it is about */
.note-arrow {
  display: block;
  width: clamp(48px, 7vw, 84px);
  height: auto;
  color: var(--pencil);
  opacity: 0.6;
  margin-top: 0.35rem;
}
.note-arrow--flip { transform: scaleX(-1); margin-left: auto; }

/* Tablets keep the overlap; only phones drop the notes back into normal flow,
   where there isn't the width to hang anything off an edge. */
@media (max-width: 640px) {
  .note, .note--right, .note--center {
    max-width: none; text-align: left;
    transform: rotate(-1.6deg); transform-origin: left center;
  }
  .note-edge {
    position: static; margin-top: 0; margin-bottom: 1.75rem;
    padding-left: 0; left: auto; right: auto;
  }
  .note-over { position: static; max-width: none; margin-top: 1.25rem; }
}

/* -- Letter-by-letter wordmark reveal --------------------------------------
   block-text-logo-terra.png is a 2 x 3 grid spelling NESTED. Each cell shows
   one sixth of the file through background-position, and the shared reveal
   system brings them in one letter at a time as the block scrolls up. */
.wordmark {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  width: clamp(150px, 24vw, 250px);
  margin-inline: auto;
}
.wordmark__cell {
  aspect-ratio: 280 / 278;      /* one cell of the 560 x 834 artwork */
  background-image: url("../images/logo/block-text-logo-terra.png");
  background-size: 200% 300%;
  background-repeat: no-repeat;
  background-position: calc(var(--col) * 100%) calc(var(--row) * 50%);
}
/* On a wide screen the six letters read better as a single line */
@media (min-width: 900px) {
  .wordmark--row { grid-template-columns: repeat(6, 1fr); width: clamp(320px, 48vw, 640px); }
}

/* -- Always / never lists -------------------------------------------------- */
.creed { display: grid; gap: var(--sp-4); }
.creed h3 {
  font-family: var(--font-display);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent-ink);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--charcoal-14);
}
.creed--never h3 { color: var(--charcoal-40); }
.creed ul { display: grid; gap: 0.6em; }
.creed li {
  position: relative;
  padding-left: 1.5em;
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: var(--t-md);
  line-height: 1.4;
  color: var(--charcoal-80);
}
.creed li::before {
  content: "+";
  position: absolute;
  left: 0; top: 0.05em;
  font-family: var(--font-body);
  font-size: 0.8em;
  color: var(--accent);
}
.creed--never li::before { content: "\00d7"; color: var(--charcoal-40); }
.creed--never li { color: var(--charcoal-40); text-decoration: line-through; text-decoration-color: var(--stone); }

/* -- Personality traits ---------------------------------------------------- */
.traits { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.traits li {
  padding: 0.55em 1.15em;
  border: 1px solid var(--stone);
  border-radius: 100px;
  font-size: var(--t-sm);
  color: var(--charcoal-80);
  background: var(--canvas);
  transition: transform 0.35s var(--ease), border-color 0.35s var(--ease), color 0.35s var(--ease);
}
.traits li:hover { border-color: var(--accent); color: var(--accent-ink); transform: translateY(-2px); }

/* -- Audience tiers -------------------------------------------------------- */
.tier { display: grid; gap: var(--sp-4); padding-top: var(--sp-5); border-top: 1px solid var(--charcoal-14); }
.tier h3 { font-size: var(--t-lg); }
.tier ul { display: grid; gap: 0.45em; }
.tier li { font-size: var(--t-sm); color: var(--charcoal-60); }

/* -- Breadcrumb / back link ------------------------------------------------ */
.back {
  display: inline-flex; align-items: center; gap: 0.6em;
  font-size: var(--t-xs); letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--charcoal-40);
  transition: color 0.3s var(--ease);
}
.back:hover { color: var(--charcoal); }

/* ==========================================================================
   11. FOOTER
   ========================================================================== */

.footer {
  background: var(--mist);
  color: var(--charcoal);
  padding-top: clamp(3.5rem, 7vw, 6rem);
  padding-bottom: var(--sp-6);
}
.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 0.8fr));
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(2.5rem, 5vw, 4rem);
}
.footer__brand { display: grid; gap: var(--sp-5); align-content: start; }
.footer__word {
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: var(--t-lg);
  line-height: 1.35;
  max-width: 16ch;
}
.footer__col h4 {
  font-family: var(--font-body);
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: var(--sp-4);
}
.footer__col ul { display: grid; gap: 0.7rem; }
.footer__col a {
  font-size: var(--t-sm);
  color: var(--charcoal-80);
  transition: color 0.3s var(--ease);
  position: relative;
}
.footer__col a:hover { color: var(--accent-ink); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  align-items: center;
  justify-content: space-between;
  padding-top: var(--sp-5);
  border-top: 1px solid var(--ink-20);
  font-size: var(--t-xs);
  letter-spacing: 0.08em;
  color: var(--charcoal-60);
}
.footer__bottom a:hover { color: var(--accent-ink); }
.footer__legal { display: flex; gap: var(--sp-5); flex-wrap: wrap; }

.social { display: flex; gap: var(--sp-4); }
.social a {
  font-size: var(--t-xs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--charcoal-80);
  padding-bottom: 0.3em;
  border-bottom: 1px solid transparent;
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.social a:hover { color: var(--accent-ink); border-bottom-color: var(--accent); }

/* Big footer wordmark — pressed into the page */
/* Was an outlined "NESTED" wordmark across the full width; it's the circle mark
   now, which carries the branding without shouting. */
.footer__stamp {
  display: grid;
  justify-items: center;
  padding-block: clamp(1.75rem, 4vw, 3.25rem) 0;
  user-select: none;
}
.footer__stamp img {
  width: clamp(70px, 9vw, 104px);
  height: auto;
  opacity: 0.85;
}

/* ==========================================================================
   12. MOTION & REVEAL
   ========================================================================== */

/* All reveal styling is gated behind .js (set by an inline script in <head>).
   Without JavaScript the page renders fully visible instead of blank. */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity var(--dur-slow) var(--ease-soft),
    transform var(--dur-slow) var(--ease-soft);
  transition-delay: var(--delay, 0ms);
  will-change: opacity, transform;
}
.js [data-reveal].is-in { opacity: 1; transform: none; will-change: auto; }

.js [data-reveal="fade"] { transform: none; }
.js [data-reveal="right"] { transform: translateX(-28px); }
.js [data-reveal="scale"] { transform: scale(0.97); }

/* Curtain reveal for images */
.js [data-reveal="curtain"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 0 100% 0);
  transition: clip-path 1.35s var(--ease-soft);
  transition-delay: var(--delay, 0ms);
}
.js [data-reveal="curtain"].is-in { clip-path: inset(0 0 0 0); }

/* Line-by-line heading reveal.
   The padding/negative-margin pair gives descenders somewhere to live —
   without it, overflow:hidden shears the tail off every g, y and p. */
.line-mask {
  display: block;
  overflow: hidden;
  padding-bottom: 0.18em;
  margin-bottom: -0.18em;
}
.js .line-mask > span {
  display: block;
  transform: translateY(105%);
  transition: transform 1.05s var(--ease-soft);
  transition-delay: var(--delay, 0ms);
}
.js .is-in .line-mask > span,
.js .line-mask.is-in > span { transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; clip-path: none !important; }
  .line-mask > span { transform: none !important; }
  .marquee__track { animation: none; }
  .stamp__ring { animation: none; }
}

/* ==========================================================================
   13. RESPONSIVE
   ========================================================================== */

@media (max-width: 1100px) {
  .footer__top { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); row-gap: var(--sp-7); }
  .footer__brand { grid-column: 1 / -1; }
  .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pillar__body { grid-template-columns: 1fr; gap: var(--sp-3); }
}

@media (max-width: 900px) {
  .nav, .header__cta { display: none; }
  .burger { display: block; }

  .grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sec-head--split { grid-template-columns: 1fr; align-items: start; }
  .split { grid-template-columns: 1fr; gap: var(--sp-6); }
  .split--reverse .split__media { order: 0; }
  .post--feature { grid-template-columns: 1fr; }
  .post--feature .img { margin-bottom: var(--sp-5); }

  .pair { grid-template-columns: 1fr; gap: var(--sp-5); }
  .pair__b { width: 100%; }
}

@media (max-width: 640px) {
  .grid--2, .grid--3, .grid--4 { grid-template-columns: minmax(0, 1fr); }
  .form__row { grid-template-columns: minmax(0, 1fr); }
  .pillar { grid-template-columns: 1fr; gap: var(--sp-3); }
  .tl { grid-template-columns: 1fr; gap: var(--sp-2); }
  .pillar .index-num { display: block; }
  .hero__row { align-items: flex-start; }
  .hero__actions { width: 100%; }
  .hero__actions .btn { flex: 1 1 auto; }
  .scroll-cue { display: none; }
  .logos { gap: var(--sp-6); }
  .footer__top { grid-template-columns: 1fr; }
  .footer__bottom { justify-content: flex-start; }
  .quote blockquote { max-width: none; }
}

/* Print — a clean, ink-saving fallback */
@media print {
  .header, .menu, .footer__stamp, .btn, .scroll-cue, body::after { display: none !important; }
  body { background: #fff; color: #000; }
  .img { border: 1px solid #ccc; }
}

/* -- Route map (journal lead) ----------------------------------------------
   A Strava-ish loop drawn over a photograph. The route is real: stop
   latitude/longitude projected equirectangular with a cos(lat) correction, so
   the shape is the actual South Island loop rather than a doodle. Generated by
   scratchpad/routemap.py; paste its output in if the stops ever change.

   Cream lines need a dark ground to read against, hence the scrim. Every line
   is drawn twice, a dark wide copy under a thin cream one, and the labels use
   paint-order to carry their own halo, so nothing disappears into a bright
   patch of photograph. */
.routemap {
  position: relative;
  aspect-ratio: 4 / 5;
  max-width: 620px;
  margin-inline: auto;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--charcoal);
}
.routemap img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Knocks the photograph back far enough for cream to sit on it, darkest at the
   top and bottom where the title and the southern stops sit. */
.routemap__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom, rgba(31,26,25,0.66) 0%, rgba(31,26,25,0.44) 38%,
                               rgba(31,26,25,0.48) 70%, rgba(31,26,25,0.70) 100%),
    rgba(31,26,25,0.22);
}
.routemap__svg { position: absolute; inset: 0; width: 100%; height: 100%; }

.routemap__track,
.routemap__track2,
.routemap__spur,
.routemap__leader { fill: none; stroke-linecap: round; stroke-linejoin: round; }

/* All white, no dark outline anywhere. Two passes of the same wobbled route at
   different strengths read as one hand-drawn line gone over twice, which is
   what gives it the sketched feel. Legibility comes from the scrim under it
   rather than from a black stroke. */
/* Route in terracotta, labels in white. --accent-soft is a lifted rust: the
   flat brand rust goes muddy against a darkened photograph, where a drawn line
   needs to stay visible at 2px. */
.routemap__track  { stroke: var(--accent-soft); stroke-width: 2.6; }
.routemap__track2 { stroke: var(--accent-soft); stroke-width: 1.6; opacity: 0.5; }
.routemap__spur   { stroke: var(--accent-soft); stroke-width: 2; stroke-dasharray: 7 9; }
.routemap__leader { stroke: rgba(250,244,234,0.55); stroke-width: 1; }

.routemap__dot        { fill: var(--accent-soft); }
.routemap__dot--minor { fill: var(--accent-soft); opacity: 0.85; }
.routemap__start      { fill: none; stroke: var(--accent-soft); stroke-width: 1.8; }

/* DaisyWheel, uppercase. Elza is kept in the stack on purpose: DaisyWheel has
   no macrons, so the Ā in WĀNAKA and the Ō in KAIKŌURA come from Elza. It also
   has no en or em dash, which is why the date line reads "5 TO 30". */
.routemap text {
  font-family: var(--font-display), var(--font-body);
  text-transform: uppercase;
  fill: var(--cream);
}
.routemap__labels text     { font-size: 16px; letter-spacing: 0.05em; }
.routemap__title           { font-size: 30px; letter-spacing: 0.22em; }
.routemap__sub             { font-size: 13px; letter-spacing: 0.12em; fill: rgba(250,244,234,0.78); }
.routemap__startlabel      { font-size: 12px; letter-spacing: 0.18em; fill: rgba(250,244,234,0.8); }

/* On a phone the whole thing is ~360px wide, so 17px of viewBox text lands at
   about 7px on screen. The secondary stops drop out and everything else grows;
   the route itself is unchanged. */
@media (max-width: 700px) {
  .routemap__label--minor { display: none; }
  /* 25px is the ceiling: at 30px the long labels (ABEL TASMAN,
     CHRISTCHURCH) grow wider than the gutter and clip on the frame edge,
     since label positions are fixed in viewBox units. Verified with getBBox
     at 375px. */
  .routemap__labels text  { font-size: 24px; letter-spacing: 0.02em; }
  .routemap__title        { font-size: 46px; }
  .routemap__sub          { font-size: 22px; }
  .routemap__track        { stroke-width: 3.6; }
  .routemap__track2       { stroke-width: 2.2; }
  .routemap__spur         { stroke-width: 2.9; stroke-dasharray: 10 12; }
  .routemap__leader       { stroke-width: 1.6; }
  .routemap__dot          { r: 6; }
}
.routemap__sublabel { font-size: 11px; letter-spacing: 0.1em; fill: rgba(250,244,234,0.78); }
@media (max-width: 700px) { .routemap__sublabel { font-size: 19px; } }

/* -- "Who I work with" disclosure ------------------------------------------
   Replaces the old scrolling marquee: the bird is the handle, and the list
   drops down when you click it. Same 0fr/1fr grid trick as the FAQ, which
   animates to the content's real height without hard-coding one.

   The collapse is deliberately gated behind html.js. With JavaScript off the
   button can't do anything, so the panel stays open rather than sealing the
   list away where nobody can reach it. */
.places {
  border: 1px solid var(--charcoal-14);
  border-radius: var(--radius);
  background: var(--canvas);
  overflow: hidden;
}
.places__toggle {
  width: 100%;
  display: flex;
  align-items: center;
  gap: clamp(0.9rem, 2vw, 1.4rem);
  padding: clamp(1rem, 2.2vw, 1.35rem) clamp(1.1rem, 2.5vw, 1.75rem);
  text-align: left;
  font-family: var(--font-display);
  font-size: var(--t-md);
  font-weight: 400;
  line-height: 1.3;
  color: var(--charcoal);
  transition: color 0.3s var(--ease);
}
.places__toggle:hover { color: var(--accent); }

.places__mark { width: clamp(30px, 4.5vw, 40px); flex: none; display: block; }
.places__mark img {
  width: 100%; height: auto; display: block;
  transition: transform 0.5s var(--ease-soft);
}
.places__toggle[aria-expanded="true"] .places__mark img { transform: rotate(-9deg) scale(1.08); }

.places__title { flex: 1 1 auto; }

/* Same plus-to-minus mark the FAQ uses, so the gesture is already familiar. */
.places__icon { position: relative; width: 14px; height: 14px; flex: none; }
.places__icon::before, .places__icon::after {
  content: "";
  position: absolute;
  background: currentColor;
  transition: transform 0.4s var(--ease-soft), opacity 0.3s var(--ease);
}
.places__icon::before { top: 50%; left: 0; width: 100%; height: 1px; transform: translateY(-50%); }
.places__icon::after  { left: 50%; top: 0; height: 100%; width: 1px; transform: translateX(-50%); }
.places__toggle[aria-expanded="true"] .places__icon::after { transform: translateX(-50%) rotate(90deg); opacity: 0; }

.places__panel { display: grid; grid-template-rows: 1fr; }
html.js .places__panel {
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s var(--ease-soft);
}
html.js .places__toggle[aria-expanded="true"] + .places__panel { grid-template-rows: 1fr; }
.places__panel > div { overflow: hidden; }

.places__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 0.6rem clamp(1rem, 3vw, 2.5rem);
  padding: 0 clamp(1.1rem, 2.5vw, 1.75rem);
  border-top: 1px solid var(--charcoal-14);
  padding-top: clamp(1.1rem, 2.4vw, 1.6rem);
}
.places__list li {
  position: relative;
  padding-left: 1.1em;
  font-size: var(--t-sm);
  color: var(--charcoal-60);
}
.places__list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.72em;
  width: 0.45em; height: 1px;
  background: var(--accent);
}
/* No max-width here. It used to be capped at 58ch, which forced the sentence
   onto two lines at every width; she wants the whole thing plus its link to
   read as one line. It runs as one line from 900px up and wraps below that,
   which is right: white-space: nowrap would push the arrow off a phone. */
/* The link sits on its own line under the sentence, not trailing it (22 Sep
   2026). justify-items:start keeps it to its own width so the underline rule
   draws under the words rather than the full column. */
.places__note {
  display: grid;
  justify-items: start;
  gap: clamp(0.9rem, 2vw, 1.2rem);
  font-size: var(--t-sm);
  color: var(--charcoal-60);
  padding: clamp(1.1rem, 2.4vw, 1.5rem) clamp(1.1rem, 2.5vw, 1.75rem) clamp(1.2rem, 2.6vw, 1.75rem);
}
.places__note p { max-width: 62ch; }

/* -- Work card gallery ------------------------------------------------------
   Each card gets a button stretched over it rather than being a button itself:
   a <button> can't legally contain an <h3>, and wrapping the card in a link
   would fight the dialog. The stretched button keeps the whole card clickable
   and gives keyboard users one focus stop with a real label. */
.work-card { position: relative; }
.work-card__open {
  position: absolute;
  inset: 0;
  width: 100%;
  cursor: pointer;
  border-radius: var(--radius);
}
.work-card__open:focus-visible { outline: 2px solid var(--accent); outline-offset: 6px; }
.work-card:hover .img img { transform: scale(1.03); }
.work-card .img img { transition: transform 0.7s var(--ease-soft); }
.work-card .img { overflow: hidden; }

/* -- Lightbox -------------------------------------------------------------- */
.lightbox { position: fixed; inset: 0; z-index: 200; }
.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(31, 26, 25, 0.72);
  backdrop-filter: blur(3px);
  animation: lb-fade 0.3s var(--ease) both;
}
.lightbox__panel {
  position: relative;
  max-width: min(980px, 100% - 2rem);
  max-height: calc(100dvh - 2rem);
  margin: 1rem auto;
  top: 50%;
  transform: translateY(-50%);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--canvas);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.75rem);
  animation: lb-rise 0.4s var(--ease-soft) both;
}
@keyframes lb-fade { from { opacity: 0 } to { opacity: 1 } }
@keyframes lb-rise { from { opacity: 0; transform: translateY(calc(-50% + 14px)) } }
@media (prefers-reduced-motion: reduce) {
  .lightbox__backdrop, .lightbox__panel { animation: none; }
}

.lightbox__head { margin-bottom: clamp(1.25rem, 3vw, 1.9rem); padding-right: 3rem; }
.lightbox__head h2 { margin-top: 0.6rem; }

.lightbox__close {
  position: absolute;
  top: clamp(0.9rem, 2.5vw, 1.4rem);
  right: clamp(0.9rem, 2.5vw, 1.4rem);
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid var(--charcoal-14);
  border-radius: 50%;
  cursor: pointer;
  transition: border-color 0.3s var(--ease), color 0.3s var(--ease);
}
.lightbox__close:hover { border-color: var(--accent); color: var(--accent); }
.lightbox__close span { position: relative; width: 13px; height: 13px; display: block; }
.lightbox__close span::before, .lightbox__close span::after {
  content: ""; position: absolute; top: 50%; left: 0;
  width: 100%; height: 1px; background: currentColor;
}
.lightbox__close span::before { transform: rotate(45deg); }
.lightbox__close span::after  { transform: rotate(-45deg); }

.lightbox__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.5rem, 1.5vw, 0.9rem);
}
/* A place with one photograph shouldn't render as a lonely quarter-tile. */
.lightbox__grid[data-count="1"] { grid-template-columns: minmax(0, 1fr); }
.lightbox__grid figure { margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--oat); }
.lightbox__grid img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4 / 3; }
.lightbox__grid[data-count="1"] img { aspect-ratio: 3 / 2; }

.lightbox__foot { margin-top: clamp(1.4rem, 3vw, 2rem); display: flex; justify-content: center; }

@media (max-width: 560px) {
  .lightbox__grid { grid-template-columns: minmax(0, 1fr); }
  .lightbox__panel { padding: clamp(1.1rem, 5vw, 1.6rem); }
}
