/* ═══════════════════════════════════════════
   DESIGN TOKENS
   ═══════════════════════════════════════════ */
:root {
  /* Palette — Core */
  --cream: #F9F8F2;        /* §3 canonical */
  --sage-green: #8A9A90;   /* §3 canonical. Decorative/large/on-dark ONLY —
                              reads 2.78 against cream in BOTH directions,
                              so it can neither carry text on cream nor sit
                              behind cream text. Use --sage-deep for those. */
  --charcoal: #2C2C2C;     /* §3 canonical. NEVER pure black. */
  --dark-rust: #5C4033;
  --stone: #E6E4DD;

  /* ── Functional derivatives ──────────────────────────────────────────
     Added 2026-08-02. A single colour token cannot serve both a light and a
     dark background — correcting it for one direction breaks the other.
     Sage is the clearest case: #8A9A90 reads 2.78 on cream but 4.8 on
     charcoal, so text that must be read against cream needs its own value. */
  --sage-deep: #5A6457;    /* sage TEXT on cream (5.65), or a sage PANEL
                              behind cream text (5.81). */
  --sage-lifted: #A9BAB0;  /* sage TEXT on the nav dropdown's lifted panel.
                              Plain --sage-green lands at 4.51 there — a
                              hairline AA pass that the next background
                              tweak would break. This reads 6.55. */

  /* Palette — Extended (previously hardcoded) */
  --sage-muted: #7B8A7E;
  --warm-gold: #C4873B;
  --cta-green: #5E7A66;
  --cta-green-dark: #4D6B55;
  --stone-muted: #9B9590;
  --charcoal-deep: #1A1A1A;
  --charcoal-muted: #4A4540;
  --terracotta: #9A5A46;
  --terracotta-dark: #844A38;

  /* Palette — Protocol-Specific */
  --rose-muted: #C4A698;
  --sun-gold: #F4D03F;

  /* Glassmorphism — Legacy */
  --glass: rgba(44, 44, 44, 0.10);
  --glass-border-legacy: rgba(255, 255, 255, 0.08);

  /* O-P-E-N / ROSEWOOD Glassmorphism — Somatic Architecture */
  --glass-bg: rgba(249, 248, 242, 0.4);
  --glass-border-color: rgba(44, 44, 44, 0.1);
  --glass-border: 1px solid var(--glass-border-color);
  --glass-blur: blur(24px);

  /* ── Glass scale ─────────────────────────────────────────────────────────
     Added 2026-08-02. Nine distinct blur radii were live (6/8/10/12/16/18/20/
     24/28px) with no rule for choosing between them — --glass-blur existed but
     exactly one file used it. Three steps, chosen by how much the element has
     to separate from what is behind it:
       sm  small controls sitting ON media (play buttons, chips)
       md  panels and cards in the flow, and the nav pill
       lg  full-surface overlays that must fully detach (drawers, modals, menus)
     Radius follows the same idea: --glass-radius for panels, pill/circle
     shapes keep their own. Never 0 — sharp corners are against §3. */
  --glass-blur-sm: blur(8px);
  --glass-blur-md: blur(16px);
  --glass-blur-lg: blur(24px);
  --glass-radius: 16px;

  /* ── Micro-copy floor ────────────────────────────────────────────────
     Added 2026-08-02. Eyebrows and labels were rendering 8.8-11.7px on a
     390px phone — uppercase, letter-spaced, and unreadable, on the device
     ~80% of visitors use. menu-of-care.css already documented a 12px floor
     and nothing else honoured it. 0.75rem = 12px is the hard minimum for
     any text a visitor is meant to read. */
  --fs-micro: 0.75rem;

  /* Typography Families */
  --font-serif: 'Editorial New', 'Playfair Display', serif;
  --font-sans: 'Geist', 'Lato', sans-serif;
  --font-indic: 'Anek Devanagari', 'Noto Sans Devanagari', sans-serif;

  /* Fluid Typography */
  --fs-display: clamp(1.67rem, 4vw + 0.67rem, 4rem);
  --fs-h2: clamp(1.75rem, 3vw + 0.5rem, 3.5rem);
  --fs-h3: clamp(1.15rem, 1.5vw + 0.5rem, 1.5rem);
  --fs-body: clamp(0.95rem, 0.8vw + 0.4rem, 1.125rem);
  --fs-small: clamp(0.8rem, 0.6vw + 0.3rem, 0.9rem);
  --fs-tag: clamp(var(--fs-micro), 0.5vw + 0.25rem, 0.8rem);   /* min was 0.7rem = 11.2px */

  /* THE ROW Typography Tokens */
  --text-h1: clamp(2.5rem, 5vw, 4.5rem);
  --text-body: clamp(1rem, 1.2vw, 1.125rem);
  --leading-body: 1.6;
  --tracking-eyebrow: 0.15em;

  /* Palette — Muted Text */
  --warm-taupe: #5A5248;   /* §3 leaves this open ("medium warm grey").
                              Was #9B9A96 here and #5A5248 in offerings.css —
                              one name, two very different values. #9B9A96 had
                              zero live uses and fails on cream (2.5); all four
                              real uses were offerings' value, so that wins. */

  /* AMAN Spatial Tokens — Massive vertical breathing room */
  /* ── Two vertical spacing systems. They are NOT interchangeable, and until
     2026-08-02 they were named --pad-section and --section-pad, which is a
     word-order collision waiting to be mis-typed.

     --pad-section  the SKILL_02 §1 "Aman void": viewport-HEIGHT driven, for
                    the big editorial gaps between major sections. Used by
                    offerings.css / faq.css.

                    svh, NOT dvh. dvh is the *dynamic* viewport height — it
                    tracks the browser's address bar, which slides away as you
                    scroll down and returns as you scroll up. Using it for
                    in-flow sizing meant the whole page physically resized
                    mid-scroll: measured on nsr-protocol, an 82px viewport
                    change moved the page 238px shorter and slid a section
                    106px up under the reader's finger. That was the "jumps
                    when I stop scrolling" reported from both an S24 Ultra and
                    an iPhone 17 Pro — and it happened only on the FIRST scroll
                    in each direction, which is exactly when the address bar
                    animates. svh is the viewport height WITH the address bar
                    showing, and never changes.

                    Still not vh: the project rule is "never vh", and svh is
                    the modern unit that rule was reaching for.
     --rhythm-unit  viewport-WIDTH driven. The base unit that sections take
                    multiples of (0.5x / 0.75x / 1x / 1.25x). Use this when
                    you want sections to relate to each other proportionally. */
  --pad-section: clamp(10svh, 15vw, 15svh);
  --pad-element: clamp(2rem, 4vw, 4rem);

  /* Spacing — Legacy (used by homepage, protocol pages) */
  /* The single vertical unit. Sections express their padding as a MULTIPLE of
     this (0.5x / 0.75x / 1x / 1.25x) so the rhythm is a ratio system rather
     than four unrelated clamps.
     Was clamp(4rem, 8vw, 8rem): the 4rem floor held until the viewport hit
     800px, so 360px and 768px got identical 64px padding — 18% of a phone's
     width but 8% of a tablet's. The 2rem + 5.5vw middle term removes that
     plateau while keeping the phone value (floor) and the 1920 value (ceiling)
     where they already were, so mobile page length is unaffected. */
  --rhythm-unit: clamp(4rem, 2rem + 5.5vw, 8rem);
  --gutter: clamp(1rem, 2vw, 2rem);

  /* ── Container ───────────────────────────────────────────────────────
     Added 2026-08-02. Content blocks were pinned to 1200 / 1100 / 1060 /
     1000px, so the footer sat 50px further in than every section above it —
     the kind of near-miss that reads as sloppy without being nameable.
     One value for full-width content; narrow measures stay explicit. */
  --container: 1200px;

  /* ── Measure ─────────────────────────────────────────────────────────
     Added 2026-08-03. Body copy ran 78-114ch at 717px and the sitewide
     footer disclaimer reached 309ch at 1920 — unconstrained full-width
     text at 12px. 68ch is the upper end of comfortable for this body face. */
  --measure: 68ch;

  /* THE ROW Shape Tokens */
  --radius-soft: 16px;
  --radius-arch: 50vw 50vw 0 0;

  /* Timing & Easing (Framer-like Physics) */
  --ease-smooth: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
  --ease-framer: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-cinematic: cubic-bezier(0.8, 0, 0.1, 1);

  /* Somatic Transition — slow, fluid, no snaps */
  --transition-somatic: all 0.8s cubic-bezier(0.2, 0.8, 0.2, 1);
}

/* Scroll offsets — clear fixed nav pill on anchor scroll */
@media (max-width: 1023px) {
  section[id] {
    scroll-margin-top: 80px;
  }
}

/* ═══════════════════════════════════════════
   RESET
   ═══════════════════════════════════════════ */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* Left as `auto` deliberately. scroll.js passes behavior:'smooth' per call
     for anchors, which keeps programmatic jump-to-top (on load, and when a
     scroll lock releases) instant. Setting it globally would animate those
     too, and the page would appear to lose its place. */
  scroll-behavior: auto;
  overscroll-behavior: none;
  overflow-x: clip;
  scrollbar-gutter: stable;
}

/* The scroll lock. Owned by scroll.js — see the long note there for why this
   is on <html> and not on <body>.

   It must be <html>: body->viewport overflow propagation only happens when
   <html> computes to `visible` in both axes, and the rule above sets
   overflow-x: clip. That is why the `body { overflow: hidden }` rules in
   menu-of-care.css and style.css never actually locked anything.

   `hidden` rather than `clip` on purpose — hidden keeps <html> a scroll
   container, so scrollTop is preserved and scrollbar-gutter still reserves its
   space. Nothing moves when this turns on or off. */
html.is-scroll-locked {
  overflow-y: hidden;
}

section {
  scroll-margin-top: 100px;
}

/* The html.lenis / .lenis-smooth / [data-lenis-prevent] rules that lived here
   were removed 2026-08-05 with Lenis itself — the classes they targeted were
   applied by that library and are never set now. Scrolling is native; the
   `data-lenis-prevent` attributes still present on the modal overlays are
   inert leftovers and harmless, but they no longer do anything.

   `overscroll-behavior: contain` is what those attributes used to buy. It now
   belongs on the scroll containers themselves so a modal's inner scroll can't
   chain out to the page behind it. */
.moc-modal-scroll,
.lp-drawer__body {
  overscroll-behavior: contain;
}

body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-body);
  line-height: 1.6;
  color: var(--charcoal);
  background: var(--cream);
  /* overflow-x: clip moved to html — keeping body clean preserves sticky */

  /* Makes <body> a PERMANENT stacking context.

     scroll.js locks the scroll with `position: fixed` on <body>, and
     position:fixed always creates a stacking context — so every modal open
     created one on the element that parents the whole page, and every close
     destroyed it, forcing the compositor to rebuild the layer tree at exactly
     the moment the modal was being torn down. Chrome does that commit
     synchronously; WebKit does not, which is why the one-frame flash was
     iOS-only. The same churn re-rooted the body::before grain blend group
     (a mix-blend-mode element blends within its nearest ancestor stacking
     context) twice per modal.

     With this, the context already exists — lock and unlock stop creating and
     destroying one, so there is no rebuild to catch mid-flight.

     `isolation` is not on the list of properties that establish a containing
     block for fixed-position descendants, so nothing moves. Verified: the
     benediction still hides mid-page and still reveals at the bottom. */
  isolation: isolate;
}



/* Organic paper texture — visible warmth across all blank areas */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: url('PageWiseAssets/Texture.webp') repeat;
  background-size: 600px;
  opacity: 0.02;
  mix-blend-mode: multiply;
}


/* ═════════════════════════════════════════════
   CURTAIN PRELOADER
   ═════════════════════════════════════════════ */
.curtain {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: url('PageWiseAssets/Texture.webp') repeat center;
  background-size: 600px;
  background-color: var(--cream);
  transition: transform 1s cubic-bezier(0.77, 0, 0.175, 1);
}

.curtain.is-raised {
  transform: translateY(-100%);
}

.curtain__logo-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  animation: curtainPulse 2s ease-in-out infinite;
}

.curtain__logo {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  object-fit: cover;
}

@keyframes curtainPulse {

  0%,
  100% {
    transform: scale(1);
    opacity: 0.8;
  }

  50% {
    transform: scale(1.06);
    opacity: 1;
  }
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-serif);
  font-weight: 500;
  line-height: 1.15;
  color: var(--dark-rust);
}

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

ul {
  list-style: none;
}

img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

