/* ==========================================================================
   LHC — Luxury Hospitality Consultancy
   Brand: Concept 2 (Lou & You)
   ========================================================================== */

@font-face {
  font-family: 'Canela';
  src: url('../assets/fonts/Canela-Light.otf') format('opentype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Riviera Nights';
  src: url('../assets/fonts/RivieraNights-Light.otf') format('opentype');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Riviera Nights';
  src: url('../assets/fonts/RivieraNights-Regular.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Penumbra HalfSerif';
  src: url('../assets/fonts/PenumbraHalfSerifStd-Reg.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  /* ────────────────────────────────────────────────────────────────────
     DESIGN TOKENS
     Single source of truth. Components reference these — never hardcode.
     Media queries are for layout flips only (row → column, hide, reorder).
     Type and spacing scale fluidly via clamp() so they don't need MQ overrides.
     ──────────────────────────────────────────────────────────────────── */

  /* Color */
  --brown: #4D3B37;
  --sand: #EAE6DB;        /* page background — neutral warm */
  --cream: #F2EEE2;       /* paper — half-shade warmer for type on dark */
  --blue: #8B93A6;
  --ink: #2A211F;
  --cornflower: #6B7FB8;  /* accent — focus rings, hover details */

  /* Typography — font families */
  --font-display: 'Canela', 'Times New Roman', serif;
  --font-serif: 'Penumbra HalfSerif', 'Times New Roman', serif;
  --font-body: 'Riviera Nights', Georgia, serif;

  /* Typography — fluid type ladder.
     Each token: clamp(mobile-min, fluid-formula, desktop-max).
     One ladder for the whole site; components reference these, never
     hardcode their own clamp(). Recalibrated 2026-05 to match what's
     actually rendered (see CLAUDE.md "design-led, not CSS-led"). */
  --type-display: clamp(44px, 4.5vw + 18px, 96px);  /* final-CTA "Let's begin" — single use */
  --type-h1:      clamp(36px, 2.4vw + 20px, 64px);  /* hero, page titles, journal masthead, footer statement, big numerals */
  --type-h2:      clamp(28px, 1.6vw + 14px, 48px);  /* manifesto, section titles, large case titles */
  --type-h3:      clamp(22px, 0.8vw + 16px, 32px);  /* card titles, small section heads */
  --type-sub:     clamp(20px, 1vw + 14px, 28px);    /* hero sub, lead copy under titles */
  --type-body:    clamp(15px, 0.3vw + 14px, 17px);  /* paragraphs */
  --type-eyebrow: clamp(11px, 0.1vw + 10.5px, 13px);/* uppercase labels, card meta */
  --type-meta:    11px;                             /* legal / footer meta */

  /* Spacing scale — fluid where it makes sense, fixed at the small end. */
  --space-xxs: 4px;
  --space-xs:  8px;
  --space-sm:  16px;
  --space-md:  clamp(20px, 1.6vw, 28px);
  --space-lg:  clamp(32px, 3vw, 48px);
  --space-xl:  clamp(56px, 6vw, 80px);
  --space-2xl: clamp(80px, 10vw, 140px);
  --space-3xl: clamp(120px, 15vw, 200px);

  /* Layout — single page-edge gutter for the entire site. 16px floor
     on smallest phones gives the content room to breathe, scales via
     5vw to 96px max on full desktop. Hero, manifesto, testimonial,
     teaser, case-study text and footer all sit on the same vertical
     line at every viewport. Single source of truth — never override
     gutter at the component level. */
  --max-w: 1440px;
  --gutter: clamp(16px, 5vw, 96px);
}

* { box-sizing: border-box; }

/* Riviera Nights only loads Light + Regular and Canela only Light.
   Disabling synthesis prevents the browser from faking bolder weights
   when CSS or default <strong>/<b> rules request 500–900, which would
   otherwise render as chunky synthetic bold. */
html { font-synthesis: none; }

/* Global focus ring — cornflower hairline offset 4px from the
   element. Replaces the default browser blue focus ring (which read
   as a chrome-style affordance against the brand) with a brand-coherent
   accent. `:focus-visible` only fires for keyboard navigation, so
   mouse clicks don't trigger it. Specific components (the dark-bg
   nav, the form underline inputs, the triad pillar) opt out below
   with their own focus styles. */
:focus-visible {
  outline: 1px solid var(--cornflower);
  outline-offset: 4px;
  border-radius: 2px;
}

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

/* Anchored section targets sit clear of the 72px sticky nav. Applied to
   the services-page approach sections so deep-links from the homepage land
   with the heading visible, not tucked under the nav. */
.services-page .case-study__section[id] {
  scroll-margin-top: clamp(72px, 8vw, 110px);
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--sand);
  color: var(--brown);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.625;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body.menu-open { overflow: hidden; }

/* --------------------------------------------------------------------------
   Menu panel — full-viewport sand overlay that reveals via a diagonal
   clip-path sweep from top-left. Content sits at full size throughout;
   only the mask grows.
   -------------------------------------------------------------------------- */
/* Menu panel — full-screen brown overlay revealing on burger toggle.
   Asymmetric editorial layout: close (TL), monogram (TC), CTA (TR),
   left-anchored nav body, footer meta band along the bottom. */
.menu-panel {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--brown);
  color: var(--cream);
  /* Diagonal sweep from top-left. easeInOutQuart curve for a more
     deliberate S-shape than the default ease. */
  clip-path: inset(0 100% 100% 0);
  transition: clip-path 0.75s cubic-bezier(0.76, 0, 0.24, 1);
  pointer-events: none;
}
.menu-panel.is-open {
  clip-path: inset(0 0 0 0);
  pointer-events: auto;
}

/* Inner items start hidden + slightly offset. They fade + slide up
   once the panel has mostly revealed (staggered delays), so the
   background grows first and the contents settle into it. */
.menu-panel__close,
.menu-panel__cta,
.menu-panel__eyebrow,
.menu-panel__links li,
.menu-panel__footer > * {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.3s ease,
    transform 0.3s ease;
}
.menu-panel__mark {
  opacity: 0;
  transform: translate(-50%, 18px);
  transition:
    opacity 0.3s ease,
    transform 0.3s ease;
}
.menu-panel.is-open .menu-panel__close,
.menu-panel.is-open .menu-panel__cta,
.menu-panel.is-open .menu-panel__eyebrow,
.menu-panel.is-open .menu-panel__links li,
.menu-panel.is-open .menu-panel__footer > * {
  opacity: 1;
  transform: translateY(0);
  transition:
    opacity 0.9s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 0.9s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.menu-panel.is-open .menu-panel__mark {
  opacity: 1;
  transform: translate(-50%, 0);
  transition:
    opacity 0.8s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 0.8s cubic-bezier(0.25, 0.1, 0.25, 1);
  transition-delay: 0.3s;
}
.menu-panel.is-open .menu-panel__close { transition-delay: 0.25s; }
.menu-panel.is-open .menu-panel__cta { transition-delay: 0.80s; }
.menu-panel.is-open .menu-panel__eyebrow { transition-delay: 0.38s; }
.menu-panel.is-open .menu-panel__links li:nth-child(1) { transition-delay: 0.45s; }
.menu-panel.is-open .menu-panel__links li:nth-child(2) { transition-delay: 0.52s; }
.menu-panel.is-open .menu-panel__links li:nth-child(3) { transition-delay: 0.59s; }
.menu-panel.is-open .menu-panel__links li:nth-child(4) { transition-delay: 0.66s; }
.menu-panel.is-open .menu-panel__links li:nth-child(5) { transition-delay: 0.73s; }
.menu-panel.is-open .menu-panel__footer > *:nth-child(1) { transition-delay: 0.88s; }
.menu-panel.is-open .menu-panel__footer > *:nth-child(2) { transition-delay: 0.93s; }
.menu-panel.is-open .menu-panel__footer > *:nth-child(3) { transition-delay: 0.98s; }

.menu-panel__close {
  position: absolute;
  top: clamp(28px, 3.2vw, 45px);
  left: var(--gutter);
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--cream);
  font-family: var(--font-serif);
  font-size: 13px;
  letter-spacing: 0.55px;
  text-transform: uppercase;
  padding: 0;
  /* Match CTA pill height + vertical alignment so the top-row trio
     (Close · monogram · CTA) sits on the same optical baseline. */
  height: 40px;
}
.menu-panel__close:hover { opacity: 0.65; }
.menu-panel__close svg { width: 16px; height: 16px; }
.menu-panel__close svg line { stroke-width: 1; }

.menu-panel__mark {
  position: absolute;
  top: clamp(28px, 3.2vw, 40px);
  left: 50%;
  display: block;
}
.menu-panel__mark img {
  height: clamp(44px, 5vw, 68px);
  width: auto;
  display: block;
}

.menu-panel__cta {
  position: absolute;
  top: clamp(28px, 3.2vw, 45px);
  right: var(--gutter);
}

/* Body — left-aligned column with eyebrow above link list, vertically
   centered. Page gutter matches the case-study left inset so the
   menu reads as continuous with the rest of the site. */
.menu-panel__body {
  position: absolute;
  top: 50%;
  left: clamp(40px, 5vw, 88px);
  right: clamp(40px, 5vw, 88px);
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.4vw, 32px);
}
.menu-panel__eyebrow {
  color: var(--cream);
  opacity: 0.55;
  margin: 0;
}
.menu-panel__links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 0.6vw, 10px);
}
/* Menu nav links — special editorial register larger than --type-h1.
   Intentionally outside the type ladder: this is the asymmetric overlay
   typography moment, not the body heading hierarchy. */
.menu-panel__links a {
  display: inline-block;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(36px, 5.6vw, 76px);
  line-height: 1.05;
  color: var(--cream);
  text-decoration: none;
  transition: opacity 0.3s ease;
}
.menu-panel__links a:hover { opacity: 0.55; }
/* The link itself is the data-words target — make sure the word mask
   sits on a baseline that doesn't clip the descender. */
.menu-panel__links a[data-words] .word { overflow: hidden; padding-bottom: 0.06em; }

/* Footer — meta + email + social spread along the bottom edge.
   Reads as a business-card footer treatment. */
.menu-panel__footer {
  position: absolute;
  bottom: clamp(28px, 3.2vw, 45px);
  left: clamp(40px, 5vw, 88px);
  right: clamp(40px, 5vw, 88px);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: clamp(16px, 3vw, 48px);
}
.menu-panel__footer > :nth-child(1) { justify-self: start; }
.menu-panel__footer > :nth-child(2) { justify-self: center; }
.menu-panel__footer > :nth-child(3) { justify-self: end; }
.menu-panel__meta {
  color: var(--cream);
  opacity: 0.55;
  margin: 0;
  white-space: nowrap;
}
.menu-panel__email {
  color: var(--cream);
  font-family: var(--font-serif);
  font-size: clamp(13px, 1vw, 15px);
  letter-spacing: 0;
  text-decoration: none;
  opacity: 0.85;
  transition: opacity 0.3s ease;
  white-space: nowrap;
}
.menu-panel__email:hover { opacity: 1; }
.menu-panel__social {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 18px;
}
.menu-panel__social a {
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0.55px;
  text-transform: uppercase;
  text-decoration: none;
  opacity: 0.55;
  transition: opacity 0.3s ease;
}
.menu-panel__social a:hover { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .menu-panel { transition-duration: 0.2s; }
}

/* Mobile — switch the panel to a flex column flow so the CTA can sit
   under the link list (designer feedback: the top-right CTA was
   clashing with the centered monogram on narrow screens). Close + mark
   stay absolute in the corners; body / cta / footer stack in flow. */
@media (max-width: 768px) {
  .menu-panel {
    display: flex;
    flex-direction: column;
    padding: 80px clamp(32px, 7vw, 48px) clamp(28px, 6vw, 45px);
  }
  /* Mobile CTA is 48px tall, match the Close button so they stay
     aligned on a shared optical baseline. */
  .menu-panel__close {
    height: 48px;
  }
  .menu-panel__body {
    position: static;
    transform: none;
    top: auto;
    left: auto;
    right: auto;
    order: 1;
    margin: auto 0 0;
  }
  .menu-panel__cta {
    position: static;
    top: auto;
    right: auto;
    order: 2;
    align-self: flex-start;
    margin-top: clamp(24px, 4vw, 36px);
  }
  .menu-panel__footer {
    position: static;
    left: auto;
    right: auto;
    bottom: auto;
    order: 3;
    margin-top: auto;
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .menu-panel__footer > :nth-child(1),
  .menu-panel__footer > :nth-child(2),
  .menu-panel__footer > :nth-child(3) { justify-self: start; }
}
@media (max-width: 480px) {
  .menu-panel__close span { display: none; }
}

a { color: inherit; text-decoration: none; }
img { display: block; max-width: 100%; }

/* Marginalia — editorial running label fixed to the left page gutter,
   reading top-to-bottom. JS swaps the text + theme per visible section
   via IntersectionObserver. Two themes: --dark (cream on dark surface)
   and --light (brown on light surface). */
.marginalia {
  position: fixed;
  left: clamp(10px, 1.1vw, 18px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 1.6px;
  text-transform: uppercase;
  color: var(--cream);
  pointer-events: none;
  white-space: nowrap;
  writing-mode: vertical-rl;
  text-orientation: sideways;
  opacity: 0;
  transition: opacity 0.5s ease, color 0.18s ease;
}
.marginalia.is-visible { opacity: 0.85; }
.marginalia.marginalia--light { color: var(--brown); }
.marginalia.marginalia--dark  { color: var(--cream); }
/* Hide on tablet and below — no spare gutter to live in. */
@media (max-width: 1024px) {
  .marginalia { display: none; }
}

/* --------------------------------------------------------------------------
   Type utility classes — these appear in HTML markup (e.g. "entry-card__title
   h1") and reference the same fluid type ladder as semantic component rules.
   Naming is legacy from the Figma design file: .h1 here is a small serif
   card title, .h3 is a body-sub. Don't conflate with the --type-* ladder.
   -------------------------------------------------------------------------- */
.h1 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--type-h3);
  line-height: 1.3;
  letter-spacing: 0;
  margin: 0;
}
.h2 {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: normal;
  letter-spacing: 0;
  margin: 0;
}
.h3 {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  line-height: 1.33;
  margin: 0;
}
.h4 {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  line-height: 1.5;
  margin: 0;
}
.eyebrow {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--type-eyebrow);
  /* Em-based tracking (~1.76px at 11px) — opens the caps to a luxury
     register. Was 0.65px which read as functional/sans-default. */
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0;
}
/* Display eyebrow — for use above hero/page-opener H1 lockups. Sits
   slightly larger and more open so it reads as a *deck* mark, not the
   same pico-cap as a card meta line. Apply via `class="eyebrow eyebrow--display"`. */
.eyebrow--display {
  font-size: clamp(12px, 0.15vw + 11.4px, 14px);
  letter-spacing: 0.22em;
}
.body {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--type-body);
  line-height: 1.625;
}

/* --------------------------------------------------------------------------
   Primary CTA — global Aura baseline (see ~/.claude/CLAUDE.md)
   -------------------------------------------------------------------------- */
.cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 154px;
  height: 40px;
  padding: 0 24px;
  font-family: var(--font-body);
  font-size: 11px;
  font-style: normal;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0.55px;
  text-transform: uppercase;
  border-radius: 200px;
  background: var(--cream);
  color: var(--brown);
  border: none;
  cursor: pointer;
  transition: background 0.3s ease;
  white-space: nowrap;
}
.cta:hover { background: #FFF5E2; }
/* Mobile: keep CTA at the same 40px height as desktop — a 48px pill
   reads as oversized against phone-sized type. Touch hit-area still
   extends slightly via padding. Drop min-width so the pill hugs
   the label rather than padding out to 154px. */
@media (max-width: 768px) {
  .cta {
    min-width: 0;
    padding: 0 22px;
  }
}

.cta--ghost {
  background: rgba(234, 230, 219, 0.12);
  color: var(--cream);
}
.cta--ghost:hover { background: rgba(234, 230, 219, 0.22); }

.cta--outline {
  background: transparent;
  color: var(--cream);
  border: 1px solid var(--cream);
}
.cta--outline:hover {
  background: rgba(234, 230, 219, 0.12);
}

/* Outline on light backgrounds — brown border + brown text */
.cta--outline-dark {
  background: transparent;
  color: var(--brown);
  border: 1px solid var(--brown);
}
.cta--outline-dark:hover {
  background: rgba(77, 59, 55, 0.06);
}

/* --------------------------------------------------------------------------
   Layout
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--max-w);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

/* --------------------------------------------------------------------------
   Site nav — sits over the hero
   -------------------------------------------------------------------------- */
.site-nav {
  --nav-height: 138px;
  --nav-logo-height: 48px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  height: var(--nav-height);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  /* Anchored to --gutter so burger + "contact" line up with the page
     grid (section copy, footer, hero content all share this edge). */
  padding: 0 var(--gutter);
  color: var(--cream);
}

.site-nav__menu,
.site-nav__contact {
  font-family: var(--font-serif);
  font-size: 13px;
  font-style: normal;
  font-weight: 400;
  line-height: normal;
  letter-spacing: 0.5px;
  color: var(--cream);
  text-align: center;
  text-transform: lowercase;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0 0 8px;
  align-self: start;
  /* align text top with top edge of logo: (nav height − logo height) / 2 */
  margin-top: calc((var(--nav-height) - var(--nav-logo-height)) / 2);
  min-height: 44px;
  display: inline-flex;
  align-items: flex-start;
}
.site-nav__contact { justify-self: end; }

/* Burger icon replaces MENU text. Top-align the SVG so it sits at
   the same optical baseline as the "contact" text on the right edge,
   not vertically centered in the 44px tap area below it. */
.site-nav__menu {
  justify-self: start;
  padding: 0;
  display: inline-flex;
  align-items: flex-start;
  padding-top: 4px;
  color: var(--cream);
  transition: opacity 0.3s ease;
}
.site-nav__menu:hover { opacity: 0.7; }
.site-nav__burger { display: block; }

/* Inverted variant — used over light page backgrounds (legal pages).
   Swaps cream text + burger to brown so the nav reads cleanly on sand
   instead of vanishing. The cream wordmark is swapped to the brown
   variant in the page HTML alongside this. */
.site-nav--inverted,
.site-nav--inverted .site-nav__menu,
.site-nav--inverted .site-nav__contact { color: var(--brown); }

/* --------------------------------------------------------------------------
   Sticky nav — appears after the hero. Hidden above the viewport by default
   via transform; body.scrolled-past-hero brings it in; body.nav-hidden
   tucks it away when scrolling down (and back on scroll up).
   -------------------------------------------------------------------------- */
.site-nav-sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  height: 72px;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  /* Match the absolute nav offset above — both anchor to --gutter. */
  padding: 0 var(--gutter);
  background: rgba(234, 230, 219, 0.88);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid rgba(77, 59, 55, 0.08);
  color: var(--brown);
  transform: translateY(-100%);
  transition: transform 0.5s cubic-bezier(0.25, 0.1, 0.25, 1);
  will-change: transform;
}
body.scrolled-past-hero .site-nav-sticky { transform: translateY(0); }
body.scrolled-past-hero.nav-hidden .site-nav-sticky { transform: translateY(-100%); }

.site-nav-sticky__menu {
  justify-self: start;
  padding: 0;
  display: inline-flex;
  align-items: center;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--brown);
  transition: opacity 0.3s ease;
  min-width: 44px;
  min-height: 44px;
}
.site-nav-sticky__menu:hover { opacity: 0.6; }

.site-nav-sticky__logo { justify-self: center; display: block; }
.site-nav-sticky__logo img { height: 32px; width: auto; display: block; }

.site-nav-sticky__contact {
  justify-self: end;
  font-family: var(--font-serif);
  font-size: 13px;
  letter-spacing: 0.5px;
  color: var(--brown);
  text-transform: lowercase;
  text-decoration: none;
  transition: opacity 0.3s ease;
}
.site-nav-sticky__contact:hover { opacity: 0.6; }

.site-nav__logo {
  justify-self: center;
  display: block;
}
.site-nav__logo img {
  height: var(--nav-logo-height);
  width: auto;
}

/* Mobile nav — drop the tall desktop chrome down to a sensible height
   and shrink the logo. CSS vars on .site-nav cascade through the menu /
   contact margin-top calc, so alignment stays correct. */
@media (max-width: 768px) {
  .site-nav {
    --nav-height: 88px;
    --nav-logo-height: 36px;
  }
  .site-nav__menu,
  .site-nav__contact {
    /* 44px tap target without disturbing visual top-alignment */
    min-width: 44px;
    padding: 0 6px 8px;
  }
}

/* --------------------------------------------------------------------------
   01_Hero — scroll-driven shrink.
   Image starts edge-to-edge; as the user scrolls, it shrinks into its
   designed box (11.6% horizontal inset, ~13.3% top/bottom). Title stays
   overlaid at the Figma position throughout.

   --hero-progress is a CSS custom property (0 → 1) driven by JS.
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--brown);
  color: var(--cream);
  height: 180vh;                  /* extra viewport gives scroll room */
  /* --hero-ease is set directly by JS (easeInOutCubic applied to a
     lerp-smoothed scroll progress — buttery feel without extra libs). */
  --hero-ease: 0;
}

.hero__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
}

.hero__image {
  position: absolute;
  /* Scroll-driven shrink — inset grows from 0 to ~13% of the viewport
     as you scroll, parking the hero into a smaller framed image above
     the manifesto. JS drives --hero-ease (0 → 1) based on scroll
     position; the calc() turns that into the corresponding inset.
     Disabled on mobile via the @media (max-width: 768px) override
     below — the effect fights mobile Safari's URL-bar collapse and
     the phone-sized viewport doesn't have room for the parked frame. */
  inset:
    calc(var(--hero-ease) * 13.48%)
    calc(var(--hero-ease) * 11.63%)
    calc(var(--hero-ease) * 13.09%)
    calc(var(--hero-ease) * 11.63%);
  overflow: hidden;
  will-change: inset;
}
.hero__image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 70%;
}
/* Soft black overlay so cream text reads cleanly. Stronger in the
   vertical center where the copy sits, softer at the top and bottom. */
.hero__image::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.14) 0%,
    rgba(0, 0, 0, 0.38) 45%,
    rgba(0, 0, 0, 0.38) 65%,
    rgba(0, 0, 0, 0.18) 100%
  );
  pointer-events: none;
}
/* Contact hero — heavier scrim because the sun in the desert image
   sits dead-centre top behind the cream title. */
.contact-page .hero__image::after {
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.28) 0%,
    rgba(0, 0, 0, 0.5) 45%,
    rgba(0, 0, 0, 0.45) 65%,
    rgba(0, 0, 0, 0.22) 100%
  );
}
/* Who We Are — Heckfield exterior at sunset is detail-rich (lavender,
   building, sky, lit windows directly behind the title). Black scrim
   in a narrow band where the title sits, darker than the homepage
   default to push through the busy roofline. Top and bottom stay
   transparent so the architecture and lavender field still read. */
.about-page .hero__image::after {
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.45) 0%,
    rgba(0, 0, 0, 0.55) 22%,
    rgba(0, 0, 0, 0.7) 42%,
    rgba(0, 0, 0, 0.7) 60%,
    transparent 82%,
    transparent 100%
  );
}
/* Home hero — portrait interior shot (chess board + vase top, kilim
   bottom). object-position biases the visible window toward the top
   so the editorial elements stay in frame. */
.home-page .hero__image img {
  object-position: center 25%;
}
/* Home hero — narrow scrim band concentrated where the title sits.
   Top and bottom of the frame stay clean (so the chess board + rug
   read cleanly) while the centre is darkened just enough for the
   cream title to read against the warm interior tones. */
.home-page .hero__image::after {
  background: linear-gradient(
    to bottom,
    transparent 0%,
    transparent 25%,
    rgba(0, 0, 0, 0.32) 45%,
    rgba(0, 0, 0, 0.36) 60%,
    transparent 82%,
    transparent 100%
  );
}
/* Airelles hero — slightly darker scrim because the maison image is
   bright and pale; cream text needs a touch more contrast here. */
.airelles-page .hero__image::after {
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.18) 0%,
    rgba(0, 0, 0, 0.5) 45%,
    rgba(0, 0, 0, 0.5) 65%,
    rgba(0, 0, 0, 0.22) 100%
  );
}
/* Airelles CTA banner — brand brown wash (replaces the case-study blue
   default), keeps the case study on-brand. */
.airelles-page .case-study__cta { background: var(--brown); }
.airelles-page .case-study__cta-overlay {
  background: linear-gradient(
    to right,
    var(--brown) 0%,
    var(--brown) 25%,
    rgba(77, 59, 55, 0.7) 50%,
    rgba(77, 59, 55, 0) 80%
  );
}
.airelles-page .case-study__section:last-of-type::after {
  background: linear-gradient(to bottom, transparent, var(--brown));
}
/* CTA banner image — biased toward the building band (middle/lower of
   image) so we see the church + waterfront, less sky. Higher Y values
   push the visible slice DOWN the image. */
.airelles-page .case-study__cta-media img {
  object-position: 50% 55%;
}
/* Widen the copy block so "Let's start the conversation." stays on one
   line at desktop. Mobile still wraps via the section's own padding. */
.airelles-page .case-study__cta-copy {
  max-width: 600px;
}

.hero__copy {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: min(1120px, 100%);
  padding: 0 var(--gutter);
  text-align: center;
  z-index: 2;
}
.hero__eyebrow {
  color: var(--cream);
  opacity: 0.7;
  margin: 0 auto var(--space-md);
  text-align: center;
}
.hero__title {
  color: var(--cream);
  margin: 0;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.05;
  letter-spacing: -0.005em;
}
/* Dateline — masthead metadata under the hero sub: typically
   "Location · Disciplines" on case studies. Reads as the editorial
   credentialing line that anchors the title (think magazine cover
   "Issue 04 · Spring 2024"). Quieter than the eyebrow above the
   title to keep the lockup hierarchy: eyebrow → title → sub →
   dateline. Wraps cleanly on phone via the max-width + center align. */
.hero__dateline {
  color: var(--cream);
  margin: clamp(20px, 2.4vw, 32px) auto 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  text-align: center;
  opacity: 0.55;
  max-width: 720px;
}
.hero__sub {
  color: var(--cream);
  margin: var(--space-sm) auto 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  line-height: 1.2;
  letter-spacing: 0;
  text-align: center;
  max-width: 620px;
  text-transform: none;
}
.hero__cta {
  margin-top: var(--space-md);
}
.hero__body {
  color: var(--cream);
  max-width: 560px;
  margin: var(--space-md) auto 0;
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.625;
  text-align: center;
  opacity: 0.9;
}
.hero__link {
  display: inline-block;
  margin-top: clamp(24px, 3vw, 40px);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.55px;
  text-transform: uppercase;
  text-decoration: underline;
  text-underline-offset: 6px;
  text-decoration-thickness: 1px;
  transition: opacity 0.3s ease;
}
.hero__link:hover { opacity: 0.7; }

/* ------------------------------------------------------------
   Word-by-word mask reveal (generic). Any element with `data-words`
   gets its text split into <span class="word"><span>word</span></span>.
   The outer span masks; the inner starts translated 110% down and
   rises into place, staggered per word.

   Trigger model:
   - If ancestor has [data-reveal], JS adds .is-visible on intersection
   - Otherwise, JS adds .is-visible immediately after the split
   ------------------------------------------------------------ */
[data-words] .word {
  display: inline-block;
  vertical-align: baseline;
  line-height: inherit;
}
[data-words] .word > span {
  display: inline-block;
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 1.1s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.1s cubic-bezier(0.25, 0.1, 0.25, 1);
  will-change: transform, opacity;
}
[data-words].is-visible .word > span,
.is-visible [data-words] .word > span {
  opacity: 1;
  transform: translateY(0);
}

/* Hero words cascade in as a continuous, overlapping flow —
   each word's fade overlaps the next so there's no pause, no click. */
.hero__title .word > span,
.hero__sub .word > span {
  transition-duration: 1.4s;
}

@media (prefers-reduced-motion: reduce) {
  [data-words] .word > span { opacity: 1; transform: none; transition: none; }
}

/* (Removed: lux-float perpetual bob.) Sixteen text elements were
   running a 7–11s 4px floating animation. At a luxury register that
   reads as a loading state rather than craft. If a single element
   ever genuinely needs "breath" — the teaser portrait at rest, say —
   reintroduce as a one-off, not as a system. */

@media (prefers-reduced-motion: reduce) {
  .hero { height: 100vh; }
  .hero__image {
    inset: 13.48% 11.63% 13.09% 11.63%;
  }
  .hero__title,
  .hero__sub { opacity: 1; animation: none; }
}

/* Mobile — disable the scroll-driven shrink. The effect is invisible
   on a phone-sized viewport but the 180vh hero leaves ~80vh of dead
   scroll before the manifesto, and the JS-driven inset transform
   fights with mobile Safari's URL-bar collapse. Hero becomes a clean
   100vh full-bleed image with sticky title; user scrolls past it
   naturally into the rest of the page. */
@media (max-width: 768px) {
  .hero { height: 100vh; }
  .hero__image { inset: 0; }
}

/* --------------------------------------------------------------------------
   02_In Good Company — slow infinite marquee with an eyebrow above.
   Duplicating the row inside the track means we can animate translateX
   to -50% (one full row width) and the loop is seamless. Pauses on
   hover so users can actually read the names.
   -------------------------------------------------------------------------- */
.strip {
  background: var(--sand);
  padding: clamp(48px, 6vw, 80px) 0;
  text-align: center;
  overflow: hidden;
  position: relative;
}
/* Cream variant — sits as its own brown section between the cases and
   the footer. Logos are recoloured to cream against the brown wash, so
   the eye carries continuity from the last case (which fades to brown)
   into this strip and out to the cream footer. Reduced top padding so
   the strip sits close to the bottom of the last case (which has its
   margin-bottom zeroed on the home page), leaving the brown as a single
   continuous panel rather than two stacked sections with a gap. */
.strip--cream {
  background: var(--brown);
  padding: clamp(32px, 4vw, 56px) 0 clamp(80px, 9vw, 120px);
}
.strip__eyebrow {
  display: block;
  margin: 0 auto clamp(24px, 3vw, 40px);
  color: var(--brown);
  opacity: 0.55;
}
.strip--cream .strip__eyebrow { color: var(--cream); }
.strip__track {
  display: flex;
  width: max-content;
  animation: strip-scroll 60s linear infinite;
}
/* Pause on hover so the user can read what they're looking at. */
.strip:hover .strip__track {
  animation-play-state: paused;
}
.strip__row {
  display: flex;
  align-items: center;
  gap: clamp(72px, 8vw, 120px);
  padding-right: clamp(72px, 8vw, 120px);
  margin: 0;
  list-style: none;
  flex-shrink: 0;
}
.strip__row li { display: flex; align-items: center; }
.strip__row img {
  width: auto;
  display: block;
  object-fit: contain;
}
/* Per-logo heights matching Lou's Figma proportions so they balance visually. */
.strip__row img[alt^="Six Senses" i],
.strip__row img[alt=""][src*="six-senses"]      { height: clamp(20px, 1.8vw, 26px); }
.strip__row img[alt^="Aman" i],
.strip__row img[alt=""][src*="aman"]            { height: clamp(22px, 2.0vw, 28px); }
.strip__row img[alt^="Cunard" i],
.strip__row img[alt=""][src*="cunard"]          { height: clamp(28px, 2.5vw, 36px); }
.strip__row img[alt^="Airelles" i],
.strip__row img[alt=""][src*="airelles"]        { height: clamp(13px, 1.2vw, 17px); }
.strip__row img[alt^="Beaverbrook" i],
.strip__row img[alt=""][src*="beaverbrook"]     { height: clamp(16px, 1.6vw, 22px); }
.strip__row img[alt^="Heckfield" i],
.strip__row img[alt=""][src*="heckfield"]       { height: clamp(30px, 2.7vw, 38px); }
.strip__row img[alt^="Shangri" i],
.strip__row img[alt=""][src*="shangri-la"]      { height: clamp(14px, 1.3vw, 18px); }
.strip__row img[alt^="Sofitel" i],
.strip__row img[alt=""][src*="sofitel"]         { height: clamp(24px, 2.2vw, 32px); }
.strip__row img[alt^="Romanengo" i],
.strip__row img[alt=""][src*="romanengo"]       { height: clamp(22px, 2.0vw, 28px); }
.strip__row img[alt^="RH" i],
.strip__row img[alt=""][src*="rh-new-york"]     { height: clamp(16px, 1.5vw, 20px); }
.strip--cream .strip__row img {
  filter: brightness(0) invert(1);
  opacity: 0.85;
}

