/* ==========================================================================
   Maison Noir — salon & med spa, Santana Row, San Jose CA
   Property token group: "maison".

   The :root block below is GENERATED from design-system/tokens.json.
   Do not hand-edit it. Edit tokens.json, re-run tools/check_tokens.py,
   and regenerate. Every rule after :root consumes var(--semantic-role) only.
   ========================================================================== */

:root {
  color-scheme: dark;

  /* --- primitives — tokens.json > primitive.maison ----------------------- */
  --maison-noir-950: #0A0A0A;
  --maison-noir-900: #121211;
  --maison-noir-850: #191816;
  --maison-noir-800: #22201D;
  --maison-noir-700: #33302B;
  --maison-noir-500: #6B6558;
  --maison-gold-300: #E2CE9B;
  --maison-gold-400: #D4BC7E;
  --maison-gold-500: #C0A55E;
  --maison-gold-600: #9C8342;
  --maison-bone-050: #F4F1EA;
  --maison-bone-300: #C6C0B3;
  --maison-bone-400: #A49D8E;
  --maison-white: #FFFFFF;

  /* --- semantic roles — tokens.json > semantic.maison -------------------- */
  --bg:                       var(--maison-noir-950);
  --surface:                  var(--maison-noir-900);
  --surface-raised:           var(--maison-noir-850);
  --surface-inset:            var(--maison-noir-800);
  --border-subtle:            var(--maison-noir-700);
  --border-interactive:       var(--maison-noir-500);
  --border-interactive-hover: var(--maison-bone-400);
  --text-primary:             var(--maison-bone-050);
  --text-secondary:           var(--maison-bone-300);
  --text-muted:               var(--maison-bone-400);
  --action-primary:           var(--maison-gold-400);
  --action-primary-hover:     var(--maison-gold-300);
  --on-action-primary:        var(--maison-noir-950);
  --accent-graphic:           var(--maison-gold-500);
  --focus-ring:               var(--maison-gold-400);
  --danger:                   var(--maison-gold-600);

  /* --- type stacks — tokens.json > typography.maison (verbatim) ---------- */
  --font-display: 'Bodoni Moda', 'Didot', 'Playfair Display', Georgia, serif;
  --font-body: 'Jost', 'Futura', 'Century Gothic', system-ui, sans-serif;

  /* --- shared scale: space — tokens.json > scales.space ------------------ */
  --space-0: 0px;
  --space-px: 2px;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-32: 128px;
  --space-40: 160px;

  /* --- shared scale: type — tokens.json > scales.type -------------------- */
  --type-xs: 12px;
  --type-sm: 14px;
  --type-base: 16px;
  --type-md: 18px;
  --type-lg: 20px;
  --type-xl: 24px;
  --type-2xl: 30px;
  --type-3xl: 36px;
  --type-4xl: 48px;
  --type-5xl: 60px;
  --type-6xl: 72px;
  --type-7xl: 96px;

  /* --- shared scale: leading — tokens.json > scales.leading -------------- */
  --leading-tight: 1.05;
  --leading-snug: 1.2;
  --leading-normal: 1.5;
  --leading-relaxed: 1.65;
  --leading-loose: 1.75;

  /* --- shared scale: weight — tokens.json > scales.weight ---------------- */
  --weight-light: 300;
  --weight-regular: 400;
  --weight-medium: 500;
  --weight-semibold: 600;
  --weight-bold: 700;
  --weight-black: 800;

  /* --- shared scale: radius — tokens.json > scales.radius ---------------- */
  /* Maison Noir binds radius-none only. Hard edges throughout. */
  --radius-none: 0px;
  --radius-xs: 2px;
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-xl: 16px;
  --radius-2xl: 20px;
  --radius-3xl: 24px;
  --radius-4xl: 32px;
  --radius-full: 999px;

  /* --- shared scale: motion — tokens.json > scales.motion ---------------- */
  --dur-instant: 120ms;
  --dur-fast: 180ms;
  --dur-base: 240ms;
  --dur-slow: 320ms;
  --dur-slower: 480ms;
  --dur-slowest: 640ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* --- shared scale: z — tokens.json > scales.z -------------------------- */
  --z-base: 0;
  --z-raised: 10;
  --z-sticky: 20;
  --z-overlay: 40;
  --z-modal: 100;
  --z-toast: 1000;

  /* --- shared scale: container — tokens.json > scales.container ---------- */
  --container-prose: 680px;
  --container-narrow: 880px;
  --container-default: 1160px;
  --container-wide: 1360px;
}


/* ==========================================================================
   PHOTO SWAP POINTS
   Every image on this page is hand-authored inline SVG plus layered CSS
   gradients. Replace the art on these selectors with real photography when
   the client supplies a shoot. Keep the zero-radius, no-shadow treatment.

     .hero__art        -> 1920x1080 full-bleed interior or campaign frame
     .treatment__art   -> 1200x1400 portrait crop, one per signature protocol
     .member__art      -> 800x1000 portrait, one per provider
     .visit__map       -> 1440x840 static map export or exterior shot

   When swapping: drop the inline <svg> from the markup, set
   background-image on the selector, and keep the existing aspect-ratio
   and object-fit rules so the layout does not move.
   ========================================================================== */