button {
  border: none;
  background: none;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

/* ═══════════════════════════════════════════
   UTILITIES
   ═══════════════════════════════════════════ */
.tag {
  display: inline-block;
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-tag);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage-green);
}


/* ═══════════════════════════════════════════
   SECTION 1 — NAVIGATION (Floating Logo + Glass Pill)
   ═══════════════════════════════════════════ */

/* --- Standalone Logo (far left, scrolls with page) --- */
.nav-logo {
  position: absolute;
  top: 1.25rem;
  left: max(1.5rem, calc((100vw - 1200px) / 2));
  z-index: 999;
  text-decoration: none;
  display: flex;
  align-items: center;
}

/* ── Mobile: Logo far-left, compact burger far-right ── */
@media (max-width: 1023px) {
  .nav-logo {
    position: fixed;
    top: 0;
    left: 0;
    padding: 16px 20px;
  }

  /* No scrim behind the fixed logo. A cream radial fade was tried here to keep
     the logo from colliding with section headings during scroll; it read as a
     smudge on the page and was removed at the founder's request (2026-08-02).
     If the overlap becomes a problem again, solve it on the logo itself — a
     subtle shadow or a solid backing shape — not with a gradient wash over the
     underlying content. */

  .nav-logo__img {
    height: 48px;
  }

  /* ─── Burger: mirror of the logo ─────────────────────────────────────────
     Three separate faults stacked up here, all verified on an iPhone.

     1. Everything below except left/right/margin was DEFEATED by the base
        .nav-pill rule further down this file — same specificity, declared
        later, so it won. `top` resolved to the desktop 2.4rem (38.4px)
        instead of 1rem, which is why the burger sat 18px lower than the
        logo. These now carry !important rather than relying on order,
        because reordering the file would switch on six other dormant mobile
        rules that have never rendered.
     2. The desktop `transform: translate3d(-50%, 0, 0)` centring survived
        into mobile, dragging the pill 34px (half its width) left of where
        `right: 20px` put it. Hence "way off".
     3. The pill measured 68x64 against a 72px logo — nearly the same visual
        weight as the brand mark, competing with it.

     Now: a 36px disc, mirrored on the logo's 20px inset and centred on the
     same 52px line. The button inside stays 44x44 and overflows the disc, so
     the touch target is untouched while the visible mark halves. */
  .nav-pill {
    top: 34px !important;          /* 52px logo centre − 18px half-height */
    left: auto !important;
    right: 20px !important;
    margin: 0 !important;
    padding: 0 !important;
    gap: 0 !important;
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    transform: none !important;
    /* The whole shorthand, with !important. `animation-name` alone lost to the
       base rule's `animation:` shorthand declared later in this file — so the
       DESKTOP keyframes kept running on mobile, and those interpolate
       translate3d(-50%, …). On a 36px pill that is an 18px leftward jump on
       every load, which is the hop reported from an iPhone: it corrected only
       once something else forced a repaint.

       The mobile keyframes move on opacity and Y only, so the pill can never
       drift horizontally regardless of what else touches transform. */
    animation: navEntranceMobile 1s var(--ease-smooth) 0.6s forwards !important;
  }

  .nav-pill__burger {
    /* Hit area stays 44x44 (WCAG 2.5.8) by overflowing the 36px disc.
       flex-shrink:0 matters — as a flex child of the 36px pill it was being
       squeezed back to 42px wide, quietly undoing the point of the override. */
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    margin: -5px;
    gap: 4px;
  }

  .nav-pill__burger span {
    width: 14px;
  }

  .nav-pill__burger.is-open span:first-child {
    transform: translate3d(0, 2.75px, 0) rotate(45deg);
  }

  .nav-pill__burger.is-open span:last-child {
    transform: translate3d(0, -2.75px, 0) rotate(-45deg);
  }
}

/* The desktop entrance animates translate3d(-50%, …); on mobile the pill is
   not centre-anchored, so it needs its own keyframes or the animation would
   reintroduce the horizontal offset the rule above just removed. */
@keyframes navEntranceMobile {
  from {
    opacity: 0;
    transform: translate3d(0, -16px, 0);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.nav-logo:hover {
  opacity: 0.8;
}

.nav-logo__img {
  height: clamp(72px, 7.2vw, 94px);
  width: auto;
  border-radius: 50%;
  object-fit: contain;
}

/* --- Glass Pill Capsule (centered, fixed) --- */
.nav-pill {
  position: fixed;
  top: 2.4rem;   /* Resting: optically centered with logo */
  left: 50%;
  transform: translate3d(-50%, 0, 0);
  z-index: 999;

  display: flex;
  align-items: center;
  gap: 0.6rem;
  /* Top padding reduced, bottom padding increased to optically center text */
  padding: 0.45rem 0.7rem 0.65rem;

  background: var(--glass);
  backdrop-filter: var(--glass-blur-md);
  -webkit-backdrop-filter: var(--glass-blur-md);
  border: 1px solid var(--glass-border-color);
  border-radius: 999px;
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.03);

  transition: box-shadow 0.4s var(--ease-smooth);

  /* Entrance: slide down + fade */
  opacity: 0;
  animation: navEntrance 1s var(--ease-smooth) 0.6s forwards;
}

@keyframes navEntrance {
  from {
    opacity: 0;
    transform: translate3d(-50%, -16px, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(-50%, 0, 0);
  }
}

.nav-pill:hover {
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.06);
}

/* Links inside pill — hidden on mobile */
.nav-pill__links {
  display: none;
}

/* Divider — hidden on mobile */
.nav-pill__divider {
  display: none;
}

/* CTA — hidden on mobile */
.nav-pill__cta-wrap {
  display: none;
}

/* Burger — visible on mobile */
.nav-pill__burger {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  padding: 0;
  z-index: 1001;
}

.nav-pill__burger span {
  display: block;
  width: 20px;
  height: 1.5px;
  background: var(--charcoal);
  border-radius: 2px;
  transition: transform 0.4s var(--ease-smooth), opacity 0.3s var(--ease-smooth);
}

.nav-pill__burger.is-open span:first-child {
  transform: translate3d(0, 3.25px, 0) rotate(45deg);
}

.nav-pill__burger.is-open span:last-child {
  transform: translate3d(0, -3.25px, 0) rotate(-45deg);
}

/* When mobile menu is open: make close button highly visible */
.nav-pill__burger.is-open span {
  background: var(--cream) !important;
  width: 22px;
  height: 2px;
}

/* Nav pill stands out from dark overlay when menu is open */
.nav-pill.menu-active,
.nav-pill:has(.nav-pill__burger.is-open) {
  background: rgba(255, 255, 255, 0.12) !important;
  border-color: rgba(255, 255, 255, 0.18) !important;
  backdrop-filter: var(--glass-blur-lg) !important;
  -webkit-backdrop-filter: var(--glass-blur-lg) !important;
}

/* Lock body scroll when mobile menu is open (CSS-driven, no JS reflow) */
body.menu-open {
  overflow: hidden;
}

/* --- Mobile Full-Screen Menu --- */
.nav-mobile {
  position: fixed;
  inset: 0;
  z-index: 998;
  background: rgba(42, 42, 42, 0.96);
  backdrop-filter: var(--glass-blur-md);
  -webkit-backdrop-filter: var(--glass-blur-md);

  display: flex;
  flex-direction: column;
  align-items: center;
  /* flex-start + top padding, not center: the offerings block below can
     grow taller than a short viewport (landscape phones, iPhone SE), and
     centered content with overflow risks clipping the top out of reach.
     overflow-y keeps everything scrollable either way. */
  justify-content: flex-start;
  overflow-y: auto;
  gap: 2.5rem;
  padding: 6.5rem 1.5rem 3rem;

  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s var(--ease-smooth), visibility 0.5s;
}

.nav-mobile.is-open {
  opacity: 1;
  visibility: visible;
}

.nav-mobile ul {
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 2.2rem;
  padding: 0;
  margin: 0;
}

.nav-mobile a {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.6rem, 5vw, 2.4rem);
  font-weight: 400;
  color: var(--cream);
  opacity: 0.7;
  transition: opacity 0.4s var(--ease-smooth), color 0.4s var(--ease-smooth);
}

.nav-mobile a:hover {
  opacity: 1;
}

/* Offering name/description — shared by the desktop dropdown panel and the
   mobile menu's offerings section so both breakpoints render the identical
   typography instead of keeping two versions in sync by hand. */
.nav-pill__dropdown-name {
  font-family: 'Playfair Display', serif;
  font-size: 1rem;
  font-weight: 500;
  color: var(--cream);
  letter-spacing: 0.01em;
}

.nav-pill__dropdown-desc {
  font-family: 'Lato', sans-serif;
  font-size: 0.82rem;
  font-weight: 400;
  /* Was 0.4, which read 3.35:1 — under the 4.5:1 AA floor for body text.
     Raised again with the lighter panel so it stays clear of the floor. */
  color: rgba(249, 248, 242, 0.82);
  letter-spacing: 0.02em;
  line-height: 1.45;
}

/* Mobile menu's offerings block: same content as the desktop dropdown
   (section label, protocols, Library row, "view all"), laid out for a
   full-screen overlay instead of an anchored panel. */
.nav-mobile__action {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  width: 100%;
  max-width: 360px;
}

.nav-mobile__section-label {
  font-family: 'Lato', sans-serif;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(249, 248, 242, 0.72);
  margin: 0;
}

.nav-mobile__protocols {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 100%;
  padding: 1rem 1.1rem;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 14px;
}

.nav-mobile__protocols a,
.nav-mobile__library {
  /* Reset the giant .nav-mobile a serif sizing — these render at the
     .nav-pill__dropdown-name/-desc sizes set on their child spans instead. */
  display: flex;
  flex-direction: column;
  gap: 3px;
  text-align: left;
  font-size: 1rem;
  opacity: 1;
}

.nav-mobile__library {
  width: 100%;
  padding: 0.9rem 1.1rem;
  background: rgba(143, 163, 150, 0.2);
  border-radius: 14px;
}

.nav-mobile__view-all {
  font-family: 'Lato', sans-serif;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--sage-lifted);
  opacity: 1;
}

/* ── Current page ────────────────────────────────────────────────────────
   aria-current is the semantic marker and doubles as the styling hook, so
   the announced state and the visible one can't drift apart. Replaces the
   library-only --active class that never applied on any other page. */
.nav-pill__dropdown-item[aria-current="page"] .nav-pill__dropdown-name,
.nav-mobile__action a[aria-current="page"] .nav-pill__dropdown-name {
  font-weight: 700;
}

.nav-pill__dropdown-item[aria-current="page"]::after,
.nav-mobile__action a[aria-current="page"]::after {
  content: 'Currently viewing';
  font-family: 'Lato', sans-serif;
  /* 12px floor — see CLAUDE.md. Do not shrink to differentiate it. */
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--sage-lifted);
  margin-top: 0.15rem;
}