@keyframes strip-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
  .strip__track { animation: none; }
  .strip { overflow-x: auto; }
}

/* --------------------------------------------------------------------------
   04_Entry Points — intro headline + 3 audience-led service cards.
   Each card: two-column grid (text on brown, image on right).
   -------------------------------------------------------------------------- */
.entry {
  background: var(--sand);
}
.entry__intro {
  background: var(--blue);
  padding: var(--space-3xl) var(--gutter);
  text-align: center;
}
.entry__intro-float {
  /* Scroll-linked parallax — --parallax-y is driven by JS */
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
/* Manifesto moment — display-weight type with per-line reveal.
   The block-level <span>s give us explicit line control (intentional
   rag) and let each line ladder in on its own delay, so the section
   reads as something composed rather than a paragraph. */
.entry__intro-title {
  max-width: 1120px;
  margin: 0 auto;
  color: var(--cream);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.18;
  letter-spacing: -0.005em;
}
.entry__intro-title span {
  display: block;
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 1.1s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.1s cubic-bezier(0.25, 0.1, 0.25, 1);
}
/* On phone the desktop's intentional line breaks (one phrase per
   span) read as orphan ragging — short fragments like "there,"
   stranded on their own line look like a legibility error rather
   than composition. Flow the spans inline so the manifesto reads as
   one paragraph at narrow widths. Spaces between phrases preserved
   via the inline display picking up natural word-spacing. */
@media (max-width: 768px) {
  .entry__intro-title span { display: inline; }
  .entry__intro-title span:not(:last-child)::after { content: ' '; }
}
.entry__intro.is-visible .entry__intro-title span { opacity: 1; transform: translateY(0); }
.entry__intro.is-visible .entry__intro-title span:nth-child(1) { transition-delay: 0.10s; }
.entry__intro.is-visible .entry__intro-title span:nth-child(2) { transition-delay: 0.25s; }
.entry__intro.is-visible .entry__intro-title span:nth-child(3) { transition-delay: 0.40s; }
.entry__intro.is-visible .entry__intro-title span:nth-child(4) { transition-delay: 0.55s; }
.entry__intro.is-visible .entry__intro-title span:nth-child(5) { transition-delay: 0.70s; }
.entry__intro.is-visible .entry__intro-title span:nth-child(6) { transition-delay: 0.85s; }
.entry__intro.is-visible .entry__intro-title span:nth-child(7) { transition-delay: 1.00s; }
@media (prefers-reduced-motion: reduce) {
  .entry__intro-title span { opacity: 1; transform: none; transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .entry__intro-float { transform: none; }
}

/* Sticky stack — each card pins to top:0, the next one slides up over it.
   For the stack to read cleanly, every card needs a solid background that
   completely covers the card stacking below. The progressive sand→brown
   tints are the *blended* hex equivalents of Lou's translucent overlays. */
.entry-card {
  position: sticky;
  top: 0;
  height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.entry-card--1 { background: #DDD8CE; }   /* sand + 8% brown */
.entry-card--2 { background: #D4CFC4; }   /* sand + 14% brown */
.entry-card--3 { background: #C7C0B7; }   /* sand + 22% brown */

.entry-card__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  gap: var(--space-sm);
  padding: var(--space-xl) clamp(40px, 8vw, 121px);
  color: var(--brown);
}

.entry-card__title {
  margin: 0;
}
.entry-card__sub {
  margin: 0;
  max-width: 420px;
}
.entry-card__copy .cta {
  margin-top: clamp(8px, 1.2vw, 16px);
}

.entry-card__media {
  position: relative;
  overflow: hidden;
}
.entry-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Strategic Partnerships card — anchor the bedroom photo to the left
   so the four-poster bed sits in the visible frame, not the right
   panel. Explicit opacity/filter overrides to prevent any cached or
   inherited fade from leaking through. */
.entry-card--2,
.entry-card--2 *,
.entry-card--2 .entry-card__media,
.entry-card--2 .entry-card__media img {
  mix-blend-mode: normal;
  background-blend-mode: normal;
}
.entry-card--2 .entry-card__media img {
  /* Pool image is centred symmetrically; bias the crop to the right
     so the pool's depth and perspective lines lead toward the left
     edge of the slot — i.e. toward the text column on the card. */
  object-position: right center;
  opacity: 1;
  filter: none;
}

/* Snami-style wipe reveal — slow cinematic sweep on the image, then
   the eyebrow/title/sub/CTA fade in once the wipe has cleared. */
.entry-card[data-reveal] .entry-card__media::after {
  content: '';
  position: absolute;
  inset: 0;
  background: #DDD8CE;
  transform-origin: left center;
  transform: scaleX(1);
  transition: transform 1.8s cubic-bezier(0.77, 0, 0.175, 1);
  z-index: 2;
  pointer-events: none;
}
.entry-card[data-reveal] .entry-card__media img {
  transform: scale(1.06);
  transition: transform 2.1s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.entry-card[data-reveal].is-visible .entry-card__media::after {
  transform: scaleX(0);
}
.entry-card[data-reveal].is-visible .entry-card__media img {
  transform: scale(1);
}

/* Copy fades in after the wipe — eyebrow first, then title/sub/CTA
   ladder in via per-element transition-delay so the section settles
   piece by piece rather than as one block. */
.entry-card[data-reveal] .entry-card__copy > * {
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 1.1s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.1s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.entry-card[data-reveal] .entry-card__copy > *:nth-child(1) { transition-delay: 1.5s; }
.entry-card[data-reveal] .entry-card__copy > *:nth-child(2) { transition-delay: 1.7s; }
.entry-card[data-reveal] .entry-card__copy > *:nth-child(3) { transition-delay: 1.9s; }
.entry-card[data-reveal] .entry-card__copy > *:nth-child(4) { transition-delay: 2.1s; }
.entry-card[data-reveal].is-visible .entry-card__copy > * {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .entry-card[data-reveal] .entry-card__media::after,
  .entry-card[data-reveal] .entry-card__media img,
  .entry-card[data-reveal] .entry-card__copy > * {
    transition: none;
    transform: none;
    opacity: 1;
  }
}
/* Tablet — 1024px and below */
@media (max-width: 1024px) {
  .entry__intro {
    padding: clamp(80px, 10vw, 128px) var(--gutter);
  }
  .entry__intro-title { max-width: 760px; }
  /* Drop the desktop sticky stack at any viewport ≤1024. The 1fr/1fr
     split crushed the copy column at 800–900px when sticky was still
     on; stacking the image above the copy reads cleanly through the
     tablet/small-laptop range. */
  .entry-card {
    position: static;
    height: auto;
    min-height: clamp(360px, 48vw, 440px);
    grid-template-columns: 1fr;
  }
  .entry-card__media { order: -1; aspect-ratio: 4 / 3; }
  .entry-card__copy {
    padding: clamp(32px, 5vw, 64px) clamp(32px, 6vw, 80px);
  }
  .teaser__inner {
    gap: clamp(56px, 8vw, 120px);
  }
  .case__copy {
    left: clamp(20px, 6vw, 80px);
    bottom: clamp(40px, 6vw, 80px);
    max-width: clamp(320px, 50vw, 500px);
  }
  .case__cta {
    right: clamp(20px, 6vw, 80px);
    bottom: clamp(40px, 6vw, 80px);
  }
  .testimonial {
    padding: var(--space-2xl) 0;
  }
}

@media (max-width: 768px) {
  /* Tighter padding override for phone — narrower side gutters than
     the 1024 default to give text room on small screens. */
  .entry-card__copy { padding: 40px 24px 56px; }
}

/* --------------------------------------------------------------------------
   05_Testimonial — brown band, centered cream Canela quote.
   -------------------------------------------------------------------------- */
.testimonial {
  background: var(--brown);
  color: var(--cream);
  padding: var(--space-3xl) 0;
}
.testimonial__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
  max-width: 1100px;
  /* Scroll-linked parallax — JS sets --parallax-y on this element */
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
.testimonial__quote {
  margin: 0;
  color: var(--cream);
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.35;
  letter-spacing: -0.005em;
  font-style: normal;
  quotes: none;
  text-align: left;
  max-width: 1100px;
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity 1.8s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.8s cubic-bezier(0.25, 0.1, 0.25, 1);
  transition-delay: 0.1s;
}
.testimonial.is-visible .testimonial__quote {
  opacity: 1;
  transform: translateY(0);
}

.testimonial__attr {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  margin: 0;
  color: var(--cream);
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity 1.8s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.8s cubic-bezier(0.25, 0.1, 0.25, 1);
  transition-delay: 0.8s;
}
.testimonial.is-visible .testimonial__attr {
  opacity: 1;
  transform: translateY(0);
}
.testimonial__attr-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cream);
  margin-top: 7px;
  flex-shrink: 0;
}
.testimonial__attr-name { display: block; }
.testimonial__attr-role { display: block; opacity: 0.65; }

@media (prefers-reduced-motion: reduce) {
  .testimonial__line,
  .testimonial__attr {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* --------------------------------------------------------------------------
   06_Who We Are teaser — sand bg, Liv portrait with blue offset
   accent rectangle behind, bio + CTA on the right.
   -------------------------------------------------------------------------- */
.teaser {
  background: var(--sand);
  padding: var(--space-3xl) 0;
}
.teaser__inner {
  display: grid;
  /* Symmetric flexible columns. A hard min on either column starves the
     other at intermediate widths (770–1100px), which crushed the bio text
     in the --reverse layout to ~3 words per line. The image is capped by
     .teaser__media max-width and stays centered in its cell. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(80px, 10vw, 200px);
  align-items: center;
}
.teaser__media {
  position: relative;
  width: 100%;
  max-width: 474px;
  aspect-ratio: 395 / 421;
  margin: 0 auto;
}
.teaser__accent {
  position: absolute;
  inset: 67px -67px -67px 67px;
  background: rgba(139, 147, 166, 0.55);
  z-index: 0;
  /* Scroll-linked parallax — JS writes --parallax-y on this element */
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .teaser__accent { transform: none; }
}
.teaser__media img {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Alex's portrait sits with his head close to the top of the source
   image; default centring crops his hair off. Bias the crop toward
   the top so the full head is in frame. */
.teaser__media img[src*="portrait-alex"] {
  object-position: center 18%;
}
/* Liv's portrait — fills the frame edge-to-edge. */
.teaser__media img[src*="portrait-liv"] {
  object-position: center 50%;
}
.teaser__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(12px, 1.4vw, 20px);
  color: var(--brown);
}
.teaser__name {
  margin: 0;
}
.teaser__bio {
  margin: 0;
  max-width: 560px;
  font-size: var(--type-sub);
  line-height: 1.4;
}
/* Credential strip — small-caps signature line under the bio that
   anchors the named brands as a verifiable provenance ladder rather
   than buried in prose. */
.teaser__credentials {
  margin: clamp(8px, 1vw, 14px) 0 0;
  color: var(--brown);
  opacity: 0.55;
  letter-spacing: 1.2px;
}
/* About-page variant — multi-paragraph bio in body type, anchored under
   the same teaser frame (sand bg, blue accent, parallax) as the home. */
.teaser__body {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 1.4vw, 22px);
  margin: 0;
  max-width: 56ch;
}
.teaser__body p {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--brown);
  margin: 0;
}
/* Flipped variant — copy on the left, portrait on the right. Columns are
   already symmetric (1fr/1fr); HTML order alone mirrors the layout.
   The blue accent moves to the bottom-left to mirror its symmetry. */
.teaser--reverse .teaser__accent {
  inset: 67px 67px -67px -67px;
}
.teaser__cta {
  margin-top: clamp(12px, 1.5vw, 20px);
}

/* Stack at 1024px — between 900 and 1024 the side-by-side 1fr/1fr
   layout still squeezed --type-sub bio copy to ~2 words per line on
   the home page founder teaser. Collapsing earlier keeps the rhythm
   readable through the tablet/small-laptop window. */
@media (max-width: 1024px) {
  .teaser__inner {
    grid-template-columns: 1fr;
    gap: 56px;
  }
  .teaser__media {
    max-width: 280px;
    margin: 0 auto;
  }
  .teaser__accent {
    inset: 80px -40px -40px 40px;
  }
  /* Mirror the mobile accent for the --reverse variant. Without this,
     the desktop rule (.teaser--reverse .teaser__accent — higher
     specificity than .teaser__accent in the MQ) keeps its 67px insets
     and bleeds 67px left/down past the centered 280px portrait,
     overlapping the eyebrow + name beneath. */
  .teaser--reverse .teaser__accent {
    inset: 80px 40px -40px -40px;
  }
  /* On a stacked layout the image always reads first regardless of
     --reverse HTML order, so the bio doesn't lead a faceless block. */
  .teaser--reverse .teaser__media {
    order: -1;
  }
}

/* --------------------------------------------------------------------------
   Case Studies — sticky-stack trio.
   Each .case is position:sticky top:0 height:100vh; the next card slides
   up over the previous as you scroll. Image + brown diagonal gradient
   overlay (hard-light blend) matches Lou's Figma treatment.
   -------------------------------------------------------------------------- */
.cases {
  background: var(--brown);         /* fallback behind image while loading */
  /* Contains the last case-study's margin-bottom so the 25vh dwell
     stays inside the brown section instead of collapsing out and
     letting the body bg show as a cream stripe before .final-cta. */
  display: flow-root;
}
.case {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  color: var(--cream);
  /* Consistent 50vh dwell on every card — including the last. Each
     card pins, holds for 50vh of scroll, then the next slides over
     it. .cases uses display: flow-root above so the last card's
     trailing margin stays inside the brown section. */
  margin-bottom: 50vh;
}
.case__media {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  overflow: hidden;
}
.case--airelles    .case__media { background-image: url('../assets/images/work/luxury-hospitality-consulting-selected-work-card-airelles.webp'); }
.case--shangri-la  .case__media {
  background-image: url('../assets/images/home/luxury-hospitality-consulting-home-case-shangri-la-monastery.webp');
  background-position: center center;
}
/* Selected Work uses a different Shangri-La cover (Yunnan rice terraces)
   so the listing reads fresh against the home page's monastery shot. */
.work-page .case--shangri-la .case__media {
  background-image: url('../assets/images/work/luxury-hospitality-consulting-selected-work-card-shangri-la.webp');
}

/* Six Senses Shaharut dinner shot in The Outcome — sunset is rich
   warm, light desaturate pulls it into the page's muted palette. */
.case-study-page img[src*="shaharut-dinner"] {
  filter: saturate(0.7) brightness(0.98) sepia(0.04);
}
.case--six-senses  .case__media { background-image: url('../assets/images/work/luxury-hospitality-consulting-selected-work-card-shaharut.webp'); }
/* Video stacks on top of the poster bg-image inside .case__media so the
   poster acts as a fallback while the video loads (or if it fails). */
.case__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.case__overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* Black scrim across all three case studies — matches Airelles so the
     shadow treatment is consistent down the stack. */
  background: linear-gradient(
    to top,
    rgba(0, 0, 0, 0.85) 0%,
    rgba(0, 0, 0, 0.55) 25%,
    rgba(0, 0, 0, 0.2) 50%,
    rgba(0, 0, 0, 0) 70%
  );
}
/* Last case bleeds into the final-cta brown — the bottom of the video
   fades to solid brown matching the next section so "In good company"
   feels like a continuation of the same surface, not a separate band.
   Scoped off the work page (where the last card cuts cleanly into the
   sand client list — no fade, image stays untreated). */
.case:last-child .case__overlay {
  background: linear-gradient(
    to top,
    var(--brown) 0%,
    rgba(77, 59, 55, 0.92) 12%,
    rgba(77, 59, 55, 0.7) 24%,
    rgba(77, 59, 55, 0.35) 40%,
    rgba(77, 59, 55, 0.1) 55%,
    rgba(77, 59, 55, 0) 70%
  );
}
/* Last case on /work fades to brown so Shangri-La bleeds smoothly into
   the brown Full Client List section beneath. */
.work-page .case:last-child .case__overlay {
  background: linear-gradient(
    to top,
    var(--brown) 0%,
    rgba(77, 59, 55, 0.92) 12%,
    rgba(77, 59, 55, 0.7) 24%,
    rgba(77, 59, 55, 0.35) 40%,
    rgba(77, 59, 55, 0.1) 55%,
    rgba(77, 59, 55, 0) 70%
  );
}
/* Selected Work uses the same sticky slide-over stack as the home —
   each case pins for 50vh, the next slides over it. Last case has
   zero dwell so the work-clients accordion sits flush below it. */
.work-page .case:last-child { margin-bottom: 0; }

/* Home page — last case has no next card to slide over it, so the
   50vh dwell from the base rule just creates empty brown scroll
   between Six Senses and the cream partner strip. Trim to 0 so the
   strip follows immediately after the last case finishes. */
.home-page .case:last-child { margin-bottom: 0; }

.case__copy {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(56px, 8vw, 120px);
  max-width: clamp(420px, 45vw, 620px);
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 1vw, 14px);
}
.case__eyebrow {
  color: var(--cream);
  opacity: 0.9;
}
.case__title {
  color: var(--cream);
  margin: 0;
}
.case__sub {
  color: var(--cream);
  margin: 0;
  max-width: 36ch;
}

.case__cta {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(56px, 8vw, 120px);
}

/* Slow cinematic wipe for case cards opted into [data-reveal]. The
   ::after sheet covers the whole card and sweeps off to the left over
   ~1.8s; the copy + CTA then fade in once the image is exposed. */
.case[data-reveal]::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--brown);
  transform-origin: left center;
  transform: scaleX(1);
  transition: transform 1.8s cubic-bezier(0.77, 0, 0.175, 1);
  z-index: 3;
  pointer-events: none;
}
.case[data-reveal].is-visible::after {
  transform: scaleX(0);
}
.case[data-reveal] .case__copy,
.case[data-reveal] .case__cta {
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 1.1s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.1s cubic-bezier(0.25, 0.1, 0.25, 1);
  transition-delay: 1.5s;
}
.case[data-reveal].is-visible .case__copy,
.case[data-reveal].is-visible .case__cta {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .case[data-reveal]::after { display: none; }
  .case[data-reveal] .case__copy,
  .case[data-reveal] .case__cta {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

@media (max-width: 768px) {
  /* Case studies on mobile = static stack. Each card is a 100vh block;
     scroll past it to see the next. Sticky-pin on a phone is friction
     without payoff — Matter of Form's own work uses static stacks here.
     Inside the card, copy + CTA sit as a column flex anchored to the
     lower third of the image. */
  .case {
    position: relative;
    top: auto;
    height: 100vh;
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    padding: 0 var(--gutter) clamp(48px, 8vw, 72px);
  }
  .case__copy {
    position: relative;
    z-index: 2;
    flex: 0 0 auto;
    max-width: none;
    left: auto;
    bottom: auto;
  }
  .case__cta {
    position: relative;
    z-index: 2;
    flex: 0 0 auto;
    right: auto;
    bottom: auto;
    margin-top: 20px;
    align-self: flex-start;
  }
  /* Cream partner strip — hide once cases switch to static stack.
     The desktop trick floats it over the last case's brown bleed via
     a -426px margin-top; on a static stack that drags the logos onto
     the Six Senses video and overlaps the footer's "Let's begin"
     statement. The top .strip already shows the same logos. */
  .final-cta { display: none; }
}

/* ==========================================================================
   MOBILE — ≤640px. Targeted overrides for content sizing, spacing, and
   layouts that need to feel right on phone-sized viewports.
   ========================================================================== */
@media (max-width: 640px) {
  /* Sticky nav — shorter bar, smaller logo */
  .site-nav-sticky { height: 56px; padding: 0 var(--gutter); }
  .site-nav-sticky__logo img { height: 22px; }
  .site-nav-sticky__contact { font-size: 10px; }

  /* Hero — scale-down that kills extra breathing room. Let the sub
     wrap naturally on the smallest phones rather than risk clipping
     at 320px when the clamp floor (15px) and 4.4vw don't shrink fast
     enough on a long line. */
  .hero__title { font-size: clamp(26px, 8vw, 32px); }
  .hero__sub   {
    font-size: clamp(15px, 4.4vw, 22px);
    max-width: none;
  }

  /* Credibility strip — tighter carousel, still readable */
  .strip { padding: clamp(36px, 9vw, 56px) 0; }
  .strip__row { gap: 56px; padding-right: 56px; }

  /* Intro band — tight padding, body-friendly size */
  .entry__intro {
    /* Generous breathing room above + below the manifesto on phone —
       luxe-magazine register for the page's first content moment. */
    padding: clamp(120px, 20vw, 160px) var(--gutter);
  }
  .entry__intro-title {
    line-height: 1.25;
    max-width: none;
  }

  /* Entry cards — still stacked (inherits from ≤768). Generous top +
     bottom padding so each panel reads as a chapter in its own right.
     Type hierarchy refined: tighter eyebrow tracking, larger title for
     stronger first-read, smaller sub for clearer subordination, more
     gap between elements so each line earns its space. */
  .entry-card__copy { padding: 80px var(--gutter) 88px; gap: 16px; }
  .entry-card .eyebrow { letter-spacing: 1.4px; margin-bottom: 4px; }
  .entry-card__title { line-height: 1.1; letter-spacing: -0.01em; }

  /* Unified mobile subheading — wider measure for body-sub on entry cards,
     case cards and founder teaser. Type sizes inherit from tokens. */
  .entry-card__sub,
  .case__sub,
  .teaser__bio {
    line-height: 1.5;
    max-width: none;
  }

  /* Testimonial — bump padding up on mobile so it carries weight against
     the brown panel and sits as its own beat between the entry cards
     and the founder teaser. */
  .testimonial { padding: clamp(120px, 20vw, 160px) 0; }
  .testimonial__inner { padding: 0 var(--gutter); gap: 28px; }
  .testimonial__quote {
    line-height: 1.4;
    max-width: none;
  }
  .testimonial__attr { font-size: var(--type-body); }

  /* Teaser — let the portrait fill the column, soften the blue accent
     so it reads as a quiet offset rather than a hard square, and open
     up the rhythm between name → bio → credentials → CTA. */
  .teaser { padding: 112px 0; }
  .teaser__inner { gap: 56px; padding: 0 var(--gutter); }
  .teaser__copy { gap: 18px; }
  .teaser__media { max-width: none; }
  .teaser__accent { inset: 24px -12px -12px 24px; opacity: 0.7; }
  .teaser__credentials { margin-top: 4px; }
  .teaser__cta { margin-top: 8px; }

  /* Case studies — stack the CTA under the copy and anchor the whole
     stack to the lower third of the image. justify-content: flex-end
     pushes copy + CTA to the bottom; the case bottom-padding sets the
     breathing room above the lower edge.
     Parent .case already applies var(--gutter) horizontally, so
     .case__copy and .case__cta must NOT add their own horizontal
     padding/margin or the title gets pushed in 40px instead of 20px. */
  .case {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-end;
    height: 100vh;
    min-height: 100vh;
    padding-bottom: clamp(72px, 12vh, 110px);
  }
  /* Reset flex:1 from the 768px rule — otherwise .case__copy stretches
     to the full case height and its content sits at the top instead of
     letting justify-content: flex-end on the parent bottom-align it. */
  .case__copy {
    padding: 0;
    flex: 0 0 auto;
  }
  .case__eyebrow { letter-spacing: 0.16em; }
  .case__cta {
    margin: 20px 0 0;
    align-self: flex-start;
  }

  /* Footer — single centered column: monogram, "Let's begin." statement,
     email, social, nav rule, meta. Each block centers on the page width
     and the rhythm between blocks is set by .footer__inner gap. */
  .footer {
    padding: 64px 0 36px;
    text-align: center;
  }
  .footer__inner {
    gap: 36px;
    padding: 0 var(--gutter);
    align-items: center;
  }
  .footer__head {
    grid-template-columns: 1fr;
    justify-items: center;
    gap: 24px;
    width: 100%;
  }
  .footer__head-copy {
    align-items: center;
    text-align: center;
    gap: 18px;
    width: 100%;
  }
  .footer__statement {
    max-width: 18ch;
  }
  .footer__mark {
    order: -1;
    align-self: center;
  }
  .footer__mark img { height: 56px; }
  .footer__social {
    justify-content: center;
    margin-top: 2px;
  }
  .footer__nav {
    gap: 14px 24px;
    padding: 22px 0;
    justify-content: center;
    width: 100%;
  }
  .footer__nav a { font-size: 12px; }
  .footer__meta {
    font-size: 11px;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
    width: 100%;
  }
  .footer__contact { font-size: 13px; }

  /* Menu panel — tighter close/logo, larger tap targets for links */
  .menu-panel__close { top: 22px; left: 20px; font-size: 12px; }
  .menu-panel__mark { top: 22px; }
  .menu-panel__mark img { height: 40px; }
  .menu-panel__links a { font-size: 28px; padding: 6px 0; }

  /* Hide the perpetual float on mobile — it reads as jitter on small
     screens and has minimal payoff. Scroll-linked parallax stays. */
  .entry-card__title,
  .entry-card__sub,
  .entry-card .eyebrow,
  .teaser__name,
  .teaser__bio,
  .case__title,
  .case__sub,
  .case__eyebrow,
  .final-cta__title,
  .hero__title,
  .hero__sub {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   07_CTA — closing moment on a flat brown wash. Two-column layout: copy
   + CTA left, partner-logo wall right (cream-toned via filter so it
   reads as quiet social proof rather than a decorative photo).
   -------------------------------------------------------------------------- */
/* Closing brown wash — hosts the cream partner strip floating above
   the footer. The strip is pulled up via negative margin so it overlaps
   the bottom of the cases section; the brown bg below it gives the
   strip a wash to read against and a beat of breathing room before
   the footer kicks in. */
.final-cta {
  background: var(--brown);
  color: var(--cream);
  padding: 0 0 clamp(40px, 5vw, 72px);
}
.final-cta__inner {
  /* Single centered column now that the logo wall is gone. */
  max-width: none;
  padding-left: clamp(24px, 8.5vw, 121px);
  padding-right: clamp(24px, 8.5vw, 121px);
  display: flex;
  justify-content: center;
  /* margin: auto vertically centers the copy block in the remaining
     flex space below the cream logo strip. translateY shifts it
     30px below true center (was -20px, now -20 + 50 = 30). */
  margin: auto 0;
  transform: translateY(30px);
  flex: 1;
  align-items: center;
}
.final-cta__copy {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(20px, 2.4vw, 32px);
  max-width: 720px;
}
.final-cta__eyebrow {
  color: var(--cream);
  opacity: 0.7;
  margin: 0;
}
.final-cta__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--cream);
  margin: 0;
}
.final-cta__cta {
  margin-top: clamp(8px, 1.2vw, 16px);
}
.final-cta__logos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(64px, auto);
  gap: clamp(28px, 4vw, 64px) clamp(32px, 5vw, 80px);
  align-items: center;
  justify-items: center;
}
.final-cta__logos li {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
}
.final-cta__logos img {
  width: auto;
  display: block;
  /* Recolor partner SVGs to cream — brightness(0) flattens to black,
     invert(1) flips to white, then opacity tones it back to a cream
     reading on the brown wash. */
  filter: brightness(0) invert(1);
  opacity: 0.7;
  transition: opacity 0.3s ease;
}
.final-cta__logos img:hover { opacity: 1; }
/* Per-logo heights — match the proportions used in the top marquee
   strip but slightly smaller so the wall reads as quiet, not loud. */
.final-cta__logos img[alt^="Six Senses" i]   { height: clamp(18px, 1.5vw, 22px); }
.final-cta__logos img[alt^="Aman" i]         { height: clamp(20px, 1.7vw, 24px); }
.final-cta__logos img[alt^="Cunard" i]       { height: clamp(24px, 2.1vw, 30px); }
.final-cta__logos img[alt^="Airelles" i]     { height: clamp(11px, 1vw, 14px); }
.final-cta__logos img[alt^="Beaverbrook" i]  { height: clamp(40px, 4vw, 56px); }
.final-cta__logos img[alt^="Heckfield" i]    { height: clamp(26px, 2.3vw, 32px); }

@media (max-width: 900px) {
  .final-cta__inner {
    grid-template-columns: 1fr;
    gap: clamp(48px, 8vw, 72px);
  }
  .final-cta__copy { align-items: flex-start; text-align: left; }
}
@media (max-width: 540px) {
  .final-cta__logos {
    grid-template-columns: repeat(2, 1fr);
    gap: 36px 28px;
  }
}

/* --------------------------------------------------------------------------
   10_Footer — sand bg, three-tier layout: brand+contact / nav / meta.
   Hairlines separate the sections. Horizontal logo anchors the top-left.
   -------------------------------------------------------------------------- */
/* Footer — editorial closing. Asymmetric: large display "Let's begin"
   + email/social on the left, LHC monogram anchored to the right. Nav
   sits as a horizontal rule below. Meta band carries copyright + locale
   stamp left, credits right. */
.footer {
  background: var(--sand);
  color: var(--brown);
  padding: var(--space-2xl) 0 var(--space-md);
}
.footer__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-xl);
  /* Inherits .container's padding: 0 var(--gutter) for the page-edge
     gutter, but max-width is removed so the footer sits at var(--gutter)
     from the actual viewport edge at all widths — matching the case-
     study text which is positioned absolute relative to the full-viewport
     case. Without this override, the footer would drift inward past
     1440px viewport while the cases stay at 96px from edge. */
  max-width: none;
}

