/* ============================================================
   A SALA — wellness hub, Lisbon
   ------------------------------------------------------------
   LAYER 1 — DESIGN TOKENS
   Every colour, space, radius and type step used on the site is
   declared here and nowhere else. Components below reference
   tokens only, so a new page inherits the system for free and
   a rebrand is a single edit in this block.

   Palette is taken straight from the A SALA logo:
   deep green #2c4c49 · sage #839c9a · sand #d7cdc0 · clay #deae87

   FILE MAP (in source order)
     LAYER 1  design tokens      — colours, type scale, spacing, radii
     LAYER 2  base               — element defaults, type primitives
     LAYER 3  components         — header, hero, cards, buttons, rail…
     LAYER 4  layout primitives  — .wrap / .tone-* / .page-hero / heads
     LAYER 5  motion & responsive

   ADDING A PAGE — no new CSS should be needed:
     1. copy any existing page (they share the same <head>/header/footer)
     2. build the body from layout primitives:
          <section class="page-hero"> … </section>
          <section class="wrap tone-paper"> … </section>
          <section class="wrap tone-pine"> … </section>
     3. use existing components inside (.btn, .team-card, .price-card…)
   ============================================================ */

:root {
  /* ---- brand primitives — the logo's four exact colours ---- */
  --deep: #2c4c49;   /* logo deep green — accents, headings, small marks */
  --sage: #839c9a;   /* logo sage grey */
  --sand: #d7cdc0;   /* logo light beige */
  --clay: #deae87;   /* logo warm beige */

  /* ---- dark scale ----
     Large dark surfaces are DESATURATED greys drawn down from --sage, not the
     saturated logo green: the green is strong and reads heavy over big areas,
     so it is kept for type and details instead. */
  --deep-800: #2b3230;
  --deep-700: #3a4240;

  /* ---- light surfaces — beige-led, taken from --sand ---- */
  --paper: #f7f3ec;
  --paper-2: #ebe3d7;
  --ivory: #f1eae0;

  /* ---- ink (text on light) ---- */
  --ink: #262b29;
  --muted: #6a736f;
  --muted-soft: #949c98;

  /* ---- text/lines on dark ---- */
  --on-dark: rgba(248, 245, 240, 0.94);
  --on-dark-soft: rgba(248, 245, 240, 0.78);
  --on-dark-faint: rgba(248, 245, 240, 0.56);
  --on-dark-line: rgba(248, 245, 240, 0.18);

  /* ---- accent (CTAs, prices, active states) ---- */
  --accent-hover: #cd9364;
  --accent-ink: #8c6038;      /* clay dark enough for text on light */
  --accent-on: #1e2c2a;       /* text colour on top of --accent */

  /* Dark bands are translucent scrims over the fixed backdrop photograph, not
     panels of colour (see body::before). --dark-ground is the tone that
     arrangement averages out to, used wherever a gradient must meet it.
     --ground-photo is the footer's own picture, the one exception. */
  --dark-ground: #1e1e1d;

  /* ---- lines, glass, scrims ---- */
  --line: rgba(38, 43, 41, 0.14);
  --line-soft: rgba(38, 43, 41, 0.08);
  --glass: rgba(248, 245, 240, 0.78);
  /* photo scrims are neutral — they darken images without tinting them */
  --photo-scrim: 18, 18, 17;

  --shadow-sm: 0 14px 40px rgba(18, 18, 17, 0.10);
  --shadow: 0 30px 80px rgba(18, 18, 17, 0.18);

  /* ---- radii ---- */
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --radius-pill: 100px;

  /* ---- type ---- */
  --display: "Fraunces", "Cormorant Garamond", Georgia, serif;
  --sans: "Inter", system-ui, -apple-system, Arial, sans-serif;
  /* brand wordmark face — geometric, matches the A SALA logo lettering */
  --brand: "Jost", "Futura", "Century Gothic", var(--sans);
  /* handwriting — used ONLY for short marginal notes next to a headline */

  /* type scale — one ladder, used everywhere */
  --fs-display: clamp(38px, 5.4vw, 74px);   /* page + hero headlines */
  --fs-h2: clamp(30px, 3.6vw, 48px);        /* section headlines */
  --fs-h3: clamp(20px, 1.9vw, 25px);        /* card headlines */
  --fs-lede: clamp(16px, 1.15vw, 19px);     /* intro paragraphs */
  --fs-body: 16px;
  --fs-small: 14px;
  --fs-label: 11.5px;                       /* eyebrows / labels */

  /* letter-spacing ladder — deliberately restrained */
  --ls-tight: -0.01em;
  --ls-body: 0;
  --ls-wide: 0.04em;      /* buttons, small links */
  --ls-label: 0.12em;     /* uppercase labels */
  --ls-brand: 0.2em;      /* wordmark only */

  /* ---- spacing ---- */
  --gut: clamp(20px, 5vw, 96px);
  --card-pad: clamp(20px, 2.2vw, 30px);

  --ease: cubic-bezier(.22, .8, .27, 1);
}

/* ============================================================
   LAYER 2 — BASE
   Element defaults + typography primitives. No component styles here.
   ============================================================ */

* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

body {
  margin: 0;
  background: var(--dark-ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-body);
  line-height: 1.6;
  overflow-x: hidden;
}

/* THE BACKDROP — one photograph, for the whole site.
   The ?v= on the two files is a cache key: bump it whenever the image content
   changes (the preloads in index.html carry the same one and must match, or the
   browser fetches the picture twice).
   A fixed element (not background-attachment:fixed, which iOS drops and which
   causes scroll jank) holding the Soul room. It is the hero image AND the
   ground under every dark section: those sections are translucent scrims, so
   the same picture shows through them and stays still while the page slides
   over it. Nothing is pasted per section.
   The scrim here is light — just enough for the header and the hero type. Each
   dark band adds its own, heavier scrim on top. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -10;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(var(--photo-scrim), 0.06) 0%, rgba(var(--photo-scrim), 0) 34%, rgba(var(--photo-scrim), 0.22) 100%),
    url("assets/photos/hero-room.webp?v=2") center 58% / cover no-repeat;
  background-color: var(--dark-ground);
}
/* portrait windows get the portrait crop of the same room */
@media (max-aspect-ratio: 1/1) {
  body::before {
    background:
      linear-gradient(180deg, rgba(var(--photo-scrim), 0.08) 0%, rgba(var(--photo-scrim), 0) 34%, rgba(var(--photo-scrim), 0.26) 100%),
      url("assets/photos/hero-room-mobile.webp?v=2") center 42% / cover no-repeat;
    background-color: var(--dark-ground);
  }
}

/* Booking pages carry their own images (the rooms, the chosen room's scene);
   the backdrop photograph behind them only made it noisy. */
body[data-booking-page]::before {
  background: linear-gradient(180deg, #171716 0%, #101010 100%);
  background-color: #101010;
}

body.menu-open { overflow: hidden; }

img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
::selection { background: var(--deep); color: var(--on-dark); }

:focus-visible {
  outline: 3px solid var(--clay);
  outline-offset: 4px;
}

.site-header.over-dark:not(.scrolled) :focus-visible,
.tone-pine :focus-visible,
.hero :focus-visible,
.page-hero :focus-visible {
  outline-color: var(--sand);
}

/* paper grain — site-wide, very subtle */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 9999;
  pointer-events: none;
  opacity: 0.05;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- typography primitives ---------- */

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 400;
  font-optical-sizing: auto;
  letter-spacing: -0.01em;
  margin: 0;
  text-wrap: balance;
}

.label {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sans);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--accent-ink);
}

.label.on-dark { color: var(--sand); }

/* ---------- buttons ---------- */

/* One primary button (warm clay from the logo, dark ink on top so it stays
   legible on light and dark sections alike) plus two outline variants. */
.btn {
  --bg: var(--clay);
  --fg: var(--accent-on);
  --bd: var(--clay);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 52px;
  padding: 0 28px;
  border: 1px solid var(--bd);
  border-radius: var(--radius-pill);
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  cursor: pointer;
  position: relative;
  transition: transform .4s var(--ease), box-shadow .4s var(--ease), color .3s var(--ease), background .3s var(--ease), border-color .3s var(--ease);
}

.btn span { position: relative; z-index: 1; }

.btn:hover {
  transform: translateY(-2px);
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  box-shadow: var(--shadow-sm);
}

/* outline button for light sections */
.btn-ghost {
  --bg: transparent;
  --fg: var(--ink);
  --bd: var(--line);
}
.btn-ghost:hover { --fg: var(--paper); background: var(--deep); border-color: var(--deep); box-shadow: var(--shadow-sm); }

/* alias kept so existing markup keeps working — same as .btn */
.btn-clay { --bg: var(--clay); --bd: var(--clay); --fg: var(--accent-on); }
.btn-clay:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

/* text link with animated underline */
.tlink {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  color: var(--deep);
}
.tlink::after {
  content: "";
  position: absolute;
  left: 0; bottom: -4px;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .45s var(--ease);
}
.tlink:hover::after { transform: scaleX(1); }
.tlink .arr { transition: transform .4s var(--ease); }
.tlink:hover .arr { transform: translateX(5px); }

/* ============================================================
   LAYER 3 — COMPONENTS
   Self-contained pieces reused across pages. Each one reads tokens only,
   so it looks right on any page without extra CSS.
   ------------------------------------------------------------
   HEADER
   ============================================================ */

.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 80;
  display: grid;
  grid-template-columns: minmax(220px, 1fr) auto minmax(220px, 1fr);
  align-items: center;
  gap: 24px;
  padding: 22px clamp(28px, 5vw, 72px);
  transition: padding .5s var(--ease), background .5s var(--ease), border-color .5s var(--ease), box-shadow .5s var(--ease);
  border-bottom: 1px solid transparent;
}

.site-header.scrolled {
  padding-top: 14px;
  padding-bottom: 14px;
  background: var(--glass);
  backdrop-filter: blur(20px) saturate(1.2);
  border-bottom-color: var(--line);
}

/* hero pages start with light header text over dark image */
.site-header.over-dark:not(.scrolled) { color: var(--on-dark); }
.site-header.over-dark:not(.scrolled) .brand-sub { color: rgba(248, 245, 240, 0.7); }
.site-header.over-dark:not(.scrolled) nav a { color: var(--on-dark); }
.site-header.over-dark:not(.scrolled) .lang-trigger { color: var(--on-dark); border-color: rgba(248, 245, 240, 0.42); }
.site-header.over-dark:not(.scrolled) .lang-trigger:hover { border-color: var(--on-dark); }
.site-header.over-dark:not(.scrolled) .menu-toggle { border-color: rgba(248, 245, 240, 0.4); }
.site-header.over-dark:not(.scrolled) .menu-toggle span { background: var(--paper); }

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 90;
  justify-self: start;
}
/* real A SALA logo mark (the cairn) */
.brand .mark { width: 30px; height: 39px; flex: none; }
/* wordmark set in the brand typeface so it matches the logo lettering */
.brand-name {
  display: block;
  font-family: var(--brand);
  font-weight: 300;
  font-size: 21px;
  letter-spacing: var(--ls-brand);
  line-height: 1;
  padding-left: 4px;
}
.brand-sub {
  display: block;
  margin-top: 4px;
  font-family: var(--brand);
  font-size: 9px;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}