/* --- Desktop: pill displays links + divider + CTA --- */
@media (min-width: 1024px) {
  .nav-pill {
    /* Symmetrical vertical padding; snug right edge houses the CTA pill */
    padding: 0.45rem 0.45rem 0.45rem 1.4rem;
    gap: 0;
  }


  .nav-pill__links {
    display: flex;
    align-items: center;
    gap: 1.6rem;
  }

  .nav-pill__links a {
    font-family: 'Lato', sans-serif;
    font-size: var(--fs-small);
    font-weight: 400;
    letter-spacing: 0.08em;
    color: var(--cream);
    opacity: 0.75;
    position: relative;
    transition: opacity 0.5s var(--ease-smooth);
    line-height: 1;
    display: inline-flex;
    align-items: center;
    padding: 0.45rem 0;
  }

  /* Visible cream glow underline on hover */
  .nav-pill__links a::after {
    content: '';
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 1.5px;
    background: rgba(253, 252, 248, 0.9);
    box-shadow: 0 0 6px rgba(253, 252, 248, 0.3);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.5s var(--ease-smooth);
  }

  .nav-pill__links a:hover {
    opacity: 1;
  }

  .nav-pill__links a:hover::after {
    transform: scaleX(1);
  }

  /* Whisper-thin Divider */
  .nav-pill__divider {
    display: block;
    width: 1px;
    height: 18px;
    margin: 0 1.2rem;
    background: rgba(253, 252, 248, 0.2);
    flex-shrink: 0;
  }

  /* CTA Wrapper — houses trigger + dropdown */
  .nav-pill__cta-wrap {
    display: block;
    position: relative;
  }

  .nav-pill__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 1.15rem;
    font-family: 'Lato', sans-serif;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--cream);
    white-space: nowrap;
    border-radius: 999px;
    background: transparent;
    border: 1px solid rgba(249, 248, 242, 0.18);
    cursor: pointer;
    text-decoration: none;
    position: relative;
    transition: background 0.5s var(--ease-smooth),
                color 0.4s var(--ease-smooth),
                border-color 0.5s var(--ease-smooth),
                transform 0.3s var(--ease-smooth);
  }

  /* Subtle bottom accent line */
  .nav-pill__cta::after {
    content: '';
    position: absolute;
    bottom: -1px;
    left: 20%;
    width: 60%;
    height: 1.5px;
    background: var(--sage-green);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.5s var(--ease-smooth);
  }

  .nav-pill__cta-wrap:hover .nav-pill__cta::after,
  .nav-pill__cta:hover::after {
    transform: scaleX(1);
  }

  /* Animated chevron arrow */
  .nav-pill__cta-arrow {
    display: inline-flex;
    width: 8px;
    height: 8px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg) translate(-1px, -1px);
    opacity: 0.45;
    transition: transform 0.5s var(--ease-smooth), opacity 0.3s var(--ease-smooth);
    flex-shrink: 0;
  }

  .nav-pill__cta-wrap:hover .nav-pill__cta-arrow,
  .nav-pill__cta-wrap.is-open .nav-pill__cta-arrow {
    transform: rotate(225deg) translate(-1px, -1px);
    opacity: 0.85;
  }

  .nav-pill__cta:hover,
  .nav-pill__cta-wrap:hover .nav-pill__cta,
  .nav-pill__cta-wrap.is-open .nav-pill__cta {
    background: rgba(143, 163, 150, 0.18);
    border-color: rgba(143, 163, 150, 0.35);
    transform: translate3d(0, -1px, 0);
  }

  /* The page-dimming .nav-scrim that used to sit behind this panel was removed
     2026-08-05. .nav-pill lives inside .page-content (z-index:1), so the nav's
     z-index:999 is scoped to that stacking context and a body-level scrim at
     900 covered the entire nav, the panel included — every click landed on the
     scrim and the site read as frozen. See nav-dropdown.js.

     Dropdown panel — opened by JS (.is-open on the wrap) on hover or focus.
     It is a preview of offerings.html, never the only route to it: the trigger
     is a plain link, so a ≥1024px touchscreen that never opens this panel
     still reaches the same content by tapping through. */
  .nav-pill__dropdown {
    position: absolute;
    top: calc(100% + 0.75rem);
    right: -0.5rem;
    min-width: 324px;
    padding: 0.85rem;
    /* Lifted off near-black and made more opaque: the old 0.92 let dark hero
       imagery bleed through and muddy the type underneath it. */
    background: rgba(52, 50, 45, 0.96);
    backdrop-filter: var(--glass-blur-lg);
    -webkit-backdrop-filter: var(--glass-blur-lg);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 16px;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18),
                0 2px 8px rgba(0, 0, 0, 0.08);

    /* Hidden by default */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition:
      opacity 0.4s var(--ease-smooth),
      visibility 0.4s,
      transform 0.4s var(--ease-smooth);
  }

  .nav-pill__cta-wrap.is-open .nav-pill__dropdown {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }

  .nav-pill__dropdown-section-label {
    font-family: 'Lato', sans-serif;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(249, 248, 242, 0.72);
    padding: 0.4rem 0.95rem 0.5rem;
    margin: 0;
  }

  .nav-pill__dropdown-item {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    padding: 0.8rem 0.95rem;
    border-radius: 12px;
    text-decoration: none;
    transition: background 0.3s var(--ease-smooth);
  }

  .nav-pill__dropdown-item:hover,
  .nav-pill__dropdown-item:focus-visible {
    background: rgba(255, 255, 255, 0.07);
  }

  .nav-pill__dropdown-item:focus-visible {
    outline: 2px solid var(--cream);
    outline-offset: -2px;
  }

  .nav-pill__dropdown-divider {
    height: 1px;
    background: rgba(255, 255, 255, 0.12);
    margin: 0.4rem 0.6rem;
  }

  .nav-pill__dropdown-footer {
    padding: 0.6rem 0.95rem 0.45rem;
    text-align: center;
  }

  .nav-pill__dropdown-footer a {
    font-family: 'Lato', sans-serif;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    /* Solid, not the old opacity:0.6 sage — that read 2.57:1, the worst
       contrast in the panel on what is meant to be its primary CTA. */
    color: var(--sage-lifted);
    text-decoration: none;
    transition: letter-spacing 0.4s var(--ease-smooth);
  }

  .nav-pill__dropdown-footer a:hover {
    letter-spacing: 0.18em;
  }

  .nav-pill__dropdown-footer a:focus-visible {
    outline: 2px solid var(--cream);
    outline-offset: 2px;
    border-radius: 6px;
  }

  /* Library — grouped below the divider, apart from the one-time protocols
     under .nav-pill__dropdown-section-label, since it's the recurring
     membership rather than a protocol. Tinted row rather than a border
     stripe so it reads as its own category, not a 4th list item. */
  .nav-pill__dropdown-item--library {
    background: rgba(143, 163, 150, 0.16);
  }

  .nav-pill__dropdown-item--library:hover,
  .nav-pill__dropdown-item--library:focus-visible {
    background: rgba(143, 163, 150, 0.26);
  }

  .nav-pill__burger {
    display: none;
  }

  .nav-mobile {
    display: none;
  }
}


/* ═══════════════════════════════════════════════════
   NAV: SCROLL-AWARE DUAL-MODE (Global)
   Default = light mode (charcoal text on light backgrounds).
   .nav--dark = dark mode (cream text on dark backgrounds).
   Toggled by nav-theme.js based on [data-nav-theme] sections.
   ═══════════════════════════════════════════════════ */

/* Smooth transitions on all color-shifting elements.
   NOTE: `transform` is in this list but the pill's transform is static
   centering (translate3d(-50%,0,0)) and never changes, so it never fires.
   Do not add a transform change here (hide-on-scroll, shrink-on-scroll):
   .nav-pill owns a backdrop-filter and contains .nav-pill__dropdown (blur
   28px), so animating it re-rasterises both blurs every frame — and the
   !important below makes that hard to opt out of later. Animate opacity
   instead. See menu-of-care.css:933. */
.nav-pill,
.nav-pill__burger span {
  transition: background 0.5s var(--ease-smooth), border-color 0.5s var(--ease-smooth), box-shadow 0.4s var(--ease-smooth), transform 0.4s var(--ease-smooth), opacity 0.3s var(--ease-smooth) !important;
}

/* ── .nav--dark: Cream text for dark sections ── */
.nav--dark .nav-pill {
  background: rgba(32, 32, 30, 0.50);
  border-color: rgba(255, 255, 255, 0.08);
}

.nav--dark .nav-pill__burger span {
  background: var(--cream) !important;
}

/* ── .nav--light: Charcoal text for light sections ── */
.nav--light .nav-pill {
  background: var(--glass);
  border-color: var(--glass-border-color);
}

.nav--light .nav-pill__burger span {
  background: var(--charcoal) !important;
}

@media (min-width: 1024px) {

  /* ── Dark mode ── */
  .nav--dark .nav-pill {
    background: rgba(32, 32, 30, 0.50) !important;
    border-color: rgba(255, 255, 255, 0.08) !important;
  }

  .nav--dark .nav-pill__links a {
    color: var(--cream) !important;
    opacity: 0.8;
    transition: color 0.5s var(--ease-smooth), opacity 0.5s var(--ease-smooth) !important;
  }

  .nav--dark .nav-pill__links a:hover {
    opacity: 1 !important;
  }

  .nav--dark .nav-pill__links a::after {
    background: rgba(245, 245, 240, 0.85) !important;
    box-shadow: 0 0 6px rgba(245, 245, 240, 0.25) !important;
  }

  .nav--dark .nav-pill__divider {
    background: rgba(245, 245, 240, 0.2) !important;
  }

  .nav--dark .nav-pill__cta {
    background: transparent !important;
    color: var(--cream) !important;
    border-color: rgba(249, 248, 242, 0.22) !important;
    transition: background 0.5s var(--ease-smooth), color 0.5s var(--ease-smooth), border-color 0.5s var(--ease-smooth), transform 0.3s var(--ease-smooth) !important;
  }

  .nav--dark .nav-pill__cta:hover,
  .nav--dark .nav-pill__cta-wrap:hover .nav-pill__cta,
  .nav--dark .nav-pill__cta-wrap.is-open .nav-pill__cta {
    background: rgba(143, 163, 150, 0.2) !important;
    border-color: rgba(143, 163, 150, 0.4) !important;
    color: var(--cream) !important;
  }

  .nav--dark .nav-pill__cta::after {
    background: var(--sage-green) !important;
  }

  .nav--dark .nav-pill__dropdown {
    background: rgba(30, 30, 28, 0.92) !important;
    border-color: rgba(249, 248, 242, 0.06) !important;
  }

  /* ── Light mode ── */
  .nav--light .nav-pill {
    background: rgba(230, 228, 221, 0.12) !important;
    border-color: rgba(230, 228, 221, 0.18) !important;
  }

  .nav--light .nav-pill__links a {
    color: var(--charcoal) !important;
    transition: color 0.5s var(--ease-smooth), opacity 0.5s var(--ease-smooth) !important;
  }

  .nav--light .nav-pill__links a:hover {
    opacity: 0.5 !important;
  }

  .nav--light .nav-pill__links a::after {
    background: rgba(42, 42, 42, 0.7) !important;
    box-shadow: 0 0 4px rgba(42, 42, 42, 0.15) !important;
  }

  .nav--light .nav-pill__divider {
    background: rgba(42, 42, 42, 0.2) !important;
  }

  .nav--light .nav-pill__cta {
    background: transparent !important;
    color: var(--charcoal) !important;
    border-color: rgba(42, 42, 42, 0.2) !important;
    transition: background 0.5s var(--ease-smooth), color 0.5s var(--ease-smooth), border-color 0.5s var(--ease-smooth), transform 0.3s var(--ease-smooth) !important;
  }

  .nav--light .nav-pill__cta:hover,
  .nav--light .nav-pill__cta-wrap:hover .nav-pill__cta,
  .nav--light .nav-pill__cta-wrap.is-open .nav-pill__cta {
    background: rgba(42, 42, 42, 0.06) !important;
    border-color: rgba(42, 42, 42, 0.3) !important;
    color: var(--charcoal) !important;
  }

  .nav--light .nav-pill__cta::after {
    background: var(--sage-green) !important;
  }

  .nav--light .nav-pill__dropdown {
    background: rgba(30, 30, 28, 0.92) !important;
    border-color: rgba(255, 255, 255, 0.06) !important;
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18), 0 2px 8px rgba(0, 0, 0, 0.08) !important;
  }

  /* Light-mode dropdown now shares the same dark glass as dark-mode — unified look */
  .nav--light .nav-pill__dropdown-item:hover,
  .nav--light .nav-pill__dropdown-item:focus-visible {
    background: rgba(255, 255, 255, 0.06) !important;
  }

  .nav--light .nav-pill__dropdown-name {
    color: var(--cream) !important;
  }

  /* 0.42 -> 0.6, matching the base-rule fix: this override was independently
     regressing the same contrast failure (2.9:1) whenever the nav sat over
     a light-themed section. */
  .nav--light .nav-pill__dropdown-desc {
    color: rgba(249, 248, 242, 0.6) !important;
  }

  .nav--light .nav-pill__dropdown-divider {
    background: rgba(255, 255, 255, 0.05) !important;
  }

  /* Same lifted sage as the base rule — the panel is the identical dark
     glass in both themes, so a plain --sage-green here would silently
     reinstate the 4.51 hairline on every light-themed section. */
  .nav--light .nav-pill__dropdown-footer a {
    color: var(--sage-lifted) !important;
  }

  .nav--light .nav-pill__dropdown-item--library {
    background: rgba(143, 163, 150, 0.16) !important;
  }

  .nav--light .nav-pill__dropdown-item--library:hover,
  .nav--light .nav-pill__dropdown-item--library:focus-visible {
    background: rgba(143, 163, 150, 0.26) !important;
  }
}


/* ════════════════════════════════════════════
   SECTION 2 — HERO (The Inhale)
   ════════════════════════════════════════•═════════ */
.hero {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100svh;
  min-height: 500px;
  overflow: hidden;
  background: var(--charcoal);
}