/* Head — closing statement + contact left, monogram right.
   Centre-aligned so the monogram visually balances against the
   midpoint of the statement+social stack on the left, rather than
   anchoring to the social row. */
.footer__head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--space-xl);
}
.footer__head-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
}
.footer__statement {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--brown);
  margin: 0;
  max-width: 13ch;
}
.footer__social {
  display: flex;
  gap: 22px;
  margin-top: 4px;
}
.footer__social a {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.55;
  text-decoration: none;
  transition: opacity 0.3s ease;
}
.footer__social a:hover { opacity: 1; }
.footer__mark {
  display: block;
  align-self: flex-end;
}
.footer__mark img {
  width: auto;
  display: block;
  height: clamp(110px, 12vw, 200px);
}

/* Nav — single horizontal line, left-aligned, rules top + bottom. */
.footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-lg);
  padding: var(--space-md) 0;
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  border-bottom: 1px solid rgba(77, 59, 55, 0.18);
}
.footer__nav a {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.7;
  text-decoration: none;
  transition: opacity 0.3s ease;
}
.footer__nav a:hover { opacity: 1; }
/* External link (LinkedIn) pushes to the right end of the nav row,
   visually separating internal navigation from outgoing pointers. */
.footer__nav-external { margin-left: auto; opacity: 0.55; }

/* Meta — copyright + locale stamp left, credits right. */
.footer__meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-md);
  font-family: var(--font-body);
  font-size: 12px;
  line-height: 1.5;
  color: var(--brown);
  opacity: 0.65;
  flex-wrap: wrap;
}
.footer__meta p { margin: 0; }
.footer__meta a { color: inherit; text-decoration: none; transition: opacity 0.3s ease; }
.footer__meta a:hover { opacity: 0.6; }

/* Mobile / tablet — entire footer centers as one stacked sign-off:
   monogram → "Let's begin." → email → social → nav → meta.
   Home nav link is hidden so the 5 remaining items fit on one row. */
@media (max-width: 768px) {
  .footer {
    padding: clamp(64px, 12vw, 100px) 0 clamp(28px, 3vw, 40px);
    text-align: center;
  }
  .footer__inner { align-items: center; }
  .footer__head {
    grid-template-columns: 1fr;
    justify-items: center;
    align-items: center;
    gap: clamp(32px, 6vw, 56px);
  }
  .footer__head-copy { align-items: center; text-align: center; }
  .footer__mark {
    order: -1;
    align-self: center;
  }
  .footer__mark img { height: clamp(60px, 15vw, 88px); }
  .footer__social { justify-content: center; }
  .footer__nav { justify-content: center; }
  .footer__nav a:first-of-type { display: none; }
  .footer__meta {
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 8px;
  }
}


/* --------------------------------------------------------------------------
   Mobile adjustments
   -------------------------------------------------------------------------- */
@media (max-width: 768px) {
  .site-nav {
    height: 88px;
    padding: 0 var(--gutter);
  }
  .site-nav__logo img { height: 32px; }
  .site-nav__menu,
  .site-nav__contact {
    font-size: 11px;
    margin-top: calc((88px - 32px) / 2);
  }

  /* On mobile, kill the scroll-shrink animation entirely — the image
     fills the viewport from the moment it loads and stays that way as
     you scroll. Phone screens are already small; further shrinking the
     image makes the hero feel weak. */
  .hero { height: 100vh; }
  .hero__image { inset: 0; }
  .hero__copy { top: 50%; }
}