/* ==========================================================================
   RESET AND BASE
   ========================================================================== */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--space-20);
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: var(--type-base);
  font-weight: var(--weight-light);
  line-height: var(--leading-relaxed);
  letter-spacing: 0.01em;
  /* clip, not hidden: `hidden` would make body a scroll container and
     break the sticky header. */
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, p, dl, dd, figure, blockquote { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
/* Must follow the rule above: an author `display` on a type selector beats the
   UA `[hidden] { display: none }` regardless of specificity, which would
   otherwise keep hidden SVG icons (the nav close glyph) painted. */
[hidden] { display: none !important; }
button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

::selection {
  background: var(--action-primary);
  color: var(--on-action-primary);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  z-index: var(--z-toast);
  padding: var(--space-3) var(--space-5);
  background: var(--action-primary);
  color: var(--on-action-primary);
  font-size: var(--type-sm);
  font-weight: var(--weight-medium);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius-none);
  transform: translateY(-200%);
  transition: transform var(--dur-fast) var(--ease-out);
}

.skip-link:focus-visible { transform: translateY(0); }


/* ==========================================================================
   TYPOGRAPHY ROLES
   ========================================================================== */

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  line-height: var(--leading-normal);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.link {
  color: var(--action-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--dur-slower) var(--ease-out),
              text-decoration-thickness var(--dur-slower) var(--ease-out);
}

.link:hover {
  color: var(--action-primary-hover);
  text-decoration-thickness: 2px;
}

.link--quiet {
  color: var(--text-secondary);
  text-decoration-color: var(--border-interactive);
}

.link--quiet:hover {
  color: var(--action-primary);
  text-decoration-color: var(--action-primary);
}


/* ==========================================================================
   HAIRLINE RULE — draws in from the left on section entry
   ========================================================================== */

.rule {
  display: block;
  width: 100%;
  height: 1px;
  background: var(--accent-graphic);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-slowest) var(--ease-out);
}

/* Rules live inside a `.reveal` section head, so the descendant selector is
   the only one that ever fires. */
.is-visible .rule { transform: scaleX(1); }


/* ==========================================================================
   BUTTON — MASTER section 6 contract
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: var(--space-3) var(--space-5);
  border: 1px solid transparent;
  border-radius: var(--radius-none);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  line-height: var(--leading-normal);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  transition: background-color var(--dur-slower) var(--ease-out),
              color var(--dur-slower) var(--ease-out),
              border-color var(--dur-slower) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}

.btn--primary {
  background: var(--action-primary);
  color: var(--on-action-primary);
  border-color: var(--action-primary);
}

.btn--primary:hover {
  background: var(--action-primary-hover);
  border-color: var(--action-primary-hover);
}

.btn--secondary {
  background: transparent;
  color: var(--action-primary);
  border-color: var(--action-primary);
}

.btn--secondary:hover {
  background: var(--surface-raised);
  color: var(--action-primary-hover);
  border-color: var(--action-primary-hover);
}

/* MASTER section 6: ghost carries no border. Secondary is the bordered
   variant; the gold edge only appears on hover. */
.btn--ghost {
  background: transparent;
  color: var(--text-primary);
  border-color: transparent;
}

.btn--ghost:hover {
  background: var(--surface-raised);
  color: var(--action-primary);
  border-color: var(--action-primary);
}

.btn:active { transform: scale(0.98); }

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
}

.btn--sm {
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  letter-spacing: 0.16em;
}

.btn--lg {
  min-height: 52px;
  padding: var(--space-4) var(--space-6);
}

@media (min-width: 1024px) {
  .btn--sm { min-height: 36px; }
}


/* ==========================================================================
   HEADER AND PRIMARY NAV
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--bg);
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur-slower) var(--ease-out),
              border-color var(--dur-slower) var(--ease-out);
}

.site-header.is-scrolled {
  background: var(--surface);
  border-bottom-color: var(--border-subtle);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: var(--space-3) var(--space-5);
}

/* The header is a stacking context (sticky + z-index), and the open nav is a
   fixed, opaque, full-viewport child of it. Lifting the two header controls to
   z-modal keeps them painted above that overlay so the menu can be dismissed
   by tapping Close. Inert while the nav is closed — nothing else overlaps. */
.brand,
.nav-toggle {
  position: relative;
  z-index: var(--z-modal);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  min-height: 44px;
  color: var(--text-primary);
  text-decoration: none;
}

.brand__mark {
  width: var(--space-6);
  height: var(--space-6);
  flex: 0 0 auto;
  color: var(--action-primary);
}

.brand__word {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 18;
  font-size: var(--type-md);
  font-weight: var(--weight-regular);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  line-height: var(--leading-snug);
}

.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  min-width: 44px;
  padding: var(--space-2) var(--space-3);
  /* WCAG 1.4.11: this border is the whole visible boundary of the only nav
     control on mobile, so it takes border-interactive at 3.42:1 rather than
     the 1.51:1 decorative hairline. */
  border: 1px solid var(--border-interactive);
  border-radius: var(--radius-none);
  background: transparent;
  color: var(--text-primary);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  cursor: pointer;
  transition: border-color var(--dur-slower) var(--ease-out),
              color var(--dur-slower) var(--ease-out);
}

.nav-toggle:hover {
  border-color: var(--action-primary);
  color: var(--action-primary);
}

.nav-toggle__icon {
  width: var(--space-5);
  height: var(--space-5);
  color: currentColor;
}

.site-nav {
  display: none;
}

.site-nav.is-open {
  display: flex;
  position: fixed;
  inset: 0;
  z-index: var(--z-overlay);
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--space-8);
  padding: var(--space-20) var(--space-6) var(--space-12);
  background: var(--bg);
  overflow-y: auto;
}

.site-nav__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: 100%;
}

.site-nav__item { display: block; }

.nav-toggle__text { line-height: 1; }

.site-nav__link {
  display: block;
  padding: var(--space-3) 0;
  min-height: 44px;
  border-bottom: 1px solid var(--border-subtle);
  color: var(--text-primary);
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  font-size: var(--type-2xl);
  font-weight: var(--weight-regular);
  letter-spacing: 0.08em;
  text-decoration: none;
  transition: color var(--dur-slower) var(--ease-out),
              border-color var(--dur-slower) var(--ease-out);
}