/* ─── Global Content Containment ───
   CONTENT wrappers only. Never a <section> that paints a background.

   .starting and .proof used to be in this list, and both are full-bleed
   sections with their own background. Capping a section at 1200px does not
   narrow its content — the inner wrappers below already do that — it narrows
   the painted box, so above 1200px the background became a band down the
   middle with .page-content's cream either side. At 1440 that is 120px of the
   wrong colour on each edge.

   Only .proof was ever visible: it paints --stone against a --cream page.
   .starting paints --cream on --cream, so it had the identical bug and looked
   perfect. Removed from this rule 2026-08-07 — .starting too, because a
   latent version of a bug you have already fixed once is worth closing while
   you are holding it.

   Each section's content stays contained by its own wrapper:
     .starting  -> .starting__header, .starting__grid  (both below)
     .proof     -> .proof__header (below), .proof__sticky (max-width 1100px) */
.starting__header,
.starting__grid,
.proof__header,
.methodology__inner,
.footer__inner {
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
}

.hero__bg {
  position: absolute;
  /* Parallax needs vertical space (top/bottom -15%), but NO horizontal cropping (left/right 0) */
  inset: -15% 0;
  z-index: 1;
  will-change: transform;
}

.hero__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Mobile: keep lady on rocks visible (left side) */
  object-position: left center;
  /* "Inhale" animation: zoom-out 105% → 100%, fade in */
  opacity: 0;
  transform: scale(1.05);
  animation: heroInhale 5s var(--ease-smooth) forwards;
  will-change: transform, opacity;
}

/* ── MOBILE HERO: 3-part organic layout ────────────── */
@media (max-width: 768px) {

  /* Reset parallax overflow — not needed on mobile */
  .hero__bg {
    inset: 0 !important;
  }

  /* PART 1: Background Physics
     The woman sits at ~25% from left in the landscape original.
     On 9:16 viewport, only ~30% of image width shows.
     Position her center-frame with sky above. */
  .hero__img {
    object-position: 15% 80% !important;
  }
}

@keyframes heroInhale {
  0% {
    opacity: 0;
    transform: scale(1.05);
  }

  30% {
    /* Fade in completes by 1.5s (30% of 5s) */
    opacity: 1;
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* Hero stays left-cropped on all sizes to keep the subject visible */

/* Warm color grade overlay — removes cool blue, adds golden warmth */
.hero__warmth {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(135deg,
      rgba(200, 160, 80, 0.12) 0%,
      rgba(143, 163, 150, 0.08) 50%,
      rgba(200, 160, 80, 0.06) 100%);
  mix-blend-mode: multiply;
  pointer-events: none;
}

/* Dark gradient overlay for text readability */
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 3;
  background: linear-gradient(270deg,
      rgba(240, 238, 233, 0.85) 0%,
      rgba(240, 238, 233, 0.4) 40%,
      transparent 70%);
  pointer-events: none;
}

/* Text cascade — right side, vertically centered (no transform — GSAP-safe) */
.hero__content {
  position: absolute;
  z-index: 4;
  top: 0;
  bottom: 0;
  margin-top: auto;
  margin-bottom: auto;
  height: fit-content;
  right: max(1.5rem, calc((100vw - 1200px) / 2 - 3rem));
  max-width: 540px;
  text-align: left;
}

@media (max-width: 768px) {

  /* PART 1 (cont.): Full viewport hero */
  .hero {
    height: 100svh;
    min-height: 100svh;
    max-height: 100svh;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    overflow: hidden;
  }

  /* Desktop fades from the RIGHT edge, because the text sits on the right of a
     wide frame. On a phone the composition rotates — the text stacks at the
     bottom — so the fade rotates with it rather than being switched off.

     It is needed. Sampling the rendered pixels under the subtitle on a 375px
     iPhone: the darkest 5% of that band is luma 109, giving charcoal-at-85%
     just 2.40:1. Three cheaper fixes were measured and rejected first:
       · vertical re-crop is inert — at 1344x768 into 375x812 the cover scale
         is driven entirely by height, so there is no vertical slack at all;
       · horizontal re-crop does work (p5 rises to 177, comfortably AA) but
         pans the woman clean out of frame;
       · narrowing the subtitle barely moves it (109 -> 119 even at 52% width)
         because the dark band is the rock edge spanning the full width, not
         the subject.

     Anchored to the bottom edge so it reads as the photograph dissolving into
     the cream section below — the same device as desktop, and the reason the
     previous attempt failed: a centred ellipse floating mid-frame read as a
     smudge on the picture. */
  .hero::after {
    background: linear-gradient(to top,
        var(--cream) 0%,
        rgba(249, 248, 242, 0.94) 16%,
        rgba(249, 248, 242, 0.66) 38%,
        rgba(249, 248, 242, 0.26) 58%,
        rgba(249, 248, 242, 0) 74%);
  }

  /* PART 2: Typography Recalibration — right-aligned breathable layout */
  .hero__content {
    position: relative;
    top: auto;
    bottom: auto;
    right: auto;
    left: auto;
    transform: none;
    width: 85%;
    max-width: 100%;
    margin-left: auto;
    margin-right: 0;
    padding: 14svh 1.25rem 12svh 0;
    box-sizing: border-box;
    text-align: right;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    z-index: 4;
  }

  /* The radial "mist guard" that used to sit here was removed 2026-08-05 —
     it read as a white smudge floating over the middle of the photograph.
     Replaced by .hero::after below: an edge-anchored fade instead of a blob.
     See the note there for why the crop could not solve this on its own. */

  /* Measured 108px of dead space between the rule and the word "ROOTED" on a
     375px iPhone. The eyebrow is a flex row, the label wraps to two lines at
     this width, and the anonymous text item then stretches to fill the row —
     inherited text-align:right pulls the words to its far edge while the rule
     stays pinned at its near edge.

     Block layout with an inline-block ::before keeps the rule attached to the
     first word however the label wraps. !important because the base
     .hero__eyebrow rule is declared LATER in this file at equal specificity;
     without it `display: block` silently loses to `display: flex`. */
  .hero__eyebrow {
    display: block !important;
    text-align: right;
  }

  .hero__eyebrow::before {
    display: inline-block !important;
    width: 24px !important;
    margin-right: 0.6rem;
    vertical-align: middle;
  }

  .hero__title {
    font-size: clamp(2rem, 8vw, 3rem);
    color: var(--charcoal);
  }

  .hero__subtitle {
    font-size: clamp(0.85rem, 3.5vw, 1rem);
    max-width: 80%;
    color: rgba(42, 42, 42, 0.85);
    align-self: flex-end;
    margin-top: 0.5rem;
  }

  .hero__cta {
    align-self: flex-end;
  }
}

/* --- Eyebrow --- */
.hero__eyebrow {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-tag);
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--sage-muted);
  margin-bottom: 1.2rem;

  opacity: 0;
  transform: translate3d(0, 15px, 0);
  animation: textCascade 0.8s var(--ease-smooth) 1.2s forwards;
}

.hero__eyebrow::before {
  content: '';
  display: block;
  width: 40px;
  height: 1px;
  background: var(--sage-muted);
}

/* --- Headline --- */
.hero__title {
  font-family: 'Playfair Display', serif;
  font-size: clamp(3rem, 6vw, 5rem);
  color: var(--charcoal);
  margin-bottom: 0.6em;
  line-height: 1.05;

  opacity: 0;
  transform: translate3d(0, 15px, 0);
  animation: textCascade 0.8s var(--ease-smooth) 1.4s forwards;
}

.hero__highlight {
  color: var(--warm-gold);
  font-style: italic;
  font-weight: 500;
}

/* --- Subheadline --- */
.hero__subtitle {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-body);
  font-weight: 300;
  color: rgba(42, 42, 42, 0.85);
  letter-spacing: 0.02em;
  line-height: 1.85;
  max-width: 44ch;
  margin-bottom: 2rem;

  opacity: 0;
  transform: translate3d(0, 15px, 0);
  animation: textCascade 0.8s var(--ease-smooth) 1.6s forwards;
}

/* --- CTA Button — the site's primary conversion link ──────────────────────
   It goes to offerings.html and sits on a photographic hero, so it has to
   carry real mass and separate cleanly from the image. Held inside the
   brand's own language: sage pill, cream type, somatic easing, nothing neon.

   Two fixes are baked in here. The entrance used `forwards` fill, so the
   animation's held end-state outranked `:hover` in the cascade and the lift
   never rendered; it now fills `backwards` off a visible base state, which
   leaves transform free once the animation ends. And the idle "breathing"
   scaled the button itself, compounding the same problem — the pulse now
   lives on a halo pseudo-element and animates opacity alone. */
.hero__cta {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  padding: 1.1rem 2.4rem;
  min-height: 56px;
  font-family: 'Lato', sans-serif;
  font-size: clamp(0.95rem, 1.1vw, 1.05rem);
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1;
  color: var(--cream);
  background: var(--cta-green);
  border: 1px solid rgba(249, 248, 242, 0.22);
  border-radius: 999px;
  box-shadow: 0 6px 28px rgba(42, 42, 42, 0.22),
              0 2px 8px rgba(42, 42, 42, 0.1);
  transition: background 0.8s var(--ease-smooth),
              transform 0.8s var(--ease-smooth),
              box-shadow 0.8s var(--ease-smooth);

  /* Resting state is the visible one — see the note above. */
  opacity: 1;
  transform: translate3d(0, 0, 0);
  animation: ctaRise 0.8s var(--ease-smooth) 1.8s backwards;
}

@keyframes ctaRise {
  from {
    opacity: 0;
    transform: translate3d(0, 15px, 0);
  }

  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

/* Idle halo — a slow breath of light around the pill so the eye finds it on a
   busy photograph without the button ever moving. Opacity only. */
.hero__cta::before {
  content: '';
  position: absolute;
  inset: -6px;
  border: 1px solid rgba(249, 248, 242, 0.45);
  border-radius: 999px;
  opacity: 0;
  pointer-events: none;
  animation: ctaHalo 4.5s var(--ease-smooth) 3s infinite;
}

@keyframes ctaHalo {

  0%,
  100% {
    opacity: 0;
  }

  50% {
    opacity: 0.55;
  }
}

.hero__cta-arrow {
  display: inline-block;
  font-size: 1.05em;
  line-height: 1;
  transition: transform 0.8s var(--ease-smooth);
}

.hero__cta:hover {
  background: var(--cta-green-dark);
  transform: translate3d(0, -2px, 0);
  box-shadow: 0 12px 36px rgba(42, 42, 42, 0.3),
              0 2px 10px rgba(42, 42, 42, 0.14);
}

.hero__cta:hover .hero__cta-arrow {
  transform: translate3d(4px, 0, 0);
}

.hero__cta:focus-visible {
  outline: 2px solid var(--cream);
  outline-offset: 4px;
}

@keyframes textCascade {
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}


/* ═══════════════════════════════════════════
   SECTION 3 — STARTING POINT (Editorial Cards)
   ═══════════════════════════════════════════ */
.starting {
  position: relative;
  z-index: 1;
  padding: var(--rhythm-unit) var(--gutter);
  background: var(--cream);
}

/* Starting Point header — scroll-reveal entrance + layout */
.starting__header {
  text-align: center;
  margin-bottom: clamp(3rem, 6vw, 5rem);
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
  /* Scroll-reveal entrance */
  opacity: 0;
  transform: translateY(25px);
  transition: opacity 1s var(--ease-smooth), transform 1s var(--ease-smooth);
}

.starting__header.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.starting__title {
  font-size: var(--fs-h2);
  /* Dark rust / warm brown — editorial, grounding */
  color: var(--dark-rust);
  line-height: 1.15;
}

/* Mobile: horizontal snap scroll */
.starting__grid {
  display: flex;
  gap: var(--gutter);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 1rem;
  scrollbar-width: none;
  max-width: 1200px;
  margin-left: auto;
  margin-right: auto;
}

.starting__grid::-webkit-scrollbar {
  display: none;
}

/* --- Card Container --- */
.starting__card {
  flex: 0 0 80%;
  scroll-snap-align: center;
  display: flex;
  flex-direction: column;
  position: relative;
  text-decoration: none;
  border-radius: 1rem;
  /* 16px standard card radius */
  overflow: hidden;
  background: #fff;
  box-shadow: 0 0 0 rgba(0, 0, 0, 0);
  transition: box-shadow 1.5s var(--ease-smooth),
    opacity 0.8s var(--ease-smooth),
    transform 0.8s var(--ease-smooth);

  /* Scroll entrance — staggered via JS transition-delay */
  opacity: 0;
  transform: translateY(30px);
}

.starting__card.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Warm diffused shadow bloom on hover — no heavy drop shadows */
.starting__card:hover {
  box-shadow: 0 8px 32px rgba(92, 64, 51, 0.06);
}

/* --- Image Area (Top 55%) --- */
.starting__card-img-wrap {
  position: relative;
  width: 100%;
  /* Full 4:5 portrait — no cropping of subject */
  aspect-ratio: 4 / 5;
  overflow: hidden;
  /* Soft corners matching earlier layout, overwriting parent if needed */
  border-radius: 16px 16px 0 0;
}

.starting__card-img-wrap img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
  /* The "Exhale" — slow 3% scale over 1.5 seconds */
  transition: transform 0.8s var(--ease-smooth), filter 0.8s var(--ease-smooth);
  will-change: transform, filter;
  filter: saturate(1) brightness(1);
}

