/* =========================================================
   MAYA'S HOMES V2 — design system
   Luxury furniture aesthetic: warm bone, deep ink, restrained ochre.
   ========================================================= */

:root {
  /* — Colour: warm, restrained, photographic — */
  --bone: #F4EFE6;
  --bone-2: #ECE5D8;
  --paper: #F8F6EE;
  --ink: #2D2926;
  --ink-2: #4A4540;
  --mid: #6B5F52;
  --soft: #9A8E7E;
  --hairline: rgba(45, 41, 38, 0.14);
  --hairline-strong: rgba(45, 41, 38, 0.30);
  --tobacco: #8B6F47;
  --ochre: #B98A4A;

  /* — Tonal rhythm: olive (spine), chestnut (bookends), cream typography — */
  --shadow: #4A4E2E;
  --chestnut: #6B4530;
  --bone-on-shadow: #F4EFE6;
  --mid-on-shadow: #CCC0AB;
  --bone-on-chestnut: #F4EFE6;
  --mid-on-chestnut: #D4C5B5;

  /* — Calm rest state: warm putty-cream backdrop for closing sections — */
  --taupe: #FAF5EC;

  /* — Type — */
  --serif: 'Cormorant Garamond', 'Playfair Display', Georgia, 'Times New Roman', serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', 'SFMono-Regular', Menlo, Consolas, 'Courier New', monospace;

  /* — Scale (fluid) — */
  --fs-xs: clamp(11px, 0.72vw, 12px);
  --fs-sm: clamp(13px, 0.92vw, 15px);
  --fs-base: clamp(15px, 1.05vw, 17px);
  --fs-lg: clamp(18px, 1.3vw, 21px);
  --fs-xl: clamp(28px, 3vw, 44px);
  --fs-2xl: clamp(44px, 5.5vw, 88px);
  --fs-3xl: clamp(64px, 9vw, 168px);

  /* — Rhythm — */
  --pad-section: clamp(96px, 12vw, 220px);
  --pad-x: clamp(24px, 5vw, 96px);
  --gutter: clamp(16px, 1.5vw, 28px);
  --container: 1480px;
  /* Section-content envelopes (used inside the page-margin .wrap utility).
     --container-max is the default width for editorial sections; the
     two narrower tokens are reserved for moments where tighter framing
     is the design intent (spine quote, letter, prose-only columns). */
  --container-max: 1480px;
  --container-narrow: 900px;
  --container-prose: 720px;

  /* — Motion — */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* — Projects grid: paper-channel seams between photos on the
       paper card. Halved again to clamp(4-8 px) — collage seams,
       not separator bands. — */
  --tile-gap: clamp(4px, 0.5vw, 8px);
}

/* — Reset — */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; scroll-behavior: smooth; }
html, body { height: 100%; }
/* Defensive: prevent horizontal page overflow site-wide so the
   fixed-position floating-nav stays anchored to the visible viewport.
   Using `clip` instead of `hidden` because `hidden` establishes a
   scroll container, which breaks every descendant `position: sticky`
   (the Cascais-biography portrait, the Welcome-to-Maja's-home video,
   the On-this-coast van photo all need to stick on scroll). */
html, body { overflow-x: clip; }
body {
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0.005em;
  overflow-x: clip;
  position: relative;
}

/* Body-level subtle noise — barely perceptible, makes the limestone feel physical. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/></svg>");
  opacity: 0.04;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 0;
}
img, video, svg { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--ink); color: var(--bone); }

/* Caption voice — IBM Plex Mono, the third typeface used only for
   figcaptions. Reads as field note / metadata, distinct from
   Cormorant (headlines) and Inter (body). Per-element rules below
   may override size / colour / placement, but font-family stays. */
figcaption {
  font-family: var(--mono);
  font-style: normal;
  letter-spacing: 0.02em;
}

/* — Type primitives — */
.display {
  font-family: var(--serif);
  font-weight: 400;
  font-size: var(--fs-2xl);
  line-height: 1.1;
  padding-bottom: 0.1em;
  letter-spacing: -0.022em;
  color: var(--ink);
}
.display em {
  font-style: italic;
  font-weight: 400;
  color: var(--ink-2);
  /* Italic glyphs lean rightward and overshoot their bounding box.
     A small padding-right gives them breathing room so they aren't
     clipped by the .word overflow: hidden wrapper used for the
     slide-up reveal. */
  padding-right: 0.08em;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--mid);
}
.eyebrow .dot {
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--tobacco);
  box-shadow: 0 0 0 4px rgba(139, 111, 71, 0.12);
}

/* =========================================================
   FLOATING NAV
   ========================================================= */
.nav {
  position: fixed;
  top: 18px;
  left: 50%;
  transform: translate(-50%, -120%);
  z-index: 80;
  /* Width fits the content — nav pill hugs the logo, links, and CTA
     instead of stretching across the viewport. */
  width: fit-content;
  max-width: calc(100% - 32px);
  transition: transform 600ms var(--ease-out), opacity 400ms var(--ease-out);
  opacity: 0;
  pointer-events: none;
  will-change: transform, opacity;
}
.nav.is-visible {
  transform: translate(-50%, 0);
  opacity: 1;
  pointer-events: auto;
}
.nav__inner {
  display: grid;
  grid-template-columns: auto auto auto;
  align-items: center;
  gap: clamp(18px, 2vw, 36px);
  padding: 10px 14px 10px 20px;
  /* Default: transparent — no chrome at all. Glassmorphism is added
     once the user starts scrolling via .nav.is-scrolled. */
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 1px solid transparent;
  border-radius: 999px;
  box-shadow: none;
  transition: background 380ms var(--ease-out),
              backdrop-filter 380ms var(--ease-out),
              -webkit-backdrop-filter 380ms var(--ease-out),
              border-color 380ms var(--ease-out),
              box-shadow 380ms var(--ease-out);
}
/* Once the brand lands: subtle glass — 55% bone, gentle blur,
   hairline border, faint shadow. Just enough to seat the wordmark. */
.nav.is-scrolled .nav__inner {
  background: rgba(244, 239, 230, 0.55);
  backdrop-filter: blur(14px) saturate(135%);
  -webkit-backdrop-filter: blur(14px) saturate(135%);
  border-color: var(--hairline);
  box-shadow: 0 8px 28px -16px rgba(20, 17, 14, 0.14),
              inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--serif);
  font-size: var(--fs-lg);
  font-weight: 500;
  letter-spacing: -0.01em;
  /* Collapsed by default — GSAP scrub expands maxWidth as the hero
     brand migrates into the header. min-width: max-content guarantees
     the slot never undercuts the wordmark's natural width once it
     becomes visible (post-flight) — was clipping 'MAYA'S HOMES' to
     'MAYA' when the GSAP target left it sub-pixel under the rendered
     text width. min-width overrides max-width per CSS spec. */
  max-width: 0;
  min-width: 0;
  overflow: hidden;
}
.nav.is-visible .nav__brand {
  min-width: max-content;
}
.nav__brand-logo {
  height: clamp(28px, 3.4vw, 38px);
  width: auto;
  object-fit: contain;
  display: block;
}
/* Wordmark in the header — wide-spaced, restrained, high-end serif.
   Hidden until the hero brand has migrated into the header (GSAP
   scrub crossfades opacity 0 → 1 in the last sliver of the flight). */
.nav__brand-name {
  display: inline-block;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(13px, 1.05vw, 16px);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
  opacity: 0;
  will-change: opacity;
}
.nav__links {
  display: flex; align-items: center;
  justify-content: center;
  gap: clamp(18px, 2.5vw, 38px);
  font-size: var(--fs-sm);
  color: var(--ink-2);
}
.nav__links a {
  position: relative;
  padding: 4px 0;
  letter-spacing: 0.01em;
  white-space: nowrap;
  transition: color 280ms var(--ease-out);
}
.nav__links a::after {
  content: '';
  position: absolute; left: 0; right: 100%; bottom: 0;
  height: 1px; background: var(--ink);
  transition: right 380ms var(--ease-out);
}
.nav__links a:hover { color: var(--ink); }
.nav__links a:hover::after { right: 0; }

/* CTA — dark-silver pill with a mouse-tracked radial shine + subtle
   3D tilt that follows the cursor. ::before is the cursor-tracked
   highlight (driven by --shine-x/-y custom properties from JS);
   ::after is the always-on horizontal polish line. */
/* =========================================================
   Unified ivory pill — one polished pebble across every primary
   CTA. Loro Piana / Aman: paler ivory gradient (top brighter,
   bottom warmer) for curvature, thin warm rim, soft top gleam,
   cursor-tracked inner bloom (no blend mode dramatics), two-
   layer ambient + lifted drop shadow. Backdrop-filter is gentle
   (blur 18 / sat 150%) — the goal is polished ivory, not frosted
   glass. Sample classes: nav CTA, contact submit, footer outro,
   .btn-glass; reserved future hooks: .project-tile__cta,
   .process-card__reveal.

   Why two pseudo-elements:
     ::before — top specular gleam (45% height, 999/0 radius)
     ::after  — cursor-tracked inner light (110 px radial, no
                blend mode, opacity 0 → 1 on hover)
   ========================================================= */
.nav__cta,
.contact__submit,
.footer__outro-cta,
.btn-glass,
.btn-silver,
.project-tile__cta,
.process-card__reveal {
  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Canonical pill — shape from /studio/ §05 on-card "View Project"
     pill, colour from §05 below-card "View All Projects" pill.
     Same shape + colour as every other button on the site. */
  padding: 12px 24px;
  border-radius: 999px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  color: var(--ink);
  cursor: pointer;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.45);

  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.16) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);

  box-shadow:
    0  8px 32px rgba(0, 0, 0, 0.08),
    0  2px  6px rgba(0, 0, 0, 0.04),
    inset 0  1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);

  transform:
    translate3d(var(--translate-x, 0), var(--translate-y, 0), 0)
    perspective(800px)
    rotateX(var(--rotate-x, 0deg))
    rotateY(var(--rotate-y, 0deg));

  transition:
    box-shadow   0.5s cubic-bezier(0.2, 0.8, 0.2, 1),
    transform    0.2s cubic-bezier(0.2, 0.8, 0.2, 1),
    border-color 0.5s ease;

  will-change: transform;
}

/* Top gleam — soft sliver of light along the upper rim. */
.nav__cta::before,
.contact__submit::before,
.footer__outro-cta::before,
.btn-glass::before,
.btn-silver::before,
.project-tile__cta::before,
.process-card__reveal::before {
  content: "";
  position: absolute;
  inset: 1px 1px auto 1px;
  height: 45%;
  border-radius: 999px 999px 0 0;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.65) 0%,
    rgba(255, 255, 255, 0.18) 55%,
    rgba(255, 255, 255, 0)    100%
  );
  pointer-events: none;
  z-index: 1;
  opacity: 0.85;
}

/* Cursor-tracked inner light — quiet warm bloom; no blend mode. */
.nav__cta::after,
.contact__submit::after,
.footer__outro-cta::after,
.btn-glass::after,
.btn-silver::after,
.project-tile__cta::after,
.process-card__reveal::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    110px circle at var(--shine-x, 50%) var(--shine-y, 0%),
    rgba(255, 250, 235, 0.55),
    rgba(255, 250, 235, 0) 70%
  );
  pointer-events: none;
  z-index: 0;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.nav__cta > *,
.contact__submit > *,
.footer__outro-cta > *,
.btn-glass > *,
.btn-silver > *,
.project-tile__cta > *,
.process-card__reveal > * {
  position: relative;
  z-index: 2;
}

/* Hover — lift the ambient shadow + brighten the glassy rim. */
.nav__cta:hover,
.contact__submit:hover,
.footer__outro-cta:hover,
.btn-glass:hover,
.btn-silver:hover,
.project-tile__cta:hover,
.process-card__reveal:hover {
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow:
    0 12px 36px rgba(0, 0, 0, 0.10),
    0  3px  8px rgba(0, 0, 0, 0.05),
    inset 0  1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
}

.nav__cta:hover::after,
.contact__submit:hover::after,
.footer__outro-cta:hover::after,
.btn-glass:hover::after,
.btn-silver:hover::after,
.project-tile__cta:hover::after,
.process-card__reveal:hover::after {
  opacity: 1;
}

.nav__cta:active,
.contact__submit:active,
.footer__outro-cta:active,
.btn-glass:active,
.btn-silver:active,
.project-tile__cta:active,
.process-card__reveal:active {
  transform:
    translate3d(var(--translate-x, 0), var(--translate-y, 0), 0)
    perspective(800px)
    rotateX(var(--rotate-x, 0deg))
    rotateY(var(--rotate-y, 0deg))
    scale(0.985);
}

/* Arrow animation — any arrow inside a canonical glass button
   translates 8px right on parent hover, with a single eased timing
   shared across the whole site. */
.nav__cta .btn-arrow,
.contact__submit .btn-arrow,
.footer__outro-cta .btn-arrow,
.btn-glass .btn-arrow,
.btn-silver .btn-arrow,
.project-tile__cta .btn-arrow,
.process-card__reveal .btn-arrow {
  display: inline-block;
  transition: transform 400ms cubic-bezier(0.2, 0.8, 0.2, 1);
  will-change: transform;
}
.nav__cta:hover .btn-arrow,
.nav__cta:focus-visible .btn-arrow,
.contact__submit:hover .btn-arrow,
.contact__submit:focus-visible .btn-arrow,
.footer__outro-cta:hover .btn-arrow,
.footer__outro-cta:focus-visible .btn-arrow,
.btn-glass:hover .btn-arrow,
.btn-glass:focus-visible .btn-arrow,
.btn-silver:hover .btn-arrow,
.btn-silver:focus-visible .btn-arrow,
.project-tile__cta:hover .btn-arrow,
.project-tile__cta:focus-visible .btn-arrow,
.process-card__reveal:hover .btn-arrow,
.process-card__reveal:focus-visible .btn-arrow {
  transform: translateX(8px);
}

/* Backdrop-filter fallback — keep button readable in old browsers. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav__cta,
  .contact__submit,
  .footer__outro-cta,
  .btn-glass,
  .btn-silver,
  .project-tile__cta,
  .process-card__reveal {
    background: rgba(255, 253, 247, 0.92);
  }
}

/* Nav-only safety: the wordmark must never get clipped by the
   parent flex grid. Visual treatment fully inherited. */
.nav__cta {
  white-space: nowrap;
  min-width: max-content;
  flex-shrink: 0;
}
.nav__cta svg {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  transition: transform 320ms var(--ease-out);
}
.nav__cta:hover svg { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .nav__cta,
  .contact__submit,
  .footer__outro-cta,
  .btn-glass {
    transform: none !important;
  }
}

@media (max-width: 960px) {
  /* Allow the nav row to scroll horizontally rather than wrap when
     the items don't fit at intermediate widths. */
  .nav__inner {
    overflow-x: auto;
    max-width: 100%;
  }
}
@media (max-width: 760px) {
  .nav__links { display: none; }
  .nav__inner { grid-template-columns: auto auto; }
}

/* =========================================================
   CINEMATIC INTRO — doors-opening video + composed typography
   ========================================================= */
.intro {
  position: relative;
  height: 100vh;
  min-height: 640px;
  width: 100%;
  background: var(--bone);
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Video plays once on entry, freezes on its final frame.
   That frozen frame becomes the persistent hero background
   beneath the composed typography. */
.intro__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 1;
  pointer-events: none;
}

.intro__brand {
  position: relative;
  display: grid;
  place-items: center;
  text-align: center;
  pointer-events: none;
  z-index: 4;
}
.intro__brand-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0;
  padding: 0 var(--pad-x);
  max-width: 1280px;
  position: relative;
  /* Lifted toward the upper half of the hero, but ~7-8 vh lower than
     the previous tuning so the cluster doesn't crowd the top edge.
     Internal spacing between wordmark / hook / guarantees unchanged. */
  transform: translateY(-7vh);
}
@media (max-width: 720px) {
  .intro__brand-inner { transform: translateY(-3vh); }
}

/* The wordmark — sits at the top of the cluster. Letter-by-letter
   build via JS-wrapped spans (the typographic build animation,
   currently inert under .intro--settled). */
.intro__name {
  font-family: var(--serif);
  font-weight: 200;
  font-size: clamp(30px, 5.25vw, 72px);
  letter-spacing: 0.15em;
  text-indent: 0.15em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1;
  /* Tightened from clamp(56, 8vh, 88) — about half the previous breath. */
  margin: 0 0 clamp(20px, 3vh, 36px);
}
.intro__name .build-letter {
  display: inline-block;
  opacity: 0;
  transform: translateY(8px);
  filter: blur(4px);
  animation: build-letter-in 600ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes build-letter-in {
  to {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
  }
}

/* Hook — italic Cormorant, sits beneath the wordmark. */
.intro__hook {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(16.5px, 2.55vw, 36px);
  line-height: 1.05;
  letter-spacing: -0.012em;
  color: var(--ink);
  /* Tightened from clamp(28, 4vh, 44). */
  margin: 0 auto clamp(20px, 3vh, 32px);
  max-width: 22ch;
}
.intro__hook em { font-style: italic; }

/* Guarantee lines — tracked uppercase, sit below the hook. */
.intro__guarantee {
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(11px, 0.92vw, 14px);
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--ink-2);
  opacity: 0.86;
  line-height: 1;
  margin: 0 0 8px;
}
.intro__guarantee:last-of-type {
  margin-bottom: 0;
}

/* Build-line elements: hook + guarantees, sequenced after the wordmark. */
[data-build-line] {
  opacity: 0;
  transform: translateY(6px);
  animation: build-line-in 700ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes build-line-in {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Scroll cue — text only, no animated line beneath. */
.intro__cue {
  position: absolute;
  left: 50%;
  bottom: clamp(28px, 5vh, 60px);
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  color: rgba(20, 17, 14, 0.7);
  opacity: 0;
  z-index: 6;
  pointer-events: none;
}

/* Scroll lock while intro plays. Applied to <html> via JS. */
html.is-intro,
html.is-intro body {
  overflow: hidden;
  height: 100vh;
}

/* Settled state: locks every animated element into its end position.
   Whether the user watched the doors-opening video play through OR
   skipped via the intro gate, the resulting hero is the composed
   final frame. The video freezes naturally on its last decoded
   frame; var(--bone) fallback covers the brief moment before the
   video paints. */
.intro--settled .build-letter,
.intro--settled [data-build-line] {
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
  animation: none !important;
}

/* — Hero state machine: gate → playing → revealed. — */
.intro[data-intro-state="gate"] .intro__brand,
.intro[data-intro-state="playing"] .intro__brand {
  opacity: 0;
  pointer-events: none;
  transition: opacity 600ms ease;
}
.intro[data-intro-state="revealed"] .intro__brand {
  opacity: 1;
  transition: opacity 800ms ease 200ms;
}

/* — Intro gate: anchored to the bottom third of the hero so the
     'Enter' gesture aligns with the door area of the freeze frame
     rather than floating mid-sky. Frosted-glass primary + italic
     skip link beneath. — */
.intro__gate {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  padding-bottom: clamp(80px, 18vh, 200px);
  gap: 18px;
  z-index: 10;
  transition: opacity 400ms ease;
  /* Let clicks pass through the empty padding zone so hero content
     beneath isn't blocked; the buttons themselves opt back in below. */
  pointer-events: none;
}
.intro__gate-enter,
.intro__gate-skip {
  pointer-events: auto;
}
.intro[data-intro-state="playing"] .intro__gate,
.intro[data-intro-state="revealed"] .intro__gate {
  opacity: 0;
  pointer-events: none;
}

/* Frosted-glass primary pill — semi-transparent so the bougainvillea
   / tile texture stays subtly visible through it. Hotel signage
   register, not chrome. */
.intro__gate-enter {
  position: relative;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  font-weight: 500;
  padding: 18px 56px;
  color: rgba(255, 255, 255, 0.95);
  cursor: pointer;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.5);
  background: rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.3),
    inset 0 -1px 0 rgba(0, 0, 0, 0.06),
    0 4px 22px rgba(0, 0, 0, 0.12),
    0 1px 3px rgba(0, 0, 0, 0.08);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18);
  transition:
    background 280ms ease,
    border-color 280ms ease,
    transform 280ms ease,
    letter-spacing 280ms ease,
    box-shadow 280ms ease;
}

/* Backdrop-filter fallback for browsers without support. */
@supports not (backdrop-filter: blur(1px)) {
  .intro__gate-enter {
    background: rgba(255, 255, 255, 0.32);
  }
}

.intro__gate-enter:hover {
  background: rgba(255, 255, 255, 0.22);
  border-color: rgba(255, 255, 255, 0.7);
  transform: translateY(-1px);
  letter-spacing: 0.42em;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.42),
    inset 0 -1px 0 rgba(0, 0, 0, 0.06),
    0 6px 28px rgba(0, 0, 0, 0.16),
    0 2px 5px rgba(0, 0, 0, 0.1);
}
.intro__gate-enter:active {
  transform: translateY(0);
  background: rgba(255, 255, 255, 0.16);
}

/* Tertiary skip link — italic, thin underline, soft text-shadow for
   readability against bright backgrounds. */
.intro__gate-skip {
  font-family: var(--sans);
  font-size: 12px;
  font-style: italic;
  letter-spacing: 0.04em;
  background: transparent;
  border: 0;
  color: rgba(255, 255, 255, 0.85);
  cursor: pointer;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  padding: 6px 10px;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
  transition: color 200ms ease;
}
.intro__gate-skip:hover {
  color: #ffffff;
}

/* =========================================================
   MANIFESTO — Maja as problem-solver
   ========================================================= */
.manifesto {
  /* Bottom padding tightened to roughly match the natural breathing
     room above the pillars — avoids a gaping gap below "Seven
     languages" before the next section. */
  padding: var(--pad-section) var(--pad-x) clamp(40px, 5vw, 96px);
  background: var(--bone);
}
.manifesto__intro {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: clamp(40px, 6vw, 120px);
  align-items: center;
}
.manifesto__portrait {
  position: relative;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
.manifesto__portrait img,
.manifesto__portrait-video {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Maja sits on the right of the source frame — shift the crop
     window ~25% rightward so she lands centred in the portrait. */
  object-position: 75% center;
  display: block;
}
.manifesto__portrait figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 16px 20px;
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone);
  background: linear-gradient(180deg, rgba(20,17,14,0) 0%, rgba(20,17,14,0.55) 100%);
}
.manifesto__copy { display: grid; gap: clamp(20px, 2vw, 32px); max-width: 60ch; }
.manifesto__copy .display {
  max-width: 24ch;
  /* "Leon taste" polish — drop a step or two from the global display
     scale and let the line breathe (relaxed leading). */
  font-size: clamp(34px, 4.4vw, 64px);
  line-height: 1.5;
}
.manifesto__lede {
  font-size: var(--fs-lg);
  color: var(--ink-2);
  line-height: 1.55;
  max-width: 56ch;
  /* Hierarchy break — extra room above the lede so it reads as a
     supporting note rather than a continuation of the headline. */
  margin-top: clamp(20px, 2.6vw, 40px);
}
.manifesto__lede em { font-style: italic; color: var(--ink); }

.manifesto__pillars {
  max-width: var(--container);
  margin: clamp(64px, 8vw, 120px) auto 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(32px, 4vw, 64px);
  border-top: 1px solid var(--hairline);
  padding-top: clamp(40px, 5vw, 64px);
}
.manifesto__pillars li {
  display: grid;
  gap: 16px;
  align-content: start;
}
.manifesto__pillars b {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(22px, 2.1vw, 32px);
  letter-spacing: -0.008em;
  color: var(--ink);
  /* Gold-leaf hairline anchor — drawn 0 → 100% on scroll-in. */
  position: relative;
  display: inline-block;
  padding-bottom: clamp(5px, 0.5vw, 9px);
}
.manifesto__pillars b::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 1px;
  background: var(--ochre);
  transition: width 300ms cubic-bezier(0.16, 1, 0.3, 1);
}
.manifesto__pillars.is-in b::after { width: 100%; }
.manifesto__pillars.is-in li:nth-child(2) b::after { transition-delay: 80ms; }
.manifesto__pillars.is-in li:nth-child(3) b::after { transition-delay: 160ms; }
.manifesto__pillars span {
  font-size: var(--fs-base);
  color: var(--mid);
  line-height: 1.55;
}
@media (max-width: 900px) {
  .manifesto__intro { grid-template-columns: 1fr; }
  .manifesto__pillars { grid-template-columns: 1fr; gap: 32px; }
}

/* =========================================================
   THE METHOD — two-column lock-up.
   Headline (left, 40%) is position: sticky and stays in view as
   the body (right, 60%) scrolls past. Hairline rule between.
   ========================================================= */
.method {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}
.method__grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 2fr 3fr;
  gap: 0;
  align-items: start;
}
.method__head {
  position: sticky;
  top: clamp(96px, 14vh, 160px);
  align-self: start;
  display: grid;
  gap: clamp(20px, 2vw, 32px);
  padding-right: clamp(40px, 6vw, 120px);
  max-width: 22ch;
}
.method__head .display {
  /* No max-width — each phrase ("One hand.", "One eye.",
     "One signature.") gets full room and never wraps mid-word.
     The <br /> tags handle the line breaks. */
  font-size: clamp(36px, 4.2vw, 64px);
  line-height: 1.08;
  white-space: nowrap;
}
.method__body {
  display: grid;
  gap: clamp(22px, 2vw, 36px);
  padding-left: clamp(40px, 6vw, 120px);
  border-left: 1px solid var(--hairline);
  font-size: var(--fs-lg);
  color: var(--ink-2);
  line-height: 1.6;
  max-width: 56ch;
}

/* — Maja's pull-quote: handwritten voice, centred, crystallises in. — */
.method__quote {
  margin: clamp(40px, 5vw, 72px) auto 0;
  padding: 0;
  text-align: center;
  max-width: 30ch;
  /* Initial state — blurred and invisible. Resolves to 0/1 when
     .is-in is added (matches the hero brand crystallise). */
  filter: blur(10px);
  opacity: 0;
  transition: filter 1.2s var(--ease-out), opacity 1.2s var(--ease-out);
  will-change: filter, opacity;
}
.method__quote.is-in {
  filter: blur(0);
  opacity: 1;
}
.method__quote-text {
  font-family: 'Sacramento', cursive;
  font-weight: 400;
  font-size: clamp(28px, 2.8vw, 42px);
  line-height: 1.28;
  color: var(--ink-2);
  letter-spacing: 0.005em;
}
.method__quote-cite {
  display: block;
  margin-top: clamp(10px, 1vw, 16px);
  font-family: var(--sans);
  font-style: normal;
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--mid);
}

@media (max-width: 900px) {
  .method__grid { grid-template-columns: 1fr; gap: clamp(28px, 4vw, 48px); }
  .method__head {
    position: static;
    padding-right: 0;
    max-width: 100%;
  }
  .method__body {
    padding-left: 0;
    border-left: 0;
    border-top: 1px solid var(--hairline);
    padding-top: clamp(28px, 4vw, 48px);
  }
  .method__quote {
    margin-right: auto;
    margin-left: auto;
    text-align: center;
    max-width: 100%;
  }
}

/* =========================================================
   STATS BAND — slim editorial line. Hairline-divided.
   Discreet, restrained, in keeping with the site's aesthetic.
   ========================================================= */
.stats {
  position: relative;
  background: var(--bone);
  padding: clamp(28px, 3vw, 48px) var(--pad-x);
  overflow: hidden;
  isolation: isolate;
}
/* Looping background video — sits behind the stats grid at 12%
   opacity. Decorative; pointer-events: none keeps it inert. */
.stats__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0.12;
  pointer-events: none;
  z-index: 0;
}
.stats__inner {
  position: relative;
  z-index: 1;
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-items: center;
}
.stats__item {
  position: relative;
  padding: 0 clamp(16px, 2.4vw, 40px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(4px, 0.5vw, 8px);
}
/* Hairline rule between items. */
.stats__item + .stats__item::before {
  content: '';
  position: absolute;
  left: 0; top: 12%; bottom: 12%;
  width: 1px;
  background: var(--hairline);
}
.stats__number {
  font-family: var(--serif);
  font-size: clamp(28px, 2.6vw, 44px);
  line-height: 1;
  font-weight: 300;
  letter-spacing: -0.012em;
  color: var(--ink);
}
.stats__number sup {
  font-size: 0.45em;
  font-weight: 400;
  vertical-align: super;
  margin-left: 0.05em;
  color: var(--mid);
}
.stats__label {
  font-family: var(--sans);
  font-size: clamp(10px, 0.7vw, 11px);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.24em;
  color: var(--mid);
}

@media (max-width: 760px) {
  .stats__inner { grid-template-columns: repeat(2, 1fr); }
  .stats__item { padding: clamp(10px, 3vw, 18px) clamp(8px, 3vw, 16px); }
  .stats__item + .stats__item::before { display: none; }
  .stats__item:nth-child(2)::before { display: block; }
}

/* — Tiny elegant licence line under the stats grid — */
.stats__legal {
  position: relative;
  z-index: 1;
  margin: clamp(20px, 2.4vw, 36px) auto 0;
  text-align: center;
  font-family: var(--sans);
  font-size: clamp(9px, 0.65vw, 10.5px);
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
  opacity: 0.78;
}

/* =========================================================
   PROJECTS
   ========================================================= */
.projects {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}
.projects__head {
  max-width: var(--container);
  margin: 0 auto clamp(24px, 3vw, 40px);
  display: flex;
  flex-direction: column;
}
.projects__head .display { max-width: 18ch; margin-top: 8px; margin-bottom: 12px; }
.projects__head .projects__lede { margin-top: 0; margin-bottom: 0; }
.projects__mobile-hint { display: none; }
@media (max-width: 768px) {
  .projects__mobile-hint {
    display: block;
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--soft);
    margin: 24px auto 0;
    text-align: center;
  }
}

/* No backing card — photographs sit directly on the section's bone
   background. The hairline frame on each .tile__media is now the
   only piece of structure on each photo. Tile gap stays tight
   (var(--tile-gap) = 4-8 px) so the section reads as a collage. */
.projects__grid {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--tile-gap);
}
.projects__row {
  display: flex;
  gap: var(--tile-gap);
  align-items: flex-start;
}

.tile.tile--square    { flex: 1;     min-width: 0; background: var(--bone); }
.tile.tile--landscape { flex: 1.333; min-width: 0; background: var(--bone); }
.tile.tile--portrait  { flex: 0.75;  min-width: 0; background: var(--bone); }

/* Controls hidden on desktop — the grid view shows all six tiles at once. */
.projects__controls {
  display: none;
}
@media (max-width: 768px) {
  /* Mobile: carousel — show ONE tile at a time. Hide the rows' flex
     structure; treat the grid as a single-cell container that swaps
     active tiles. Same pattern as the Eight Hands signature carousel. */
  .projects__grid {
    position: relative;
  }
  .projects__row {
    display: contents;
  }
  .projects__grid .tile {
    display: none;
    flex: 1 1 auto;
    width: 100%;
  }
  .projects__grid .tile.is-active {
    display: block;
  }
  /* Carousel controls — prev/next arrows pinned to left/right edges
     with the "n / 6" counter centred between them. Mirrors the
     Eight Hands signature controls. */
  .projects__controls {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: clamp(20px, 3vw, 32px);
    max-width: var(--container);
    margin: clamp(28px, 4vw, 40px) auto 0;
    padding: 0 clamp(16px, 4vw, 24px);
  }
  .projects__arrow {
    width: 44px;
    height: 44px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--ink);
    background: linear-gradient(
      135deg,
      rgba(255, 255, 255, 0.36) 0%,
      rgba(255, 255, 255, 0.18) 100%
    );
    backdrop-filter: blur(24px) saturate(1.25);
    -webkit-backdrop-filter: blur(24px) saturate(1.25);
    border: 1px solid rgba(255, 255, 255, 0.48);
    box-shadow:
      0 8px 24px rgba(0, 0, 0, 0.08),
      0 2px 6px rgba(0, 0, 0, 0.04),
      inset 0 1px 0 rgba(255, 255, 255, 0.6),
      inset 0 -1px 0 rgba(0, 0, 0, 0.03);
    transition: transform 0.25s ease;
  }
  .projects__arrow:active { transform: scale(0.97); }
  .projects__arrow--prev { justify-self: start; }
  .projects__arrow--next { justify-self: end; }
  .projects__counter {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--ink-2);
    margin: 0;
    text-align: center;
    min-width: 5ch;
  }
}

/* ── PROFILE / STUDIO PAGE — solo carousel variant ─────────────────────
   On /profile/, the "Six homes" section shows ONE transformation at
   a time on ALL viewports (the homepage keeps its 2×3 grid). The
   stage is a fixed-height cinematic frame; the active tile fills it
   at a unified 4:3 landscape aspect, capped by both viewport width
   AND viewport height so it never overflows. Header (eyebrow / H2
   / lede) is centre-aligned on the studio page only — scoped via
   body.page-studio so the homepage version stays left-aligned. */
body.page-studio .projects__head {
  align-items: center;
  text-align: center;
}
body.page-studio .projects__head .display {
  margin-left: auto;
  margin-right: auto;
}
body.page-studio .projects__head .projects__lede {
  max-width: 56ch;
  margin-left: auto;
  margin-right: auto;
}

.projects__grid--solo {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: clamp(580px, 82vh, 1080px);
}
.projects__grid--solo .projects__row {
  display: contents;
}
.projects__grid--solo .tile {
  display: none;
  width: 100%;
  margin: 0;
}
.projects__grid--solo .tile.is-active {
  display: block;
}
/* In solo mode every tile renders at the SAME aspect ratio (4:3
   landscape) regardless of the tile's homepage modifier class.
   This unifies the carousel — no jumping height between slides —
   and gives every transformation the same cinematic frame. The
   videos are object-fit: cover, so non-landscape source media gets
   cropped at the edges rather than letterboxed. */
.projects__grid--solo .tile,
.projects__grid--solo .tile.tile--landscape,
.projects__grid--solo .tile.tile--square,
.projects__grid--solo .tile.tile--portrait {
  max-width: min(1440px, 94vw, 108vh);
}
.projects__grid--solo .tile .tile__media,
.projects__grid--solo .tile.tile--landscape .tile__media,
.projects__grid--solo .tile.tile--square .tile__media,
.projects__grid--solo .tile.tile--portrait .tile__media {
  aspect-ratio: 4 / 3;
}
/* Click-to-advance affordance — the whole tile body acts as the
   "next" trigger in solo mode (the .tile__view pill stays its own
   click target, untouched). */
.projects__grid--solo .tile .tile__link {
  cursor: pointer;
}

/* Side-pinned glass pill arrows for the solo carousel. The buttons
   live INSIDE .projects__grid--solo (not in a sibling .projects__
   controls strip), so they absolute-position against the grid stage
   and sit vertically centred in the left/right gutters beside the
   active tile. Canonical glass identity — 135° gradient, blur 24,
   hairline border — same as every other button on the site. */
.projects__grid--solo > .projects__arrow {
  position: absolute;
  top: 50%;
  transform: translate3d(0, -50%, 0);
  z-index: 5;
  width: clamp(48px, 4vw, 60px);
  height: clamp(48px, 4vw, 60px);
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  cursor: pointer;
  color: var(--ink);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.36) 0%,
    rgba(255, 255, 255, 0.18) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  border: 1px solid rgba(255, 255, 255, 0.48);
  box-shadow:
    0  8px 24px rgba(0, 0, 0, 0.10),
    0  2px  6px rgba(0, 0, 0, 0.05),
    inset 0  1px 0 rgba(255, 255, 255, 0.60),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
  outline: none;
  transition:
    background 0.32s var(--ease-out),
    border-color 0.32s var(--ease-out),
    box-shadow 0.32s var(--ease-out),
    transform 0.32s var(--ease-out);
}
.projects__grid--solo > .projects__arrow--prev {
  left: clamp(8px, 2vw, 32px);
}
.projects__grid--solo > .projects__arrow--next {
  right: clamp(8px, 2vw, 32px);
}
.projects__grid--solo > .projects__arrow svg {
  width: clamp(18px, 1.4vw, 22px);
  height: clamp(18px, 1.4vw, 22px);
  stroke: currentColor;
  transition: transform 0.32s var(--ease-out);
}
.projects__grid--solo > .projects__arrow:hover,
.projects__grid--solo > .projects__arrow:focus-visible {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.50) 0%,
    rgba(255, 255, 255, 0.28) 100%
  );
  border-color: rgba(255, 255, 255, 0.72);
  box-shadow:
    0 12px 32px rgba(0, 0, 0, 0.14),
    0  3px  8px rgba(0, 0, 0, 0.06),
    inset 0  1px 0 rgba(255, 255, 255, 0.70),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
}
.projects__grid--solo > .projects__arrow--prev:hover svg,
.projects__grid--solo > .projects__arrow--prev:focus-visible svg {
  transform: translateX(-3px);
}
.projects__grid--solo > .projects__arrow--next:hover svg,
.projects__grid--solo > .projects__arrow--next:focus-visible svg {
  transform: translateX(3px);
}
.projects__grid--solo > .projects__arrow:active {
  transform: translate3d(0, -50%, 0) scale(0.97);
}

/* The counter span remains in the DOM for JS slide tracking but
   is hidden via the [hidden] attribute on the <p> element. */

/* View Project pill — brighter glass, larger size, scoped to solo
   mode only. Compensates for the dark .tile__solved backdrop the
   pill sits over after the morph completes; gives it the same
   readable presence the homepage pill has against bone. Canonical
   button identity (135° gradient, blur 24, hairline border)
   preserved — just dialled up for the dark band. */
.projects__grid--solo .tile.is-revealed .tile__view {
  padding: clamp(14px, 1.3vw, 18px) clamp(28px, 2.6vw, 38px);
  font-size: clamp(11px, 0.95vw, 13px);
  letter-spacing: 0.18em;
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.58) 0%,
    rgba(255, 255, 255, 0.32) 100%
  );
  border-color: rgba(255, 255, 255, 0.70);
}
.projects__grid--solo .tile.is-revealed .tile__view svg {
  width: 14px;
  height: 14px;
}

@media (max-width: 768px) {
  /* Mobile — let the tile fill the column at its native aspect; the
     fixed-height stage doesn't make sense at this width. */
  .projects__grid--solo {
    min-height: 0;
  }
  .projects__grid--solo .tile,
  .projects__grid--solo .tile.tile--portrait,
  .projects__grid--solo .tile.tile--landscape,
  .projects__grid--solo .tile.tile--square {
    max-width: 100%;
  }
  /* Mobile arrows: the tile fills the column, so there's no side
     gutter — instead of overlapping the photo, drop the arrows into
     a strip BELOW the card. The grid reserves bottom padding for the
     strip; arrows pin to the bottom corners, clear of the image. */
  .projects__grid--solo {
    padding-bottom: 64px;
  }
  .projects__grid--solo > .projects__arrow {
    width: 44px;
    height: 44px;
    top: auto;
    bottom: 0;
    transform: none;
  }
  .projects__grid--solo > .projects__arrow--prev { left: clamp(8px, 5vw, 28px); }
  .projects__grid--solo > .projects__arrow--next { right: clamp(8px, 5vw, 28px); }
  .projects__grid--solo > .projects__arrow:active { transform: scale(0.97); }
  .projects__grid--solo > .projects__arrow svg {
    width: 16px;
    height: 16px;
  }
}

/* OUTER TILE — no portrait wrapper; just the landscape photo + slim caption. */
.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  background: transparent;
  border: 0;
  transition: transform 700ms var(--ease-out);
}
.tile:hover { transform: translateY(-4px); }

/* The button wrapper — neutralised to behave like a transparent block. */
.tile__link {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.tile__link:focus-visible { outline: 2px solid var(--ink); outline-offset: 4px; }

/* Positioning context for the post-reveal pill (.tile__view). */
.tile__frame { position: relative; }

/* PHOTO FRAME — default 4:3; per-position modifiers below override this.
   1 px hairline frame on every photo reads as a deliberate print mount
   without fighting the image. Universal box-sizing: border-box keeps
   the border inside the aspect-ratio frame so row baselines stay aligned. */
.tile__media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--bone-2);
  border: 1px solid var(--hairline-strong);
}
/* Aspect ratios on the photo frame — paired with the flex-grow values
   above so each row of three tiles shares one consistent height. */
.tile.tile--square    .tile__media { aspect-ratio: 1 / 1; }
.tile.tile--landscape .tile__media { aspect-ratio: 4 / 3; }
.tile.tile--portrait  .tile__media { aspect-ratio: 3 / 4; }

@media (max-width: 760px) {
  .tile.tile--square    .tile__media,
  .tile.tile--landscape .tile__media,
  .tile.tile--portrait  .tile__media {
    aspect-ratio: 4 / 3;
  }
}
.tile__media img,
.tile__video {
  width: 100%; height: 100%;
  /* cover — fills the frame at every aspect ratio. The morph action sits
     in the centre of every clip, so edge-cropping is acceptable for the
     16:9, 4:5, 1:1, 3:4, and 2:1 frames carved from a 4:3 source. */
  object-fit: cover;
  object-position: center;
  display: block;
  transition: transform 1200ms var(--ease-out), filter 600ms var(--ease-out);
  will-change: transform;
}
.tile__video { background: var(--bone-2); }

/* Hover halo — same treatment for img or video. */
.tile:hover .tile__media > img,
.tile:focus-within .tile__media > img,
.tile:hover .tile__video,
.tile:focus-within .tile__video {
  transform: scale(1.02);
}
/* Once playing, kill the dimming so the morph reads cleanly. */
.tile.is-playing .tile__video { filter: none !important; transform: none !important; }
.tile.is-playing:hover .tile__video { filter: none !important; }

/* — Hover overlay: project title + meta + "Click to reveal" pill.
     Visible on hover/focus on desktop; persistently visible on mobile
     (where hover doesn't exist) but with the click hint hidden. — */
.tile__hover {
  position: absolute !important;
  inset: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
  align-items: center !important;
  padding: clamp(16px, 4%, 32px) !important;
  z-index: 2;
  opacity: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(20,17,14,0.10) 0%, rgba(20,17,14,0.55) 100%);
  transition: opacity 360ms var(--ease-out);
  text-align: center;
}
.tile:hover .tile__hover,
.tile:focus-within .tile__hover {
  opacity: 1;
}
/* Hide hover overlay during morph play and after reveal. */
.tile.is-playing .tile__hover,
.tile.is-revealed .tile__hover {
  opacity: 0 !important;
}
.tile__hover-title {
  font-family: var(--serif);
  font-size: clamp(24px, 1.9vw, 32px);
  font-weight: 400;
  letter-spacing: -0.008em;
  color: rgba(244, 239, 230, 0.98);
  line-height: 1.2;
  margin: 0 0 14px 0;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.35);
}
.tile__hover-meta {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.78);
  margin: 0 0 24px 0;
}
.tile__hover-hint {
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.88);
  padding: 8px 16px;
  border: 1px solid rgba(244, 239, 230, 0.4);
  border-radius: 999px;
}

/* — "What changed" overlay — appears ONLY after the morph has finished
     (.is-revealed). Not on hover. Not during play. Bottom padding leaves
     room for the View Project pill that fades in beneath it. — */
.tile__solved {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(18px, 5%, 36px);
  padding-bottom: clamp(110px, 20%, 140px);
  z-index: 3;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 720ms 120ms var(--ease-out),
              transform 820ms 120ms var(--ease-out);
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(20, 17, 14, 0.45) 0%,
    rgba(20, 17, 14, 0.62) 60%,
    rgba(20, 17, 14, 0.78) 100%);
  text-align: center;
}
.tile__solved-text {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(16px, 1.4vw, 24px);
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.96);
  max-width: 28ch;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.45);
  margin: 0 0 28px 0;
}
.tile__solved-detail {
  font-family: var(--sans);
  font-size: clamp(10px, 0.85vw, 12px);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.72);
  max-width: 36ch;
  margin: 0;
}
/* The ONLY trigger for the solved overlay — post-morph reveal. */
.tile.is-revealed .tile__solved {
  opacity: 1;
  transform: translateY(0);
}


/* — Projects: section lede — */
.projects__head .projects__lede {
  font-size: var(--fs-lg);
  color: var(--mid);
  line-height: 1.55;
  max-width: 48ch;
  margin-top: 0;
  margin-bottom: 0;
}

/* — View Project: bone pill anchored to the bottom-centre of the photo
     frame. Fades in 240 ms after the solved caption, only when the tile
     has .is-revealed. Lives inside .tile__frame as a sibling of the
     button, so it's its own click target. — */
/* Project tile reveal pill — hidden by default. Hover/focus reveals
   on desktop; on (hover: none) touch devices, .is-revealed (the
   morph state) re-enables visibility so the tap target exists. */
.tile__view {
  position: absolute;
  left: 50%;
  top: 72%;
  transform: translate3d(-50%, -50%, 0);
  z-index: 4;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 24px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  border-radius: 999px;

  color: var(--ink);
  /* Canonical pill colour — glassy translucent, same as every
     other button on the site. */
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.16) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  border: 1px solid rgba(255, 255, 255, 0.45);
  box-shadow:
    0  8px 32px rgba(0, 0, 0, 0.08),
    0  2px  6px rgba(0, 0, 0, 0.04),
    inset 0  1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);

  opacity: 0 !important;
  pointer-events: none !important;
  transition: opacity 360ms var(--ease-out);
}
.tile__view svg {
  width: 12px;
  height: 12px;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Pre-reveal hover keeps title + meta + Click-to-reveal only;
   View Project surfaces only once the morph has played and the
   user is hovering the now-revealed result. */
.tile.is-revealed:hover .tile__view,
.tile.is-revealed:focus-within .tile__view {
  opacity: 1 !important;
  pointer-events: auto !important;
}

.tile.is-revealed:hover .tile__view svg,
.tile.is-revealed:focus-within .tile__view svg {
  transform: translateX(3px);
}

/* Canonical hover + active feedback for the View Project pills on the
   homepage tiles AND the studio page work-cards. Adds the same brighten,
   press, and arrow-translate that every other button on the site gets
   — without disturbing each button's positioning transform. */
.tile__view:hover,
.tile__view:focus-visible,
.studio__work-card-view:hover,
.studio__work-card-view:focus-visible {
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow:
    0 12px 36px rgba(0, 0, 0, 0.12),
    0  3px  8px rgba(0, 0, 0, 0.06),
    inset 0  1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
}
.tile.is-revealed .tile__view:active {
  transform: translate3d(-50%, -50%, 0) scale(0.985);
}
.studio__work-card.is-revealed .studio__work-card-view:active {
  transform: translate3d(-50%, 0, 0) scale(0.985);
}
.tile.is-revealed:hover .tile__view svg,
.tile.is-revealed:focus-within .tile__view svg,
.studio__work-card.is-revealed .studio__work-card-view:hover svg,
.studio__work-card.is-revealed .studio__work-card-view:focus-visible svg {
  transform: translateX(8px);
}

@media (hover: none) {
  .tile.is-revealed .tile__view {
    opacity: 1 !important;
    pointer-events: auto !important;
  }
}

@media (max-width: 700px) {
  .tile__view { top: 78%; padding: 10px 20px; font-size: 10px; }
}

/* Mobile: title + meta become persistently visible (hover doesn't
   exist on touch). The Click-to-reveal hint is dropped — every tile
   reads as obviously tappable on touch. */
@media (max-width: 760px) {
  .tile__hover {
    opacity: 1;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(20,17,14,0) 0%, rgba(20,17,14,0.55) 100%);
    justify-content: flex-end;
    padding-bottom: clamp(20px, 5vw, 32px);
  }
  .tile__hover-hint { display: none; }
  .tile.is-playing .tile__hover,
  .tile.is-revealed .tile__hover { opacity: 0 !important; }
}

.projects__cta {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin: clamp(48px, 6vw, 80px) auto 0;
  padding: 14px 26px;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  font-family: var(--sans);
  font-size: var(--fs-sm);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  transition: background 320ms var(--ease-out), color 320ms var(--ease-out), padding 320ms var(--ease-out);
  display: inline-flex;
}
.projects__cta { display: flex; max-width: max-content; margin-left: auto; margin-right: auto; }
.projects__cta svg { width: 14px; height: 14px; transition: transform 320ms var(--ease-out); }
.projects__cta:hover { background: var(--ink); color: var(--bone); padding-right: 32px; }
.projects__cta:hover svg { transform: translateX(4px); }

/* =========================================================
   TESTIMONIALS — three editorial quotes, hairline-divided.
   ========================================================= */
.testimonials {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}
.testimonials__head {
  max-width: var(--container);
  margin: 0 auto clamp(48px, 6vw, 96px);
  display: grid;
  gap: clamp(14px, 1.4vw, 24px);
  text-align: center;
  justify-items: center;
}
.testimonials__head .display { max-width: 22ch; }

/* Testimonials — typography shared by both viewports. */
.testimonial {
  position: relative;
  padding: clamp(20px, 2.4vw, 44px) clamp(24px, 3vw, 56px);
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.4vw, 36px);
  text-align: center;
  align-items: center;
}
.testimonial__cite { margin-top: auto; }

/* Mobile (<=1023px): single-card carousel. Cards stack on the
   same grid cell; .is-active fades in. JS toggles .is-active and
   updates the count. Arrows + counter visible. */
@media (max-width: 1023px) {
  .testimonials__grid {
    max-width: 720px;
    margin: 0 auto;
    list-style: none;
    padding: 0;
    display: grid;
    position: relative;
    min-height: 320px;
  }
  .testimonials__grid > .testimonial {
    grid-area: 1 / 1;
    opacity: 0;
    pointer-events: none;
    transition: opacity 480ms ease;
    cursor: pointer;
  }
  .testimonials__grid > .testimonial.is-active {
    opacity: 1;
    pointer-events: auto;
  }
  .testimonials__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    margin-top: clamp(32px, 4vw, 56px);
  }
  .testimonials__arrow {
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: 1px solid var(--hairline-strong);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background 220ms ease, border-color 220ms ease;
  }
  .testimonials__arrow:hover {
    background: rgba(60, 50, 35, 0.04);
    border-color: var(--ink);
  }
  .testimonials__count {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    color: var(--mid);
    min-width: 50px;
    text-align: center;
  }
}

/* Desktop (>=1024px): 3-up horizontal row with scroll-snap.
   Cards render side-by-side, no opacity carousel. Arrows + counter
   hidden by default; .testimonials.has-overflow reveals the arrow
   pair when the JS detects more than 3 testimonials. */
@media (min-width: 1024px) {
  .testimonials__grid {
    max-width: var(--container);
    margin: 0 auto;
    list-style: none;
    padding: 4px 0 8px;
    display: flex;
    flex-direction: row;
    gap: 32px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    scrollbar-width: none;
    min-height: 0;
  }
  .testimonials__grid::-webkit-scrollbar { display: none; }
  .testimonials__grid > .testimonial {
    flex: 0 0 calc((100% - 64px) / 3);
    scroll-snap-align: start;
    grid-area: auto;
    opacity: 1;
    pointer-events: auto;
    transition: none;
    cursor: default;
    text-align: left;
    align-items: flex-start;
  }
  .testimonials__nav {
    display: none;
    margin-top: 32px;
    gap: 14px;
    justify-content: flex-end;
    align-items: center;
  }
  .testimonials.has-overflow .testimonials__nav {
    display: flex;
  }
  .testimonials__count { display: none; }
  .testimonials__arrow {
    width: 44px;
    height: 44px;
    border-radius: 999px;
    border: 1px solid var(--hairline);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: border-color 220ms ease, background 220ms ease;
  }
  .testimonials__arrow:hover,
  .testimonials__arrow:focus-visible {
    border-color: var(--ink);
    background: var(--paper);
  }
}
/* Five-star rating row — small ochre stars at the top of each card. */
.testimonial__stars {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 14px;
  color: var(--ochre);
}
.testimonial__stars svg {
  width: 14px;
  height: 14px;
  fill: currentColor;
  display: block;
}

/* Decorative opening quotation glyph — large, serif, soft ink. */
.testimonial__quote {
  position: relative;
  margin: 0;
  padding-top: clamp(28px, 2.8vw, 44px);
}
.testimonial__quote::before {
  content: '\201C';                    /* opening curly double-quote */
  position: absolute;
  top: -0.18em;
  left: -0.04em;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(64px, 6vw, 96px);
  line-height: 1;
  color: var(--soft);
  pointer-events: none;
}
.testimonial__quote p {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(17px, 1.4vw, 22px);
  line-height: 1.55;
  color: var(--ink);
  letter-spacing: -0.005em;
  max-width: 32ch;
}

/* Citation block — name·location on top, then project, then date. */
.testimonial__cite {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--hairline);
  display: grid;
  grid-template-columns: max-content 1fr;
  column-gap: 10px;
  row-gap: 4px;
  align-items: baseline;
}
.testimonial__name {
  grid-column: 1;
  grid-row: 1;
  font-family: var(--sans);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.testimonial__loc {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  color: var(--mid);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.testimonial__project {
  grid-column: 1 / -1;
  grid-row: 2;
  font-family: var(--serif);
  font-style: italic;
  font-size: var(--fs-sm);
  color: var(--mid);
  letter-spacing: -0.002em;
}
.testimonial__date {
  grid-column: 1 / -1;
  grid-row: 3;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  color: var(--soft);
  letter-spacing: 0.06em;
}

@media (max-width: 900px) {
  .testimonials__grid { max-width: 620px; }
}

/* =========================================================
   100% IN-HOUSE TRUST BLOCK — the differentiator
   ========================================================= */
.craft {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}
.craft__head {
  max-width: var(--container);
  margin: 0 auto clamp(48px, 6vw, 96px);
  display: grid;
  gap: clamp(16px, 1.6vw, 28px);
}
.craft__head .display { max-width: 18ch; }
.craft__lede {
  font-size: var(--fs-lg);
  color: var(--ink-2);
  line-height: 1.55;
  max-width: 64ch;
}

/* — Maja's pull-quote in the Craft section — left-aligned Cormorant
     italic with an ochre left-border accent. The handwritten Sacramento
     treatment stays exclusive to the Method section's founder quote.
     Reveals with the same blur-to-clear .is-in toggle. — */
.craft__quote {
  margin: clamp(28px, 3vw, 48px) 0 0;
  padding: 4px 0 4px 18px;
  border-left: 2px solid var(--ochre);
  max-width: 56ch;
  text-align: left;
  filter: blur(10px);
  opacity: 0;
  transition: filter 1.2s var(--ease-out), opacity 1.2s var(--ease-out);
  will-change: filter, opacity;
}
.craft__quote.is-in {
  filter: blur(0);
  opacity: 1;
}
.craft__quote-text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(17px, 1.4vw, 22px);
  line-height: 1.55;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0 0 6px 0;
}
.craft__quote-cite {
  display: block;
  margin-top: 6px;
  font-family: var(--sans);
  font-style: normal;
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid);
}

@media (max-width: 900px) {
  .craft__quote {
    margin-left: 0;
    margin-right: 0;
    max-width: 100%;
  }
}

/* =========================================================
   How We Work — pillar grid alignment reset.
   Forces identical column geometry regardless of source image
   dimensions. The aspect-ratio on the img is the actual fix:
   rendered height = column width × 0.75 every time. Explicit
   margins on each child override browser defaults that would
   otherwise leak into one column and shift its baseline.
   ========================================================= */
.craft__grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(28px, 3vw, 56px);
  align-items: start;
}
.craft__cell {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  align-self: start;
}
.craft__shot {
  position: relative;
  overflow: hidden;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  margin: 0 0 clamp(20px, 1.8vw, 30px);
}
.craft__shot img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center;
  display: block;
  margin: 0;
  padding: 0;
  transition: transform 1200ms var(--ease-out);
}
.craft__cell:hover .craft__shot img { transform: scale(1.02); }
.craft__pillar {
  margin: 0 0 clamp(12px, 1vw, 18px);
  padding: 0;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(22px, 2vw, 30px);
  letter-spacing: -0.012em;
  line-height: 1.25;
  color: var(--ink);
}
.craft__copy {
  margin: 0;
  padding: 0;
  font-size: var(--fs-base);
  color: var(--mid);
  line-height: 1.6;
  max-width: 38ch;
}
@media (max-width: 900px) {
  .craft__grid { grid-template-columns: 1fr; max-width: 560px; }
}

/* =========================================================
   PROCESS TIMELINE — four steps, vertical alternating spread
   ========================================================= */
.process {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}

.process__head {
  max-width: var(--container);
  margin: 0 auto clamp(64px, 8vw, 120px);
  display: grid;
  gap: 18px;
}
.process__head .display { max-width: 20ch; }
.process__lede {
  font-size: var(--fs-lg);
  color: var(--mid);
  line-height: 1.55;
  max-width: 56ch;
  margin: 0;
}

.process__steps {
  list-style: none;
  padding: 0;
  max-width: var(--container);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: clamp(80px, 10vw, 160px);
}

.process__step {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: clamp(36px, 5vw, 88px);
}
.process__step--reverse .process__visual-stack {
  grid-column: 2;
  grid-row: 1;
}
.process__step--reverse .process__copy {
  grid-column: 1;
  grid-row: 1;
}

/* Wrapper that holds a step's video figure + the small caption
   beneath it so both occupy a single grid cell. */
.process__visual-stack {
  display: grid;
  gap: clamp(18px, 2vw, 28px);
}

.process__visual {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--bone-2);
  aspect-ratio: 4 / 3;
}
.process__visual img,
.process__visual video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* — Click-to-play wrapper: full-coverage transparent button. Whole
     video frame becomes the click target without imposing visual
     chrome. Mirrors the project-tile pattern. — */
.process__step-link {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  position: relative;
  -webkit-tap-highlight-color: transparent;
}
.process__step-link:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

/* Subtle scale on hover so the user knows the frame is clickable. */
.process__visual .process__video,
.process__visual .process__result-video {
  transition: transform 1200ms var(--ease-out), filter 600ms var(--ease-out);
  will-change: transform;
}
.process__step-link:hover .process__video,
.process__step-link:focus-visible .process__video,
.process__step-link:hover .process__result-video,
.process__step-link:focus-visible .process__result-video {
  transform: scale(1.015);
}
.process__visual.is-playing .process__video,
.process__visual.is-playing .process__result-video {
  transform: none !important;
  filter: none !important;
}

/* Hint pill: top-left corner, glass-morphism, tracked uppercase.
   Matches the project-tile hint pill exactly. */
/* Process card "Click to reveal" / "Play again" pill — ivory
   pebble vocabulary at micro-scale. Keeps the existing top-left
   absolute placement + the play/end transform animation. */
/* Canonical glass pill — same identity as every other button sitewide
   (135° glass gradient, blur 24px, cream border, ambient shadow). The
   hint is decorative (pointer-events: none); the entire video frame is
   the actual click target. */
.process__hint {
  position: absolute;
  top: clamp(14px, 1.6vw, 22px);
  left: clamp(14px, 1.6vw, 22px);
  z-index: 5;
  padding: 12px 24px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.45);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.16) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink);
  pointer-events: none;
  transition: opacity 360ms var(--ease-out), transform 480ms var(--ease-out);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.08),
    0 2px 6px rgba(0, 0, 0, 0.04),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);
}

/* Hide the pill while the video is actively playing. */
.process__visual.is-playing .process__hint {
  opacity: 0;
  transform: translateY(-4px);
}

/* Two-state label: 'Click to reveal' before play, 'Play again' after. */
.process__hint-label--initial { display: inline; }
.process__hint-label--replay  { display: none; }
.process__visual.is-revealed .process__hint-label--initial { display: none; }
.process__visual.is-revealed .process__hint-label--replay  { display: inline; }

/* The pill comes back after the video ends, now reading 'Play again'. */
.process__visual.is-revealed .process__hint {
  opacity: 1;
  transform: translateY(0);
}

.process__copy {
  display: grid;
  gap: clamp(12px, 1.2vw, 18px);
  max-width: 48ch;
}
.process__num {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.32em;
  color: var(--soft);
}
.process__when {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.process__title {
  font-family: var(--serif);
  font-size: clamp(28px, 3vw, 44px);
  font-weight: 400;
  letter-spacing: -0.012em;
  color: var(--ink);
  line-height: 1.12;
  margin: 0;
}
.process__body {
  font-size: var(--fs-base);
  color: var(--ink-2);
  line-height: 1.6;
  margin: 0;
  max-width: 44ch;
}
.process__quote {
  margin: clamp(12px, 1.6vw, 20px) 0 0;
  padding: 4px 0 4px 18px;
  border-left: 2px solid var(--ochre);
  max-width: 44ch;
}
.process__quote p {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(15px, 1.2vw, 19px);
  line-height: 1.55;
  color: var(--ink);
  margin: 0 0 6px;
}
.process__quote cite {
  display: block;
  font-family: var(--sans);
  font-style: normal;
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid);
}

@media (max-width: 900px) {
  .process__step,
  .process__step--reverse {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  .process__step--reverse .process__visual,
  .process__step--reverse .process__copy {
    grid-column: 1;
    grid-row: auto;
  }
}

/* — The Result: vertical closer beneath the four steps. Different aspect
     (9:16) signals 'closing image', not a fifth step. The 480 px max-width
     keeps the iPhone-photo register at desktop scale. — */
.process__result {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: clamp(18px, 2vw, 28px);
  margin: clamp(80px, 10vw, 140px) auto 0;
  max-width: 560px;
  padding: 0 var(--pad-x);
}
.process__result-eyebrow {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--soft);
}
.process__result-visual {
  margin: 0;
  width: 100%;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: var(--bone-2);
}
.process__result-video,
.process__result-visual img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Shared caption beneath each step video and the result video.
   Cereal magazine register: small italic Cormorant. Mono is now
   reserved for technical metadata only (IMPIC, project specs). */
.process__caption {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.5;
  color: var(--ink-2);
  letter-spacing: 0;
  margin: 0 auto;
  max-width: 52ch;
  text-align: center;
}

@media (max-width: 760px) {
  .process__result {
    max-width: 88vw;
    margin-top: clamp(48px, 8vw, 80px);
  }
}

/* =========================================================
   LOCAL MASTERY — Cascais commitment + custom SVG map
   ========================================================= */
.cascais {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}

/* Atmospheric closer — Maya's Homes van on the Cascais waterfront,
   sitting at the bottom of the section as the emotional anchor. */
/* Two-column intro: atmosphere photo (left) + bridge lede (right).
   Sits beneath the section header; the .local-mastery diagram
   continues below. Header, image, and lede share the same left
   edge so the three elements read as one editorial unit. */
.cascais__intro {
  max-width: 1440px;
  margin: 0 auto clamp(48px, 6vw, 80px);
  padding: 0 clamp(24px, 4vw, 64px);
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 72px);
  align-items: center;
}

/* .cascais__atmosphere retired — the van photo moved to /local/'s
   hero. See .local__hero-image in the /local/ section below. */

.cascais__intro-text {
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Small editorial title above the bridge paragraph — gives the
   intro block structure (title + paragraph) instead of a lone
   floating sentence. */
.cascais__intro-title {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(24px, 2.4vw, 32px);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 16px;
}

/* Bridge lede sits in the right column, left-aligned to match
   the section header above it. */
.cascais__lede-bridge {
  margin: 0;
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  letter-spacing: -0.005em;
  text-align: left;
  max-width: 38ch;
}

@media (max-width: 960px) {
  .cascais__intro {
    grid-template-columns: 1fr;
    gap: 28px;
  }
}

/* Section header — left-aligned at the same 1440px container as
   the .cascais__intro and .local-mastery blocks beneath, so the
   eyebrow / headline / image / lede share one left edge. */
.cascais__head {
  max-width: 1440px;
  margin: 0 auto clamp(28px, 4vw, 48px);
  padding: 0 clamp(24px, 4vw, 64px);
  display: grid;
  gap: clamp(14px, 1.4vw, 24px);
  text-align: left;
}
.cascais__head .display {
  font-size: clamp(48px, 5.6vw, 84px);
  letter-spacing: -0.012em;
  line-height: 1.05;
  max-width: 22ch;
}

/* Local Mastery — tabs + map share the LEFT grid column, content
   sits in the RIGHT column. The hairline below the tabs naturally
   ends at the map's right edge because the tabs container is
   nested inside the map column. */
.local-mastery {
  max-width: 1440px;
  margin: clamp(40px, 6vw, 80px) auto 0;
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 72px);
  align-items: start;
}

.local-mastery__map-column {
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 3vw, 36px);
  min-width: 0;
}

/* (Removed: .local-mastery__tabs / .local-mastery__tab / __tab-num /
   __tab-label / .is-active::after / hover states. The four-tab
   widget was collapsed to a single static map; tab styling is dead.) */

/* Map frame — sits in the LEFT grid column.
   Aspect-ratio locked so switching tabs doesn't reflow the layout.
   3:2 keeps every panel image at the same height; object-fit
   stays contain so map labels (Sintra, Cascais, etc.) aren't
   cropped by the frame. */
.local-mastery__frame {
  position: relative;
  margin: 0;
  width: 100%;
  background: transparent;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  box-shadow: none;
}

.local-mastery__map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  opacity: 0;
  transition: opacity 400ms ease;
}

.local-mastery__map.is-active { opacity: 1; }

/* Right column content — anchored near the upper third of the map.
   Padding-top + internal gap tuned so the longest toggle copy
   (Atlantic Climate, Local Permits) fits within the map's
   vertical extent. */
.local-mastery__content {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.6vw, 22px);
  /* padding-top removed — used to reserve space for the tab bar
     that sat above the map column. Tabs are gone; right column
     now top-aligns with the map. */
}

/* Eyebrow row — positioning context. Captions stack absolutely
   inside it so the row height stays constant across all four
   toggle states; the lede below never shifts when the user
   clicks between Overview / Area / Permits / Climate. */
.local-mastery__eyebrow {
  position: relative;
  min-height: clamp(40px, 4vw, 56px);
  display: block;
}

.local-mastery__caption {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: block;
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.5;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-2);
  margin: 0;
  padding-top: 0;
  border-top: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 400ms ease;
}

.local-mastery__caption.is-active {
  opacity: 1;
  pointer-events: auto;
}

/* Lede paragraph */
.local-mastery__lede {
  position: relative;
  width: 100%;
}

.local-mastery__lede-text {
  font-family: var(--sans);
  font-style: normal;
  font-weight: 400;
  font-size: 16px;
  line-height: 1.75;
  color: var(--ink-2);
  letter-spacing: 0;
  text-align: left;
  margin: 0 0 clamp(8px, 1vw, 14px);
  display: none;
  opacity: 0;
  transition: opacity 400ms ease 150ms;
}

.local-mastery__lede-text.is-active {
  display: block;
  opacity: 1;
}

/* Quote — sits beneath the lede with no divider; the typography
   does the separation. */
.local-mastery__quote {
  position: relative;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
}

.local-mastery__quote-text {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.6vw, 22px);
  line-height: 1.45;
  color: var(--ink);
  margin: 0 0 14px;
  display: none;
  opacity: 0;
  transition: opacity 400ms ease 300ms;
}

.local-mastery__quote-text.is-active {
  display: block;
  opacity: 1;
}

.local-mastery__quote cite {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  font-style: normal;
  color: var(--ink-2);
}

/* Mobile — stack vertically, map column first then content;
   recentre the tabs since the layout is no longer two-column. */
@media (max-width: 960px) {
  .local-mastery {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .local-mastery__content {
    padding-top: 0;
  }
}

@media (max-width: 720px) {
  .local-mastery__tabs {
    flex-direction: column;
    gap: 0;
    border-bottom: 0;
  }
  .local-mastery__tab {
    padding: 14px 16px;
    border-bottom: 1px solid var(--hairline);
  }
  .local-mastery__tab.is-active::after { display: none; }
}

/* Defensive: keep the cascais header in normal flow. */
.cascais__head {
  transform: none !important;
  margin-top: 0 !important;
}
/* Supplier video slot — small inset within the supply-chain pillar.
   Markup is currently HTML-commented; uncomment when Maja's clip lands. */
.cascais__supplier {
  margin: 14px 0 0;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}
.cascais__supplier-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

@media (max-width: 900px) {
  .cascais__grid { grid-template-columns: 1fr; }
}

/* =========================================================
   SERVICES — what we offer, six-card grid + future-venture footnote
   ========================================================= */
.services {
  padding: var(--pad-section) var(--pad-x);
  background: var(--bone);
}
.services__head {
  max-width: var(--container);
  margin: 0 auto clamp(48px, 6vw, 96px);
  display: grid;
  gap: clamp(16px, 1.6vw, 28px);
}
.services__head .display { max-width: 18ch; }
.services__lede {
  font-size: var(--fs-lg);
  color: var(--mid);
  line-height: 1.55;
  max-width: 42ch;
}
/* Solo variant — single supporting paragraph under the H2 (replaces
   the older two-column .services__lede-split, which split the body
   into side-by-side parallel statements that had no clear reading
   order). The H2 itself carries the "yours / ours" parallel; the
   body just flows as one paragraph supporting it. */
.services__lede--solo {
  max-width: 64ch;
  margin: 0;
}
.services__grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(36px, 4vw, 72px);
}
.services__card {
  display: grid;
  gap: clamp(14px, 1.4vw, 22px);
  align-content: start;
  text-decoration: none;
  color: inherit;
}
/* Editorial hover — subtle image zoom + title tone shift. The whole
   card is a link to the matching anchor on /services/. No "Learn
   more →" link is rendered; the hover affordance handles it. */
.services__card .services__shot img {
  transition: transform 0.6s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.services__card:hover .services__shot img,
.services__card:focus-visible .services__shot img {
  transform: scale(1.04);
}
.services__card .services__title {
  transition: color 240ms ease;
}
.services__card:hover .services__title,
.services__card:focus-visible .services__title {
  color: var(--mid);
}
.services__shot {
  position: relative;
  margin: 0;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  display: grid;
  place-items: center;
  text-align: center;
  padding: clamp(16px, 2vw, 28px);
}
/* Real photo fills the shot edge-to-edge, overriding the
   placeholder's centred-text padding and grid centring. */
.services__shot img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Legacy gradient stand-in for any card still missing a photo. */
.services__shot[data-todo] .services__placeholder {
  display: none;
}
.services__shot[data-todo] {
  background:
    linear-gradient(135deg, var(--bone) 0%, var(--paper) 50%, var(--soft) 100%);
}
.services__placeholder {
  font-family: var(--sans);
  font-style: italic;
  font-size: var(--fs-xs);
  letter-spacing: 0.04em;
  color: var(--soft);
  max-width: 24ch;
  line-height: 1.5;
}
.services__title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(26px, 2.4vw, 36px);
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 8px 0;
  line-height: 1.2;
  text-wrap: balance;
}
.services__copy {
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: 1.6;
  color: var(--mid);
  max-width: 38ch;
  margin: 0;
}
/* Closing band beneath the 6-service grid — announces the sister
   practice. Visually demoted from the cards above (no card frame,
   hairline rules top and bottom). */
.services__sister {
  max-width: 640px;
  margin: clamp(48px, 6vw, 80px) auto 0;
  padding: clamp(40px, 5vw, 64px) 0;
  text-align: left;
  position: relative;
}
.services__sister::before,
.services__sister::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: clamp(120px, 18vw, 220px);
  height: 1px;
  background: rgba(45, 41, 38, 0.18);
  pointer-events: none;
}
.services__sister::before { top: 0; }
.services__sister::after  { bottom: 0; }
.services__sister-eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 16px;
}
.services__sister-title {
  font-family: var(--serif);
  font-size: clamp(28px, 3vw, 36px);
  font-weight: 400;
  margin: 0 0 16px;
  color: var(--ink);
}
.services__sister-body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 24px;
  max-width: 56ch;
}
.services__sister-status {
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink-2);
  margin: 0;
}
.services__sister-status em {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16px;
  color: var(--ink);
}
.services__sister-link {
  margin-left: 12px;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 200ms ease;
}
.services__sister-link:hover {
  color: var(--ink-2);
}

@media (max-width: 900px) {
  .services__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .services__grid { grid-template-columns: 1fr; max-width: 480px; }
}

/* =========================================================
   FINAL INVITATION — contact form (dark)
   ========================================================= */
/* Contact — cream-on-cream editorial spread. Two-column: intro
   (headline + lede + direct contact) on the left, form on the
   right. Credentials sit beneath as a quiet centred affirmation. */
.contact {
  background: var(--bone);
  color: var(--ink);
  padding: clamp(80px, 10vw, 160px) clamp(24px, 4vw, 64px);
}

.contact__inner {
  max-width: 1240px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(48px, 6vw, 96px);
  align-items: start;
}

/* LEFT — intro + direct contact. Sticky so the headline anchors
   the page as the user scrolls down through the form. */
.contact__intro {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: sticky;
  top: clamp(80px, 10vw, 140px);
  align-self: start;
}

.contact__eyebrow {
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 clamp(20px, 2.5vw, 32px);
}

/* Contact title is now the page's closing typographic moment —
   sized to match the previous footer outro. */
.contact__title {
  font-family: var(--serif);
  font-size: clamp(56px, 8vw, 120px);
  font-weight: 400;
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
  max-width: none;
}

.contact__title em {
  font-style: italic;
}

/* Subtitle margin-top bumped 16-24 → 48-80 so the giant headline
   has real breath before the smaller italic line appears. */
.contact__subtitle {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 2.4vw, 28px);
  line-height: 1.3;
  color: var(--ink-2);
  margin: clamp(48px, 6vw, 80px) 0 clamp(40px, 5vw, 64px);
}

.contact__lede {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0 0 clamp(40px, 5vw, 64px);
  max-width: 38ch;
}

.contact__direct {
  margin: 0;
  padding-top: clamp(32px, 4vw, 48px);
  border-top: 1px solid var(--hairline);
}

.contact__direct-label {
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 20px;
}

.contact__direct-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.contact__direct-list li {
  display: grid;
  grid-template-columns: 100px 1fr;
  gap: 24px;
  align-items: baseline;
}

.contact__direct-key {
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
}

.contact__direct-value {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  line-height: 1.4;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease;
}

a.contact__direct-value:hover {
  border-bottom-color: var(--ink);
}

/* RIGHT — form */
.contact__form {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.5vw, 28px);
}

.contact__field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.contact__label {
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.contact__label em {
  font-style: italic;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--mid);
  margin-left: 6px;
}

.contact__input,
.contact__textarea {
  font-family: var(--serif);
  font-size: 19px;
  line-height: 1.5;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--hairline-strong);
  padding: 12px 0 10px;
  outline: none;
  transition: border-color 240ms ease;
  width: 100%;
}

.contact__textarea {
  resize: vertical;
  min-height: 180px;
  border: 1px solid var(--hairline-strong);
  padding: 18px 20px;
}

.contact__input:focus,
.contact__textarea:focus {
  border-color: var(--ink);
}

.contact__input::placeholder,
.contact__textarea::placeholder {
  color: var(--mid);
  opacity: 1;
}

/* Form-submit specific overrides: keep the shared light-silver
   visuals (defined in the shared block near .nav__cta) but add
   form-flow tweaks — top spacing, left alignment in the column. */
.contact__submit {
  margin-top: clamp(8px, 1.5vw, 16px);
  align-self: flex-start;
}

/* Post-submit thank-you panel — replaces the form on ?sent=1. */
.contact__sent {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: clamp(40px, 5vw, 64px);
  border: 1px solid var(--hairline-strong);
  background: var(--paper);
}
.contact__sent[hidden] { display: none; }
.contact__sent-title {
  font-family: var(--serif);
  font-size: clamp(28px, 3vw, 36px);
  font-weight: 400;
  margin: 0;
  color: var(--ink);
}
.contact__sent-body {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
}

@media (max-width: 960px) {
  .contact__inner {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  .contact__intro {
    position: static;
    top: auto;
  }
  .contact__direct-list li {
    grid-template-columns: 80px 1fr;
    gap: 16px;
  }
}

/* =========================================================
   FOOTER
   ========================================================= */
/* =========================================================
   FOOTER — compact closing block
   Two rows: brand + socials, then legal credentials + meta links.
   Keeps the dark ink-2 palette (continuation of the contact
   section above) but radically reduces height and content.
   ========================================================= */
/* =========================================================
   FOOTER — three-zone editorial footer, cream-on-cream.
   ZONE 1: oversized serif outro statement.
   ZONE 2: details band — brand / nav / contact in three cols.
   ZONE 3: credentials strip — © · sister site · legal.
   ========================================================= */
/* Footer sits one tone darker than the page above (paper, not
   bone) so the footer reads as a distinct zone — same warm
   family, visibly different surface. */
.footer {
  background-color: transparent;
  background-image: none;
  color: var(--ink);
  padding: 0;
  border-top: 1px solid var(--hairline-strong);
}

/* (The previous .footer__outro section was deleted: the contact
   section's headline is now the page's closing typographic
   moment, so a duplicate footer outro was pure repetition.) */

/* Details band — three balanced columns with generous gap. */
.footer__details {
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(80px, 10vw, 120px) clamp(24px, 4vw, 64px);
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr) minmax(0, 1.2fr);
  gap: clamp(56px, 7vw, 112px);
  border-bottom: 1px solid var(--hairline);
}

.footer__brand {
  display: flex;
  flex-direction: column;
  gap: 20px;
  align-self: start;
}

.footer__wordmark {
  font-family: var(--serif);
  font-size: clamp(28px, 2.4vw, 36px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0;
}

.footer__tagline {
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
  max-width: 28ch;
}

.footer__social {
  list-style: none;
  padding: 0;
  margin: 16px 0 0;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: clamp(14px, 1.6vw, 22px);
}

.footer__social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: var(--mid);
  text-decoration: none;
  border: 0;
  padding: 0;
  border-radius: 999px;
  transition: color 200ms ease, background 200ms ease;
}

.footer__social a:hover,
.footer__social a:focus-visible {
  color: var(--ink);
  background: rgba(60, 50, 35, 0.04);
  outline: none;
}

.footer__nav-label,
.footer__contact-label {
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 20px;
}

.footer__nav ul,
.footer__contact ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.footer__nav a {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  transition: border-color 200ms ease;
}

.footer__nav a:hover {
  border-bottom-color: var(--ink);
}

.footer__contact ul {
  gap: 16px;
}

.footer__contact li {
  display: grid;
  /* Key column grows to fit the longest label (English "WHATSAPP"
     stays ~90px; Portuguese "LOCALIZAÇÃO" is wider and would
     otherwise overflow the fixed 90px track and collide with the
     value). minmax keeps a 90px floor so short labels stay aligned. */
  grid-template-columns: minmax(90px, max-content) 1fr;
  gap: 16px;
  align-items: baseline;
}

.footer__contact-key {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
  white-space: nowrap;
}

.footer__contact-value {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16px;
  line-height: 1.4;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 200ms ease;
}

a.footer__contact-value:hover {
  border-bottom-color: var(--ink);
}

/* Nav + footer logo — img element replacement for the legacy
   .brand-mark span. Both reference /logo/mayas-homes-mark.png. */
.nav__logo {
  display: inline-block;
  width: 28px;
  height: 28px;
  object-fit: contain;
  vertical-align: middle;
}
.footer__logo {
  display: block;
  width: 40px;
  height: 40px;
  object-fit: contain;
  margin-bottom: 4px;
}

/* ZONE 3b — Credentials strip
   Two-row structure: top row is the 3-column credentials grid
   (copyright · license · Maya's Care). Below it, a single centred
   line of legal links (Privacy · Terms · Livro de Reclamações) so
   the right column stays single-line and the layout reads balanced. */
.footer__credentials {
  max-width: 1440px;
  margin: 0 auto;
  padding: clamp(28px, 3vw, 36px) clamp(24px, 4vw, 64px);
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.6vw, 22px);
}
.footer__credentials-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto) minmax(0, 1fr);
  gap: clamp(16px, 3vw, 40px);
  align-items: center;
}
.footer__credentials-legal {
  text-align: center;
  padding-top: clamp(10px, 1.2vw, 18px);
  border-top: 1px solid rgba(45, 41, 38, 0.08);
}

.footer__credentials-line {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--mid);
  margin: 0;
  line-height: 1.5;
}

.footer__credentials-line em {
  font-family: var(--serif);
  font-style: italic;
  font-size: 12px;
  letter-spacing: 0;
  color: var(--ink);
}

.footer__credentials-line--left   { text-align: left; }
.footer__credentials-line--center { text-align: center; }
.footer__credentials-line--right  { text-align: right; }

.footer__credentials-link {
  color: var(--ink-2);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 200ms ease, border-color 200ms ease;
}

.footer__credentials-link:hover {
  color: var(--ink);
  border-bottom-color: var(--ink);
}

@media (max-width: 960px) {
  .footer__details {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  .footer__credentials {
    gap: 14px;
    text-align: center;
  }
  .footer__credentials-row {
    grid-template-columns: 1fr;
    gap: 12px;
    text-align: center;
  }
  .footer__credentials-line--left,
  .footer__credentials-line--center,
  .footer__credentials-line--right {
    text-align: center;
  }
  /* Tighten letter-spacing + allow wrap so the long credentials line
     ("Licensed renovation contractor · IMPIC 97976-PAR · AMI 18698")
     and the legal line below it don't overflow the viewport on phones. */
  .footer__credentials-line {
    font-size: 10px;
    letter-spacing: 0.08em;
    line-height: 1.7;
    overflow-wrap: break-word;
  }
  .footer__credentials-line em {
    font-size: 11px;
  }
  .footer__contact li {
    grid-template-columns: 80px 1fr;
    gap: 12px;
  }
}

/* — Reduced motion — */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =========================================================
   LAUNCH-PREP — disabled links, focus-visible, mobile nav
   ========================================================= */

/* Disable links to pages that don't exist yet. Visually softened,
   keyboard-skipped, click-blocked. Drop the inline override when
   the destination page lands. */
a[data-todo="project-page"],
a[data-todo="future-page"] {
  pointer-events: none;
  opacity: 0.55;
  cursor: default;
}

/* Focus-visible: a clear ink outline on all interactive elements
   when reached via keyboard. Skip when reached by mouse. */
a:focus-visible,
button:focus-visible,
[role="tab"]:focus-visible,
.contact__input:focus-visible,
.contact__textarea:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Mobile nav — hide the inline link bar at narrow widths and
   surface a hamburger that toggles a full-bleed drawer. */
.nav__menu-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: transparent;
  border: 0;
  color: var(--ink);
  cursor: pointer;
  padding: 0;
}
.nav__menu-toggle svg { width: 20px; height: 14px; }
.nav__menu-toggle .is-bar-x { display: none; }
.nav.is-open .nav__menu-toggle .is-bar-burger { display: none; }
.nav.is-open .nav__menu-toggle .is-bar-x      { display: inline; }

@media (max-width: 768px) {
  .nav__links {
    display: none;
  }
  .nav__cta {
    padding: 12px 16px;
    font-size: 11px;
    letter-spacing: 0.16em;
  }
  .nav__menu-toggle {
    display: inline-flex;
  }
  .nav.is-open .nav__links {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 28px;
    position: fixed;
    inset: 0;
    background: var(--bone);
    padding: clamp(80px, 18vh, 140px) clamp(28px, 6vw, 56px);
    z-index: 60;
    font-family: var(--serif);
    font-style: italic;
    font-size: clamp(24px, 6vw, 32px);
    color: var(--ink);
  }
  .nav.is-open .nav__links a {
    color: var(--ink);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: border-color 200ms ease;
  }
  .nav.is-open .nav__links a:hover {
    border-bottom-color: var(--ink);
  }
  /* Float the close (X) button above the drawer so it stays
     reachable while the menu is open. */
  .nav.is-open .nav__menu-toggle {
    position: fixed;
    top: 24px;
    right: 24px;
    z-index: 70;
  }
  /* Hide the CTA pill while the drawer is open so it doesn't
     bleed through visually. */
  .nav.is-open .nav__cta,
  .nav.is-open .nav__brand {
    visibility: hidden;
  }
}

/* =========================================================
   BRAND MARK — Maya's Homes mark, served from /logo/.
   ========================================================= */
.brand-mark {
  display: inline-block;
  width: 36px;
  height: 36px;
  background: url('/logo/mayas-homes-mark.png') center / contain no-repeat;
  flex-shrink: 0;
}
.brand-mark--small  { width: 28px; height: 28px; }
.brand-mark--large  { width: 56px; height: 56px; }

.footer__brand-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* =========================================================
   PAGE HEADER — shared top-of-page block on every dedicated
   page. Brand mark + eyebrow + display headline + lede.
   ========================================================= */
.page-header {
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(120px, 14vw, 200px) clamp(24px, 4vw, 64px) clamp(60px, 8vw, 120px);
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 3vw, 32px);
}
.page-header__eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0;
}
.page-header__title {
  font-family: var(--serif);
  font-size: clamp(48px, 8vw, 120px);
  font-weight: 400;
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
}
.page-header__title em {
  font-style: italic;
}
.page-header__lede {
  font-family: var(--sans);
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.55;
  color: var(--ink);
  letter-spacing: -0.005em;
  max-width: 56ch;
  margin: 0;
}

.page-section {
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(60px, 8vw, 120px) clamp(24px, 4vw, 64px);
}
.page-section + .page-section {
  /* Full-width border-top replaced by a centred hairline pseudo —
     see the shared .section-divider-hairline rule near the
     .section-ornament block for the actual line styles. */
  position: relative;
}
.page-section__head {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: clamp(32px, 4vw, 48px);
}
.page-section__eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.page-section__title {
  font-family: var(--serif);
  font-size: clamp(32px, 4vw, 56px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
}
.page-section__title em { font-style: italic; }
.page-section__lede {
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0;
  max-width: 64ch;
}
.page-section__body {
  display: flex;
  flex-direction: column;
  gap: 1.2em;
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.7;
  color: var(--ink);
  max-width: 64ch;
}

/* =========================================================
   PHOTO PLACEHOLDER — square paper-cream frame with the
   brand mark inside. Replace each <figure> contents with an
   <img> when real photography lands; aspect-ratio container
   prevents layout shift.
   ========================================================= */
.photo-placeholder {
  background: var(--paper);
  aspect-ratio: 4 / 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  border: 1px solid var(--hairline);
  margin: 0;
  text-align: center;
  padding: clamp(16px, 2vw, 28px);
}
.photo-placeholder--portrait { aspect-ratio: 4 / 5; }
.photo-placeholder--square   { aspect-ratio: 1 / 1; }
.photo-placeholder--wide     { aspect-ratio: 16 / 9; }
.photo-placeholder__caption {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
}

/* Active state for the floating nav link matching the current page. */
.nav__links a.is-current {
  color: var(--ink);
  position: relative;
}
.nav__links a.is-current::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 1px;
  background: var(--ink);
}

/* =========================================================
   PAGE-SECTION HELPERS — used across the new dedicated pages.
   Centred CTA blocks, stacked content scaffolds, etc.
   ========================================================= */
.page-section--cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  text-align: center;
}

/* ---- Studio page ---- */
.studio-principles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(28px, 3vw, 44px);
}
.studio-principles article {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 24px;
  border-top: 1px solid var(--hairline);
}
.studio-principles h3 {
  font-family: var(--serif);
  font-size: clamp(20px, 1.8vw, 26px);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.005em;
  margin: 0;
}
.studio-principles p {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
}

.studio-bench {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
}
.studio-bench li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 24px;
  padding: 16px 0;
  border-top: 1px solid var(--hairline);
  align-items: baseline;
}
.studio-bench li:last-child { border-bottom: 1px solid var(--hairline); }
.studio-bench b {
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 400;
  letter-spacing: -0.005em;
}
.studio-bench span {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
}

.studio-press {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: clamp(20px, 2vw, 32px);
}

/* ---- Projects index ---- */
.projects-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: clamp(40px, 5vw, 64px);
}
.projects-filter__btn {
  background: transparent;
  border: 1px solid var(--hairline-strong);
  border-radius: 999px;
  padding: 10px 20px;
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  transition: background 200ms ease, color 200ms ease, border-color 200ms ease;
}
.projects-filter__btn:hover { color: var(--ink); border-color: var(--ink); }
.projects-filter__btn.is-active {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

.projects-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(28px, 3vw, 48px);
}
@media (max-width: 960px) {
  .projects-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .projects-grid { grid-template-columns: 1fr; }
}
.project-card a {
  display: flex;
  flex-direction: column;
  gap: 16px;
  text-decoration: none;
  color: inherit;
}
.project-card h3 {
  font-family: var(--serif);
  font-size: clamp(20px, 1.8vw, 26px);
  font-weight: 400;
  letter-spacing: -0.005em;
  margin: 0;
  color: var(--ink);
}
.project-card p {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.project-card a:hover h3 { text-decoration: underline; text-underline-offset: 4px; }

/* ---- Single project page ---- */
.project-meta {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 24px;
  border-top: 1px solid var(--hairline);
  padding-top: 24px;
}
.project-meta li { display: flex; flex-direction: column; gap: 6px; }
.project-meta span {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
}
.project-meta b {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 18px;
  color: var(--ink);
}

.project-photo-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
}
@media (min-width: 960px) {
  .project-photo-grid { grid-template-columns: repeat(3, 1fr); }
}
.project-photo-grid li { margin: 0; }

.project-decisions {
  list-style: none;
  counter-reset: decision;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 28px;
}
.project-decisions li {
  counter-increment: decision;
  padding-top: 24px;
  border-top: 1px solid var(--hairline);
}
.project-decisions h3 {
  font-family: var(--serif);
  font-size: clamp(20px, 2vw, 28px);
  font-weight: 400;
  margin: 0 0 8px;
}
.project-decisions h3::before {
  content: counter(decision, decimal-leading-zero) " · ";
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  color: var(--mid);
  margin-right: 4px;
  vertical-align: middle;
}
.project-decisions p {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0;
  max-width: 64ch;
}

.project-materials {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
}
.project-materials li {
  display: grid;
  grid-template-columns: minmax(0, 200px) minmax(0, 1fr);
  gap: 24px;
  padding: 16px 0;
  border-top: 1px solid var(--hairline);
  align-items: baseline;
}
.project-materials li:last-child { border-bottom: 1px solid var(--hairline); }
.project-materials span {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
}
.project-materials b {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 18px;
}

.next-projects {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(28px, 3vw, 48px);
}
@media (max-width: 600px) {
  .next-projects { grid-template-columns: 1fr; }
}

/* ---- Services index page ---- */
.services-detail-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: clamp(48px, 5vw, 80px);
}
.service-detail-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: clamp(32px, 4vw, 56px);
  align-items: start;
  padding-top: clamp(40px, 5vw, 64px);
  border-top: 1px solid var(--hairline);
}
.service-detail-card:first-child { padding-top: 0; border-top: 0; }
.service-detail-card .services__shot {
  position: relative;
  aspect-ratio: 4 / 3;
  margin: 0;
  background: var(--bone-2);
  overflow: hidden;
  border: 1px solid var(--hairline);
}
.service-detail-card h2 {
  font-family: var(--serif);
  font-size: clamp(28px, 3vw, 40px);
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 0 0 16px;
}
.service-detail-card p {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink);
  margin: 0 0 16px;
  max-width: 64ch;
}
.service-detail-card h4 {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 24px 0 12px;
}
.service-detail-card ul {
  list-style: none;
  padding: 0;
  margin: 0 0 20px;
  display: grid;
  gap: 6px;
}
.service-detail-card ul li {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
  position: relative;
  padding-left: 18px;
}
.service-detail-card ul li::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--mid);
}
.services__example-link {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
}
@media (max-width: 720px) {
  .service-detail-card { grid-template-columns: 1fr; }
}

/* ---- K&B page ---- */
.kb-materials {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: clamp(28px, 3vw, 48px);
}
.kb-materials li {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.kb-materials h3 {
  font-family: var(--serif);
  font-size: clamp(20px, 1.8vw, 26px);
  font-weight: 400;
  margin: 0;
}
.kb-materials p {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0;
}

.kb-pricing {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: clamp(32px, 4vw, 56px);
}
.kb-pricing li {
  padding: clamp(28px, 3vw, 40px);
  border: 1px solid var(--hairline-strong);
  background: var(--paper);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.kb-pricing h3 {
  font-family: var(--serif);
  font-size: clamp(22px, 2vw, 28px);
  font-weight: 400;
  margin: 0;
}
.kb-pricing__range {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(28px, 3vw, 40px);
  color: var(--ink);
  margin: 0;
}
.kb-pricing p {
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
}

/* ---- Process page ---- */
.process-phase__head {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: clamp(32px, 4vw, 48px);
}
.process-phase__duration {
  font-family: var(--sans);
  font-style: italic;
  font-size: 14px;
  letter-spacing: 0.04em;
  color: var(--mid);
  margin: 0;
}
.process-phase__body {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
  gap: clamp(40px, 5vw, 72px);
  align-items: start;
}
@media (max-width: 720px) {
  .process-phase__body { grid-template-columns: 1fr; }
}
.process-phase__deliverables {
  margin-top: clamp(40px, 5vw, 64px);
  padding: clamp(28px, 3vw, 40px);
  background: var(--paper);
  border: 1px solid var(--hairline);
}
.process-phase__deliverables h4 {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 16px;
}
.process-phase__deliverables ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px 32px;
}
.process-phase__deliverables li {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
  position: relative;
  padding-left: 18px;
}
.process-phase__deliverables li::before {
  content: "—";
  position: absolute;
  left: 0;
  color: var(--mid);
}

/* ---- Contact page extras ---- */
.contact__form--full {
  display: grid;
  gap: clamp(20px, 2.5vw, 28px);
  max-width: 720px;
  margin: 0 auto;
}
.contact__radios {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 24px;
  font-family: var(--serif);
  font-size: 17px;
  color: var(--ink);
}
.contact__radios label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
select.contact__input {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8'><path d='M1 1l5 5 5-5' stroke='%2314110E' stroke-width='1.5' fill='none'/></svg>");
  background-repeat: no-repeat;
  background-position: right 4px center;
  padding-right: 24px;
}

.contact-next-steps {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(28px, 3vw, 48px);
}
@media (max-width: 720px) {
  .contact-next-steps { grid-template-columns: 1fr; }
}
.contact-next-steps li {
  padding-top: 24px;
  border-top: 1px solid var(--hairline);
}
.contact-next-steps h3 {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 12px;
}
.contact-next-steps p {
  font-family: var(--serif);
  font-size: 18px;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
}

.contact-faq {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
}
.contact-faq li {
  border-top: 1px solid var(--hairline);
}
.contact-faq li:last-child { border-bottom: 1px solid var(--hairline); }
.contact-faq summary {
  font-family: var(--serif);
  font-size: clamp(18px, 1.6vw, 22px);
  font-weight: 400;
  color: var(--ink);
  padding: 20px 0;
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.contact-faq summary::-webkit-details-marker { display: none; }
.contact-faq summary::after {
  content: "+";
  font-family: var(--sans);
  font-size: 22px;
  color: var(--mid);
  transition: transform 240ms ease;
}
.contact-faq details[open] summary::after { content: "−"; }
.contact-faq details p {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0 0 24px;
  max-width: 64ch;
}

/* ---- Journal page ---- */
.journal-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(40px, 5vw, 72px);
}
@media (max-width: 720px) {
  .journal-grid { grid-template-columns: 1fr; }
}
.journal-card a {
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}
.journal-card__meta {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.journal-card h3 {
  font-family: var(--serif);
  font-size: clamp(22px, 2.2vw, 32px);
  font-weight: 400;
  letter-spacing: -0.005em;
  line-height: 1.15;
  margin: 0;
  color: var(--ink);
}
.journal-card p:not(.journal-card__meta):not(.journal-card__date) {
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0;
}
.journal-card__date {
  font-family: var(--sans);
  font-style: italic;
  font-size: 12px;
  color: var(--mid);
  margin: 0;
}

/* ─────────────────────────────────────────────────────────────
 * CTA SYSTEM — three tiers
 * ─────────────────────────────────────────────────────────────
 * TIER 1: Primary action — glass pill (.nav__cta, .contact__submit,
 *         .footer__outro-cta, .btn-glass). Sparingly used.
 * TIER 2: Section closer (.section-closer) — italic serif link
 *         with arrow, sits at the end of major sections.
 * TIER 3: Inline cross-link (.cross-link) — within body copy.
 *
 * Use Tier 2 for "next destination" navigation between sections.
 * Use Tier 3 for in-prose cross-references.
 * ───────────────────────────────────────────────────────────── */

/* TIER 2 — Section closer.
   Discrete inline transition. No hairline above; breathing space
   above and below replaces it so the closer reads as a soft
   outdent of the previous section, never as a new band. */
.section-closer,
.section-closer--minimal {
  border-top: 0;
  padding-top: clamp(48px, 6vw, 80px);
  padding-bottom: 0;
  background: transparent;
}
.section-closer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  margin: 0;
}
.section-closer__eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.section-closer__link,
.section-closer--minimal .section-closer__link {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(17px, 1.4vw, 21px);
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
  transition: gap 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.section-closer__arrow {
  display: inline-block;
  transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.section-closer__link:hover,
.section-closer--minimal .section-closer__link:hover {
  color: var(--ink);
  text-decoration: none;
  gap: 18px;
}
.section-closer__link:hover > span:not(.section-closer__arrow),
.section-closer--minimal .section-closer__link:hover > span:not(.section-closer__arrow) {
  text-decoration: underline;
  text-underline-offset: 4px;
}
.section-closer__link:hover .section-closer__arrow,
.section-closer--minimal .section-closer__link:hover .section-closer__arrow {
  transform: translateX(4px);
}

/* Minimal variant — ghost pill at rest, full glass on hover.
   Differentiates the section closer (tertiary navigation) from
   primary CTAs (.nav__cta, .contact__submit, .tile__view) which
   stay in filled glass at rest. The hover transition delivers the
   primary-button feel only on intentional interaction. */
.section-closer--minimal {
  max-width: var(--container, 1240px);
  margin: 0 auto;
  padding-left: clamp(24px, 4vw, 64px);
  padding-right: clamp(24px, 4vw, 64px);
  display: flex;
  justify-content: flex-end;
  gap: 0;
}

/* Canonical glassy-white pill — same identity as .btn-silver
   sitewide. Previously this link used a ghost-then-cream-gradient
   pattern which read gold on warm body backgrounds; switched to
   the canonical glass so every button on the site shares one
   shape and one colour. */
.section-closer--minimal .section-closer__link {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 12px 24px;
  font-family: var(--sans);
  font-style: normal;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--ink);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.16) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 999px;
  box-shadow:
    0  8px 32px rgba(0, 0, 0, 0.08),
    0  2px  6px rgba(0, 0, 0, 0.04),
    inset 0  1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);
  transition:
    gap 360ms cubic-bezier(0.2, 0.8, 0.2, 1),
    border-color 0.3s ease,
    box-shadow 0.3s ease,
    transform 0.25s ease;
}

.section-closer--minimal .section-closer__link:hover {
  gap: 18px;
  text-decoration: none;
  color: var(--ink);
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow:
    0 12px 36px rgba(0, 0, 0, 0.10),
    0  3px  8px rgba(0, 0, 0, 0.05),
    inset 0  1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
  transform: translateY(-1px);
}

/* Neutralize the shared underline-on-hover for the pill variant —
   the pill itself signals the click target, no underline needed. */
.section-closer--minimal .section-closer__link:hover > span:not(.section-closer__arrow) {
  text-decoration: none;
}

/* Mobile breathing room — when long button text wraps to two lines on
   small screens (e.g. "Meet the practice behind the work"), line-height: 1
   makes the lines touch and feel cramped. Bump to 1.5 so wrapped text
   reads as a deliberate two-line label, not a squeezed afterthought.
   Also centre the pill on mobile — the desktop flex-end alignment
   pushes it to the right edge, which reads as orphaned at column
   widths. Centred reads as a deliberate end-cap. */
@media (max-width: 768px) {
  .section-closer--minimal {
    justify-content: center;
  }
}
@media (max-width: 480px) {
  .section-closer--minimal .section-closer__link {
    line-height: 1.5;
  }
}

.section-closer--minimal .section-closer__arrow {
  display: inline-block;
  font-size: 14px;
  transition: transform 360ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.section-closer--minimal .section-closer__link:hover .section-closer__arrow {
  transform: translateX(3px);
}

@media (max-width: 700px) {
  .section-closer { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* TIER 3 — Inline cross-link within body copy */
.cross-link {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
  padding-bottom: 1px;
  transition: border-color 220ms ease;
}
.cross-link:hover {
  border-bottom-color: var(--ink);
}
.cross-link::after {
  content: " →";
  display: inline-block;
  font-family: var(--sans);
  font-style: normal;
  font-size: 0.85em;
  margin-left: 2px;
  transition: transform 280ms ease;
}
.cross-link:hover::after {
  transform: translateX(3px);
}

/* =========================================================
   Shared editorial helpers — used by /studio/ and /projects/
   (and any future long-form page).
   ========================================================= */
.wrap {
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 clamp(24px, 4vw, 64px);
}
.wrap--narrow { max-width: 720px; }

.eyebrow--centered { text-align: center; }

.fade-in {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.9s cubic-bezier(0.2, 0.8, 0.2, 1),
              transform 0.9s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.fade-in.is-in {
  opacity: 1;
  transform: translateY(0);
}

/* Pull-quote — italic Cormorant with a hairline left rule. */
.maja-quote {
  margin: 0 auto;
  padding: 0 0 0 clamp(24px, 3vw, 48px);
  border-left: 1px solid var(--hairline-strong);
  max-width: 880px;
}
.maja-quote p {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 2vw, 28px);
  line-height: 1.5;
  color: var(--ink);
  margin: 0 0 clamp(20px, 2.5vw, 32px);
}
.maja-quote--large p {
  font-size: clamp(22px, 2.4vw, 34px);
  line-height: 1.4;
}
.maja-quote cite {
  font-family: var(--sans);
  font-style: normal;
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
}


/* Placeholder image blocks — used until photography ships. */
.ph-block {
  position: relative;
  width: 100%;
  background: var(--paper);
  border: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
}
.ph-block--portrait      { aspect-ratio: 4 / 5; }
.ph-block--portrait-tall { aspect-ratio: 3 / 4; }
.ph-block--square        { aspect-ratio: 1 / 1; }
.ph-block--landscape     { aspect-ratio: 16 / 9; }
.ph-block__label {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mid);
  text-align: center;
  padding: 0 16px;
}

/* =========================================================
   /studio/ page
   ========================================================= */
/* === Studio §01 — Magazine title page (typographic, centered) ===
   Transparent — body marble backsplash shows through. Plain typography on
   marble, no pills, no panels. The headline carries the section. */
.studio__hero {
  position: relative;
  min-height: 100vh;
  padding: clamp(140px, 18vh, 240px) 0 clamp(40px, 5vh, 64px);
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: transparent;
  background-image: none;
  box-shadow: none;
  box-sizing: border-box;
}
.studio__hero > * {
  position: relative;
  z-index: 2;
}
.studio__hero-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 clamp(24px, 4vw, 48px);
}
.studio__hero .eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(45, 41, 38, 0.85);
  margin: 0 0 clamp(28px, 3.2vw, 44px);
}
.studio__name {
  font-family: var(--serif);
  font-style: normal;
  font-weight: 400;
  font-size: clamp(3rem, 7vw, 6rem);
  line-height: 1.05;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0;
}
.studio__role {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: rgba(45, 41, 38, 0.85);
  margin: clamp(32px, 3.6vw, 48px) 0 0;
}
.studio__lede {
  font-family: var(--serif);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.55;
  color: var(--ink);
  max-width: 56ch;
  margin: clamp(36px, 4vw, 56px) auto 0;
}
@media (max-width: 760px) {
  .studio__hero {
    padding: clamp(100px, 14vh, 140px) 0 clamp(56px, 8vh, 80px);
  }
  .studio__name {
    font-size: clamp(2.5rem, 10vw, 4rem);
    letter-spacing: -0.012em;
  }
  .studio__hero .eyebrow,
  .studio__role {
    font-size: 10.5px;
    letter-spacing: 0.18em;
  }
  .studio__lede {
    font-size: clamp(16px, 2.2vw, 19px);
  }
}

/* === Studio §02 — A practice in Cascais ===
   Two-column meet-the-founder layout. Portrait sticks at desktop so the
   reader keeps Maja in view through the biography. Italic budget for §02
   stays at three: H2 "Still here.", ¶3 voice line, figcaption "Alcabideche". */
.studio__intro {
  padding: clamp(80px, 10vw, 140px) 0 clamp(100px, 12vw, 160px);
  background-color: transparent;
  background-image: none;
}
.studio__intro-photo {
  margin: 0 auto;
  width: 100%;
  max-width: 1400px;
  padding: 0 clamp(32px, 5vw, 96px);
  box-sizing: border-box;
}
.studio__intro-photo-frame {
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
.studio__intro-photo-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Caption block beneath the photo — Plex Mono metadata left, italic title +
   explanatory paragraph right. Cereal magazine image-with-credits register. */
/* === Scene break / bridge between §02 biography and §03 spread === */
.scene-break {
  max-width: 540px;
  margin: 7rem auto;
  text-align: center;
}
.scene-break p {
  font-style: italic;
  font-family: var(--serif);
  font-size: 1.25rem;
  line-height: 1.6;
  color: rgba(45, 41, 38, 0.75);
  margin: 0;
  letter-spacing: 0.005em;
}
@media (max-width: 768px) {
  .scene-break {
    margin: 5rem auto;
  }
  .scene-break p {
    font-size: 1.125rem;
  }
}

/* === §03 side-by-side: image LEFT (dominant) + text RIGHT.
       1.4fr / 1fr — inverse of §02's 1.4fr / 1fr text-dominant
       ratio, so the photo carries the visual weight here while
       §02 carries it via the longer biographical text. === */
.studio__intro-spread {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 4rem;
  align-items: center;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 2rem;
}
.studio__intro-spread .studio__intro-photo {
  position: sticky;
  top: 6rem;
  align-self: start;
  margin: 0;
  width: 100%;
  max-width: none;
  padding: 0;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  overflow: hidden;
  /* Atmospheric layered lift — close + soft shadows so the photo
     reads as a contained editorial plate on the taupe section. */
  box-shadow:
    0 1px 2px rgba(45, 41, 38, 0.04),
    0 24px 56px rgba(45, 41, 38, 0.08);
}
.studio__intro-photo-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}
.studio__intro-spread .studio__intro-spread-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 16px 20px;
  border-top: 0;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone);
  background: linear-gradient(180deg, rgba(20, 17, 14, 0) 0%, rgba(20, 17, 14, 0.55) 100%);
}
.studio__intro-spread .studio__intro-spread-caption span {
  font-family: var(--sans);
  color: var(--bone);
  letter-spacing: 0.22em;
  font-size: var(--fs-xs);
  line-height: 1;
}
.studio__intro-spread-caption {
  display: block;
  margin-top: 1rem;
}
.studio__intro-spread-text .studio__intro-subtitle {
  margin-bottom: 0;
}
.studio__intro-spread-caption span {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(45, 41, 38, 0.7);
  line-height: 1.6;
}
.studio__intro-spread-text {
  align-self: center;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 0;
}
/* §03 eyebrow — mirror §02's .studio__intro-text .eyebrow exactly
   so the two intro columns read at the same eyebrow size/weight.
   The base .eyebrow (12 px, weight 500, ls 0.22em) was too heavy
   above the §03 "Welcome to Maja's home." headline. */
.studio__intro-spread-text .eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-2);
  margin: 0 0 clamp(20px, 2.4vw, 32px);
}
/* §03 hospitality headline — sized at the canonical .display scale
   (var(--fs-2xl)) so it reads at the same weight as home page H2s.
   Earlier passes inflated it to 6rem when the section had no body
   content; with the manifesto-style lede paragraph reintroduced,
   standard scale carries enough weight. Deterministic <br> in the
   markup breaks the line cleanly at "Welcome to / Maja's home." */
.studio__intro-spread-text .studio__h2 {
  font-size: var(--fs-2xl);
  line-height: 1.05;
  letter-spacing: -0.022em;
  margin: 0 0 1.5rem;
}
/* Manifesto-style lede paragraph — Inter sans, secondary ink,
   matches the home page .manifesto__lede pattern. */
.studio__intro-spread-lede {
  font-family: var(--sans);
  font-size: var(--fs-lg);
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0 0 1.5rem;
  max-width: 56ch;
}
/* Invitation closer — sits beneath the lede as the section's
   editorial flourish line. Uses the same Inter sans family as the
   lede above so §03 reads as one consistent typeset (the closer
   was previously Cormorant italic, which broke the section's
   single-family rhythm against the §02 bio column). */
.studio__intro-spread-close {
  font-family: var(--sans);
  font-style: italic;
  font-size: var(--fs-lg);
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
}
.studio__intro-spread-close em {
  font-style: italic;
}
.studio__intro-spread-text p em {
  font-style: italic;
  color: var(--ink-2);
}
.studio__intro-spread-text p {
  font-family: var(--sans);
  font-size: var(--fs-lg);
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--ink-2);
  margin: 0 0 1.5rem;
}
.studio__intro-spread-text p:last-child {
  margin-bottom: 0;
}
.studio__intro-close {
  font-style: italic;
  margin-top: clamp(8px, 1vw, 16px) !important;
}
@media (max-width: 900px) {
  .studio__intro-spread {
    grid-template-columns: 1fr;
    gap: 2.5rem;
    padding: 0 1.5rem;
    max-width: 540px;
  }
  .studio__intro-spread .studio__intro-photo {
    position: static;
    top: auto;
    align-self: stretch;
    /* Image goes BELOW the text on mobile in "The House" / "Welcome
       to Maja's home" — eyebrow + heading + body lead, photo confirms. */
    order: 2;
  }
  .studio__intro-spread-text {
    align-self: stretch;
    order: 1;
  }
  .studio__intro-spread-text .studio__h2 {
    font-size: clamp(2.5rem, 9vw, 4rem);
    letter-spacing: -0.018em;
  }
}
/* iPad landscape intermediate band — 1.4fr/1fr feels squeezed at
   1024-1100px (text column ~370px against a sticky photo ~520px).
   Rebalance to equal 1fr/1fr in this range so the text breathes. */
@media (min-width: 901px) and (max-width: 1100px) {
  .studio__intro-spread {
    grid-template-columns: 1fr 1fr;
  }
}
.studio__intro .wrap--narrow {
  margin-bottom: clamp(72px, 9vw, 120px);
}
/* === §02 — biographical text + Maja portrait companion ===
   2-column grid: text left (1.4fr), sticky portrait right (1fr).
   The italic line "An Italian birth, a Northern eye." sits as
   a subtitle directly under the .studio__h2 inside the text
   column. Mobile collapses to a single column with the portrait
   stacked beneath the text and capped at 360px. */
.studio__intro-subtitle {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(1.125rem, 1.5vw, 1.375rem);
  line-height: 1.4;
  color: rgba(45, 41, 38, 0.75);
  font-weight: 400;
  margin: -0.75rem 0 1.75rem 0;
}
@media (max-width: 900px) {
  .studio__intro-subtitle {
    font-size: 1.125rem;
    margin: -0.5rem 0 1.25rem 0;
  }
}
.studio__intro-bio {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(24px, 4vw, 48px);
}
.studio__intro-columns {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: 4rem;
  align-items: start;
  margin-top: clamp(28px, 3vw, 40px);
}
.studio__intro-portrait {
  margin: 0;
  position: sticky;
  top: 8rem;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
.studio__intro-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border-radius: 0;
}
.studio__intro-portrait figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 16px 20px;
  margin-top: 0;
  border-top: 0;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone);
  background: linear-gradient(180deg, rgba(20, 17, 14, 0) 0%, rgba(20, 17, 14, 0.55) 100%);
}
/* Hide the dark image-overlay captions on mobile — at small widths the
   "MAJA MILIČ — CASCAIS" and "STUDIO — ALCABIDECHE" bands read as
   stock-photo descriptors rather than editorial labels. */
@media (max-width: 768px) {
  .studio__intro-portrait figcaption,
  .studio__intro-spread .studio__intro-spread-caption {
    display: none;
  }
}
@media (max-width: 900px) {
  .studio__intro-columns {
    grid-template-columns: 1fr;
    gap: 2.5rem;
    max-width: 540px;
    margin-left: auto;
    margin-right: auto;
  }
  .studio__intro-portrait {
    position: static;
    max-width: 360px;
    margin: 0 auto;
  }
}

.studio__intro-text {
  display: flex;
  flex-direction: column;
}
.studio__intro-text .eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-2);
  margin: 0 0 clamp(20px, 2.4vw, 32px);
}
.studio__h2 {
  font-family: var(--serif);
  font-weight: 400;
  font-style: normal;
  font-size: var(--fs-2xl);
  line-height: 1.1;
  letter-spacing: -0.022em;
  color: var(--ink);
  margin: 0 0 clamp(36px, 4vw, 56px);
}
.studio__h2--centered { text-align: center; }
.studio__h2 em { font-style: italic; }

/* ===== Approach section (slot 04b on /profile/, salvaged from the
   deleted /local/ page 2026-05-24). Three beats: a centred header,
   a 2-column materials/finishes grid, then a split layout pairing
   the "on the light" copy with the van-on-Cascais-waterfront photo.
   Sits between the spine quote and Maja's Selection. */
.studio__approach {
  padding: clamp(96px, 12vw, 160px) 0;
  background: var(--bone);
}
.studio__approach-head {
  text-align: center;
  margin: 0 auto clamp(64px, 8vw, 112px);
  max-width: 800px;
}
.studio__approach-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  max-width: 1100px;
  margin: 0 auto clamp(80px, 10vw, 140px);
}
.studio__approach-block .eyebrow {
  margin-bottom: clamp(14px, 1.6vw, 22px);
}
.studio__approach-block p {
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: 1.65;
  color: var(--ink-2);
  margin: 0 0 1.1rem;
}
.studio__approach-h3 {
  font-family: var(--serif);
  font-size: clamp(28px, 2.8vw, 40px);
  font-weight: 400;
  line-height: 1.15;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 clamp(20px, 2vw, 28px);
}
/* Reverse variant of the House spread — text left (1fr), photo right
   (1.4fr). Same proportions as §03 but mirrored. Photo frame opens to
   its native aspect ratio here instead of being cropped to 4:3, since
   the van photo is landscape and meant to be seen uncropped.
   Scoped to ≥901px — at mobile the existing collapse rule for
   .studio__intro-spread (1fr) must apply to both variants. */
@media (min-width: 901px) {
  .studio__intro-spread--reverse {
    grid-template-columns: 1fr 1.4fr;
  }
}
.studio__intro-spread--reverse .studio__intro-photo-frame {
  aspect-ratio: auto;
}
.studio__intro-spread--reverse .studio__intro-photo-frame img {
  height: auto;
  object-fit: initial;
}
.studio__intro-text p {
  font-family: var(--sans);
  font-weight: 400;
  font-size: var(--fs-lg);
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--ink-2);
  max-width: 56ch;
  margin: 0 0 1.5rem;
}
.studio__intro-text p:last-child {
  margin-bottom: 0;
}
.studio__intro-text p em {
  font-style: italic;
  color: var(--ink);
}
@media (max-width: 760px) {
  .studio__intro {
    padding: clamp(56px, 8vw, 80px) 0 clamp(72px, 10vw, 100px);
  }
  .studio__intro .wrap--narrow {
    margin-bottom: clamp(48px, 8vw, 80px);
  }
}
@media (max-width: 600px) {
  .studio__intro-text p {
    font-size: 16px;
    line-height: 1.6;
  }
}

/* === Studio §05 — Nine-person studio grid (Loro Piana atelier sheet).
   Maja in the lead cell, then the bench by tenure. 4:5 portrait aspect
   ratio locks row baselines across all nine cells. Background returns to
   var(--bone) so §03's --paper stays the only spine moment in the page. */
.studio__people {
  /* Trimmed twice — once for the flat-taupe pass, again for this
     rhythm tightening so the section reads continuous with the
     thinner hairline divider above it. */
  padding: clamp(64px, 8vw, 96px) 0;
  background-color: transparent;
  background-image: none;
}
.studio__people .eyebrow--centered {
  text-align: center;
  margin: 0 0 clamp(20px, 2.4vw, 32px);
}
.studio__people .studio__h2--centered {
  text-align: center;
  font-family: var(--serif);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(36px, 4.2vw, 56px);
  line-height: 1.12;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0 auto;
  max-width: 18ch;
}
.studio__people .studio__h2--centered em {
  font-style: italic;
}
.studio__people-lede {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.55;
  color: var(--ink-2);
  text-align: center;
  margin: clamp(20px, 2.4vw, 32px) auto 0;
  max-width: 56ch;
}
.studio__people-note {
  font-family: var(--serif);
  font-weight: 400;
  font-style: normal;
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.55;
  color: var(--mid);
  text-align: center;
  margin: clamp(48px, 6vw, 80px) auto 0;
  max-width: 60ch;
}
.studio__people-note em {
  font-style: italic;
  color: var(--ink-2);
}
@media (max-width: 600px) {
  .studio__people {
    padding: clamp(80px, 12vw, 120px) 0;
  }
  .studio__people .studio__h2--centered {
    font-size: clamp(28px, 6.5vw, 36px);
  }
}

/* === Studio §06 — Schools, licenses, languages ===
   Quiet data interlude. Plex Mono on every body line — schools, license
   codes, language abbreviations — so the section reads as one calm field
   of facts. Single hairline above the grid marks the data block. Padding
   smaller than §04/§05 so the section reads as a brief pause before §07. */
.studio__credentials {
  padding: clamp(80px, 10vw, 120px) 0;
  background-color: var(--bone);
  background-image: none;
  /* Border-top removed — the .section-ornament div in HTML above
     this section already provides the centered-hairline divider. */
}
/* §08 eyebrow → H2 vertical breathing room. Bigger than the
   §05/§07 baseline (clamp 20, 2.4vw, 32) per user request, since
   the stat-grid section's H2 is doing more weight-lifting and
   needs more space above it to land. */
.studio__credentials .eyebrow--centered {
  margin: 0 0 clamp(28px, 3.2vw, 44px);
}
/* §08 stat grid — four big serif numbers across, each with a small
   caps label and a body line. Replaces the previous four-column
   .studio__credentials-grid of Plex Mono bullet lines, which read
   as webpage-footer rather than editorial proof. */
.studio__facts-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(32px, 4vw, 64px);
  align-items: start;
  margin: clamp(48px, 6vw, 80px) auto 0;
}
.studio__facts-stat {
  display: flex;
  flex-direction: column;
  /* Centre every child horizontally + centre the text inside each
     child. Without this, the number (variable character width:
     "25" vs "8") sat left-aligned inside the cell, so "8" looked
     visually offset from its label. */
  align-items: center;
  text-align: center;
  /* Bigger uniform gap between number and label since they now
     align across all four cells. */
  gap: 16px;
  margin: 0;
}
.studio__facts-number {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(56px, 7vw, 96px);
  /* line-height 1 gives every number a consistent text-box height
     regardless of character. font-variant-numeric forces lining
     (uniform cap-height, all on same baseline) + tabular (uniform
     advance width) so a single-digit "8" sits at the exact same
     vertical position as the two-digit "25" — Cormorant's
     proportional figures rendered "8" slightly higher in its
     line-box than the others. */
  font-variant-numeric: lining-nums tabular-nums;
  line-height: 1;
  letter-spacing: -0.025em;
  color: var(--ink);
  margin: 0;
}
.studio__facts-label {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0;
}
.studio__facts-body {
  font-family: var(--sans);
  font-size: clamp(14px, 1.1vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0;
  max-width: 20ch;
}
/* Recessive regulatory/capability footnote — Plex Mono, small,
   centred. Lives for due-diligence visitors (is she licensed?
   what trades?) without fighting the stat grid for attention. */
.studio__facts-footnote {
  font-family: var(--mono);
  font-size: clamp(11px, 0.85vw, 13px);
  font-weight: 400;
  line-height: 1.7;
  letter-spacing: 0.02em;
  color: var(--mid);
  text-align: center;
  margin: clamp(56px, 7vw, 88px) auto 0;
  max-width: 80ch;
}
@media (max-width: 900px) {
  .studio__facts-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: clamp(36px, 5vw, 48px);
  }
}
@media (max-width: 540px) {
  .studio__facts-grid {
    grid-template-columns: 1fr;
    gap: clamp(28px, 6vw, 36px);
  }
  .studio__facts-number {
    font-size: clamp(48px, 14vw, 72px);
  }
}
@media (max-width: 760px) {
  .studio__credentials {
    padding: clamp(64px, 9vw, 88px) 0;
  }
}

/* === Studio §07 — A note from Maja + section closer ===
   Italic Cormorant body — entire letter wrapped in <em> in the markup;
   font-style: italic on the rule reinforces. Block-centered (max-width
   720px on the wrap), text inside flows left-aligned — letter format,
   not poem format. Signature uses normal-weight em-dash + italic name,
   mirroring how a typewritten letter would actually be signed. Section
   closer is scoped so it only restyles the closer when nested inside
   .studio__letter — base .section-closer component stays unchanged. */
.studio__letter {
  position: relative;
  padding: clamp(120px, 16vw, 200px) 0 clamp(80px, 10vw, 120px);
  background-color: var(--bone);
  background-image: none;
  /* Border-top removed — the .section-ornament div in HTML above
     this section already provides the centered-hairline divider. */
  box-shadow: none;
  color: var(--ink);
}
.studio__letter > * {
  position: relative;
  z-index: 2;
}
.studio__letter .wrap--narrow {
  /* Override the default --container-narrow (900 px) → 1000 px so
     the bigger Cormorant italic body has room to breathe. Still
     narrower than the regular .wrap (1240 px) so the section keeps
     its "personal letter" register rather than becoming a wide
     manifesto banner. */
  max-width: 1000px;
  margin: 0 auto;
}
.studio__letter .eyebrow--centered {
  display: block;
  text-align: center;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(45, 41, 38, 0.85);
  /* Eyebrow → portrait spacing is set on the portrait's margin-top
     below; eyebrow margin-bottom just provides the immediate gap. */
  margin: 0 0 clamp(28px, 3.4vw, 44px);
}
/* §09 note body — Cormorant italic at full editorial scale. Bumped
   from clamp(22, 2.2vw, 30) → clamp(28, 2.8vw, 42) px so the note
   reads as the page's closing focal moment, not a discreet
   whisper. The wider container override below gives the bigger
   type room to breathe without wrapping awkwardly. */
.studio__letter-body {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 3.4vw, 44px);
}
.studio__letter-body p {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(28px, 2.8vw, 42px);
  line-height: 1.5;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0;
}
.studio__letter-sign {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(28px, 2.8vw, 42px);
  line-height: 1.5;
  color: var(--ink);
  margin: clamp(16px, 1.8vw, 24px) 0 0;
}
/* (§09 .studio__letter-cta retired — replaced by .section-closer
   arrow-link pattern that the rest of the site uses for section-
   to-section navigation. Spacing now handled by the .section-closer
   margins inherited from the base component.) */
@media (max-width: 760px) {
  .studio__letter {
    padding: clamp(80px, 12vw, 120px) 0 clamp(60px, 9vw, 80px);
  }
  .studio__letter-body {
    gap: clamp(16px, 3vw, 24px);
  }
  .studio__letter-body p {
    /* Sacramento needs a larger floor on mobile to stay legible. */
    font-size: clamp(22px, 6vw, 30px);
    line-height: 1.4;
  }
  .studio__letter-sign {
    font-size: clamp(28px, 8vw, 40px);
  }
}

/* =========================================================
   /projects/ index — editorial portfolio, NOT a tile grid.
   ========================================================= */
/* Full-viewport hero — mirrors .services__hero. Marble vein fills
   the screen on load (via the shared body.page-X main > section:first
   marble rule), the visitor scrolls past it to reach the cards. Flex-
   centred so the eyebrow + title + lede sit at the optical centre of
   the viewport rather than top-aligned. */
.portfolio__hero {
  min-height: 100vh;
  min-height: 100svh;
  padding: clamp(140px, 18vh, 240px) 0 clamp(48px, 6vw, 80px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.portfolio__hero .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.portfolio__title {
  font-family: var(--serif);
  font-size: clamp(56px, 8vw, 120px);
  line-height: 1.02;
  font-weight: 400;
  color: var(--ink);
  margin: 16px 0 24px;
  letter-spacing: -0.012em;
}
.portfolio__title em { font-style: italic; }
.portfolio__lede {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 700px;
  margin: 0 auto;
}

/* .portfolio__filter rules removed 2026-05-22: the filter strip was
   deleted from the /projects/ index because its "Delivered / In
   Progress" split added no value once Monte Estoril got its own
   section, and the filter links never wired to actual filtering
   behaviour. */

.portfolio__card { background: var(--bone); }
.portfolio__card--full { padding: clamp(60px, 8vw, 120px) 0; }
.portfolio__card--full + .portfolio__card--full { position: relative; }
.portfolio__card-link { display: block; overflow: hidden; }
.portfolio__card-link .ph-block { transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1); }
.portfolio__card-link:hover .ph-block { transform: scale(1.015); }

.portfolio__meta-block {
  padding-top: clamp(32px, 4vw, 56px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.portfolio__name {
  font-family: var(--serif);
  font-size: clamp(48px, 6vw, 88px);
  line-height: 1.05;
  font-weight: 400;
  color: var(--ink);
  margin: 14px 0 18px;
}
.portfolio__name--small {
  font-size: clamp(32px, 4vw, 56px);
  margin: 18px 0 12px;
}
.portfolio__name em { font-style: italic; }
.portfolio__caption {
  font-family: var(--serif);
  font-size: clamp(17px, 1.3vw, 22px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 640px;
  margin: 0 0 clamp(20px, 2.5vw, 32px);
}
.portfolio__caption--lead { font-size: clamp(20px, 1.6vw, 26px); }

.portfolio__meta {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(20px, 2.5vw, 36px);
  width: 100%;
  margin: 0 0 clamp(24px, 3vw, 40px);
  padding: 20px 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.portfolio__meta--inline { grid-template-columns: repeat(2, 1fr); }
.portfolio__meta div { display: flex; flex-direction: column; gap: 4px; }
.portfolio__meta dt {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mid);
}
.portfolio__meta dd {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--ink);
  margin: 0;
}

.portfolio__view {
  font-family: var(--serif);
  font-style: italic;
  font-size: 18px;
  color: var(--ink);
  text-decoration: none;
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
  transition: gap 0.4s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.portfolio__view span { transition: transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1); }
.portfolio__view:hover { gap: 18px; }
.portfolio__view:hover span { transform: translateX(4px); }

.portfolio__row {
  padding: clamp(60px, 8vw, 120px) 0;
  background: var(--bone);
}
/* Short centred ornament between rows — same convention as
   .section-ornament elsewhere on the site. Replaces the full-width
   hairline that was previously above each row after the first. The
   ornament sits at the top of each non-first row and uses negative
   margin to lift halfway into the row's padding-top, so it appears
   centred in the space between rows rather than tucked at the top. */
.portfolio__row + .portfolio__row::before {
  content: "";
  display: block;
  width: clamp(120px, 18vw, 220px);
  height: 1px;
  background: rgba(45, 41, 38, 0.18);
  margin: calc(-1 * clamp(30px, 4vw, 60px)) auto clamp(30px, 4vw, 60px);
}
/* Near-full-bleed portfolio rows (2026-05-24). The 2-up cards drop the
   1480px wrap cap and extend close to the viewport edges, with only
   var(--pad-x) gutters left and right. Matches the wider register of
   the home page transformation tiles and the studio showcase — each
   project photograph gets real-estate equal to its weight on the page. */
.portfolio__row .wrap.portfolio__row-grid {
  max-width: none;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}
.portfolio__row-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 96px);
}
.portfolio__row .portfolio__card { padding: 0; }

/* 2-up card uniform sizing (2026-05-22 redesign): all six cards
   now sit at equal 2-up width across three rows. To make the
   sizing actually uniform, force a single aspect on every card
   image, flex-column the card so the silver button can be pushed
   to the bottom, and align buttons across the row via margin-top:
   auto. The 16:9 aspect matches 5 of 6 bleed sources natively
   (Rosa is 3:2 and gets a gentle side-crop via object-fit cover). */
.portfolio__row--two-up .portfolio__card-link img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  display: block;
}
.portfolio__row--two-up .portfolio__card {
  display: flex;
  flex-direction: column;
}
.portfolio__row--two-up .portfolio__card .btn-silver {
  margin-top: auto;
}

.portfolio__in-progress {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--paper);
  border-top: 1px solid var(--hairline);
}
/* Near-full-bleed wrap matches the 2-up row layout above so the
   two coming-soon blocks land at the same column widths as the
   project cards. */
.portfolio__in-progress .wrap {
  max-width: none;
  padding-left: var(--pad-x);
  padding-right: var(--pad-x);
}
/* Coming-soon block: shared "— Coming soon" eyebrow as a header,
   then a 3-column row beneath — Monte Estoril | "&" | Atiba — where
   the ampersand fills the gap as a designed editorial connector
   (magazine-spread title rhythm) rather than visual silence. */
.portfolio__in-progress-inner {
  display: flex;
  flex-direction: column;
}
.portfolio__in-progress-head {
  text-align: center;
  margin-bottom: clamp(40px, 5vw, 72px);
}
.portfolio__in-progress-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: clamp(24px, 4vw, 80px);
  align-items: center;
}
.portfolio__in-progress-amp {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(72px, 11vw, 160px);
  font-weight: 300;
  line-height: 1;
  color: var(--ink);
  opacity: 0.38;
  text-align: center;
  user-select: none;
  display: block;
}
.portfolio__in-progress-text {
  padding-right: 0;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.ph-block--muted {
  background: var(--bone);
  border-color: var(--hairline-strong);
}
.portfolio__in-progress-note {
  font-family: var(--serif);
  font-size: 16px;
  color: var(--mid);
  margin-top: 16px;
}

/* ===== Curated /projects/ additions (2026-05-22) =====
   Three new sections on the /projects/ index:
   - .portfolio__why          — 3-column manifesto under the hero
   - .portfolio__role-line    — italic line above each card's H2
   - .portfolio__rooms        — asymmetric moodboard of room entry-points
   ============================================================= */

/* "Why these six" — 3-column manifesto block under the hero.
   Three stanzas (aesthetic, story, capability) each name all six
   projects in parallel construction. Reads like a magazine
   manifesto index; collapses to a vertical stack on mobile. */
.portfolio__why {
  padding: clamp(40px, 5vw, 80px) 0 clamp(48px, 5vw, 88px);
}
.portfolio__why-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(28px, 3.5vw, 56px);
}
.portfolio__why-col {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.4vw, 20px);
}
.portfolio__why-body {
  font-family: var(--serif);
  font-size: clamp(15px, 1.15vw, 18px);
  line-height: 1.55;
  color: var(--ink);
  margin: 0;
}

/* Role line — italic Cormorant line above each card's project H2.
   Names the project's role in the collection ("The view, let in.",
   "The conversion.", etc.). Sits between the lens eyebrow and the
   H2 to land the curation logic at-a-glance. */
.portfolio__role-line {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.3;
  color: var(--mid);
  margin: 8px 0 4px;
}
.portfolio__role-line--small {
  font-size: clamp(15px, 1.15vw, 18px);
}

/* Curious about a specific room? — asymmetric moodboard. The big
   portrait Bathrooms tile spans both rows on the left; two smaller
   landscape tiles (Kitchens, External) stack on the right. All three
   are data-todo placeholders until Phase 2 builds /projects/rooms/
   sub-pages. The cursor: not-allowed + aria-disabled signals
   placeholder state. */
.portfolio__rooms {
  padding: clamp(80px, 9vw, 140px) 0 clamp(40px, 5vw, 80px);
}
.portfolio__rooms-head {
  text-align: center;
  margin: 0 auto clamp(40px, 5vw, 64px);
  max-width: 720px;
}
.portfolio__rooms-title {
  font-family: var(--serif);
  font-size: clamp(36px, 4vw, 56px);
  font-weight: 300;
  line-height: 1.1;
  margin: 12px 0 16px;
  color: var(--ink);
}
.portfolio__rooms-lede {
  font-family: var(--serif);
  font-size: clamp(17px, 1.4vw, 22px);
  line-height: 1.45;
  color: var(--ink-2);
  margin: 0;
}
.portfolio__room-tiles {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  grid-template-rows: auto auto;
  gap: clamp(16px, 1.6vw, 24px);
}
.portfolio__room-tile {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bone);
  color: var(--ink);
  text-decoration: none;
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.portfolio__room-tile:hover {
  transform: translateY(-3px);
}
.portfolio__room-tile .ph-block {
  transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.portfolio__room-tile:hover .ph-block {
  transform: scale(1.015);
}
.portfolio__room-tile--feature {
  grid-column: 1;
  grid-row: 1 / span 2;
}
.portfolio__room-tile-text {
  padding: clamp(20px, 2vw, 32px) clamp(20px, 2vw, 32px) clamp(24px, 2.4vw, 36px);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.portfolio__room-tile-title {
  font-family: var(--serif);
  font-size: clamp(24px, 2.4vw, 36px);
  font-weight: 300;
  line-height: 1.1;
  margin: 4px 0 0;
  color: var(--ink);
}
.portfolio__room-tile-note {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 8px 0 0;
}
.portfolio__room-tile[aria-disabled="true"] {
  cursor: not-allowed;
}

@media (max-width: 900px) {
  .portfolio__row-grid { grid-template-columns: 1fr; gap: 48px; }
  .portfolio__meta { grid-template-columns: repeat(2, 1fr); gap: 18px; }
  .portfolio__meta--inline { grid-template-columns: 1fr; }
  .portfolio__in-progress-row { grid-template-columns: 1fr; gap: 24px; }
  .portfolio__in-progress-amp { font-size: 56px; }
  .portfolio__why-grid { grid-template-columns: 1fr; gap: 32px; }
  .portfolio__room-tiles {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
  }
  .portfolio__room-tile--feature {
    grid-column: 1;
    grid-row: auto;
  }
}

/* =========================================================
   /services/ page — atelier menu
   ========================================================= */
/* /services/ page's <main> uses class="services" — same class
   name as the HOMEPAGE's services section. The homepage rule at
   line ~2436 adds clamp(96, 12vw, 220) px padding + a bone bg,
   which on the /services/ <main> inset everything from the
   viewport edges and made the marble hero impossible to reach
   the screen edge. Reset those properties on the /services/
   <main> specifically. */
body.page-services main.services {
  padding: 0;
  background: transparent;
}

.services__hero {
  /* Full-viewport hero — marble vein fills the screen on load and
     stays put as the visitor scrolls past, same convention as
     .studio__hero and the homepage .intro. Flex-centred so short
     hero copy still sits at the optical centre of the viewport
     rather than top-aligned. */
  min-height: 100vh;
  padding: clamp(140px, 18vh, 240px) 0 clamp(48px, 6vw, 80px);
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  position: relative;
}
@media (max-width: 768px) {
  .services__hero { background-attachment: scroll; }
}
/* Centre the hero content (eyebrow, H1, lede) horizontally and as
   a typographic block — same convention as .studio__hero-inner.
   The hero section already centres the wrap with flex; this
   centres the text within the wrap. */
.services__hero .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.services__hero .services__title {
  font-family: var(--serif);
  font-size: clamp(56px, 8vw, 120px);
  line-height: 1.02;
  font-weight: 400;
  color: var(--ink);
  margin: 16px 0 24px;
  letter-spacing: -0.012em;
}
.services__hero .services__title em { font-style: italic; }
.services__hero .services__lede {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 700px;
  margin: 0 auto;
}

/* =========================================================
   /services/ chapter system. Below the hero, each service is a
   self-contained editorial spread (.services__chapter). Layout
   shape varies per chapter — split, full-bleed image, spotlight,
   announcement, adjacent pair, quiet coda — so no two adjacent
   sections share the same composition. Replaces the prior
   templated rhythm (3-col card grid → centered feature →
   alternating centered text bands) which had collapsed into a
   stock services-page pattern.
   ========================================================= */

.services__chapter {
  padding: clamp(80px, 10vw, 140px) clamp(24px, 5vw, 96px);
}

.services__chapter-inner {
  max-width: 1240px;
  margin: 0 auto;
}
.services__chapter-inner--narrow {
  max-width: 720px;
}

.services__chapter-num {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 clamp(20px, 2vw, 28px);
}
.services__chapter-num--centered { text-align: center; }

.services__chapter-title {
  font-size: clamp(40px, 4.8vw, 72px);
  margin: 12px 0 clamp(24px, 2.6vw, 36px);
  text-wrap: balance;
}
.services__chapter-title--centered { text-align: center; }
.services__chapter-title em { font-style: italic; }

.services__chapter-lede {
  font-family: var(--sans);
  font-size: var(--fs-lg);
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0 0 clamp(16px, 1.8vw, 24px);
  max-width: 52ch;
}
.services__chapter-lede--centered {
  text-align: center;
  margin-left: auto;
  margin-right: auto;
}

.services__chapter-detail {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(17px, 1.3vw, 21px);
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
  max-width: 52ch;
}

/* In-chapter CTA — used on the Hidden Work chapter and the Standards
   chapter. Sits below the lede with generous breathing room so the
   .btn-silver pill reads as a deliberate punctuation, not crammed
   into the text. The --centered modifier is used on chapters where
   the surrounding text is already centred (Turnkey-style spread,
   Standards). */
.services__chapter-cta {
  margin: clamp(28px, 3vw, 40px) 0 0;
}
.services__chapter-cta--centered {
  text-align: center;
}

/* ---- Split chapter (text + photo, side by side) ---- */
.services__chapter--split .services__chapter-inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  align-items: center;
}
/* Mobile: stack text above photo. Both columns at 50% on a 375px screen
   leave each at ~150px — text wraps unreadably and the photo collapses.
   Single column at full width brings the image back into view. */
@media (max-width: 768px) {
  .services__chapter--split .services__chapter-inner {
    grid-template-columns: 1fr;
    gap: clamp(24px, 4vw, 40px);
  }
  /* On mobile, the rotate (Kitchens) and sequence (Hidden Work) photo
     animations can leave images stuck at opacity 0 (prefers-reduced-
     motion shortens animation-duration to 0.01ms, which for the
     sequence keyframe lands on its 100% { opacity: 0 } end state).
     Drop the animation and toggle visibility manually via .is-active.
     The Kitchens chapter gets prev/next skip buttons (wired in
     js/chapter-carousel.js); Hidden Work still shows its first photo
     statically. Desktop keeps the crossfade animation. */
  .services__chapter-photo--rotate img,
  .services__chapter-photo--sequence img {
    animation: none;
    opacity: 0;
  }
  .services__chapter-photo--rotate img.is-active,
  .services__chapter-photo--rotate img:first-of-type,
  .services__chapter-photo--sequence img:first-of-type {
    opacity: 1;
  }
  /* When a specific image is marked .is-active, all non-active fade out. */
  .services__chapter-photo--rotate:has(img.is-active) img:not(.is-active) {
    opacity: 0;
  }
  /* Carousel controls overlay on the photo, bottom-centred. */
  .services__chapter-photo-controls {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 12px;
    z-index: 10;
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: clamp(16px, 3vw, 24px);
    padding: 0 12px;
  }
  .services__chapter-photo-arrow {
    width: 40px;
    height: 40px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: var(--ink);
    background: linear-gradient(
      135deg,
      rgba(255, 255, 255, 0.42) 0%,
      rgba(255, 255, 255, 0.22) 100%
    );
    backdrop-filter: blur(24px) saturate(1.25);
    -webkit-backdrop-filter: blur(24px) saturate(1.25);
    border: 1px solid rgba(255, 255, 255, 0.55);
    box-shadow:
      0 8px 24px rgba(0, 0, 0, 0.12),
      0 2px 6px rgba(0, 0, 0, 0.06),
      inset 0 1px 0 rgba(255, 255, 255, 0.7),
      inset 0 -1px 0 rgba(0, 0, 0, 0.04);
    transition: transform 0.25s ease;
  }
  .services__chapter-photo-arrow:active {
    transform: scale(0.97);
  }
  .services__chapter-photo-arrow svg {
    width: 14px;
    height: 14px;
  }
  .services__chapter-photo-arrow--prev { justify-self: start; }
  .services__chapter-photo-arrow--next { justify-self: end; }
  .services__chapter-photo-counter {
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--bone);
    margin: 0;
    padding: 6px 12px;
    border-radius: 999px;
    background: rgba(20, 17, 14, 0.55);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    text-align: center;
    white-space: nowrap;
  }
}
.services__chapter--split .services__chapter-text {
  display: flex;
  flex-direction: column;
}
.services__chapter--split.services__chapter--reverse .services__chapter-text { order: 2; }
.services__chapter--split.services__chapter--reverse .services__chapter-photo { order: 1; }

.services__chapter-photo {
  margin: 0;
  position: relative;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  overflow: hidden;
  aspect-ratio: 4 / 5;
}
.services__chapter-photo img,
.services__chapter-photo .ph-block {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  border: 0;
  aspect-ratio: auto;
}
.services__chapter-photo figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 16px 20px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--bone);
  background: linear-gradient(180deg, rgba(20, 17, 14, 0) 0%, rgba(20, 17, 14, 0.55) 100%);
}

/* Stacked variant — dormant on /services/ as of 2026-05-24 (the
   Kitchens chapter that used it switched to the --rotate variant).
   Kept for any future chapter that needs a 2:3 diptych. */
.services__chapter-photo--stack {
  aspect-ratio: auto;
  background: transparent;
  border: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(12px, 1.4vw, 20px);
  overflow: visible;
}
.services__chapter-photo--stack img,
.services__chapter-photo--stack .ph-block {
  position: static;
  inset: auto;
  aspect-ratio: 2 / 3;
  object-fit: cover;
  border: 1px solid var(--hairline);
  width: 100%;
  height: 100%;
}

/* Rotate variant — two photos in one slot crossfading every ~4
   seconds. The Kitchens & bathrooms chapter uses this so both rooms
   get screen time without splitting the figure into a cramped diptych
   or breaking the page's layout unity (chapter still reads as a
   standard split-reverse). Aspect 4:5 matches the Signature
   commission chapter directly above. */
.services__chapter-photo--rotate {
  aspect-ratio: 4 / 5;
}
/* Carousel controls hidden by default — only shown on mobile via the
   ≤768px @media block above. Desktop keeps the CSS crossfade animation. */
.services__chapter-photo-controls {
  display: none;
}
.services__chapter-photo--rotate img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: chapterPhotoFade 8s infinite;
}
.services__chapter-photo--rotate img:nth-child(2) {
  animation-delay: -4s;
}
@keyframes chapterPhotoFade {
  0%, 45% { opacity: 1; }
  55%, 95% { opacity: 0; }
  100% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .services__chapter-photo--rotate img {
    animation: none;
  }
  .services__chapter-photo--rotate img:nth-child(2) {
    display: none;
  }
}

/* Sequence variant — 7-photo crossfade telling a wall's evolution
   (before → demolition → framing → wiring → drywall → skim → done).
   Each photo gets ~4 seconds with ~0.5s crossfade between, for a
   28-second full cycle. The Hidden Work chapter uses this to make
   the chapter's argument ("walls moved, beams added, stamped")
   visible as a process. Aspect 4:5 matches the other split chapters. */
.services__chapter-photo--sequence {
  aspect-ratio: 4 / 5;
}
.services__chapter-photo--sequence img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  animation: chapterPhotoSequence 28s infinite;
}
/* Always-visible fallback for the first photo in each rotate / sequence
   chapter. Guards against the sitewide prefers-reduced-motion rule
   shortening the animation to 0.01ms and leaving the sequence keyframe
   stuck at its 100% { opacity: 0 } end state. Higher specificity than
   the base img rule, so it survives both with and without animation. */
.services__chapter-photo--rotate img:first-of-type,
.services__chapter-photo--sequence img:first-of-type {
  opacity: 1;
}
/* Hard override for reduced-motion: disable the animation entirely
   (sitewide *,*::before,*::after !important rule collapses the
   animation-duration to 0.01ms, which lands the sequence at opacity 0).
   With animation: none !important here, the base opacity above wins. */
@media (prefers-reduced-motion: reduce) {
  .services__chapter-photo--rotate img,
  .services__chapter-photo--sequence img {
    animation: none !important;
    opacity: 0;
  }
  .services__chapter-photo--rotate img:first-of-type,
  .services__chapter-photo--sequence img:first-of-type {
    opacity: 1;
  }
}
.services__chapter-photo--sequence img:nth-child(1) { animation-delay: 0s; }
.services__chapter-photo--sequence img:nth-child(2) { animation-delay: 4s; }
.services__chapter-photo--sequence img:nth-child(3) { animation-delay: 8s; }
.services__chapter-photo--sequence img:nth-child(4) { animation-delay: 12s; }
.services__chapter-photo--sequence img:nth-child(5) { animation-delay: 16s; }
.services__chapter-photo--sequence img:nth-child(6) { animation-delay: 20s; }
.services__chapter-photo--sequence img:nth-child(7) { animation-delay: 24s; }
@keyframes chapterPhotoSequence {
  /* Crossfade — each photo holds opacity 1 until its successor begins
     fading in at 14.3% (t=4s, matching the 4-second stagger between
     animation-delays). Old keyframe ended the fade-out at 14% (t=3.92s),
     leaving a ~0.64s "blank" gap before the next image had reached
     opacity 1. Now the fade-out spans 14.3-16.3% (t=4-4.56s), which
     overlaps exactly with the next image's 0-2% fade-in window.
     No blank frame between transitions. */
  0%     { opacity: 0; }
  2%     { opacity: 1; }
  14.3%  { opacity: 1; }
  16.3%  { opacity: 0; }
  100%   { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .services__chapter-photo--sequence img {
    animation: none;
    opacity: 0;
  }
  .services__chapter-photo--sequence img:nth-child(1) {
    opacity: 1;
  }
  .services__chapter-photo--sequence img:nth-child(n+2) {
    display: none;
  }
}

/* ---- Bleed chapter — dormant on /services/ post-2026-05-24 (no
   chapter uses it after the Turnkey conversion to spread layout).
   Rules kept in place in case a future chapter needs full-bleed. ---- */
.services__chapter--bleed {
  padding-left: 0;
  padding-right: 0;
}
.services__chapter--bleed .services__chapter-inner {
  padding-left: clamp(24px, 5vw, 96px);
  padding-right: clamp(24px, 5vw, 96px);
}
.services__chapter-bleed-photo {
  margin: clamp(48px, 5vw, 72px) 0 0;
}

/* ---- Spread chapter (centred text + contained landscape photo
   below). For chapters with native landscape photography that
   doesn't crop well to portrait. Photo sits inside the chapter
   container with cream margins on all sides — distinct from the
   split chapters (side-by-side) and the bleed chapters (full-
   viewport-width). ---- */
.services__chapter--spread .services__chapter-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(40px, 5vw, 72px);
  max-width: 1240px;
}
.services__chapter-text--centred {
  text-align: center;
  max-width: 720px;
}
.services__chapter-photo--landscape {
  width: 100%;
  /* Matches the .services__chapter-inner max-width below, so the
     landscape photo here lines up at the same horizontal width as
     the split chapters that follow — same column edges, different
     layout. */
  max-width: 1240px;
  margin: 0;
  position: relative;
  overflow: hidden;
  background: var(--bone-2);
  border: 1px solid var(--hairline);
  /* Override the base .services__chapter-photo aspect-ratio: 4/5
     (which forces a portrait crop) — landscape variant lets the
     image's intrinsic dimensions drive the container instead. */
  aspect-ratio: auto;
}
.services__chapter-photo--landscape img {
  /* Override the base rule that absolutely-positions the img and
     forces object-fit: cover (which crops the 16:9 photo to fit a
     4:5 container). Reset to natural flow so the photo renders at
     its true ratio inside the container. */
  position: static;
  inset: auto;
  width: 100%;
  height: auto;
  object-fit: initial;
  display: block;
  border: 0;
  aspect-ratio: auto;
}
.services__chapter-bleed-photo img {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  display: block;
}

/* ---- Spotlight chapter (centered material moment) ---- */
.services__chapter--spotlight .services__chapter-header {
  text-align: center;
  margin: 0 auto clamp(40px, 5vw, 64px);
}
.services__chapter-spotlight-photo {
  margin: 0 auto clamp(36px, 4vw, 56px);
  max-width: 900px;
}
.services__chapter-spotlight-photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}
.services__chapter-spotlight-photo figcaption {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--mid);
  margin-top: 14px;
  text-align: center;
  font-style: italic;
}

/* ---- Announcement chapter (Maya's Care) ---- Differentiated via
   hairline rules (top + bottom) rather than a background shift,
   so the chapter respects the page-level blanket-transparent
   override and matches the homepage's .services__sister
   convention. */
.services__chapter--announcement .services__chapter-inner {
  text-align: center;
  /* border-top + border-bottom removed 2026-05-24 — the surrounding
     .section-ornament hairlines already separate this chapter from
     its neighbours; the internal borders were doubling up the dividers
     visually around the Maya's Care announcement. */
  padding-top: clamp(48px, 5vw, 72px);
  padding-bottom: clamp(48px, 5vw, 72px);
}
.services__chapter-status {
  margin: clamp(20px, 2.2vw, 28px) 0 0;
  font-family: var(--sans);
  font-size: var(--fs-base);
  color: var(--ink-2);
}
.services__chapter-status em {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(17px, 1.2vw, 19px);
  color: var(--ink);
}
.services__chapter-status-link {
  margin-left: 14px;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: color 200ms ease;
}
.services__chapter-status-link:hover {
  color: var(--ink-2);
}

/* ---- Adjacent chapter (§09 + §10 as paired before/after) ---- */
.services__chapter--adjacent .services__chapter-header {
  text-align: center;
  margin: 0 auto clamp(40px, 5vw, 64px);
}
.services__adjacent-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 4vw, 72px);
  max-width: 1100px;
  margin: 0 auto;
}
.services__adjacent-card {
  display: flex;
  flex-direction: column;
  padding: clamp(32px, 3vw, 48px) 0 0;
  border-top: 1px solid var(--hairline);
}
.services__adjacent-card .services__chapter-num {
  margin-bottom: 18px;
}
.services__adjacent-title {
  font-family: var(--serif);
  font-size: clamp(28px, 2.4vw, 34px);
  font-weight: 400;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin: 0 0 clamp(18px, 2vw, 24px);
  line-height: 1.15;
}
.services__adjacent-body {
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: 1.6;
  color: var(--ink-2);
  margin: 0 0 18px;
  max-width: 46ch;
}
.services__adjacent-meta {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(15px, 1.05vw, 17px);
  line-height: 1.5;
  color: var(--mid);
  /* margin-top: auto pushes the italic meta to the bottom of the
     flex-column card. Since the two cards stretch to equal height
     via the grid's default align-items: stretch, both meta lines
     land at the same vertical position regardless of how long
     each body paragraph is. */
  margin: auto 0 0;
  max-width: 46ch;
}

/* ---- Quiet chapter (closer coda) ---- */
.services__chapter--quiet {
  padding: clamp(60px, 7vw, 96px) clamp(24px, 5vw, 96px) clamp(40px, 5vw, 64px);
}
.services__quiet-line {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(17px, 1.3vw, 21px);
  line-height: 1.6;
  color: var(--ink-2);
  text-align: center;
  margin: 0 0 clamp(24px, 2.6vw, 36px);
}
.services__quiet-line:last-of-type {
  margin-bottom: clamp(40px, 4vw, 56px);
}

/* ---- Mobile breakpoints ---- */
@media (max-width: 900px) {
  .services__chapter--split .services__chapter-inner {
    grid-template-columns: 1fr;
    gap: clamp(32px, 6vw, 48px);
  }
  /* Adjacent (Pre-Purchase / Aftercare) cards need real breathing room
     between them on mobile — they read as two distinct services, not
     a tight pair. Bumped gap from 32px to clamp(56-96px). */
  .services__adjacent-grid {
    grid-template-columns: 1fr;
    gap: clamp(56px, 12vw, 96px);
  }
  /* Kitchens & Bathrooms is a --reverse chapter (photo first in HTML
     so it sits LEFT on desktop). On mobile the user wants text first,
     then photo — eyebrow + headline + body lead, image confirms. */
  .services__chapter--split.services__chapter--reverse .services__chapter-text {
    order: 1;
  }
  .services__chapter--split.services__chapter--reverse .services__chapter-photo {
    order: 2;
  }
  /* On mobile, the full-width 1px border-top above each adjacent card
     reads as a page-divider band rather than a quiet card delimiter.
     Replace with the same delicate centred hairline used as the
     section-ornament elsewhere — small, soft, deliberate. */
  .services__adjacent-card {
    border-top: 0;
    position: relative;
    padding-top: clamp(32px, 4vw, 48px);
  }
  .services__adjacent-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: clamp(80px, 18vw, 140px);
    height: 1px;
    background: rgba(45, 41, 38, 0.18);
    pointer-events: none;
  }
  .services__chapter--split.services__chapter--reverse .services__chapter-text { order: 0; }
  .services__chapter--split.services__chapter--reverse .services__chapter-photo { order: 0; }
  .services__chapter-photo {
    /* Fallback for iOS < 15: padding hack */
    padding-top: 125%; /* 5/4 = 1.25 */
    height: 0;
    max-width: 520px;
    margin: 0 auto;
    width: 100%;
  }
  @supports (aspect-ratio: 4/5) {
    .services__chapter-photo {
      padding-top: 0;
      height: auto;
      aspect-ratio: 4 / 5;
    }
  }
  .services__chapter-photo--stack { aspect-ratio: auto; padding-top: 0; height: auto; }
  /* Turnkey's landscape variant must keep its native aspect (it's a
     16:9 photo). The mobile rule above was forcing it into 4/5 portrait
     which cropped the photo on the sides and looked broken. */
  .services__chapter-photo--landscape {
    aspect-ratio: auto;
    padding-top: 0;
    height: auto;
    max-width: 100%;
  }
  .services__chapter-photo--landscape img {
    position: static;
    width: 100%;
    height: auto;
    object-fit: initial;
  }
  .services__chapter-bleed-photo img { aspect-ratio: 4 / 3; }
}
@media (max-width: 600px) {
  .services__chapter-title { font-size: clamp(32px, 9vw, 48px); }
  .services__adjacent-card { padding-top: 24px; }
}

/* =========================================================
   /process/ page — alternating editorial spreads
   ========================================================= */
.process__hero {
  padding: clamp(120px, 14vw, 200px) 0 clamp(48px, 6vw, 80px);
  background: var(--bone);
}
.process__hero .process__title {
  font-family: var(--serif);
  font-size: clamp(56px, 8vw, 120px);
  line-height: 1.02;
  font-weight: 400;
  color: var(--ink);
  margin: 16px 0 24px;
}
.process__hero .process__title em { font-style: italic; }
.process__lede {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 720px;
  margin: 0;
}

.process__timeline {
  padding: clamp(40px, 5vw, 80px) 0;
  background: var(--bone);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.process__timeline-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 4vw, 64px);
}
.process__timeline-item {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-right: clamp(16px, 2vw, 32px);
  border-right: 1px solid var(--hairline);
}
.process__timeline-item:last-child {
  border-right: none;
  padding-right: 0;
}
.process__timeline-num {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.process__timeline-name {
  font-family: var(--serif);
  font-size: clamp(22px, 2vw, 30px);
  line-height: 1.1;
  color: var(--ink);
  font-weight: 400;
  margin: 0;
}
.process__timeline-duration {
  font-family: var(--serif);
  font-style: italic;
  font-size: 16px;
  color: var(--ink-2);
  margin: 0;
}

/* Phase spread — alternating image L / image R via .phase--mirror. */
.phase {
  padding: clamp(80px, 10vw, 160px) 0;
  background: var(--bone);
}
.phase + .phase { position: relative; }
.phase__grid {
  display: grid;
  grid-template-columns: 6fr 6fr;
  gap: clamp(40px, 6vw, 96px);
  align-items: center;
}
.phase--mirror .phase__grid > .phase__text  { order: 1; }
.phase--mirror .phase__grid > .phase__image { order: 2; }

.phase__image { margin: 0; }
.phase__image figcaption {
  font-family: var(--mono);
  font-style: normal;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--mid);
  margin-top: 12px;
  text-align: left;
}
.phase__num {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 8px;
}
.phase__name {
  font-family: var(--serif);
  font-size: clamp(48px, 5.5vw, 88px);
  line-height: 1.05;
  font-weight: 400;
  color: var(--ink);
  margin: 12px 0 18px;
}
.phase__name em { font-style: italic; }
.phase__lede {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 clamp(24px, 3vw, 36px);
}
.phase__text p {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.75;
  color: var(--ink-2);
  margin: 0 0 18px;
}
.phase__steps {
  font-family: var(--sans) !important;
  font-size: 11px !important;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mid) !important;
  padding: 18px 0 0;
  border-top: 1px solid var(--hairline);
  margin: 20px 0 0 !important;
  line-height: 1.8 !important;
}

.process__quote-band {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--paper);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

.process__close { padding: clamp(80px, 10vw, 140px) 0; background: var(--bone); }
.process__close-body {
  font-family: var(--serif);
  font-size: clamp(20px, 1.7vw, 26px);
  line-height: 1.55;
  color: var(--ink);
  text-align: center;
  margin: 24px 0 0;
}

@media (max-width: 900px) {
  .process__timeline-grid { grid-template-columns: repeat(2, 1fr); gap: 24px; }
  .process__timeline-item { border-right: none; padding-right: 0; }
  .phase__grid { grid-template-columns: 1fr; gap: 32px; }
  .phase--mirror .phase__grid > .phase__text  { order: 2; }
  .phase--mirror .phase__grid > .phase__image { order: 1; }
}

/* =========================================================
   /local/ page — geographic authority
   ========================================================= */
.local__hero {
  /* Top padding trimmed (was clamp 120-200 → now 80-120) since the
     van photo banner now sits at the top of the section and needs
     less head-clearance than the previous text-only hero. */
  padding: clamp(80px, 10vw, 120px) 0 clamp(48px, 6vw, 80px);
  background: var(--bone);
}
/* Hero banner — full-width van photo above the h1. Aspect 21:9
   gives a cinematic banner feel rather than a square hero card.
   Moved from the homepage Cascais section (.cascais__atmosphere),
   where it was creating a stacked-landscape redundancy with the
   map below it. */
.local__hero-image {
  margin: 0 0 clamp(40px, 5vw, 64px);
  padding: 0;
  width: 100%;
}
.local__hero-image img {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  display: block;
}
.local__title {
  font-family: var(--serif);
  font-size: clamp(56px, 8vw, 120px);
  line-height: 1.02;
  font-weight: 400;
  color: var(--ink);
  margin: 16px 0 24px;
}
.local__title em { font-style: italic; }
.local__lede {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 720px;
  margin: 0;
}
.local__h2 {
  font-family: var(--serif);
  font-size: clamp(36px, 4vw, 56px);
  line-height: 1.1;
  color: var(--ink);
  font-weight: 400;
  margin: 14px 0 28px;
}
.local__h2--centered { text-align: center; }
.local__h2 em { font-style: italic; }

.local__map { padding: clamp(40px, 6vw, 80px) 0 clamp(60px, 8vw, 100px); background: var(--bone); }
.local__map-figure { margin: 0; }
.local__map-figure figcaption {
  font-family: var(--mono);
  font-style: normal;
  font-size: 13px;
  letter-spacing: 0.02em;
  color: var(--mid);
  margin-top: 16px;
  text-align: center;
}
.ph-block--map {
  aspect-ratio: 16 / 8;
  background: var(--paper);
}

.local__villages {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--bone);
  border-top: 1px solid var(--hairline);
}
.villages-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(32px, 4vw, 56px) clamp(28px, 3vw, 40px);
  margin-top: clamp(40px, 5vw, 64px);
}
.village { display: flex; flex-direction: column; }
.village h3 {
  font-family: var(--serif);
  font-size: clamp(24px, 2.4vw, 36px);
  line-height: 1.1;
  font-weight: 400;
  color: var(--ink);
  margin: 18px 0 8px;
}
.village h3 em { font-style: italic; }
.village__caption {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 8px;
}
.village__detail {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.08em;
  color: var(--mid);
  line-height: 1.7;
  margin: 0;
}

.local__detail { padding: clamp(80px, 10vw, 140px) 0; }
.local__detail--materials { background: var(--paper); position: relative; }
.local__detail--light     { background: var(--bone); }
.local__detail--rules     { background: var(--paper); position: relative; }
.local__detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}
.local__detail-h3 {
  font-family: var(--serif);
  font-size: clamp(28px, 2.6vw, 40px);
  line-height: 1.15;
  font-weight: 400;
  color: var(--ink);
  margin: 14px 0 16px;
}
.local__detail-h3--centered { text-align: center; }
.local__detail-h3 em { font-style: italic; }
.local__detail p {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.75;
  color: var(--ink-2);
  margin: 0 0 16px;
}
.local__light-body {
  font-family: var(--serif);
  font-size: clamp(19px, 1.6vw, 23px) !important;
  line-height: 1.7 !important;
  color: var(--ink-2);
  text-align: center;
  margin-top: 16px;
}

.local__quote-band {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--bone);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

.local__bench { padding: clamp(80px, 10vw, 120px) 0; background: var(--bone); }
.local__bench-body {
  font-family: var(--serif);
  font-size: clamp(20px, 1.7vw, 26px);
  line-height: 1.55;
  color: var(--ink);
  text-align: center;
  margin: 24px 0 16px;
}
.local__bench-date {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mid);
  text-align: center;
  margin: 0;
}

@media (max-width: 900px) {
  .villages-grid     { grid-template-columns: 1fr; gap: 32px; }
  .local__detail-grid { grid-template-columns: 1fr; gap: 32px; }
}

/* =========================================================
   /journal/ — editorial archive scaffold
   ========================================================= */
.journal__hero {
  min-height: 100vh;
  min-height: 100svh;
  padding: clamp(140px, 18vh, 240px) 0 clamp(48px, 6vw, 80px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.journal__hero .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.journal__title {
  font-family: var(--serif);
  font-size: clamp(56px, 8vw, 120px);
  line-height: 1.02;
  font-weight: 400;
  color: var(--ink);
  margin: 16px 0 24px;
}
.journal__title em { font-style: italic; }
.journal__lede {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 24px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 720px;
  margin: 0;
}
.journal__h2 {
  font-family: var(--serif);
  font-size: clamp(36px, 4vw, 56px);
  line-height: 1.1;
  color: var(--ink);
  font-weight: 400;
  margin: 14px 0 clamp(40px, 5vw, 64px);
}
.journal__h2 em { font-style: italic; }

.journal__filter {
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  background: var(--bone);
}
.journal__filter-inner {
  display: flex;
  gap: clamp(20px, 3vw, 48px);
  padding: 20px 0;
  flex-wrap: wrap;
}
.journal__filter-link {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mid);
  text-decoration: none;
  transition: color 0.3s ease;
}
.journal__filter-link:hover,
.journal__filter-link.is-active { color: var(--ink); }

/* Featured spread */
/* Featured piece — stacked editorial cover. Massive native-aspect hero
   image at --container width, then a centered ~52ch body block below.
   Per-piece magazine front (à la Cereal/Kinfolk) rather than a blog row. */
.journal__featured { padding: clamp(60px, 8vw, 120px) 0; background: var(--bone); }
.journal__featured-image {
  display: block;
  overflow: hidden;
  text-decoration: none;
  margin: 0 auto;
  width: 100%;
  max-width: 680px;
  padding: 0 clamp(20px, 3vw, 48px);
  box-sizing: border-box;
}
.journal__featured-image img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.journal__featured-image:hover img { transform: scale(1.015); }
.journal__featured-text {
  max-width: 52ch;
  margin: clamp(40px, 5vw, 72px) auto 0;
  padding: 0 clamp(20px, 3vw, 48px);
  text-align: center;
}
.journal__featured-cta {
  margin-top: clamp(8px, 1vw, 14px);
}

/* Archive grid — activates when piece #2 publishes (see HTML scaffold
   in /journal/index.html). Auto-fill grid that handles 1, 2, 4, 6+
   cards gracefully. Native aspect ratio on images (per site convention). */
.journal__archive {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--bone);
  border-top: 1px solid var(--hairline);
}
.journal__archive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  gap: clamp(40px, 5vw, 72px);
  margin-top: clamp(32px, 4vw, 56px);
}
.journal__archive-card {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.4vw, 20px);
}
.journal__archive-card-image {
  display: block;
  overflow: hidden;
  text-decoration: none;
}
.journal__archive-card-image img {
  width: 100%;
  height: auto;
  display: block;
  transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.journal__archive-card-image:hover img { transform: scale(1.015); }
.journal__archive-card-title {
  font-family: var(--serif);
  font-size: clamp(22px, 2vw, 28px);
  line-height: 1.2;
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
.journal__archive-card-meta {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}
.journal__archive-card-cta {
  align-self: flex-start;
  margin-top: clamp(4px, 0.6vw, 8px);
}
.journal__featured-title {
  font-family: var(--serif);
  font-size: clamp(32px, 3.6vw, 52px);
  line-height: 1.1;
  font-weight: 400;
  color: var(--ink);
  margin: 14px 0 18px;
}
.journal__featured-title em { font-style: italic; }
.journal__featured-dek {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 18px;
}
.journal__featured-meta {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mid);
  padding: 14px 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  margin: 0 0 20px;
}
.journal__featured-pull {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink-2);
  margin: 0 0 24px;
}

/* Asymmetric index grid */
.journal__index {
  padding: clamp(80px, 10vw, 140px) 0;
  background: var(--bone);
  border-top: 1px solid var(--hairline);
}
.journal-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(36px, 4vw, 56px) clamp(28px, 3vw, 40px);
}
.journal-card { display: flex; flex-direction: column; }
.journal-card--large  { grid-column: span 8; }
.journal-card--medium { grid-column: span 6; }
.journal-card--small  { grid-column: span 4; }
.journal-card__image {
  display: block;
  overflow: hidden;
  text-decoration: none;
}
.journal-card__image .ph-block {
  transition: transform 0.7s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.journal-card__image:hover .ph-block { transform: scale(1.015); }
.journal-card .eyebrow { margin-top: 18px; }
.journal-card__title {
  font-family: var(--serif);
  font-size: clamp(22px, 2.2vw, 32px);
  line-height: 1.2;
  font-weight: 400;
  color: var(--ink);
  margin: 8px 0 10px;
}
.journal-card--large .journal-card__title {
  font-size: clamp(28px, 2.8vw, 40px);
}
.journal-card__title em { font-style: italic; }
.journal-card__dek {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  line-height: 1.55;
  color: var(--ink-2);
  margin: 0 0 12px;
}
.journal-card__meta {
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0;
}

.journal__cadence {
  padding: clamp(60px, 8vw, 100px) 0;
  background: var(--paper);
  border-top: 1px solid var(--hairline);
}
.journal__cadence-body {
  font-family: var(--serif);
  font-size: clamp(18px, 1.5vw, 22px);
  line-height: 1.6;
  color: var(--ink-2);
  text-align: center;
  margin: 24px 0 0;
}

/* Article shell — used by /journal/[slug]/ stubs until each
   essay ships. */
.article { padding: clamp(120px, 14vw, 200px) 0; background: var(--bone); }
/* Widened article body — 720px (.wrap--narrow default) felt cramped on
   /journal/[slug]/. 960px gives the title/dek/byline and the hero image
   real editorial presence. Body prose below is constrained separately so
   reading line length stays sensible. */
.article .wrap--narrow {
  max-width: 960px;
}
.article__title {
  font-family: var(--serif);
  font-size: clamp(40px, 5vw, 72px);
  line-height: 1.05;
  font-weight: 400;
  color: var(--ink);
  margin: 20px 0 24px;
}
.article__title em { font-style: italic; }
.article__dek {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.7vw, 26px);
  line-height: 1.5;
  color: var(--ink-2);
  margin: 0 0 32px;
}
.article__coming {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.7;
  color: var(--mid);
  margin: 48px 0;
  padding: 24px;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  text-align: center;
}
.article__back {
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
  color: var(--ink);
  text-decoration: none;
}
.article__back:hover { color: var(--ink-2); }
.article__byline {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.6;
  margin: 0 0 clamp(40px, 5vw, 64px);
}
/* Hero image sits within the 960px article wrap — no break-out, so it
   reads in line with the title and body rather than as a full-bleed plate. */
.article__hero-image {
  margin: 0 0 clamp(40px, 5vw, 64px);
  overflow: hidden;
}
.article__hero-image img {
  width: 100%;
  height: auto;
  display: block;
}
/* Body prose stays at ~800px max for a readable line length (~80-90
   chars at 17-19px serif). The wrap above can be wider, but paragraphs
   stay in this narrower column, centered. */
.article__prose {
  max-width: 800px;
  margin: 0 auto clamp(56px, 7vw, 96px);
}
.article__prose p {
  font-family: var(--serif);
  font-size: clamp(17px, 1.2vw, 19px);
  line-height: 1.75;
  margin: 0 0 clamp(20px, 1.8vw, 28px);
  color: var(--ink);
}
.article__prose h2 {
  font-family: var(--serif);
  font-size: clamp(28px, 2.8vw, 40px);
  line-height: 1.2;
  font-weight: 400;
  color: var(--ink);
  margin: clamp(56px, 7vw, 96px) 0 clamp(20px, 1.8vw, 28px);
}
.article__prose h3 {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(22px, 2vw, 28px);
  line-height: 1.25;
  font-weight: 400;
  color: var(--ink);
  margin: clamp(32px, 4vw, 56px) 0 clamp(14px, 1.4vw, 22px);
}
.article__prose ul {
  margin: 0 0 clamp(20px, 1.8vw, 28px);
  padding-left: clamp(20px, 2vw, 28px);
}
.article__prose ul li {
  font-family: var(--serif);
  font-size: clamp(17px, 1.2vw, 19px);
  line-height: 1.7;
  margin: 0 0 clamp(10px, 1.1vw, 14px);
  color: var(--ink);
}
.article__prose strong {
  font-weight: 500;
  color: var(--ink);
}
.article__prose em { font-style: italic; }
.article__prose blockquote {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.7vw, 24px);
  line-height: 1.5;
  color: var(--ink-2);
  margin: clamp(32px, 4vw, 52px) 0;
  padding: clamp(18px, 2.4vw, 32px) clamp(22px, 3vw, 40px);
  border-left: 2px solid rgba(45, 41, 38, 0.30);
  background: rgba(45, 41, 38, 0.03);
}

/* ============ /privacy/ and /terms/ — legal pages ============
   Marble-vein hero band at the top (site-DNA texture, same asset as the
   footer), big editorial title + italic subtext. Then a feathered
   transition into a wider cream article body for the legal copy. */
.legal-hero {
  position: relative;
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  padding: clamp(160px, 20vw, 240px) 0 clamp(96px, 12vw, 160px);
  text-align: center;
}
.legal-hero::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(48px, 6vw, 96px);
  background: linear-gradient(to bottom, rgba(244, 239, 230, 0), var(--bone));
  pointer-events: none;
}
.legal-hero__eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.6;
  margin: 0 0 clamp(16px, 1.8vw, 28px);
}
.legal-hero__title {
  font-family: var(--serif);
  font-size: clamp(56px, 9vw, 132px);
  line-height: 1.0;
  font-weight: 300;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin: 0 0 clamp(20px, 2.4vw, 36px);
}
.legal-hero__title em { font-style: italic; }
.legal-hero__subtext {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(18px, 1.65vw, 24px);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 56ch;
  margin: 0 auto;
}
/* "Last updated" stamp under the legal-hero subtext — top-of-page
   freshness signal so visitors don't have to scroll to the foot of
   the page to find the effective date. Mono, small caps, ink-3. */
.legal-hero__updated {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3, var(--mid));
  margin: clamp(20px, 2.5vw, 32px) auto 0;
  text-align: center;
}
.legal-hero__updated strong {
  font-weight: 500;
  color: var(--ink);
}

.legal__article {
  padding: clamp(40px, 6vw, 80px) 0 clamp(120px, 14vw, 200px);
  background: var(--bone);
}
.legal__article .wrap {
  max-width: 960px;
}
.legal__article h2 {
  font-family: var(--serif);
  font-size: clamp(28px, 2.8vw, 40px);
  line-height: 1.2;
  font-weight: 400;
  color: var(--ink);
  margin: clamp(56px, 7vw, 96px) 0 clamp(20px, 1.8vw, 28px);
}
.legal__article h2:first-of-type { margin-top: clamp(24px, 3vw, 40px); }
.legal__article p {
  font-family: var(--serif);
  font-size: clamp(17px, 1.2vw, 19px);
  line-height: 1.75;
  margin: 0 0 clamp(20px, 1.8vw, 28px);
  color: var(--ink);
}
.legal__article ul {
  margin: 0 0 clamp(20px, 1.8vw, 28px);
  padding-left: clamp(20px, 2vw, 28px);
}
.legal__article ul li {
  font-family: var(--serif);
  font-size: clamp(17px, 1.2vw, 19px);
  line-height: 1.7;
  margin: 0 0 clamp(10px, 1.1vw, 14px);
  color: var(--ink);
}
.legal__article a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 200ms ease;
}
.legal__article a:hover { color: var(--ink-2); }
.legal__article .article__meta {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.55;
  margin: clamp(64px, 8vw, 112px) 0 clamp(20px, 2vw, 28px);
  padding-top: clamp(24px, 3vw, 40px);
  border-top: 1px solid var(--hairline);
}
.legal__article .article__meta em { font-style: normal; }
.legal__article .article__back {
  display: inline-block;
  margin-top: clamp(12px, 1.4vw, 20px);
}

@media (max-width: 900px) {
  .journal__featured-grid { grid-template-columns: 1fr; gap: 32px; }
  .journal-grid { grid-template-columns: 1fr; gap: 40px; }
  .journal-card--large,
  .journal-card--medium,
  .journal-card--small { grid-column: span 1; }
}

/* /contact/ page */
.contact-page__hero {
  min-height: 100vh;
  min-height: 100svh;
  padding: clamp(140px, 18vh, 240px) 0 clamp(48px, 6vw, 80px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.contact-page__hero .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.contact-page__title { font-family: var(--serif); font-size: clamp(48px, 7vw, 96px); line-height: 1.05; font-weight: 400; color: var(--ink); margin: 16px 0 24px; }
.contact-page__title em { font-style: italic; }
.contact-page__lede { font-family: var(--serif); font-style: italic; font-size: clamp(18px, 1.5vw, 24px); line-height: 1.55; color: var(--ink-2); max-width: 720px; }
.contact-page__h2 { font-family: var(--serif); font-size: clamp(36px, 4vw, 56px); line-height: 1.1; color: var(--ink); font-weight: 400; margin: 14px 0 28px; }
.contact-page__h2--centered { text-align: center; }
.contact-page__h2 em { font-style: italic; }

/* Form section */
.contact-page__form-section { padding: clamp(60px, 8vw, 120px) 0; background: var(--bone); position: relative; }
.contact-page__form-grid { display: grid; grid-template-columns: 5fr 7fr; gap: clamp(48px, 6vw, 96px); align-items: start; }

.contact-page__aside-block { padding-bottom: clamp(28px, 3vw, 48px); margin-bottom: clamp(28px, 3vw, 48px); border-bottom: 1px solid var(--hairline); }
.contact-page__aside-block:last-child { border-bottom: none; margin-bottom: 0; }
.contact-page__direct { display: flex; flex-direction: column; gap: 14px; margin: 18px 0 0; padding: 0; }
.contact-page__direct div { display: flex; flex-direction: column; gap: 4px; }
.contact-page__direct dt { font-family: var(--sans); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--mid); }
.contact-page__direct dd { font-family: var(--serif); font-size: 17px; color: var(--ink); margin: 0; }
.contact-page__direct a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--hairline); transition: border-color 0.3s ease; }
.contact-page__direct a:hover { border-bottom-color: var(--ink); }
.contact-page__guide { font-family: var(--serif); font-size: 16px; line-height: 1.7; color: var(--ink-2); margin-top: 16px; }

/* Form */
.contact-page__form { display: flex; flex-direction: column; gap: clamp(24px, 3vw, 36px); }
.contact-page__form-header {
  margin: 0 0 clamp(8px, 1vw, 14px);
}
.contact-page__form-h2 {
  margin: 12px 0 0;
}
.contact-page__honeypot { position: absolute; left: -9999px; }
.contact-page__field { display: flex; flex-direction: column; gap: 8px; }
.contact-page__field label { font-family: var(--serif); font-size: 14px; color: var(--ink-2); }
.contact-page__field-opt { font-family: var(--serif); font-style: italic; color: var(--mid); margin-left: 6px; }
.contact-page__field input,
.contact-page__field select,
.contact-page__field textarea {
  font-family: var(--serif); font-size: 17px; color: var(--ink);
  background: transparent; border: none; border-bottom: 1px solid var(--hairline-strong);
  padding: 8px 0; outline: none; transition: border-color 0.3s ease;
  border-radius: 0;
}
.contact-page__field input:focus,
.contact-page__field select:focus,
.contact-page__field textarea:focus { border-bottom-color: var(--ink); }
.contact-page__field textarea { resize: vertical; min-height: 140px; }
.contact-page__field select { appearance: none; background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' stroke='%23999' fill='none' stroke-width='1'/></svg>"); background-repeat: no-repeat; background-position: right 4px center; padding-right: 24px; }

/* Defensive: prevent iOS Safari from auto-zooming when a form field is
   tapped. Any input/select/textarea with font-size < 16px triggers the
   zoom. The contact form is already at 17px, but this protects any
   future forms (search, newsletter, sub-page contact, etc.). */
@media (max-width: 768px) {
  input,
  select,
  textarea {
    font-size: 16px !important;
  }
}

.contact-page__form .contact__submit { align-self: flex-start; margin-top: 12px; }
.contact-page__form-note { font-family: var(--serif); font-size: 14px; color: var(--mid); margin-top: 12px; }

/* FAQ */
.contact-page__faq { padding: clamp(80px, 10vw, 140px) 0; background: var(--paper); position: relative; }
.faq-list { list-style: none; padding: 0; margin: clamp(40px, 5vw, 64px) 0 0; display: flex; flex-direction: column; gap: 0; }
/* Single-column accordion across all viewports. Each <details> item
   collapses to its question by default; clicking expands the answer
   below. Desktop gets a "— Click to view" / "— Click to close" text
   cue on the right edge of the question; mobile gets the existing
   +/− symbol since it's more compact at narrow widths. */
.faq-list__item {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(14px, 1.6vw, 22px);
  padding: clamp(28px, 3.5vw, 44px) 0;
  border-bottom: 1px solid var(--hairline);
  align-items: start;
}
.faq-list__item:last-child { border-bottom: none; }
.faq-list__q {
  font-family: var(--serif);
  font-size: clamp(22px, 2vw, 30px);
  line-height: 1.3;
  color: var(--ink);
  margin: 0;
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 2vw, 24px);
  padding-right: 4px;
}
.faq-list__q::-webkit-details-marker { display: none; }
/* Desktop cue text — mono small-caps, mid-grey, sits to the right of
   the question. Swaps copy when the item is open. */
.faq-list__q::after {
  content: "\2014\00a0 Click to view";
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-3, var(--mid));
  line-height: 1;
  flex: 0 0 auto;
  white-space: nowrap;
  transition: color 0.25s ease;
}
.faq-list__item[open] .faq-list__q::after {
  content: "\2014\00a0 Click to close";
}
.faq-list__item:hover .faq-list__q::after,
.faq-list__item:focus-within .faq-list__q::after {
  color: var(--ink);
}
.faq-list__a {
  font-family: var(--serif);
  font-size: clamp(17px, 1.2vw, 19px);
  line-height: 1.75;
  color: var(--ink-2);
  margin: 0;
  max-width: 72ch;
}
/* Native <details> handles collapse — answer hidden when closed,
   visible when open. No CSS override needed for desktop now. */
@media (max-width: 900px) {
  /* Mobile — swap the verbose text cue for a compact +/− symbol so
     the question doesn't wrap awkwardly at narrow widths. */
  .faq-list__q::after {
    content: "+";
    font-family: var(--sans);
    font-size: 22px;
    font-weight: 300;
    letter-spacing: 0;
    text-transform: none;
    color: var(--ink-2);
    line-height: 1;
  }
  .faq-list__item[open] .faq-list__q::after {
    content: "\2212"; /* minus sign */
  }
}

/* Studio details */
.contact-page__details { padding: clamp(80px, 10vw, 140px) 0; background: var(--bone); position: relative; }
.contact-page__details-grid { display: grid; grid-template-columns: 6fr 6fr; gap: clamp(40px, 6vw, 96px); align-items: center; }
.contact-page__details-text p { font-family: var(--serif); font-size: 17px; line-height: 1.75; color: var(--ink-2); margin-bottom: 24px; }
.contact-page__details-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px 32px; padding: 24px 0; border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); margin: 0; }
.contact-page__details-list div { display: flex; flex-direction: column; gap: 4px; }
.contact-page__details-list dt { font-family: var(--sans); font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase; color: var(--mid); }
.contact-page__details-list dd { font-family: var(--serif); font-size: 16px; color: var(--ink); margin: 0; }
.contact-page__map { margin: 0; }
.contact-page__map figcaption { font-family: var(--mono); font-style: normal; font-size: 12px; letter-spacing: 0.02em; color: var(--mid); margin-top: 12px; text-align: center; }

/* Closing letter */
.contact-page__letter { padding: clamp(100px, 12vw, 160px) 0; background: var(--bone); position: relative; }
/* Generous breathing room between the "— A note from Maja" eyebrow and
   the body text — the letter should feel composed, not crowded. */
.contact-page__letter-body {
  margin-top: clamp(40px, 5vw, 72px);
}
/* Editor's-letter typography — narrow 720px column, but body italic
   scaled up to display size. Commands attention through type, not
   through screen real estate (Kinfolk / Monocle pattern). */
.contact-page__letter-body p {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(24px, 2.4vw, 34px);
  line-height: 1.45;
  letter-spacing: -0.005em;
  color: var(--ink);
  text-align: center;
  margin: 0 0 clamp(24px, 2.4vw, 36px);
}
.contact-page__letter-sign {
  font-family: var(--serif);
  font-size: clamp(18px, 1.4vw, 22px);
  color: var(--ink-2);
  margin-top: clamp(32px, 3.6vw, 48px);
}

/* /contact/thanks/ page */
.contact-thanks { padding: clamp(140px, 16vw, 220px) 0; background: var(--bone); }
.contact-thanks__title { font-family: var(--serif); font-size: clamp(40px, 6vw, 80px); line-height: 1.05; font-weight: 400; color: var(--ink); text-align: center; margin: 20px 0 24px; }
.contact-thanks__title em { font-style: italic; }
.contact-thanks__dek { font-family: var(--serif); font-style: italic; font-size: clamp(18px, 1.5vw, 22px); line-height: 1.5; color: var(--ink-2); text-align: center; margin-bottom: 48px; }
.contact-thanks__links { display: flex; gap: clamp(32px, 4vw, 56px); justify-content: center; flex-wrap: wrap; }

@media (max-width: 900px) {
  .contact-page__form-grid { grid-template-columns: 1fr; gap: 48px; }
  .contact-page__details-grid { grid-template-columns: 1fr; gap: 32px; }
  .contact-page__details-list { grid-template-columns: 1fr; }
}

/* Home-page section flow — uniform bone background, tightened
   bottom-padding so the gap between a section's closer and the
   next section's header collapses by ~half. Closer's own
   padding-top still provides space above it; next section's full
   --pad-section top still provides space above its header. */
.manifesto,
.method,
.projects,
.testimonials,
.craft,
.process,
.cascais,
.services {
  padding-bottom: clamp(48px, 6vw, 96px);
}

/* =========================================================
   PAGE-HOME — three-act background structure
   Marble at hero (act 1) → taupe body (act 2) → marble at footer (act 3).
   Scoped to body.page-home so studio and other pages are unaffected.
   ========================================================= */
body.page-home {
  background-color: var(--bone);
  background-image: none;
}
body.page-home .intro {
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
body.page-home .footer {
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  border-top: 1px solid rgba(45, 41, 38, 0.10);
  position: relative;
}
body.page-home .intro + section {
  border-top: none;
}

/* Home-page feathers — match the sitewide transition convention. The
   body bg here is var(--taupe) instead of var(--bone), so the feathers
   fade to/from taupe at the .intro and .footer boundaries. */
body.page-home .intro {
  position: relative;
}
body.page-home .intro::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(140px, 18vh, 280px);
  background: linear-gradient(to bottom, rgba(244, 239, 230, 0), var(--bone));
  pointer-events: none;
  z-index: 1;
}
/* Home footer also uses the hard hairline (no ::before feather)
   for sitewide consistency. */
@media (max-width: 768px) {
  body.page-home .intro,
  body.page-home .footer {
    background-attachment: scroll;
  }
}

/* =========================================================
   PAGE-HOME — hero composition + scroll handover to nav
   The wordmark, headline, and guarantee lines stack as one vertically-
   centered cluster. The .intro section already flex-centers; we just
   neutralise the legacy upward lift on .intro__brand-inner and let the
   stack sit true-center. As the visitor scrolls past the hero, the
   wordmark fades + scales down, and the nav-bar wordmark fades in.
   Wired via js/scroll-brand.js (IntersectionObserver on .intro).
   ========================================================= */
body.page-home .intro__brand-inner {
  transform: none;
  gap: clamp(16px, 1.8vh, 22px);
}
body.page-home .intro__guarantee {
  line-height: 1.7;
}
body.page-home .intro__name {
  position: static;
  margin: 0;
  font-size: clamp(2.5rem, 5vw, 4.5rem);
  letter-spacing: 0.04em;
  will-change: opacity, transform;
  /* opacity + transform driven inline by js/scroll-brand.js per
     scroll frame; no CSS transition so the animation tracks the
     scroll position exactly without lag. */
}
@media (max-width: 768px) {
  body.page-home .intro__brand-inner {
    gap: clamp(12px, 1.4vh, 16px);
  }
  body.page-home .intro__name {
    font-size: clamp(1.75rem, 8vw, 2.5rem);
  }
}

/* =========================================================
   Force glassy nav — wins the cascade over any earlier or
   ad-hoc beige/paper background. Stronger blur + saturate so
   the marble + vein read clearly through the bar.
   ========================================================= */
.floating-nav {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.16) 100%
  ) !important;
  background-color: transparent !important;
  backdrop-filter: blur(28px) saturate(1.25) !important;
  -webkit-backdrop-filter: blur(28px) saturate(1.25) !important;
  border: 1px solid rgba(255, 255, 255, 0.45) !important;
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.08),
    0 2px 6px rgba(0, 0, 0, 0.04),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03) !important;
  border-radius: 9999px !important;
}
.floating-nav .nav-cta {
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.4) 0%,
    rgba(255, 255, 255, 0.22) 100%
  ) !important;
  backdrop-filter: blur(20px) saturate(1.2) !important;
  -webkit-backdrop-filter: blur(20px) saturate(1.2) !important;
  border: 1px solid rgba(255, 255, 255, 0.5) !important;
}

/* =========================================================
   UNIVERSAL PALETTE — marble bookends + taupe body
   Applies to every page-{name} body. Studio used to be excluded
   (marble dominant + olive at §04 + taupe at §08/§09), but per
   the user's directive the marble vein now appears ONLY at the
   hero and footer — every section in between reads taupe so the
   body has a single continuous tone with no mid-page palette
   shifts. /studio/ §01 hero is wrapped in .studio__opening (a div,
   not a <section>), so the studio hero is targeted explicitly.
   Marble image kept in sync with the body fallback
   (background-v3.webp is the project's current marble plate).
   ========================================================= */
body.page-studio,
body.page-projects,
body.page-services,
body.page-process,
body.page-local,
body.page-journal,
body.page-contact {
  background-color: var(--bone);
  background-image: none;
  color: var(--ink);
}

/* /contact/ override — marble across the entire page. The non-first
   sections are already painted transparent via the existing
   `body.page-contact main > section:not(:first-of-type)` rule, so
   painting the body marble makes the whole page read as one continuous
   marble surface — no cream interruption. /journal/ reverts to the
   default treatment: marble hero + cream body + marble footer. */
body.page-contact {
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
}
/* Null the hero's marble→cream bottom feather on /contact/ — body
   below is marble too, so a fade to cream would create a visible cream
   strip mid-page. /journal/ keeps the feather since its body is cream. */
body.page-contact main > section:first-of-type::after {
  display: none;
}
@media (max-width: 768px) {
  body.page-contact {
    background-attachment: scroll;
  }
}

/* /projects/ index override (2026-05-22) — body bg matches the
   .portfolio__card bg so the cards merge into the page instead of
   reading as visible "cubed" rectangles. Same colour-discipline fix
   as the project detail pages just got: cards stop being containers
   you can see the edges of; the page becomes one continuous cream
   surface, and the photos + text float on it as the only visual
   elements. The hero (first section) keeps its marble background
   for the editorial title moment; everything below reverts to cream.
   The other non-home pages (studio, services, etc.) keep their
   --taupe body bg until/unless flagged. */
body.page-projects {
  background-color: var(--bone);
}

/* Hero — first <section> in main on each non-home page. On /studio/
   the hero lives inside .studio__opening (a <div>), targeted directly
   so the marble shows through the transparent .studio__hero inside it. */
body.page-projects main > section:first-of-type,
body.page-services main > section:first-of-type,
body.page-process main > section:first-of-type,
body.page-local main > section:first-of-type,
body.page-journal main > section:first-of-type,
body.page-contact main > section:first-of-type,
body.page-studio .studio__opening {
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  position: relative;
}

/* Footer — uniform .footer class across the site. Marble + vein on
   every page including /studio/. */
body.page-studio .footer,
body.page-projects .footer,
body.page-services .footer,
body.page-process .footer,
body.page-local .footer,
body.page-journal .footer,
body.page-contact .footer,
body.page-legal .footer {
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  position: relative;
  border-top: 1px solid rgba(45, 41, 38, 0.10);
}
@media (max-width: 768px) {
  body.page-studio .footer,
  body.page-projects .footer,
  body.page-services .footer,
  body.page-process .footer,
  body.page-local .footer,
  body.page-journal .footer,
  body.page-contact .footer,
  body.page-legal .footer {
    background-attachment: scroll;
  }
}

/* ============ Background-transition feather (sitewide convention) ============
   Wherever two background surfaces meet (marble ↔ cream, photo ↔ cream,
   photo ↔ marble), a thin gradient strip dissolves one into the next so
   the boundary reads as a soft mix rather than a hard line. Same
   technique as .legal-hero::after, applied as a universal rule.

   Exception: the project pull-quote band keeps its hard top/bottom edges
   on purpose — it's the page's one designed cinematic punctuation moment. */

/* Footer hard-aligned sitewide (2026-05-24). The cream-to-marble
   gradient feather here was previously the convention; the user
   asked for a clean hairline-aligned transition instead — same
   treatment as individual project pages already have. The hairline
   above (in the marble footer rule) is now the divider. No ::before
   pseudo on any page's footer. */

/* Marble hero → cream body. Applies to every page with a marble first
   section: projects, services, process, local, journal, contact (via
   the shared "main > section:first-of-type" rule above) plus studio
   (via its bespoke .studio__opening). Legal pages have their own
   .legal-hero::after with the identical pattern.
   Height bumped 2026-05-24 from 96px max to 280px max — at full-
   viewport hero scale the shorter fade read as a "compressed transition
   strip" rather than a smooth blend; the longer gradient dissolves
   marble into cream over ~1/4 of the viewport. */
body.page-projects main > section:first-of-type::after,
body.page-services main > section:first-of-type::after,
body.page-process main > section:first-of-type::after,
body.page-local main > section:first-of-type::after,
body.page-journal main > section:first-of-type::after,
body.page-contact main > section:first-of-type::after,
body.page-studio .studio__opening::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(140px, 18vh, 280px);
  background: linear-gradient(to bottom, rgba(244, 239, 230, 0), var(--bone));
  pointer-events: none;
  z-index: 1;
}

/* Project hero bleed (photo) → cream Brief section. Soft-feather the
   bottom edge of the hero photograph so it dissolves into the cream
   below instead of meeting it at a hard line. */
.project__hero--bleed {
  position: relative;
}
.project__hero--bleed::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: clamp(56px, 6vw, 104px);
  background: linear-gradient(to bottom, transparent, var(--project-anchor));
  pointer-events: none;
  z-index: 2;
}
/* On mobile, kill the hero-bottom gradient feather — the user wants the
   first photo fully visible with a hard edge into the body, not a soft
   dissolve that visually crops the bottom of the image. */
@media (max-width: 768px) {
  .project__hero--bleed::after {
    display: none;
  }
}

/* Project up-next banner → marble footer is the ONE exception to the
   sitewide feather convention. Per the user's request, the banner
   photo abuts the marble footer with a hard, aligned edge — feathering
   here was "stealing from the image" at the photo's bottom. The footer
   ::before feather is also disabled on project detail pages (see the
   body.page-project .footer rule further down). */

@media (max-width: 768px) {
  body.page-home,
  body.page-studio,
  body.page-projects,
  body.page-services,
  body.page-process,
  body.page-local,
  body.page-journal,
  body.page-contact,
  body.page-studio .studio__opening,
  body.page-projects main > section:first-of-type,
  body.page-services main > section:first-of-type,
  body.page-process main > section:first-of-type,
  body.page-local main > section:first-of-type,
  body.page-journal main > section:first-of-type,
  body.page-contact main > section:first-of-type {
    background-attachment: scroll;
  }
}

/* =========================================================
   OLIVE ACCENT — punctuation panel + button utility
   Used sparingly: at most one moment per page. Apply .accent-olive
   to a contained card / panel / quote block; .btn-olive to a primary
   CTA. Olive on a taupe body reads as the brand's exclamation point.
   ========================================================= */
.accent-olive {
  background-color: var(--shadow);
  color: var(--bone);
  padding: 2.5rem 2rem;
  border-radius: 4px;
}
.accent-olive h2,
.accent-olive h3,
.accent-olive h4 {
  color: var(--bone);
}
.accent-olive p {
  color: rgba(244, 239, 230, 0.88);
}
.accent-olive a {
  color: var(--bone);
  border-bottom: 1px solid rgba(244, 239, 230, 0.4);
  text-decoration: none;
}
.accent-olive a:hover {
  border-bottom-color: var(--bone);
}

.btn-olive {
  background-color: var(--shadow);
  color: var(--bone);
  padding: 0.875rem 2rem;
  border: none;
  border-radius: 9999px;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 0.2s ease;
}
.btn-olive:hover {
  background-color: #5A5E3A;
}

/* Nav wordmark — hidden until the visitor scrolls past the hero, then
   settles in next to the logo mark. */
body.page-home .nav-brand .nav-wordmark {
  opacity: 0;
  pointer-events: none;
  will-change: opacity, transform;
  /* opacity + transform + pointer-events driven inline by
     js/scroll-brand.js per scroll frame. */
}

/* =========================================================
   INTRO OVERLAY — bathroom transformation video, plays once per session,
   contained in a centered framed window that floats over the marble.
   The hero (.intro__brand) sits dimmed behind it during play and fades
   back to full opacity as the overlay exits. Wired via js/intro.js +
   sessionStorage('mayasHomesIntroSeen').
   ========================================================= */
.intro-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.04);
  padding: 2rem;
  transition: opacity 1.2s ease;
  will-change: opacity;
}
.intro-overlay.is-fading {
  opacity: 0;
  pointer-events: none;
}
.intro-overlay.is-hidden {
  display: none;
}
.intro-video-wrapper {
  position: relative;
  width: min(72vw, 900px);
  aspect-ratio: 16 / 9;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.35);
  box-shadow:
    0 32px 80px rgba(0, 0, 0, 0.18),
    0 12px 24px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.intro-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.intro-skip {
  position: absolute;
  bottom: 3rem;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.35) 0%,
    rgba(255, 255, 255, 0.18) 100%
  );
  backdrop-filter: blur(20px) saturate(1.15);
  -webkit-backdrop-filter: blur(20px) saturate(1.15);
  border: 1px solid rgba(255, 255, 255, 0.45);
  color: var(--ink);
  padding: 0.6rem 1.5rem;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  cursor: pointer;
  border-radius: 9999px;
  opacity: 0;
  transition: opacity 0.6s ease 2s, background 0.25s ease, border-color 0.25s ease;
  box-shadow:
    0 4px 16px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.intro-overlay.is-loaded .intro-skip {
  opacity: 1;
}
.intro-skip:hover,
.intro-skip:focus-visible {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.5) 0%, rgba(255, 255, 255, 0.3) 100%);
  border-color: rgba(255, 255, 255, 0.6);
}
@media (max-width: 768px) {
  .intro-video-wrapper {
    width: 90vw;
    border-radius: 8px;
  }
  .intro-skip {
    bottom: 2rem;
    font-size: 0.65rem;
    padding: 0.5rem 1.2rem;
  }
}
body.intro-active {
  overflow: hidden;
}
/* Hero content visible-but-dimmed behind the framed video, then fades
   up to full opacity as the overlay exits. The 0.4s delay on the
   default rule lets the overlay start dissolving before the hero brightens. */
body.page-home .intro__brand {
  transition: opacity 1.2s ease 0.4s;
}
body.intro-active.page-home .intro__brand {
  opacity: 0.25;
  transition: opacity 1.2s ease;
}

/* /thank-you/ — Netlify Forms post-submit landing. */
.thank-you {
  background: var(--bone);
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
.thank-you__inner {
  max-width: 600px;
  padding: clamp(40px, 6vw, 80px) clamp(24px, 4vw, 64px);
  text-align: center;
}
.thank-you__lede {
  font-family: var(--sans);
  font-size: var(--fs-base);
  color: var(--mid);
  line-height: 1.6;
  margin: 24px 0 48px;
}
.thank-you__back {
  font-family: var(--sans);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline-strong);
  padding-bottom: 2px;
  transition: border-color 220ms ease;
}
.thank-you__back:hover {
  border-bottom-color: var(--ink);
}

/* Custom inline form errors — replaces browser native validation
   tooltip. Italic Cormorant in muted ink, fades in when populated.
   .contact__field--invalid is set by js/main.js on the field
   wrapper and tints the input bottom-border to var(--ink). */
.contact__error {
  display: block;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.4;
  color: var(--mid);
  margin-top: 10px;
  min-height: 1.4em;
  opacity: 0;
  transition: opacity 240ms ease;
}
.contact__error:not(:empty) { opacity: 1; }
.contact__field--invalid .contact__input,
.contact__field--invalid .contact__textarea {
  border-bottom-color: var(--ink);
}

/* =========================================================
   PROJECT DETAIL PAGE — /projects/[slug]/
   ========================================================= */
.project {
  background: var(--bone);
  padding-bottom: clamp(80px, 10vw, 140px);
}
.project__hero {
  padding: clamp(96px, 12vw, 180px) var(--pad-x) clamp(48px, 6vw, 80px);
  text-align: center;
}
.project__hero .display {
  margin: 12px 0 20px;
}
.project__strap {
  font-family: var(--sans);
  font-size: var(--fs-lg);
  line-height: 1.55;
  color: var(--ink-2);
  max-width: 56ch;
  margin: 0 auto clamp(48px, 6vw, 80px);
}
.project__hero-frame {
  margin: 0 auto;
  max-width: var(--container);
  padding: 0 var(--pad-x);
}
.project__hero-frame .ph-block {
  width: 100%;
  aspect-ratio: 16 / 9;
}
.project__hero-frame figcaption {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  text-align: center;
  margin-top: 14px;
}
.project__specs {
  padding: clamp(48px, 6vw, 80px) var(--pad-x);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.project__specs-list {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 3vw, 40px);
  padding: 0;
}
.project__spec dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin-bottom: 8px;
}
.project__spec dd {
  font-family: var(--serif);
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
@media (max-width: 760px) {
  .project__specs-list { grid-template-columns: repeat(2, 1fr); }
}
/* Brief — magazine 2-col article opener. Sidebar (1/3) carries
   eyebrow + project meta (Scope / Year / Surface). Body column
   (2/3) carries the display headline and prose. Sidebar sticks
   to the top of the viewport on long bodies so the meta stays
   visible while the reader scrolls through the brief. Collapses
   to a single column at 900px. */
.project__brief {
  padding: clamp(80px, 10vw, 140px) var(--pad-x);
}
.project__brief-inner {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: clamp(48px, 6vw, 96px);
  align-items: start;
}
.project__brief-aside {
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 3vw, 40px);
  position: sticky;
  top: 120px;
}
.project__brief-aside .eyebrow {
  margin: 0;
}
.project__brief-meta {
  display: grid;
  gap: 18px;
  margin: 0;
  padding: 0;
}
.project__brief-meta-item dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 6px;
}
.project__brief-meta-item dd {
  font-family: var(--serif);
  font-size: clamp(17px, 1.4vw, 21px);
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
.project__brief-body-col .display {
  max-width: 22ch;
  margin: 0 0 clamp(28px, 3vw, 40px);
}
.project__brief-body {
  font-family: var(--sans);
  font-size: var(--fs-base);
  line-height: 1.7;
  color: var(--ink-2);
  max-width: 56ch;
}
.project__brief-body + .project__brief-body {
  margin-top: 1.2em;
}
/* Primary CTA block after the /profile/ "Maja's Selection" carousel —
   replaces the prior section-closer-only treatment so warm visitors
   have a one-click route to /contact/, with /projects/ kept as a
   secondary inline option. Centred, generous breathing room. */
.profile__selection-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(14px, 1.6vw, 22px);
  margin: clamp(48px, 6vw, 80px) auto 0;
  text-align: center;
}
.profile__selection-cta-after {
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-3, var(--mid));
  margin: 0;
}
.profile__selection-cta-after a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.28s var(--ease-out);
}
.profile__selection-cta-after a:hover,
.profile__selection-cta-after a:focus-visible {
  color: var(--ink);
}

/* "Further reading" cross-link footer inside the brief body — sits
   beneath the last brief paragraph, quieter than body copy. Links
   each project to its canonical service section or journal article
   (Vista/Belle Rivière → turnkey, Tasca → structural, La Sala →
   piso-radiante, Rosa/Figueiras → full-home). Italic, smaller,
   underlined link with a hover lift in trim. */
.project__brief-link {
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-3, var(--mid));
  margin-top: clamp(20px, 2vw, 28px);
  max-width: 56ch;
  letter-spacing: 0.01em;
}
.project__brief-link a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.28s var(--ease-out);
}
.project__brief-link a:hover,
.project__brief-link a:focus-visible {
  color: var(--project-trim, var(--ink));
}
@media (max-width: 900px) {
  .project__brief-inner {
    grid-template-columns: 1fr;
    gap: clamp(32px, 4vw, 48px);
  }
  .project__brief-aside {
    position: static;
  }
}
/* On mobile, compress the Brief metadata (Scope / Typology / Location /
   Year) into a 2x2 grid so it occupies half the vertical space — the
   stacked 4-row pattern eats too much screen above the body copy. */
@media (max-width: 768px) {
  .project__brief-meta {
    grid-template-columns: 1fr 1fr;
    gap: 18px 24px;
  }
}
.project__photos {
  padding: clamp(60px, 8vw, 120px) var(--pad-x);
}
.project__photos-eyebrow {
  text-align: center;
  display: block;
  margin: 0 auto clamp(40px, 5vw, 64px);
}
.project__photos-grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(24px, 3vw, 40px);
}
.project__photo { margin: 0; }
.project__photo .ph-block { width: 100%; }
.project__photo--landscape .ph-block { aspect-ratio: 4 / 3; }
.project__photo--portrait  .ph-block { aspect-ratio: 3 / 4; }
.project__photo--square    .ph-block { aspect-ratio: 1 / 1; }
.project__photo figcaption {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin-top: 14px;
}
@media (max-width: 760px) {
  .project__photos-grid { grid-template-columns: 1fr; }
}
.project__quote {
  max-width: 720px;
  margin: clamp(80px, 10vw, 140px) auto;
  padding: 0 var(--pad-x);
  text-align: center;
}
.project__materials {
  padding: clamp(80px, 10vw, 140px) var(--pad-x);
}
.project__materials .display {
  max-width: 18ch;
  margin: 12px 0 40px;
}
.project__materials-list {
  list-style: none;
  padding: 0;
  margin: 0;
  max-width: 720px;
  display: grid;
  gap: 0;
}
.project__materials-list li {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 24px;
  padding: 18px 0;
  border-bottom: 1px solid var(--hairline);
  align-items: baseline;
}
.project__materials-list li:first-child {
  border-top: 1px solid var(--hairline);
}
.project__materials-list span:first-child {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
}
.project__materials-list span:last-child {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(15px, 1.2vw, 18px);
  color: var(--ink);
  line-height: 1.5;
}
@media (max-width: 600px) {
  .project__materials-list li { grid-template-columns: 1fr; gap: 4px; }
}
.project__before-after {
  padding: clamp(60px, 8vw, 120px) var(--pad-x);
  border-top: 1px solid var(--hairline);
}
.project__before-after-eyebrow {
  text-align: center;
  display: block;
  margin: 0 auto clamp(40px, 5vw, 64px);
}
.project__before-after-grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(16px, 2vw, 24px);
}
.project__ba-pair { margin: 0; }
.project__ba-pair .ph-block { width: 100%; aspect-ratio: 4 / 3; }
.project__ba-pair figcaption {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin-top: 14px;
}
@media (max-width: 760px) {
  .project__before-after-grid { grid-template-columns: 1fr; }
}
/* ---- UP NEXT — full-bleed photo with floating tab CTA
   Edge-to-edge banner photo (per-project #B image, not the hero bleed).
   A cream-coloured plaque sits inset in the bottom-left corner: mono
   eyebrow + serif project name + arrow. Tab lifts on hover. ---- */
.project__upnext {
  display: block;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-top: clamp(80px, 10vw, 140px);
  margin-bottom: calc(-1 * clamp(80px, 10vw, 140px));  /* cancel .project's padding-bottom so the banner sits flush against the footer */
  text-decoration: none;
  color: inherit;
}
.project__upnext-frame {
  position: relative;
  width: 100%;
  height: clamp(460px, 68vh, 780px);
  overflow: hidden;
  background: var(--bone);
}
.project__upnext-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 1.2s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.project__upnext-tab {
  position: absolute;
  bottom: clamp(24px, 3vw, 56px);
  left: clamp(24px, 3vw, 56px);
  padding: clamp(16px, 1.6vw, 24px) clamp(22px, 2.2vw, 32px);
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.45);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.32) 0%,
    rgba(255, 255, 255, 0.16) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.12),
    0 2px 6px rgba(0, 0, 0, 0.06),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);
  display: flex;
  flex-direction: column;
  gap: clamp(6px, 0.6vw, 10px);
  transition: transform 480ms cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 480ms ease,
              border-color 480ms ease;
  max-width: min(80vw, 480px);
}
.project__upnext-label {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.7;
}
.project__upnext-name {
  font-family: var(--serif);
  font-size: clamp(26px, 3.2vw, 40px);
  font-weight: 300;
  line-height: 1.0;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.project__upnext-arrow {
  display: inline-block;
  font-family: var(--sans);
  font-style: normal;
  font-size: 0.55em;
  margin-left: 0.6em;
  vertical-align: 0.2em;
  transition: transform 400ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.project__upnext:hover .project__upnext-frame img,
.project__upnext:focus-visible .project__upnext-frame img {
  transform: scale(1.04);
}
.project__upnext:hover .project__upnext-tab,
.project__upnext:focus-visible .project__upnext-tab {
  transform: translateY(-6px);
  border-color: rgba(255, 255, 255, 0.6);
  box-shadow:
    0 16px 44px rgba(0, 0, 0, 0.18),
    0 4px 10px rgba(0, 0, 0, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
}
.project__upnext:hover .project__upnext-arrow,
.project__upnext:focus-visible .project__upnext-arrow {
  transform: translateX(8px);
}

/* =========================================================
   PROJECT DETAIL — bespoke per-project palette system

   Every project detail page gets two body classes:
   - .page-project (generic) — sets project-page conventions:
     custom body bg, transparent project article, footer that
     inherits the project palette
   - .page-{slug} (specific) — overrides palette CSS variables
     (--project-anchor, --project-fill, --project-accent),
     derived from THAT home's actual materials

   The chassis below consumes those variables so each project
   page shares structure (hero → brief → before/during → after
   magazine spread → quote → numbers → materials → nav) but
   carries its own colour identity.

   Sitewide constants per the design rules: 3:2 aspect ratio
   on every photo, variety from scale + asymmetry, never from
   varied aspect ratios.
   ========================================================= */

body.page-project {
  --project-anchor: var(--bone);
  --project-fill: var(--paper);
  --project-accent: var(--tobacco);
  --project-trim: var(--tobacco);
  /* Body bg uses each project's bespoke --project-anchor — restored
     2026-05-24 per user request. Each of the six polished projects
     (Vista, Belle Rivière, Figueiras, La Sala, The Tasca, Rosa)
     overrides --project-anchor with its own warm tint in the
     body.page-{slug} block further down. The earlier sitewide
     --bone treatment removed that identity; bringing it back so
     each project has its own surface colour. */
  background-color: var(--project-anchor);
  /* Suppress the base body's marble PNG — marble belongs only on
     the header (when used) and the footer bookend. */
  background-image: none;
  color: var(--ink);
}
body.page-project .project { background: transparent; }
body.page-project .project .eyebrow { color: var(--project-accent); }
/* Brass-gold link hover applies to editorial body links only —
   exclude buttons (.btn-silver, section-closer pill, up-next card)
   so their canonical glass identity stays intact instead of
   tinting their text on hover. */
body.page-project .project a:hover:not(.btn-silver):not(.section-closer__link):not(.project__upnext) { color: var(--project-trim); }

/* Footer keeps the brand marble + gold-veins on every project
   detail page — sitewide bookend that hands the visitor back to
   the rest of the site. The bespoke palette governs the BODY
   only; the marble frames it top and bottom (where the hero
   isn't a full-bleed photograph). */
body.page-project .footer {
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  border-top: 1px solid rgba(45, 41, 38, 0.10);
  position: relative;
}
/* Note: no ::before cream-to-marble feather on project detail pages.
   The up-next banner photo sits directly above the footer and abuts
   the marble with a hard, aligned edge — that's the user-preferred
   treatment for this specific spot. Feathering here would create a
   cream-tinted band between the photo's bottom and the marble,
   reading as a soft seam rather than a deliberate cut. */
@media (max-width: 768px) {
  body.page-project .footer { background-attachment: scroll; }
}

/* Vista palette. Per user feedback the body anchor was moved from
   the near-marble warm white (#F7F2EC, too similar to the brand
   marble bookend used on the header/footer) to a clearly warm
   beige (#E8DDD0). The specs strip moves from oak to a placeholder
   warm gold (#C9A865) ahead of a future gold-metallic textured
   asset with subtle blur + animation.

   Hero crop overrides: aspect 21:10 (~2.1) is wider than the
   image's native 16:9, so vertical cropping kicks in;
   object-position bottom anchors the crop to the BOTTOM of the
   image, lopping ~15% off the TOP (the ceiling) so the room
   itself reads as the focal point on first scroll. */
body.page-vista {
  /* EXPERIMENT — body bg moved off warm beige onto a soft pink
     derived from the kitchen tile. To keep the rose pull-quote
     band from disappearing into the body (same hue family), the
     accent is deepened to a darker dusty rose so the band still
     reads as a deliberate moment, not a wash. Revert these two
     values back to #E8DDD0 / #D9A5A5 if the pink doesn't sit. */
  --project-anchor: #F2DDD8;
  --project-fill: #C9A865;
  --project-accent: #B98080;
  --project-trim: #B98F4A;
  /* Hero photo is supplied pre-cropped (full-bleed-vista.webp) so
     the image displays at its intrinsic aspect — no CSS crop. */
  --hero-aspect: auto;
}

/* Specs strip — placeholder warm gold band, white text on top.
   Replaces the oak fill that previously sat here. Spacing widened
   (gap, vertical padding, per-item padding) so the four metrics
   breathe. Future iteration: swap background-color for a gold
   metallic background-image with backdrop-filter blur + a slow
   shimmer animation. */
body.page-vista .project__specs {
  background-color: var(--project-fill);
  padding: clamp(56px, 6vw, 88px) var(--pad-x);
  border-top: 0;
  border-bottom: 0;
}
body.page-vista .project__specs-list {
  gap: clamp(40px, 5vw, 80px);
}
body.page-vista .project__spec {
  position: relative;
  padding-left: clamp(20px, 2vw, 32px);
}
body.page-vista .project__spec:first-child {
  padding-left: 0;
}
body.page-vista .project__spec + .project__spec::before {
  content: "";
  position: absolute;
  left: 0;
  top: 4px;
  bottom: 4px;
  width: 1px;
  background: rgba(255, 255, 255, 0.35);
}
body.page-vista .project__spec dt {
  color: rgba(255, 255, 255, 0.78);
}
body.page-vista .project__spec dd {
  color: #FFFFFF;
}

/* Section eyebrows on Vista (Before / During / After) — white
   instead of the default --project-accent rose so they read
   crisply against the pink body bg. The accent rose was the
   right pick when the body was beige, but with the pink body
   the same-family color washes out. */
body.page-vista .project__section-eyebrow {
  color: #FFFFFF;
}

/* Rose tile-textured surface on the pull quote — full-viewport
   screen sitting FLUSH against the closing pair above (no top
   margin, no ornament gap). Layered background mirrors the studio
   §03 display-quote chassis: directional light gradient + rose
   color overlay (0.78 opacity) + Vista pink-tile texture, with
   inset shadows for depth. Display-scale text matches the studio's
   spine quote so this lands as Vista's own showcase moment. */
body.page-vista .project__quote {
  position: relative;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.08) 100%),
    linear-gradient(rgba(185, 128, 128, 0.78), rgba(185, 128, 128, 0.78)),
    url('/assets/textures/Vista-pink-tile.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    inset 0 60px 80px -40px rgba(0, 0, 0, 0.25),
    inset 0 -60px 80px -40px rgba(0, 0, 0, 0.30),
    inset 80px 0 80px -40px rgba(0, 0, 0, 0.15),
    inset -80px 0 80px -40px rgba(0, 0, 0, 0.15),
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--ink);
  max-width: none;
  margin: 0 0 clamp(80px, 10vw, 140px);
  padding: clamp(140px, 16vw, 220px) var(--pad-x);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
/* Subtle noise grain so the flat tint reads as a printed surface
   rather than a flat fill — same trick as the studio band. */
body.page-vista .project__quote::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/></svg>");
  opacity: 0.07;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 1;
}
body.page-vista .project__quote > * {
  position: relative;
  z-index: 2;
}
/* Display-scale headline — matches studio §03 spine quote. */
body.page-vista .project__quote .maja-quote__text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: rgba(255, 250, 240, 0.96);
  max-width: none;
  margin: 0 auto;
}
/* Supporting body line — warm cream over the dusty-rose tile so the
   text reads cleanly without fighting the photographic texture. */
body.page-vista .project__quote .project__quote-body {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  line-height: 1.5;
  margin-top: clamp(32px, 4vw, 56px);
  max-width: 720px;
  color: rgba(255, 250, 240, 0.88);
}
/* Cite — mono caps, dimmer cream so it sits as quiet attribution
   beneath the body line. */
body.page-vista .project__quote .maja-quote__cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: rgba(255, 250, 240, 0.72);
  margin-top: clamp(40px, 5vw, 64px);
}

/* ═══════════════════════════════════════════════════════════════════════
   Belle Rivière palette — chestnut walnut + warm cream + aged brass.
   Mirrors Vista's per-project palette pattern: anchor sets the body
   bg (warm oat cream picking up marble counters + warm walls in the
   photography), accent sets the pull-quote band tint (deep walnut
   wood, so the band drops dramatically against the cream body — same
   material-contrast logic as Vista's pink-into-deeper-rose, inverted
   light→dark). Trim is aged brass for fixture-style accents. Text on
   the walnut band switches to cream (bone-on-shadow) because the
   surface is now dark, not light.
   ═══════════════════════════════════════════════════════════════════════ */
body.page-belle-riviere {
  --project-anchor: #EFE5D6;
  --project-fill: #C8B89B;
  --project-accent: #5D3F22;
  --project-trim: #B98F4A;
  --hero-aspect: auto;
}

/* Section eyebrows — deep walnut so they pop against the cream body. */
body.page-belle-riviere .project__section-eyebrow {
  color: var(--project-accent);
}

/* Walnut-textured surface on the pull quote — full-viewport screen,
   same chassis as Vista's rose tile. Layered: directional light +
   walnut brown overlay (0.78 opacity) + chestnut-walnut.webp texture
   underneath. Inset shadows deepen because the surface is darker.
   Text reads cream (bone-on-shadow / mid-on-shadow) since the
   walnut surface is dark, not light. */
body.page-belle-riviere .project__quote {
  position: relative;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.08) 100%),
    linear-gradient(rgba(93, 63, 34, 0.78), rgba(93, 63, 34, 0.78)),
    url('/assets/textures/chestnut-walnut.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    inset 0 60px 80px -40px rgba(0, 0, 0, 0.35),
    inset 0 -60px 80px -40px rgba(0, 0, 0, 0.40),
    inset 80px 0 80px -40px rgba(0, 0, 0, 0.20),
    inset -80px 0 80px -40px rgba(0, 0, 0, 0.20),
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--bone-on-shadow);
  max-width: none;
  margin: 0 0 clamp(80px, 10vw, 140px);
  padding: clamp(140px, 16vw, 220px) var(--pad-x);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
body.page-belle-riviere .project__quote::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/></svg>");
  opacity: 0.07;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 1;
}
body.page-belle-riviere .project__quote > * {
  position: relative;
  z-index: 2;
}
body.page-belle-riviere .project__quote .maja-quote__text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--bone-on-shadow);
  max-width: none;
  margin: 0 auto;
}
body.page-belle-riviere .project__quote .project__quote-body {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  line-height: 1.5;
  margin-top: clamp(32px, 4vw, 56px);
  max-width: 720px;
  color: var(--bone-on-shadow);
}
body.page-belle-riviere .project__quote .maja-quote__cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--mid-on-shadow);
  margin-top: clamp(40px, 5vw, 64px);
}

/* Design pair height-match. Belle Rivière's design photo is a wide
   landscape rendering and the materials shot is a tall portrait —
   left to their natural aspects they render unequal heights at
   2fr/1fr columns. Forcing 3:2 on the left and 3:4 on the right
   resolves to the same height because 2fr·(2/3) == 1fr·(4/3). */
body.page-belle-riviere .project__design-frame:first-child img,
body.page-figueiras .project__design-frame:first-child img,
body.page-la-sala .project__design-frame:first-child img,
body.page-rosa .project__design-frame:first-child img {
  aspect-ratio: 3 / 2;
  object-fit: cover;
}
body.page-belle-riviere .project__design-frame:nth-child(2) img,
body.page-figueiras .project__design-frame:nth-child(2) img,
body.page-la-sala .project__design-frame:nth-child(2) img,
body.page-rosa .project__design-frame:nth-child(2) img {
  aspect-ratio: 3 / 4;
  object-fit: cover;
}

/* During-pair ph-block height-match. The img selectors at
   .project__during-frame--portrait/--landscape force 3:4 and 3:2
   so the 1fr/2fr column math gives equal heights. While placeholder
   ph-blocks (not <img>) are in the during frames, they need the
   same aspect-ratios so the row doesn't tower-and-shrimp. When
   real photos drop in, these rules become harmless overlap with
   the img rules above. */
body.page-la-sala .project__during-frame--portrait .ph-block,
body.page-rosa .project__during-frame--portrait .ph-block {
  aspect-ratio: 3 / 4;
}
body.page-la-sala .project__during-frame--landscape .ph-block,
body.page-rosa .project__during-frame--landscape .ph-block {
  aspect-ratio: 3 / 2;
}

/* Tasca's bespoke before-grid 2×2 override removed 2026-05-22 —
   the 2×2 layout is now the sitewide default. The override was
   doing the same as the default rule. */

/* ═══════════════════════════════════════════════════════════════════════
   Figueiras palette — soft mauve + brushed brass + warm whites.
   Where Vista's signature material was kitchen tile (pink) and Belle
   Rivière's was chestnut cabinetry, Figueiras's is the dusty-rose
   feature wall that runs through the living room into the kitchen.
   The palette pulls the body up to that mauve so the wall reads as
   the project's identity, then deepens for the pull-quote band — the
   same body-into-band move Vista used (pink → rose) but in the
   mauve family. The band uses figueiras-plaster.webp as the texture
   layer (Vista/Belle Rivière pattern), with the mauve overlay at
   0.78 opacity sitting over it.
   ═══════════════════════════════════════════════════════════════════════ */
body.page-figueiras {
  --project-anchor: #E8D8D6;
  --project-fill: #C8A9A3;
  --project-accent: #A8857F;
  --project-trim: #B98F4A;
  /* Pull-quote typography on the mauve+plaster band. Bespoke to this
     project: the apartment's signature material pairing is mauve
     cabinetry + brushed-brass hardware, so the band's type renders
     as champagne (the brass trim lightened for legibility at display
     scale) with a deeper brass for the mono cite. Belle Rivière
     uses --bone-on-shadow on its chestnut band; Figueiras doesn't,
     so the band carries the project's own material story instead of
     reusing the generic dark-band cream. */
  --champagne-on-mauve: #F0DDB8;
  --brass-on-mauve: #D4B57E;
  --hero-aspect: auto;
}

/* Section eyebrows — deeper mauve so they pop against the soft
   mauve body without going monotone. */
body.page-figueiras .project__section-eyebrow {
  color: var(--project-accent);
}

/* Mauve plaster surface on the pull quote — full-viewport screen,
   same chassis as Vista/Belle Rivière. 3-layer background mirrors
   Vista: directional light gradient + mauve color overlay (0.78
   opacity) + figueiras-plaster.webp texture, with inset shadows for
   depth. The plaster carries enough surface variation that the
   stand-in SVG noise ::before is no longer needed. */
body.page-figueiras .project__quote {
  position: relative;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.10) 100%),
    linear-gradient(rgba(168, 133, 127, 0.78), rgba(168, 133, 127, 0.78)),
    url('/assets/textures/figueiras-plaster.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    inset 0 60px 80px -40px rgba(0, 0, 0, 0.25),
    inset 0 -60px 80px -40px rgba(0, 0, 0, 0.30),
    inset 80px 0 80px -40px rgba(0, 0, 0, 0.15),
    inset -80px 0 80px -40px rgba(0, 0, 0, 0.15),
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--ink);
  max-width: none;
  margin: 0 0 clamp(80px, 10vw, 140px);
  padding: clamp(140px, 16vw, 220px) var(--pad-x);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
body.page-figueiras .project__quote .maja-quote__text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--champagne-on-mauve);
  max-width: none;
  margin: 0 auto;
}
body.page-figueiras .project__quote .project__quote-body {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  line-height: 1.5;
  margin-top: clamp(32px, 4vw, 56px);
  max-width: 720px;
  color: var(--champagne-on-mauve);
}
body.page-figueiras .project__quote .maja-quote__cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--brass-on-mauve);
  margin-top: clamp(40px, 5vw, 64px);
}

/* ═══════════════════════════════════════════════════════════════════════
   La Sala palette — pale sage + warm ochre.
   Where Figueiras' signature material was the mauve feature wall and
   Belle Rivière's was chestnut cabinetry, La Sala's is the teal/sage
   moment that runs across the living-room fireplace wall and into the
   kitchen-tile backsplash. The palette pulls the body up to the sage
   side so the wall reads as the project's identity (the same body-into-
   accent move Figueiras made with mauve), then deepens for the pull-
   quote band. Warm ochre — the mustard sofa in the living room — sits
   as the project's complement trim. The band uses la-sala-texture.webp
   as the texture layer (Vista/Belle Rivière/Figueiras pattern), with
   the deep-sage overlay at 0.78 opacity sitting over it.
   ═══════════════════════════════════════════════════════════════════════ */
body.page-la-sala {
  /* Pale sage-cream — replaces the previous pale butter (#EBDFB8)
     which read as "too yellow" per user direction. Sits in the same
     tonal family as the deep sage band (#5E7E73) so the spread reads
     monochromatic; warm enough to feel editorial, cool enough to set
     off the deep band as a deliberate moment. */
  --project-anchor: #E2E7DD;
  --project-fill: #A5C3B8;
  --project-accent: #5E7E73;
  --project-trim: #C49B5F;
  /* Pull-quote typography on the deep-sage band. Bespoke to this
     project: the band IS the body bg deepened, and the band's type
     IS the band lightened — a monochromatic tonal answer where the
     whole spread reads as one sage spectrum. Distinct from Vista
     (dark ink on rose), Belle Rivière (--bone-on-shadow on chestnut),
     and Figueiras (champagne brass on mauve plaster). The dim cite
     pulls slightly toward the band so the mono caps recede instead
     of competing with the headline. */
  --cream-on-sage: #DDE6E0;
  --dim-on-sage: #B5C8BE;
  --hero-aspect: auto;
}

/* Section eyebrows — deeper sage so they pop against the pale-sage
   body without going monotone. */
body.page-la-sala .project__section-eyebrow {
  color: var(--project-accent);
}

/* Deep-sage textured surface on the pull quote — full-viewport screen,
   same chassis as Figueiras/Belle Rivière/Vista. 3-layer background
   mirrors Vista: directional light gradient + deep-sage color overlay
   (0.78 opacity) + la-sala-texture.webp, with inset shadows for depth.
   The texture carries enough surface variation that the stand-in SVG
   noise ::before is no longer needed. */
body.page-la-sala .project__quote {
  position: relative;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.10) 100%),
    linear-gradient(rgba(94, 126, 115, 0.78), rgba(94, 126, 115, 0.78)),
    url('/assets/textures/la-sala-texture.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    inset 0 60px 80px -40px rgba(0, 0, 0, 0.25),
    inset 0 -60px 80px -40px rgba(0, 0, 0, 0.30),
    inset 80px 0 80px -40px rgba(0, 0, 0, 0.15),
    inset -80px 0 80px -40px rgba(0, 0, 0, 0.15),
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--cream-on-sage);
  max-width: none;
  margin: 0 0 clamp(80px, 10vw, 140px);
  padding: clamp(140px, 16vw, 220px) var(--pad-x);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
body.page-la-sala .project__quote > * {
  position: relative;
  z-index: 2;
}
body.page-la-sala .project__quote .maja-quote__text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--cream-on-sage);
  max-width: none;
  margin: 0 auto;
}
body.page-la-sala .project__quote .project__quote-body {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  line-height: 1.5;
  margin-top: clamp(32px, 4vw, 56px);
  max-width: 720px;
  color: var(--cream-on-sage);
}
body.page-la-sala .project__quote .maja-quote__cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--dim-on-sage);
  margin-top: clamp(40px, 5vw, 64px);
}

/* ═══════════════════════════════════════════════════════════════════════
   The Tasca palette — warm terracotta + black metal.
   Where Vista's signature material was kitchen tile (pink), Belle
   Rivière's was chestnut cabinetry, Figueiras's was the mauve feature
   wall and La Sala's was the sage moment, The Tasca's is the
   terracotta accent wall that runs through the converted tavern.
   The palette pulls the body up to the terracotta side so the wall
   reads as the project's identity (same body-into-accent move as
   Figueiras/La Sala), then deepens for the pull-quote band. Black
   metal — the slim-profile door and window frames — sits as the
   graphic complement trim, the industrial counterpoint to the warm
   wall. The band uses the-tasca-texture.webp as the texture layer
   (Vista/Belle Rivière/Figueiras/La Sala pattern), with the deep-
   terracotta overlay at 0.78 opacity sitting over it.
   ═══════════════════════════════════════════════════════════════════════ */
body.page-the-tasca {
  --project-anchor: #F1E2CE;
  --project-fill: #E5C5A0;
  --project-accent: #B5755A;
  --project-trim: #1F1B17;
  /* Pull-quote typography on the deep-terracotta band. Bespoke to
     this project: the band IS the body bg deepened, and the band's
     type IS the band lightened — a monochromatic tonal answer in
     the terracotta family. Distinct from Vista (dark ink on rose),
     Belle Rivière (--bone-on-shadow on chestnut), Figueiras
     (champagne brass on mauve plaster), and La Sala (sage cream on
     sage). The dim cite pulls slightly toward the band so the mono
     caps recede instead of competing with the headline. */
  --cream-on-terracotta: #FBEEE0;
  --dim-on-terracotta: #E5C5B0;
  --hero-aspect: auto;
}

/* Section eyebrows — deeper terracotta so they pop against the pale-
   terracotta body without going monotone. */
body.page-the-tasca .project__section-eyebrow {
  color: var(--project-accent);
}

/* Deep-terracotta textured surface on the pull quote — full-viewport
   screen, same chassis as Figueiras/Belle Rivière/Vista/La Sala.
   3-layer background mirrors Vista: directional light gradient +
   deep-terracotta color overlay (0.78 opacity) + the-tasca-texture.webp,
   with inset shadows for depth. The texture carries enough surface
   variation that the stand-in SVG noise ::before is no longer needed. */
body.page-the-tasca .project__quote {
  position: relative;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.10) 100%),
    linear-gradient(rgba(181, 117, 90, 0.78), rgba(181, 117, 90, 0.78)),
    url('/assets/textures/the-tasca-texture.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    inset 0 60px 80px -40px rgba(0, 0, 0, 0.25),
    inset 0 -60px 80px -40px rgba(0, 0, 0, 0.30),
    inset 80px 0 80px -40px rgba(0, 0, 0, 0.15),
    inset -80px 0 80px -40px rgba(0, 0, 0, 0.15),
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--cream-on-terracotta);
  max-width: none;
  margin: 0 0 clamp(80px, 10vw, 140px);
  padding: clamp(140px, 16vw, 220px) var(--pad-x);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
body.page-the-tasca .project__quote > * {
  position: relative;
  z-index: 2;
}
body.page-the-tasca .project__quote .maja-quote__text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--cream-on-terracotta);
  max-width: none;
  margin: 0 auto;
}
body.page-the-tasca .project__quote .project__quote-body {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  line-height: 1.5;
  margin-top: clamp(32px, 4vw, 56px);
  max-width: 720px;
  color: var(--cream-on-terracotta);
}
body.page-the-tasca .project__quote .maja-quote__cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--dim-on-terracotta);
  margin-top: clamp(40px, 5vw, 64px);
}

/* ═══════════════════════════════════════════════════════════════════════
   Rosa palette — anthracite + saddle-tan + pale dove.
   Where the other projects all rode a warm-color identity (Vista's
   rose, Belle Rivière's chestnut, Figueiras's mauve, La Sala's sage,
   The Tasca's terracotta), Rosa is the FIRST dark-band project. Its
   signature material is the black stormy marble that runs across the
   kitchen counter + backsplash, paired with matt-charcoal cabinetry,
   saddle-tan leather barstools, pale oak floor, and conservation-
   district white walls with original cornice. The body pulls up to a
   warm dove (the cooled-down anthracite, tinted with saddle warmth)
   so the page reads as a sea-misted urban neutral, then deepens
   hard for the pull-quote band to anthracite — the kitchen's
   defining darkness. Saddle-tan sits as the warm complement trim.
   No texture URL on the band yet; when a stone/marble/concrete
   swatch lands in /assets/textures/ it can be added the same way
   Figueiras uses figueiras-plaster.webp.
   ═══════════════════════════════════════════════════════════════════════ */
body.page-rosa {
  --project-anchor: #DBD5CC;
  --project-fill: #8C8780;
  --project-accent: #2D2826;
  --project-trim: #C9A87A;
  /* Pull-quote typography on the anthracite band. Bespoke to this
     project: Rosa is the only dark-band project in the portfolio,
     so the typography sits as pale champagne — warm enough to honor
     the saddle-tan trim, light enough to read on near-black. Cite
     uses the trim color (saddle-tan) directly, so the mono caps
     recede into the band's warm complement instead of competing
     with the headline. Distinct from every other project (Vista,
     Belle Rivière, Figueiras, La Sala, The Tasca all run dark-on-
     warm or warm-cream-on-warm). Rosa runs warm-cream-on-dark. */
  --champagne-on-anthracite: #ECE0C6;
  --saddle-on-anthracite: #C9A87A;
  --hero-aspect: auto;
}

/* Section eyebrows — the project trim (saddle-tan) so they pop
   against the warm-dove body without going monotone. */
body.page-rosa .project__section-eyebrow {
  color: var(--project-trim);
}

/* Anthracite-marble surface on the pull quote — full-viewport
   screen. Layer 1: directional light gradient. Layer 2: anthracite
   color overlay (0.78 — the dark base). Layer 3: rosa-texture
   (light marble with gold + dark veining; the dark overlay
   on top means the marble veining peeks through as warm shadow
   detail rather than showing as its native cream tones). The
   inset vignette shadows were removed at the user's direction —
   only the outer edge depth-shadows remain. */
body.page-rosa .project__quote {
  position: relative;
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.10) 100%),
    linear-gradient(rgba(45, 40, 38, 0.60), rgba(45, 40, 38, 0.60)),
    url('/assets/textures/rosa-texture.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--champagne-on-anthracite);
  max-width: none;
  margin: 0 0 clamp(80px, 10vw, 140px);
  padding: clamp(140px, 16vw, 220px) var(--pad-x);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
}
/* SVG noise ::before removed 2026-05-22 — texture replaces it. */
body.page-rosa .project__quote::before {
  content: none;
  display: none;
  pointer-events: none;
  z-index: 1;
}
body.page-rosa .project__quote > * {
  position: relative;
  z-index: 2;
}
body.page-rosa .project__quote .maja-quote__text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--champagne-on-anthracite);
  max-width: none;
  margin: 0 auto;
}
body.page-rosa .project__quote .project__quote-body {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(20px, 1.8vw, 28px);
  font-weight: 400;
  line-height: 1.5;
  margin-top: clamp(32px, 4vw, 56px);
  max-width: 720px;
  color: var(--champagne-on-anthracite);
}
body.page-rosa .project__quote .maja-quote__cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--saddle-on-anthracite);
  margin-top: clamp(40px, 5vw, 64px);
}

/* Expanded During section for Rosa — bespoke 7-photo sequence
   documenting the patio's "what was under the tile" story (find
   water damage → strip → waterproof → rebuild → tile). Layout:
   landscape single → portrait FEATURE single (the water discovery,
   gets its own dramatic slot) → portrait pair (strip + waterproof)
   → portrait pair (substructure + new tile) → landscape single.
   Section is container-constrained (not full-bleed) so the
   process-photo density doesn't overwhelm the page. Reuses
   .project__detail (singles) and .project__pair (pairs) building
   blocks; adds a .project__detail--portrait modifier for the
   centered portrait feature slot. Per the aspect-ratio rule, photos
   honour their actual orientation — no cropping enforced. */
body.page-rosa .project__during {
  /* Was max-width: 1040px which made the eyebrow + photo pairs sit
     narrower than the surrounding BEFORE and AFTER sections (both
     at var(--container) = 1480px). Widened to the sitewide container
     so the eyebrow aligns with the other section eyebrows and the
     DURING photo pairs fill the same horizontal column. */
  max-width: var(--container);
  margin: clamp(48px, 6vw, 88px) auto;
  padding: 0 var(--pad-x);
  display: flex;
  flex-direction: column;
  gap: clamp(56px, 7vw, 96px);
}
/* Inside the during section, the pair primitives' default container
   max-width and bottom margins are absorbed by the parent flex-column
   gap — keep each pair fluid and let the container drive the size. */
body.page-rosa .project__during .project__pair,
body.page-rosa .project__during .project__design-pair {
  max-width: none;
  margin: 0;
  padding: 0;
  gap: clamp(24px, 3vw, 40px);
}

/* The eyebrow already gets standard project__section-eyebrow styling
   from the chassis — but on Rosa, the .project__during section has
   its own padding-x (added when widening the section to var(--container))
   which stacks with the eyebrow's own padding-x and pushes the eyebrow
   text one pad-x further inward than the photos and the BEFORE/AFTER
   eyebrows. Zero the eyebrow's own padding so it aligns with the
   surrounding sections. */
body.page-rosa .project__during > .project__section-eyebrow {
  padding-left: 0;
  padding-right: 0;
  max-width: none;
}

/* Portrait FEATURE single — for the "found water" slot. Centered,
   narrower, gives the discovery moment full visual weight without
   spanning the whole container. */
body.page-rosa .project__during .project__detail--portrait {
  max-width: 520px;
  margin-left: auto;
  margin-right: auto;
}
body.page-rosa .project__during .project__detail--portrait img {
  aspect-ratio: 3 / 4;
  object-fit: cover;
  width: 100%;
}

/* Portrait pair frames — override the default 3:2 landscape so
   portrait process shots render at their natural orientation. */
body.page-rosa .project__during .project__pair-frame img {
  aspect-ratio: 3 / 4;
}

/* Per-frame caption beneath each Rosa during photo — italic serif,
   muted, names the narrative beat. */
body.page-rosa .project__during .project__detail figcaption,
body.page-rosa .project__during .project__pair-frame figcaption {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  margin-top: 12px;
  max-width: 56ch;
}

/* ---- YOUR HOME, NEXT — voicey CTA bridging the project page to
   /contact/. Centered editorial block — eyebrow + display + italic
   line + canonical pill — sits between the prev/next nav and the
   back-to-projects closer. ---- */
.project__closer-cta {
  max-width: var(--container);
  margin: clamp(80px, 8vw, 120px) auto clamp(48px, 5vw, 72px);
  padding: 0 var(--pad-x);
  text-align: center;
}
.project__closer-cta .eyebrow {
  margin: 0 auto clamp(20px, 2vw, 28px);
}
.project__closer-cta-title {
  max-width: 22ch;
  margin: 0 auto clamp(20px, 2vw, 28px);
}
.project__closer-cta-body {
  font-family: var(--serif);
  font-size: clamp(17px, 1.4vw, 22px);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 48ch;
  margin: 0 auto clamp(32px, 4vw, 48px);
}

/* ---- HERO: full-bleed photo. Title is baked into the image
   itself, so no CSS overlay is needed — the photograph IS the
   cover. A visually-hidden H1 (.sr-only) preserves the page's
   semantic title for screen readers + SEO. ---- */
.project__hero--bleed {
  padding: 0;
}
.project__hero--bleed .project__hero-frame {
  max-width: none;
  padding: 0;
  margin: 0;
}

/* Visually-hidden utility — content stays in the accessibility
   tree but is removed from the visual layout. Standard SR-only
   pattern. */
.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;
}
/* Hero photo crop. Aspect ratio + object-position are per-project
   CSS variables so each project can tune its hero focal point —
   some homes' best frames are wide and bottom-heavy (Vista), some
   are tall and centred. Defaults (3:2 + centre) are sensible for
   most landscape shots; per-page overrides live on body.page-{slug}. */
.project__hero--bleed .project__hero-frame img {
  width: 100%;
  aspect-ratio: var(--hero-aspect, 3 / 2);
  object-fit: cover;
  object-position: var(--hero-position, center center);
  display: block;
}
/* On mobile, lift brightness slightly so the baked-in Didot wordmark
   ("Vista", "Figueiras", etc.) reads more clearly against the photo.
   The photo doesn't blow out at brightness 1.15 — it just brings the
   dimmer text characters up to where they're legible on small screens. */
@media (max-width: 768px) {
  .project__hero--bleed .project__hero-frame img {
    filter: brightness(1.15) contrast(0.95);
  }
}
/* Hero text band. Container stretches to var(--container) so the
   left/right gutters match every other section on the page; the
   text inside caps at reading-line widths (display ~24ch, strap
   ~64ch) so the typography stays readable while the composition
   stays editorial-wide. */
.project__hero-text {
  max-width: var(--container);
  margin: 0 auto;
  padding: clamp(48px, 6vw, 80px) var(--pad-x) clamp(32px, 4vw, 56px);
  text-align: center;
}
.project__hero-text .display {
  margin: 14px auto 24px;
  max-width: 28ch;
}
.project__hero-text .project__strap {
  margin: 0 auto;
  max-width: 64ch;
}

/* Section eyebrow used to label Before / Design / During / After.
   Owns its own horizontal gutter (padding 0 var(--pad-x)) so the
   eyebrow always sits at the same x-coordinate as the photo grids
   beneath it, regardless of whether the parent section has
   horizontal padding or not. Unified gutter system across all
   four after-page chapters means perfect column alignment. */
.project__section-eyebrow {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--project-accent);
  max-width: var(--container);
  margin: 0 auto clamp(28px, 3vw, 44px);
  padding: 0 var(--pad-x);
}
/* Normalize the eyebrow-to-image gap across every project section.
   Some image elements (.project__detail, .project__pair, etc.) carry
   their own margin-top so they sit nicely BETWEEN sibling figures —
   but when they're the FIRST element after a section eyebrow, that
   margin stacks on top of the eyebrow's own margin-bottom and the
   gap balloons. Adjacent-sibling reset keeps the gap uniform across
   BEFORE, DESIGN, DURING, AFTER sections on every project. */
.project__section-eyebrow + .project__before-grid,
.project__section-eyebrow + .project__detail,
.project__section-eyebrow + .project__pair,
.project__section-eyebrow + .project__design-pair,
.project__section-eyebrow + .project__during-pair,
.project__section-eyebrow + .project__bleed {
  margin-top: 0;
}

/* Photo-frame zoom — every contained photo on a project page gets
   the same subtle scale-zoom on hover/focus. Replaces the earlier
   per-section caption hover-reveal as the page's kinetic register;
   keeps the visitor's eye engaged without competing with the
   editorial type. Overflow:hidden clips the scaled image to the
   frame edge. Hero is excluded — it's a page cover, not a card. */
.project__before-frame,
.project__design-frame,
.project__during-frame,
.project__detail,
.project__pair-frame,
.project__bleed {
  overflow: hidden;
}
.project__before-frame img,
.project__design-frame img,
.project__during-frame img,
.project__detail img,
.project__pair-frame img,
.project__bleed img {
  transition: transform 720ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.project__before-frame:hover img,
.project__before-frame:focus-within img,
.project__design-frame:hover img,
.project__design-frame:focus-within img,
.project__during-frame:hover img,
.project__during-frame:focus-within img,
.project__detail:hover img,
.project__detail:focus-within img,
.project__pair-frame:hover img,
.project__pair-frame:focus-within img,
.project__bleed:hover img,
.project__bleed:focus-within img {
  transform: scale(1.03);
}

/* ---- DESIGN chapter: 2-frame pair filling the container at the
   same width-scale as Before / During / After so the page rhythm
   stays consistent. Grid columns are 2:1 (matching the inverse of
   the two images' aspect ratios — 3:2 landscape vs 3:4 portrait),
   which makes both frames render at the same height naturally
   while honouring each image's intrinsic aspect. No height cap —
   the math constrains to ~560px tall at desktop, which matches
   the surrounding chapter scale. ---- */
.project__design {
  padding: clamp(48px, 6vw, 80px) 0;
}
.project__design-pair {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: clamp(16px, 2vw, 28px);
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  align-items: start;
}
.project__design-frame {
  margin: 0;
  display: flex;
  flex-direction: column;
}
.project__design-frame img {
  width: 100%;
  height: auto;
  display: block;
}
/* Caption sits BELOW the design photo, always visible. */
.project__design-frame figcaption {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  margin-top: 12px;
  max-width: 56ch;
}
@media (max-width: 760px) {
  .project__design-pair {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .project__design-frame img {
    max-width: 480px;
    margin: 0 auto;
  }
}

/* ---- BEFORE strip: 3 thumbnails, demoted scale + slight desat ---- */
.project__before {
  padding: clamp(48px, 6vw, 80px) 0 clamp(20px, 2vw, 32px);
}
/* Before strip — 3 portrait frames (kitchen / bathroom / bedroom).
   All shots at the same 3:4 portrait aspect, sitting as a
   deliberate contrast against the page's otherwise landscape-
   locked photography — the shape shift signals "before, raw" vs
   "after, opened up". Slight desaturation + opacity demote the
   frames so they sit as supporting content, not the headline.
   Grid owns its own padding-x gutter so widths match the After
   gallery at wide viewports (unified container - 2*pad-x). */
/* Default sitewide: 4-up row of portrait befores (Figueiras, Vista,
   Belle Rivière, La Sala, Rosa — all 3:4 portrait shots that read
   well as a single horizontal strip of four). Tasca's befores are
   landscape so it gets its own 2×2 override below. */
.project__before-grid {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.4vw, 22px);
  align-items: start;
}
/* The Tasca's 4 BEFORE photos are all landscape — at 4-up each frame
   becomes a stretched ribbon. Override back to 2×2 so each landscape
   gets meaningful width. */
body.page-the-tasca .project__before-grid {
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(18px, 1.8vw, 28px);
}
/* Frames sit slightly desaturated + lifted-down at rest; hover
   restores full saturation, full opacity, a subtle 4px lift, AND
   reveals an italic caption overlay at the bottom of the photo
   describing what's in the frame. Editorial concept: hover
   "wakes the memory up" and gives the visitor the caption they
   only need if they're curious enough to dwell. */
.project__before-frame {
  margin: 0;
  filter: saturate(0.85);
  opacity: 0.92;
  transform: translateY(0);
  transition:
    filter 400ms cubic-bezier(0.2, 0.8, 0.2, 1),
    opacity 400ms cubic-bezier(0.2, 0.8, 0.2, 1),
    transform 400ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.project__before-frame:hover,
.project__before-frame:focus-within {
  filter: saturate(1);
  opacity: 1;
  transform: translateY(-4px);
}
.project__before-frame img {
  width: 100%;
  height: auto;
  display: block;
}

/* Caption overlay — italic serif on a SOLID dark band at the
   bottom of the frame (not a gradient). Solid bg ensures the text
   sits on a consistent backdrop regardless of what's underneath
   the band, so it stays legible whether the photo behind is light
   (cream bathroom tile) or dark (brown kitchen cabinets). A tiny
   gradient sliver above the band softens the hard edge. */
/* Caption sits BELOW the image in the page space (not an overlay)
   — magazine convention. Italic Cormorant, muted dark on the page
   background. Always visible (no hover-reveal). */
.project__before-frame figcaption {
  margin-top: clamp(10px, 1vw, 14px);
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(13px, 1vw, 16px);
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  text-align: center;
  color: var(--ink-2);
}
.project__before-frame .ph-block { width: 100%; }
/* 900px breakpoint removed 2026-05-22 — default is already 2×2
   sitewide, so the tablet-only re-statement was a no-op. */
@media (max-width: 540px) {
  .project__before-grid { grid-template-columns: 1fr; gap: 12px; }
}
/* The Tasca's 4 BEFORE photos are all landscape — on mobile the 2x2
   override squeezes them. Stack 1-per-row so each landscape frame has
   real width and breathing room. */
@media (max-width: 768px) {
  body.page-the-tasca .project__before-grid {
    grid-template-columns: 1fr;
    gap: clamp(20px, 3vw, 32px);
  }
}

/* Tasca DURING — even vertical rhythm between the singles and the
   pairs. The base CSS gives .project__detail only a top margin while
   .project__pair gets both top and bottom — visually unequal between
   adjacent siblings. Equalize on Tasca so the 7-image sequence breathes
   consistently. Also style the figcaptions that we just added. */
body.page-the-tasca .project__during > .project__detail,
body.page-the-tasca .project__during > .project__pair {
  margin-top: clamp(28px, 3.4vw, 48px);
  margin-bottom: clamp(28px, 3.4vw, 48px);
}
body.page-the-tasca .project__during > .project__detail:first-of-type {
  margin-top: clamp(20px, 2.4vw, 32px);
}
body.page-the-tasca .project__during .project__pair {
  gap: clamp(28px, 3.4vw, 48px);
}
body.page-the-tasca .project__during .project__detail figcaption,
body.page-the-tasca .project__during .project__pair-frame figcaption {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  margin-top: 12px;
  max-width: 56ch;
  text-align: center;
}
@media (max-width: 760px) {
  body.page-the-tasca .project__during .project__pair {
    gap: clamp(28px, 3.4vw, 48px);
  }
}

/* ---- DURING: two-frame pair, inverse of Design (small + large).
   Mirrors .project__design-pair / .project__design-frame chassis
   but flips the column ratio to 1fr / 2fr so the smaller frame
   leads and the larger one closes. ---- */
.project__during { padding: clamp(40px, 5vw, 64px) 0; }
.project__during-pair {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: clamp(16px, 2vw, 28px);
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--pad-x);
  align-items: start;
}
.project__during-frame {
  margin: 0;
  display: flex;
  flex-direction: column;
}
.project__during-frame img,
.project__during-frame .ph-block {
  width: 100%;
  height: auto;
  display: block;
}
/* Orientation modifiers — force a portrait crop on the left frame
   (3:4) and a landscape crop on the right (3:2). The 1fr/2fr grid
   math ensures both frames land at the same height when these
   ratios pair (1·4/3 == 2·2/3), so the row reads as a balanced
   editorial diptych instead of one frame towering over the other.
   object-fit: cover crops the landscape source into the desired
   shape — adjust object-position if a subject gets clipped. */
.project__during-frame--portrait img {
  aspect-ratio: 3 / 4;
  object-fit: cover;
  height: auto;
}
.project__during-frame--landscape img {
  aspect-ratio: 3 / 2;
  object-fit: cover;
  height: auto;
}
/* Caption sits BELOW the during photo, always visible. */
.project__during-frame figcaption {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  margin-top: 12px;
  max-width: 56ch;
}
@media (max-width: 760px) {
  .project__during-pair {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .project__during-frame img,
  .project__during-frame .ph-block {
    max-width: 480px;
    margin: 0 auto;
  }
}

/* ---- AFTER gallery — magazine spread ---- */
.project__after {
  padding: clamp(60px, 7vw, 96px) 0 clamp(80px, 8vw, 120px);
}

/* Pair: asymmetric 2-up (large + small). The LARGE frame defines
   the row height via aspect-ratio 3:2; the SMALL frame stretches
   to match that height. Without this split, both frames would
   carry aspect-ratio 3:2 and the larger column (2fr wide) would
   compute to ~1.5× the height of the smaller (1fr wide), top-
   aligning with an asymmetric gap below the small frame. With
   the split, both frames sit on the same baseline and the small
   image just crops more aggressively via object-fit: cover. */
.project__pair {
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: clamp(16px, 2vw, 28px);
  max-width: var(--container);
  margin: clamp(40px, 5vw, 72px) auto;
  padding: 0 var(--pad-x);
  align-items: stretch;
}
.project__pair--reverse { grid-template-columns: 1fr 1fr; }
/* Equal-width pair: both frames at 1fr columns + locked 3:2 aspect
   on both images. Honours the sitewide 3:2 rule on every photo.
   Scale variation across the after-gallery comes from layout TYPE
   (wide-contained vs pair vs full-bleed vs single-detail), NOT
   from asymmetric column widths within a single pair — which was
   the source of the cropping/aspect inconsistency in the earlier
   2fr/1fr version. */
.project__pair {
  grid-template-columns: 1fr 1fr;
}
.project__pair-frame {
  margin: 0;
  display: flex;
  flex-direction: column;
}
.project__pair-frame img,
.project__pair-frame .ph-block {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
}
/* Optional caption beneath a pair frame — italic serif, restrained,
   used for room-specific lines like "Lavender cabinets, pink tile…". */
.project__pair-frame figcaption {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.5;
  color: var(--ink-2);
  margin-top: 12px;
}
@media (max-width: 900px) {
  .project__pair,
  .project__pair--reverse {
    grid-template-columns: 1fr;
    gap: 16px;
  }
}

/* Bleed: full-bleed image, no container, edge to edge */
.project__bleed { margin: clamp(48px, 5vw, 72px) 0; padding: 0; }
.project__bleed img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
}
/* --flush variant: zero bottom margin so an adjacent full-bleed
   section (e.g. the rose pull-quote screen) stacks against the
   image with no white-space gap. */
.project__bleed--flush { margin-bottom: 0; }

/* Detail: contained single frame at the end of the gallery */
.project__detail {
  max-width: var(--container);
  margin: clamp(40px, 5vw, 72px) auto 0;
  padding: 0 var(--pad-x);
}
.project__detail img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  display: block;
}

/* ---- NUMBERS strip — duration / sq m / trades / permits ---- */
.project__numbers {
  padding: clamp(60px, 7vw, 96px) var(--pad-x);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.project__numbers-grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 3vw, 40px);
}
.project__number dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 10px;
}
.project__number dd {
  font-family: var(--serif);
  font-size: clamp(24px, 2.4vw, 36px);
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
@media (max-width: 760px) {
  .project__numbers-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ---- DETAILS: combined Numbers + Materials in a single wide
   section. Replaces what used to be two stacked sections (one
   for numbers, one for materials), which doubled vertical scroll
   without using horizontal space. Two columns at desktop, single
   column at mobile. ---- */
.project__details {
  padding: clamp(60px, 7vw, 96px) var(--pad-x);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.project__details-grid {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(48px, 6vw, 96px);
  align-items: start;
}
.project__details-col {
  display: flex;
  flex-direction: column;
}
.project__details-col .eyebrow {
  margin: 0 0 clamp(20px, 2vw, 28px);
}
.project__details-col .display {
  font-size: clamp(28px, 2.4vw, 36px);
  margin: 0 0 clamp(28px, 3vw, 40px);
  max-width: 18ch;
}
.project__details-numbers {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(24px, 3vw, 40px) clamp(20px, 2.4vw, 32px);
}
.project__details-numbers .project__number dt {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  margin: 0 0 8px;
}
.project__details-numbers .project__number dd {
  font-family: var(--serif);
  font-size: clamp(22px, 2vw, 30px);
  font-weight: 400;
  color: var(--ink);
  margin: 0;
}
.project__details-materials {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 0;
}
.project__details-materials li {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 20px;
  padding: 14px 0;
  border-bottom: 1px solid var(--hairline);
  align-items: baseline;
}
.project__details-materials li:first-child {
  border-top: 1px solid var(--hairline);
}
.project__details-materials span:first-child {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
}
.project__details-materials span:last-child {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(15px, 1.1vw, 17px);
  color: var(--ink);
  line-height: 1.5;
}
@media (max-width: 900px) {
  .project__details-grid {
    grid-template-columns: 1fr;
    gap: clamp(48px, 6vw, 72px);
  }
}
@media (max-width: 600px) {
  .project__details-numbers { grid-template-columns: 1fr; }
  .project__details-materials li { grid-template-columns: 1fr; gap: 4px; }
}

/* ---- 3:2 placeholder aspect (sitewide locked project aspect) ---- */
.ph-block--3-2 { aspect-ratio: 3 / 2; }

/* =========================================================
   ZENBOOK FOLD / FOLDABLE-LAPTOP RESPONSIVE PASS
   The default 960px collapse-to-single-column breakpoint is
   too eager for the 820-1024px range (Zenbook Fold etc).
   Hold the two-column desktop layouts a little wider; restore
   per-section spacing where the legacy collapse misfires.
   ========================================================= */
@media (min-width: 820px) and (max-width: 1024px) {
  /* Method (Our Approach) — keep two-col headline / body split. */
  .method__grid {
    grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
    gap: clamp(32px, 4vw, 56px);
  }
  .method__head { padding-right: 0; }

  /* Craft images flush to the section's left edge. */
  .craft__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(20px, 2.5vw, 32px);
    padding-left: 0;
    padding-right: 0;
  }
  .craft__cell { padding-left: 0; }

  /* Process phases — image + text two-col with min-width:0 so the
     copy column can't be squeezed into a narrow strip by the image's
     intrinsic size. */
  .phase__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(32px, 4vw, 56px);
  }
  .phase__text { padding-right: 0; min-width: 0; }
  .phase__image { min-width: 0; }

  /* Footer — three-up at slightly tighter padding. */
  .footer__details {
    grid-template-columns: 1fr 1fr 1fr;
    gap: clamp(40px, 5vw, 72px);
    padding: clamp(60px, 8vw, 100px) clamp(32px, 5vw, 80px);
  }
}

/* Cascais intro (atmosphere photo + bridge lede) — at <=1024 the
   van photo dominates above the closer text. Reverse so the copy
   sits on top. */
@media (max-width: 1024px) {
  .cascais__intro {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto;
  }
  .cascais__intro-text  { order: -1; }

  /* Contact "Begin a project" — stack to single centred column. */
  .contact__inner {
    grid-template-columns: 1fr;
    max-width: 720px;
    margin: 0 auto;
    text-align: left;
  }
  .contact__intro,
  .contact__form { max-width: 100%; }
}

/* Footer breathing space below the foldable threshold. */
@media (max-width: 819px) {
  .footer__details {
    gap: clamp(48px, 6vw, 72px);
    padding-top: clamp(60px, 8vw, 100px);
    padding-bottom: clamp(60px, 8vw, 100px);
  }
  .footer__brand,
  .footer__nav,
  .footer__contact { margin-bottom: 16px; }
}

/* =========================================================
   MOBILE RESPONSIVE PASS — iPhone SE / 375px viewport.
   Scoped to <=760px unless noted. A small set of rules also
   reverse the cascais intro at <=1024 (handled in the prior
   Zenbook block).
   ========================================================= */

/* Single-line nav CTA on mobile. */
@media (max-width: 760px) {
  .nav__cta {
    white-space: nowrap;
    padding: 10px 18px;
    font-size: 11px;
    letter-spacing: 0.14em;
  }
  .nav__cta span:not([aria-hidden]) { display: inline; }
}

/* Section closers — filled glass default at mobile (no hover state). */
@media (max-width: 760px) {
  .section-closer--minimal .section-closer__link {
    background: linear-gradient(
      180deg,
      rgba(255, 253, 247, 0.95) 0%,
      rgba(248, 243, 232, 0.88) 55%,
      rgba(240, 234, 220, 0.85) 100%
    );
    border-color: rgba(255, 252, 244, 0.85);
    box-shadow:
      inset 0  1px 0   rgba(255, 255, 255, 0.95),
      inset 0 -1px 0   rgba(120, 105,  80, 0.10),
      0  1px  1px rgba(60, 50, 35, 0.04),
      0  6px  14px rgba(60, 50, 35, 0.07);
  }
}

/* Project tile reveal — looser breathing space at mobile. */
@media (max-width: 760px) {
  .tile__solved {
    padding: clamp(20px, 6%, 36px) clamp(16px, 5%, 24px) clamp(80px, 18%, 100px);
  }
  .tile__solved-text {
    font-size: clamp(15px, 3.6vw, 18px);
    line-height: 1.5;
    letter-spacing: 0.1em;
    margin: 0 0 22px 0;
    max-width: 100%;
  }
  .tile__solved-detail {
    font-size: 10px;
    letter-spacing: 0.14em;
    line-height: 1.65;
  }
}

/* Process phases — image on top, text below, on every phase. */
@media (max-width: 760px) {
  .phase__grid,
  .phase--mirror .phase__grid {
    grid-template-columns: 1fr;
    gap: clamp(24px, 4vw, 40px);
  }
  .phase__image,
  .phase--mirror .phase__grid > .phase__image { order: 0; }
  .phase__text,
  .phase--mirror .phase__grid > .phase__text { order: 1; padding: 0; min-width: 0; }
}

/* Cascais — eyebrow no-wrap, sticky horizontal toggle bar. The
   cascais__intro reversal lives in the <=1024 block above. */
@media (max-width: 760px) {
  .cascais__head .eyebrow { white-space: nowrap; }

  /* (Removed: mobile tab strip rules for the now-collapsed widget.) */
}

/* Footer — 2-row layout: brand spans top, site + reach as 2 cols below. */
@media (max-width: 760px) {
  .footer__details {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "brand brand"
      "site contact";
    gap: clamp(40px, 6vw, 56px) clamp(20px, 4vw, 32px);
    padding: clamp(60px, 8vw, 96px) clamp(24px, 5vw, 32px);
  }
  .footer__brand   { grid-area: brand; }
  .footer__nav     { grid-area: site; }
  .footer__contact { grid-area: contact; }

  .footer__nav ul,
  .footer__contact ul { font-size: 14px; }
  .footer__contact-value { font-size: 14px; word-break: break-word; }

  .footer__credentials {
    flex-direction: column;
    gap: 16px;
    text-align: center;
    padding: clamp(32px, 5vw, 48px) clamp(24px, 5vw, 32px);
  }
  .footer__credentials-line { text-align: center !important; }
}

/* Craft carousel — mobile only. Desktop keeps the 3-column grid. */
@media (max-width: 760px) {
  .craft__grid {
    display: grid;
    grid-template-columns: 1fr;
    position: relative;
  }
  .craft__grid > .craft__cell {
    grid-area: 1 / 1;
    opacity: 0;
    pointer-events: none;
    transition: opacity 480ms ease;
  }
  .craft__grid > .craft__cell.is-active {
    opacity: 1;
    pointer-events: auto;
  }
  .craft__nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    margin-top: clamp(28px, 4vw, 48px);
  }
  .craft__arrow {
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: 1px solid var(--hairline-strong);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .craft__count {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    color: var(--mid);
    min-width: 50px;
    text-align: center;
  }
}
@media (min-width: 761px) {
  .craft__nav { display: none; }
}

/* =========================================================
   MOBILE — process steps carousel, map tap-to-advance, footer
   contact label-above-value. iPhone 12 Pro / 390px and below.
   ========================================================= */

/* Process steps -> single-cell carousel on mobile. The four
   <li class="process__step"> items stack on the same grid cell;
   .is-active fades in. The .process__result aside lives outside
   the <ol> so it stays inline beneath the carousel. */
@media (max-width: 760px) {
  .process__steps {
    display: grid;
    position: relative;
    list-style: none;
    padding: 0;
    margin: 0;
  }
  .process__steps > .process__step {
    grid-area: 1 / 1;
    grid-template-columns: 1fr !important;
    opacity: 0;
    pointer-events: none;
    transition: opacity 480ms ease;
  }
  .process__steps > .process__step.is-active {
    opacity: 1;
    pointer-events: auto;
    position: relative;
  }
  .process__phases-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    margin: clamp(28px, 5vw, 48px) auto clamp(40px, 6vw, 72px);
  }
  .process__phase-arrow {
    width: 40px;
    height: 40px;
    border-radius: 999px;
    border: 1px solid var(--hairline-strong);
    background: transparent;
    color: var(--ink);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  .process__phase-count {
    font-family: var(--mono);
    font-size: 11px;
    letter-spacing: 0.18em;
    color: var(--mid);
    min-width: 50px;
    text-align: center;
  }
}
@media (min-width: 761px) {
  .process__phases-nav { display: none; }
}

/* (Removed: .local-mastery__frame-button / __tap-hint / __nav /
   __arrow / __map-count rules. The four-state interactive widget
   was collapsed to a single static map; the click-to-advance and
   arrow nav have no remaining purpose.) */

/* Footer contact list -> label above value at mobile. Each row
   stacks: small mono key on top, italic Cormorant value beneath.
   Email no longer wraps mid-domain. */
@media (max-width: 760px) {
  .footer__contact ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 18px;
  }
  .footer__contact li { display: block; }
  .footer__contact-key {
    display: block;
    font-family: var(--mono);
    font-size: 10px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--mid);
    margin-bottom: 4px;
  }
  .footer__contact-value {
    display: block;
    font-family: var(--serif);
    font-style: italic;
    font-size: 14px;
    color: var(--ink);
    word-break: keep-all;
    overflow-wrap: anywhere;
  }
  .footer__nav ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    gap: 14px;
  }
  .footer__nav a {
    font-family: var(--serif);
    font-size: 16px;
    color: var(--ink);
    text-decoration: none;
  }
}

/* =========================================================
   MOBILE NAV REBUILD — slim editorial pill at <=760px.
   Light, breathing, never crowded. Brand-mark + wordmark on
   the left, compact CTA on the right, nothing in between.
   This block is intentionally last so it wins the cascade.
   ========================================================= */
@media (max-width: 760px) {
  .nav {
    top: 12px;
    left: 12px;
    right: 12px;
  }
  .nav__inner {
    padding: 10px 14px;
    border-radius: 999px;
    backdrop-filter: blur(18px) saturate(140%);
    -webkit-backdrop-filter: blur(18px) saturate(140%);
    background: rgba(248, 246, 240, 0.78);
    border: 1px solid rgba(0, 0, 0, 0.05);
    box-shadow: 0 4px 18px rgba(0, 0, 0, 0.04);
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 12px;
  }

  /* Hide the middle nav links + the burger toggle. The brand and
     CTA are the only two elements that matter on mobile. */
  .nav__links,
  .nav__menu-toggle { display: none !important; }

  /* Brand row — small mark + tight wordmark. */
  .nav__brand { gap: 8px; }
  .nav__logo,
  .nav__brand .brand-mark {
    width: 26px;
    height: 26px;
    flex: 0 0 26px;
    object-fit: contain;
  }
  .nav__brand-name {
    font-family: var(--serif);
    font-style: normal;
    font-size: 14px;
    letter-spacing: 0.04em;
    line-height: 1;
    color: var(--ink);
    white-space: nowrap;
  }

  /* CTA pill — accent, not control panel. */
  .nav__cta {
    padding: 7px 14px;
    font-size: 11.5px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    border-radius: 999px;
    line-height: 1;
    white-space: nowrap;
    gap: 6px;
  }
  .nav__cta svg { width: 12px; height: 12px; }
}

/* iPhone SE territory — tighten one more notch. */
@media (max-width: 390px) {
  .nav {
    top: 10px;
    left: 10px;
    right: 10px;
  }
  .nav__inner {
    padding: 9px 12px;
    gap: 10px;
  }
  .nav__logo,
  .nav__brand .brand-mark {
    width: 24px;
    height: 24px;
    flex: 0 0 24px;
  }
  .nav__brand-name {
    font-size: 13px;
  }
  .nav__cta {
    padding: 6px 11px;
    font-size: 10.5px;
    letter-spacing: 0.06em;
  }
  .nav__cta svg { width: 11px; height: 11px; }
}

/* =========================================================
   FLOATING NAV — slim editorial ribbon. Brand left, three
   monochrome social icons + hamburger right. The "Begin a
   Project" CTA lives on the home page bridge section now,
   not in the nav. Aman / Loro Piana register: the bar is a
   bookmark, not a control panel.
   ========================================================= */
.floating-nav {
  position: fixed;
  top: 16px;
  left: 16px;
  right: 16px;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 11px 18px;
  border-radius: 999px;
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.35) 0%,
    rgba(255, 255, 255, 0.18) 100%
  );
  backdrop-filter: blur(24px) saturate(1.2);
  -webkit-backdrop-filter: blur(24px) saturate(1.2);
  border: 1px solid rgba(255, 255, 255, 0.45);
  box-shadow:
    0 6px 32px rgba(0, 0, 0, 0.08),
    0 1px 4px rgba(0, 0, 0, 0.04),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);
  transition: transform 0.4s ease, opacity 0.3s ease;
}

/* Hide pre-intro on the home page; the intro state machine adds
   .is-visible (via nav.js intro:end handler). On dedicated pages
   we mark the header .is-visible directly so it shows on load. */
html.is-intro .floating-nav {
  transform: translateY(-140%);
  opacity: 0;
  pointer-events: none;
}

.nav-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--ink);
}
.nav-brand .nav-mark {
  width: 32px;
  height: 32px;
  flex: 0 0 32px;
  object-fit: contain;
  border-radius: 0;
}
.nav-brand .nav-wordmark {
  font-family: var(--serif);
  font-size: 19px;
  letter-spacing: 0.022em;
  line-height: 1;
  color: var(--ink);
  white-space: nowrap;
}

.nav-tools {
  display: inline-flex;
  align-items: center;
  gap: 14px;
}
.nav-social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  color: var(--mid);
  text-decoration: none;
  transition: color 0.25s ease, transform 0.25s ease;
}
.nav-social svg {
  width: 16px;
  height: 16px;
  fill: currentColor;
}
.nav-social:hover,
.nav-social:focus-visible {
  color: var(--ink);
  transform: translateY(-1px);
}

.nav-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: transparent;
  border: 0;
  padding: 0;
  margin-left: 4px;
  color: var(--ink);
  cursor: pointer;
}
.nav-menu-icon {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 20px;
  height: 14px;
}
.nav-menu-icon span {
  display: block;
  height: 1px;
  background: var(--ink);
  width: 100%;
  transition: transform 0.3s ease, opacity 0.3s ease, width 0.3s ease;
}
.nav-menu-icon span:nth-child(2) {
  width: 70%;
  align-self: flex-end;
}
.nav-menu-toggle[aria-expanded="true"] .nav-menu-icon span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.nav-menu-toggle[aria-expanded="true"] .nav-menu-icon span:nth-child(2) {
  opacity: 0;
}
.nav-menu-toggle[aria-expanded="true"] .nav-menu-icon span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* Drawer — full-bleed marble overlay with stacked Cormorant links. */
.nav-drawer {
  position: fixed;
  inset: 0;
  z-index: 80;
  background-color: var(--bone);
  background-image: url('/assets/images/background-v3.webp');
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}
.nav-drawer.is-open {
  opacity: 1;
  pointer-events: auto;
}
.nav-drawer[hidden] { display: none; }

.nav-drawer__inner {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 80px 32px 56px;
  max-width: 720px;
  margin: 0 auto;
}
.nav-drawer__close {
  position: absolute;
  top: 22px;
  right: 22px;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  color: var(--ink);
  cursor: pointer;
}
.nav-drawer__close svg { width: 18px; height: 18px; }

.nav-drawer__links {
  display: flex;
  flex-direction: column;
  gap: 32px;
  margin-top: 32px;
}
.nav-drawer__links a {
  position: relative;
  font-family: var(--serif);
  font-size: clamp(34px, 7vw, 56px);
  font-weight: 400;
  letter-spacing: -0.008em;
  line-height: 1.02;
  color: var(--ink);
  text-decoration: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 4px;
  transition: color 0.25s ease, padding-left 0.3s ease;
}
.nav-drawer__links a:hover,
.nav-drawer__links a:focus-visible {
  color: var(--ink);
  padding-left: 4px;
}

.nav-drawer__footer {
  margin-top: clamp(28px, 4vw, 40px);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.nav-drawer__footer .btn-silver {
  align-self: center;
}

body.nav-locked { overflow: hidden; }

/* Silver pill button — glassy 3D feel. Used in the drawer footer and the
   floating-nav CTA. Transform is intentionally NOT touched on :hover so the
   magnetic translation handler can drive it without the rules fighting. */
/* .btn-silver — now a peer selector inside the canonical glass group at
   the top of this file (gleam + cursor-tracked shine + scale-on-press),
   so this standalone block is intentionally empty. The class identity
   (shape, padding, font, colour) lives in the canonical block alongside
   .nav__cta, .btn-glass, etc. */

/* Mobile-specific tightening. */
@media (max-width: 760px) {
  .floating-nav {
    top: 12px;
    left: 12px;
    right: 12px;
    padding: 9px 14px;
    gap: 10px;
  }
  .nav-brand .nav-mark {
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border-radius: 0;
  }
  .nav-brand .nav-wordmark {
    font-size: 17px;
    letter-spacing: 0.02em;
  }
  .nav-tools { gap: 10px; }
  .nav-social { width: 26px; height: 26px; }
  .nav-social svg { width: 14px; height: 14px; }
  .nav-menu-toggle { width: 30px; height: 30px; margin-left: 2px; }
  .nav-drawer__inner { padding: 72px 22px 44px; }
}
@media (max-width: 390px) {
  .floating-nav {
    top: 10px;
    left: 10px;
    right: 10px;
    padding: 8px 12px;
    gap: 8px;
  }
  .nav-brand { gap: 8px; }
  .nav-brand .nav-mark {
    width: 26px;
    height: 26px;
    flex: 0 0 26px;
    border-radius: 0;
  }
  .nav-brand .nav-wordmark {
    font-size: 15.5px;
    letter-spacing: 0.018em;
    white-space: nowrap;
  }
  .nav-tools { gap: 8px; }
  .nav-social {
    width: 24px;
    height: 24px;
  }
  .nav-social svg {
    width: 13px;
    height: 13px;
  }
  .nav-menu-toggle {
    width: 28px;
    height: 28px;
  }
}

/* === Cinematic hero — single line at every viewport === */
.intro__name {
  white-space: nowrap;
  letter-spacing: -0.005em;
}
@media (max-width: 1024px) {
  .intro__name {
    font-size: clamp(42px, 8.25vw, 72px);
    line-height: 1;
  }
}
@media (max-width: 760px) {
  .intro__name {
    font-size: clamp(34.5px, 9.75vw, 54px);
    letter-spacing: -0.008em;
    line-height: 1;
  }
}
@media (max-width: 390px) {
  .intro__name {
    font-size: clamp(31.5px, 9.375vw, 42px);
    letter-spacing: -0.012em;
  }
}

/* =========================================================
   DESKTOP NAV — inline eyebrow links + Begin a Project pill
   at >=1024px. Mobile (<=1023px) keeps the brand + socials +
   hamburger pattern unchanged; the inline links and pill are
   hidden by default and only revealed at desktop. The drawer
   stays mobile-only because its toggle lives inside .nav-tools
   which is hidden at desktop.
   ========================================================= */
.nav-links { display: none; }
.nav-cta   { display: none; }

@media (min-width: 1024px) {
  .floating-nav {
    top: 18px;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: max-content;
    max-width: calc(100vw - 80px);
    padding: 13px 22px 13px 26px;
    gap: 32px;
    border-radius: 999px;
    background: rgba(248, 246, 240, 0.82);
    backdrop-filter: blur(22px);
    -webkit-backdrop-filter: blur(22px);
    border: 1px solid rgba(0, 0, 0, 0.05);
    box-shadow: 0 6px 22px rgba(0, 0, 0, 0.04);
  }

  .nav-tools {
    gap: 24px;
  }

  .nav-menu-toggle,
  .nav-social {
    display: none;
  }

  .nav-brand {
    gap: 14px;
  }

  .nav-brand .nav-mark {
    width: 28px;
    height: 28px;
    flex: 0 0 28px;
    border-radius: 0;
  }

  .nav-brand .nav-wordmark {
    font-family: var(--serif);
    font-size: 17px;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.115em;
    line-height: 1;
    color: var(--ink);
  }

  .nav-links {
    display: inline-flex;
    flex: 0 0 auto;
    gap: 32px;
  }

  .nav-links a {
    position: relative;
    font-family: var(--sans);
    font-size: 11px;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.16em;
    color: var(--ink-2);
    text-decoration: none;
    line-height: 1;
    white-space: nowrap;
    transition: color 0.3s ease;
  }

  .nav-links a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -5px;
    height: 1px;
    background: var(--ink);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.35s ease;
  }

  .nav-links a:hover,
  .nav-links a:focus-visible,
  .nav-links a.is-current {
    color: var(--ink);
  }

  .nav-links a:hover::after,
  .nav-links a:focus-visible::after,
  .nav-links a.is-current::after {
    transform: scaleX(1);
  }

  .nav-cta {
    display: inline-flex;
  }

  .nav-cta.btn-silver {
    padding: 11px 20px;
    font-size: 11px;
    letter-spacing: 0.16em;
  }
}

/* === Defensive override — fade-in must always render visible ===
   If JS doesn't fire (ScrollTrigger error, script load failure, etc.),
   sections must still be readable. Animation is sacrificed for visibility. */
.fade-in {
  opacity: 1 !important;
  transform: none !important;
  visibility: visible !important;
}

/* === Studio portrait imgs — slot into the placeholder geometry ===
   Same dimensions and crop behavior as the .ph-block placeholders they
   replace, so the surrounding layout doesn't shift when real photos land. */
.studio__person-photo {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center top;
  display: block;
  margin: 0;
}
/* Per-portrait crop modifiers — move the focal point of the source
   image down a fraction so the head doesn't sit pinned to the top
   of the 4:5 frame. Replaces the inline style="object-position…"
   attributes that previously lived on each <img>. */
.studio__person-photo--top { object-position: 50% 18%; }
.studio__person-photo--top-right { object-position: 58% 18%; }
/* Per-user request: shift the focal point a further 10 percentage
   points down on portraits where the head was sitting too high in
   the 4:5 frame (Bogdan, Yurii, Vlad, Ivan, Jhon → was 18%, now 28%;
   Iurie → was 0%, now 10%). Artur (--top-right) and Lukas (--top)
   stay where they were. */
.studio__person-photo--lowered { object-position: 50% 28%; }
.studio__person-photo--lowered-shallow { object-position: 50% 10%; }
.studio__intro-portrait-image {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: center top;
  display: block;
  margin: 0;
}

/* === Studio §05 — Selected work (project teaser) === */
.studio__work {
  /* Trimmed three times — clamp(120, 14vw, 180) tuned to marble,
     then clamp(80, 10vw, 120) on the flat-taupe pass, then
     clamp(56, 7vw, 88) on the rhythm pass. This pass trims the
     bottom further so the hairline divider below sits closer to
     the CTA pill. */
  padding: clamp(48px, 6vw, 72px) 0;
  background-color: transparent;
  background-image: none;
}
.studio__work .wrap {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.studio__work .eyebrow--centered {
  text-align: center;
  margin: 0 0 clamp(20px, 2.4vw, 32px);
}
.studio__work .studio__h2--centered {
  text-align: center;
  margin: 0 auto clamp(56px, 7vw, 80px);
  max-width: 16ch;
}
.studio__work-tile {
  margin: 0;
}
.studio__work-link-tile {
  display: flex;
  flex-direction: column;
  gap: 14px;
  text-decoration: none;
  color: inherit;
}
.studio__work-tile .ph-block {
  width: 100%;
  aspect-ratio: 4 / 3;
  margin: 0;
  transition: transform 0.5s ease;
}
.studio__work-link-tile:hover .ph-block,
.studio__work-link-tile:focus-visible .ph-block {
  transform: scale(1.01);
}
.studio__work-name {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(20px, 1.8vw, 26px);
  line-height: 1.15;
  color: var(--ink);
  margin: 8px 0 0;
}
.studio__work-location {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-2);
  margin: 0;
}
.studio__work-cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin: clamp(56px, 7vw, 80px) auto 0;
  align-self: center;
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(20px, 1.8vw, 26px);
  color: var(--ink);
  text-decoration: none;
  position: relative;
  width: fit-content;
  padding: 4px 0;
}
.studio__work-cta::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.35s ease;
}
.studio__work-cta:hover::after,
.studio__work-cta:focus-visible::after {
  transform: scaleX(1);
}
.studio__work-cta-arrow {
  display: inline-block;
  transition: transform 0.35s ease;
}
.studio__work-cta:hover .studio__work-cta-arrow,
.studio__work-cta:focus-visible .studio__work-cta-arrow {
  transform: translateX(4px);
}

/* === Studio §07 — Studio details (workspace) === */
.studio__details {
  /* Trimmed from clamp(100, 12vw, 160) — was tuned to marble. */
  padding: clamp(80px, 10vw, 120px) 0;
  background-color: transparent;
  background-image: none;
}
/* §07 eyebrow — same Inter 11 px weight 400 ls 0.16 em treatment
   as §02 and §03 so the three intro-level eyebrows read as one
   family. Was inheriting the base .eyebrow (12 px Plex Mono-ish
   weight 500, ls 0.22 em) which felt heavy here. */
.studio__details .eyebrow--centered {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-2);
  text-align: center;
  margin: 0 0 clamp(20px, 2.4vw, 32px);
}
.studio__details .studio__h2--centered {
  text-align: center;
  margin: 0 auto clamp(56px, 7vw, 80px);
  max-width: 16ch;
}

/* === Studio section markers — varied registers per section ===
   Italic Cormorant lead-in (§02, §06, §09): voice register, sets a tone.
   Plex Mono utility marker (§04, §07): technical-metadata register,
   numbered chapter or place dispatch. Together with no-marker sections
   (§03, §05) and the §01 stamp+eyebrow opener, the page presents six
   different opening shapes across nine sections. */

/* Italic Cormorant lead-in — used in §02, §06, §09 */
.studio__lead-in {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(17px, 1.5vw, 22px);
  line-height: 1.4;
  letter-spacing: 0.005em;
  color: var(--mid);
  margin: 0 0 clamp(20px, 2.4vw, 32px);
}
.studio__lead-in--centered {
  text-align: center;
  max-width: 36ch;
  margin-left: auto;
  margin-right: auto;
}
.studio__lead-in em {
  font-style: italic;
}

/* Plex Mono utility marker — §04 (numbered chapter) and §07 (place dispatch) */
.studio__mono-marker {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--mid);
  margin: 0 0 clamp(24px, 2.8vw, 36px);
  text-align: center;
}

@media (max-width: 760px) {
  .studio__lead-in {
    font-size: clamp(15px, 4vw, 18px);
  }
  .studio__mono-marker {
    font-size: 10.5px;
    letter-spacing: 0.2em;
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   Studio page — magazine-spread restructure.
   Five compositional moves: marginalia timeline (§02), full-bleed display
   quote (§03), feature + grid (§05), asymmetric founder + bench (§06),
   horizontal marquee (§07). Each section attacks the linearity differently.
   ═══════════════════════════════════════════════════════════════════════ */

/* === Studio §03 — full-bleed display-scale spine quote === */
.studio__quote-band {
  position: relative;
  padding: clamp(140px, 16vw, 220px) 0;
  /* Layer 1: directional light. Layer 2: olive color overlay (0.78 — tile shows
     through more than before). Layer 3: tile texture. */
  background:
    linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0) 40%, rgba(0, 0, 0, 0.08) 100%),
    linear-gradient(rgba(74, 78, 46, 0.78), rgba(74, 78, 46, 0.78)),
    url('/assets/textures/olive-tile.webp');
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  box-shadow:
    inset 0 60px 80px -40px rgba(0, 0, 0, 0.25),
    inset 0 -60px 80px -40px rgba(0, 0, 0, 0.30),
    inset 80px 0 80px -40px rgba(0, 0, 0, 0.15),
    inset -80px 0 80px -40px rgba(0, 0, 0, 0.15),
    0 -2px 20px rgba(0, 0, 0, 0.18),
    0 2px 20px rgba(0, 0, 0, 0.18);
  color: var(--bone-on-shadow);
}
.studio__quote-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.4'/></svg>");
  opacity: 0.07;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 1;
}
.studio__quote-band > * {
  position: relative;
  z-index: 2;
}
.studio__quote-spread {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 clamp(32px, 5vw, 96px);
}
.studio__quote-display {
  margin: 0;
  padding: 0;
}
.studio__quote-display p {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.5rem, 5.5vw, 5.25rem);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--bone-on-shadow);
  margin: 0 auto;
  max-width: none;
}
.studio__quote-display cite {
  display: block;
  font-family: var(--mono);
  font-style: normal;
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--mid-on-shadow);
  margin-top: clamp(40px, 5vw, 64px);
  text-align: right;
}
@media (max-width: 760px) {
  .studio__quote-display p {
    font-size: clamp(26px, 7vw, 40px);
  }
}

/* === Studio §05 — feature + grid === */
.studio__work-feature {
  margin: 0 0 clamp(48px, 6vw, 80px);
}
.studio__work-feature .studio__work-link-tile {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 2vw, 24px);
  text-decoration: none;
  color: inherit;
}
.studio__work-feature .ph-block {
  width: 100%;
  aspect-ratio: 21 / 9;
  margin: 0;
  transition: transform 0.5s ease;
}
.studio__work-feature .studio__work-link-tile:hover .ph-block {
  transform: scale(1.005);
}
.studio__work-feature-meta {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.studio__work-feature-name {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(28px, 3vw, 44px);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0;
}
.studio__work-note {
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(15px, 1.2vw, 18px);
  line-height: 1.5;
  color: var(--mid);
  margin: 0;
}
.studio__work-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(20px, 2.6vw, 36px);
  align-items: start;
}
.studio__work-grid .ph-block {
  aspect-ratio: 4 / 3;
}
.studio__work-grid .studio__work-name {
  font-size: clamp(15px, 1.2vw, 18px);
  margin: 6px 0 0;
}
@media (max-width: 1024px) {
  .studio__work-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
@media (max-width: 600px) {
  .studio__work-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* === Studio §05 — eight-person bench grid (uniform 4×2 at desktop) === */
/* Eight Hands · One Signature.
   Desktop: 4-column grid showing all eight craftspeople at once.
   Mobile (≤1024px): single-person carousel — persons stack
   absolutely in one cell; only .is-active is visible; prev/next
   buttons cycle through. JS in js/people-carousel.js. */
.studio__people-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(24px, 3vw, 40px);
  align-items: start;
  margin-top: clamp(56px, 7vw, 96px);
}
/* Controls hidden on desktop — full grid is the navigation. */
.studio__people-controls {
  display: none;
}
@media (max-width: 1024px) {
  .studio__people-grid {
    position: relative;
    grid-template-columns: 1fr;
    max-width: 420px;
    margin: clamp(56px, 7vw, 96px) auto 0;
  }
  .studio__people-grid > .studio__person {
    grid-column: 1;
    grid-row: 1;
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.45s var(--ease-out), visibility 0s ease 0.45s;
  }
  .studio__people-grid > .studio__person.is-active {
    position: relative;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0);
    transition: opacity 0.45s var(--ease-out), visibility 0s ease 0s;
  }
  .studio__people-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(20px, 3vw, 32px);
    margin: clamp(32px, 4vw, 48px) auto 0;
    max-width: 420px;
  }
}
.studio__people-arrow {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--ink);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.36) 0%,
    rgba(255, 255, 255, 0.18) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  border: 1px solid rgba(255, 255, 255, 0.48);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.08),
    0 2px 6px rgba(0, 0, 0, 0.04),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.studio__people-arrow:hover,
.studio__people-arrow:focus-visible {
  transform: scale(1.05);
  outline: none;
}
.studio__people-arrow:active {
  transform: scale(0.97);
}
.studio__people-counter,
.studio__work-counter {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0;
  min-width: 5ch;
  text-align: center;
}
/* Counter is mobile-only — on desktop the dot indicator below
   the stage is the position cue, so the counter stays hidden. */
.studio__work-counter {
  display: none;
}
/* §06 bench portraits — staggered reveal pattern. Each cell sits
   invisible + slightly down by default; .is-revealed on the parent
   grid triggers a per-cell fade-in with an 80 ms cascade left to
   right. Adds personality without choreography — the eye reads
   "8 people, one after another" instead of "block of 8 photos." */
.studio__person {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0;
}
.studio__person .ph-block,
.studio__person .studio__person-photo {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  margin: 0;
}
.studio__person h3 {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(18px, 1.4vw, 22px);
  line-height: 1.15;
  letter-spacing: 0.005em;
  color: var(--ink);
  margin: 4px 0 0;
}
.studio__person-role {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--ink-2);
  margin: 0;
}
.studio__person-detail {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.45;
  color: var(--mid);
  margin: 0;
}
@media (max-width: 1024px) {
  .studio__people-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: clamp(28px, 4vw, 36px);
  }
}
@media (max-width: 600px) {
  .studio__people-grid {
    grid-template-columns: 1fr;
    gap: 36px;
    max-width: 360px;
    margin-left: auto;
    margin-right: auto;
  }
}
/* Stagger cascade — fires when JS adds .is-revealed to the grid
   (via ScrollTrigger in js/main.js). 80 ms gap between each cell. */
.studio__people-grid.is-revealed .studio__person {
  opacity: 1;
  transform: translateY(0);
}
.studio__people-grid.is-revealed .studio__person:nth-child(1)  { transition-delay:   0ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(2)  { transition-delay:  80ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(3)  { transition-delay: 160ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(4)  { transition-delay: 240ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(5)  { transition-delay: 320ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(6)  { transition-delay: 400ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(7)  { transition-delay: 480ms; }
.studio__people-grid.is-revealed .studio__person:nth-child(8)  { transition-delay: 560ms; }

/* === Studio §07 — horizontal marquee === */
/* §07 triptych — drawing → sample → install. Three uniform 4:3 frames
   in a row at desktop, each labelled with a Plex Mono step plate
   ("1 · Drawing", "2 · Sample", "3 · Install") and closed with an
   italic Cormorant caption. Replaces the previous horizontal marquee
   which was 75 % placeholder. Stacks to one column on mobile. */
.studio__triptych {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 2.6vw, 40px);
  margin: clamp(40px, 5vw, 64px) auto 0;
  max-width: 1280px;
}
/* §07 triptych frame — sequential reveal pattern. Each frame sits
   invisible + slightly down by default; .is-revealed on the parent
   .studio__triptych triggers a 200 ms cascade across the three
   frames. Teaches the visitor's eye the temporal logic of the
   triptych (design → sample → install) instead of dumping all
   three frames in simultaneously. */
.studio__triptych-frame {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0;
}
/* Step plate above each frame — same Inter eyebrow style used by the
   section eyebrow and §02/§03. Brings every label in §07 into one
   typographic family. Previously Plex Mono, which read as a one-off
   font that didn't appear in the canonical eyebrow system. */
.studio__triptych-step {
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 0 0 2px;
}
/* Triptych frame aspect: 3:4 portrait. Source assets (render + samples
   are 3584×4800; install rotated to 3024×4032) all read natural at this
   ratio, so the install crops the least and the render + samples fit
   perfectly. */
.studio__triptych-frame .ph-block,
.studio__triptych-frame img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  display: block;
  margin: 0;
}
/* Caption below each frame — italic Cormorant (the original
   editorial-flourish font) at the bigger 15-18 px size, in full
   charcoal ink. User reverted the family from Inter back to serif
   per "we don't use that font there elsewhere" feedback, but kept
   the bigger size + charcoal color so the line still reads
   visibly. The original 13-15 px in --mid was the version that
   was barely visible; this is the same family at the bigger size
   and darker color. */
.studio__triptych-frame figcaption {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.5;
  letter-spacing: 0;
  color: var(--ink);
  margin: 0;
}
@media (max-width: 768px) {
  .studio__triptych {
    grid-template-columns: 1fr;
    gap: clamp(36px, 6vw, 56px);
    max-width: 480px;
  }
}
/* Sequential reveal — fires when JS adds .is-revealed to the
   triptych (via ScrollTrigger in js/main.js). 200 ms between
   frames: design lands first, then sample, then install. */
.studio__triptych.is-revealed .studio__triptych-frame {
  opacity: 1;
  transform: translateY(0);
}
.studio__triptych.is-revealed .studio__triptych-frame:nth-child(1) { transition-delay:   0ms; }
.studio__triptych.is-revealed .studio__triptych-frame:nth-child(2) { transition-delay: 200ms; }
.studio__triptych.is-revealed .studio__triptych-frame:nth-child(3) { transition-delay: 400ms; }

/* === Studio §04 (was §05) — recent work tile notes ===
   Small italic editorial note beneath each smaller tile's location. The
   feature tile (Belle Rivière) uses .studio__work-note at a larger scale;
   this rule handles the five smaller tiles' archive-register notes. */
.studio__work-tile-note {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(13px, 1vw, 15px);
  line-height: 1.4;
  color: var(--mid);
  margin: 6px 0 0;
}

/* === Studio §04 — recent work hero images ===
   Slot into the placeholder geometry the .ph-block elements held: 21:9 wide
   landscape for the Belle Rivière feature, 4:3 for the five smaller tiles.
   Same hover scale as the original placeholder transition. */
.studio__work-feature-image {
  width: 100%;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  display: block;
  margin: 0;
  transition: transform 0.5s ease;
}
.studio__work-link-tile:hover .studio__work-feature-image,
.studio__work-link-tile:focus-visible .studio__work-feature-image {
  transform: scale(1.005);
}
.studio__work-tile-image {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  margin: 0;
  transition: transform 0.5s ease;
}
.studio__work-link-tile:hover .studio__work-tile-image,
.studio__work-link-tile:focus-visible .studio__work-tile-image {
  transform: scale(1.01);
}


/* === Studio §01.5 — Publication stamp band ===
   Small horizontal editorial stripe between the title page and the practice
   intro — Maya's Homes mark + Plex Mono dispatch + italic tagline, framed by
   hairlines above and below. Aman section break + Cereal publication mark
   register. */
.studio__stamp {
  padding: clamp(40px, 5vw, 56px) 0 clamp(56px, 7vw, 80px);
  background-color: transparent;
  background-image: none;
}
@media (max-width: 768px) {
  .studio__stamp {
    padding: 2rem 0 2.5rem;
  }
}

/* === Studio §01 + §01.5 — combined opening composition.
   The wrapper fills 100vh and vertically centers the hero
   (name, role, lede) plus the publication stamp band as one
   magazine-cover-style title page. Inner sections drop their
   own min-height / vertical padding so the void between them
   collapses to a deliberate gap. */
.studio__opening {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 8rem 0 4rem;
  gap: 5rem;
}
.studio__opening .studio__hero {
  min-height: auto;
  padding: 0;
}
.studio__opening .studio__stamp {
  padding: 0;
}
@media (max-width: 768px) {
  .studio__opening {
    padding: 6rem 0 3rem;
    gap: 3rem;
  }
}
.studio__stamp-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(16px, 2vw, 24px);
  text-align: center;
}
.studio__stamp-mark {
  display: flex;
  align-items: center;
  justify-content: center;
}
.studio__stamp-mark img {
  width: 80px;
  height: 80px;
  object-fit: contain;
  display: block;
}
.studio__stamp-caption {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  justify-items: center;
  width: 100%;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--mid);
  margin: 0;
}
.studio__stamp-caption-left {
  justify-self: end;
  padding-right: 0.4em;
  text-align: right;
}
.studio__stamp-caption-right {
  justify-self: start;
  padding-left: 0.4em;
  text-align: left;
}
.studio__stamp-tagline {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.45;
  color: var(--ink-2);
  margin: 0;
  max-width: 36ch;
}
@media (max-width: 760px) {
  .studio__stamp {
    padding: clamp(40px, 6vw, 60px) 0;
  }
  .studio__stamp-mark img {
    width: 64px;
    height: 64px;
  }
  .studio__stamp-tagline {
    font-size: clamp(14px, 4vw, 16px);
  }
}
@media (max-width: 480px) {
  /* Stamp caption stacks vertically on phones — three lines, all centered. */
  .studio__stamp-caption {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 0.2em;
  }
  .studio__stamp-caption-left,
  .studio__stamp-caption-right {
    justify-self: center;
    padding: 0;
    text-align: center;
  }
}

/* === Mobile fallback — parallax (background-attachment: fixed) breaks on iOS
   Safari; force scroll on small viewports so the body backsplash and section
   panels still render. === */
@media (max-width: 768px) {
  body,
  .studio__hero,
  .studio__quote-band,
  .studio__letter {
    background-attachment: scroll;
  }
}

/* === Print — strip all textures and depth effects, render flat for paper === */
@media print {
  body {
    background-image: none;
    background-color: var(--bone);
  }
  body::before {
    display: none;
  }
  .studio__hero,
  .studio__quote-band,
  .studio__letter {
    background: var(--bone);
    color: var(--ink);
    box-shadow: none;
  }
  .studio__quote-band::before {
    display: none;
  }
}

/* =========================================================
   MOBILE PROCESS STEP FIX
   - Force every step to stack as a flex column on mobile
   - Force text (.process__copy) above image (.process__visual-stack)
     on every step regardless of DOM order or the --reverse modifier
   - Desktop layout (display: grid; 1fr 1fr; --reverse alternation)
     is untouched
   The parent .process__steps remains a grid carousel on mobile;
   each step's internal layout is what we override here.
   ========================================================= */
@media (max-width: 768px) {
  .process__step,
  .process__step--reverse {
    display: flex !important;
    flex-direction: column !important;
    gap: 1.75rem;
  }
  .process__step .process__copy,
  .process__step--reverse .process__copy {
    order: 1 !important;
  }
  .process__step .process__visual-stack,
  .process__step--reverse .process__visual-stack {
    order: 2 !important;
  }
}

/* =========================================================
   MOBILE-ONLY — process section breathing room + CTA padding
   - Adds ~10rem total clearance between .process and .cascais
   - Pads the "See the full process, week by week" link so the
     text + arrow don't feel pinched
   Desktop unchanged.
   ========================================================= */
@media (max-width: 768px) {
  .process {
    padding-bottom: 5rem;
  }
  .cascais {
    padding-top: 5rem;
  }
  .process .section-closer__link,
  .process .section-closer--minimal .section-closer__link {
    padding: 1.125rem 2rem;
    line-height: 1.5;
  }
}

/* =========================================================
   Hero — tighten the headline → subtitle seam, then nudge the
   whole subtitle slightly higher in the composition.
   Affects only .intro__guarantee (the "ONE TEAM…/ TWENTY-FIVE
   YEARS." subtitle), not the wordmark→headline gap and not the
   internal line-height between the two subtitle lines.
   ========================================================= */
body.page-home .intro__guarantee {
  margin-top: -1rem !important;
  position: relative;
  top: -0.5rem;
}
@media (max-width: 768px) {
  body.page-home .intro__guarantee {
    margin-top: -0.6rem !important;
    top: -0.3rem;
  }
}

/* =========================================================
   STUDIO PAGE — substance-arc taupe sections (§05–§07)
   §01–§03 stay on marble (body backsplash), §04 stays olive,
   §05–§07 join §08 and §09 in a continuous taupe arc through
   to the marble footer. §08 (.studio__credentials) and §09
   (.studio__letter) already paint taupe + hairline-top from
   the earlier task; this block adds the same treatment to
   §05–§07 plus the marble→taupe seam hairline at §05's top.
   ========================================================= */
body.page-studio .studio__work,
body.page-studio .studio__people,
body.page-studio .studio__details {
  background-color: var(--bone);
  background-image: none;
}
body.page-studio .studio__work {
  position: relative;
}
body.page-studio .studio__work::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: clamp(80px, 10vw, 120px);
  height: 1px;
  background: rgba(45, 41, 38, 0.22);
  pointer-events: none;
}

/* =========================================================
   STUDIO PAGE — extend taupe back to §02 + §03.
   .studio__intro contains both the "Cascais ever since"
   biography and the "studio is a house" spread (with the
   scene break between them) as sub-blocks of a single
   <section>. Painting .studio__intro taupe covers both at
   once. Hairline at its top marks the §01.5 marble → §02
   taupe transition. The scene-break div inside is
   transparent by default so the parent taupe shows through.
   ========================================================= */
body.page-studio .studio__intro {
  background-color: var(--bone);
  background-image: none;
  /* border-top removed — the .studio__opening hero's bottom feather
     handles the marble-to-cream handoff. Hairline border on top of
     the gradient was creating a visible 1px seam right under the fade. */
}

/* Align studio inner .wrap containers to the home page's actual
   --container width (1480px). Earlier .wrap default is 1240px,
   which made the studio sections read narrower than home. The
   .studio__letter .wrap--narrow override and the §04
   .studio__quote-spread (--container-narrow) keep their tighter
   widths because their specificity is higher. */
body.page-studio .wrap {
  max-width: var(--container);
}

/* §02 → §03 separator: enough to register a section change but
   not so much that the page feels paused. Roughly half the prior
   spacing — combined ~112–176px on desktop. */
.studio__intro-bio {
  padding-bottom: clamp(48px, 6vw, 80px);
}
.studio__intro-spread {
  position: relative;
  padding-top: clamp(64px, 8vw, 96px);
}
@media (max-width: 768px) {
  .studio__intro-bio {
    padding-bottom: clamp(40px, 6vw, 56px);
  }
  .studio__intro-spread {
    padding-top: clamp(48px, 8vw, 72px);
  }
}

/* === Studio pull quote — mirrors the home page .craft__quote treatment.
       Italic Cormorant body type, ochre 2px left border, blur-crystallise
       reveal on scroll-in via [data-studio-quote] (wired in js/main.js). === */
.studio__pullquote {
  margin: clamp(48px, 6vw, 88px) 0;
  padding: 4px 0 4px 18px;
  border-left: 2px solid var(--ochre);
  max-width: 56ch;
  text-align: left;
  filter: blur(10px);
  opacity: 0;
  transition: filter 1.2s var(--ease-out), opacity 1.2s var(--ease-out);
  will-change: filter, opacity;
}
.studio__pullquote.is-in {
  filter: blur(0);
  opacity: 1;
}
.studio__pullquote-text {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 300;
  font-size: clamp(17px, 1.4vw, 22px);
  line-height: 1.55;
  color: var(--ink);
  letter-spacing: -0.005em;
  margin: 0 0 6px 0;
}
.studio__pullquote-cite {
  display: block;
  margin-top: 6px;
  font-family: var(--sans);
  font-style: normal;
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mid);
}
@media (max-width: 900px) {
  .studio__pullquote {
    margin: clamp(40px, 6vw, 64px) 0;
  }
}

/* === §02 marginalia — editor's-note fact block below the portrait.
       Hairline-separated rows: Plex Mono small caps label on the
       left, italic Cormorant value on the right. === */
.studio__intro-marginalia {
  margin-top: 2.5rem;
  display: flex;
  flex-direction: column;
}
.marginalia-item {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.75rem 0;
  border-top: 1px solid rgba(45, 41, 38, 0.12);
}
.marginalia-item:last-child {
  border-bottom: 1px solid rgba(45, 41, 38, 0.12);
}
.marginalia-item__label {
  font-family: var(--mono);
  font-size: 0.65rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(45, 41, 38, 0.7);
}
.marginalia-item__value {
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--ink);
  text-align: right;
}
@media (max-width: 900px) {
  .studio__intro-marginalia {
    margin-top: 2rem;
    max-width: 360px;
    margin-left: auto;
    margin-right: auto;
  }
}

/* === Refined image caption — applies only to the §03 spread caption now;
       the §02 portrait caption is overlaid on the image (mirrors the home
       page .manifesto__portrait pattern) so it has its own rule above. === */
.studio__intro-spread-caption {
  margin-top: 1.25rem;
  padding-top: 0.875rem;
  border-top: 1px solid rgba(45, 41, 38, 0.2);
}

/* === Pull quote — hanging quotation marks. The opening curly quote
       absolutely positions to hang into the left margin so the first
       letter of "The" sits flush against the column edge — print-grade
       typographic detail. === */
.pull-quote p {
  position: relative;
}
.pull-quote__open-mark,
.pull-quote__close-mark {
  display: inline-block;
  color: rgba(45, 41, 38, 0.5);
  font-style: italic;
}
.pull-quote__open-mark {
  position: absolute;
  left: -0.6em;
  top: 0;
}
.pull-quote__close-mark {
  margin-left: 0.05em;
}
@media (max-width: 768px) {
  .pull-quote__open-mark {
    left: -0.4em;
  }
}

/* === Section ornament — thin hairline rule centred between sections.
       Was a typographic "— § —" glyph (Cormorant italic, faded ink),
       which the user found too decorative for a contemporary editorial
       feel. Now reads as a single low-opacity 1 px line. HTML markup
       (<div class="section-ornament">— § —</div>) stays untouched;
       font-size:0 + color:transparent neutralise the inner glyph so
       the wrapper renders only the hairline background. === */
.section-ornament {
  display: block;
  width: clamp(120px, 18vw, 220px);
  height: 1px;
  margin: clamp(48px, 6vw, 80px) auto;
  background: rgba(45, 41, 38, 0.18);
  border: 0;
  font-size: 0;
  line-height: 0;
  color: transparent;
  user-select: none;
}
@media (max-width: 768px) {
  .section-ornament {
    width: clamp(100px, 30vw, 160px);
    margin: clamp(36px, 8vw, 56px) auto;
  }
}

/* Section-divider hairline — same centred 1 px line as .section-ornament,
   but drawn as a ::before pseudo on sections that previously used a
   full-width border-top to separate themselves from the section above.
   The replaced selectors (.page-section + .page-section, .phase + .phase,
   etc.) all set position:relative so the pseudo can anchor to the
   section's top edge. */
.page-section + .page-section::before,
.portfolio__card--full + .portfolio__card--full::before,
.phase + .phase::before,
.local__detail--materials::before,
.local__detail--rules::before,
.contact-page__faq::before,
.contact-page__details::before,
.contact-page__letter::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  transform: translateX(-50%);
  width: clamp(120px, 18vw, 220px);
  height: 1px;
  background: rgba(45, 41, 38, 0.18);
  pointer-events: none;
}
@media (max-width: 768px) {
  .page-section + .page-section::before,
  .portfolio__card--full + .portfolio__card--full::before,
  .phase + .phase::before,
  .local__detail--materials::before,
  .local__detail--rules::before,
  .contact-page__faq::before,
  .contact-page__details::before,
  .contact-page__letter::before {
    width: clamp(100px, 30vw, 160px);
  }
}

/* === Section folios — small Plex Mono publication markers
       in the top-right corner of every major section. === */
.studio__opening,
.studio__intro,
.studio__intro-spread,
.studio__quote-band,
.studio__work,
.studio__people,
.studio__details,
.studio__credentials,
.studio__letter {
  position: relative;
}
.section-folio {
  position: absolute;
  top: 2rem;
  right: 2rem;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  color: rgba(45, 41, 38, 0.45);
  text-transform: uppercase;
  pointer-events: none;
  z-index: 5;
}
@media (max-width: 768px) {
  .section-folio {
    top: 1.5rem;
    right: 1.5rem;
    font-size: 0.65rem;
  }
}

/* =========================================================
   STUDIO §05 — Cinematic project slideshow.
   One large active card visible at a time; thumbnail strip
   below for direct navigation; position counter; CTA to the
   full archive at the bottom. JS in js/projects-slideshow.js
   toggles .studio__work-card--active and .studio__work-thumb--active.
   ========================================================= */
.studio__work-inner {
  max-width: 1200px;
  margin: 0 auto;
}
.studio__work-header {
  text-align: center;
  /* Trimmed twice now — was clamp(40, 5vw, 64), then clamp(20,
     2.6vw, 32). User asked for one more pass to pull the card
     closer under the "Maja's Selection." headline. */
  margin-bottom: clamp(10px, 1.4vw, 18px);
}
.studio__work-showcase {
  position: relative;
  margin-bottom: clamp(32px, 4vw, 48px);
}
/* Each card is a contained editorial still — full-card photo at
   3:2, project name + location overlaid at bottom-left on a soft
   dark gradient (manifesto-portrait pattern), glassy "Click to
   animate" hint pill at top-left (process-hint pattern). Sharp
   4 px corners, hairline border on the taupe section, layered
   ambient shadow (close + soft) so the card sits in a softly
   lit room rather than floating above the page. Active = visible,
   non-active = behind it absolutely. Cross-fades on swap. */
.studio__work-card {
  position: absolute;
  inset: 0 0 auto 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.45s ease, visibility 0s ease 0.45s;
  pointer-events: none;
  display: block;
  background: var(--bone);
  border: 1px solid rgba(45, 41, 38, 0.08);
  border-radius: 4px;
  overflow: hidden;
  box-shadow:
    0 1px 2px rgba(45, 41, 38, 0.04),
    0 40px 80px rgba(45, 41, 38, 0.08);
}
.studio__work-card--active {
  position: relative;
  opacity: 1;
  visibility: visible;
  transition: opacity 0.45s ease, visibility 0s ease 0s;
  pointer-events: auto;
}
.studio__work-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}
/* Legacy .studio__work-card-image (img-based) — kept inert so older
   markup wouldn't break; the active layout uses .studio__work-card-media. */
.studio__work-card-image { display: none; }
.studio__work-card-title {
  font-family: var(--serif);
  font-size: clamp(2rem, 3.5vw, 2.75rem);
  line-height: 1.15;
  font-weight: 400;
  color: var(--ink);
  margin: 0 0 0.5rem 0;
}
.studio__work-card-location {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: rgba(45, 41, 38, 0.7);
  text-transform: uppercase;
  margin: 0 0 1rem 0;
}
.studio__work-card-description {
  font-family: var(--serif);
  font-size: 17px;
  line-height: 1.6;
  color: rgba(45, 41, 38, 0.85);
  margin: 0;
}

/* Stage wrapper — three-column grid that frames the contained card
   between the two glassy arrows. Stage is capped just wider than the
   card so the arrows sit close to the card's edges, not floating
   in unrelated whitespace. Arrows align to the photo's vertical
   midpoint (not the card's overall midpoint) via align-self: start
   plus a margin-top tuned to the 3:2 photo aspect. */
.studio__work-stage {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(16px, 2.5vw, 32px);
  max-width: 1280px;
  /* Tightened twice — was clamp(40, 5vw, 64) on first rhythm
     pass, now further trimmed so the CTA pill sits even closer
     under the card. */
  margin: 0 auto clamp(16px, 2vw, 28px);
}
.studio__work-stage .studio__work-showcase {
  margin-bottom: 0;
  /* Card capped 9 % smaller than the previous 1100 px so it stops
     dominating the viewport. */
  max-width: min(1000px, calc(100vw - 8rem));
  margin-left: auto;
  margin-right: auto;
  width: 100%;
}
/* Full-card photo at 3:2 = card width × 0.667. At 1000 px max card →
   ~667 px tall. Showcase reserves at least that vertical space so the
   absolutely-positioned non-active cards don't collapse the layout. */
.studio__work-showcase {
  min-height: clamp(380px, 45vw, 667px);
}

/* Card trigger — the figure becomes a clickable button without
   chrome. data-project-trigger fires the before/after animation
   (wired in js/projects-slideshow.js, currently a no-op placeholder). */
.studio__work-card-trigger {
  display: block;
  width: 100%;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.studio__work-card-trigger:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}
.studio__work-card-trigger {
  display: block;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  -webkit-tap-highlight-color: transparent;
}
.studio__work-card-media {
  position: relative;
  width: 100%;
  /* Both aspect-ratio (modern) AND explicit min-height (fallback)
     so the media always has visible size regardless of how the
     <button> ancestor's containing-block semantics resolve. */
  aspect-ratio: 3 / 2;
  min-height: clamp(280px, 50vw, 733px);
  overflow: hidden;
  background: var(--bone-2);
  display: block;
}
.studio__work-card-video,
.studio__work-card-after,
.studio__work-card-before {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}
/* Before-state image starts hidden. When the visitor clicks the
   card, the .is-before-active class on .studio__work-card-media
   cross-dissolves the before image in for ~1.6 s, holds, then
   fades back out. If the before src is missing or empty, the
   click is a no-op and the after image continues to display. */
.studio__work-card-before {
  opacity: 0;
  pointer-events: none;
  transition: opacity 1.6s var(--ease-out);
  z-index: 2;
}
.studio__work-card-media.is-before-active .studio__work-card-before {
  opacity: 1;
}
.studio__work-card-video {
  transition: transform 0.8s var(--ease-out);
}
.studio__work-card-trigger:hover .studio__work-card-video {
  transform: scale(1.015);
}
/* Hide the hint pill while the transformation video plays so the
   morph is unobstructed. After the video ends, .is-revealed swaps
   the pill label from "Click to animate" → "Play again". */
.studio__work-card-media.is-playing .studio__work-card-hint {
  opacity: 0;
  transition: opacity 0.36s var(--ease-out);
}
/* Caption overlay — bottom-left of the photo, dark gradient
   backing, project name in white Cormorant + location in
   tracked-uppercase Plex Mono. Mirrors .manifesto__portrait
   figcaption pattern from home. */
.studio__work-card-caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: clamp(20px, 2.4vw, 32px);
  color: var(--bone);
  background: linear-gradient(
    180deg,
    rgba(20, 17, 14, 0) 0%,
    rgba(20, 17, 14, 0.55) 100%
  );
  z-index: 4;
  pointer-events: none;
}
.studio__work-card-caption .studio__work-card-title {
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(20px, 1.8vw, 28px);
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: var(--bone);
  margin: 0 0 0.35rem;
}
.studio__work-card-caption .studio__work-card-location {
  font-family: var(--mono);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.85);
  margin: 0;
}

/* Click-to-animate hint pill — top-left, glassy, mirrors the
   home page .process__hint pattern. Two label spans toggle
   visibility based on .is-revealed on the parent .studio__work-
   card-media: initial shows "Click to animate", once the visitor
   has triggered the before/after reveal the label switches to
   "Play again" and stays. */
/* Hint label — minimal pill outline on the corner of the video,
   matches the homepage .tile__hover-hint convention (text in a
   thin-bordered pill, no heavy gradient fill). Sits over the
   video, kept light so it doesn't read as a clunky CTA. */
.studio__work-card-hint {
  position: absolute;
  top: clamp(14px, 1.6vw, 22px);
  left: clamp(14px, 1.6vw, 22px);
  z-index: 5;
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid rgba(244, 239, 230, 0.45);
  background: transparent;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.88);
  pointer-events: none;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.4);
}
.studio__work-card-hint-label--initial { display: inline; }
/* After first reveal, the visitor has learned the affordance — hide
   the hint pill entirely. Clicking the tile restarts the animation
   without needing a "Play again" prompt. */
.studio__work-card-media.is-playing .studio__work-card-hint,
.studio__work-card-media.is-revealed .studio__work-card-hint {
  opacity: 0;
  transition: opacity 240ms var(--ease-out);
}

/* "What changed" overlay — mirrors home page .tile__solved. Fades in
   ONLY after the morph finishes (.is-revealed). Pairs with a video
   blur+dim so the screen-print copy reads cleanly against the frozen
   last frame of the transformation. */
.studio__work-card-solved {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: clamp(24px, 5%, 48px);
  padding-bottom: clamp(120px, 22%, 160px);
  z-index: 6;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 720ms 120ms var(--ease-out),
              transform 820ms 120ms var(--ease-out);
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(20, 17, 14, 0.42) 0%,
    rgba(20, 17, 14, 0.58) 60%,
    rgba(20, 17, 14, 0.72) 100%
  );
  text-align: center;
}
.studio__work-card-solved-text {
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(24px, 2.6vw, 42px);
  line-height: 1.3;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.96);
  max-width: 32ch;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.45);
  margin: 0 0 32px 0;
}
.studio__work-card-solved-detail {
  font-family: var(--sans);
  font-size: clamp(13px, 1.1vw, 16px);
  font-weight: 400;
  line-height: 1.6;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.78);
  max-width: 52ch;
  margin: 0;
}
/* Reveal cascade — video blurs + dims, solved overlay fades in,
   bottom-left caption fades out so the centred overlay carries the
   storytelling. Hint pill swap is handled higher up via the
   .is-revealed --initial/--replay rules. */
.studio__work-card-media .studio__work-card-video {
  transition: filter 480ms var(--ease-out), transform 0.8s var(--ease-out);
}
.studio__work-card-media.is-revealed .studio__work-card-video {
  filter: blur(6px) brightness(0.55);
}
.studio__work-card-media.is-revealed .studio__work-card-solved {
  opacity: 1;
  transform: translateY(0);
}
.studio__work-card-caption {
  transition: opacity 320ms var(--ease-out);
}
.studio__work-card-media.is-revealed .studio__work-card-caption {
  opacity: 0;
}

/* View Project pill — anchored bottom-centre of the card, sibling of
   the trigger button so it's its own click target (you can't nest
   <a> inside <button>). Mirrors home page .tile__view glassy pill.
   Visibility gated by .is-revealed on the parent .studio__work-card. */
.studio__work-card-view {
  position: absolute;
  left: 50%;
  bottom: clamp(28px, 4%, 56px);
  transform: translate3d(-50%, 8px, 0);
  z-index: 7;

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 12px 24px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  border-radius: 999px;

  color: var(--ink);
  /* Canonical pill colour — glassy translucent. Bumped from the
     standard 0.32/0.16 alphas to 0.72/0.5 because this pill sits
     OVER a dimmed photo (the card's revealed state has a dark
     overlay); the standard low-alpha glass lets too much of that
     dimness bleed through and the pill reads as a dark muddy
     blob. Same hue + gradient direction as every other button on
     the site, just opaque enough to keep its identity over a
     dark image background. */
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.72) 0%,
    rgba(255, 255, 255, 0.5) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  border: 1px solid rgba(255, 255, 255, 0.6);
  box-shadow:
    0  8px 32px rgba(0, 0, 0, 0.08),
    0  2px  6px rgba(0, 0, 0, 0.04),
    inset 0  1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);

  opacity: 0;
  pointer-events: none;
  transition: opacity 360ms 320ms var(--ease-out),
              transform 360ms 320ms var(--ease-out);
}
.studio__work-card-view svg {
  width: 12px;
  height: 12px;
  transition: transform 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.studio__work-card.is-revealed .studio__work-card-view {
  opacity: 1;
  pointer-events: auto;
  transform: translate3d(-50%, 0, 0);
}
.studio__work-card.is-revealed .studio__work-card-view:hover svg,
.studio__work-card.is-revealed .studio__work-card-view:focus-visible svg {
  transform: translateX(3px);
}
@media (max-width: 700px) {
  .studio__work-card-view {
    bottom: clamp(20px, 5%, 36px);
    padding: 10px 20px;
    font-size: 10px;
  }
}

/* Glassy chevron arrows — clearly clickable at 56px, same frosted
   treatment as the floating-nav pill. Sit in the stage's outer
   columns just outside the card's left/right edges. */
/* §05 scroll-progress dots — six small dots below the card stage
   showing which project is active. Sits between the stage and the
   "View all projects" section-closer. Click any dot to jump to
   that project (wired in js/projects-slideshow.js). */
.studio__work-dots {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin: clamp(16px, 2vw, 28px) 0 0;
}
.studio__work-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 0;
  padding: 0;
  background: rgba(45, 41, 38, 0.22);
  cursor: pointer;
  transition: background 0.3s ease, transform 0.3s ease;
}
.studio__work-dot:hover {
  background: rgba(45, 41, 38, 0.45);
  transform: scale(1.15);
}
.studio__work-dot.is-active {
  background: rgba(45, 41, 38, 0.85);
}
.studio__work-dot:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

.studio__work-arrow {
  width: 56px;
  height: 56px;
  border-radius: 9999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: var(--ink);
  background: linear-gradient(
    135deg,
    rgba(255, 255, 255, 0.36) 0%,
    rgba(255, 255, 255, 0.18) 100%
  );
  backdrop-filter: blur(24px) saturate(1.25);
  -webkit-backdrop-filter: blur(24px) saturate(1.25);
  border: 1px solid rgba(255, 255, 255, 0.48);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.08),
    0 2px 6px rgba(0, 0, 0, 0.04),
    inset 0 1px 0 rgba(255, 255, 255, 0.6),
    inset 0 -1px 0 rgba(0, 0, 0, 0.03);
  opacity: 0.85;
  transition: opacity 0.25s ease, transform 0.25s ease, box-shadow 0.25s ease;
  /* Landscape card: photo and text columns share the same height,
     so the card's vertical midpoint == the photo's vertical midpoint.
     Stage's align-items: center handles arrow alignment cleanly. */
  align-self: center;
}
.studio__work-arrow:hover,
.studio__work-arrow:focus-visible {
  opacity: 1;
  transform: scale(1.05);
  box-shadow:
    0 12px 32px rgba(0, 0, 0, 0.10),
    0 3px 8px rgba(0, 0, 0, 0.05),
    inset 0 1px 0 rgba(255, 255, 255, 0.7),
    inset 0 -1px 0 rgba(0, 0, 0, 0.04);
  outline: none;
}
.studio__work-arrow svg {
  width: 18px;
  height: 18px;
}

/* (.studio__work-cta-button retired — §05 "View All Projects" pill
   replaced by the .section-closer arrow-link pattern used elsewhere
   for section-to-section navigation. Keeps canonical pill button
   style reserved for nav-cta + contact section closers per user
   directive.) */
.studio__work-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
}

@media (max-width: 768px) {
  /* Mobile: identical pattern to the homepage Six Homes carousel.
     Card stacks above; controls bar below has prev / counter / next
     in a 1fr auto 1fr grid so arrows pin to left/right edges and the
     counter sits centred between them. */
  .studio__work-stage {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    grid-template-rows: auto auto;
    align-items: center;
    gap: clamp(16px, 2.5vw, 24px) clamp(20px, 3vw, 32px);
  }
  .studio__work-stage .studio__work-showcase {
    grid-row: 1;
    grid-column: 1 / -1;
    max-width: 100%;
    width: 100%;
    min-height: 0;
  }
  .studio__work-card-media {
    min-height: 0;
  }
  .studio__work-arrow {
    width: 44px;
    height: 44px;
    align-self: auto;
    opacity: 1;
  }
  .studio__work-arrow svg {
    width: 16px;
    height: 16px;
  }
  .studio__work-arrow--prev {
    grid-row: 2;
    grid-column: 1;
    justify-self: start;
  }
  .studio__work-arrow--next {
    grid-row: 2;
    grid-column: 3;
    justify-self: end;
  }
  /* Counter moves INTO the stage as a 3rd grid item between the arrows. */
  .studio__work-counter {
    display: block;
    grid-row: 2;
    grid-column: 2;
    margin: 0;
    text-align: center;
  }
  /* Hide the dots on mobile — counter is the position indicator now. */
  .studio__work-dots {
    display: none;
  }
}

/* =========================================================
   FORCE SECTIONS TRANSPARENT — let body linen show through.
   The home / projects / services / process / local / journal /
   contact pages have section-level rules that paint solid
   var(--bone) (e.g. .manifesto, .method, .craft, .process,
   .cascais, .contact, .services, .services__feature, etc.) —
   those rules cover the body linen entirely. This override
   nukes every non-hero, non-footer section on those pages so
   the linen shows. Studio is intentionally excluded so its
   own rhythm stays intact. The hero (first <section> in main)
   keeps its marble override; the footer keeps its marble too.
   ========================================================= */
body.page-home main > section:not(.intro),
body.page-projects main > section:not(:first-of-type),
body.page-services main > section:not(:first-of-type),
body.page-process main > section:not(:first-of-type),
body.page-local main > section:not(:first-of-type),
body.page-journal main > section:not(:first-of-type),
body.page-contact main > section:not(:first-of-type) {
  background-color: transparent !important;
  background-image: none !important;
}

/* Chapter sections on /services/ paint themselves transparent
   except where they declare a deliberate background (e.g. the
   Maya's Care announcement uses var(--paper)). Keep that intent
   intact — the announcement chapter SHOULD override the taupe
   body, so do not blanket-force chapters transparent here. */


/* Language Toggle */
.nav-lang-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-family: var(--font-mono);
  font-size: 13px;
  text-transform: uppercase;
  color: var(--mid);
  margin-right: 0.5rem;
}
.nav-lang-toggle a {
  color: var(--mid);
  text-decoration: none;
  transition: color 0.25s ease;
}
.nav-lang-toggle a:hover,
.nav-lang-toggle a.is-active {
  color: var(--ink);
}
.nav-lang-toggle span {
  opacity: 0.4;
}

.nav-drawer__lang {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--mid);
  margin-bottom: 2rem;
}
.nav-drawer__lang a {
  color: var(--mid);
  text-decoration: none;
}
.nav-drawer__lang a.is-active {
  color: var(--ink);
}