.site-nav__link:hover,
.site-nav__link.is-current {
  color: var(--action-primary);
  border-bottom-color: var(--accent-graphic);
}

.site-nav__cta { align-self: stretch; }

@media (min-width: 1024px) {
  .site-header__inner {
    padding: var(--space-4) var(--space-20);
  }

  .nav-toggle { display: none; }

  .site-nav,
  .site-nav.is-open {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-8);
    position: static;
    inset: auto;
    padding: 0;
    overflow: visible;
    background: transparent;
  }

  .site-nav__list {
    flex-direction: row;
    gap: var(--space-6);
    width: auto;
  }

  .site-nav__link {
    display: inline-flex;
    align-items: center;
    padding: var(--space-2) 0;
    min-height: 44px;
    border-bottom: 1px solid transparent;
    font-family: var(--font-body);
    font-size: var(--type-xs);
    font-weight: var(--weight-medium);
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--text-secondary);
  }

  .site-nav__cta { align-self: auto; }
}

@media (min-width: 1536px) {
  .site-header__inner { padding: var(--space-4) var(--space-40); }
}


/* ==========================================================================
   HERO
   ========================================================================== */

.hero {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  min-height: 100svh;
  padding: var(--space-20) var(--space-5) var(--space-16);
  overflow: hidden;
  isolation: isolate;
}

.hero__art {
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 18% 24%, var(--surface-inset) 0%, var(--bg) 62%),
    var(--bg);
}

/* A square layer centred on the hero, feathered to a circle. Rotation leaves a
   circle unchanged, so the turning layer can never swing a hard corner edge
   into view; only the light inside it moves. 130vmax clears the half-diagonal
   of any landscape hero, and the feather hides the rim on tall ones. */
.hero__sheen {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 130vmax;
  height: 130vmax;
  margin: -65vmax 0 0 -65vmax;
  /* Only the mask's alpha is read; any opaque role would serve. */
  -webkit-mask-image: radial-gradient(circle closest-side, var(--bg) 62%, transparent 100%);
          mask-image: radial-gradient(circle closest-side, var(--bg) 62%, transparent 100%);
  background:
    conic-gradient(from 210deg at 58% 42%,
      var(--bg) 0deg,
      var(--surface-inset) 42deg,
      var(--accent-graphic) 96deg,
      var(--surface-raised) 148deg,
      var(--bg) 206deg,
      var(--surface-inset) 268deg,
      var(--accent-graphic) 322deg,
      var(--bg) 360deg);
  /* Capped so the composite under the hero copy never lightens past
     surface-inset by more than a hair: gold-500 at 0.06 over noir-800 is the
     pair verified in contrastChecks ("maison / muted on hero sheen"). */
  opacity: 0.06;
  /* Ambient loop, not an interaction — expressed as a multiple of the motion
     scale rather than a bare literal. 640ms x 120 = 76.8s a turn, under five
     degrees a second: felt rather than seen. main.js parks it (.is-still)
     while the hero is offscreen or the tab is hidden. */
  animation: mn-sheen calc(var(--dur-slowest) * 120) linear infinite;
  will-change: transform;
}

/* Lighter on phones and touch screens: the full-bleed turning layer is the
   costliest thing on the page, so there it holds still and stays unpromoted.
   The load fade and the one-off shimmer still play. */
@media (max-width: 767px), (hover: none) {
  .hero__sheen {
    animation: none;
    will-change: auto;
  }
}

.hero__grain {
  position: absolute;
  inset: 0;
  opacity: 0.16;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'%3E%3Cfilter id='mn-grain' x='0' y='0'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.86' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23mn-grain)'/%3E%3C/svg%3E");
  background-size: 160px 160px;
}

.silk {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.5;
}

.silk__lines path {
  fill: none;
  stroke: var(--accent-graphic);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
  opacity: 0.22;
}

.silk__lines path:nth-child(3n) { opacity: 0.4; }
.silk__lines path:nth-child(4n) { opacity: 0.12; }

/* Full-bleed signature: the hero, the section heads and the footer are
   contained by their own padding, not by a max-width, so heading blocks and
   the grids they introduce stop at the same right edge above 1520px. */
.hero__inner {
  position: relative;
  z-index: var(--z-raised);
  width: 100%;
}

.hero__eyebrow { margin-bottom: var(--space-6); }

.hero__title {
  position: relative;
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 48;
  font-size: clamp(var(--type-3xl), 12vw, var(--type-7xl));
  font-weight: var(--weight-regular);
  line-height: var(--leading-tight);
  letter-spacing: 0.06em;
  color: var(--text-primary);
  margin-bottom: var(--space-6);
  text-wrap: balance;
}

/* The wordmark ships pre-split into letters; the word box keeps each word
   from breaking between its letters. At rest the letters are plain inline
   text, so the font's kerning holds across them: an atomic inline box ends
   the shaping run, and at 96px a lost kern of 20-40 units is 2-4px, visible
   in display type. They become inline-blocks only while the load timeline
   needs a transform, and settle back when main.js releases .is-loading. */
.hero__word {
  display: inline-block;
  white-space: nowrap;
}

.hero__char { display: inline; }

@media (prefers-reduced-motion: no-preference) {
  .is-loading .hero__char { display: inline-block; }
}

/* Unlike the section rules, the hero rule is drawn at rest. The load
   choreography in main.js draws it in from the left; with no script, a failed
   script, or reduced motion it is simply there. */
.hero__rule {
  max-width: var(--space-40);
  margin-bottom: var(--space-6);
  transform: none;
}