.header-nav {
  display: contents;
  align-items: center;
  gap: clamp(20px, 2.4vw, 40px);
}

nav.main-nav {
  display: flex;
  justify-self: center;
  justify-content: center;
  gap: clamp(24px, 2.6vw, 42px);
}
nav.main-nav a {
  position: relative;
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: var(--ls-body);
  padding: 4px 0;
}
nav.main-nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .4s var(--ease);
}
nav.main-nav a:hover::after { transform: scaleX(1); }

/* language dropdown */
.lang-select { position: relative; }
.lang-trigger {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 44px;
  padding: 0 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  cursor: pointer;
  transition: border-color .3s var(--ease), background .3s var(--ease), color .3s var(--ease);
}
.lang-trigger:hover { border-color: var(--deep); }
.lang-trigger .globe { width: 16px; height: 16px; opacity: 0.85; }
.lang-trigger .chev { width: 13px; height: 13px; transition: transform .35s var(--ease); }
.lang-select.open .lang-trigger { border-color: var(--deep); }
.lang-select.open .lang-trigger .chev { transform: rotate(180deg); }

.lang-menu {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  min-width: 186px;
  margin: 0;
  padding: 7px;
  list-style: none;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  opacity: 0;
  transform: translateY(-8px) scale(0.98);
  transform-origin: top right;
  pointer-events: none;
  transition: opacity .3s var(--ease), transform .3s var(--ease);
  z-index: 60;
}
.lang-select.open .lang-menu { opacity: 1; transform: none; pointer-events: auto; }
.lang-menu li { margin: 0; }
.lang-menu button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  width: 100%;
  padding: 11px 14px;
  border: 0;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink);
  font-size: var(--fs-small);
  cursor: pointer;
  transition: background .25s var(--ease), color .25s var(--ease);
}
.lang-menu button i { font-style: normal; font-size: var(--fs-label); letter-spacing: var(--ls-label); color: var(--muted); }
.lang-menu button:hover { background: var(--paper-2); }
.lang-menu button.is-active { background: var(--deep); color: var(--on-dark); }
.lang-menu button.is-active i { color: rgba(248, 245, 240, 0.75); }

.menu-toggle {
  display: none;
  width: 44px; height: 44px;
  margin-right: -8px;
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  cursor: pointer;
  z-index: 90;
}
.menu-toggle span {
  display: block;
  width: 20px; height: 1.5px;
  margin: 6px auto;
  background: var(--ink);
  transition: transform .4s var(--ease), opacity .3s var(--ease);
}
.menu-open .menu-toggle span:first-child { transform: translateY(3.75px) rotate(45deg); }
.menu-open .menu-toggle span:last-child { transform: translateY(-3.75px) rotate(-45deg); }

/* mobile nav panel */
.nav-panel-extras {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 24px;
}

@media (max-width: 1023px) {
  .site-header {
    display: flex;
    justify-content: space-between;
    padding-inline: var(--gut);
  }
  .menu-toggle { display: block; }
  .header-nav {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 85;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 0;
    padding: clamp(94px, 15vh, 124px) var(--gut) max(28px, env(safe-area-inset-bottom));
    background: var(--deep-800);
    color: var(--on-dark);
    clip-path: inset(0 0 0 100%);
    transition: clip-path .6s var(--ease);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .menu-open .header-nav { clip-path: inset(0); }
  .menu-open .site-header {
    color: var(--on-dark);
    background: transparent;
    border-bottom-color: transparent;
    box-shadow: none;
    backdrop-filter: none;
  }
  .menu-open .site-header .brand-sub { color: rgba(248, 245, 240, 0.7); }
  .menu-open .menu-toggle { border-color: rgba(248, 245, 240, 0.4); }
  .menu-open .menu-toggle span { background: var(--paper); }
  nav.main-nav {
    flex-direction: column;
    gap: 0;
    width: 100%;
  }
  .header-nav nav.main-nav a {
    font-family: var(--display);
    font-size: var(--fs-h2);
    line-height: 0.98;
    color: var(--on-dark);
    padding: 7px 0;
  }
  .header-nav nav.main-nav a::after { display: none; }
  .nav-panel-extras {
    display: flex;
    width: 100%;
    flex-direction: column;
    align-items: center;
    gap: 18px;
    margin-top: clamp(26px, 6vh, 42px);
  }
  /* in the panel the two controls are stacked, so they are the same object:
     same width, same height. One used to be visibly bigger than the other. */
  .header-cta-wrap { order: 1; width: 100%; }
  .lang-select { order: 2; width: 100%; }
  .site-header .header-nav .lang-trigger {
    width: 100%;
    justify-content: center;
    color: var(--on-dark);
    border-color: rgba(248, 245, 240, 0.34);
    min-height: 52px;
    padding-inline: 18px;
    background: rgba(248, 245, 240, 0.03);
  }
  .lang-menu {
    position: static; min-width: 0; width: 100%; margin-top: 10px;
    background: rgba(248, 245, 240, 0.06); border-color: transparent;
    box-shadow: none; opacity: 1; transform: none; pointer-events: auto;
    max-height: 0; padding-block: 0; overflow: hidden;
    transition: max-height .4s var(--ease), padding .4s var(--ease);
  }
  .lang-select.open .lang-menu { max-height: 340px; padding-block: 7px; border-color: rgba(248, 245, 240, 0.2); }
  .lang-menu button { color: var(--on-dark); }
  .lang-menu button i { color: rgba(248, 245, 240, 0.6); }
  .lang-menu button:hover { background: rgba(248, 245, 240, 0.1); }
  .lang-menu button.is-active { background: var(--paper); color: var(--deep-800); }
  /* the active row flips to a light chip in the mobile panel, so its code
     has to flip with it — the desktop rule is more specific otherwise */
  .lang-menu button.is-active i { color: rgba(43, 50, 48, 0.66); }
  .header-nav .header-cta-wrap .btn { width: 100%; min-height: 52px; --bg: var(--clay); --bd: var(--clay); }
}

@media (min-width: 1024px) {
  .header-cta-wrap .btn {
    min-height: 44px;
    min-width: 158px;
    padding: 0 24px;
  }
}
/* primary "Reserve" CTA is the same warm clay in the header as in the hero */
.header-cta-wrap .btn { --bg: var(--clay); --bd: var(--clay); }

/* ============================================================
   HERO
   ============================================================ */

.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  align-items: center;
  padding: 118px var(--gut) clamp(42px, 6vh, 72px);
  isolation: isolate;
  overflow: hidden;
  color: var(--on-dark);
}

/* The hero shows the site backdrop itself (see body::before) — it holds no
   image of its own. This fade hands the picture over to the first dark band:
   it ends on the same scrim value that band uses, so the two meet invisibly. */
.hero::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: clamp(90px, 14vh, 180px);
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(180deg, rgba(var(--photo-scrim), 0) 0%, rgba(var(--photo-scrim), 0.90) 100%);
}

.hero-scrim { position: absolute; inset: 0; z-index: -2; }
.page-hero .ph-media picture,
.page-hero .ph-media img,
.space-slide .ph picture,
.space-slide .ph img {
  width: 100%;
  height: 100%;
  display: block;
}
.page-hero .ph-media img,
.space-slide .ph img {
  object-fit: cover;
}
/* No filter over the hero photograph. The only two layers left are a whisper at
   the very top, so the white header holds, and the fade at the bottom edge
   (.hero::after). Legibility of the type comes from its own soft shadow, not
   from darkening the room. */
.hero-scrim {
  z-index: -1;
  background: linear-gradient(180deg, rgba(var(--photo-scrim), 0.22) 0%, rgba(var(--photo-scrim), 0) 22%);
}

.hero-inner {
  width: min(920px, 88vw);
  position: relative;
  z-index: 2;
  margin: 0 auto;
  text-align: center;
}

/* Two lines and one button. The wordmark leads, the sentence answers it. */
.hero h1 {
  text-shadow: 0 2px 26px rgba(12, 12, 11, 0.6), 0 1px 3px rgba(12, 12, 11, 0.4);
  font-family: var(--display);
  font-size: clamp(26px, 2.9vw, 42px);
  line-height: 1.14;
  font-weight: 300;
  letter-spacing: var(--ls-tight);
  color: var(--on-dark);
  margin: clamp(18px, 2.6vh, 30px) auto 0;
  max-width: 26ch;
  opacity: 0;
  animation: heroLineIn 1.4s var(--ease) 1.05s forwards;
}

/* Hero wordmark — the brand exactly as the navbar sets it: one word in Jost,
   the same 0.2em tracking, only bigger and lighter. It arrives in a single
   quiet fade, not letter by letter.
   text-indent cancels the trailing letter-space so the word optically centres. */
.hero-wordmark {
  display: block;
  text-shadow: 0 2px 34px rgba(12, 12, 11, 0.55), 0 1px 4px rgba(12, 12, 11, 0.35);
  margin: 0;
  font-family: var(--brand);
  font-weight: 200;
  font-size: clamp(42px, 8.2vw, 120px);
  line-height: 1;
  letter-spacing: var(--ls-brand);
  text-indent: var(--ls-brand);
  color: var(--on-dark);
  opacity: 0;
  animation: heroLineIn 1.6s var(--ease) .12s forwards;
}
@keyframes heroLineIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-wordmark,
  .hero h1,
  .hero .hero-actions { animation: none; opacity: 1; transform: none; filter: none; }
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 16px; }
.hero .hero-actions {
  justify-content: center;
  margin-top: clamp(30px, 4.5vh, 52px);
  opacity: 0;
  animation: heroLineIn 1.2s var(--ease) 1.35s forwards;
}
.hero .hero-actions .btn {
  min-width: 200px;
}

/* ------------------------------------------------------------------
   FOUNDERS — a short, warm intro to the two people who run the house,
   sitting above the practitioner directory.
   ------------------------------------------------------------------ */
/* The three of them side by side and top-aligned, so the portraits and the names
   line up even when one role wraps onto a second line. Three columns or one,
   never two: two would leave the third on its own row. */