/* ==========================================================================
   Work landing page — Matter-of-Form-style intro + sticky case stack
   ========================================================================== */
/* Brown/taupe wash, cream text, big display title left + body right —
   Matter-of-Form-style entry. */
.work-intro {
  background: var(--brown);
  color: var(--cream);
  padding: clamp(120px, 14vw, 180px) 0 clamp(40px, 5vw, 72px);
}
.work-intro__inner {
  /* Standard .container gutters keep margins consistent with the case
     study pages. Title pinned left, body pinned to the right edge of
     the container — two-anchor editorial layout. */
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: clamp(24px, 3vw, 56px);
  text-align: left;
}
.work-intro__title { flex: 0 0 auto; }
.work-intro__body  { flex: 0 1 auto; max-width: 44ch; }
.work-intro__eyebrow {
  display: none; /* Matter-of-Form pattern leads with the title only */
}
.work-intro__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--cream);
  margin: 0;
}
.work-intro__copy {
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.2vw, 18px);
}
.work-intro__body {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.55;
  color: var(--cream);
  opacity: 0.75;
  margin: 0;
  /* No max-width — body should reach the right gutter so its end-line
     aligns with the contact CTA above. */
}
/* Secondary intro line (the discretion note) — same body type, dimmer
   so it reads as context, not the headline body copy. */
.work-intro__body--meta {
  opacity: 0.55;
}

/* Full Client List bar — wide darker strip below the intro with a
   right-aligned arrow link to the table further down the page.
   Matches nav gutters so the bar spans the same edges as "Our Work." */
.work-clients {
  background: var(--brown);
  padding: 0 0 clamp(32px, 4vw, 56px);
}
.work-clients__inner {
  display: block;
}

/* Accordion toggle — section opener. The bar reads as a chapter
   heading (Canela display "Full Client List" + small eyebrow lede)
   rather than a UI control. Hairline rules top/bottom, generous
   padding, chevron lifts to suggest the expand interaction. */
.work-clients__toggle {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: clamp(24px, 3vw, 48px);
  /* Modest horizontal padding so the hairline rules + chevron breathe
     inward from the page gutter — full-flush hairlines reading edge
     to edge felt too tight at wide desktop widths. Title sits ~24–48px
     in from the gutter, which still feels visually anchored to the
     "Selected Work" title above without the bar dominating the page. */
  padding: clamp(28px, 3.5vw, 56px) clamp(24px, 3vw, 48px);
  background: transparent;
  border: none;
  border-top: 1px solid rgba(234, 230, 219, 0.15);
  border-bottom: 1px solid rgba(234, 230, 219, 0.15);
  color: var(--cream);
  font-family: var(--font-body);
  text-align: left;
  cursor: pointer;
  transition: background 0.3s ease;
}
.work-clients__toggle:hover { background: rgba(234, 230, 219, 0.04); }
.work-clients__toggle:focus-visible {
  outline: 1px solid rgba(234, 230, 219, 0.5);
  outline-offset: 4px;
}
.work-clients__heading {
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.3vw, 18px);
}
.work-clients__title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--type-h3);
  line-height: 1.2;
  letter-spacing: 0;
  color: var(--cream);
}
.work-clients__lede {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cream);
  opacity: 0.55;
}
.work-clients__chevron {
  width: clamp(20px, 2vw, 28px);
  height: auto;
  color: var(--cream);
  opacity: 0.7;
  transition: transform 0.4s cubic-bezier(0.25, 0.1, 0.25, 1);
  flex-shrink: 0;
}
.work-clients.is-open .work-clients__chevron {
  transform: rotate(180deg);
  opacity: 1;
}

/* Panel animation — grid-template-rows trick lets us animate from
   collapsed (0fr) to natural height (1fr) without max-height hacks. */
.work-clients__panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.6s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.work-clients__panel-inner {
  overflow: hidden;
  min-height: 0;
}
.work-clients.is-open .work-clients__panel {
  grid-template-rows: 1fr;
}
.work-clients.is-open .work-clients__panel-inner {
  background: var(--sand);
  color: var(--brown);
  margin-top: 0;
  padding: clamp(24px, 3vw, 40px) clamp(28px, 4vw, 56px) clamp(48px, 6vw, 80px);
}
@media (prefers-reduced-motion: reduce) {
  .work-clients__panel,
  .work-clients__chevron { transition: none; }
}
@media (max-width: 600px) {
  .work-clients__toggle { padding: 32px clamp(20px, 5vw, 28px); gap: 20px; }
  .work-clients__lede { letter-spacing: 0.16em; }
}

@media (max-width: 900px) {
  .work-intro {
    padding: clamp(120px, 16vw, 180px) 0 clamp(64px, 10vw, 96px);
  }
  .work-intro__inner {
    grid-template-columns: 1fr;
    gap: clamp(20px, 3vw, 32px);
    align-items: flex-start;
  }
}
@media (max-width: 600px) {
  /* More breathing room above the chapter title on phone — 96px sat
     too close to the sticky nav for a hero opener. */
  .work-intro { padding: clamp(120px, 22vh, 160px) 0 56px; }
  .work-clients__toggle { padding: 24px clamp(20px, 5vw, 28px); }
}

/* --------------------------------------------------------------------------
   Full Client List — flat 5-col table grouped by Resort / City / Other.
   Sand wash, always open: the breadth IS the credibility signal.
   -------------------------------------------------------------------------- */
.client-list {
  background: var(--sand);
  color: var(--brown);
  padding: clamp(56px, 7vw, 96px) 0 clamp(96px, 12vw, 160px);
  position: relative;
  z-index: 2;
}
/* Cases section keeps its base brown background on /work — pairs
   cleanly with the brown work-clients accordion that follows. The
   prior sand override was for the original sand-bg client list,
   which has since been wrapped in a brown accordion. */
.client-list__header {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: clamp(32px, 6vw, 96px);
  align-items: end;
  padding-bottom: clamp(40px, 5vw, 72px);
  border-bottom: 1px solid rgba(77, 59, 55, 0.18);
}
.client-list__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.15;
  letter-spacing: -0.005em;
  margin: 0;
}
.client-list__lede {
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.55;
  color: var(--brown);
  opacity: 0.7;
  margin: 0;
  max-width: 42ch;
}
.client-list__count {
  margin-left: 6px;
  opacity: 0.55;
  font-feature-settings: 'tnum';
}

/* Filter bar — sand strip with pill-shaped selects, MoF-style. */
.client-list__filters {
  margin: clamp(32px, 4vw, 56px) 0 clamp(24px, 3vw, 40px);
  padding: clamp(16px, 1.6vw, 24px) clamp(20px, 2vw, 32px);
  background: rgba(77, 59, 55, 0.04);
  border-radius: 999px;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(12px, 1.4vw, 20px);
}
.filter {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  position: relative;
}
.filter__label {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.55;
}
.filter__select {
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  border: 1px solid rgba(77, 59, 55, 0.25);
  border-radius: 999px;
  padding: 8px 36px 8px 16px;
  font-family: var(--font-body);
  font-size: clamp(13px, 0.95vw, 15px);
  color: var(--brown);
  cursor: pointer;
  /* Custom caret */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath fill='none' stroke='%234D3B37' stroke-width='1' d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  transition: border-color 0.3s ease, background-color 0.3s ease;
}
.filter__select:hover { border-color: rgba(77, 59, 55, 0.5); }
.filter__select:focus-visible {
  outline: none;
  border-color: var(--brown);
}

.client-list__empty {
  padding: clamp(40px, 5vw, 64px) 0;
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--type-body);
  color: var(--brown);
  opacity: 0.55;
  margin: 0;
}
.client-list__head,
.client-list__rows li {
  display: grid;
  /* 4 visual columns: client (display) | sector | location | services.
     Duration span is hidden — most entries are "—" so the column wasted
     space. Ratios biased toward client name + services for balance. */
  grid-template-columns: 1.5fr 1.1fr 1fr 1.8fr;
  gap: clamp(16px, 2vw, 28px);
  padding: clamp(12px, 1.2vw, 18px) 0;
  align-items: baseline;
}
/* Hide the Duration span (4th child) in both the head and each row. */
.client-list__head > span:nth-child(4),
.client-list__rows li > span:nth-child(4) {
  display: none;
}
.client-list__head {
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  border-bottom: 1px solid rgba(77, 59, 55, 0.18);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.55;
}
.client-list__rows {
  list-style: none;
  margin: 0;
  padding: 0;
}
.client-list__rows li {
  border-bottom: 1px solid rgba(77, 59, 55, 0.1);
  font-family: var(--font-body);
  font-size: clamp(13px, 0.95vw, 15px);
  line-height: 1.5;
  color: var(--brown);
}
.client-list__rows li > span:first-child {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  letter-spacing: -0.005em;
  line-height: 1.2;
}
.client-list__rows li > span:nth-child(2),
.client-list__rows li > span:nth-child(3) {
  opacity: 0.7;
}
.client-list__rows li > span:nth-child(5) {
  opacity: 0.85;
}
/* The `display: grid` above overrides [hidden]'s UA `display: none`, so
   filtering needs an explicit rule. */
.client-list__rows li[hidden] { display: none; }

/* Stack the 4/5-col client list at ≤900 (was 768). Between 769–900 the
   "Sector" column ("Ultra-luxury hospitality" — 24 chars) and "Services"
   column were crushing against the 16px gap. */
@media (max-width: 900px) {
  .client-list { padding: clamp(64px, 10vw, 96px) 0 clamp(72px, 12vw, 112px); }
  .client-list__header {
    grid-template-columns: 1fr;
    gap: 20px;
    align-items: start;
  }
  .client-list__head { display: none; }
  .client-list__rows li {
    grid-template-columns: 1fr;
    gap: 4px;
    padding: 16px 0;
  }
  .client-list__rows li > span:not(:first-child) {
    font-size: 13px;
    opacity: 0.78;
  }
}

/* Phone — drop the pill wrapper around the filter bar so the two
   selects can stack full-width without bulging past the gutter, and
   bump font-size to 16px so iOS Safari doesn't auto-zoom on focus. */
@media (max-width: 600px) {
  .client-list__filters {
    border-radius: 12px;
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
  }
  .filter {
    display: flex;
    width: 100%;
    flex: 1 1 100%;
    gap: 12px;
    min-width: 0;
    align-items: center;
  }
  .filter__label {
    flex: 0 0 auto;
    width: 96px;
  }
  .filter__select {
    flex: 1 1 0;
    width: 100%;
    min-width: 0;
    max-width: 100%;
    box-sizing: border-box;
    min-height: 44px;
    /* 16px floor prevents iOS auto-zoom on focus. */
    font-size: 16px;
    padding: 10px 36px 10px 16px;
  }
}

/* ==========================================================================
   About page — Values section
   ========================================================================== */
.values {
  background: #DDD8CE; /* same alt-sand as case-study__section--alt */
  color: var(--brown);
  padding: clamp(96px, 12vw, 160px) 0;
}
.values__inner {
  display: flex;
  flex-direction: column;
  gap: clamp(48px, 6vw, 96px);
}
.values__header {
  max-width: 720px;
}
.values__eyebrow {
  margin: 0 0 clamp(16px, 2vw, 24px);
  opacity: 0.65;
}
.values__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.2;
  letter-spacing: -0.005em;
  color: var(--brown);
  margin: 0;
  /* Tightened from 22ch → 18ch so the title's right edge sits closer
     to the value items below (which cap at 32ch of body type ≈ a
     visually narrower measure). The previous 22ch let the title
     sprawl ~90px wider than the items on phone. */
  max-width: 18ch;
}
.values__grid {
  list-style: none;
  margin: 0;
  padding: clamp(40px, 5vw, 72px) 0 0;
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(32px, 4vw, 72px);
}
.values__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.4vw, 20px);
  padding-top: clamp(20px, 2vw, 28px);
  /* Reveal: items fade up + drift in, staggered by nth-child. */
  opacity: 0;
  transform: translateY(24px);
  transition:
    opacity 1.2s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.2s cubic-bezier(0.25, 0.1, 0.25, 1);
}
/* Thin top-rule on each value — draws in from 0 → 32px on reveal. */
.values__item::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 1px;
  background: rgba(77, 59, 55, 0.5);
  transition: width 1.4s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.values.is-visible .values__item {
  opacity: 1;
  transform: translateY(0);
}
.values.is-visible .values__item::before { width: 36px; }
.values.is-visible .values__item:nth-child(1)            { transition-delay: 0.2s; }
.values.is-visible .values__item:nth-child(2)            { transition-delay: 0.4s; }
.values.is-visible .values__item:nth-child(3)            { transition-delay: 0.6s; }
.values.is-visible .values__item:nth-child(1)::before    { transition-delay: 0.5s; }
.values.is-visible .values__item:nth-child(2)::before    { transition-delay: 0.7s; }
.values.is-visible .values__item:nth-child(3)::before    { transition-delay: 0.9s; }
/* Hover micro-interaction — small lift, faster than the reveal. */
@media (hover: hover) {
  .values.is-visible .values__item {
    transition:
      opacity 1.2s cubic-bezier(0.25, 0.1, 0.25, 1),
      transform 0.45s cubic-bezier(0.25, 0.1, 0.25, 1);
  }
  .values.is-visible .values__item:hover {
    transform: translateY(-4px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .values__item { opacity: 1; transform: none; transition: none; }
  .values__item::before { width: 36px; transition: none; }
}
.values__item .eyebrow {
  color: var(--brown);
  opacity: 0.85;
  margin: 0;
}
.values__item p:not(.eyebrow) {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.55;
  color: var(--brown);
  opacity: 0.78;
  margin: 0;
  max-width: 32ch;
}

/* Tablet — collapse from 3 to 2 columns so each value isn't crushed
   to ~210px wide between 769–900px (where its body copy was wrapping
   to 5–6 word lines). */
@media (max-width: 900px) {
  .values__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(28px, 4vw, 56px);
  }
}

@media (max-width: 768px) {
  .values { padding: clamp(72px, 10vw, 112px) 0; }
  .values__grid {
    grid-template-columns: 1fr;
    gap: clamp(24px, 4vw, 40px);
    padding-top: clamp(28px, 4vw, 48px);
    /* Drop the full-width grid hairline on mobile — each value already
       carries its own short ::before rule, which gives enough delineation
       in a single-column stack. The long line reads as redundant. */
    border-top: none;
  }
}

/* ==========================================================================
   Services / How We Work page
   ========================================================================== */
/* Our Approach — sand bg, editorial typography, no diagram. Big
   statement up top, supporting paragraph, 3-pillar grid below. */
.approach {
  background: var(--sand);
  color: var(--brown);
  padding: clamp(96px, 12vw, 160px) 0;
}
.approach__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(48px, 6vw, 96px);
  align-items: center;
}
.approach__copy {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 3vw, 44px);
  max-width: 52ch;
}
.approach__eyebrow {
  margin: 0;
  opacity: 0.65;
}
.approach__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: var(--brown);
  margin: 0;
  max-width: 18ch;
}
.approach__lede {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.85;
  color: var(--brown);
  opacity: 0.78;
  margin: 0;
  max-width: 52ch;
}
/* Triadic diagram — three Canela words at the corners of a hairline
   triangle, center mark for Strategic Clarity. Lines draw on reveal,
   hover any pillar to focus + change the description below. */
.triad {
  position: relative;
  width: 100%;
  max-width: 640px;
  aspect-ratio: 1 / 0.9;
  margin: 0 auto;
  color: var(--brown);
}
.triad__lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.triad__path {
  opacity: 0.5;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition:
    stroke-dashoffset 2s cubic-bezier(0.25, 0.1, 0.25, 1) 0.3s,
    opacity 0.5s ease;
}
.approach.is-visible .triad__path { stroke-dashoffset: 0; }

/* Each corner is anchored at its apex with a caps eyebrow, display
   name, and a short sentence underneath. Sand bg punches the
   triangle line behind the labels so the type sits cleanly over it. */