.hero__lede {
  max-width: var(--container-narrow);
  font-size: var(--type-lg);
  font-weight: var(--weight-light);
  line-height: var(--leading-relaxed);
  color: var(--text-primary);
  margin-bottom: var(--space-4);
}

/* text-secondary, not text-muted: this copy sits on the sheen composite rather
   than on flat noir-950, and secondary keeps real headroom over the grain.
   It also matches .section__lede, which is secondary everywhere else. */
.hero__sub {
  max-width: var(--container-prose);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
  margin-bottom: var(--space-10);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-5);
  margin-bottom: var(--space-16);
}

.hero__tel {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--type-sm);
  letter-spacing: 0.1em;
}

.hero__facts {
  display: grid;
  gap: var(--space-4);
  border-top: 1px solid var(--border-subtle);
  padding-top: var(--space-5);
}

.hero__fact {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.hero__fact-k {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.hero__fact-v {
  font-size: var(--type-base);
  color: var(--text-secondary);
}

.hero__cue {
  position: absolute;
  left: var(--space-5);
  bottom: 0;
  z-index: var(--z-raised);
  width: 1px;
  height: var(--space-16);
  background: var(--accent-graphic);
  transform-origin: bottom center;
  /* Ambient loop: 480ms x 10 = 4.8s, derived from the motion scale. */
  animation: mn-cue calc(var(--dur-slower) * 10) var(--ease-in-out) infinite;
}

@media (min-width: 480px) {
  .hero { padding: var(--space-24) var(--space-6) var(--space-20); }
  .hero__cue { left: var(--space-6); }
}

@media (min-width: 768px) {
  .hero {
    padding: var(--space-24) var(--space-10) var(--space-20);
  }

  .hero__title { font-variation-settings: 'opsz' 96; }

  .hero__facts {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-8);
  }

  .hero__cue { left: var(--space-10); }
}

@media (min-width: 1024px) {
  .hero { padding: var(--space-32) var(--space-20) var(--space-24); }
  .hero__lede { font-size: var(--type-xl); }
  .hero__cue { left: var(--space-20); }
}

@media (min-width: 1536px) {
  .hero { padding: var(--space-32) var(--space-40) var(--space-24); }
  .hero__cue { left: var(--space-40); }
}


/* ==========================================================================
   SECTION SHELL — full bleed, contained by internal padding only
   ========================================================================== */

.section {
  position: relative;
  padding: var(--space-16) var(--space-5);
  border-top: 1px solid var(--border-subtle);
}

/* Sections alternate ground so the hairlines read as intentional breaks
   rather than as arbitrary dividers. */
.section--menu,
.section--team,
.section--booking { background: var(--surface); }

.section--treatments,
.section--membership,
.section--visit { background: var(--bg); }

.section__head {
  margin-bottom: var(--space-12);
}

.section__rule {
  max-width: var(--space-24);
  margin-bottom: var(--space-4);
}

.section__index {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  margin-bottom: var(--space-5);
}

.section__num {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 24;
  font-size: var(--type-xl);
  font-weight: var(--weight-regular);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.1em;
  color: var(--action-primary);
}

.section__title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 60;
  font-size: clamp(var(--type-2xl), 6vw, var(--type-5xl));
  font-weight: var(--weight-regular);
  line-height: var(--leading-snug);
  letter-spacing: 0.02em;
  color: var(--text-primary);
  max-width: var(--container-narrow);
  margin-bottom: var(--space-5);
  text-wrap: balance;
}

.section__lede {
  max-width: var(--container-prose);
  font-size: var(--type-md);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

@media (min-width: 480px) {
  .section { padding: var(--space-20) var(--space-6); }
}

@media (min-width: 768px) {
  .section { padding: var(--space-20) var(--space-10); }
  .section__head { margin-bottom: var(--space-16); }
}

@media (min-width: 1024px) {
  .section { padding: var(--space-24) var(--space-20); }
  .section__lede { font-size: var(--type-lg); }
}

@media (min-width: 1280px) {
  .section { padding: var(--space-24) var(--space-32); }
}

@media (min-width: 1536px) {
  .section { padding: var(--space-32) var(--space-40); }
}


/* ==========================================================================
   01 — SERVICE MENU
   ========================================================================== */

.menu__groups {
  display: grid;
  gap: var(--space-16);
}

.menu-group { display: block; }

.menu-group__title {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--accent-graphic);
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  font-size: var(--type-2xl);
  font-weight: var(--weight-regular);
  line-height: var(--leading-snug);
  letter-spacing: 0.1em;
  color: var(--text-primary);
  margin-bottom: var(--space-5);
}

.menu-group__numeral {
  font-size: var(--type-sm);
  font-family: var(--font-body);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  color: var(--action-primary);
}

.menu-group__note {
  max-width: 62ch;
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  margin-bottom: var(--space-10);
}

.menu-list {
  display: grid;
  gap: var(--space-8);
}

.menu-item__row {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.menu-item__name {
  font-size: var(--type-md);
  font-weight: var(--weight-regular);
  line-height: var(--leading-snug);
  letter-spacing: 0.02em;
  color: var(--text-primary);
  flex: 0 1 auto;
}

/* The leader carries meaning (it ties a name to its price), so it uses
   border-interactive at 3.42:1 rather than the 1.51:1 decorative hairline. */
.menu-item__leader {
  flex: 1 1 var(--space-6);
  min-width: var(--space-6);
  height: 1px;
  margin-bottom: 0.3em;
  background: var(--border-interactive);
  transition: background-color var(--dur-slower) var(--ease-out);
}

.menu-item:hover .menu-item__leader { background: var(--accent-graphic); }

.menu-item__price {
  flex: 0 0 auto;
  font-size: var(--type-md);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: 0.04em;
  color: var(--action-primary);
  white-space: nowrap;
}

.menu-item__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-width: 64ch;
}