.founders {
  display: grid;
  gap: clamp(18px, 2.4vw, 32px);
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
  justify-content: center;
  max-width: 380px;
  margin-inline: auto;
}
@media (min-width: 760px) {
  .founders {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    max-width: 960px;
  }
}
.founder-card {
  display: grid;
  grid-template-rows: auto auto;
  justify-items: center;
  text-align: center;
  gap: 16px;
}
.fc-photo {
  width: clamp(120px, 14vw, 168px);
  aspect-ratio: 1;
  border-radius: 50%;
  overflow: hidden;
  background: var(--paper-2);
  box-shadow: var(--shadow-sm);
}
.fc-photo picture, .fc-photo img { width: 100%; height: 100%; display: block; }
.fc-photo img { object-fit: cover; }
.fc-photo img[src*="daniela"] { object-position: center 30%; }
.fc-body h3 { font-size: var(--fs-h3); font-weight: 300; color: var(--ink); margin: 0 0 4px; }
.fc-body p {
  margin: 0;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--accent-ink);
  max-width: 26ch;
}

/* ------------------------------------------------------------------
   SPACE STORIES — one room per block, full page width.
   The room's name sits ON its lead photograph; the rate and the booking button
   sit in a panel beside it; the remaining shots run underneath. The panel
   swaps sides from one room to the next.
   ------------------------------------------------------------------ */
.space-stories { display: grid; gap: 0; }
/* What the whole house offers — one quiet typographic line under the section
   head, items separated by dots. A list for i18n and screen readers, a
   sentence to the eye. */
.amenities {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  column-gap: 8px;
  row-gap: 6px;
  margin: clamp(44px, 6vw, 80px) auto 0;
  max-width: 760px;
  padding: 0;
  list-style: none;
  text-align: center;
}
.amenities li {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--on-dark-faint);
}
.amenities li:not(:last-child)::after {
  content: "·";
  margin-left: 8px;
  color: var(--clay);
}

/* Rooms used to run into each other: photograph, photograph, photograph, and no
   telling where one room ended. Each block is now separated by a rule and its
   own number, so the page reads as four rooms and not as a gallery. */
.space-story {
  display: grid;
  gap: clamp(14px, 1.6vw, 22px);
  padding-block: clamp(48px, 7vw, 96px);
  border-top: 1px solid var(--on-dark-line);
}
.space-story:first-child { border-top: 0; padding-top: 0; }
.space-story:last-child { padding-bottom: 0; }

/* --- one frame per space, stepped through with the arrows, the name over it ---
   Every photograph of the space is stacked in the frame and only the current one
   is shown. The whole frame is clickable (a transparent button on top of it) and
   opens the same set full screen. */
.ss-hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  aspect-ratio: 16 / 10;
  background: var(--deep-800);
}
.ss-frame { position: absolute; inset: 0; }
.ss-frame figure {
  margin: 0;
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .45s var(--ease);
}
.ss-frame figure.is-on { opacity: 1; }
.ss-frame figure.is-portrait::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--shot) center / cover no-repeat;
  filter: blur(28px) brightness(0.5) saturate(0.85);
  transform: scale(1.12);
}
.ss-frame figure.is-portrait picture { position: relative; z-index: 1; }
.ss-frame figure.is-portrait img { object-fit: contain; }
/* a contained photograph must not grow past its frame on hover */
.ss-hero:hover .ss-frame figure.is-portrait.is-on img { transform: none; }
.ss-hero-open {
  position: absolute; inset: 0;
  z-index: 1;
  padding: 0; border: 0; background: none; cursor: zoom-in;
  display: block;
}
.ss-hero-open:focus-visible { outline: 2px solid var(--clay); outline-offset: -6px; }
.ss-hero picture, .ss-hero img { width: 100%; height: 100%; display: block; }
.ss-hero img { object-fit: cover; transition: transform 1.1s var(--ease); }
.ss-hero:hover .ss-frame figure.is-on img { transform: scale(1.03); }

/* the arrows and the position in the set, on a pill in the corner */
.ss-shots {
  position: absolute;
  z-index: 3;
  right: clamp(12px, 1.6vw, 20px);
  bottom: clamp(12px, 1.6vw, 20px);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(248, 245, 240, 0.28);
  background: rgba(18, 18, 17, 0.5);
  backdrop-filter: blur(6px);
}
.ss-arrow {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  /* the UA button face would paint this light grey and swallow the glyph */
  background: none;
  border-radius: 50%;
  color: var(--on-dark);
  cursor: pointer;
  transition: background .3s var(--ease);
}
.ss-arrow:hover { background: rgba(248, 245, 240, 0.16); }
/* a finger needs more than a mouse pointer */
@media (hover: none) {
  .ss-arrow { width: 42px; height: 42px; }
}
.ss-arrow svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; }
.ss-count {
  min-width: 44px;
  text-align: center;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: var(--on-dark-soft);
  font-variant-numeric: tabular-nums;
}
.ss-hero::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(var(--photo-scrim), 0) 34%, rgba(var(--photo-scrim), 0.82) 100%);
}
.ss-hero-copy {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  inset: auto 0 0 0;
  padding: clamp(20px, 3vw, 44px);
  /* keep the name clear of the arrows pill in the opposite corner */
  padding-right: clamp(160px, 20%, 200px);
  display: grid;
  gap: 10px;
  justify-items: start;
}
.ss-hero-copy .label { color: var(--sand); }
.ss-hero-copy h3 {
  font-size: clamp(32px, 4.6vw, 68px);
  font-weight: 300;
  color: var(--on-dark);
  line-height: 0.98;
  letter-spacing: var(--ls-tight);
  text-shadow: 0 2px 30px rgba(12, 12, 11, 0.5);
}

/* --- what the room does, what it costs, how to take it ---
   Deliberately NOT a card: no border, no panel. The copy sits beside the
   photograph like a caption in a magazine, which is what makes the pair read
   horizontally instead of as two boxes. */
.ss-panel {
  display: grid;
  gap: 18px;
  align-content: center;
  justify-items: start;
  padding-inline: clamp(0px, 1.4vw, 22px);
}
.ss-services {
  color: var(--on-dark-soft);
  font-size: clamp(16px, 1.15vw, 19px);
  line-height: 1.62;
  margin: 0;
  max-width: 34ch;
}
/* What the space holds — a quiet card the full width of its space's block,
   right under the photograph and the panel, every item on its own line icon.
   The on-request extras are shared, so they live in ONE note for the whole
   house (.ss-extra-global), after the last space. */
.ss-equip {
  width: 100%;
  margin-top: clamp(8px, 1.2vw, 14px);
  padding: clamp(18px, 2.4vw, 30px) clamp(18px, 2.4vw, 32px);
  border: 1px solid var(--on-dark-line);
  border-radius: var(--radius);
  background: rgba(248, 245, 240, 0.04);
}
.ss-equip-label {
  margin: 0 0 clamp(12px, 1.6vw, 18px);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--sand);
}
.ss-equip-label span { color: var(--on-dark-faint); letter-spacing: var(--ls-wide); }
.ss-extra {
  margin: clamp(12px, 1.6vw, 18px) 0 0;
  padding-top: clamp(10px, 1.4vw, 14px);
  border-top: 1px solid var(--on-dark-line);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--on-dark-faint);
}
/* the single, house-wide note */
.ss-extra-global {
  max-width: 68ch;
  margin: clamp(20px, 3vw, 36px) auto 0;
  text-align: center;
}
.ss-extra-global b { display: block; margin: 0 0 6px; }
.ss-extra b {
  font-weight: 600;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--on-dark-soft);
  margin-right: 10px;
}
.ss-equip ul {
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 2;
  column-gap: clamp(22px, 3vw, 40px);
}
.ss-equip li {
  break-inside: avoid;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--on-dark-soft);
  margin-bottom: 9px;
}
.ss-equip li svg {
  flex: none;
  width: 19px;
  height: 19px;
  margin-top: 1px;
  fill: none;
  stroke: var(--clay);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
@media (min-width: 900px) {
  .ss-equip { grid-column: 1 / -1; }
  .ss-equip ul { columns: 3; }
}
@media (max-width: 480px) {
  .ss-equip ul { columns: 1; }
}
/* the rate sits on a hairline, the way a price does on a menu */
.ss-rate {
  display: flex;
  align-items: baseline;
  gap: 9px;
  width: 100%;
  margin: 0;
  padding-top: 18px;
  border-top: 1px solid var(--on-dark-line);
}
.ss-rate b { font-family: var(--display); font-size: clamp(36px, 3.6vw, 52px); font-weight: 400; color: var(--clay); line-height: 1; }
.ss-rate span { font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--on-dark-faint); }
.ss-panel .btn { margin-top: 2px; min-width: 170px; }

@media (min-width: 900px) {
  .space-story {
    grid-template-columns: minmax(0, 1.72fr) minmax(0, 1fr);
    gap: clamp(22px, 2.6vw, 44px);
  }
  .space-story.is-flipped {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.72fr);
  }
  .space-story.is-flipped .ss-hero { order: 2; }
  .space-story.is-flipped .ss-panel { order: 1; }
  /* order on the two above resets the equip card to first place; keep it last */
  .space-story.is-flipped .ss-equip { order: 3; }
}
@media (max-width: 899px) {
  .ss-hero { aspect-ratio: 4 / 3; }
  .ss-panel { justify-items: stretch; }
  .ss-panel .btn { justify-self: start; }
}

/* ------------------------------------------------------------------
   SPACE GALLERY (lightbox)
   Clicking a space's photograph — on a card or on the Spaces page — opens
   every photograph of that space. The overlay is created by initGallery on
   the first click, so no page carries markup for it and no-JS visitors just
   see plain pictures.
   ------------------------------------------------------------------ */
.gallery-hint {
  position: absolute;
  z-index: 3;
  top: clamp(12px, 1.6vw, 20px);
  right: clamp(12px, 1.6vw, 20px);
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(248, 245, 240, 0.34);
  background: rgba(18, 18, 17, 0.42);
  backdrop-filter: blur(6px);
  color: var(--on-dark);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  /* a hint, not a button: it fades up when the photograph is pointed at */
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .35s var(--ease), transform .35s var(--ease);
}
.space-slide:hover .gallery-hint,
.ss-hero:hover .gallery-hint,
.ph:focus-visible .gallery-hint,
.ss-hero-open:focus-visible .gallery-hint { opacity: 1; transform: none; }
/* no hover on a touch screen, so the hint is simply always there */
@media (hover: none) {
  .gallery-hint { opacity: 1; transform: none; }
}

body.lb-open { overflow: hidden; }
/* the header would otherwise read through the scrim and sit under the close button */
body.lb-open .site-header { opacity: 0; pointer-events: none; }
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(10px, 2vw, 28px);
  /* opaque, not a scrim: the site's fixed backdrop photograph and the copy
     underneath would otherwise read through and fight the photograph shown */
  background: rgb(var(--photo-scrim));
  animation: lbIn .28s var(--ease);
}
.lightbox[hidden] { display: none; }
@keyframes lbIn { from { opacity: 0; } to { opacity: 1; } }
/* The panel must take the overlay's full height: the photographs inside the
   stage are absolutely positioned, so an auto-height stage would collapse to
   nothing and the picture would never be seen. */