.hero__aura {
  position: absolute;
  top: 0;
  left: 0;
  width: 50vw;
  height: 50vw;
  background: radial-gradient(circle, rgba(230, 140, 90, 0.25) 0%, rgba(200, 90, 50, 0) 70%);
  border-radius: 50%;
  pointer-events: none;
  filter: blur(80px);
  z-index: 1;
  opacity: 0;
  mix-blend-mode: soft-light;
  will-change: transform, opacity;
}

/* Card 2 (Menstrual Days) — pull focal point down to show both hands */
.starting__card:nth-child(2) .starting__card-img-wrap img {
  object-position: center 35%;
}

.starting__card:hover .starting__card-img-wrap img {
  transform: scale(1.03);
  filter: saturate(1.1) brightness(1.03);
}

/* --- Text Area (Bottom 45%) --- */
.starting__card-body {
  padding: 1.5rem 1.5rem 2rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: 0.5rem;
  flex: 1;
}

/* Eyebrow — tiny sage-green caps */
.starting__card-eyebrow {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-tag);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage-deep, #5A6457);
}

/* Title — elegant serif */
.starting__card-title {
  font-family: 'Playfair Display', serif;
  font-size: var(--fs-h3);
  font-weight: 600;
  color: var(--charcoal);
  line-height: 1.25;
  margin-top: 0.2rem;
  margin-bottom: 0.2rem;
}

/* Body text — clean sans-serif, muted */
.starting__card-text {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-small);
  font-weight: 400;
  color: rgba(44, 44, 44, 0.85);
  line-height: 1.6;
  margin: 0;
}

/* Text-link CTA */
.starting__card-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--sage-deep, #5A6457);
  margin-top: auto;
  padding-top: 1rem;
  transition: color 0.8s var(--ease-smooth);
}

/* Dark Rust text fade on hover — somatic warmth */
.starting__card:hover .starting__card-link {
  color: var(--dark-rust);
}

.starting__card-arrow {
  display: inline-block;
  transition: transform 0.4s var(--ease-smooth);
}

.starting__card:hover .starting__card-arrow {
  transform: translateX(4px);
}

/* Mobile: stack cards vertically */
@media (max-width: 768px) {
  .starting__grid {
    flex-direction: column;
    overflow-x: visible;
    scroll-snap-type: none;
    gap: 2rem;
    padding: 0 1.5rem;
  }

  .starting__card {
    flex: none;
    width: 100%;
  }
}

/* Tablet portrait: two columns rather than the phone stack.
   Between 600px and 768px the cards were stacking full-width, which is the
   single biggest reason this page ran ~2x longer at 768 (14,326px) than at
   1024 (7,229px) — there is comfortably room for two cards at 736px of
   content width. Phones keep stacking; 769-1023 keeps the scroll-snap rail. */
@media (min-width: 600px) and (max-width: 768px) {
  .starting__grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 2rem;
    overflow: visible;
    scroll-snap-type: none;
  }

  .starting__card {
    flex: none;
    width: auto;
  }
}

/* Desktop: 3-column grid with massive breathing room */
@media (min-width: 1024px) {
  .starting__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    /* 4rem ≈ 3–4 inches of visual gap at typical screen sizes */
    gap: 4rem;
    overflow: visible;
    padding-bottom: 0;
  }

  .starting__card {
    flex: none;
  }
}


/* --- Curtain Preloader --- */
.curtain {
  position: fixed;
  inset: 0;
  z-index: 10000;
  background: var(--cream);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.8s var(--ease-smooth);
}

.curtain.is-raised {
  transform: translate3d(0, -100%, 0);
  pointer-events: none;
}

.curtain__logo-wrap {
  width: 80px;
  opacity: 0;
  transform: scale(0.9);
  animation: logoPulse 2s ease-out forwards;
}

.curtain__logo {
  width: 100%;
  height: auto;
}

@keyframes logoPulse {
  0% {
    opacity: 0;
    transform: scale(0.9);
  }

  40% {
    opacity: 1;
    transform: scale(1);
  }

  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* ═══════════════════════════════════════════
   SECTION 4 — METHODOLOGY (Sticky Split-Screen)
   ═══════════════════════════════════════════ */
.methodology {
  position: relative;
  z-index: 1;
  background: var(--sage-deep);
  /* 1.25x the section unit — the page's biggest statement block. */
  padding: calc(var(--rhythm-unit) * 1.25) clamp(1.5rem, 4vw, 4rem);
  overflow: hidden;
}




.methodology__inner {
  display: flex;
  flex-direction: column;
  gap: clamp(3rem, 5vw, 4rem);
  max-width: 1200px;
  margin: 0 auto;
  align-items: center;
}

/* --- Left: Arch Image with Depth --- */
.methodology__media {
  position: relative;
  width: 100%;
  max-width: 440px;
}

.methodology__img-wrap {
  position: relative;
  width: 100%;
  border-radius: 220px 220px 16px 16px;
  overflow: hidden;
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.25),
    0 12px 32px rgba(0, 0, 0, 0.15),
    0 0 0 1px rgba(255, 255, 255, 0.08);
}

.methodology__img-wrap img {
  width: 100%;
  height: auto;
  display: block;
  object-fit: cover;
  aspect-ratio: 3 / 4;
}

/* Play button overlay */
.methodology__play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--charcoal);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  transition: transform 0.6s var(--ease-smooth), box-shadow 0.6s var(--ease-smooth);
  z-index: 2;
}

.methodology__play svg {
  margin-left: 3px;
}

.methodology__play:hover {
  transform: translate(-50%, -50%) scale(1.1);
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.2);
}

/* Holistic badge — bottom-left */
.methodology__badge {
  position: absolute;
  bottom: 1.5rem;
  left: -0.5rem;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: var(--glass-blur-md);
  -webkit-backdrop-filter: var(--glass-blur-md);
  border-radius: 12px;
  padding: 0.75rem 1.2rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
  z-index: 2;
  max-width: 200px;
}

.methodology__badge-title {
  display: block;
  font-family: 'Lato', sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--charcoal);
  margin-bottom: 0.25rem;
}

.methodology__badge-desc {
  display: block;
  font-family: 'Lato', sans-serif;
  font-size: 0.75rem;
  font-weight: 400;
  color: rgba(42, 42, 42, 0.7);
  line-height: 1.4;
}

/* --- Right: Text Content --- */
.methodology__text {
  width: 100%;
  text-align: center;
}

.methodology__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-bottom: 1.5rem;
}

.methodology__eyebrow-line {
  display: block;
  width: 40px;
  height: 1px;
  background: rgba(255, 255, 255, 0.35);
}

.methodology__eyebrow-label {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-tag);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  white-space: nowrap;
}

.methodology__title {
  font-family: 'Playfair Display', serif;
  font-size: clamp(2rem, 4vw + 0.5rem, 3.2rem);
  color: #fff;
  line-height: 1.15;
  margin-bottom: 1.5rem;
  font-weight: 500;
}

.methodology__title em {
  font-style: italic;
}

.methodology__body {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-body);
  font-weight: 300;
  color: rgba(255, 255, 255, 0.85);
  line-height: 1.7;
  max-width: 50ch;
  margin: 0 auto 3rem;
}

/* --- Three Icon Pillars --- */
/* The three methodology pillars stay on ONE row at every width — never 2+1.
   `nowrap` plus `min-width: 0` on the items lets them shrink past min-content
   so the labels wrap inside their own column instead of pushing a pillar onto
   a second row. Measured at 375px: three 98px columns, no overflow. */
.methodology__pillars {
  display: flex;
  justify-content: center;
  /* Max gap is 2.5rem, not the 4rem it was: the three labels need 543px of
     natural width and the column is 635px at 1280, so a 4rem gap left them
     10px short and forced every label onto two lines. Buying that back from
     the gap keeps them on one line each on wide screens. */
  gap: clamp(1rem, 3vw, 2.5rem);
  flex-wrap: nowrap;
  padding-top: 2rem;
  border-top: 1px solid rgba(255, 255, 255, 0.2);
}

.methodology__pillar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  text-align: center;
}

.methodology__pillar-icon {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(255, 255, 255, 0.9);
}

.methodology__pillar-label {
  font-family: 'Lato', sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.9);
}

/* --- Desktop: Side-by-side --- */
@media (min-width: 1024px) {
  .methodology {
    /* horizontal only — vertical rhythm stays on the shared ratio */
    padding-left: clamp(2rem, 5vw, 5rem);
    padding-right: clamp(2rem, 5vw, 5rem);
  }

  .methodology__inner {
    flex-direction: row;
    align-items: center;
    gap: clamp(4rem, 6vw, 6rem);
  }

  .methodology__media {
    width: 42%;
    flex-shrink: 0;
  }

  .methodology__text {
    width: 58%;
    text-align: left;
  }

  .methodology__eyebrow {
    justify-content: flex-start;
  }

  .methodology__body {
    margin-left: 0;
    margin-right: 0;
  }

  .methodology__pillars {
    justify-content: flex-start;
  }
}

/* A previous revision dropped these to a 2+1 grid on phones, because three
   ~90px columns made "OUTCOME-MAPPED PROTOCOLS" break awkwardly. One row is
   now required at every width instead, so the space is recovered from tracking
   rather than from the layout: 0.15em → 0.06em is worth roughly 20px per
   label at this size. The 12px type floor set in 728468b is deliberately
   preserved — the fix is horizontal, not smaller text. */
@media (max-width: 600px) {
  .methodology__pillar-label {
    letter-spacing: 0.06em;
    hyphens: auto;
  }
}




/* ═══════════════════════════════════════════
   SECTION 5 — SOCIAL PROOF (Scroll-driven Waterfall)
   ═══════════════════════════════════════════ */

/* Outer section — must NOT have overflow:hidden/auto/scroll (breaks child sticky) */
.proof {
  position: relative;
  z-index: 1;
  background: var(--stone);
  /* Section height is set by the JS-generated .proof__scroll-height spacer div */
}

/* Spacer div — JS sets its height to create scroll distance for the waterfall */
.proof__scroll-height {
  position: relative;
  pointer-events: none;
}

/*
  Sticky viewport frame — pins to screen while parent scrolls.
  overflow:hidden on the sticky element itself is FINE (only ancestor overflow breaks sticky).
  This clips the columns as they translate upward through the frame.
*/
.proof__sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: var(--gutter);
  max-width: 1100px;
  margin: 0 auto;
}

.proof__header {
  text-align: center;
  padding: clamp(3rem, 6vw, 5rem) var(--gutter) 2rem;
}

.proof__tag {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-tag);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--stone-muted);
}

.proof__title {
  font-size: var(--fs-h2);
  color: var(--charcoal-deep);
  margin-top: 0.4rem;
  line-height: 1.12;
}

.proof__title em {
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-weight: 400;
  color: var(--charcoal-muted);
  display: block;
  margin-top: 0.15em;
}

.proof__masonry {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  flex: 1;
  min-height: 0;
}

.proof__col {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  will-change: transform;
}

.proof__card {
  border-radius: 16px;
  overflow: hidden;
}

.proof__card--text {
  background: #fff;
  padding: 2rem;
}

.proof__card--text blockquote {
  font-family: 'Playfair Display', serif;
  font-size: var(--fs-body);
  font-weight: 400;
  font-style: italic;
  color: var(--charcoal);
  line-height: 1.6;
  margin: 0;
  margin-bottom: 0.8em;
}

.proof__card--text cite {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-small);
  font-style: normal;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--sage-deep, #5A6457);
}

/* The surrounding quote recedes; the reviewer's one standout line stays sharp.
   filter:blur() on an inline span rasterizes only that span's own content, so
   the sharp <mark> sitting between two blurred spans is unaffected — no
   "unblur the child" trick needed. The soft bleed at each span's edge reads
   as an intentional gradient into clarity rather than a seam. */