.menu-item__dur {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.menu-item__desc {
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

.menu__footnote {
  max-width: var(--container-prose);
  margin-top: var(--space-16);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

@media (min-width: 768px) {
  .menu-item__meta {
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-5);
  }

  .menu-item__dur { flex: 0 0 var(--space-20); }
}

@media (min-width: 1024px) {
  .menu__groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--space-20);
    row-gap: var(--space-24);
  }

  .menu-item__name { font-size: var(--type-lg); }
  .menu-item__price { font-size: var(--type-lg); }
}

@media (min-width: 1280px) {
  .menu__groups { column-gap: var(--space-32); }
}


/* ==========================================================================
   02 — SIGNATURE TREATMENTS
   ========================================================================== */

.treatment {
  display: grid;
  gap: var(--space-10);
  padding-top: var(--space-16);
  border-top: 1px solid var(--border-subtle);
}

.treatment:first-of-type {
  padding-top: 0;
  border-top: 0;
}

.treatment + .treatment { margin-top: var(--space-16); }

.treatment__art {
  position: relative;
  background:
    radial-gradient(90% 70% at 50% 30%, var(--surface-raised) 0%, var(--bg) 72%),
    var(--bg);
  border: 1px solid var(--border-subtle);
  padding: var(--space-6);
  aspect-ratio: 5 / 6;
  overflow: hidden;
}

.treatment__art .art {
  width: 100%;
  height: 100%;
}

.treatment__title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 48;
  font-size: clamp(var(--type-xl), 5vw, var(--type-4xl));
  font-weight: var(--weight-regular);
  line-height: var(--leading-snug);
  letter-spacing: 0.03em;
  color: var(--text-primary);
  margin: var(--space-3) 0 var(--space-5);
}

.treatment__copy {
  max-width: 62ch;
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
  margin-bottom: var(--space-8);
}

.treatment__facts {
  display: grid;
  gap: var(--space-5);
  margin-bottom: var(--space-8);
}

.treatment__fact {
  display: grid;
  gap: var(--space-2);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

.treatment__fact-k {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--action-primary);
}

.treatment__fact-v {
  margin: 0;
  max-width: 58ch;
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

.treatment__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--type-sm);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

@media (min-width: 768px) {
  .treatment__facts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-6);
  }

  .treatment__fact:first-child { grid-column: 1 / -1; }
}

@media (min-width: 1024px) {
  .treatment {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    align-items: center;
    gap: var(--space-20);
    padding-top: var(--space-24);
  }

  .treatment + .treatment { margin-top: var(--space-24); }

  .treatment--reverse .treatment__art { order: 2; }
  .treatment--reverse .treatment__body { order: 1; }

  .treatment__art { aspect-ratio: 4 / 5; }
}


/* ==========================================================================
   03 — THE ATELIER
   ========================================================================== */

.team__grid {
  display: grid;
  gap: var(--space-16);
}

.member {
  display: flex;
  flex-direction: column;
}

.member__art {
  background:
    linear-gradient(180deg, var(--surface-raised) 0%, var(--bg) 88%),
    var(--bg);
  border: 1px solid var(--border-subtle);
  border-bottom: 1px solid var(--accent-graphic);
  padding: var(--space-6) var(--space-6) 0;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  margin-bottom: var(--space-5);
}

.member__art .art {
  width: 100%;
  height: 100%;
}

.member__name {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  font-size: var(--type-xl);
  font-weight: var(--weight-regular);
  line-height: var(--leading-snug);
  letter-spacing: 0.06em;
  color: var(--text-primary);
  margin-bottom: var(--space-2);
}

.member__role {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--action-primary);
  margin-bottom: var(--space-3);
}

.member__spec {
  font-size: var(--type-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-4);
}

.member__bio {
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
  margin-bottom: var(--space-5);
}

/* Bodoni Moda is loaded upright only, so the quote takes its emphasis from
   size and tracking rather than a synthesised oblique. */
.member__quote {
  margin: 0;
  padding-left: var(--space-5);
  border-left: 1px solid var(--accent-graphic);
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 20;
  font-size: var(--type-md);
  font-weight: var(--weight-regular);
  line-height: var(--leading-normal);
  letter-spacing: 0.03em;
  color: var(--text-primary);
}

@media (min-width: 768px) {
  .team__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-12) var(--space-10);
  }
}

@media (min-width: 1280px) {
  .team__grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-10);
  }
}


/* ==========================================================================
   04 — MEMBERSHIP  (three columns split by hairline gold rules, no cards)
   ========================================================================== */

.tiers {
  display: grid;
  gap: var(--space-12);
}

.tier {
  position: relative;
  padding-top: var(--space-8);
  border-top: 1px solid var(--accent-graphic);
}

/* The featured tier is marked, not boxed — the section signature forbids
   cards, so the distinction is the flag and a gold name. */
.tier--featured { padding-top: var(--space-12); }

.tier--featured .tier__name { color: var(--action-primary); }

.tier__flag {
  position: absolute;
  top: var(--space-2);
  right: 0;
  display: inline-block;
  padding: var(--space-1) var(--space-3);
  background: var(--action-primary);
  color: var(--on-action-primary);
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  line-height: var(--leading-normal);
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.tier__name {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 36;
  font-size: var(--type-3xl);
  font-weight: var(--weight-regular);
  line-height: var(--leading-snug);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-primary);
  margin-bottom: var(--space-4);
}

.tier__price {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-bottom: var(--space-4);
}