.lb-panel {
  width: min(1180px, 100%);
  height: 100%;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: clamp(10px, 1.4vh, 18px);
}
.lb-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.lb-meta {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 12px;
  color: var(--on-dark);
}
.lb-meta b { font-family: var(--display); font-size: clamp(19px, 2.2vw, 26px); font-weight: 400; }
.lb-meta span {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  color: var(--on-dark-faint);
  font-variant-numeric: tabular-nums;
}
.lb-btn {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid rgba(248, 245, 240, 0.28);
  background: rgba(248, 245, 240, 0.08);
  color: var(--on-dark);
  transition: background .3s var(--ease), border-color .3s var(--ease);
}
.lb-btn:hover { background: rgba(248, 245, 240, 0.18); border-color: var(--on-dark); }
.lb-btn svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.lb-stage { position: relative; min-height: 0; }
.lb-stage figure {
  margin: 0;
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .34s var(--ease);
  pointer-events: none;
}
.lb-stage figure.is-on { opacity: 1; }
.lb-stage picture, .lb-stage img { width: 100%; height: 100%; display: block; }
.lb-stage img { object-fit: contain; border-radius: var(--radius); }
.lb-nav { display: flex; justify-content: center; gap: 14px; }

/* ============================================================
   LAYER 4 — LAYOUT PRIMITIVES
   The page skeleton: section padding, tone (light/dark) variants and
   section headings. A NEW PAGE IS BUILT FROM THESE:
     <section class="wrap tone-paper">   light section
     <section class="wrap tone-pine">    dark section
     <section class="page-hero">         subpage hero
   ------------------------------------------------------------
   SECTION SHELL
   ============================================================ */

section { position: relative; }

.wrap {
  padding: clamp(72px, 11vh, 150px) var(--gut);
  /* clip, NOT hidden: overflow:hidden turns a section into a scrollport and
     silently breaks any position:sticky child inside it */
  overflow: clip;
}
.wrap-tight { padding: clamp(56px, 8vh, 110px) var(--gut); }

.manifesto::before,
.tone-paper::before,
.tone-sand::before,
.tone-pine::before {
  content: "";
  position: absolute;
  inset: -1px 0 auto;
  height: clamp(42px, 8vh, 86px);
  pointer-events: none;
  z-index: 0;
}
.manifesto::before,
.tone-pine::before {
  background: linear-gradient(180deg, rgba(18, 18, 17, 0), rgba(18, 18, 17, 0.22));
}
.manifesto::before { display: none; }
.tone-paper::before,
.tone-sand::before {
  background: linear-gradient(180deg, rgba(18, 18, 17, 0.18), rgba(248, 245, 240, 0));
}
/* feather the bottom of a light section when a dark one follows, so the
   light↔dark seam reads as a gradual settle rather than a hard band */
.tone-paper:has(+ .tone-pine)::after,
.tone-sand:has(+ .tone-pine)::after,
.tone-paper:has(+ .manifesto)::after,
.tone-sand:has(+ .manifesto)::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: clamp(54px, 8vh, 104px);
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(180deg, rgba(18, 18, 17, 0), rgba(18, 18, 17, 0.16));
}
.manifesto > *,
.tone-paper > *,
.tone-sand > *,
.tone-pine > * {
  position: relative;
  z-index: 1;
}

.section-head {
  max-width: 760px;
  margin-inline: auto;
  margin-bottom: clamp(40px, 6vh, 72px);
  text-align: center;
}
.section-head h2 {
  font-size: var(--fs-h2);
  line-height: 0.98;
  font-weight: 300;
  color: var(--deep);
  margin-top: 18px;
}
.section-head p {
  margin: 22px auto 0;
  max-width: 580px;
  color: var(--muted);
  font-size: 17px;
}
.section-head .label { justify-content: center; }

/* tone variants.
   Every dark band stands on the patio photograph. The scrim is deliberately
   heavy (0.90+): the picture is there as ground and texture, and the copy on
   top has to stay as readable as it was on a flat colour. Each band takes a
   different crop of the photo so the page doesn't repeat itself. */
.tone-pine {
  position: relative;
  isolation: isolate;
  /* a scrim, not a panel: the fixed backdrop photograph shows through it */
  background: linear-gradient(180deg, rgba(var(--photo-scrim), 0.90), rgba(var(--photo-scrim), 0.94));
  color: var(--on-dark);
}
.tone-pine h2 { color: var(--on-dark); }
.tone-pine p { color: rgba(248, 245, 240, 0.74); }
/* Opaque near-black. Used where a photograph must NOT show through: bands whose
   own images are the subject (the room pickers) or that sit right before the
   footer photograph, where scrim-on-photo-on-photo turned to mud. */
.tone-ink {
  position: relative;
  isolation: isolate;
  background: linear-gradient(180deg, #161615 0%, #101010 100%);
  color: var(--on-dark);
}
.tone-ink h2, .tone-ink h3, .tone-ink h4 { color: var(--on-dark); }
.tone-ink p { color: var(--on-dark-soft); }
.tone-ink .label { color: var(--sand); }

.tone-paper {
  background:
    linear-gradient(180deg, rgba(248, 245, 240, 0.98), rgba(248, 245, 240, 1)),
    var(--paper);
}
.tone-sand {
  background:
    linear-gradient(180deg, rgba(248, 245, 240, 0.94), rgba(248, 245, 240, 0.98)),
    var(--paper-2);
}

/* ============================================================
   MANIFESTO — scroll-lit story
   ------------------------------------------------------------
   The section straight after the hero is an OPAQUE dark field: the photo
   stops at the fold, the copy sits on a solid ground and stays perfectly
   readable. The hero fades into this exact colour (see .hero::after) so the
   seam between photograph and section reads as one continuous move.

   Each statement carries a --lit value (0 → 1) written by JS from its
   distance to the reading line: it brightens as it arrives and settles back
   as it leaves, so the story lights up under the cursor of the scroll.
   Everything degrades to plain, fully-lit text without JS (--lit: 1).
   ============================================================ */
.manifesto {
  position: relative;
  isolation: isolate;
  background: linear-gradient(180deg, rgba(var(--photo-scrim), 0.90), rgba(var(--photo-scrim), 0.94));
  color: var(--on-dark);
}
.manifesto .label { color: var(--sand); }

.manifesto-inner { display: grid; gap: clamp(32px, 4vw, 64px); }

/* --- the statements --- */
.story-steps { display: grid; gap: clamp(46px, 8vh, 104px); }
.story-step {
  --lit: 1;
  opacity: calc(0.26 + 0.74 * var(--lit));
  transform: translateY(calc((1 - var(--lit)) * 14px));
  transition: opacity .5s linear, transform .5s var(--ease);
}

.story-step h2,
.story-step h3 {
  max-width: 21ch;
  font-family: var(--display);
  font-weight: 300;
  letter-spacing: var(--ls-tight);
  line-height: 1.06;
  color: var(--on-dark);
  margin: 0;
}
/* sized to fill its column on a wide screen, not to sit in a narrow ribbon */
.story-step.is-lead h2 { font-size: clamp(30px, 3.9vw, 60px); }

/* Write-in sentence. JS wraps each word in a .w span and gives it a --w value
   (0 → 1) as the block crosses the lower half of the screen, so the line
   writes itself word by word. Default --w: 1 keeps it fully legible with no JS. */
.write-in .w {
  --w: 1;
  display: inline-block;
  opacity: calc(0.12 + 0.88 * var(--w));
  filter: blur(calc((1 - var(--w)) * 5px));
  transform: translateY(calc((1 - var(--w)) * 0.16em));
  transition: opacity .25s linear, filter .25s linear, transform .25s var(--ease);
}
@media (prefers-reduced-motion: reduce) {
  .write-in .w { opacity: 1; filter: none; transform: none; }
}
.story-step h3 { font-size: clamp(24px, 2.9vw, 42px); }
.story-step p {
  margin: clamp(14px, 1.8vh, 20px) 0 0;
  font-size: clamp(16px, 1.2vw, 21px);
  line-height: 1.6;
  color: var(--on-dark-soft);
  max-width: 50ch;
}
.story-step .accent { color: var(--clay); font-style: italic; }

/* --- the sticky picture column --- */
.story-media {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--deep-700);
}
.story-media figure {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  transform: scale(1.04);
  transition: opacity 1.1s var(--ease), transform 1.4s var(--ease);
}
.story-media figure.is-active { opacity: 1; transform: scale(1); }
.story-media picture, .story-media img { width: 100%; height: 100%; display: block; }
.story-media img { object-fit: cover; }

@media (min-width: 900px) {
  .manifesto-inner {
    grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
    align-items: start;
  }
  /* copy leads, picture follows on the right and holds while you read */
  .story-steps { order: 1; padding-block: clamp(24px, 7vh, 80px); }
  .story-media {
    order: 2;
    position: sticky;
    top: clamp(96px, 18vh, 190px);
    width: 100%;
    justify-self: end;
  }
}
@media (max-width: 899px) {
  .manifesto-inner { gap: clamp(24px, 5vw, 40px); }
  .story-steps { gap: clamp(38px, 6vh, 60px); }
  .story-media { order: -1; aspect-ratio: 3 / 2; }
  .story-step.is-lead h2 { font-size: clamp(26px, 6.4vw, 34px); }
  .story-step h3 { font-size: clamp(22px, 5.6vw, 30px); }

  /* PINNED STORY (JS adds .is-pinned on phones only).
     The section becomes a tall scroll track; the panel inside stays stuck for
     its whole length, one act on stage at a time: the sentence writes itself,
     then each statement takes the last one's place while the picture changes.
     Past the last act the pin releases and the page moves on.
     Without JS the class never lands and the plain flow above applies. */
  .manifesto.is-pinned {
    min-height: 430svh;
    padding: 0;
  }
  .manifesto.is-pinned .manifesto-inner {
    position: sticky;
    top: 0;
    height: 100svh;
    display: grid;
    /* words first, taking whatever room they need; the photograph closes the
       screen underneath them */
    grid-template-rows: 1fr auto;
    gap: clamp(16px, 2.6vh, 28px);
    padding: calc(64px + max(14px, env(safe-area-inset-top))) var(--gut) clamp(18px, 3.4vh, 34px);
    overflow: hidden;
  }
  .manifesto.is-pinned .story-media {
    order: 2;
    max-height: 32svh;
    width: auto;
    justify-self: stretch;
  }
  .manifesto.is-pinned .story-steps { order: 1; }

  /* The type is the act here, so it is sized to fill the phone: the statements
     run near the full width at display scale, and the supporting line stays
     deliberately small under them. */
  .manifesto.is-pinned .story-step h2,
  .manifesto.is-pinned .story-step h3 {
    max-width: none;
    line-height: 1.02;
  }
  .manifesto.is-pinned .story-step.is-lead h2 { font-size: clamp(34px, 9.4vw, 50px); }
  .manifesto.is-pinned .story-step h3 { font-size: clamp(38px, 11vw, 58px); }
  .manifesto.is-pinned .story-step p {
    margin-top: clamp(14px, 2.2vh, 22px);
    font-size: 17px;
    line-height: 1.5;
    max-width: 34ch;
  }
  .manifesto.is-pinned .story-step .label { margin-bottom: 4px; }
  /* the acts are stacked in one slot; only the one on stage is visible */
  .manifesto.is-pinned .story-steps {
    position: relative;
    gap: 0;
    min-height: 0;
  }
  /* the act leaving the stage clears fast; the next one arrives a beat later,
     so two texts never sit on top of each other for long */
  .manifesto.is-pinned .story-step {
    position: absolute;
    inset: 0;
    display: grid;
    align-content: center;
    opacity: 0;
    transform: translateY(18px);
    transition: opacity .22s var(--ease), transform .22s var(--ease);
    pointer-events: none;
  }
  .manifesto.is-pinned .story-step.is-on {
    opacity: 1;
    transform: none;
    pointer-events: auto;
    transition: opacity .5s var(--ease) .14s, transform .55s var(--ease) .14s;
  }
}
@media (prefers-reduced-motion: reduce) {
  .story-step { opacity: 1; transform: none; }
}