.triad__point {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  background: var(--sand);
  /* Top padding leaves room for the absolute-positioned dot marker
     (pseudo) which sits at the box's TOP edge — the apex. */
  padding: 22px clamp(10px, 1.4vw, 18px) 8px;
  color: var(--brown);
  text-align: center;
  /* Cap label width so long names + sentences wrap to a column rather
     than overflowing past the diagram's 8%/92% anchor points. */
  max-width: clamp(220px, 26vw, 280px);
  opacity: 0;
  transition: opacity 1.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.triad__eyebrow {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.7;
}
/* Triad labels — sized smaller than --type-sub on purpose. The points
   are absolutely positioned at left:8% / right:92% so a wider label
   overflows the canvas. Keep this clamp local. */
.triad__name {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(19px, 1.4vw + 11px, 25px);
  line-height: 1.15;
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.triad__point-desc {
  margin: 2px 0 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.6;
  color: var(--brown);
  opacity: 0.85;
}
/* Boxes anchor TOP-at-apex (not center) so the dot pseudo can sit
   exactly on the corner and the labels stack cleanly below. */
.triad__point--brand       { top: 8%;  left: 50%; transform: translateX(-50%); }
.triad__point--people      { top: 88%; left: 8%;  transform: translateX(-50%); }
.triad__point--operations  { top: 88%; left: 92%; transform: translateX(-50%); }
/* Static dot marker at each apex — anchors the pillar to its triangle
   corner. No pulse, no hover state. */
.triad__point::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: currentColor;
  transform: translate(-50%, -50%);
}
.approach.is-visible .triad__point { opacity: 1; }
.approach.is-visible .triad__point--brand      { transition-delay: 1.4s; }
.approach.is-visible .triad__point--people     { transition-delay: 1.7s; }
.approach.is-visible .triad__point--operations { transition-delay: 2s; }

/* Center mark — caps eyebrow + display name for the synthesis: e.g.
   "COMMERCIAL PERFORMANCE / Sustainable Value". */
.triad__center {
  position: absolute;
  top: 60%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  pointer-events: none;
  text-align: center;
  opacity: 0;
  transition: opacity 1s ease 2.4s;
}
.approach.is-visible .triad__center { opacity: 1; }
.triad__center-eyebrow {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.55;
}
.triad__center-name {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(19px, 1.4vw + 11px, 25px);
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: var(--brown);
}
.triad__center-desc {
  margin: 2px 0 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.6;
  color: var(--brown);
  opacity: 0.85;
}


/* ==========================================================================
   Approach — STATIC PREVIEW variant (our-approach-static.html only).
   Three pillars laid out inline; descriptions visible by default.
   Lives behind .approach--static so the live page is unaffected.
   ========================================================================== */
.approach--static {
  background: var(--sand);
  color: var(--brown);
  padding: clamp(96px, 12vw, 180px) 0 clamp(96px, 12vw, 180px);
}
.approach-static {
  display: flex;
  flex-direction: column;
  gap: clamp(56px, 7vw, 96px);
}
.approach-static__head {
  max-width: 60ch;
}
.approach-static__head .approach__title {
  margin: 0 0 clamp(20px, 2vw, 32px);
}
.approach-static__head .approach__lede {
  margin: 0;
}

.pillars {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(40px, 5vw, 80px);
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  padding-top: clamp(40px, 4vw, 56px);
}
.pillar {
  display: flex;
  flex-direction: column;
  gap: clamp(10px, 1vw, 16px);
}
.pillar__eyebrow {
  margin: 0;
  color: var(--brown);
  opacity: 0.55;
}
.pillar__name {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(22px, 1.6vw + 12px, 32px);
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--brown);
}
.pillar__body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.7;
  color: var(--brown);
  opacity: 0.85;
  max-width: 36ch;
}

.approach-static__synthesis {
  margin: 0;
  max-width: 60ch;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(20px, 1.4vw + 10px, 28px);
  line-height: 1.35;
  color: var(--brown);
  display: flex;
  flex-direction: column;
  gap: clamp(8px, 0.8vw, 14px);
  padding-top: clamp(32px, 3vw, 48px);
  border-top: 1px solid rgba(77, 59, 55, 0.18);
}
.approach-static__synthesis .eyebrow {
  font-family: var(--font-body);
  font-weight: 400;
  opacity: 0.55;
}

@media (max-width: 900px) {
  .pillars {
    grid-template-columns: 1fr;
    gap: clamp(32px, 6vw, 48px);
  }
}

@media (max-width: 900px) {
  .approach__inner {
    grid-template-columns: 1fr;
    gap: clamp(40px, 6vw, 64px);
    align-items: start;
  }
  .approach__title { max-width: none; }
  .approach__copy { max-width: none; }
}
@media (max-width: 768px) {
  .approach { padding: clamp(72px, 10vw, 112px) 0; }
  /* On phone the triad reads as a clean diagram — eyebrow + name at
     each apex and a centre mark, no descriptions. The page intro
     above already explains the concept; the Venn carries the visual. */
  .triad {
    aspect-ratio: 1 / 0.95;
    max-width: 380px;
    margin-bottom: clamp(40px, 8vw, 64px);
  }
  .triad__point { max-width: clamp(110px, 36vw, 160px); }
  .triad__point--people     { left: 14%; }
  .triad__point--operations { left: 86%; }
  .triad__point-desc,
  .triad__center-desc { display: none; }
  .triad__center { top: 58%; }
}
@media (prefers-reduced-motion: reduce) {
  .triad__path { stroke-dashoffset: 0; transition: none; }
  .triad__point,
  .triad__center { opacity: 1; transition: none; }
}

/* Service tag pills — used inside each service section to list the
   four practical engagement areas. */
/* Service items — clean editorial list, no boxes. The previous pill
   treatment was reading as "clickable button" which it isn't. Items
   sit as a vertical list with a hairline rule at the top, separated
   by thin dividers, so they read as a list of disciplines, not CTAs. */
.service__tags {
  list-style: none;
  margin: clamp(12px, 1.4vw, 20px) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  border-top: 1px solid rgba(77, 59, 55, 0.18);
}
.service__tags li {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: clamp(13px, 0.95vw, 15px);
  letter-spacing: 0.02em;
  padding: clamp(10px, 1vw, 14px) 0;
  color: var(--brown);
  opacity: 0.85;
  border-bottom: 1px solid rgba(77, 59, 55, 0.12);
}

/* Editorial text link with arrow — case study link for each service. */
.service__cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: clamp(20px, 2.4vw, 32px);
  padding-bottom: 6px;
  font-family: var(--font-body);
  font-size: clamp(13px, 0.95vw, 15px);
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brown);
  text-decoration: none;
  border-bottom: 1px solid rgba(77, 59, 55, 0.45);
  transition: gap 0.3s ease, border-color 0.3s ease;
  align-self: flex-start;
}
.service__cta svg { transition: transform 0.3s ease; }
.service__cta:hover { gap: 16px; border-color: var(--brown); }
.service__cta:hover svg { transform: translateX(4px); }

/* Services-page CTA banner — brown wash like the about page (instead
   of the case-study detail blue). */
.services-page .case-study__cta { background: var(--brown); }
.services-page .case-study__cta-overlay {
  background: linear-gradient(
    to right,
    var(--brown) 0%,
    var(--brown) 25%,
    rgba(77, 59, 55, 0.7) 50%,
    rgba(77, 59, 55, 0) 80%
  );
}
.services-page .case-study__section:last-of-type::after {
  background: linear-gradient(to bottom, transparent, var(--brown));
}
/* Section headings on services page match the .h1 size used elsewhere
   for consistency across the site. */
.services-page .case-study__heading {
  font-size: var(--type-h2);
  line-height: 1.15;
}

/* ==========================================================================
   Case Study page
   ========================================================================== */

/* Case-study hero override — lilac bg behind the shrinking image.
   Scoped to body.case-study-page so the homepage hero stays brown. */
.case-study-page .hero {
  background: var(--brown);
}
.hero__video,
.case-study__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* Wrapper that contains case-study videos needs relative positioning. */
.case-study__overview-media,
.case-study__section-media {
  position: relative;
}

/* 01_Hero — brown wash, eyebrow + display title left, image right.
   Padding-top accounts for the inverted nav above. */
.case-study__hero {
  background: var(--brown);
  color: var(--cream);
  padding: clamp(140px, 16vw, 220px) 0 clamp(80px, 10vw, 140px);
}
.case-study__hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(48px, 7vw, 120px);
  align-items: center;
}
.case-study__eyebrow {
  color: var(--cream);
  opacity: 0.7;
  margin: 0 0 clamp(24px, 3vw, 40px);
}
.case-study__hero-title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--cream);
  margin: 0;
  max-width: 14ch;
}
.case-study__hero-media {
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
.case-study__hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Section type — base layout reused by overview / challenge / approach /
   outcome. Alternating image side via modifier classes on the media. */
.case-study__overview,
.case-study__section {
  background: var(--sand);
  color: var(--brown);
  padding: clamp(144px, 16vw, 224px) 0;
}
.case-study__section--alt {
  background: #DDD8CE; /* slight tint to break the rhythm */
}
.case-study__overview-inner,
.case-study__section-inner {
  display: grid;
  /* Image side now ~65% of the row (was 60%, started at 50%). */
  grid-template-columns: minmax(0, 0.7fr) minmax(0, 1.3fr);
  gap: clamp(48px, 7vw, 120px);
  align-items: center;
}
/* When the media is on the left side, swap the column ratio so the
   image still takes the larger share regardless of order. */
.case-study__section-inner:has(.case-study__section-media--left) {
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 0.7fr);
}

.case-study__overview-copy,
.case-study__section-copy {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.6vw, 36px);
  /* Parallax — text moves ~1.75× the image speed for the differential
     "gliding past each other" feel (Palmer-studio pattern). */
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .case-study__overview-copy,
  .case-study__section-copy { transform: none; }
}
@media (max-width: 900px) {
  .case-study__overview-copy,
  .case-study__section-copy { transform: none; }
}
.case-study__heading {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--type-h2);
  line-height: 1.2;
  letter-spacing: 0;
  color: var(--brown);
  margin: 0;
}
/* On the about page, section headings drop to --type-h3 to sit at the
   same rhythm as the founder teaser blocks. Body stays on --type-body
   (token default) so the Specialist Network paragraph reads at the
   same size as the Liv/Alex bios on the same page. */
.about-page .case-study__heading {
  font-size: var(--type-h3);
  line-height: 1.3;
}
.about-page .case-study__section-copy {
  gap: clamp(12px, 1.4vw, 20px);
}
/* About-page CTA banner — brown scrim instead of the blue/grey wash
   used on case-study detail pages. The atmospheric hero image bleeds
   under a left-to-right brown gradient so the copy stays legible. */
.about-page .case-study__cta { background: var(--brown); }
.about-page .case-study__cta-overlay {
  background: linear-gradient(
    to right,
    var(--brown) 0%,
    var(--brown) 25%,
    rgba(77, 59, 55, 0.7) 50%,
    rgba(77, 59, 55, 0) 80%
  );
}
.about-page .case-study__section:last-of-type::after {
  background: linear-gradient(to bottom, transparent, var(--brown));
}
.case-study__body {
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.4vw, 24px);
}
.case-study__body p {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.55;
  margin: 0;
  max-width: 52ch;
}

.case-study__overview-media,
.case-study__section-media {
  width: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  /* Parallax — JS writes --parallax-y per the data-parallax attribute. */
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
.case-study__section-media--left  { order: -1; }
.case-study__section-media--right { order: 0;  }
@media (prefers-reduced-motion: reduce) {
  .case-study__overview-media,
  .case-study__section-media { transform: none; }
}
.case-study__overview-media img,
.case-study__section-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Services list (under overview) and outcomes list. */
.case-study__services {
  margin-top: clamp(16px, 2vw, 28px);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.case-study__services .eyebrow { margin: 0 0 6px; }
.case-study__services ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
}

.case-study__outcomes {
  list-style: none;
  margin: clamp(8px, 1vw, 16px) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(16px, 1.8vw, 24px);
}
.case-study__outcomes li {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.case-study__outcomes .eyebrow { margin: 0; }
.case-study__outcomes p:not(.eyebrow) {
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.5;
  margin: 0;
  max-width: 44ch;
  color: var(--brown);
}

/* 05_Pull Quote — blue wash, italic display, dot attribution. */
.case-study__quote {
  background: var(--blue);
  color: var(--cream);
  padding: clamp(96px, 12vw, 160px) 0;
}
.case-study__quote-inner {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(28px, 3.4vw, 48px);
  max-width: 1100px;
}
.case-study__quote-text {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.35;
  letter-spacing: -0.02em;
  color: var(--cream);
  margin: 0;
  max-width: 52ch;
  /* Fade + translate up on reveal — same timing as homepage testimonial. */
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity 1.8s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.8s cubic-bezier(0.25, 0.1, 0.25, 1);
  transition-delay: 0.1s;
}
.case-study__quote.is-visible .case-study__quote-text {
  opacity: 1;
  transform: translateY(0);
}
.case-study__quote-attr {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.55;
  margin: 0;
  color: var(--cream);
  /* Attribution fades in 0.7s after the quote — same delay pattern as
     homepage testimonial so the quote settles before the dot + name. */
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity 1.8s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 1.8s cubic-bezier(0.25, 0.1, 0.25, 1);
  transition-delay: 0.8s;
}
.case-study__quote.is-visible .case-study__quote-attr {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .case-study__quote-text,
  .case-study__quote-attr {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
.case-study__quote-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cream);
  margin-top: 8px;
  flex-shrink: 0;
}
.case-study__quote-name { display: block; }
.case-study__quote-role { display: block; opacity: 0.65; }

/* 07_Final CTA — full-bleed boat photo with a soft slate-blue wash
   bleeding in from the left carrying the copy + button. */
.case-study__cta {
  position: relative;
  background: #8B93A7;
  color: var(--cream);
  padding: 0;
  overflow: hidden;
}
.case-study__cta-media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.case-study__cta-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.case-study__cta-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(
    to right,
    #8B93A7 0%,
    #8B93A7 25%,
    rgba(139, 147, 167, 0.7) 50%,
    rgba(139, 147, 167, 0) 80%
  );
}
/* Soft fade above the CTA — last sand section bleeds into brown so
   the transition into the closing wash isn't a hard line. */
.case-study__section:last-of-type {
  position: relative;
}
.case-study__section:last-of-type::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: clamp(120px, 14vw, 200px);
  background: linear-gradient(to bottom, transparent, var(--blue));
  pointer-events: none;
}
.case-study__cta-inner {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  min-height: clamp(260px, 26vw, 400px);
  padding: clamp(48px, 6vw, 80px) var(--gutter);
}
.case-study__cta-copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(20px, 2.4vw, 32px);
  max-width: 420px;
}
.case-study__cta-title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--cream);
  margin: 0;
}
/* --------------------------------------------------------------------------
   Pagination — minimal prev/next strip on case-study pages. Sits above
   the closing CTA so readers can jump to an adjacent case without
   scrolling back up. Just text + arrow, no images, no fanfare.
   -------------------------------------------------------------------------- */