.tier__amount {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 48;
  font-size: var(--type-4xl);
  font-weight: var(--weight-regular);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: 0.02em;
  color: var(--action-primary);
}

.tier__period {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.tier__pitch {
  max-width: 42ch;
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-5);
}

.tier__list {
  display: grid;
  gap: var(--space-3);
  margin-bottom: var(--space-8);
}

.tier__item {
  position: relative;
  padding-left: var(--space-5);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-secondary);
}

.tier__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: var(--space-3);
  height: 1px;
  background: var(--accent-graphic);
}

.tier__cta { width: 100%; }

.tiers__footnote {
  max-width: var(--container-prose);
  margin-top: var(--space-12);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

@media (min-width: 1024px) {
  .tiers {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0;
  }

  .tier {
    padding: var(--space-8) var(--space-10) 0;
    border-left: 1px solid var(--accent-graphic);
    border-top: 0;
  }

  .tier--featured { padding-top: var(--space-8); }
  .tier__flag { top: var(--space-2); right: var(--space-10); }

  .tier:first-child { padding-left: 0; border-left: 0; }
  .tier:last-child { padding-right: 0; }

  .tier__cta { width: auto; }
}


/* ==========================================================================
   05 — BOOKING  (underline-only fields, per the no-radius no-shadow rule)
   ========================================================================== */

.booking {
  display: grid;
  gap: var(--space-16);
}

.booking__form {
  display: grid;
  gap: var(--space-10);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.field__input {
  width: 100%;
  min-height: 48px;
  padding: var(--space-2) 0;
  border: 0;
  border-bottom: 1px solid var(--border-interactive);
  border-radius: var(--radius-none);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-body);
  font-size: var(--type-base);
  font-weight: var(--weight-light);
  letter-spacing: 0.02em;
  transition: border-color var(--dur-slower) var(--ease-out);
}

.field__input::placeholder {
  color: var(--text-muted);
  opacity: 1;
}

.field__input:hover { border-bottom-color: var(--border-interactive-hover); }

.field__input:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
  border-bottom-color: var(--action-primary);
}

.field__input:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.field__input[readonly] { background: var(--surface-raised); }

/* MASTER section 6 Field: error is a danger border. The maison group has no
   red primitive and one must not be invented, so `danger` binds gold-600 —
   the one gold the palette carries that is not already the focus/action
   colour, so an errored field no longer reads identically to a focused one. */
.field__input.is-error { border-bottom-color: var(--danger); }

.field__input::-webkit-calendar-picker-indicator {
  filter: invert(1);
  opacity: 0.55;
  cursor: pointer;
}

.field__select-wrap {
  position: relative;
  display: block;
}

.field__select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--space-8);
  cursor: pointer;
}

.field__select-wrap::after {
  content: "";
  position: absolute;
  right: var(--space-1);
  bottom: var(--space-5);
  width: var(--space-3);
  height: var(--space-2);
  background: var(--action-primary);
  clip-path: polygon(0 0, 50% 100%, 100% 0, 84% 0, 50% 68%, 16% 0);
  pointer-events: none;
}

.field__textarea {
  min-height: var(--space-32);
  padding: var(--space-3) 0;
  resize: vertical;
  line-height: var(--leading-relaxed);
}

.field__hint {
  font-size: var(--type-xs);
  line-height: var(--leading-normal);
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.field__error {
  padding-left: var(--space-4);
  border-left: 2px solid var(--danger);
  font-size: var(--type-xs);
  line-height: var(--leading-normal);
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}

.booking__submit {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

.booking__note {
  font-size: var(--type-xs);
  letter-spacing: 0.1em;
  color: var(--text-muted);
}

.booking__status {
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--accent-graphic);
  font-size: var(--type-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-primary);
  background: var(--surface-raised);
}

.booking__status.is-error {
  border-color: var(--border-interactive);
  color: var(--text-secondary);
}

.booking__aside {
  padding-top: var(--space-8);
  border-top: 1px solid var(--accent-graphic);
}

.booking__aside-title {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  font-size: var(--type-xl);
  font-weight: var(--weight-regular);
  letter-spacing: 0.08em;
  color: var(--text-primary);
  margin-bottom: var(--space-6);
}

.booking__aside-list {
  display: grid;
  gap: var(--space-6);
}

.booking__aside-row {
  display: grid;
  gap: var(--space-2);
  padding-bottom: var(--space-5);
  border-bottom: 1px solid var(--border-subtle);
}

.booking__aside-k {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--action-primary);
}

.booking__aside-v {
  margin: 0;
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

@media (min-width: 768px) {
  .booking__form {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-10) var(--space-10);
  }

  .field--wide,
  .booking__submit,
  .booking__status { grid-column: 1 / -1; }

  .booking__submit {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

@media (min-width: 1024px) {
  .booking {
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: var(--space-20);
    align-items: start;
  }

  .booking__aside { padding-top: var(--space-6); }
}


/* ==========================================================================
   06 — HOURS AND LOCATION
   ========================================================================== */

.visit {
  display: grid;
  gap: var(--space-12);
}

.visit__col {
  display: flex;
  flex-direction: column;
}

.visit__sub {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 24;
  font-size: var(--type-lg);
  font-weight: var(--weight-regular);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-primary);
  padding-bottom: var(--space-4);
  border-bottom: 1px solid var(--accent-graphic);
  margin-bottom: var(--space-6);
}

.hours {
  display: grid;
  gap: var(--space-3);
  margin-bottom: var(--space-6);
}

.hours__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
}