.proof__blur {
  transition: filter 0.8s var(--ease-smooth), opacity 0.8s var(--ease-smooth);
}

.proof__highlight {
  background: none;
  color: var(--dark-rust);
  font-weight: 500;
  font-style: normal;
}

/* Blur ONLY where there is a pointer to lift it with.
   Touch devices have no hover, so a permanently softened quote is simply an
   unreadable quote — and ~80% of this site's visitors are on touch. There the
   full testimonial renders sharp and the highlight carries the emphasis on its
   colour alone, which is the same editorial intent without the legibility
   cost. Mouse users get the recede-then-reveal treatment. */
@media (hover: hover) {
  .proof__blur {
    filter: blur(1.6px);
    opacity: 0.6;
  }

  .proof__card--text:hover .proof__blur,
  .proof__card--text:focus-within .proof__blur {
    filter: blur(0);
    opacity: 1;
  }
}

/* ── Touch: the same reveal, driven by scroll position instead of a cursor ──
   Core directives §3: "Map desktop hover micro-animations to IntersectionObserver
   on mobile — trigger when centered in viewport." A card sits softened until it
   reaches the middle of the screen, then resolves — the reader's attention and
   the focus arrive together, with nothing to tap.

   Gated on .proof--focus-reveal, which main.js adds only after the observer is
   actually wired. If the script never runs, the class never lands and every
   quote stays sharp — the failure mode is plain text, never unreadable text. */
@media (hover: none) {
  .proof--focus-reveal .proof__blur {
    filter: blur(1.6px);
    opacity: 0.6;
  }

  .proof--focus-reveal .proof__card--text.is-centred .proof__blur {
    filter: blur(0);
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .proof__blur {
    transition: none;
  }
}

/* Blur is a legibility cost, not just a style choice — waive it under
   prefers-contrast rather than asking low-vision visitors to hover to read.
   Also covers the touch path above, since that blur is a filter too. */
@media (prefers-contrast: more) {
  .proof__blur,
  .proof--focus-reveal .proof__blur {
    filter: none;
    opacity: 1;
  }
}

.proof__card--image {
  aspect-ratio: 4 / 5;
}

.proof__card--image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 16px;
}

/* ── Desktop: 3-column ── */
@media (min-width: 1024px) {
  .proof__masonry {
    flex-direction: row;
    align-items: flex-start;
    gap: 1.5rem;
  }

  .proof__col {
    flex: 1;
    gap: 1.5rem;
  }
}

/* ── Mobile: plain document flow, every testimonial reachable ──
   The pinned waterfall is a desktop device: it runs three columns through a
   100dvh window, translating each by its own height on scroll. That mechanic
   has no sensible one-column form, and the previous workaround — hiding
   columns 1 and 2 — meant phone visitors saw a third of the social proof and
   never knew the rest existed. Since ~80% of traffic is phones, the majority
   platform gets the honest version: unpin the frame, stack all three columns
   in normal flow, and let the page scroll itself. main.js skips the transform
   below this width so nothing fights the layout. */
@media (max-width: 1023px) {
  .proof__sticky {
    position: static;
    height: auto;
    overflow: visible;
    padding-bottom: clamp(3rem, 8vw, 5rem);
  }

  .proof__masonry {
    flex: none;
    min-height: 0;
  }

  .proof__col {
    transform: none !important;   /* belt-and-braces against a stale inline transform */
  }

  .proof__scroll-height {
    display: none;                /* scroll distance now comes from the content itself */
  }
}


/* ═════════════════════════════════════════════
   SECTION 6 — CINEMATIC CARE CARD
   ═════════════════════════════════════════════ */
.care {
  position: relative;
  z-index: 1;
  width: 100%;
  height: 85svh;
  min-height: 550px;
  overflow: hidden;
  background: var(--charcoal);
}

/* --- Stage: Full-bleed background image --- */
.care__bg {
  position: absolute;
  inset: 0;
  z-index: 1;
}

.care__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  /* Breathing hover: slow zoom on card hover */
  transition: transform 1.5s var(--ease-smooth);
}

/* Directional gradient for card readability - darken right side where card is */
.care__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to left, rgba(42, 42, 42, 0.7), rgba(42, 42, 42, 0.1));
  pointer-events: none;
}

/* --- Floating Glass Card --- */
.care__card {
  /* Mobile: bottom-center */
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: 5%;
  transform: translateX(-50%);
  width: 90%;
  max-width: 400px;
  padding: 2rem;

  /* Material Physics */
  background: var(--glass);
  backdrop-filter: var(--glass-blur-md);
  -webkit-backdrop-filter: var(--glass-blur-md);
  border: 1px solid var(--glass-border-color);
  border-radius: 16px;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);

  /* Breathing hover */
  transition: transform 0.6s var(--ease-smooth), box-shadow 0.6s var(--ease-smooth);
}

/* Breathing effect: card scales + bg zooms */
.care__card:hover {
  transform: translateX(-50%) scale(1.02);
  box-shadow: 0 24px 50px rgba(0, 0, 0, 0.2);
}

.care__card:hover~.care__bg .care__img,
.care:has(.care__card:hover) .care__img {
  transform: scale(1.05);
}

/* --- Typography --- */
.care__eyebrow {
  display: block;
  font-family: 'Lato', sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sage-green);
  margin-bottom: 1rem;
}

.care__title {
  font-family: var(--font-serif);
  font-size: clamp(1.5rem, 3vw, 2.5rem);
  color: var(--cream);
  margin-bottom: 1.5rem;
  line-height: 1.15;
}

.care__body {
  font-family: 'Lato', sans-serif;
  font-size: 1rem;
  color: rgba(253, 252, 248, 0.85);
  line-height: 1.7;
  margin-bottom: 0;
}

.care__body--signature {
  margin-top: 1.2rem;
  font-family: 'Playfair Display', serif;
  font-style: italic;
  font-size: 1.05rem;
  color: rgba(253, 252, 248, 0.95);
}

.care__link {
  color: var(--cream);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-color: var(--sage-green);
  text-underline-offset: 3px;
  transition: color 0.3s var(--ease-smooth);
}

.care__link:hover {
  color: var(--sage-green);
}

.care__footnote {
  display: block;
  margin-top: 2rem;
  font-family: 'Lato', sans-serif;
  font-size: 0.75rem;
  font-style: italic;
  color: rgba(253, 252, 248, 0.55);
}

/* Desktop: Card floats center-right */
@media (min-width: 1024px) {
  .care__card {
    /* Override mobile positioning */
    left: auto;
    bottom: auto;
    transform: translateY(-50%);
    right: 15%;
    top: 50%;
    width: 400px;
    padding: 3rem;
  }

  .care__card:hover {
    transform: translateY(-50%) scale(1.02);
  }
}


/* ═════════════════════════════════════════════
   SECTION 7 — FOOTER
   ═════════════════════════════════════════════ */
/* ═══════════════════════════════════════════════
   SECTION — THE PRACTICE LIBRARY (Waitlist)
   ═══════════════════════════════════════════════ */
/* Theme matched to .moc-lib (menu-of-care.css:880) — the "If this isn't your
   door" section on the protocol pages. Same blurred photographic field, same
   warm veil, same cream glass panel. The two sections make the same offer, so
   they should read as the same place. Raise --practice-library-veil before touching
   anything else if the photograph starts competing for attention. */
.practice-library {
  --practice-library-veil: 0.62;
  position: relative;
  z-index: 1;
  isolation: isolate;
  /* 0.75x the section unit — a quieter closing invitation. */
  padding: calc(var(--rhythm-unit) * 0.75) var(--gutter);
  background: var(--cream);
  border-top: 1px solid rgba(44, 44, 44, 0.08);
  text-align: left;
  overflow: hidden;
}

/* Mobile-first: portrait crop. Inset bleed + scale keeps the blur from
   showing a soft edge where the image ends. */
.practice-library::before {
  content: '';
  position: absolute;
  inset: -60px;
  z-index: -2;
  background-image: url('PageWiseAssets_rs/LibrarySectionBackground-portrait.jpg');
  background-size: cover;
  background-position: center;
  filter: blur(16px) saturate(0.9) brightness(1.28);
  transform: scale(1.05);
}

/* Warm veil, not a flat one. A single cream wash over this photograph lands
   cool grey — the source is dark and blue-toned, and cool grey is the one
   neutral the palette rules out. The gradient carries a warm sand mid-stop
   so the field stays on the cream/taupe axis. (menu-of-care.css:904) */
.practice-library::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    160deg,
    rgba(249, 248, 242, calc(var(--practice-library-veil) + 0.14)) 0%,
    rgba(238, 229, 213, calc(var(--practice-library-veil) - 0.04)) 52%,
    rgba(249, 248, 242, calc(var(--practice-library-veil) + 0.10)) 100%
  );
}

@media (min-width: 768px) {
  .practice-library::before {
    background-image: url('PageWiseAssets_rs/LibrarySectionBackground-wide.jpg');
  }
}

/* The glass panel — o-p-e-n.com spec from SKILL_01 section 4. */
.practice-library__inner {
  position: relative;
  z-index: 2;
  max-width: 640px;
  margin: 0 auto;
  padding: clamp(1.75rem, 5vw, 3.25rem);
  background: rgba(249, 248, 242, 0.72);
  backdrop-filter: var(--glass-blur-lg) saturate(1.1);
  -webkit-backdrop-filter: var(--glass-blur-lg) saturate(1.1);
  border: 1px solid rgba(44, 44, 44, 0.10);
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(44, 44, 44, 0.10);
  opacity: 0;
  /* Opacity-only arrival. The old rule translated 30px, and translating an
     element that owns a backdrop-filter re-rasterises the blur every frame
     — visibly cheap on a mid-range phone. (menu-of-care.css:940) */
  transition: opacity 1s var(--ease-smooth);
}

.practice-library__inner.is-visible {
  opacity: 1;
}

.practice-library__eyebrow {
  display: block;
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-tag);
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--charcoal);
  opacity: 0.7;
  /* Reduced margin */
  margin-bottom: 0.75rem;
}

.practice-library__title {
  font-family: 'Playfair Display', serif;
  font-size: clamp(2.2rem, 4vw + 1rem, 3.5rem);
  font-weight: 400;
  color: var(--charcoal);
  /* Reduced margin */
  margin-bottom: 0.5rem;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.practice-library__body {
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-body);
  font-weight: 300;
  color: var(--charcoal);
  /* 1.6 is the mandated body line-height (core directives section 3); this
     rule predated that and read looser than the .moc-lib block it now matches. */
  line-height: 1.6;
  max-width: 46ch;
  margin: 0 0 1.5rem;
  opacity: 0.85;
}








/* Library CTA replaced the practice-library form — same pill, rendered as a link */
.practice-library__action {
  display: flex;
  justify-content: flex-start;
  margin-top: 2.25rem;
}

/* The action row is a flex container with the default justify-content, so a
   single child sits hard left. Measured on a 375px iPhone: button 45→244
   inside a 45→330 row. Centred below the two-column threshold, where the row
   only ever holds this one button. */
@media (max-width: 1023px) {
  .practice-library__action {
    justify-content: center;
  }
}





@media (max-width: 500px) {



}


/* ═════════════════════════════════════════════
   FOOTER — THE ONLY DEFINITION. Do not copy this block.
   ═════════════════════════════════════════════
   The footer markup is copy-pasted into all 11 pages, so its CSS is the one
   thing holding them together. Every per-page stylesheet loads AFTER this
   file at equal specificity, which means any `.footer` / `.footer__*` rule
   in about.css, faq.css, library.css, offerings.css, privacy-policy.css,
   nsr-protocol.css, soft-cycle.css, menu-of-care.css or
   foundation-session.css silently wins — and drifts the moment this file
   changes. faq.css and privacy-policy.css both did exactly that and shipped
   a broken 3-column grid for a 4-column footer; both were deleted 2026-08-07.

   The rule, in one line: a per-page stylesheet may never contain a BARE
   .footer / .footer__* selector. Two sanctioned ways to vary the footer:

   1. Override a TOKEN (preferred — no selector at all):
        --footer-rule        mobile column hairline
        --footer-legal-ink   legal-link colour on dark backgrounds
      If a page needs something these can't express, add a new token HERE.

   2. Page-scoped, COLOUR-ONLY overrides, e.g. `.nsr-page .footer__heading`.
      nsr-protocol.css does this for the one footer rendered on charcoal.
      Scoped means it can't leak; colour-only means it can't drift the layout
      out from under this file. Never put grid, sizing, spacing or display
      properties in a page-scoped override — put them here.

   Grep before you ship:
     grep -n '\.footer' *.css | grep -v '^style.css:'
   As of 2026-08-07 that returns nothing but comments and nsr-protocol.css's
   seven .nsr-page colour rules. Anything else is the bug described above. */