/* ============================================================
   SPACES — horizontal scroll rail
   ============================================================ */

.spaces-rail-section {
  /* how much vertical scroll the horizontal pan consumes — kept short so the
     rail never feels like it stalls */
  min-height: 190svh;
  overflow: clip;
}
/* The sticky panel is exactly one viewport tall and must not stretch,
   otherwise nothing actually sticks and the rail settles too high. */
.spaces-sticky {
  position: sticky;
  top: 0;
  align-self: start;
  width: 100vw;
  height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-content: stretch;
  padding: clamp(78px, 9vh, 104px) 0 clamp(28px, 4vh, 48px);
  overflow: clip;
}
.rail-head {
  width: 100vw;
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 10px;
  padding: 0 var(--gut);
  margin-bottom: clamp(18px, 2.4vh, 28px);
}
.rail-head h2 { font-size: var(--fs-h2); color: var(--on-dark); margin-top: 0; font-weight: 300; }
.rail-head .label { color: var(--sand); }
.spaces-rail {
  width: max-content;
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.6vw, 22px);
  overflow: visible;
  scrollbar-width: none;
  transform: translate3d(var(--rail-x, 0px), 0, 0);
  will-change: transform;
}
.spaces-rail::-webkit-scrollbar { display: none; }

/* Cards are sized from the available HEIGHT (width follows the ratio), so a
   card can never be taller than the sticky panel and get cut off. */
.space-slide {
  flex: 0 0 auto;
  height: 100%;
  max-height: 430px;
  width: auto;
  aspect-ratio: 8 / 5;
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--deep-800);
  box-shadow: var(--shadow-sm);
}
/* A button, so the photograph opens the space's gallery. The scrim and the
   caption sit on top of it and must let the click through; only the booking
   link inside the caption takes clicks back. */
.space-slide .ph {
  position: absolute; inset: 0;
  padding: 0; border: 0; background: none; cursor: zoom-in;
  transform: scale(1.04);
  transition: transform 1.1s var(--ease), filter 1.1s var(--ease);
}
.space-slide .ph:focus-visible { outline: 2px solid var(--clay); outline-offset: -6px; }
.space-slide::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(var(--photo-scrim), 0) 20%, rgba(var(--photo-scrim), 0.52) 58%, rgba(var(--photo-scrim), 0.90) 100%);
}
.space-slide:hover .ph { transform: scale(1.10); }
.space-slide .meta {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  inset: auto 0 0 0;
  padding: clamp(18px, 2.4vw, 28px);
  color: var(--on-dark);
}
.space-slide .meta .idx {
  font-size: 10px; letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--sand); opacity: 0.85;
}
.space-slide .meta h3 {
  font-size: var(--fs-h3);
  font-weight: 300;
  margin: 8px 0 4px;
  color: var(--on-dark);
}
.space-slide .meta .use {
  font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase;
  color: rgba(248, 245, 240, 0.78);
}
.space-slide .meta p {
  margin: 14px 0 18px;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: rgba(248, 245, 240, 0.84);
  max-width: 40ch;
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity .5s var(--ease), max-height .6s var(--ease), margin .5s var(--ease);
}
.space-slide:hover .meta p,
.space-slide:focus-within .meta p { opacity: 1; max-height: 120px; }
/* touch devices have no hover — keep the description visible so it isn't lost */
@media (hover: none) {
  .space-slide .meta p { opacity: 1; max-height: 160px; margin: 14px 0 18px; }
}
.space-slide .meta .row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.space-slide .meta .from {
  font-family: var(--display); font-size: 22px;
}
.space-slide .meta .from small { font-size: var(--fs-label); font-family: var(--sans); color: rgba(248, 245, 240, 0.7); letter-spacing: var(--ls-wide); }
.space-slide .book {
  pointer-events: auto;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 20px;
  border: 1px solid rgba(248, 245, 240, 0.5);
  border-radius: var(--radius-pill);
  font-size: var(--fs-label); font-weight: 600; letter-spacing: var(--ls-wide);
  background: rgba(248, 245, 240, 0.08);
  backdrop-filter: blur(4px);
  transition: all .35s var(--ease);
}
.space-slide .book:hover { background: var(--paper); color: var(--deep-800); border-color: var(--on-dark); }

.rail-progress {
  height: 2px;
  background: rgba(248, 245, 240, 0.16);
  margin: clamp(22px, 3vh, 34px) var(--gut) 0;
  transition: opacity .4s var(--ease);
  border-radius: 2px;
  overflow: hidden;
}
.rail-progress i { display: block; height: 100%; width: 30%; background: var(--clay); border-radius: 2px; transition: transform .25s linear, width .25s linear; }

/* On a phone the horizontal pan is the wrong gesture and landscape cards leave
   a tall empty band inside the sticky panel. The rail becomes a plain vertical
   list of the same cards: nothing sticks, nothing pans, you just scroll. */
@media (max-width: 720px) {
  .spaces-rail-section { min-height: 0; }
  .spaces-sticky {
    position: static;
    height: auto;
    width: auto;
    grid-template-rows: none;
    padding: clamp(56px, 8vh, 80px) 0 clamp(56px, 8vh, 80px);
    overflow: visible;
  }
  .spaces-rail {
    width: auto;
    display: grid;
    grid-template-columns: 1fr;
    gap: 14px;
    padding-inline: var(--gut);
    transform: none !important;
  }
  .space-slide {
    height: auto;
    width: auto;
    aspect-ratio: 4 / 3;
    max-height: none;
  }
  .space-slide .meta { padding: 20px; }
  /* the services list lives on the Spaces page; here the card stays a card */
  .space-slide .meta p { display: none; }
  .rail-progress { display: none; }
}

/* ============================================================
   THE HOUSE — story of the place, told in photographs
   ------------------------------------------------------------
   Copy on one side, five frames of the entrance and common areas on the
   other, each arriving on its own delay as the section scrolls in.
   ============================================================ */

.house { display: grid; gap: clamp(34px, 5vw, 72px); align-items: center; }
.house-copy { display: grid; gap: 16px; justify-items: start; max-width: 46ch; }
.house-copy h2 { font-size: var(--fs-h2); font-weight: 300; color: var(--on-dark); line-height: 1.02; }
.house-copy p { color: var(--on-dark-soft); font-size: var(--fs-lede); line-height: 1.62; margin: 0; }
.house-copy .tlink { margin-top: 8px; }

.house-gallery {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(10px, 1.2vw, 18px);
}
.house-gallery figure {
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
  background: var(--deep-700);
}
/* The patio is the one portrait shot, so it takes the full height of the first
   two rows rather than being cropped into a letterbox. The fourth photograph
   then runs the width of the pair below them, which closes the block instead of
   leaving a hole beside it. */
.house-gallery figure:first-child { grid-row: span 2; aspect-ratio: auto; }
.house-gallery figure:nth-child(4):last-child { grid-column: 1 / -1; aspect-ratio: 16 / 7; }
.house-gallery picture, .house-gallery img { width: 100%; height: 100%; display: block; }
.house-gallery img { object-fit: cover; transition: transform .8s var(--ease); }
.house-gallery figure:hover img { transform: scale(1.04); }

/* On a phone, five photographs stacked one under another is a long silent
   scroll. They become a strip you swipe instead, with the entrance leading. */
@media (max-width: 760px) {
  .house-gallery {
    display: flex;
    gap: 10px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    margin-inline: calc(var(--gut) * -1);
    padding-inline: var(--gut);
  }
  .house-gallery::-webkit-scrollbar { display: none; }
  .house-gallery figure {
    flex: 0 0 auto;
    width: min(76vw, 340px);
    aspect-ratio: 4 / 3;
    grid-row: auto;
    scroll-snap-align: center;
  }
  .house-gallery figure:first-child { aspect-ratio: 3 / 4; width: min(62vw, 280px); }
}

@media (min-width: 900px) {
  .house { grid-template-columns: 0.82fr 1.18fr; }
  .house-copy { position: sticky; top: clamp(110px, 20vh, 190px); }
}

/* ============================================================
   PRICING
   ============================================================ */

.price-grid { display: grid; gap: clamp(18px, 2vw, 28px); }
@media (min-width: 900px) { .price-grid { grid-template-columns: 1fr 1fr; } }

/* Pricing cards — flat, quiet, typographic. No dark banner, no gradients:
   the room name and the hourly rate carry the hierarchy, the rows are a
   clean price list. */
.price-card {
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--paper);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: border-color .4s var(--ease), box-shadow .4s var(--ease);
}
.price-card:hover { border-color: var(--line); box-shadow: var(--shadow-sm); }