.hours__day {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.hours__time {
  margin: 0;
  font-size: var(--type-base);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: 0.06em;
  color: var(--text-primary);
}

.visit__note {
  max-width: 56ch;
  font-size: var(--type-base);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

.visit__address {
  font-style: normal;
  font-size: var(--type-md);
  line-height: var(--leading-relaxed);
  letter-spacing: 0.04em;
  color: var(--text-primary);
  margin-bottom: var(--space-6);
}

.visit__contacts {
  display: grid;
  gap: var(--space-4);
  margin-bottom: var(--space-6);
}

.visit__contact {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

/* The 44px belongs on the anchor, not on the wrapper — a 44px li centring a
   23px inline link is a 23px tap target. */
.visit__contact a {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  min-height: 44px;
}

.visit__contact-k {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.visit__map {
  border: 1px solid var(--border-subtle);
  background:
    linear-gradient(160deg, var(--surface-raised) 0%, var(--bg) 76%),
    var(--bg);
  padding: var(--space-4);
  overflow: hidden;
}

@media (min-width: 768px) {
  .visit {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-16) var(--space-12);
  }

  .visit__map { grid-column: 1 / -1; }
}

@media (min-width: 1024px) {
  .visit {
    grid-template-columns: minmax(0, 3fr) minmax(0, 3fr) minmax(0, 6fr);
    gap: var(--space-16);
  }

  .visit__map { grid-column: auto; }
}


/* ==========================================================================
   INLINE SVG ART — all strokes and fills bind to semantic roles
   ========================================================================== */

.art {
  display: block;
  width: 100%;
  height: auto;
}

.art__stroke {
  fill: none;
  stroke: var(--accent-graphic);
  stroke-width: 1;
  stroke-linecap: square;
  vector-effect: non-scaling-stroke;
  opacity: 0.34;
}

.art__stroke--bright { opacity: 0.85; }
.art__stroke--heavy { stroke-width: 2; }

.art__fill {
  fill: var(--action-primary);
  stroke: none;
}

/* Sized in user units against the 720-wide map viewBox so the labels stay
   legible once the SVG is scaled down to a column. */
.art__label {
  fill: var(--text-muted);
  stroke: none;
  font-family: var(--font-body);
  font-size: var(--type-lg);
  font-weight: var(--weight-medium);
  letter-spacing: 0.12em;
}

.art__label--bright { fill: var(--action-primary); }

.brand__mark .art__stroke,
.nav-toggle__icon .art__stroke {
  stroke: currentColor;
  opacity: 1;
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.art--fan .art__rays .art__stroke { opacity: 0.2; }
.art--fan .art__arcs .art__stroke { stroke-linecap: round; }
.art--cell .art__spokes .art__stroke { opacity: 0.22; }
.art--cell .art__nodes .art__fill { opacity: 0.8; }
.art--contour .art__contours .art__stroke { opacity: 0.3; }
.art--contour .art__ticks .art__stroke { opacity: 0.6; }
.art__marks .art__stroke { stroke-linecap: butt; }
.art--portrait { margin-inline: auto; }

.art--map { aspect-ratio: 12 / 7; }
.art--map .art__streets .art__stroke { opacity: 0.26; }
.art--map .art__streets .art__stroke--bright { opacity: 0.7; }


/* ==========================================================================
   FOOTER
   ========================================================================== */

.site-footer {
  background: var(--bg);
  border-top: 1px solid var(--accent-graphic);
  padding: var(--space-16) var(--space-5) var(--space-10);
}

.site-footer__inner {
  display: grid;
  gap: var(--space-12);
  margin-bottom: var(--space-12);
}

.site-footer__brand .brand__mark {
  width: var(--space-8);
  height: var(--space-8);
  color: var(--action-primary);
  margin-bottom: var(--space-4);
}

.site-footer__word {
  font-family: var(--font-display);
  font-variation-settings: 'opsz' 30;
  font-size: var(--type-xl);
  font-weight: var(--weight-regular);
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--text-primary);
  margin-bottom: var(--space-3);
}

.site-footer__tagline {
  max-width: 36ch;
  font-size: var(--type-sm);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

.site-footer__nav,
.site-footer__contact { display: block; }

.site-footer__heading {
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--action-primary);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--border-subtle);
  margin-bottom: var(--space-4);
}

.site-footer__list {
  display: grid;
  gap: var(--space-2);
  font-size: var(--type-sm);
}

.site-footer__list li {
  min-height: 44px;
  display: flex;
  align-items: center;
}

/* Height on the anchor, so the hit area is the link rather than the li that
   merely centres it. The li keeps its own 44px for the plain address rows. */
.site-footer__list a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.site-footer__plain { color: var(--text-muted); }

.site-footer__legal {
  max-width: var(--container-narrow);
  padding-top: var(--space-6);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--type-xs);
  line-height: var(--leading-relaxed);
  color: var(--text-muted);
}

@media (min-width: 768px) {
  .site-footer { padding: var(--space-20) var(--space-10) var(--space-10); }

  .site-footer__inner {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--space-16);
  }
}

@media (min-width: 1024px) {
  .site-footer { padding: var(--space-24) var(--space-20) var(--space-12); }
}

@media (min-width: 1536px) {
  .site-footer { padding: var(--space-24) var(--space-40) var(--space-12); }
}


/* ==========================================================================
   CREDIT STRIP — BRIEF section 6. Identical markup across all four demos.
   ========================================================================== */

.credit {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-5);
  background: var(--surface);
  border-top: 1px solid var(--border-subtle);
}

.credit__text {
  font-size: var(--type-xs);
  letter-spacing: 0.12em;
  color: var(--text-muted);
}

.credit__text strong {
  font-weight: var(--weight-medium);
  color: var(--text-secondary);
}

.credit__link {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--type-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.12em;
  color: var(--action-primary);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: color var(--dur-slower) var(--ease-out);
}