.footer {
  /* max-width folded in from a second, stray `.footer` rule that sat ~1600
     lines above this one — 2026-08-05. */
  max-width: 100%;
  position: relative;
  z-index: 2;
  background: var(--cream);
  /* Bottom tracks the top at half its value instead of sitting at a flat 2rem.
     Unchanged on phones/tablets (--rhythm-unit is 4rem there, so this still
     resolves to 2rem); at 1920 it grows 32px -> 64px, which stops the footer
     from having 4x more air above its content than below it. */
  padding: var(--rhythm-unit) var(--gutter) calc(var(--rhythm-unit) * 0.5);
  border-top: 1px solid var(--stone);
}

.footer__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2.5rem;
  max-width: var(--container, 1200px);
  margin: 0 auto;
}

.footer__logo {
  height: 72px;
  width: auto;
  border-radius: 50%;
  object-fit: contain;
  margin-bottom: 1rem;
}

.footer__heading {
  display: block;
  font-family: var(--font-serif);
  font-size: var(--fs-h3);
  margin-bottom: 0.8em;
  color: var(--charcoal);
}

.footer__text {
  font-size: var(--fs-small);
  color: rgba(42, 42, 42, 0.7);
  max-width: 30ch;
  line-height: 1.6;
}

.footer__list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.footer__list a {
  font-size: var(--fs-small);
  color: rgba(42, 42, 42, 0.65);
  position: relative;
  display: inline-block;
  transition: color 0.3s var(--ease-smooth);
}

/* Slow-exhale underline on footer links */
.footer__list a::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 1px;
  background: var(--sage-green);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.5s var(--ease-smooth);
}

.footer__list a:hover {
  color: var(--sage-green);
}

.footer__list a:hover::after {
  transform: scaleX(1);
}

.footer__bottom {
  margin-inline: auto;
  max-width: var(--measure, 68ch);
  margin-top: clamp(2rem, 4vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--stone);
  text-align: center;
  font-size: var(--fs-small);
  color: rgba(42, 42, 42, 0.67);
  letter-spacing: 0.04em;
}

/* The sitewide medical disclaimer. Was an inline style repeated on all 11
   pages (complete with a stray double semicolon); it is required copy on every
   page, so it gets a real class. */
.footer__disclaimer {
  margin-top: 0.5rem;
  font-size: 0.75rem;
  max-width: var(--measure, 68ch);
  margin-inline: auto;
}

/* Legal links. These used to sit in the Connect column, which is for
   channels (Instagram, email) — a policy document is not a channel. Small
   print under the disclaimer is the conventional home for them.
   Flex-wrap rather than inline text so the long Terms label breaks onto
   its own line cleanly on a phone instead of splitting mid-label. */
.footer__legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 0 0.75rem;
  margin-top: 0.5rem;
  /* 12px floor — see CLAUDE.md; do not shrink to match the disclaimer. */
  font-size: 0.75rem;
  /* offerings.css uppercases its whole footer-bottom block. Reset here so
     this line reads the same on all 11 pages rather than shouting on one. */
  text-transform: none;
  letter-spacing: 0.04em;
}

/* inline-flex + min-height keeps the tap target at 24px (WCAG 2.5.8 AA);
   12px text alone measures ~14px tall and fails.

   Ink comes from a variable, not a fixed value and not plain inherit.
   nsr-protocol.html renders this same footer on charcoal, so a hardcoded
   dark value disappears there; but inheriting .footer__bottom's colour
   drags in its 0.67 alpha, which lands at 3.9:1 on cream and fails AA at
   12px. The variable keeps one strong value per theme — the default below
   covers every cream footer, and .nsr-page overrides it in
   nsr-protocol.css for the dark one. */
.footer__legal a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  color: var(--footer-legal-ink, rgba(42, 42, 42, 0.92));
  border-bottom: 1px solid transparent;
  transition: border-color 0.8s var(--ease-smooth);
}

/* currentColor underline rather than a fixed accent, so hover adapts too. */
.footer__legal a:hover {
  border-bottom-color: currentColor;
}

/* Decorative only (aria-hidden) — safe to sit below text contrast. */
.footer__legal-sep {
  opacity: 0.45;
}

@media (min-width: 1024px) {
  /* Four columns since 2026-08-05: brand | Pathways | contextual | Connect.
     Below 1024px they become stacked heading/links rows (see the block near
     the end of this file), so adding a column costs one more row on a phone
     rather than squeezing the grid — which is the failure mode CLAUDE.md
     warns about for `repeat(N, 1fr)`.

     Written as ONE explicit track plus implicit auto-columns rather than a
     fixed `2fr 1fr 1fr 1fr`, so the count in the CSS can never disagree with
     the count in the markup. A hardcoded track list is exactly how faq.css
     and privacy-policy.css broke: they pinned three columns while all 11
     pages shipped four, and the fourth silently wrapped onto a second row.
     Here the brand block takes the 2fr track and every remaining .footer__col
     — however many there are — gets an equal implicit column. Add or remove a
     rung and the grid follows; nothing falls off.

     minmax(0, …) on both, not bare fr: `1fr` floors at min-content, which is
     the off-screen-column hazard in CLAUDE.md. */
  .footer__inner {
    grid-template-columns: minmax(0, 2fr);
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
  }
}


/* ═════════════════════════════════════════════
   BENEDICTION — Fixed behind all page content
   ═════════════════════════════════════════════ */

/* ── Page content wrapper — sits ON TOP of the fixed benediction ── */
.page-content {
  position: relative;
  z-index: 1;
  background: var(--cream);
}

/* Transparent spacer: height set by benediction.js to match the section */
.benediction-spacer {
  height: var(--benediction-h, 400px);
  pointer-events: none;
}

/* ─── MAGNETIC GATHER ─────────────────────────────────────────────────────
   benediction.js writes two numbers per line: --bu (opacity, arrives early)
   and --bm (the magnetic curve, 0 = dispersed, 1 = home). The per-line
   dispersion signature (--bx/--by/--br/--bl) is set once at init.

   Every default is the SETTLED state, so with no JavaScript — file missing,
   script error, reduced motion, a crawler — the shloka renders exactly as it
   does today, fully assembled. A blessing must never fail to arrive.

   No `will-change`: these are six small text blocks, and pinning layers for
   the whole page life to serve one moment at the very bottom is the trade
   this codebase has made too often already. */
.benediction__verse,
.benediction__transliteration,
.benediction__meaning {
  opacity: var(--bu, 1);
  transform:
    translate3d(
      calc(var(--bx, 0px) * (1 - var(--bm, 1))),
      calc(var(--by, 0px) * (1 - var(--bm, 1))),
      0
    )
    rotate(calc(var(--br, 0deg) * (1 - var(--bm, 1))));
  /* Layout property, animated deliberately — see the header of
     benediction.js. Guarded per line by a runtime wrap probe, and 0em for
     every line the probe rejects. */
  letter-spacing: calc(var(--bl, 0em) * (1 - var(--bm, 1)));
}

@media (prefers-reduced-motion: reduce) {
  .benediction__verse,
  .benediction__transliteration,
  .benediction__meaning {
    opacity: 1;
    transform: none;
    letter-spacing: normal;
  }
}

/* While the scroll is locked (a modal or the mobile menu is open) this is the
   ONLY element on the site with a negative z-index, and it is hidden purely
   because .page-content paints over it.

   scroll.js locks by setting `position: fixed` on <body>, and position:fixed
   always creates a stacking context — so opening or closing a modal creates
   and then destroys a stacking context on the element that parents the whole
   page. The compositor has to rebuild the layer tree at that moment. Chrome
   does it synchronously (measured: zero exposure across every frame of a full
   lock/unlock cycle, exact scroll restore) which is why Android is clean.
   WebKit does not, and iOS shows this layer for a single frame — the flash of
   Devanagari reported from an iPhone 17 Pro, caught on a 120fps recording.

   Hiding it while locked is a visual no-op: it is completely covered at that
   moment anyway. It just means there is no layer left to flash. */
body.is-scroll-locked .benediction {
  visibility: hidden;
}

/* Fixed behind everything — revealed as page-content scrolls away */
.benediction {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: -1;
  background: var(--charcoal, #2C2C2C);
  color: var(--cream, #F9F8F2);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(4rem, 8vw, 6rem) var(--gutter, 2rem);
  min-height: 50svh;
}

.benediction__inner {
  max-width: 900px;
  width: 100%;
  text-align: center;
}

/* Sanskrit verses in Devanagari — ALL bold */
.benediction__sanskrit {
  margin-bottom: clamp(2rem, 4vw, 3rem);
}

.benediction__verse {
  font-family: var(--font-indic);
  font-size: clamp(1.15rem, 2.2vw, 1.6rem);
  font-weight: 700;
  color: var(--cream);
  line-height: 1.8;
  margin: 0;
}

/* Two-column layout: transliteration (left) + meaning (right) */
.benediction__translations {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2rem;
  text-align: center;
}

.benediction__transliteration {
  font-family: 'Playfair Display', serif;
  font-size: clamp(0.8rem, 1.1vw, 0.95rem);
  font-style: italic;
  color: rgba(249, 248, 242, 0.65);
  line-height: 1.7;
  margin: 0;
}

.benediction__meaning {
  margin-inline: auto;
  max-width: var(--measure, 68ch);
  font-family: 'Lato', sans-serif;
  font-size: clamp(0.8rem, 1.1vw, 0.95rem);
  color: rgba(249, 248, 242, 0.65);
  line-height: 1.7;
  margin: 0;
}

.benediction__meaning--closing {
  margin-top: 1rem;
  font-style: italic;
  color: var(--sage-green);
}

@media (min-width: 768px) {
  .benediction__translations {
    grid-template-columns: 1fr 1fr;
    gap: clamp(2rem, 4vw, 4rem);
    text-align: left;
  }

  .benediction__col:last-child {
    text-align: right;
  }
}


/* ═══════════════════════════════════════════════
   SOMATIC REVEAL — Universal entrance animation
   ═══════════════════════════════════════════════ */

/* Soft Arch mask utility — semicircle top, flat bottom (cathedral window) */
.soft-arch {
  border-radius: 50% 50% 16px 16px / 35% 35% 0 0;
  overflow: hidden;
}

/* Elements with data-somatic-reveal start hidden, 15px below */
[data-somatic-reveal] {
  opacity: 0;
  transform: translate3d(0, 15px, 0);
  transition: opacity 0.8s var(--ease-smooth), transform 0.8s var(--ease-smooth);
}

/* Stagger support via data-somatic-delay */
[data-somatic-reveal][data-somatic-delay="1"] {
  transition-delay: 0.1s;
}

[data-somatic-reveal][data-somatic-delay="2"] {
  transition-delay: 0.2s;
}

[data-somatic-reveal][data-somatic-delay="3"] {
  transition-delay: 0.3s;
}

/* Revealed state — floats into place */
[data-somatic-reveal].is-revealed {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* ═══════════════════════════════════════════
   BRIDGE — Emotional transition between hero and content
   ═══════════════════════════════════════════ */
.bridge {
  position: relative;
  z-index: 1;
  background: var(--cream);
  text-align: center;
  /* 0.5x the section unit — a connective interlude, not a section. */
  padding: calc(var(--rhythm-unit) * 0.5) var(--gutter);
}

.bridge__text {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.1rem, 2vw + 0.3rem, 1.5rem);
  font-style: italic;
  font-weight: 400;
  color: rgba(42, 42, 42, 0.65);
  max-width: 42ch;
  margin: 0 auto;
  line-height: 1.6;
  letter-spacing: 0.01em;
}


/* ═══════════════════════════════════════════
   FOUNDER CALLOUT — Personal quote + portrait
   ═══════════════════════════════════════════ */
.founder-callout {
  background: var(--cream);
  padding: clamp(3rem, 6vw, 5rem) var(--gutter);
  border-top: 1px solid rgba(42, 42, 42, 0.06);
  border-bottom: 1px solid rgba(42, 42, 42, 0.06);
}

.founder-callout__inner {
  max-width: 900px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  gap: clamp(2rem, 4vw, 3.5rem);
}

.founder-callout__portrait {
  width: clamp(80px, 12vw, 140px);
  height: clamp(80px, 12vw, 140px);
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  box-shadow: 0 8px 30px rgba(42, 42, 42, 0.1);
}

.founder-callout__eyebrow {
  display: block;
  font-family: 'Lato', sans-serif;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage-green);
  margin-bottom: 0.75rem;
}

.founder-callout__quote {
  font-family: 'Playfair Display', serif;
  font-size: clamp(1.05rem, 1.5vw + 0.3rem, 1.35rem);
  font-style: italic;
  font-weight: 400;
  color: var(--charcoal);
  line-height: 1.6;
  margin: 0 0 0.75rem 0;
}

.founder-callout__name {
  font-family: 'Lato', sans-serif;
  font-size: 0.85rem;
  font-weight: 700;
  font-style: normal;
  letter-spacing: 0.1em;
  color: rgba(42, 42, 42, 0.5);
}

@media (max-width: 768px) {
  .founder-callout__inner {
    flex-direction: column;
    text-align: center;
  }
}


/* ═════════════════════════════════════════════
   REDUCED MOTION — authoritative, loaded by every page
   ═════════════════════════════════════════════
   Cut movement, keep arrival. The failure mode to avoid is content that
   never reveals because its reveal was animation-driven: an element stuck
   at opacity 0 is a worse bug than the motion was. So every reveal pattern
   used anywhere on the site is forced to its end state here. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0.001ms !important;
    transition-duration: 0.001ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }

  [data-somatic-reveal], [data-moc-reveal], [data-reveal],
  .sr, .reveal, .somatic-reveal, .is-visible, .is-revealed,
  .faq-item, .faq-cta__glass, .policy__section, .offerings__card,
  .validation-bullet, .sc-reveal, .moc-lib__inner,
  /* Elements whose arrival is JS-driven (GSAP/ScrollTrigger). Listed
     explicitly so a reduced-motion visitor never depends on that JS
     running to see the content — verified by scrolling each page. */
  .anchor, .mirror__item, .philosophy__text, .philosophy__block,
  .architecture__intro, .timeline__phase, .pricing-card,
  .starting__header, .starting__card, .proof__title,
  .care__eyebrow, .care__title, .practice-library__inner, .practice-library__eyebrow, .practice-library__title,
  .lineage__content, .offerings-hero__body, .offerings-library__body,
  .sc-bento__card, .sc-acc, .sc-preview__micro, .sc-guide__quote,
  .sc-promise__item, .sc-faq__title {
    opacity: 1 !important;
    transform: none !important;
    visibility: visible !important;
    clip-path: none !important;
  }

  /* Final safety net. Some reveals are driven from JS on elements with no
     distinctive class (surya utility classes, a bare <p> on soft-cycle), so
     they cannot be enumerated. Scoped to readable text inside main: never
     leave a reduced-motion visitor with invisible copy. Decorative fades
     (.proof__blur, ghost numerals) are spans and stay untouched. */
  main :is(h1, h2, h3, h4, p, li, blockquote, cite) {
    opacity: 1 !important;
    transform: none !important;
  }
}