.case-study__pagination {
  background: var(--sand);
  border-top: 1px solid rgba(77, 59, 55, 0.12);
  padding: clamp(32px, 4vw, 56px) var(--gutter);
}
.case-study__pagination-inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: clamp(24px, 4vw, 48px);
  max-width: var(--max-w);
  margin: 0 auto;
}
.case-study__pagination-link {
  display: inline-flex;
  flex-direction: column;
  gap: 6px;
  color: var(--brown);
  text-decoration: none;
  transition: opacity 0.3s ease;
}
.case-study__pagination-link:hover { opacity: 0.6; }
.case-study__pagination-link--prev { text-align: left; }
.case-study__pagination-link--next { text-align: right; margin-left: auto; }
.case-study__pagination-label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.6;
}
.case-study__pagination-name {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(18px, 1.6vw, 24px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.case-study__pagination-link--next .case-study__pagination-name { justify-content: flex-end; }
@media (max-width: 640px) {
  .case-study__pagination-inner {
    flex-direction: column;
    align-items: stretch;
    gap: 24px;
  }
  .case-study__pagination-link--next { margin-left: 0; }
}
/* --------------------------------------------------------------------------
   Case study — responsive breakpoints
   -------------------------------------------------------------------------- */

/* About-page only: stack the Specialist Network section at ≤1024 so
   it matches the teasers above (which stack at 1024). Without this,
   at 901–1024 the page jumps from stacked teasers back to a 2-col
   Specialist Network where the copy column shrinks to ~360px. */
@media (max-width: 1024px) {
  .about-page .case-study__section-inner {
    grid-template-columns: 1fr;
    gap: clamp(40px, 8vw, 64px);
  }
  .about-page .case-study__section-inner:has(.case-study__section-media--left) {
    grid-template-columns: 1fr;
  }
  .about-page .case-study__section-media {
    order: -1;
    aspect-ratio: 4 / 3;
    transform: none;
  }
}

/* Tablet — collapse the 2-col grid + image-on-top, scale down padding. */
@media (max-width: 900px) {
  .case-study__overview,
  .case-study__section {
    padding: clamp(96px, 13vw, 160px) 0;
  }
  .case-study__overview-inner,
  .case-study__section-inner {
    grid-template-columns: 1fr;
    gap: clamp(40px, 8vw, 64px);
  }
  .case-study__section-inner:has(.case-study__section-media--left) {
    grid-template-columns: 1fr;
  }
  /* Mobile: image always above the copy regardless of side modifier.
     Parallax disabled — touch-scroll renders smoother without the
     JS-driven transform on every frame. */
  .case-study__overview-media,
  .case-study__section-media {
    order: -1;
    aspect-ratio: 4 / 3;
    transform: none;
  }
  .case-study__quote      { padding: clamp(72px, 10vw, 120px) 0; }
  .case-study__cta-inner  {
    min-height: clamp(220px, 32vw, 320px);
    padding: clamp(48px, 7vw, 80px) var(--gutter);
  }
  .case-study__cta-copy   { max-width: 360px; }
}

/* Phone — drop one more notch in padding, type, and images. Disables
   the image parallax (fixed transform) so the layout stays settled. */
@media (max-width: 600px) {
  .case-study__overview,
  .case-study__section {
    padding: clamp(80px, 12vw, 120px) 0;
  }
  .case-study__overview-inner,
  .case-study__section-inner { gap: 32px; }
  .case-study__overview-media,
  .case-study__section-media { aspect-ratio: 4 / 3; }
  .case-study__heading      { line-height: 1.2; }
  .case-study__body p       { line-height: 1.55; max-width: none; }
  .case-study__services ul  { gap: 4px; }
  .case-study__outcomes     { gap: 16px; }
  .case-study__quote        { padding: clamp(56px, 9vw, 88px) 0; }
  .case-study__quote-attr   { font-size: var(--type-body); }
  .case-study__cta-inner    {
    /* Raised min-height floor — at 320 the previous 240 floor cropped
       the panel below where the multi-line CTA title needed room. */
    min-height: clamp(320px, 80vw, 400px);
    padding: 48px var(--gutter);
  }
  /* Wash a bit more brand-blue across mobile so the copy stays legible
     even when the image fills more of the cropped narrow frame.
     Scoped away from .about-page and .airelles-page so those keep
     their brown wash on mobile (they override the desktop overlay
     and shouldn't flip to blue here). */
  .case-study__cta-overlay {
    background: linear-gradient(
      to right,
      #8B93A7 0%,
      #8B93A7 45%,
      rgba(139, 147, 167, 0.7) 65%,
      rgba(139, 147, 167, 0) 95%
    );
  }
  .about-page .case-study__cta-overlay,
  .airelles-page .case-study__cta-overlay {
    background: linear-gradient(
      to right,
      var(--brown) 0%,
      var(--brown) 45%,
      rgba(77, 59, 55, 0.7) 65%,
      rgba(77, 59, 55, 0) 95%
    );
  }
  /* Tighter sand→blue blend at the bottom of the last section on mobile. */
  .case-study__section:last-of-type::after {
    height: clamp(80px, 16vw, 140px);
  }
}

/* ==========================================================================
   Contact page
   - Image hero (uses shared .hero pattern with scroll-shrink)
   - Body: editorial underline form (left) + personal letter & details (right)
   ========================================================================== */
.contact-page { background: var(--sand); }

/* Body — sand background, two columns. The right column is narrower than the
   form so the page reads "form first, considered note alongside". */
.contact-body {
  position: relative;
  background: var(--sand);
  color: var(--brown);
  padding: clamp(40px, 5vw, 80px) 0 clamp(56px, 6vw, 96px);
}
/* Hairline divider before the footer — inset by the page gutter so it
   matches the width of the footer nav's top + bottom rules, rather than
   running edge-to-edge of the viewport. */
.contact-body::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: var(--gutter);
  right: var(--gutter);
  height: 1px;
  background: rgba(77, 59, 55, 0.18);
}
.contact-body__inner {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: clamp(48px, 6vw, 80px);
  max-width: clamp(720px, 60vw, 960px);
}

/* ----- Editorial underline form -----
   No fills, no pills. Just label + thin brown rule that thickens on focus.
   Reads as luxury hospitality stationery rather than a Squarespace form. */
.contact-form {
  display: flex;
  flex-direction: column;
  gap: clamp(28px, 2.6vw, 40px);
}
.contact-form__label {
  margin: 0 0 clamp(6px, 0.8vw, 14px);
  color: var(--brown);
  opacity: 0.65;
}
.contact-form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 3vw, 48px);
}
.contact-form__field {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.contact-form__field label {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.65px;
  text-transform: uppercase;
  color: rgba(77, 59, 55, 0.55);
  transition: color 0.3s ease;
}
.contact-form__field input,
.contact-form__field textarea {
  width: 100%;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--type-body);
  line-height: 1.4;
  color: var(--brown);
  background: var(--cream);
  border: 1px solid rgba(77, 59, 55, 0.10);
  border-radius: 4px;
  padding: 14px 16px;
  outline: none;
  transition:
    border-color 0.35s ease,
    background 0.35s ease,
    color 0.3s ease;
  -webkit-appearance: none;
  appearance: none;
}
.contact-form__field textarea {
  resize: vertical;
  min-height: 156px;
}
.contact-form__field input:hover,
.contact-form__field textarea:hover {
  border-color: rgba(77, 59, 55, 0.22);
}
.contact-form__field input:focus,
.contact-form__field textarea:focus {
  border-color: rgba(77, 59, 55, 0.45);
  background: #FBF8EE;
}
.contact-form__field:focus-within label {
  color: var(--brown);
}
.contact-form__optional {
  font-size: 10px;
  opacity: 0.6;
  margin-left: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
/* Mobile-safe autofill — Chrome paints autofills with a yellow background;
   keep it transparent so the underline aesthetic survives. */
.contact-form__field input:-webkit-autofill,
.contact-form__field textarea:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--cream) inset;
  -webkit-text-fill-color: var(--brown);
  caret-color: var(--brown);
}

/* Submit — sits left-aligned, brown outlined pill. Arrow nudges on hover.
   Stays on-brand: pills are reserved for CTAs, and this is a primary CTA. */
.contact-form__submit {
  margin-top: clamp(12px, 1.4vw, 24px);
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-width: 180px;
  height: 40px;
  padding: 0 24px;
  background: var(--brown);
  color: var(--cream);
  border: none;
  border-radius: 200px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.55px;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    background 0.3s ease,
    transform 0.3s ease;
}
.contact-form__submit svg {
  transition: transform 0.35s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.contact-form__submit:hover {
  background: #5a4642;
}
.contact-form__submit:hover svg {
  transform: translateX(6px);
}
.contact-form__submit:focus-visible {
  outline: 2px solid var(--brown);
  outline-offset: 4px;
}
.contact-form__submit:disabled {
  opacity: 0.55;
  cursor: progress;
}

/* Honeypot — hidden from sighted users and screen readers, but bots
   filling every visible/invisible field will tick this and get their
   submission silently dropped at /api/contact. */
.contact-form__honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Inline error — sits between the form fields and the submit button
   when /api/contact returns a non-200 response, so users see what
   actually happened instead of a fake success. */
.contact-form__error {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.5;
  color: #8a3a2d;
}
.contact-form__error[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Contact intro — direct contact details lead the section. Email at
   display weight as the human-route invitation, with a small intro line
   below bridging readers to the form. Hairline below separates it from
   the form fields.
   -------------------------------------------------------------------------- */
.contact-intro {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(8px, 1vw, 14px);
  padding-bottom: clamp(36px, 4.5vw, 56px);
  border-bottom: 1px solid rgba(77, 59, 55, 0.12);
}
.contact-intro__label {
  margin: 0;
  color: var(--brown);
  opacity: 0.6;
}
.contact-intro__email {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(20px, 2vw, 28px);
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--brown);
}
.contact-intro__email a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(77, 59, 55, 0.25);
  padding-bottom: 2px;
  transition: border-color 0.3s ease;
}
.contact-intro__email a:hover { border-color: var(--brown); }
.contact-intro__or {
  margin: clamp(10px, 1.2vw, 16px) 0 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  color: var(--brown);
  opacity: 0.7;
}
/* Socials sit inside the intro block as alternative contact methods,
   between the email and the bridge line into the form. */
.contact-intro__social {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin-top: clamp(6px, 0.8vw, 12px);
  font-family: var(--font-body);
  font-size: 13px;
  color: var(--brown);
  opacity: 0.7;
}
.contact-intro__social a {
  color: inherit;
  text-decoration: none;
  transition: opacity 0.3s ease;
}
.contact-intro__social a:hover { opacity: 0.55; }
.contact-intro__social span { opacity: 0.4; }

/* Inline success state — replaces the form once submission resolves.
   Same visual register as a contact-letter card so the column doesn't
   collapse; soft fade-in matches the rest of the page rhythm. */
.contact-form__success {
  display: flex;
  flex-direction: column;
  gap: clamp(12px, 1.4vw, 20px);
  max-width: 520px;
  opacity: 0;
  transform: translateY(8px);
  animation: contact-success-in 0.6s cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
}
.contact-form__success[hidden] { display: none; }
.contact-form__success-title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--brown);
  margin: 0;
}
.contact-form__success-body {
  font-family: var(--font-body);
  font-size: 14px; /* matches .contact-intro__or */
  line-height: 1.55;
  color: var(--brown);
  opacity: 0.8;
  margin: 0;
  max-width: 42ch;
}
@keyframes contact-success-in {
  to { opacity: 1; transform: translateY(0); }
}

/* ----- Details column ----- */
.contact-details {
  display: flex;
  flex-direction: column;
  gap: clamp(36px, 3.5vw, 56px);
  padding-top: clamp(0px, 1vw, 12px);
}

/* Personal letter — italic note + sign-off. Reads like a magazine
   editor's letter rather than form copy. */
.contact-letter {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: clamp(18px, 1.6vw, 26px);
}
.contact-letter__eyebrow {
  margin: 0;
  color: var(--brown);
  opacity: 0.65;
}
.contact-letter__note {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  line-height: 1.4;
  color: var(--brown);
}
.contact-letter__sign {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: clamp(4px, 0.8vw, 12px);
}
.contact-letter__name {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 15px;
  line-height: 1.4;
  color: var(--brown);
  /* Hairline above the name acts as the signature line on a letter. */
  padding-top: clamp(10px, 1vw, 16px);
  border-top: 1px solid rgba(77, 59, 55, 0.35);
  align-self: flex-start;
  padding-right: clamp(40px, 6vw, 90px);
}
.contact-letter__role {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.65px;
  text-transform: uppercase;
  color: rgba(77, 59, 55, 0.6);
}

/* Divider between letter and details */
.contact-details__divider {
  height: 1px;
  background: rgba(77, 59, 55, 0.14);
  width: 100%;
}

.contact-details__list {
  display: flex;
  flex-direction: column;
  gap: clamp(22px, 2vw, 30px);
}
.contact-details__label {
  margin: 0 0 clamp(2px, 0.4vw, 6px);
  color: var(--brown);
  opacity: 0.65;
}
.contact-details__group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.contact-details__small {
  margin: 0;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: rgba(77, 59, 55, 0.55);
}
.contact-details__line {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  line-height: 1.35;
  color: var(--brown);
  /* Long email at --type-sub can overflow the right edge once the
     details column drops to full-width on phone. */
  overflow-wrap: anywhere;
  max-width: 100%;
}
.contact-details__line a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(77, 59, 55, 0.25);
  transition: border-color 0.3s ease, color 0.3s ease;
}
.contact-details__line a:hover {
  border-color: var(--brown);
}
.contact-details__group--social {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.85;
  margin-top: clamp(4px, 1vw, 10px);
}
.contact-details__group--social a {
  text-decoration: none;
  color: inherit;
  border-bottom: 1px solid rgba(77, 59, 55, 0.3);
  padding-bottom: 1px;
  transition: border-color 0.3s ease;
}
.contact-details__group--social a:hover { border-color: var(--brown); }
.contact-details__group--social span { opacity: 0.4; }

/* ----- Reveal stagger ----- */
.contact-body .contact-form__label,
.contact-body .contact-form__row,
.contact-body .contact-form > .contact-form__field,
.contact-body .contact-form__submit {
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 0.55s cubic-bezier(0.25, 0.1, 0.25, 1),
    transform 0.55s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.contact-body.is-visible .contact-form__label,
.contact-body.is-visible .contact-form__row,
.contact-body.is-visible .contact-form > .contact-form__field,
.contact-body.is-visible .contact-form__submit {
  opacity: 1;
  transform: translateY(0);
}
.contact-body.is-visible .contact-form__label    { transition-delay: 0.06s; }
.contact-body.is-visible .contact-form__row      { transition-delay: 0.14s; }
.contact-body.is-visible .contact-form > .contact-form__field:nth-of-type(2) { transition-delay: 0.20s; }
.contact-body.is-visible .contact-form > .contact-form__field:nth-of-type(3) { transition-delay: 0.26s; }
.contact-body.is-visible .contact-form__submit   { transition-delay: 0.34s; }

@media (prefers-reduced-motion: reduce) {
  .contact-body .contact-form__label,
  .contact-body .contact-form__row,
  .contact-body .contact-form > .contact-form__field,
  .contact-body .contact-form__submit {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Mobile — single column, form first.
   Stack at 900 to align with the rest of the site's two-col → one-col
   flips (.approach__inner, .case-study__section-inner). At the previous
   820 threshold the form column shrank to ~370px between 768–820 with
   the details column squeezed beside it — awkward window. */
@media (max-width: 900px) {
  .contact-body__inner {
    grid-template-columns: 1fr;
    gap: clamp(56px, 12vw, 84px);
  }
  .contact-form__row {
    grid-template-columns: 1fr;
    gap: clamp(28px, 6vw, 36px);
  }
  .contact-form__submit {
    width: 100%;
  }
  .contact-details {
    border-top: 1px solid rgba(77, 59, 55, 0.14);
    padding-top: clamp(40px, 9vw, 60px);
  }
}

/* ==========================================================================
   Journal — listing + article. Sand-bg pages with a quiet editorial
   register. Reuses tokens; no new clamps invented at the component level.
   ========================================================================== */
.journal-page {
  background: var(--sand);
  color: var(--brown);
}

/* Journal pages sit on a sand bg, so the nav needs brown text
   and the brown logo (the inverted/cream variant is for dark heroes). */
.journal-article-page .site-nav,
.journal-article-page .site-nav__menu,
.journal-article-page .site-nav__contact,
.journal-listing-page .site-nav,
.journal-listing-page .site-nav__menu,
.journal-listing-page .site-nav__contact { color: var(--brown); }

/* ---- Listing top — Aman Stories register: no full-bleed hero, just
   a quiet eyebrow + display title + intro line, then straight into the
   image-led card grid below. Wider max-width + scoped gutter let the
   cards breathe across the full viewport, like aman.com/stories. ----- */
.journal-stories,
.journal-grid,
.journal-divider {
  --gutter: clamp(28px, 4vw, 64px);
  max-width: 1680px;
  margin-left: auto;
  margin-right: auto;
}
.journal-divider {
  width: 100%;
  border: 0;
  border-top: 1px solid rgba(77, 59, 55, 0.18);
}
.journal-stories {
  padding: clamp(140px, 16vw, 200px) 0 clamp(56px, 7vw, 96px);
}
.journal-stories__inner {
  text-align: center;
  max-width: 880px;
}
.journal-stories__eyebrow {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.55;
  margin: 0 0 clamp(20px, 2.5vw, 28px);
}
/* Page masthead — uses the shared --type-h1 token (same family as
   the hero title, so the journal's "Journal" mark sits at the same
   visual weight as the home hero. */
.journal-stories__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.05;
  letter-spacing: -0.005em;
  margin: 0 auto var(--space-sm);
  max-width: 14ch;
}
/* Intro reads as body copy — same size as article body, wider measure. */
.journal-stories__intro {
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.6;
  max-width: 640px;
  margin: 0 auto;
  opacity: 0.78;
}

/* ---- Card grid — 3 columns on desktop, 2 on tablet, 1 on phone.
   Square images, simple eyebrow + serif title + 2-line excerpt. Padding
   left and right come from the .container class on this element — the
   list resets only top/bottom, never the gutters. ----------------------- */
.journal-grid {
  list-style: none;
  margin: 0 auto;
  padding-top: 0;
  padding-bottom: clamp(96px, 14vw, 180px);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: clamp(32px, 3.5vw, 56px);
  row-gap: clamp(56px, 7vw, 96px);
}
@media (max-width: 980px) {
  .journal-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .journal-grid {
    grid-template-columns: 1fr;
    row-gap: clamp(40px, 8vw, 56px);
  }
}

.journal-card {
  display: block;
  text-decoration: none;
  color: var(--brown);
}
.journal-card__figure {
  margin: 0 0 clamp(20px, 2.4vw, 28px);
  overflow: hidden;          /* clip the image lift on hover */
}
.journal-card__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  transition: transform 0.9s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.journal-card__meta {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.55;
  margin: 0 0 clamp(12px, 1.4vw, 16px);
  transition: opacity 0.4s ease;
}
.journal-card__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h3);
  line-height: 1.22;
  letter-spacing: -0.005em;
  margin: 0 0 clamp(8px, 1vw, 12px);
  /* Hairline underline drawn-in on hover. inline-block + bg-image
     positions a 1px line at the bottom that grows from 0 → 100%. */
  display: inline-block;
  background-image: linear-gradient(currentColor, currentColor);
  background-position: 0 100%;
  background-repeat: no-repeat;
  background-size: 0 1px;
  padding-bottom: 4px;
  transition: background-size 0.6s cubic-bezier(0.25, 0.1, 0.25, 1);
}

