/* ═══════════════════════════════════════════════════════════
   MENU OF CARE — CREAM-CANVAS · SOLID-MATERIAL ARCHITECTURE
   YogNeeti · Somatic Wellness

   MOBILE-FIRST (min-width breakpoints)

   Variable Harmony:
     --cream       → #F9F8F2  (defined on all pages)
     --charcoal    → #2C2C2C  (matched to existing pages)
     --sage        → #8A9A90  (matched to existing pages)
     --dark-rust   → #5C4033  (MOC-only, with fallback)
     --f-serif     → Cormorant Garamond (matched to existing pages)
     --f-sans      → Lato (matched to existing pages)

   Laws:
     ✓ Background is --cream, NOT dark
     ✓ ZERO hover movement (no scale, no translateY)
     ✓ Inverted typography: Titles massive, prices secondary
     ✓ Massive internal padding (2rem mobile → 3rem desktop)
     ✓ Flex column + margin-top:auto for CTAs
     ✓ GPU acceleration on interactive elements
     ✓ Somatic easing: 0.8s cubic-bezier(0.2, 0.8, 0.2, 1)
   ═══════════════════════════════════════════════════════════ */

:root {
  --moc-ease: cubic-bezier(0.2, 0.8, 0.2, 1);
  --moc-dur: 0.8s;
}


/* ─── SR-ONLY ─── */
.moc-sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}


/* ─── SCROLL REVEAL ─── */
[data-moc-reveal] {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity var(--moc-dur) var(--moc-ease),
              transform var(--moc-dur) var(--moc-ease);
}
[data-moc-reveal].moc-revealed {
  opacity: 1;
  transform: translateY(0);
}
[data-moc-delay="1"] { transition-delay: 0.1s; }
[data-moc-delay="2"] { transition-delay: 0.25s; }
[data-moc-delay="3"] { transition-delay: 0.4s; }


/* ─── PRICE BLOCK: CSS GRID STACK (zero layout thrash) ─── */
.moc-card__price-block {
  display: grid;
  grid-template-rows: 1fr;
  margin-bottom: 1rem;
}
.price-full,
.price-monthly {
  grid-area: 1 / 1;
  transition: opacity 0.4s var(--moc-ease);
}
.price-monthly {
  display: flex;
  align-items: baseline;
  gap: 0.3em;
  opacity: 0;
  pointer-events: none;
  user-select: none;
}


/* ═══════════════════════════════════════════════
   SECTION — Seamless cream canvas
   ═══════════════════════════════════════════════ */