.credit__link:hover { color: var(--action-primary-hover); }

@media (min-width: 768px) {
  .credit { padding: var(--space-5) var(--space-10); }
}

@media (min-width: 1024px) {
  .credit { padding: var(--space-5) var(--space-20); }
}

@media (min-width: 1536px) {
  .credit { padding: var(--space-5) var(--space-40); }
}


/* ==========================================================================
   BODY-ROLE TYPE STEP-DOWN
   MASTER section 4: "Body is 16px minimum on mobile." Everything below plays
   the `body` role — running prose the visitor reads to understand the offer —
   so it ships at type-base and only steps down to type-sm once the viewport
   can carry the density. The 12px eyebrow, duration, and label roles are
   `caption`/`eyebrow`, not `body`; they stay at 12px because that extreme
   scale contrast against the 96px Bodoni is the property's signature.
   ========================================================================== */

@media (min-width: 768px) {
  .menu-group__note,
  .menu-item__desc,
  .menu__footnote,
  .treatment__fact-v,
  .member__bio,
  .tier__pitch,
  .tier__item,
  .tiers__footnote,
  .booking__aside-v,
  .visit__note { font-size: var(--type-sm); }
}


/* ==========================================================================
   MOTION — 480ms interactions, 640ms reveals, 80ms stagger
   ========================================================================== */

.reveal {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-slowest) var(--ease-out),
              transform var(--dur-slowest) var(--ease-out);
}

.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.menu__groups > .reveal:nth-child(2),
.team__grid > .reveal:nth-child(2),
.tiers > .reveal:nth-child(2) { transition-delay: 80ms; }

.menu__groups > .reveal:nth-child(3),
.team__grid > .reveal:nth-child(3),
.tiers > .reveal:nth-child(3) { transition-delay: 160ms; }

.menu__groups > .reveal:nth-child(4),
.team__grid > .reveal:nth-child(4) { transition-delay: 240ms; }

.booking > .reveal:nth-child(2) { transition-delay: 80ms; }
.visit > .reveal:nth-child(2) { transition-delay: 80ms; }
.visit > .reveal:nth-child(3) { transition-delay: 160ms; }

@keyframes mn-sheen {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes mn-cue {
  0%, 100% { transform: scaleY(0.25); opacity: 0.35; }
  50%      { transform: scaleY(1); opacity: 1; }
}

/* Ambient loops hold still while the hero is offscreen or the tab is hidden.
   main.js toggles the class; with no script they simply run. */
.hero.is-still .hero__sheen,
.hero.is-still .hero__cue { animation-play-state: paused; }


/* ==========================================================================
   LOAD CHOREOGRAPHY — the cinematic open, timed in main.js
   An inline script in <head> puts .is-loading on the document element before
   the stylesheet arrives. Only elements marked [data-load] are hidden, and
   only while that class is present. If main.js never runs, the failsafe
   releases every one of them at 2.5s on its own.
   ========================================================================== */

.is-loading [data-load] { opacity: 0; }

.is-loading [data-load] { animation: load-failsafe 0s 2.5s forwards; }

@keyframes load-failsafe { to { opacity: 1; } }

/* The rule above would freeze the cue at full strength if main.js never runs,
   so the cue's failsafe is its own pulse, started at 2.5s. No backwards fill:
   it stays hidden through the wait like every other [data-load] element. The
   name differs from mn-cue on purpose, so the normal release still starts
   mn-cue on its first frame, which is where the load timeline leaves the cue. */
.is-loading .hero__cue { animation: mn-cue-late calc(var(--dur-slower) * 10) var(--ease-in-out) 2.5s infinite; }

@keyframes mn-cue-late {
  0%, 100% { transform: scaleY(0.25); opacity: 0.35; }
  50%      { transform: scaleY(1); opacity: 1; }
}


/* ==========================================================================
   WORDMARK SHIMMER — one pass, after the load, never repeated
   main.js lays a copy of the wordmark over the original in champagne gold,
   masked to a soft slanted band. The band slides across while the copy
   inside it slides back by the same distance, so the glyphs hold perfectly
   still under a moving window of light. Transform only; removed when done.
   ========================================================================== */

.hero__shine {
  position: absolute;
  inset: 0;
  color: var(--action-primary-hover);
  pointer-events: none;
  /* Alpha-only mask, so the opaque stop can be any role. */
  -webkit-mask-image: linear-gradient(100deg, transparent 0, var(--bg) 1.5em, transparent 3em);
          mask-image: linear-gradient(100deg, transparent 0, var(--bg) 1.5em, transparent 3em);
}

/* Block, at the heading's full width: the copy breaks and balances its lines
   exactly as the original does, so every glyph lands on its twin. */
.hero__shine .hero__wordmark { display: block; }


/* ==========================================================================
   VIEW TRANSITIONS — same-origin navigations crossfade natively.
   Browsers without support navigate as they always have.
   ========================================================================== */

@view-transition { navigation: auto; }


/* ==========================================================================
   REDUCED MOTION — transforms and animations off
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    transition-delay: 0ms !important;
    transform: none !important;
    scroll-behavior: auto !important;
  }

  @view-transition { navigation: none; }

  /* No load timeline, no ambient loops, no shimmer. main.js also releases
     .is-loading at once; this holds even before it runs. */
  .is-loading [data-load] { opacity: 1 !important; }

  .hero__sheen,
  .hero__cue { animation: none !important; }

  .hero__shine { display: none; }

  .reveal { opacity: 1 !important; }
  .hero__cue { opacity: 0.6 !important; }
  .skip-link { top: calc(var(--space-24) * -1); }
  .skip-link:focus-visible { top: var(--space-2); }
}