.pc-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  gap: 8px 20px;
  padding: var(--card-pad) var(--card-pad) calc(var(--card-pad) * 0.7);
  border-bottom: 1px solid var(--line-soft);
}
.pc-tag {
  grid-column: 1 / -1;
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.pc-head h3 {
  font-size: var(--fs-h2);
  font-weight: 300;
  color: var(--ink);
  line-height: 1;
}
.pc-dropin { text-align: right; display: flex; align-items: baseline; gap: 8px; }
.pc-dropin-k {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}
.pc-dropin-v { font-family: var(--display); font-size: var(--fs-h3); color: var(--accent-ink); line-height: 1; }

/* rows */
.pc-rows { margin: 0; padding: 6px var(--card-pad); list-style: none; display: grid; }
.pc-rows li { list-style: none; border-bottom: 1px solid var(--line-soft); }
.pc-rows li:last-child { border-bottom: 0; }
.pc-row {
  position: relative;
  display: grid;
  grid-template-columns: 2.2rem 1fr auto;
  align-items: center;
  gap: 16px;
  padding: 15px 0;
  text-decoration: none;
  color: var(--ink);
  transition: color .25s var(--ease);
}
.pc-plan { display: contents; }
.pc-plan b {
  font-family: var(--sans);
  font-size: var(--fs-label);
  font-weight: 700;
  letter-spacing: var(--ls-label);
  color: var(--muted);
}
.pc-plan span { color: var(--muted); font-size: var(--fs-small); }
.pc-right { display: flex; align-items: baseline; gap: 14px; justify-content: flex-end; }
.pc-amt { font-family: var(--display); font-size: var(--fs-h3); color: var(--ink); white-space: nowrap; }
.pc-go {
  font-size: var(--fs-label); font-weight: 600;
  color: var(--accent-ink); white-space: nowrap;
  transition: transform .3s var(--ease);
}
.pc-row:hover .pc-go { transform: translateX(3px); }
.pc-row:hover .pc-amt { color: var(--accent-ink); }

/* the most-booked row is marked with a single accent rule, not a box */
.pc-row.is-popular::before {
  content: "";
  position: absolute;
  left: calc(var(--card-pad) * -1); top: 0; bottom: 0;
  width: 2px;
  background: var(--clay);
}
.pc-row.is-popular .pc-amt { color: var(--accent-ink); }
/* badge is taken out of the flow so it never disturbs the 3-column grid */
.pc-row.is-popular { padding-top: 30px; }
.pc-badge {
  position: absolute;
  top: 7px;
  left: 0;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--accent-ink);
}

.pc-foot {
  margin-top: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: calc(var(--card-pad) * 0.8) var(--card-pad) var(--card-pad);
  border-top: 1px solid var(--line-soft);
}
.pc-valid { font-size: var(--fs-label); color: var(--muted); max-width: 30ch; line-height: 1.5; }

.pc-soon {
  margin-top: auto;
  display: flex; flex-direction: column; align-items: flex-start; gap: 18px;
  padding: var(--card-pad);
}
.pc-soon p { font-size: var(--fs-small); color: var(--muted); max-width: 28ch; line-height: 1.5; }

.redeem-note {
  margin: 26px auto 0; text-align: center;
  font-size: var(--fs-small); color: var(--muted);
}

/* ============================================================
   FLOW / STEPS
   ============================================================ */

/* Four steps read as one continuous move, not as four boxes: no panels, no
   dividing walls. A single hairline runs behind the numerals and each step sits
   a little lower than the last, so the eye travels along the line. */
.flow-steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(34px, 5vh, 56px);
}
.flow-step {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 6px 22px;
}
.flow-step .n {
  font-family: var(--display);
  font-size: clamp(30px, 3vw, 44px);
  font-weight: 300;
  font-style: italic;
  color: var(--clay);
  line-height: 0.9;
}
.flow-step h4 {
  font-family: var(--display);
  font-size: clamp(21px, 1.9vw, 26px);
  font-weight: 300;
  color: var(--deep);
  margin: 0;
}
.flow-step p {
  grid-column: 2;
  font-size: var(--fs-small);
  color: var(--muted);
  margin: 8px 0 0;
  max-width: 34ch;
}

@media (min-width: 760px) {
  .flow-steps {
    grid-template-columns: repeat(4, 1fr);
    gap: clamp(24px, 3vw, 48px);
    position: relative;
  }
  /* the line the steps hang from */
  .flow-steps::before {
    content: "";
    position: absolute;
    left: 4px; right: 4px;
    top: 0;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--line), var(--line), transparent);
  }
  .flow-step {
    grid-template-columns: 1fr;
    gap: 0;
    padding-top: 28px;
  }
  /* organic stagger: 2 and 4 hang a little lower than 1 and 3 */
  .flow-step:nth-child(even) { padding-top: clamp(46px, 5.4vh, 66px); }
  .flow-step .n {
    display: block;
    margin-bottom: 16px;
  }
  .flow-step h4 { max-width: 14ch; }
  .flow-step p { grid-column: 1; }
}

.tone-pine .flow-steps::before {
  background: linear-gradient(90deg, transparent, var(--on-dark-line), var(--on-dark-line), transparent);
}
.tone-pine .flow-step .n { color: var(--clay); }
.tone-pine .flow-step h4 { color: var(--on-dark); }
.tone-pine .flow-step p { color: var(--on-dark-faint); }

/* ============================================================
   PRACTITIONERS
   ============================================================ */

.prac-grid { display: grid; gap: 24px; counter-reset: prac; }
@media (min-width: 760px) { .prac-grid { grid-template-columns: 1fr 1fr; } }
.prac-card {
  counter-increment: prac;
  position: relative;
  background: rgba(248, 245, 240, 0.72);
  border: 1px solid rgba(18, 18, 17, 0.10);
  border-radius: var(--radius);
  padding: 40px 38px 36px;
  overflow: hidden;
  transition: transform .5s var(--ease), box-shadow .5s var(--ease);
}
.prac-card::before {
  content: "";
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 4px; background: var(--deep);
  transform: scaleY(0); transform-origin: top;
  transition: transform .6s var(--ease);
}
.prac-card.is-visible::before { transform: scaleY(1); }
.prac-card::after {
  content: counter(prac, decimal-leading-zero);
  position: absolute; top: 22px; right: 30px;
  font-family: var(--display); font-weight: 300; font-style: italic;
  font-size: 64px; line-height: 1; color: var(--sand); opacity: 0.5;
}
.prac-card:hover { transform: translateY(-5px); box-shadow: var(--shadow-sm); }
.prac-card h3 { font-size: var(--fs-h3); color: var(--ink); font-weight: 300; margin: 0 0 26px; max-width: 11ch; }

.team-groups { display: grid; gap: clamp(34px, 6vw, 72px); }
.team-group {
  display: grid;
  gap: 24px;
  padding-top: 34px;
  border-top: 1px solid rgba(18, 18, 17, 0.10);
}
.team-group-head {
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 18px;
}
.team-group-head span {
  font-family: var(--display);
  color: var(--accent-ink);
  font-size: 24px;
}
.team-group-head h2 {
  color: var(--deep);
  font-size: var(--fs-h2);
  font-weight: 300;
  line-height: 1;
}
/* Practitioner cards — portrait-led so the people are the subject.
   Equal-height columns, photo on top, details below. */
.team-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: clamp(16px, 1.6vw, 24px);
}
.team-card {
  display: grid;
  grid-template-rows: auto 1fr;
  overflow: hidden;
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  background: var(--paper);
  text-align: left;
  box-shadow: var(--shadow-sm);
  transition: transform .4s var(--ease), border-color .4s var(--ease), box-shadow .4s var(--ease);
}
.team-card:hover,
.team-card:focus-within {
  transform: translateY(-4px);
  border-color: rgba(222, 174, 135, 0.5);
  box-shadow: var(--shadow);
}

/* portrait, or the practitioner's initials when no photo was supplied */
.tc-photo {
  width: 100%;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--paper-2);
  display: grid;
  place-items: center;
}
.tc-photo picture, .tc-photo img { width: 100%; height: 100%; display: block; }
.tc-photo img { object-fit: cover; transition: transform .6s var(--ease); }
/* Portrait framing, tuned per photo after visual checks.
   --zoom lets a wide/full-body shot be pushed in on the face; it composes
   with the hover scale below so both effects survive.
   Percentages are ratio-based and the box is always 1:1, so the framing
   holds identically at every screen size. */
.tc-photo img { --zoom: 1; object-position: center 32%; transform: scale(var(--zoom)); }
.team-card:hover .tc-photo img { transform: scale(calc(var(--zoom) * 1.04)); }

.tc-photo img[src*="saskia-van-gils"]  { object-position: 60% 28%; }
.tc-photo img[src*="carla-talina"]     { object-position: center 28%; }
.tc-photo img[src*="daniel-fischer"]   { object-position: center 20%; }
.tc-photo img[src*="esteban-hezkibel"] { object-position: 45% 32%; }
.tc-photo img[src*="isabel-cocheira"]  { object-position: center 12%; }
.tc-photo img[src*="joseph-wilders"]   { object-position: center 25%; }
.tc-photo img[src*="daniela"]          { object-position: center 30%; }
/* full-body shot taken from across the room — pushed in so the face reads */
.tc-photo img[src*="joao-sequeira"]    { object-position: 35% 18%; }

/* No portrait supplied yet: show the A SALA mark on a soft beige field
   instead of initials — reads as intentional rather than as a gap. */
.tc-photo-empty {
  background: linear-gradient(160deg, var(--paper-2) 0%, var(--sand) 100%);
  place-items: center;
}
.tc-photo-empty img {
  width: 30%;
  height: auto;
  opacity: 0.55;
  transform: none;
}
.team-card:hover .tc-photo-empty img { transform: none; opacity: 0.7; }


.tc-body {
  padding: var(--card-pad);
  display: grid;
  align-content: start;
  gap: 8px;
}
.team-card h3 {
  font-size: var(--fs-h3);
  color: var(--ink);
  font-weight: 300;
  margin: 0;
}
.tc-services { font-size: var(--fs-small); line-height: 1.55; color: var(--muted); margin: 0; }
.tc-contact {
  display: grid;
  gap: 2px;
  margin: 6px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line-soft);
  font-size: 13px;
}
.tc-contact a { color: var(--accent-ink); word-break: break-word; }
.tc-contact a:hover { text-decoration: underline; }
.team-card p {
  margin: 0;
  color: var(--muted);
  font-size: var(--fs-small);
  line-height: 1.45;
}

/* ============================================================
   FAQ
   ============================================================ */