/* ═════════════════════════════════════════════
   FOCUS — visible keyboard affordance sitewide
   ═════════════════════════════════════════════ */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--sage-deep, #5A6457);
  outline-offset: 3px;
  border-radius: 4px;
}

/* On charcoal surfaces the deep sage disappears — use the on-dark sage. */
[data-nav-theme="dark"] a:focus-visible,
[data-nav-theme="dark"] button:focus-visible,
.benediction a:focus-visible,
.nav-pill a:focus-visible,
.nav-pill button:focus-visible,
.nav-mobile a:focus-visible {
  outline-color: var(--sage-green, #8A9A90);
}


/* ─── FOOTER — mobile distribution ─────────────────────────────────────────
   Everything stacked hard left and left two thirds of the width empty. Below
   the 3-column threshold each block now runs edge to edge — heading on one
   side, its links opposite — while the brand block and the legal strip stay
   centred, so the footer reads as composed rather than as a list that ran out
   of room. Desktop is untouched: the 1024px grid already fills its width. */
@media (max-width: 1023px) {
  .footer__inner {
    gap: 1.75rem;
  }

  /* Brand block (logo + name + tagline) — centred */
  .footer__col:first-child {
    text-align: center;
  }

  .footer__col:first-child .footer__logo {
    margin-inline: auto;
  }

  .footer__col:first-child .footer__text {
    margin-inline: auto;
    max-width: 30ch;
  }

  /* Link blocks — heading one side, links the other.
     These used to carry two extra selector variants: bare `<div>`s (library.html
     shipped its columns unclassed) and .offerings-footer__* (offerings.html had
     a parallel class tree). Both pages now use .footer__col like everywhere
     else, so the variants are gone — 2026-08-05. */
  .footer__col:not(:first-child) {
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: start;
    column-gap: 1.5rem;
    padding-block: 0.75rem;
    /* Tokenised: nsr-protocol renders this same footer on charcoal, where a
       hardcoded charcoal hairline is invisible. The page overrides the token
       rather than the rule. */
    border-top: 1px solid var(--footer-rule, rgba(42, 42, 42, 0.14));
  }

  .footer__col:not(:first-child) .footer__heading {
    grid-column: 1;
    margin-bottom: 0;
  }

  .footer__col:not(:first-child) .footer__list {
    grid-column: 2;
    text-align: right;
    justify-self: end;
  }
}

/* The Instagram link is an inline <svg> followed by a bare text node. Once the
   list became right-aligned in a narrow column the two could break apart, so
   on some pages the icon sat on its own line above the word. inline-flex binds
   them into one unbreakable unit, and the row is reversed back to normal
   ordering so the icon always leads. */
.footer__list a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}

.footer__list a > svg {
  flex-shrink: 0;
  vertical-align: middle;
  margin-right: 0;
}



/* ─── "EXPLORE THE LIBRARY" — one gentle button, five pages ───────────────
   index · offerings · nsr-protocol · soft-cycle-landing · surya-namaskar.

   Was inconsistent per page: index and offerings rendered a solid terracotta
   pill, while nsr / soft-cycle / surya rendered a quiet underlined text link.
   Same destination, same offer, three different weights.

   OUTLINED, not filled, and that is deliberate. On the protocol pages this
   block is explicitly a downsell — its own markup comment says it "must stay
   visually quieter than everything above it" — and a filled pill would
   compete with the purchase CTA a few hundred pixels above. An outline reads
   unmistakably as a control while still yielding to it.

   NOTE — this rule was accidentally deleted on 2026-08-07 and restored the
   same day. It had been grouped with .waitlist__btn, and the sweep that
   removed the dead waitlist form CSS matched the whole selector list. The
   grouping is gone now: this rule stands alone so a future cleanup of some
   neighbouring class cannot take the site's shared button with it. */
.lib-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 52px;
  padding: 0.95rem 2rem;
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-small, 0.9rem);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-decoration: none;
  white-space: nowrap;
  color: var(--dark-rust, #5C4033);

  /* OPAQUE fill, not transparent — this is what makes it read as a control.
     All five of these sections put the button on a blurred photograph under a
     warm veil whose alpha runs 0.58-0.76, so 24-42% of the photo shows
     through. A transparent button inherited whatever happened to be behind
     it, which is why it looked fine on some pages and dissolved on others.
     Filled, its interior is the same cream everywhere and the shape reads on
     its own before the border is even considered.

     Cream rather than terracotta on purpose. On the protocol pages this block
     is a downsell — its markup says it "must stay visually quieter than
     everything above it" — and a filled rust pill would compete with the
     purchase CTA a few hundred pixels up. A cream pill is unmistakably a
     button and still defers. */
  background: var(--cream, #F9F8F2);

  /* 0.65, raised from 0.42 on 2026-08-07. Measured: the old value gave the
     boundary 2.11:1 against cream, under the 3:1 that WCAG 1.4.11 asks of a
     UI component boundary, and 2.03:1 over the lightest part of the photo.
     0.65 gives 3.53:1 on cream — comfortably over, without going so dark that
     the button starts shouting. */
  border: 1.5px solid rgba(92, 64, 51, 0.65);
  border-radius: 999px;

  /* Warm-tinted, never grey: shadows on this site are rust at low alpha, so
     they read as depth in a warm room rather than as a drop shadow. Two
     layers — a tight one for the edge, a wide one for the lift. */
  box-shadow: 0 1px 2px rgba(92, 64, 51, 0.07),
              0 6px 16px rgba(92, 64, 51, 0.06);
  cursor: pointer;
  transition: background 0.8s var(--ease-smooth),
              border-color 0.8s var(--ease-smooth),
              box-shadow 0.8s var(--ease-smooth),
              transform 0.8s var(--ease-smooth);
}

/* Hover: warms rather than brightens. The fill picks up a little sand, the
   border goes to full rust (8.83:1), and the whole thing lifts 2px on the
   somatic curve. Opaque tint, not a translucent wash — a wash would let the
   photograph back in and undo the point of the fill. */
.lib-cta:hover {
  background: #F3EEE7;
  border-color: var(--dark-rust, #5C4033);
  box-shadow: 0 2px 4px rgba(92, 64, 51, 0.09),
              0 10px 24px rgba(92, 64, 51, 0.08);
  transform: translate3d(0, -2px, 0);
}

/* Press. Settles back to the resting plane and pulls the shadow in, so the
   button feels like it takes weight. Faster than the 0.8s entrance easing —
   a press should answer immediately even on a slow site. */
.lib-cta:active {
  transform: translate3d(0, 0, 0);
  box-shadow: 0 1px 2px rgba(92, 64, 51, 0.10);
  transition-duration: 0.12s;
}

.lib-cta:focus-visible {
  outline: 2px solid var(--dark-rust, #5C4033);
  outline-offset: 3px;
}

.lib-cta__arrow {
  flex-shrink: 0;
  transition: transform 0.8s var(--ease-smooth);
}

.lib-cta:hover .lib-cta__arrow {
  transform: translate3d(3px, 0, 0);
}

@media (prefers-reduced-motion: reduce) {
  .lib-cta:hover,
  .lib-cta:hover .lib-cta__arrow { transform: none; }
}


/* ═══════════════════════════════════════════════════
   SHORT VIEWPORT — a phone held in landscape
   ═══════════════════════════════════════════════════
   THE canonical explanation. Page stylesheets carry their own small block for
   their own hero; they point here rather than repeat this.

   Keyed to HEIGHT, and deliberately not to width. A landscape phone is
   812-932px wide, so it clears every `min-width: 768px` breakpoint on this
   site and is already served the tablet layout — one built assuming ~1024px of
   height, on a device that has 375-430px. Giving landscape "more desktop" is
   the cause of the problem, not the cure.

   Two things were wrong before 2026-08-07:

   1. Every hero VSL is sized by WIDTH, with aspect-ratio: 16/9. Landscape has
      width to spare and no height, so a 16:9 box sized to the available width
      is taller than the screen once width passes ~667px. Measured on
      nsr-protocol at 812x375: the video rendered 731x411 inside a 375px
      viewport, with 9% of it on screen. Every hero on every common landscape
      phone was over by 20-67px. Capping width against svh lets HEIGHT drive
      the size; aspect-ratio then derives the width, so the ratio never breaks.

   2. min-height: 100svh, plus clamp() floors. A clamp FLOOR does not shrink:
      clamp(6rem, 14svh, 8rem) resolves to 96px at 375px tall, not 52px. So the
      vertical padding stayed desktop-sized on a screen a third the height.

   Scope note: `orientation: landscape` alone is not enough — an iPad in
   landscape is 1024x768 and wants none of this. The max-height is what makes
   it mean "phone". Portrait phones never match (they are 812px tall), and no
   laptop does either (720px tall clears it comfortably).

   Honest limit: this does not make the hero fit one landscape screen. The
   headline still pushes it past the fold. It makes the VIDEO fit, which is the
   thing someone rotates their phone for. A true single-screen landscape hero
   needs a side-by-side layout — a design change, not a media query. */
@media (max-height: 480px) and (orientation: landscape) {
  /* Homepage hero. ONLY the min-height floor comes off.
     `height: 100svh` stays, and `height: auto` is not an option here: this
     hero's children are absolutely positioned (.hero__bg and the content
     layer), so with auto there is nothing in flow to size against and the
     section collapses — measured at 40px, i.e. its padding and nothing else.
     Padding is left alone for the same reason: it does not place anything.
     The floor was the whole bug — 100svh resolves to 375px on a landscape
     phone, and min-height: 500px then forced 125px of overflow. */
  .hero {
    min-height: 0;
  }
}