/* Card hover — three layers: image scales subtly (1 → 1.04), title
   draws its underline left-to-right, meta + subtitle fade up. */
.journal-card:hover .journal-card__image { transform: scale(1.04); }
.journal-card:hover .journal-card__title { background-size: 100% 1px; }
.journal-card:hover .journal-card__meta,
.journal-card:hover .journal-card__subtitle { opacity: 0.9; }
/* Subtitle / topic tag — sits under the title as the editorial frame
   for the piece. Same caps register as the article-page subtitle. */
.journal-card__subtitle {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.55;
  margin: 0 0 clamp(12px, 1.4vw, 16px);
  transition: opacity 0.4s ease;
}
.journal-card__excerpt {
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.55;
  margin: 0;
  opacity: 0.75;
  max-width: 56ch;
}

/* ---- Article header — centred, sand bg, magazine masthead register.
   Top: back-link (left). Centre stack: issue number, eyebrow, title,
   byline. Hairline above/below the title block to frame it like a
   Kinfolk masthead. Edge gutter matches the nav offset. ------------- */
.journal-article-header,
.journal-article-body,
.journal-article-end {
  --gutter: clamp(16px, 2vw, 28px);
}
.journal-article-header {
  background: var(--sand);
  color: var(--brown);
  padding: clamp(140px, 16vw, 200px) 0 clamp(56px, 7vw, 88px);
  position: relative;
}
.journal-article-header__inner {
  max-width: 760px;
  text-align: center;
}
.journal-article-header__back {
  position: absolute;
  /* The absolute .site-nav is 138px tall on desktop. Previous top value
     (clamp 96–140) hid the back-link behind the nav from 721–1255px.
     Raised to keep it clear at every desktop width. */
  top: clamp(160px, 13vw, 188px);
  left: var(--gutter);
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--brown);
  text-decoration: none;
  opacity: 0.6;
  /* 12px vertical padding gives a 44px+ tap surface around the 11px
     uppercase text — meets touch-target minimum without changing the
     visual weight of the link. */
  padding: 12px 0;
  transition: opacity 0.3s ease;
}
.journal-article-header__back:hover { opacity: 1; }
.journal-article-header__issue {
  display: block;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.55;
  margin: 0 0 clamp(28px, 4vw, 40px);
}
.journal-article-header__eyebrow {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  opacity: 0.6;
  margin: 0 0 clamp(20px, 2.5vw, 28px);
  padding-bottom: 14px;
  border-bottom: 1px solid rgba(77, 59, 55, 0.3);
}
.journal-article-header__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.1;
  letter-spacing: -0.005em;
  margin: 0 auto clamp(20px, 2vw, 28px);
  max-width: 22ch;
}
/* Topic / theme tag — small caps subtitle that sits between the title
   and the byline. Echoes the issue line above the title for symmetry,
   gives each article a thematic frame without anchoring to a date. */
.journal-article-header__subtitle {
  margin: 0 auto clamp(28px, 3.5vw, 40px);
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.55;
}
.journal-article-header__byline {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(10px, 1.6vw, 16px);
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.6;
}
.journal-article-header__byline-dot {
  display: inline-block;
  width: 3px;
  height: 3px;
  background: currentColor;
  border-radius: 50%;
  opacity: 0.6;
}
/* Static-flip threshold raised from 720 → 1024. Between 721–1024 the
   absolute back-link was sitting in space already occupied by the
   138px tall .site-nav. On tablet/small-laptop the back-link now
   stacks centred above the title in the natural flow. */
@media (max-width: 1024px) {
  .journal-article-header__back {
    position: static;
    display: block;
    margin: 0 auto clamp(32px, 8vw, 48px);
    text-align: center;
  }
  .journal-article-header { padding-top: clamp(120px, 24vw, 160px); }
}

/* ---- Article body — narrow reading column, drop cap on opener,
   centred pull quote framed by hairlines. Cereal/Kinfolk register. ---- */
.journal-article-body {
  padding: clamp(56px, 7vw, 96px) 0 clamp(96px, 14vw, 180px);
  border-top: 1px solid rgba(77, 59, 55, 0.18);
}
.journal-article-body__inner {
  max-width: 760px;
}
.journal-article-body p {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--type-body);
  line-height: 1.78;
  margin: 0 0 clamp(20px, 2.4vw, 28px);
  color: var(--brown);
}
.journal-article-body p:last-child { margin-bottom: 0; }

/* Q&A question heads (used in the Wellness conversation article).
   Display weight in Canela so each question reads as the interviewer's
   lift, with the answer below in body type. Generous top margin
   separates from the previous answer; tighter bottom hugs the answer
   that follows. Without this rule, the markup falls back to default
   browser <h2> bold sans, which clashes with the editorial register. */
.journal-article-body__q {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-sub);
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--brown);
  margin: clamp(40px, 5vw, 64px) 0 clamp(14px, 1.4vw, 20px);
}
.journal-article-body__q:first-child { margin-top: 0; }

/* Drop cap on the opening paragraph — Canela display, four lines tall.
   Tracks slightly tighter to settle visually next to the body.
   Intentionally outside the type ladder: drop caps are sized to the
   body's line-height, not to a heading tier. */
.journal-article-body__inner > p:first-child::first-letter {
  font-family: var(--font-display);
  font-weight: 300;
  float: left;
  font-size: clamp(56px, 5.6vw + 12px, 88px);
  line-height: 0.85;
  padding: 8px 14px 0 0;
  margin: 4px 4px 0 -2px;
  color: var(--brown);
}

/* In-body editorial figure — a single plate breaks the reading column,
   captioned in tracked small caps. Width matches the body column for
   restraint; can be made wider with a different modifier later. */
.journal-article-body__figure {
  margin: clamp(56px, 8vw, 96px) 0;
}
.journal-article-body__figure img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
/* Article hero — full-bleed atmospheric image above the masthead.
   Optional per article; sits between the navs and the typographic
   header. Aspect ratio cropped wide so the image reads as a
   cinematographic lead, not a portrait card. */
.journal-article-hero {
  width: 100%;
  background: var(--brown);
  overflow: hidden;
}
.journal-article-hero img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 7;
  object-fit: cover;
}

/* Responsive video embed (YouTube etc) — sits with the same vertical
   rhythm as figures, locked to a 16:9 frame so the iframe scales with
   the reading column. */
.journal-article-body__video {
  position: relative;
  margin: clamp(56px, 8vw, 96px) 0;
  aspect-ratio: 16 / 9;
  background: #000;
}
.journal-article-body__video iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}
/* Audio podcast embed (Spotify etc) — fixed-height mini player. Sits
   on its own row with the same outer rhythm as a figure / video, but
   constrained in width so the strip doesn't stretch absurdly wide. */
.journal-article-body__podcast {
  margin: clamp(40px, 6vw, 72px) 0;
  display: flex;
  justify-content: center;
}
.journal-article-body__podcast iframe {
  width: 100%;
  max-width: 540px;
  height: 152px;
  border: 0;
  display: block;
}
/* Inline external link in body copy — underlined hairline, on-hover
   thickens. Used for source / out-link references. */
.journal-article-body__link {
  color: var(--brown);
  text-decoration: none;
  border-bottom: 1px solid rgba(77, 59, 55, 0.3);
  padding-bottom: 2px;
  transition: border-color 0.3s ease;
}
.journal-article-body__link:hover { border-color: var(--brown); }
.journal-article-body__caption {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  opacity: 0.55;
  margin: clamp(14px, 1.6vw, 18px) 0 0;
}

/* Centred pull quote — display serif, framed by hairlines. Spans the
   full body column so it lines up with the rest of the reading copy. */
.journal-article-body__pull {
  text-align: center;
  /* Inscriptional-caps treatment to echo the logo wordmark.
     Penumbra HalfSerif is the site's Roman serif caps face; uppercased
     and letter-spaced it reads as a quiet testimonial mark between the
     two hairlines. Size lowered vs mixed-case because caps render
     visually larger at the same point size. */
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(20px, 1.1vw + 12px, 28px);
  line-height: 1.5;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: clamp(48px, 7vw, 80px) 0;
  padding: clamp(40px, 5.5vw, 64px) clamp(20px, 4vw, 56px);
  border-top: 1px solid rgba(77, 59, 55, 0.32);
  border-bottom: 1px solid rgba(77, 59, 55, 0.32);
  border-left: none;
  color: var(--brown);
}

/* ---- Article end (back-link + CTA, sand band) ------------------------ */
.journal-article-end {
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  padding: clamp(40px, 5vw, 64px) 0;
}
.journal-article-end__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-md);
  flex-wrap: wrap;
}
.journal-article-end__back {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.55px;
  text-transform: uppercase;
  color: var(--brown);
  text-decoration: none;
  opacity: 0.7;
  /* 12px vertical padding lifts the touch surface to ~44px around
     the 11px uppercase label. */
  padding: 12px 0;
  transition: opacity 0.3s ease;
}
.journal-article-end__back:hover { opacity: 1; }

/* Narrow phones — back-link + CTA were sitting side-by-side with no
   gap below ~480px. Stack to give each its own row. */
@media (max-width: 480px) {
  .journal-article-end__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: clamp(20px, 5vw, 28px);
  }
}

/* --------------------------------------------------------------------------
   Legal pages — Privacy, Cookies. Quiet centred composition: small
   eyebrow, display title, generous body whitespace. Placeholder copy
   sits in the centre of the page until the legal partner provides
   the final text.
   -------------------------------------------------------------------------- */
.legal-page { background: var(--sand); color: var(--brown); }

.legal-header {
  padding: clamp(140px, 18vw, 220px) 0 var(--space-xl);
}
.legal-header__inner {
  max-width: clamp(800px, 70vw, 1120px);
  padding-left: clamp(16px, 1.5vw, 32px);
  padding-right: clamp(16px, 1.5vw, 32px);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-md);
}
.legal-header__eyebrow {
  color: var(--brown);
  opacity: 0.6;
}
.legal-header__title {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h1);
  line-height: 1.05;
  letter-spacing: -0.005em;
  color: var(--brown);
  margin: 0;
}

.legal-body {
  padding: 0 0 clamp(120px, 16vw, 200px);
}
.legal-body__inner {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.legal-body__placeholder {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h2);
  line-height: 1.2;
  color: var(--brown);
  margin: 0;
}
.legal-body__note {
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: 1.6;
  color: var(--brown);
  opacity: 0.75;
  margin: 0;
}
.legal-body__note a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: opacity 0.3s ease;
}
.legal-body__note a:hover { opacity: 0.6; }
.legal-body__inline-button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
  transition: opacity 0.3s ease;
}
.legal-body__inline-button:hover { opacity: 0.6; }

/* Structured legal content — used when the full policy is in place,
   replacing the centred placeholder. Block layout with adjacent-
   sibling margins (instead of flex+gap) so we can tune heading-to-
   paragraph rhythm per pair: lots of air above h2 to separate
   sections, tight under h2/h3 so the heading sits close to its
   paragraph rather than floating between them. */
/* Wider editorial column for the policy text — internal side padding
   pulled in tighter so the text runs closer to the column edge. */
.legal-body__content {
  max-width: clamp(800px, 70vw, 1120px);
  margin: 0 auto;
  padding: 0 clamp(16px, 1.5vw, 32px);
}
.legal-body__content > * { margin: 0; }
.legal-body__content > * + * { margin-top: var(--space-md); }
.legal-body__content > h2 { margin-top: var(--space-xl); }
.legal-body__content > h2:first-of-type { margin-top: var(--space-md); }
.legal-body__content > h2 + * { margin-top: var(--space-md); }
.legal-body__content > h3 { margin-top: var(--space-lg); }
.legal-body__content > h3 + * { margin-top: var(--space-sm); }

.legal-body__intro {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.6;
  color: rgba(77, 59, 55, 0.88);
}
.legal-body__content h2 {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--type-h3);
  line-height: 1.15;
  letter-spacing: -0.005em;
  color: var(--brown);
}
.legal-body__content h3 {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--type-eyebrow);
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.75;
}
.legal-body__content p,
.legal-body__content li {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: var(--type-body);
  line-height: 1.6;
  color: rgba(77, 59, 55, 0.88);
}
/* <strong> tags inside legal copy mark defined terms ("Client",
   "Data Protection Legislation", etc.) for accessibility, but the
   text should read identically to the surrounding paragraph — no
   weight difference, no colour difference — since the only loaded
   Riviera Nights weights are Light and Regular. */
.legal-body__content strong {
  font-weight: inherit;
  color: inherit;
}
.legal-body__content ul {
  list-style: disc;
  padding-left: var(--space-md);
}
.legal-body__content ul > li + li { margin-top: var(--space-xs); }
.legal-body__content a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: opacity 0.3s ease;
}
.legal-body__content a:hover { opacity: 0.6; }
.legal-body__meta {
  margin-top: var(--space-2xl);
  padding-top: var(--space-md);
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--brown);
  opacity: 0.6;
}

/* --------------------------------------------------------------------------
   Cookie consent banner — bottom-pinned, discreet, fades in. Sand
   background to match the page, with a subtle top border so it reads
   as a discrete band rather than an overlay. Two action buttons
   inherit the existing CTA pill spec.
   -------------------------------------------------------------------------- */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90;
  background: var(--sand);
  border-top: 1px solid rgba(77, 59, 55, 0.18);
  padding: var(--space-md) 0;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.4s ease, transform 0.4s ease;
  pointer-events: none;
}
.cookie-banner.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.cookie-banner__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  padding: 0 var(--gutter);
  max-width: 1440px;
  margin: 0 auto;
}
.cookie-banner__copy {
  font-family: var(--font-body);
  font-size: 13px;
  line-height: 1.5;
  color: var(--brown);
  margin: 0;
  max-width: 56ch;
}
.cookie-banner__copy a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: opacity 0.3s ease;
}
.cookie-banner__copy a:hover { opacity: 0.6; }
.cookie-banner__actions {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}
.cookie-banner__btn {
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.055em;
  text-transform: uppercase;
  height: 40px;
  padding: 0 24px;
  border-radius: 200px;
  cursor: pointer;
  transition: background 0.3s ease, color 0.3s ease, border-color 0.3s ease;
}
.cookie-banner__btn--ghost {
  background: transparent;
  color: var(--brown);
  border: 1px solid rgba(77, 59, 55, 0.4);
}
.cookie-banner__btn--ghost:hover {
  background: rgba(77, 59, 55, 0.06);
}
.cookie-banner__btn--solid {
  background: var(--brown);
  color: var(--cream);
  border: 1px solid var(--brown);
}
.cookie-banner__btn--solid:hover {
  background: #3a2c29;
  border-color: #3a2c29;
}

@media (max-width: 640px) {
  .cookie-banner__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-md);
  }
  .cookie-banner__actions {
    align-self: stretch;
  }
  .cookie-banner__btn {
    flex: 1;
  }
}