.faq-list { display: grid; gap: 0; border-top: 1px solid var(--line); max-width: 880px; margin-inline: auto; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item summary {
  list-style: none;
  cursor: pointer;
  padding: 26px 50px 26px 0;
  position: relative;
  font-family: var(--display);
  font-size: var(--fs-h3);
  font-weight: 300;
  color: var(--deep);
  text-align: center;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "";
  position: absolute; right: 6px; top: 50%;
  width: 16px; height: 16px;
  background:
    linear-gradient(var(--clay),var(--clay)) center/16px 1.5px no-repeat,
    linear-gradient(var(--clay),var(--clay)) center/1.5px 16px no-repeat;
  transform: translateY(-50%) rotate(0deg);
  transition: transform .4s var(--ease);
}
.faq-item[open] summary::after { transform: translateY(-50%) rotate(135deg); }
.faq-item .faq-a {
  padding: 0 clamp(0px, 6vw, 60px) 28px;
  color: var(--muted);
  font-size: var(--fs-body);
  max-width: 70ch;
  margin-inline: auto;
  text-align: center;
}
.faq-item .faq-a p { margin: 0 0 10px; }

/* ============================================================
   PRIVACY
   ============================================================ */

.privacy-hero { min-height: 54svh; }
.privacy-hero .ph-media img { object-position: center 62%; }
.privacy-wrap { padding-block: clamp(64px, 9vw, 120px); }
.privacy-intro {
  max-width: 760px;
  margin: 0 auto clamp(44px, 7vw, 78px);
  text-align: center;
}
.privacy-intro > p:first-child {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(26px, 3.2vw, 44px);
  font-weight: 300;
  line-height: 1.18;
  color: var(--deep);
}
.privacy-updated {
  margin: 18px 0 0;
  color: var(--muted);
  font-size: var(--fs-small);
}
.privacy-grid {
  width: min(1040px, 100%);
  margin-inline: auto;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
}
.privacy-card {
  min-width: 0;
  padding: clamp(28px, 4vw, 50px);
  background: var(--paper);
}
.privacy-card h2 {
  margin: 0 0 16px;
  color: var(--deep);
  font-size: var(--fs-h3);
  font-weight: 300;
}
.privacy-card p,
.privacy-card li {
  color: var(--muted);
  font-size: var(--fs-small);
  line-height: 1.7;
}
.privacy-card p { margin: 0; }
.privacy-card ul { margin: 0; padding-left: 18px; display: grid; gap: 10px; }
.privacy-links { display: flex; flex-wrap: wrap; gap: 8px 18px; margin-top: 20px !important; }
.privacy-links a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }

/* ============================================================
   LOCAL / CONTACT
   ============================================================ */

/* The invitation to book is the FIRST BLOCK OF THE FOOTER,
not a band of its
   own: one section,
one photograph { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 8px; }

/* ============================================================
   FOOTER
   ============================================================ */

.site-footer {
  /* The patio, the friendliest corner of the house, is the ONE photograph here
     and it runs behind the whole footer: the invitation to book, the columns
     and the legal line all stand on the same picture, under one scrim. */
  background:
    linear-gradient(180deg, rgba(var(--photo-scrim), 0.76) 0%, rgba(var(--photo-scrim), 0.72) 42%, rgba(var(--photo-scrim), 0.86) 100%),
    url("assets/photos/footer-patio.webp") center 58% / cover no-repeat;
  color: var(--on-dark);
  padding: clamp(64px, 10vh, 120px) var(--gut) 40px;
  position: relative;
  overflow: hidden;
}
/* the footer photograph starts at a hard edge against whatever came before it;
   this short fade at the very top lets it arrive instead of appearing */
.site-footer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: clamp(60px, 9vh, 120px);
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg, #101010 0%, rgba(16, 16, 16, 0) 100%);
}

/* the invitation, centred, opening the footer */
.footer-cta {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 18px;
  max-width: 900px;
  margin: 0 auto clamp(64px, 9vh, 104px);
}
.footer-cta .label { justify-content: center; }
.footer-cta .label::before { display: none; }
.footer-cta h2 {
  text-shadow: 0 2px 26px rgba(12, 12, 11, 0.62);
  font-size: var(--fs-h2);
  color: var(--on-dark);
  font-weight: 300;
  line-height: 1.02;
  max-width: 24ch;
}
.footer-cta .btn { margin-top: 16px; min-width: 200px; }
/* a hairline where the invitation ends and the columns begin, instead of the
   hard edge two separate sections used to make */
.footer-cta + .footer-top {
  border-top: 1px solid rgba(248, 245, 240, 0.12);
  padding-top: clamp(48px, 7vh, 80px);
}
.footer-top { display: grid; gap: 48px; position: relative; z-index: 1; }
@media (min-width: 880px) { .footer-top { grid-template-columns: 1.4fr 1fr 1fr; align-items: start; } }
.footer-brand .brand-name { font-family: var(--brand); font-weight: 300; font-size: 28px; color: var(--on-dark);  letter-spacing: var(--ls-brand); }
.footer-brand p { color: rgba(248, 245, 240, 0.72); text-shadow: 0 1px 14px rgba(12, 12, 11, 0.6); max-width: 34ch; margin: 22px 0 0; font-size: var(--fs-small); }
.footer-col h5 { font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--sand); margin: 0 0 18px; font-weight: 600; }
.footer-col a, .footer-col p { display: block; color: rgba(248, 245, 240, 0.86); text-shadow: 0 1px 14px rgba(12, 12, 11, 0.6); font-size: var(--fs-small); margin: 0 0 12px; transition: color .3s var(--ease); }
.footer-col a:hover { color: var(--clay); }
.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 16px; justify-content: space-between;
  margin-top: clamp(48px, 7vh, 84px);
  padding-top: 28px;
  border-top: 1px solid rgba(248, 245, 240, 0.14);
  font-size: var(--fs-label);
  color: rgba(248, 245, 240, 0.62);
  text-shadow: 0 1px 14px rgba(12, 12, 11, 0.6);
  letter-spacing: var(--ls-wide);
  position: relative; z-index: 1;
}

/* ============================================================
   INTERIOR PAGE HERO (subpages)
   ============================================================ */

.page-shell { padding-top: 0; }
.page-hero {
  position: relative;
  min-height: 64svh;
  display: grid;
  align-content: center;
  justify-items: center;
  text-align: center;
  padding: 160px var(--gut) clamp(48px, 7vh, 80px);
  color: var(--on-dark);
  overflow: hidden;
  isolation: isolate;
}
.page-hero .ph-media, .page-hero .ph-scrim { position: absolute; inset: 0; z-index: -2; }
.page-hero .ph-media { transform: scale(1.05); }
.page-hero .ph-media img { object-position: center; }
/* One neutral vertical gradient, like the home hero: no colour cast, no side
   veils, just enough shade at top and bottom for the header and the seam. */
.page-hero .ph-scrim {
  z-index: -1;
  background: linear-gradient(180deg,
    rgba(var(--photo-scrim), 0.42) 0%,
    rgba(var(--photo-scrim), 0.20) 40%,
    rgba(var(--photo-scrim), 0.62) 100%);
}
/* The title is the whole hero. margin-inline: auto matters: without it a
   max-width narrower than a sibling parks the h1 box on the left and the
   centred text inside it reads visibly off-centre. */
.page-hero .reveal { opacity: 1; transform: none; width: 100%; }
.page-hero h1 {
  text-shadow: 0 2px 28px rgba(12, 12, 11, 0.6), 0 1px 3px rgba(12, 12, 11, 0.35);
  font-size: var(--fs-display);
  font-weight: 300;
  color: var(--on-dark);
  line-height: 1;
  margin: 0 auto;
  max-width: 18ch;
  text-align: center;
}
.page-hero p {
  text-shadow: 0 1px 20px rgba(12, 12, 11, 0.75);
  max-width: 56ch;
  margin: 22px auto 0;
  color: rgba(248, 245, 240, 0.84);
  font-size: 17px;
  text-align: center;
}

/* ============================================================
   BOOKING
   ============================================================ */

.booking-shell { padding-top: clamp(92px, 10vh, 118px); min-height: 100svh; }
.booking-privacy {
  margin: 0;
  padding: 34px var(--gut) 42px;
  text-align: center;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.booking-privacy a { color: rgba(248, 245, 240, 0.68); }
.booking-privacy a:hover { color: var(--on-dark); }
/* Booking pages get a clean, calm dark backdrop — no photo bleed behind the
   content, so the steps and room cards stay readable. The signature image is
   reserved for the footer, which also carries the "reserve a space" invitation. */
.booking-head { max-width: none; padding: clamp(40px,6vh,72px) var(--gut) 0; margin-inline: 0; text-align: left; }
/* back link left, chosen space centred, step counter right */
.booking-head-row {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 18px;
}
.booking-head-row .back-link { justify-self: start; }
.booking-head-row .step-count { justify-self: end; }
.head-chip { justify-self: center; }
.head-chip:empty { display: none; }
@media (max-width: 860px) {
  /* no room for three columns: the chip drops to its own line */
  .booking-head-row { grid-template-columns: 1fr auto; }
  .head-chip { grid-row: 2; grid-column: 1 / -1; justify-self: start; }
}
.booking-head-row .back-link { margin-bottom: 0; }
.booking-head .step-count { font-size: var(--fs-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--clay); }
/* the booking pages sit straight on the dark ground, so this title is on-dark */
.booking-head h1 { font-size: var(--fs-display); color: var(--on-dark); font-weight: 300; line-height: 0.92; margin: clamp(12px, 2vh, 20px) 0 0; }
.booking-head p { color: rgba(248, 245, 240, 0.76); margin: 18px 0 0; max-width: 56ch; }
.booking-head-row .step-count { margin: 0; text-align: right; }
.booking-head .back-link { color: rgba(248, 245, 240, 0.72); }
.booking-head .back-link:hover { color: var(--on-dark); }

/* ------------------------------------------------------------------
   BOOKING · STEP 1 — the room picker as a 2×2 grid of tiles
   Full-width rows read as a table; tiles read as places. Photograph on
   top, one line of facts under it, and the whole tile is the link — no
   pill, the hover is the affordance.
   ------------------------------------------------------------------ */
.booking-picker { padding: clamp(20px, 3vh, 36px) var(--gut) clamp(40px, 6vh, 72px); }
.booking-list { display: grid; gap: 14px; }
@media (min-width: 640px) { .booking-list { grid-template-columns: 1fr 1fr; } }
/* four across on a laptop: the photos keep their natural 4/3 and the whole
   step still fits one screen */
@media (min-width: 1100px) { .booking-list { grid-template-columns: repeat(4, 1fr); } }

.booking-row {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 14px;
  padding: 10px 10px 16px;
  border: 1px solid var(--on-dark-line);
  border-radius: var(--radius-lg);
  background: rgba(248, 245, 240, 0.035);
  color: var(--on-dark);
  text-align: left;
  cursor: pointer;
  transition: background .35s var(--ease), border-color .35s var(--ease), transform .35s var(--ease);
}
.booking-row:hover,
.booking-row:focus-visible {
  background: rgba(248, 245, 240, 0.07);
  border-color: rgba(222, 174, 135, 0.42);
  transform: translateY(-2px);
}

.br-ph {
  display: block;
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
  background: var(--deep-800);
}
.br-ph picture, .br-ph img { width: 100%; height: 100%; display: block; }
.br-ph img { object-fit: cover; transition: transform .8s var(--ease); }
.booking-row:hover .br-ph img { transform: scale(1.04); }

.br-body { display: grid; gap: 6px; min-width: 0; padding: 0 8px; }
.br-head { display: flex; align-items: baseline; gap: 12px; }
.br-num {
  font-family: var(--display);
  font-size: clamp(15px, 1.4vw, 17px);
  font-weight: 400;
  color: var(--clay);
  line-height: 1;
}
.br-use {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--sand);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* title on the left, both prices on the right, one line */
.br-title-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.br-title {
  font-family: var(--display);
  font-size: clamp(20px, 1.55vw, 24px);
  font-weight: 300;
  line-height: 1.05;
  color: var(--on-dark);
}
.br-rate { display: flex; align-items: baseline; gap: 6px; white-space: nowrap; }
.br-rate b { font-family: var(--display); font-size: clamp(20px, 1.55vw, 24px); font-weight: 400; color: var(--clay); line-height: 1; }
.br-rate small { font-size: var(--fs-label); letter-spacing: var(--ls-wide); color: var(--on-dark-faint); }
.br-services {
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--on-dark-faint);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.br-price { display: grid; gap: 3px; justify-items: end; }
.br-alt {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-wide);
  color: var(--on-dark-faint);
  white-space: nowrap;
}