.moc-section {
  background: var(--cream, #F9F8F2);
  padding: clamp(4rem, 8vw, 8rem) clamp(1.25rem, 5vw, 4rem);
  position: relative;
}

.moc-section__inner {
  max-width: 1200px;
  margin: 0 auto;
}


/* ═══════════════════════════════════════════════
   HEADER
   ═══════════════════════════════════════════════ */
.moc-header {
  text-align: center;
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

.moc-eyebrow {
  display: block;
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(0.75rem, 0.7vw, 0.75rem);
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage-deep, #5A6457);
  margin-bottom: 0.75rem;
}

.moc-title {
  font-family: var(--f-serif, 'Cormorant Garamond', serif);
  font-size: clamp(2rem, 5vw + 0.5rem, 3.5rem);
  font-weight: 400;
  color: var(--charcoal, #2C2C2C);
  line-height: 1.15;
}
.moc-title em {
  font-style: italic;
  color: var(--sage, #8A9A90);
}


/* ═══════════════════════════════════════════════
   TOGGLE — Carved into the cream page
   ═══════════════════════════════════════════════ */
.moc-toggle-wrap {
  display: flex;
  justify-content: center;
  margin-bottom: clamp(3rem, 5vw, 4.5rem);
}

.moc-toggle {
  display: inline-flex;
  position: relative;
  padding: 4px;
  border-radius: 50px;
  background: rgba(0, 0, 0, 0.05);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1);
  transform: translateZ(0);
  will-change: opacity, transform;
}

/* The sliding white frosted pill */
.moc-toggle__slider {
  position: absolute;
  top: 4px; bottom: 4px;
  left: 4px;
  width: 80px;
  border-radius: 50px;
  background: #FFFFFF;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  pointer-events: none;
  transition: left var(--moc-dur) var(--moc-ease),
              width var(--moc-dur) var(--moc-ease);
  will-change: left, width;
  transform: translateZ(0);
}

.moc-toggle__btn {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border: none;
  background: transparent;
  padding: 0.65rem 1.4rem;
  border-radius: 50px;
  color: rgba(42, 42, 42, 0.4);
  cursor: pointer;
  transition: color 0.4s var(--moc-ease);
  white-space: nowrap;
  position: relative;
  z-index: 1;
  min-height: 48px;
  display: flex;
  align-items: center;
}
/* Both labels are `white-space: nowrap`, so at 375px the pair measures ~370px
   inside a 335px column and the toggle spills past its container. Tightening
   the horizontal padding and tracking buys back ~30px, which is enough — and
   keeps the 48px min-height that makes it a comfortable touch target. */
@media (max-width: 480px) {
  .moc-toggle__btn {
    padding-left: 0.9rem;
    padding-right: 0.9rem;
    letter-spacing: 0.06em;
  }
}

.moc-toggle__btn.is-active {
  color: var(--charcoal, #2C2C2C);
}


/* ═══════════════════════════════════════════════
   CARDS — Mobile stack (default), desktop grid
   ═══════════════════════════════════════════════ */
.moc-cards {
  display: flex;
  flex-direction: column;
  gap: 4rem;
}


/* ─── CARD WRAPPER ─── */
.moc-card-wrap {
  position: relative;
}


/* ─── THE BADGE ─── */
.moc-card__badge {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  white-space: nowrap;
  z-index: 5;
  padding: 0.45rem 1.5rem;
  border-radius: 999px;
  background: var(--charcoal, #2C2C2C);
  color: var(--cream, #F9F8F2);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
}


/* ═══════════════════════════════════════════════
   THE CARD — Solid material, flexbox column
   ═══════════════════════════════════════════════ */
.moc-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 20px;
  overflow: hidden;
  transform: translateZ(0);
  will-change: opacity, transform;
  /* ONLY hover: soft shadow bloom. ZERO movement. */
  transition: box-shadow var(--moc-dur) var(--moc-ease),
              opacity 0.4s var(--moc-ease);
}


/* ─── CARD VARIANT: LIGHT (T1) ─── */
.moc-card--light {
  background: #FFFFFF;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
}
.moc-card--light:hover {
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.1);
}
.moc-card--light .moc-card__tier,
.moc-card--light .moc-card__name,
.moc-card--light .price-full,
.moc-card--light .price-monthly {
  color: var(--charcoal, #2C2C2C);
}
.moc-card--light .moc-card__desc,
.moc-card--light .moc-card__features li {
  color: rgba(42, 42, 42, 0.7);
}
.moc-card--light .feat-icon {
  color: var(--sage, #8A9A90);
}


/* ─── CARD VARIANT: SAGE (T2 HERO) ─── */
.moc-card--sage {
  /* Deepened from #8A9A90. Cream on that sage measured 2.78 — the whole
     card failed AA, including the price. Same on-cream/on-dark sage split
     as foundation-session.css; this value matches it. */
  background-color: var(--sage-deep, #5A6457) !important;
  color: #F9F8F2 !important;
  box-shadow: 0 20px 40px rgba(90, 100, 87, 0.25) !important;
}
.moc-card--sage:hover {
  box-shadow: 0 24px 56px rgba(90, 100, 87, 0.35) !important;
}
.moc-card--sage .moc-card__tier,
.moc-card--sage .moc-card__name,
.moc-card--sage .price-full,
.moc-card--sage .price-monthly {
  color: var(--cream, #F9F8F2);
}
.moc-card--sage .moc-card__desc,
.moc-card--sage .moc-card__features li {
  color: rgba(249, 248, 242, 0.9);
}
.moc-card--sage .moc-card__desc em {
  color: var(--cream, #F9F8F2);
  font-style: italic;
}
.moc-card--sage .feat-icon {
  color: rgba(249, 248, 242, 0.5);
}


/* ─── CARD VARIANT: DARK (T3 VIP) ─── */
.moc-card--dark {
  background: var(--charcoal, #2C2C2C);
  border: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1);
}
.moc-card--dark:hover {
  box-shadow: 0 8px 40px rgba(0, 0, 0, 0.18);
}
.moc-card--dark .moc-card__tier,
.moc-card--dark .moc-card__name,
.moc-card--dark .price-full,
.moc-card--dark .price-monthly {
  color: var(--cream, #F9F8F2);
}
.moc-card--dark .moc-card__desc,
.moc-card--dark .moc-card__features li {
  color: rgba(249, 248, 242, 0.6);
}
.moc-card--dark .feat-icon {
  color: rgba(249, 248, 242, 0.35);
}


/* ─── MEDIA WINDOW (top of card — 60% height) ─── */
.moc-card__media {
  width: 100%;
  aspect-ratio: 16 / 5.4;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 16px 16px 0 0;
  /* Default: soft sage wash — aesthetic glass pane */
  background: rgba(138, 154, 144, 0.15);
}
.moc-card__media--sage {
  background: rgba(249, 248, 242, 0.12);
}
.moc-card__media--dark {
  background: rgba(255, 255, 255, 0.04);
}

.moc-card__media-label {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: center;
  color: rgba(42, 42, 42, 0.25);
}
.moc-card--sage .moc-card__media-label,
.moc-card--dark .moc-card__media-label {
  color: rgba(249, 248, 242, 0.25);
}


/* ─── CARD BODY ─── */
.moc-card__body {
  padding: 2rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}

.moc-card__tier {
  display: block;
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.5;
  margin-bottom: 0.6rem;
}

/* INVERTED HIERARCHY: Title is massive — the focal point */
.moc-card__name {
  font-family: var(--f-serif, 'Cormorant Garamond', serif);
  font-size: clamp(2.5rem, 4vw, 3.5rem) !important;
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin-bottom: 0.75rem;
  color: inherit;
}

/* Price is SECONDARY — clean, smaller */
.price-full,
.price-monthly {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(1.25rem, 2vw, 1.5rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.01em;
}

.mo-text {
  font-size: 0.8rem;
  opacity: 0.7;
  font-weight: 400;
  margin-left: 0.15em;
}

.moc-card__desc {
  max-width: var(--measure, 68ch);
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(0.88rem, 1vw, 0.95rem);
  line-height: 1.65;
  margin-bottom: 1.25rem;
}


/* ─── MODAL TRIGGER ──────────────────────────────────────────────────────
   Secondary control: it opens the "what's also included" dialog, so it must
   read as tappable at rest without competing with .moc-card__cta below it.

   It used to be dim italic underlined text at 0.55 alpha — on a phone, where
   there is no hover to reveal it, that read as a caption rather than a
   control and went unnoticed. It is now a bordered chip: the same 14px-radius
   family and sans face as the primary CTA, but sentence case, lighter weight,
   a hairline border and a barely-there ground — subordinate by contrast and
   size, not by hiding. Resting state carries the whole affordance; hover only
   deepens what is already visible. */
/* The label used to end in a literal "↗" (U+2197). That codepoint has emoji
   presentation by default, so iOS rendered it as a colour emoji sitting inside
   an otherwise monochrome control — reported from an iPhone 2026-08-05. Every
   other arrow on the site is "→" (U+2192), which has no emoji form, which is
   why this was the only one that broke. Replaced with an inline SVG so the
   glyph can never be substituted by a platform font again. */
.modal-trigger__arrow {
  flex-shrink: 0;
  transition: transform 0.4s var(--moc-ease);
}

.modal-trigger:hover .modal-trigger__arrow {
  transform: translate3d(2px, -2px, 0);
}

@media (prefers-reduced-motion: reduce) {
  .modal-trigger:hover .modal-trigger__arrow { transform: none; }
}

.modal-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  max-width: 100%;
  cursor: pointer;
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1.4;
  padding: 0.7rem 1.1rem;
  min-height: 44px;
  margin: 0 0 1.25rem;
  text-align: left;
  text-wrap: balance; /* keeps the ↗ from orphaning onto its own line */
  text-decoration: none;
  border-radius: 14px;
  background: rgba(42, 42, 42, 0.045);
  border: 1px solid rgba(42, 42, 42, 0.28);
  color: rgba(42, 42, 42, 0.9);
  transition: background 0.4s var(--moc-ease),
              border-color 0.4s var(--moc-ease),
              color 0.4s var(--moc-ease),
              box-shadow var(--moc-dur) var(--moc-ease);
}
.modal-trigger:hover {
  background: rgba(42, 42, 42, 0.075);
  border-color: rgba(42, 42, 42, 0.5);
  color: var(--charcoal, #2C2C2C);
  box-shadow: 0 4px 18px rgba(42, 42, 42, 0.07);
}
.modal-trigger:focus-visible {
  outline: 2px solid var(--charcoal, #2C2C2C);
  outline-offset: 3px;
}

/* Light variant (on sage/dark cards) */
.modal-trigger--light,
.moc-card--sage .modal-trigger,
.moc-card--dark .modal-trigger {
  background: rgba(249, 248, 242, 0.09);
  border-color: rgba(249, 248, 242, 0.42);
  color: rgba(249, 248, 242, 0.95);
}
.modal-trigger--light:hover,
.moc-card--sage .modal-trigger:hover,
.moc-card--dark .modal-trigger:hover {
  background: rgba(249, 248, 242, 0.16);
  border-color: rgba(249, 248, 242, 0.68);
  color: var(--cream, #F9F8F2);
  box-shadow: 0 4px 18px rgba(249, 248, 242, 0.08);
}
.modal-trigger--light:focus-visible,
.moc-card--sage .modal-trigger:focus-visible,
.moc-card--dark .modal-trigger:focus-visible {
  outline: 2px solid var(--cream, #F9F8F2);
  outline-offset: 3px;
}


/* ─── FEATURES LIST ─── */
.moc-card__features {
  list-style: none;
  padding: 0;
  margin: 0 0 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.moc-card__features li {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(0.82rem, 0.9vw, 0.88rem);
  line-height: 1.5;
}
.feat-icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  margin-top: 2px;
}

/* ─── HIGHLIGHTED FEATURE ───────────────────────────────────────────────
   The live 1-to-1 sessions are what actually separate this tier from the
   self-paced ones, so the line naming them gets full-strength ink and a
   tinted ground instead of sitting at the same recessed alpha as the rest
   of the list. Negative inline margin equal to the padding keeps the icon
   on the same optical line as its neighbours while the tint bleeds wider. */
.moc-card__features li.is-highlighted {
  padding: 0.6rem 0.7rem;
  margin-inline: -0.7rem;
  background: rgba(143, 163, 150, 0.16);
  border-radius: 12px;
  font-weight: 600;
}

/* Specificity has to beat `.moc-card--dark .moc-card__features li`, which
   otherwise recesses this to 0.6 alpha like every other row. */
.moc-card--dark .moc-card__features li.is-highlighted,
.moc-card--sage .moc-card__features li.is-highlighted,
.moc-card--light .moc-card__features li.is-highlighted {
  color: var(--cream, #F9F8F2);
}

.moc-card--light .moc-card__features li.is-highlighted {
  color: var(--charcoal, #2C2C2C);
  background: rgba(90, 100, 87, 0.14);
}

.moc-card--dark .moc-card__features li.is-highlighted .feat-icon,
.moc-card--sage .moc-card__features li.is-highlighted .feat-icon {
  color: var(--sage-lifted, #A9BAB0);
}


/* ─── CTA BUTTONS ─── */
.moc-card__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 52px;
  padding: 0.9rem 1.5rem;
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 14px;
  cursor: pointer;
  margin-top: auto;
  transition: box-shadow var(--moc-dur) var(--moc-ease),
              background 0.4s var(--moc-ease),
              border-color 0.4s var(--moc-ease);
  transform: translateZ(0);
  will-change: opacity, transform;
}

/* Ghost dark — on white card */
.moc-cta--ghost-dark {
  background: transparent;
  border: 1.5px solid var(--charcoal, #2C2C2C);
  color: var(--charcoal, #2C2C2C);
}
.moc-cta--ghost-dark:hover {
  background: rgba(42, 42, 42, 0.04);
  box-shadow: 0 4px 20px rgba(42, 42, 42, 0.08);
}

/* Solid dark — on sage card */
.moc-cta--solid-dark {
  background: var(--charcoal, #2C2C2C);
  border: 1.5px solid var(--charcoal, #2C2C2C);
  color: var(--cream, #F9F8F2);
}
.moc-cta--solid-dark:hover {
  box-shadow: 0 4px 20px rgba(42, 42, 42, 0.2);
}

/* Ghost light — on dark card */
.moc-cta--ghost-light {
  background: transparent;
  border: 1.5px solid rgba(249, 248, 242, 0.3);
  color: var(--cream, #F9F8F2);
}
.moc-cta--ghost-light:hover {
  border-color: rgba(249, 248, 242, 0.5);
  box-shadow: 0 4px 20px rgba(249, 248, 242, 0.06);
}


/* ─── T3 DIMMING ─── */
.moc-card--dimmed {
  opacity: 0.4;
  pointer-events: none;
}


/* ═══════════════════════════════════════════════
   INCLUDED WITH EVERY PLAN
   Sits directly under the pricing cards — the Community Circle
   applies to all three tiers, so it gets its own beat instead of
   living inside the guarantee footer, where it read as a footnote
   to the refund policy and got missed.
   ═══════════════════════════════════════════════ */
.moc-included {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  width: fit-content;
  max-width: calc(100% - 2rem);
  margin: 3.5rem auto 0;
  padding: 0.9rem 1.75rem;
  border-radius: 999px;
  background: rgba(138, 154, 144, 0.14);
  border: 1px solid rgba(138, 154, 144, 0.32);
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(0.85rem, 1vw, 0.95rem);
  font-weight: 500;
  color: var(--sage-deep, #5A6457);
  line-height: 1.4;
  text-align: center;
}
.moc-included__icon {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  opacity: 0.9;
}


/* ═══════════════════════════════════════════════
   GUARANTEE FOOTER
   ═══════════════════════════════════════════════ */
.moc-guarantee {
  text-align: center;
  max-width: 700px;
  margin: 8svh auto 0;
  padding: 0 1rem;
}

.moc-guarantee__icon {
  width: 44px;
  height: 44px;
  color: var(--charcoal, #2C2C2C);
  opacity: 0.35;
  margin: 0 auto 1.5rem;
  display: block;
}

.moc-guarantee__headline {
  font-family: var(--f-serif, 'Cormorant Garamond', serif);
  font-size: clamp(1.25rem, 2.5vw, 1.75rem);
  font-weight: 400;
  color: var(--charcoal, #2C2C2C);
  line-height: 1.3;
  margin-bottom: 1.5rem;
}

.moc-guarantee__body {
  margin-inline: auto;
  max-width: var(--measure, 68ch);
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(0.88rem, 1vw, 0.95rem);
  color: var(--charcoal, #2C2C2C);
  opacity: 0.8;
  line-height: 1.8;
  margin-bottom: 1.25rem;
}

/* ═══════════════════════════════════════════════
   DESKTOP GRID — min-width: 1024px (Mobile-First)
   ═══════════════════════════════════════════════ */
@media (min-width: 1024px) {
  .moc-cards {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 2rem;
    align-items: stretch;
  }

  .moc-card__body {
    padding: 3rem;
  }

  /* Hero Pop — Card 2 scales up to break the flat plane.
     Applied to the CARD, not the wrap, to avoid transform
     collision with the scroll-reveal translateY on the wrap. */
  .moc-card-wrap--hero {
    z-index: 2;
    position: relative;
  }
  .moc-card-wrap--hero .moc-card {
    transform: scale(1.05);
    transform-origin: center center;
  }

  .moc-card-wrap:has(.moc-card--dimmed) {
    pointer-events: none;
  }
}


/* ═══════════════════════════════════════════════
   MODAL — iOS BOTTOM SHEET (Mobile-First)
   ═══════════════════════════════════════════════ */

/* Overlay */
/* The close used to flash a dark band across the lower half of the screen.
   Measured frame by frame: the overlay's opacity transition ended at 524ms and
   cleanup un-fixed <body> at 527ms — but the panel's transform ran to 624ms,
   so the page was relaid out and the scroll position restored while this
   element still owned a live backdrop-filter layer. A backdrop sampler being
   torn down mid-relayout is exactly when iOS paints an unsampled (black)
   frame.

   Three changes, all here rather than in JS:
     · durations matched to the panel's 0.6s, so nothing outlives anything else
     · backdrop-filter and will-change scoped to .is-open — they were permanent,
       which pinned six composited layers per page (three overlays, three
       panels) with a live backdrop sampler on each, for the whole page life
     · content-visibility while closed so the subtree costs nothing at rest */
.moc-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 9999;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  background: rgba(42, 42, 42, 0.4);
  transition: opacity 0.6s var(--moc-ease), visibility 0.6s;
  /* Stays on the base rule DELIBERATELY. It was briefly scoped to .is-open on
     2026-08-05 and that caused a worse artefact than the one it was chasing:
     removing the class drops the blur in a single frame while this element is
     still at full opacity, so for the rest of the 0.6s fade the page shows
     sharply through a 40% dark wash. Reported as "just black on NSR, half
     green half black on soft cycle" — that is the dark tier-3 card, and the
     sage tier-2 card beside it, seen unblurred through the scrim.
     backdrop-filter cannot be transitioned away cleanly either, since blur(24px)
     does not interpolate to `none`. Leave it on. */
  backdrop-filter: var(--glass-blur-lg);
  -webkit-backdrop-filter: var(--glass-blur-lg);
}
.moc-modal-overlay.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  /* will-change STAYS scoped — unlike backdrop-filter it has no visual effect,
     so promoting only while open is a pure win. Unconditionally it pinned six
     composited layers per page for the whole page life. */
  will-change: opacity;
}

/* Body lock */
body.moc-modal-open {
  overflow: hidden;
}
/* The position-fixed half of the lock moved into scroll.js (2026-08-05) so
   there is one implementation instead of four. Left as overflow:hidden only —
   harmless alongside it, and still correct if this stylesheet is ever used
   without the controller. */

/* Panel — MOBILE: bottom sheet */
.moc-modal-panel {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  transform: translateY(100%);
  height: 90svh;
  background: var(--cream, #F9F8F2);
  border-radius: 24px 24px 0 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: transform 0.6s var(--moc-ease);
  box-shadow: 0 -8px 40px rgba(0, 0, 0, 0.15);
}

/* Promoted only while the sheet is actually moving — see the overlay note. */
.moc-modal-overlay.is-open .moc-modal-panel {
  will-change: transform;
}
.moc-modal-overlay.is-open .moc-modal-panel {
  transform: translateY(0);
}

/* Close button — 44×44 min */
.moc-modal-close {
  position: sticky;
  top: 0;
  align-self: flex-end;
  z-index: 10;
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  border-radius: 50%;
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(42, 42, 42, 0.06);
  margin: 0.75rem 0.75rem 0 0;
  flex-shrink: 0;
  transition: background 0.3s var(--moc-ease);
}
.moc-modal-close svg {
  width: 18px; height: 18px;
  color: var(--charcoal, #2C2C2C);
}
.moc-modal-close:hover {
  background: rgba(42, 42, 42, 0.12);
}

/* Scroll area */
.moc-modal-scroll {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
}

/* Lenis/Locomotive scroll-lock shield — prevents global smooth-scroller
   from consuming wheel events that originate inside the modal panel */
.moc-modal-overlay,
.moc-modal-panel,
.moc-modal-scroll {
  overscroll-behavior: contain;
}

/* Hero placeholder inside modal */
.moc-modal__hero {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: rgba(138, 154, 144, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  /* Anchors the absolutely-positioned iframe vsl-embed.js injects here.
     Without it the video would position against the nearest positioned
     ancestor — the modal panel — and overflow the 16:9 box. */
  position: relative;
}
.moc-modal__hero .moc-card__media-label {
  color: rgba(42, 42, 42, 0.2);
}

/* Modal content */
.moc-modal__content {
  padding: 2rem;
}

.moc-modal__eyebrow {
  display: block;
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--sage-deep, #5A6457);
  margin-bottom: 0.6rem;
}

.moc-modal__headline {
  font-family: var(--f-serif, 'Cormorant Garamond', serif);
  font-size: clamp(1.35rem, 3vw, 1.75rem);
  font-weight: 400;
  color: var(--charcoal, #2C2C2C);
  line-height: 1.25;
  margin-bottom: 0.6rem;
}

.moc-modal__subhead {
  max-width: var(--measure, 68ch);
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: clamp(0.85rem, 1vw, 0.92rem);
  color: rgba(42, 42, 42, 0.7);
  line-height: 1.6;
  margin-bottom: 2rem;
}

/* Feature grid — 1 col mobile */
.moc-modal__features {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

.moc-modal__feat {
  padding: 1.25rem;
  border-radius: 16px;
  background: rgba(138, 154, 144, 0.06);
  border: 1px solid rgba(42, 42, 42, 0.05);
}

.moc-modal__feat-icon {
  width: 26px; height: 26px;
  color: var(--sage, #8A9A90);
  margin-bottom: 0.6rem;
  margin-top: 4px;
  flex-shrink: 0;
}

.moc-modal__feat-title {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--charcoal, #2C2C2C);
  margin-bottom: 0.3rem;
}

.moc-modal__feat-body {
  max-width: var(--measure, 68ch);
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.82rem;
  color: rgba(42, 42, 42, 0.7);
  line-height: 1.55;
}

/* Modal CTA bars removed — modals are pure "Quick Look" informational sheets.
   Checkout happens on the card CTAs which respect the active toggle state. */


/* ═══════════════════════════════════════════════
   DESKTOP MODAL — Centered float (min-width)
   ═══════════════════════════════════════════════ */
@media (min-width: 768px) {
  .moc-modal-panel {
    position: absolute;
    bottom: auto;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%) translateY(40px);
    width: 92%;
    max-width: 800px;
    height: auto;
    max-height: 85svh;
    border-radius: 24px;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.15);
  }
  .moc-modal-overlay.is-open .moc-modal-panel {
    transform: translate(-50%, -50%) translateY(0);
  }

  .moc-modal__content {
    padding: 2.5rem;
  }

  .moc-modal__features {
    grid-template-columns: 1fr 1fr;
    gap: 1.5rem;
  }


}


/* ═══════════════════════════════════════════════
   ALSO HERE — THE PRACTICE LIBRARY
   Quiet downsell. Loaded only on the three protocol pages.

   Placement law: this block sits AFTER the pricing chooser and
   AFTER the FAQ, so the protocol has already been read, priced,
   and defended before the Library is named at all.

   Weight laws — this must stay quieter than the protocol's own offer:
     ✓ No filled button. A text link only. Filled rust CTAs stay
       reserved for the protocol, and that hierarchy is what protects it.
     ✓ $49 is never set beside the protocol price.
     ✓ Framed as a different door, not a cheaper one.

   The photograph is ATMOSPHERE, not a hero image: blurred to texture
   and veiled with cream so it reads as warmth behind glass rather than
   as a picture competing for attention. If it ever starts reading as a
   second hero, raise --moc-lib-veil before touching anything else.
   ═══════════════════════════════════════════════ */

.moc-lib {
  --moc-lib-veil: 0.62;
  position: relative;
  isolation: isolate;
  background: var(--cream, #F9F8F2);
  border-top: 1px solid rgba(44, 44, 44, 0.08);
  padding: clamp(5rem, 12svh, 9rem) clamp(1.25rem, 5vw, 4rem);
  overflow: hidden;
}

/* Mobile-first: portrait crop. Inset bleed + scale keeps the blur from
   showing a soft edge where the image ends. */
.moc-lib::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. */
.moc-lib::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    160deg,
    rgba(249, 248, 242, calc(var(--moc-lib-veil) + 0.14)) 0%,
    rgba(238, 229, 213, calc(var(--moc-lib-veil) - 0.04)) 52%,
    rgba(249, 248, 242, calc(var(--moc-lib-veil) + 0.10)) 100%
  );
}

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

/* The glass panel — o-p-e-n.com spec from SKILL_01 §4. */
.moc-lib__inner {
  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-only arrival. The inherited reveal translates 24px, and
   translating an element that owns a backdrop-filter re-rasterises the
   blur every frame — visibly cheap on a mid-range phone. */
.moc-lib__inner[data-moc-reveal] {
  transform: none;
}

/* 12px floor — the sitewide eyebrows render 9.3–11.5px and are
   unreadable on a phone. Do not shrink this one to match them. */
.moc-lib__eyebrow {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(44, 44, 44, 0.78);
  margin: 0 0 1.5rem;
}

.moc-lib__title {
  font-family: var(--f-serif, 'Cormorant Garamond', serif);
  font-size: clamp(1.9rem, 4.5vw, 3rem);
  font-weight: 300;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--charcoal, #2C2C2C);
  margin: 0 0 1.5rem;
}

.moc-lib__body {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 1rem;
  line-height: 1.6;
  color: rgba(44, 44, 44, 0.85);
  max-width: 46ch;
  margin: 0 0 2.5rem;
}

/* Text link, hairline rule — never a filled button.
   inline-flex + min-height keeps the tap target at 44px (WCAG 2.5.8),
   but the rule belongs on the label, not on the 44px box — otherwise it
   floats ~20px under the type and reads as an unrelated divider. */
/* .moc-lib__link / __label / __arrow removed 2026-08-05. This block's CTA now
   uses the shared .lib-cta in style.css, so the same control renders on all
   five pages that offer the Library instead of a text link here and a filled
   terracotta pill on index and offerings. */

.moc-lib__terms {
  font-family: var(--f-sans, 'Lato', sans-serif);
  font-size: 0.8125rem;
  line-height: 1.6;
  color: rgba(44, 44, 44, 0.78);
  max-width: 44ch;
  margin: 2rem 0 0;
}

/* Content must still arrive when motion is off — the reveal starts
   at opacity 0, so this has to override, not just shorten. */
@media (prefers-reduced-motion: reduce) {
  .moc-lib__inner[data-moc-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .moc-lib__label,
  .moc-lib__arrow {
    transition: none;
  }
}