/* ------------------------------------------------------------------
   BOOKING · STEP 2 — how long
   Three quiet cards. The duration is the headline, the price sits under
   it, and one line says what that length is usually for.
   ------------------------------------------------------------------ */
.time-desc { color: var(--on-dark-soft); }

/* the chosen space, carried through steps 2 and 3 */
.chosen-chip {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  margin: 0;
  padding: 6px 20px 6px 6px;
  border: 1px solid var(--on-dark-line);
  border-radius: 14px;
  background: rgba(248, 245, 240, 0.05);
}
/* a landscape crop of a landscape photograph: a circle cut these room shots
   into an unreadable fragment */
.cc-ph {
  display: block;
  width: 64px;
  height: 44px;
  flex: none;
  overflow: hidden;
  border-radius: 8px;
  background: var(--deep-800);
}
.cc-ph picture { display: block; width: 100%; height: 100%; }
.cc-ph img { width: 100%; height: 100%; display: block; object-fit: cover; object-position: center; }
.cc-txt { display: grid; gap: 2px; }
.cc-txt b {
  font-family: var(--display);
  font-size: clamp(17px, 1.5vw, 21px);
  font-weight: 400;
  line-height: 1.1;
  color: var(--on-dark);
}
.cc-txt span {
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--clay);
}

.time-grid { display: grid; gap: 14px; }
@media (min-width: 760px) { .time-grid { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); } }

.time-opt {
  display: grid;
  align-content: start;
  gap: 6px;
  padding: clamp(20px, 2.6vw, 30px);
  border: 1px solid var(--on-dark-line);
  border-radius: var(--radius-lg);
  background: rgba(248, 245, 240, 0.035);
  color: var(--on-dark);
  transition: background .35s var(--ease), border-color .35s var(--ease), transform .35s var(--ease);
}
.time-opt:hover,
.time-opt:focus-visible {
  background: rgba(248, 245, 240, 0.07);
  border-color: rgba(222, 174, 135, 0.42);
  transform: translateY(-2px);
}
.to-len {
  font-family: var(--display);
  font-size: clamp(26px, 2.6vw, 36px);
  font-weight: 300;
  line-height: 1;
}
.to-price {
  font-family: var(--display);
  font-size: clamp(19px, 1.7vw, 23px);
  color: var(--clay);
  line-height: 1;
}
.to-body { margin-top: 8px; font-size: var(--fs-small); line-height: 1.55; color: var(--on-dark-faint); }

/* what people actually want to know before they commit */
.booking-reassure {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin: clamp(26px, 4vh, 40px) 0 0;
  padding: 0;
  list-style: none;
}
.booking-reassure li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-small);
  color: var(--on-dark-faint);
}
.booking-reassure li::before {
  content: "";
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--clay);
  flex: none;
}

/* acuity / booking */
.booking-two {
  display: grid;
  gap: 30px;
  width: min(1160px, calc(100% - (var(--gut) * 2)));
  margin-inline: auto;
  padding: 0 0 clamp(72px,10vh,120px);
}
.acuity-shell { display: grid; gap: 22px; }
.booking-flow {
  display: grid;
  gap: clamp(20px, 3vw, 32px);
}
/* The three steps share one ground: the same dark surface, the same cards, the
   same pills. Step 3 used to swap in the room photograph and a cream panel,
   which made the last step look like a different site. */
/* No container around the calendar step: the bar and the embed sit straight
   on the page. A frame around a frame was decoration, not structure. */
.booking-flow-panel {
  display: grid;
  gap: clamp(14px, 1.8vw, 20px);
  animation: panelIn .5s var(--ease) both;
}
/* space, instruction and durations on one line */
.flow-bar {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 24px;
}
.flow-bar-title { display: grid; gap: 4px; }

.booking-room-scheduler {
  scroll-margin-top: 7rem;
}

/* The Packs nav entry lands here, clear of the sticky header. */
#packs {
  scroll-margin-top: 7rem;
}

.booking-room-scheduler:empty {
  display: none;
}
@keyframes panelIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .booking-flow-panel { animation: none; }
}
.flow-bar-title .label { color: var(--sand); }
.flow-bar-title h2 {
  color: var(--on-dark);
  font-size: clamp(24px, 2.4vw, 32px);
  font-weight: 300;
  line-height: 1;
}
/* The 1h / 1h30 choice lives on the site so the Acuity embed can skip its
   own "Select Appointment" list and open straight on the calendar. */
.duration-toggle {
  display: flex;
  gap: 10px;
}
.duration-opt {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  min-height: 44px;
  padding: 0 22px;
  border: 1px solid rgba(248, 245, 240, 0.34);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--on-dark);
  font: inherit;
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
}
.duration-opt b { font-weight: 500; }
.duration-opt span { color: var(--on-dark-faint); font-size: var(--fs-small); }
.duration-opt:hover { border-color: var(--on-dark); }
.duration-opt.is-active {
  background: var(--clay);
  border-color: var(--clay);
  color: var(--accent-on);
}
.duration-opt.is-active span { color: inherit; opacity: 0.75; }
.duration-note {
  color: var(--on-dark-faint);
  font-size: var(--fs-small);
  margin: -4px 0 0;
}
/* Anyone who lands on checkout without credits needs a way out to the shop. */
.packs-link {
  color: var(--clay);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  white-space: nowrap;
}
.packs-link:hover { color: var(--deep); }
@media (max-width: 560px) {
  .booking-shell { padding-top: 88px; }
}
.acuity-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  background: linear-gradient(150deg, var(--paper), var(--paper-2));
  padding: clamp(28px, 4vw, 44px);
}
.acuity-card h2 { font-size: var(--fs-h2); color: var(--deep); font-weight: 300; margin-bottom: 14px; }
.acuity-card p { color: var(--muted); max-width: 60ch; }
.acuity-card ol { margin: 26px 0 0; padding: 0; list-style: none; display: grid; gap: 10px; }
.acuity-card li { padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); font-size: var(--fs-small); color: var(--ink); display: flex; gap: 14px; }
.acuity-card li b { color: var(--accent-ink); font-family: var(--display); font-size: 18px; }
.acuity-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
/* Acuity repeats the room, the duration, the price and a photograph above its
   calendar. Cropping it out with a fixed offset was tried and reverted: the
   offset moves with the viewport width and with whether the appointment type
   carries a photo, so the cut landed inside the calendar on real screens.
   Removing it belongs in the Acuity admin, not here. */
.acuity-embed { border-radius: var(--radius-lg); overflow: hidden; background: var(--paper); }
.acuity-embed iframe { display: block; width: 100%; min-height: 760px; border: 0; }

/* ------------------------------------------------------------------
   BOOKING ON DESKTOP — one screen per step
   A step you have to scroll is not a step. On a laptop each of the three
   pages is laid out to fit the viewport: smaller step titles, one-line
   room rows, and the reassurance and privacy lines pulled into a thin
   strip at the bottom. The calendar is the one thing that can still
   overflow — the Acuity iframe needs its 760px and we do not control it.
   ------------------------------------------------------------------ */
@media (min-width: 1024px) {
  /* No forced 100svh: stretching a short step to the full height only opened a
     hole between the title and the cards. The page is as tall as its content,
     which on these two steps is already less than a screen. */
  body[data-page="booking"] .booking-shell { min-height: 0; padding-top: 92px; }
  .booking-head { padding-top: clamp(16px, 2.6vh, 30px); margin-inline: 0; }
  .booking-head h1 { font-size: clamp(30px, 3.1vw, 44px); line-height: 1.02; }
  .booking-head p { font-size: var(--fs-small); margin-top: 10px; max-width: 62ch; }
  .booking-picker { padding-top: clamp(20px, 3vh, 34px); padding-bottom: 0; }

  /* shared bottom strip */
  .booking-reassure { margin-top: clamp(14px, 2.2vh, 24px); gap: 8px 24px; }
  .booking-two { padding-bottom: 0; }
  .booking-privacy { padding: 8px var(--gut) 10px; }
}

/* ============================================================
   LAYER 5 — MOTION & RESPONSIVE
   ------------------------------------------------------------
   REVEAL ANIMATIONS
   ============================================================ */

.reveal { opacity: 0; transform: translateY(34px); transition: opacity 1s var(--ease), transform 1.1s var(--ease); }
.reveal.is-visible { opacity: 1; transform: none; }
.reveal[data-delay="1"] { transition-delay: .1s; }
.reveal[data-delay="2"] { transition-delay: .2s; }
.reveal[data-delay="3"] { transition-delay: .3s; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
  .page-hero .ph-media,
  .space-slide .ph {
    transform: none !important;
    will-change: auto;
  }
}

@media (hover: none), (pointer: coarse) {
  .space-slide .meta p {
    opacity: 1;
    max-height: 140px;
  }
}

@media (max-width: 720px) {
  body { background: var(--dark-ground); }
  .privacy-grid { grid-template-columns: 1fr; }
  .privacy-card { padding: 28px 24px; }
  .hero {
    min-height: 100svh;
    align-items: center;
    padding: 104px var(--gut) max(52px, env(safe-area-inset-bottom));
  }
  .hero-inner {
    width: min(360px, 100%);
    margin: 0 auto;
  }
  .hero-wordmark { font-size: clamp(38px, 13vw, 62px); }
  .hero h1 {
    font-size: 21px;
    line-height: 1.3;
    max-width: 24ch;
  }
  .hero .hero-actions {
    gap: 12px;
  }
  .hero .hero-actions .btn {
    width: min(260px, 100%);
    min-height: 56px;
  }

  body[data-booking-page="room"] .booking-shell {
    padding-top: 78px;
  }
    body[data-booking-page="room"] .booking-head {
    padding-top: 26px;
  }
}

/* ============================================================
   BOOKING — back link, calendar, pay choice
   ============================================================ */

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 20px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: var(--ls-wide);
  color: var(--muted);
  transition: color .3s var(--ease), gap .3s var(--ease);
}
.back-link:hover { color: var(--deep); gap: 12px; }
.back-link span[aria-hidden] { font-size: 17px; line-height: 1; }
