/* ═══════════════════════════════════════════════════════════
   CMS — section template styles (Prompt 6)
   Classes used by /sections/{type}.php templates that aren't
   already covered by home.css. Extends existing tokens; no new
   visual language introduced.
   ═══════════════════════════════════════════════════════════ */

/* ─── Page hero (hero_simple) ───────────────────────────── */
.page-hero {
    min-height: 80vh;
    min-height: 80dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;   /* vertically centered — inner-page hero composition reads as calmer than the homepage's flex-end anchor */
    padding-block: var(--section-y-large);
    padding-top: calc(var(--section-y-large) + var(--space-16));
    position: relative;
}

.page-hero__headline {
    font-family: var(--font-display);
    font-size: clamp(2.25rem, 6vw, 4.5rem);   /* TI5A: -25% from clamp(3rem, 8vw, 6rem) — most-aggressive offender on cream */
    font-weight: 400;
    text-transform: uppercase;
    line-height: 0.92;
    letter-spacing: var(--tracking-display);
    color: var(--color-pearl);
    margin: var(--space-4) 0 var(--space-6);
    max-width: 18ch;
}

.page-hero__subtitle {
    font-family: var(--font-body);
    font-size: var(--text-lg);
    line-height: var(--leading-loose);
    color: var(--color-bone);
    max-width: 56ch;
    margin: 0;
}

.page-hero__subtitle p { margin: 0 0 var(--space-4); }
.page-hero__subtitle p:last-child { margin-bottom: 0; }

/* ─── Page hero — backdrop variant (TI5B) ──────────────────
   Optional cinematic full-bleed-photo variant for hero_simple
   when hero_image_id is set. Smaller scale than hero_photographic
   (60vh vs 80vh) — sized for inner-page heroes. Forward-compat:
   future video backdrop wraps the bg-image div with <video
   autoplay loop muted playsinline>. */
.page-hero--backdrop {
    position: relative;
    min-height: 80vh;   /* TI5D: 60vh → 80vh — matches homepage hero, consistent substantial entry */
    min-height: 80dvh;
    display: flex;
    align-items: center;
    overflow: hidden;
    isolation: isolate;
    padding: 0;
}

.page-hero--backdrop .page-hero__backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-size: cover;
    background-repeat: no-repeat;
    background-color: #0a0908;
}

.page-hero--backdrop .page-hero__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(180deg,
        rgba(11, 11, 14, 0.5) 0%,
        rgba(11, 11, 14, 0.25) 35%,
        rgba(11, 11, 14, 0.55) 70%,
        rgba(11, 11, 14, 0.85) 100%);
}

.page-hero--backdrop .page-hero__inner {
    position: relative;
    z-index: 10;
    padding-block: var(--space-20);
}

.page-hero--backdrop .page-hero__headline {
    color: var(--color-bone);           /* warm-white via scope override */
    text-shadow: 0 4px 32px rgba(0, 0, 0, 0.5);
}

.page-hero--backdrop .page-hero__subtitle {
    color: var(--color-bone);
    text-shadow: 0 2px 16px rgba(0, 0, 0, 0.4);
}

/* ─── Pull-quote attribution ────────────────────────────── */
.home-quote__attribution {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--platinum);
    margin-top: var(--space-8);
    font-style: normal;
}

/* ─── Image block ───────────────────────────────────────── */
.cms-image-block { padding-block: var(--section-y); }
.cms-image-block--bleed { padding-block: 0; }

.cms-image-block__figure {
    margin: 0;
    overflow: hidden;
    position: relative;
}

.cms-image-block__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.cms-image-block__caption {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--platinum-muted);
    margin: var(--space-4) 0 0;
    line-height: var(--leading-loose);
    max-width: 56ch;
}

/* ─── CMS gallery grid (alternative layout) ─────────────── */
.cms-gallery__grid {
    margin-top: var(--space-10);
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-4);
}

@media (min-width: 880px) {
    .cms-gallery__grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

.cms-gallery__item {
    background: none;
    border: 0;
    padding: 0;
    cursor: pointer;
    overflow: hidden;
    aspect-ratio: 4 / 3;
}

.cms-gallery__item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform var(--t-slow), filter var(--t-slow);
}

.cms-gallery__item:hover img {
    transform: scale(1.04);
    filter: brightness(1.05);
}

/* ─── Rich text ─────────────────────────────────────────── */
.cms-rich-text { padding-block: var(--section-y); }

.cms-rich-text__body {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-loose);
    color: var(--color-bone);
}

.cms-rich-text__body p { margin: 0 0 var(--space-5); }
.cms-rich-text__body p:last-child { margin-bottom: 0; }

.cms-rich-text__body strong {
    color: var(--color-pearl);
    font-weight: var(--weight-semibold);
}

.cms-rich-text__body em {
    font-style: italic;
    color: var(--platinum-bright);
}

.cms-rich-text__body a {
    color: var(--platinum);
    border-bottom: 1px solid currentColor;
    padding-bottom: 1px;
    transition: color var(--t-base);
}

.cms-rich-text__body a:hover { color: var(--platinum-bright); }

/* ─── Accordion / FAQ ───────────────────────────────────── */
.cms-accordion { padding-block: var(--section-y); }

.cms-accordion__list {
    list-style: none;
    padding: 0;
    margin: var(--space-6) 0 0;   /* TI5C: 40px → 24px */
}

.cms-accordion__item { border-bottom: 1px solid var(--color-divider); }
.cms-accordion__item:first-child { border-top: 1px solid var(--color-divider); }
.cms-accordion__item details { margin: 0; }

.cms-accordion__item summary {
    list-style: none;
    cursor: pointer;
    padding: var(--space-4) 0;
    font-family: var(--font-body);
    font-size: var(--text-xl);
    font-weight: var(--weight-semibold);
    letter-spacing: normal;
    color: var(--color-pearl);
    line-height: var(--leading-snug);
    position: relative;
    padding-right: var(--space-12);
    transition: color var(--t-base);
}

.cms-accordion__item summary::-webkit-details-marker { display: none; }

.cms-accordion__item summary::after {
    content: '+';
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    font-family: var(--font-body);
    font-size: var(--text-xl);
    font-weight: var(--weight-light);
    color: var(--platinum);
    transition: transform var(--t-base), color var(--t-base);
    line-height: 1;
}

.cms-accordion__item details[open] summary::after {
    content: '\2212'; /* minus sign */
    color: var(--platinum-bright);
}

.cms-accordion__item summary:hover { color: var(--platinum-bright); }

.cms-accordion__answer {
    padding: 0 0 var(--space-6);
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-loose);
    color: var(--color-steel);
    max-width: 70ch;
}

.cms-accordion__answer p { margin: 0 0 var(--space-3); }
.cms-accordion__answer p:last-child { margin-bottom: 0; }

.cms-accordion__answer a {
    color: var(--platinum);
    border-bottom: 1px solid currentColor;
    transition: color var(--t-base);
}

.cms-accordion__answer a:hover { color: var(--platinum-bright); }

/* ─── Comparison table ──────────────────────────────────── */
.cms-comparison { padding-block: var(--section-y); }

.cms-comparison__wrap {
    margin-top: var(--space-10);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.cms-comparison__table {
    width: 100%;
    border-collapse: collapse;
    min-width: 600px;
}

.cms-comparison__table thead th {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--platinum-muted);
    padding: var(--space-4);
    text-align: left;
    border-bottom: 1px solid var(--color-divider);
}

.cms-comparison__th--us {
    color: var(--platinum-bright);
    background: var(--color-onyx-elevated);
}

.cms-comparison__table tbody th {
    font-family: var(--font-body);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--color-bone);
    padding: var(--space-4);
    text-align: left;
    border-bottom: 1px solid var(--color-divider);
}

.cms-comparison__table tbody td {
    font-family: var(--font-body);
    font-size: var(--text-base);
    color: var(--color-steel);
    padding: var(--space-4);
    border-bottom: 1px solid var(--color-divider);
}

.cms-comparison__td--us {
    color: var(--color-pearl);
    background: var(--color-onyx-elevated);
    font-weight: var(--weight-semibold);
}

.cms-comparison__tr--emphasized {
    background: rgba(197, 194, 182, 0.04);
}

/* ─── Final CTA — flat variant (no photo backdrop) ──────── */
.home-final--flat {
    background: var(--color-onyx-deep);
    min-height: auto;
    padding: var(--section-y-large) 0;
}

.home-final--flat .home-final__photo,
.home-final--flat .home-final__overlay {
    display: none;
}

/* ─── Timeline ──────────────────────────────────────────── */
.cms-timeline { padding-block: var(--section-y); }

.cms-timeline__list {
    list-style: none;
    padding: 0;
    margin: var(--space-10) 0 0;
    position: relative;
}

.cms-timeline__list::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background: var(--platinum-deep);
}

.cms-timeline__item {
    position: relative;
    padding-left: var(--space-10);
    padding-bottom: var(--space-12);
}

.cms-timeline__item::before {
    content: '';
    position: absolute;
    left: -4px;
    top: 0;
    width: 9px;
    height: 9px;
    background: var(--platinum);
    border-radius: 50%;
    box-shadow: 0 0 0 4px var(--color-onyx-deep);
}

.cms-timeline__year {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--platinum);
    margin: 0 0 var(--space-2);
}

.cms-timeline__title {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: var(--tracking-display);
    color: var(--color-pearl);
    margin: 0 0 var(--space-3);
    line-height: var(--leading-snug);
}

.cms-timeline__desc {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-loose);
    color: var(--color-bone);
    max-width: 56ch;
}

.cms-timeline__desc p { margin: 0 0 var(--space-3); }
.cms-timeline__desc p:last-child { margin-bottom: 0; }

/* ─── Divider ───────────────────────────────────────────── */
.cms-divider { padding-block: var(--space-8); }
.cms-divider--space { padding-block: var(--space-16); }

.cms-divider__hairline {
    border: 0;
    height: 1px;
    background: var(--gradient-hairline-h);
    margin: 0;
}

.cms-divider__space { height: var(--space-12); }

.cms-divider__ornament {
    display: flex;
    align-items: center;
    gap: var(--space-6);
}

.cms-divider__ornament::before,
.cms-divider__ornament::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--platinum-deep);
}

.cms-divider__ornament-label {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--platinum-muted);
}

/* ─── Video embed ───────────────────────────────────────── */
.cms-video-embed { padding-block: var(--section-y); }
.cms-video-embed--bleed { padding-block: 0; }

.cms-video-embed__wrap {
    position: relative;
    overflow: hidden;
    margin-top: var(--space-10);
    background: var(--color-onyx-deep);
}

.cms-video-embed__wrap iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

.cms-video-embed__caption {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--platinum-muted);
    margin: var(--space-4) 0 0;
    line-height: var(--leading-loose);
    max-width: 56ch;
}

/* ─── Contact form ──────────────────────────────────────── */
.cms-contact-form { padding-block: var(--section-y); }

.cms-contact-form__form {
    margin-top: var(--space-10);
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
    max-width: 560px;
}

.cms-contact-form__field {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.cms-contact-form__field label {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--platinum);
}

.cms-contact-form__field input,
.cms-contact-form__field textarea {
    font-family: var(--font-body);
    font-size: var(--text-base);
    color: var(--color-pearl);
    background: var(--color-onyx-rich);
    border: 1px solid var(--color-divider);
    padding: var(--space-3) var(--space-4);
    transition: border-color var(--t-base), background var(--t-base);
    border-radius: 0;
}

.cms-contact-form__field input:focus,
.cms-contact-form__field textarea:focus {
    outline: none;
    border-color: var(--platinum);
    background: var(--color-onyx-warm);
}

.cms-contact-form__field textarea {
    resize: vertical;
    min-height: 120px;
}

/* Honeypot — visually hidden, accessible to bots only */
.cms-contact-form__honeypot {
    position: absolute;
    left: -9999px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.cms-contact-form__form button[type="submit"] {
    align-self: flex-start;
    margin-top: var(--space-2);
}

.cms-contact-form__message {
    padding: var(--space-4) var(--space-6);
    border: 1px solid var(--platinum-muted);
    background: var(--color-onyx-elevated);
    color: var(--color-bone);
    font-family: var(--font-body);
    font-size: var(--text-base);
    margin-top: var(--space-6);
}

.cms-contact-form__message--success {
    border-color: #2d7a3d;
    color: var(--color-pearl);
}

.cms-contact-form__message--error {
    border-color: #8b3a3a;
    color: var(--color-pearl);
}

/* ═══════════════════════════════════════════════════════════
   MARKDOWN PARAGRAPH SPACING
   base.css * { margin: 0 } wipes browser-default paragraph
   margins. The rules below cover md_to_html() output for the
   container classes not already handled earlier in this file
   or in home.css. (page-hero__subtitle, cms-rich-text__body,
   cms-accordion__answer, cms-timeline__desc are already
   handled above. home-standard__body has the bottom margin
   in home.css; the :last-child override here suppresses the
   trailing gap.)
   ═══════════════════════════════════════════════════════════ */

/* Narrative body (the actually-buggy section — home.css sets
   margin-bottom but no :last-child override) */
.home-standard__body p { margin: 0 0 var(--space-6); }
.home-standard__body p:last-child { margin-bottom: 0; }

/* Pricing footnote (renders markdown via md_to_html) */
.home-pricing__footnote p { margin: 0 0 var(--space-3); }
.home-pricing__footnote p:last-child { margin-bottom: 0; }

/* ═══════════════════════════════════════════════════════════
   MIGRATED FROM home.css (CSS architecture fix — Prompt 8.5)
   These rules support section templates that may render on any
   CMS page, not just the homepage. They were originally written
   for the homepage but the patterns are now reusable.

   What stayed in home.css: .hero__title, .hero__eyebrow-line,
   .hero__scroll-cue/__scroll-line and @keyframes scrollPulse —
   these are unique to the hardcoded homepage hero. Everything
   else moved here verbatim (rules unchanged).

   Audit of /sections/*.php classes covered by what follows:
     hero_photographic → .hero, .hero__photo, .hero__overlay,
       .hero__inner, .hero__eyebrow, .hero__subtitle, .hero__actions
     narrative         → .home-standard, .home-standard__body
     pull_quote        → .home-quote* family
     banner_manifesto  → .home-banner-manifesto* family
     image_gallery     → .home-gallery* family + .lightbox* family
     quote             → .home-find-quote* family
     features_grid     → .home-features* family
     stat_strip        → .home-stat-strip* family
     equipment_strip   → .home-equipment-strip* family
     pricing_cards     → .home-pricing* family
     find_us           → .home-find* family
     cta_strip         → .home-final* family
   ═══════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════
   HERO — Photographic full-bleed (shared with the hardcoded
   homepage hero in index.php and hero_photographic.php template)
   ═══════════════════════════════════════════════════════════ */

/* ─── Hero (TI5B — full-bleed photographic cinematic) ──────
   Reverted from TI4's split-screen editorial back to the proven
   pre-inversion dark-overlay pattern. Photo bg-image full-bleed,
   dark gradient overlay, content anchored lower-left in a
   container. Text tokens flip to warm-white inside .hero via
   the TI5B scope override in tokens.css.

   Optional video backdrop: .hero__video (autoplay/loop/muted/
   playsinline) layers directly over .hero__photo using the same
   overlay + content composition. The photo stays as the poster/
   fallback (loading, phones, prefers-reduced-motion).
   ──────────────────────────────────────────────────────── */
.hero {
    position: relative;
    min-height: 100vh;
    min-height: 100dvh;   /* fills the viewport so the next section doesn't bleed in beneath */
    display: flex;
    align-items: flex-end;
    overflow: hidden;
    isolation: isolate;
    padding: 0;
}

.hero__photo {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-size: cover;
    background-repeat: no-repeat;
    background-color: #0a0908;             /* literal warm-near-black fallback (TI2 inverted --color-onyx) */
    opacity: 0;
    animation: heroPhotoFadeIn 1.2s var(--ease-out-expo) 0.1s forwards;
}

@keyframes heroPhotoFadeIn {
    from { opacity: 0; transform: scale(1.04); }
    to   { opacity: 1; transform: scale(1); }
}

/* Optional background video. Sits directly above .hero__photo so the
   photo serves as the poster/fallback underneath (while the video
   buffers, if it fails, or when hidden on phones / reduced-motion).
   Same overlay + content composition as the photo-only hero. */
.hero__video {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background-color: #0a0908;
    opacity: 0;
    animation: heroPhotoFadeIn 1.2s var(--ease-out-expo) 0.1s forwards;
}

.hero__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background:
        linear-gradient(180deg,
            rgba(11, 11, 14, 0.5) 0%,
            rgba(11, 11, 14, 0.2) 25%,
            rgba(11, 11, 14, 0.55) 65%,
            rgba(11, 11, 14, 0.92) 100%);
}

.hero__inner {
    position: relative;
    z-index: 10;
    width: 100%;
    max-width: var(--max-width);
    margin: 0 auto;
    padding-top: 0;
    padding-bottom: var(--space-24);
    padding-left: max(var(--gutter), env(safe-area-inset-left));
    padding-right: max(var(--gutter), env(safe-area-inset-right));
}

@media (min-width: 880px) {
    .hero__inner {
        padding-bottom: var(--space-32);
    }
}

.hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-medium);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--chrome);
    margin: 0 0 var(--space-6);
    opacity: 0;
    transform: translateY(20px);
    animation: heroContentRise 0.9s var(--ease-out-expo) 0.4s forwards;
}

.hero__eyebrow::before {
    content: '';
    display: inline-block;
    width: 36px;
    height: 1px;
    background: var(--chrome);
    flex-shrink: 0;
}

.hero__headline {
    font-family: var(--font-display);
    font-size: clamp(2rem, 5vw, 4.25rem);   /* TI5A reduced */
    font-weight: 400;
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    text-transform: none;
    color: var(--color-bone);                /* resolves warm-white inside .hero via scope override */
    margin: 0 0 var(--space-6);
    max-width: 18ch;
    text-shadow: 0 4px 32px rgba(0, 0, 0, 0.5);
}

.hero__subtitle {
    font-family: var(--font-body);
    font-size: var(--text-lg);
    font-weight: var(--weight-regular);
    color: var(--color-bone);                /* warm-white via scope override */
    max-width: 44ch;
    margin: 0 0 var(--space-8);
    line-height: var(--leading-loose);
    text-shadow: 0 2px 16px rgba(0, 0, 0, 0.4);
    opacity: 0;
    transform: translateY(20px);
    animation: heroContentRise 0.9s var(--ease-out-expo) 0.7s forwards;
}

.hero__actions {
    display: flex;
    gap: var(--space-4);
    flex-wrap: wrap;
    opacity: 0;
    transform: translateY(20px);
    animation: heroContentRise 0.9s var(--ease-out-expo) 0.85s forwards;
}

@keyframes heroContentRise {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (max-width: 768px) {
    .hero__headline {
        font-size: clamp(1.75rem, 5vh, 3rem);
    }
}

@media (prefers-reduced-motion: reduce) {
    .hero__photo,
    .hero__eyebrow,
    .hero__subtitle,
    .hero__actions {
        opacity: 1;
        transform: none;
        animation: none;
    }
    /* Honor reduced-motion: drop the autoplaying video, show the
       still poster photo instead. */
    .hero__video {
        display: none;
    }
}

/* ════════════════════════════════════════════════════════════════
   HERO SIZE MODIFIERS — 3-mode system

   The default .hero rules above lock the section to 100vh, which is
   right for the homepage entry point but pins every other page to
   a full-viewport wall before the visitor sees actual content.
   These modifier classes give the operator (per-section, in admin)
   three behaviors:

     .hero--size-full       Default. 100vh photographic — homepage only.
     .hero--size-compact    ~360px photographic band. Brand-rich inner
                            pages where the imagery earns its space
                            (About, Day Pass, Join).
     .hero--size-editorial  No photo. Tight text-on-cream header
                            (~200px). Directory pages where content
                            below is the value (Trainers, Pricing,
                            Contact, Members).

   .hero--size-full is intentionally a no-op — it just lets us emit
   the class unconditionally for analytics/debugging without affecting
   the at-rest cascade. The historical .hero rules govern its sizing.
   ════════════════════════════════════════════════════════════════ */

/* ─── Compact mode ──────────────────────────────────────────── */
.hero.hero--size-compact {
    min-height: 360px;
    max-height: 440px;
    align-items: center;
}
.hero.hero--size-compact .hero__inner {
    padding-top: var(--space-10);
    padding-bottom: var(--space-10);
}
.hero.hero--size-compact .hero__headline {
    font-size: clamp(1.75rem, 4vw, 3rem);
    margin-bottom: var(--space-4);
}
.hero.hero--size-compact .hero__subtitle {
    margin-bottom: var(--space-6);
    font-size: var(--text-base);
}
.hero.hero--size-compact .hero__actions {
    margin-bottom: 0;
}
.hero.hero--size-compact .hero__photo,
.hero.hero--size-compact .hero__video {
    /* The 1.04→1 scale-in is dramatic at full viewport; cut it
       at compact size since the motion reads as a glitch when the
       container is small. Still respects reduced-motion below. */
    animation: none;
    opacity: 1;
}
@media (max-width: 768px) {
    .hero.hero--size-compact {
        min-height: 240px;
        max-height: 320px;
    }
    .hero.hero--size-compact .hero__inner {
        padding-top: var(--space-6);
        padding-bottom: var(--space-6);
    }
}

/* ─── Editorial mode ───────────────────────────────────────────
   No photographic background, no overlay. Text sits on the page's
   cream surface, so the dark-token-scope inherited from .hero
   (which makes color-bone resolve to warm-light for legibility on
   dark imagery) is reverted here so the headline reads as warm
   near-black on cream.
   ──────────────────────────────────────────────────────────── */
.hero.hero--size-editorial {
    min-height: 0;
    padding: var(--space-10) 0 var(--space-6);
    background: transparent;
    isolation: auto;
    align-items: flex-start;
    overflow: visible;
}
.hero.hero--size-editorial .hero__inner {
    padding-top: 0;
    padding-bottom: 0;
}
/* Animation timings retired — entrance polish for a 200px header
   reads as nervous compared to the simple presence we want. Content
   appears at rest. */
.hero.hero--size-editorial .hero__eyebrow,
.hero.hero--size-editorial .hero__subtitle,
.hero.hero--size-editorial .hero__actions {
    opacity: 1;
    transform: none;
    animation: none;
}
.hero.hero--size-editorial .hero__eyebrow {
    color: #555048;                /* warm body gray — readable on cream */
}
.hero.hero--size-editorial .hero__eyebrow::before {
    background: #555048;
}
.hero.hero--size-editorial .hero__headline {
    color: #2A2521;                /* warm near-black for display text */
    text-shadow: none;
    font-size: clamp(2rem, 4.5vw, 3.5rem);
    max-width: 24ch;
}
.hero.hero--size-editorial .hero__subtitle {
    color: #555048;
    text-shadow: none;
    max-width: 56ch;
    margin-bottom: 0;
    font-size: var(--text-base);
    line-height: var(--leading-loose);
}
.hero.hero--size-editorial .hero__actions {
    margin-top: var(--space-6);
}
@media (max-width: 768px) {
    .hero.hero--size-editorial {
        padding: var(--space-8) 0 var(--space-4);
    }
    .hero.hero--size-editorial .hero__headline {
        font-size: clamp(1.75rem, 7vw, 2.5rem);
    }
}

/* ── Mobile hero redesign (Moment 1 — Arrival).
      Inverts the previous center-aligned mobile layout to a
      left-aligned asymmetric composition: generous top breathing
      room, stacked wordmark in display type, primary filled CTA
      with secondary as a quiet text link, status pill bottom-left
      and a small scroll-cue bottom-right.

      All rules scoped to the 768px breakpoint (foundation
      convention). Desktop (>768px) renders the original
      composition unchanged. ─────────────────────────────── */
@media (max-width: 768px) {
    .hero {
        /* Override the desktop bottom-anchored layout so the chrome
           row can sit at the visual bottom while the wordmark cluster
           lives in the middle third.

           Height cascade — most-conservative wins on supporting
           browsers so the chrome row is always inside the visible
           viewport (svh = smallest viewport, computed with browser
           chrome visible; dvh dynamic; vh static fallback):
              100vh   — always-supported fallback
              100dvh  — Safari 15.4+ / Chrome 108+ (dynamic)
              100svh  — same support, always = visible viewport
           Polish pass: chrome row was falling below the fold on
           devices with persistent URL bars because 100dvh measured
           from the unhidden state. 100svh anchors chrome to the
           smallest visible area. */
        align-items: stretch;
        min-height: 100vh;
        min-height: 100dvh;
        min-height: 100svh;
    }
    .hero__inner {
        /* Asymmetric, left-aligned. Top padding uses max() so the
           eyebrow has comfortable breathing room from the fixed
           nav on shorter viewports (iPhone SE 375×667) while
           scaling up for taller phones. The 5.5rem floor (88px)
           catches anything ≤ ~575vh — below that, 16vh would drop
           under the comfort threshold. Target: eyebrow sits at
           ~16% from viewport top across all common mobile
           viewports (15-18% goal). */
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        text-align: left;
        padding-top: max(16vh, 5.5rem);
        /* Bottom padding clears the fixed .mobile-bottom-nav (which is
           ~70px tall and overlays the bottom of the viewport on mobile —
           see components.css `body { padding-bottom: 70px }` at the
           768px breakpoint). Without this, the chrome row sits behind
           the bottom nav. The literal 70px matches the body offset; if
           that value ever changes, update both. var(--space-6) adds
           breathing room between the chrome row and the bottom nav. */
        padding-bottom: calc(70px + var(--space-6));
        /* Override the desktop gutter (which uses --gutter ≈ 15px at
           375vp) with one notch more breathing room from the left
           edge. env(safe-area-inset-left) still wins on notched
           devices when it exceeds --space-6. */
        padding-left: max(var(--space-6), env(safe-area-inset-left));
    }
    .hero__eyebrow {
        /* Drop the desktop ::before line for cleaner left-aligned chrome.
           Color upgraded from the desktop --chrome (muted gray) to
           warm-white with slight transparency — readable against the
           dark video backdrop without competing with the wordmark. */
        justify-content: flex-start;
        margin: 0 0 var(--space-4);
        color: var(--color-bone);
        opacity: 0.85;
    }
    .hero__eyebrow::before {
        display: none;
    }
    .hero__headline {
        /* Wordmark scale — restrained. Dropped from
           clamp(3.5rem, 14vw, 5.5rem) in polish round 3 because the
           larger range crowded the rest of the composition. New
           range still anchors the page as the dominant visual but
           leaves body + CTAs + chrome their proper share of the
           composition.
           Resolves: 375vp → 44px (floor), 414vp → 44px (floor),
           500vp → 50px, 640vp → 64px (ceiling reached). */
        font-size: clamp(2.75rem, 10vw, 4rem);
        line-height: 0.92;
        letter-spacing: -0.02em;
        max-width: none;
        margin: 0 0 var(--space-5);
    }
    .hero__subtitle {
        max-width: 28ch;
        /* Slightly more space (one token-notch up from --space-6) so
           the body line has visual breathing room before the CTA
           cluster — reads as a separate moment, not crowded against
           the buttons. */
        margin: 0 0 var(--space-8);
        margin-left: 0;
        margin-right: 0;
        font-size: var(--text-base);
        line-height: var(--leading-normal);
    }

    /* CTA hierarchy: primary filled + sized to content; secondary
       as a quiet text link with a trailing arrow. Stacked vertically. */
    .hero__actions {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-2);
        justify-content: flex-start;
    }
    .hero__actions .btn--primary {
        /* Override the 480px-and-below stretch rule (which makes both
           CTAs full-width). Primary stays sized to content. Vertical
           padding bumped from --space-3 to --space-4 in the polish
           pass — gives the button more presence and read-weight as
           the page's primary action. */
        width: auto;
        max-width: none;
        padding: var(--space-4) var(--space-6);
    }
    .hero__actions .btn:not(.btn--primary) {
        /* Restyle the secondary CTA as a quiet text link. Strip the
           button chrome; render as inline-flex with an arrow appended
           via ::after so the operator-edited label stays clean.

           Polish round 2 — subordinate the secondary to the primary:
           • Drop font-size from --text-sm to --text-xs (12px) so it
             reads visibly smaller than the primary CTA's label
           • Tighten letter-spacing from --tracking-wider to
             --tracking-wide so it loses the loud "tracked-out chrome"
             presence that was competing with the primary
           • margin-left: --space-3 indents it 12px right of the
             primary's left edge — proximity says "still grouped as
             one CTA cluster" but the offset says "not at the same
             priority"
           • Lower opacity from 0.85 to 0.75 so it sits one more
             notch behind the primary visually */
        background: transparent;
        border: 0;
        color: var(--color-bone);
        padding: var(--space-2) 0;
        margin-left: var(--space-3);
        font-family: var(--font-body);
        font-size: var(--text-xs);
        font-weight: var(--weight-semibold);
        letter-spacing: var(--tracking-wide);
        text-transform: uppercase;
        text-decoration: none;
        width: auto;
        max-width: none;
        min-height: 0;
        opacity: 0.75;
    }
    .hero__actions .btn:not(.btn--primary)::after {
        content: ' →';
        margin-left: var(--space-1);
        transition: transform var(--t-base);
        display: inline-block;
    }
    .hero__actions .btn:not(.btn--primary):hover::after {
        transform: translateX(2px);
    }

    /* Mobile video framing — shift the crop's vertical anchor from
       50% (center, default) to 30% (top-biased). On a tall portrait
       mobile viewport, object-fit:cover with a landscape source
       crops heavily off the left and right sides; biasing toward
       the top of the source frame reveals more of the equipment +
       atmospheric context that typically sits in the upper portion
       of fitness videos, less of the floor (which is less
       interesting in a thin vertical slice). Educated starting
       value — may benefit from a small post-deploy tweak (e.g.,
       "70% 30%" for right+top bias) once the actual crop is
       observed on the live site. Single-property change makes it
       trivial to iterate.

       Scoped to .hero__video only. The companion .hero__photo is a
       background-image div with admin-set focal point (focal_x /
       focal_y from the photo row, applied inline) — overriding its
       background-position here would clash with the operator's
       choice. The photo is only visible while the video buffers or
       in prefers-reduced-motion mode; its focal point already
       represents the operator's intentional framing. */
    .hero__video {
        object-position: 50% 30%;
    }

    /* Chrome row — status pill left, scroll cue right. Pushed to
       bottom of the flex column via margin-top:auto. */
    .hero__chrome {
        display: flex;
        align-items: flex-end;
        justify-content: space-between;
        width: 100%;
        margin-top: auto;
        padding-top: var(--space-8);
        padding-bottom: max(var(--space-4), env(safe-area-inset-bottom));
        gap: var(--space-4);
    }
}

/* Chrome is mobile-only. Hide on desktop via the default scope so
   it never appears at >768px. (The 768px media query above only
   adjusts layout; the default hide here keeps the chrome out of
   desktop rendering entirely.) */
.hero__chrome {
    display: none;
}
@media (max-width: 768px) {
    .hero__chrome { display: flex; }
}

/* Scroll cue — small chevron-down at the bottom-right of the hero
   chrome row. Subtle vertical bounce; fades as the user scrolls
   (fade managed by main.js setting --hero-cue-opacity). Clickable
   <a> smooth-scrolls to the next section via JS handler. */
.hero__scroll-cue {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    color: var(--color-bone);
    text-decoration: none;
    opacity: var(--hero-cue-opacity, 0.8);
    transition: opacity var(--t-smooth), transform var(--t-smooth);
    animation: heroCueBounce 2.4s var(--ease-out-quint) infinite;
    -webkit-tap-highlight-color: transparent;
}
.hero__scroll-cue:hover {
    opacity: 1;
    transform: translateY(2px);
}
.hero__scroll-cue svg {
    width: 24px;
    height: 24px;
    display: block;
    filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.35));
}

@keyframes heroCueBounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(4px); }
}

@media (prefers-reduced-motion: reduce) {
    .hero__scroll-cue {
        animation: none;
    }
}

/* Status pill — on-media variant for use over the dark video
   backdrop. Semi-transparent dark bg + warm-white text + subtle
   blur for legibility. Reusable: Moment 5 (Place) will also use
   this modifier when it gets a media backdrop. */
.status-pill--on-media {
    color: var(--color-bone);              /* warm white via hero scope override */
    background: rgba(8, 7, 6, 0.55);
    border-color: rgba(250, 246, 239, 0.18);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.status-pill--on-media .status-pill__dot {
    /* Brighter rim so the warm-white dot stays vivid on dark/blurred bg. */
    box-shadow: 0 0 0 2px rgba(250, 246, 239, 0.45);
}

/* ── Narrow widths block superseded by the Moment 1 redesign.
      The previous rules here centered + stretched both CTAs full-
      width at <=480px, which conflicted with the new left-aligned
      composition (primary sized to content, secondary as text
      link). The 768px block above already handles 375px and 414px
      viewports correctly — no separate narrow-width override
      needed. Block intentionally removed; comment kept for
      archeology. (Moment 1 — Hero redesign) ───────────────── */

/* ── Short landscape (rotated phones, ~390-500px height).
      The desktop title clamp (75-90px) plus padding-bottom
      overflows these viewports. Compress the title, drop
      the padding, hide the scroll cue. ───────────────────── */
@media (max-height: 500px) and (orientation: landscape) {
    .hero__inner { padding-bottom: var(--space-8); }
    .hero__scroll-cue { display: none; }
}
@media (max-height: 500px) {
    .hero__title,
    .hero__headline {
        font-size: clamp(1.75rem, 5vh, 3rem);   /* TI5A: -14% from clamp(2rem, 6vh, 3.5rem) */
    }
}

/* ── Wide monitor (1900px+): cap hero height and center content
      so the headline doesn't read as orphaned at the bottom of a
      tall photographic area. Mid-range viewports (<1900px) keep
      the bottom-anchored composition. ─────────────────────── */
@media (min-width: 1900px) {
    .hero {
        min-height: 85vh;
        align-items: center;
    }
    .hero__inner {
        padding-bottom: 0;
    }
}

/* ═══════════════════════════════════════════════════════════
   A NEW STANDARD — narrative, type-driven, slate backdrop
   ═══════════════════════════════════════════════════════════ */
.home-standard {
    padding-block: var(--section-y);   /* TI5C: dropped from --section-y-large (was the biggest single waste in any section type) */
    position: relative;
    overflow: hidden;
}

/* Override the global .section-title for narrative sections.
   • max-width 20ch — original override (Archivo Black uppercase at display
     size + 18ch was breaking "Built on what came before." awkwardly)
   • TI5D: reduced font-size 29% from --text-4xl (clamp 2rem, 5vw, 3.5rem)
     to clamp 1.5rem, 3.5vw, 2.5rem — narrative headlines were dominating
     viewport. Substantial editorial heading, not full-viewport billboard.
   • TI5D: line-height tightened from --leading-tight (1.1) to 1.05. */
.home-standard .section-title {
    font-size: clamp(1.5rem, 3.5vw, 2.5rem);
    line-height: 1.05;
    max-width: 20ch;
}

.home-standard__body {
    margin-top: var(--space-8);
    font-family: var(--font-body);
    font-size: var(--text-lg);
    color: var(--color-bone);
    line-height: var(--leading-normal);   /* TI5C: 1.75 → 1.5 — premium editorial standard (Aesop / Tracksmith), single biggest density win for narrative */
}

.home-standard__body p {
    margin-bottom: var(--space-4);   /* TI5C: 24px → 16px between paragraphs */
    max-width: 56ch;
}

@media (min-width: 880px) {
    .home-standard__body {
        font-size: var(--text-xl);
    }
}

/* ═══════════════════════════════════════════════════════════
   PULL QUOTE — full-bleed photographic moment
   The signature copy line, isolated and amplified.
   ═══════════════════════════════════════════════════════════ */
/* ─── Pull quote (TI4 — editorial composition) ──────────────
   Photo in a 4/5 editorial frame on the left ~5fr, blockquote
   on the right ~7fr at editorial scale (3rem max, down from
   billboard 4.5rem). Mobile stacks photo (16/10 landscape)
   on top, quote below. Replaces the full-bleed billboard.
   ──────────────────────────────────────────────────────── */
.home-quote {
    padding-block: var(--section-y-large);
    background: var(--color-onyx);            /* page surface — PD2 transition handles rhythm */
}

.home-quote__composition {
    display: grid;
    grid-template-columns: 5fr 7fr;
    gap: var(--space-12);
    align-items: center;
    max-width: 1100px;
    margin-inline: auto;
}

.home-quote__photo-frame {
    margin: 0;
    aspect-ratio: 4 / 5;
    overflow: hidden;
}

.home-quote__photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 50%;
    display: block;
}

.home-quote__text {
    margin: 0;
}

.home-quote__text p {
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 3vw, 2.5rem);     /* TI5A: -17% from clamp(1.75rem, 3.5vw, 3rem) */
    font-weight: 400;
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-display);
    text-transform: none;                     /* TI4 Q4 option (b.iii) */
    color: var(--color-bone);                  /* warm-dark via token */
    margin: 0 0 var(--space-6);
}

.home-quote__attribution {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--color-steel);
    text-transform: uppercase;
    letter-spacing: var(--tracking-wider);
}

@media (max-width: 768px) {
    .home-quote__composition {
        grid-template-columns: 1fr;
        gap: var(--space-8);
    }
    .home-quote__photo-frame {
        aspect-ratio: 16 / 10;
    }
}

/* ═══════════════════════════════════════════════════════════
   THE STANDARD — three-feature grid, each paired with a photo
   ═══════════════════════════════════════════════════════════ */
.home-features {
    padding-block: var(--section-y);
    background: var(--color-onyx);
}

/* Mobile polish — tighten the section's TOP breathing room.
   --section-y clamps to 56px floor on all mobile viewports ≤~800vw,
   which read as excessive cream space between the hero boundary and
   the "THE STANDARD" eyebrow. Tightened iteratively: 56→32→20px.
   20px (--space-5) reads as deliberate section transition without
   floating the eyebrow in cream void. The hero's bottom-padding
   area (94px clearing the fixed bottom-nav) still contributes
   visible empty space above the section boundary; the section's
   own padding-top now keeps its share tight. Bottom padding stays
   at --section-y (56px) — gap to the next section is fine as-is. */
@media (max-width: 768px) {
    .home-features {
        padding-block-start: var(--space-5);
    }
}

.home-features__grid {
    list-style: none;
    padding: 0;
    margin: var(--space-16) 0 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-16);
}

@media (min-width: 880px) {
    .home-features__grid {
        grid-template-columns: repeat(3, 1fr);
        gap: var(--space-10);
    }
}

.home-features__item {
    padding-top: 0;
    border-top: 0;
    display: flex;
    flex-direction: column;
}

/* Operator photo (.home-features__media) is hidden globally after
   the icon-promotion pass. The data stays in the DB and the field
   stays in the admin form for future flexibility, but the icon is
   now the primary graphic element on both mobile and desktop.
   Rules + hover effect kept defensively in case a future iteration
   wants the photo treatment back. */
.home-features__media {
    display: none;
    width: 100%;
    aspect-ratio: 4 / 3;
    background-size: cover;
    background-position: center;
    background-color: var(--color-onyx-rich);
    margin-bottom: var(--space-6);
    filter: brightness(0.7) contrast(1.05);
    transition: filter var(--t-slow), transform var(--t-slow);
}

.home-features__item:hover .home-features__media {
    filter: brightness(0.85) contrast(1.05);
    transform: scale(1.02);
}

/* .home-features__content has no chrome of its own — the
   previous border-top + padding-top hairline was a vestige from
   when the photo sat above (separator between photo and text).
   With the icon now playing the graphic-anchor role, the
   hairline read as orphaned. Removed in the desktop polish pass. */
.home-features__name {
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 400;
    color: var(--color-bone);
    margin: 0 0 var(--space-4);
    text-transform: uppercase;
    letter-spacing: var(--tracking-display);
    line-height: var(--leading-tight);
}

.home-features__desc {
    font-size: var(--text-base);
    color: var(--color-steel);
    line-height: var(--leading-loose);
    margin: 0;
    max-width: 36ch;
}

/* Icon — primary graphic element at the top of each card.
   Promoted (from "mobile-only chrome") to "primary graphic across
   all viewports" in the polish pass that removed the redundant
   01/02/03 numbers. clamp() scales from 40px on narrow mobile up
   to 56px ceiling on tablet/desktop — substantial graphic anchor
   without theatrical scale. Muted color (--color-steel) reads as
   graphic element, not loud branding. */
.home-features__icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: clamp(2.5rem, 7vw, 3.5rem);
    height: clamp(2.5rem, 7vw, 3.5rem);
    margin: 0 0 var(--space-5);
    color: var(--color-steel);
}
.home-features__icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* Indicators stay default-hidden — mobile-only chrome. */
.home-features__indicators {
    display: none;
}

/* ─── Desktop polish (≥769px) ─────────────────────────────────
   Mobile (≤768px) gets the swipe-deck pattern in the block
   below; tablet+desktop here gets:
     • Larger icons calibrated for laptop+ widths (~48-72px)
     • Card chrome matching the mobile deck cards and Members hub
       (white-on-cream + 1px divider + two-layer subtle shadow)
       so cards read as discrete units instead of bare text columns
     • Card heights equalize automatically via grid's
       align-items: stretch — now visible because the cards have
       chrome to show the equalized box
     • Section top padding reduced from var(--section-y) (88px on
       wide viewports) to var(--space-12) (48px). Dark hero →
       cream features does enough visual work; 88px of empty cream
       above the eyebrow read as cavernous.
   ────────────────────────────────────────────────────────── */
@media (min-width: 769px) {
    .home-features {
        padding-block-start: var(--space-12);
    }

    .home-features__grid {
        gap: clamp(var(--space-8), 5vw, var(--space-16));
    }

    /* ── Editorial: no boxes. A hairline rule with the icon as a
       confident graphic anchor, copy below. Reads "designed magazine,"
       not "SaaS card." (Pillars aren't a sequence, so no numerals.) ── */
    .home-features__item {
        position: relative;
        background: none;
        border: 0;
        box-shadow: none;
        padding: var(--space-6) 0 0;
        border-top: 2px solid var(--color-divider-strong);
        transition: border-color var(--t-base);
    }

    .home-features__icon {
        width: clamp(2.75rem, 4vw, 3.5rem);
        height: clamp(2.75rem, 4vw, 3.5rem);
        margin: 0 0 var(--space-6);
        color: var(--color-bone);
        transition: transform var(--t-base);
    }

    .home-features__name {
        font-size: var(--text-xl);
        margin-bottom: var(--space-3);
    }

    /* Hover — draw the rule dark and lift the icon. */
    .home-features__item:hover { border-top-color: var(--color-pearl); }
    .home-features__item:hover .home-features__icon {
        transform: translateY(-3px);
    }

    /* Stagger the scroll reveal across the three columns. */
    .home-features__item:nth-child(2).reveal-on-scroll { transition-delay: 0.08s; }
    .home-features__item:nth-child(3).reveal-on-scroll { transition-delay: 0.16s; }
}

/* ══════════════════════════════════════════════════════════════
   Mobile swipe deck (Moment 2 — ≤768px).
   Transforms the existing .home-features__grid <ul> into a
   horizontal scroll-snap deck. Same markup; CSS handles the layout
   swap. Cards take 85% of the viewport width so the next card peeks
   at the right edge ("more to swipe" signal). Inline-SVG icon
   replaces the photo on mobile so the deck reads cleanly.
   ══════════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
    /* Icon rules now live at the default scope (visible on all
       viewports). Photo hiding also moved to the default scope.
       Only the swipe-deck transformation remains mobile-scoped. */

    /* Transform .home-features__grid from vertical stack to
       horizontal scroll-snap deck. Negative margin + matching
       padding gives a full-bleed effect so the cards extend to
       the viewport edges while the section eyebrow/headline stay
       container-aligned. */
    .home-features__grid {
        margin: var(--space-8) calc(var(--gutter) * -1) 0;
        padding: var(--space-2) var(--gutter) var(--space-3);
        display: flex;
        flex-direction: row;
        grid-template-columns: none;            /* override desktop grid template */
        gap: var(--space-4);
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        scroll-padding-left: var(--gutter);
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;                  /* Firefox */
        -ms-overflow-style: none;               /* Edge legacy */
    }
    .home-features__grid::-webkit-scrollbar {
        display: none;                          /* WebKit / Chromium */
    }

    /* Cards become deck slides. 85% viewport width so the next
       card peeks at the right edge. Soft elevation matches the
       Members hub card pattern (white-on-cream + 1px divider +
       subtle two-layer shadow). */
    .home-features__item {
        flex: 0 0 85%;
        scroll-snap-align: start;
        scroll-snap-stop: always;
        padding: var(--space-6);
        background: var(--color-onyx-rich);
        border: 1px solid var(--color-divider);
        box-shadow: 0 1px 3px rgba(8, 7, 6, 0.025),
                    0 6px 20px rgba(8, 7, 6, 0.04);
        opacity: 0.6;
        transform: scale(0.96);
        transition: opacity 0.35s var(--ease-out-expo),
                    transform 0.35s var(--ease-out-expo);
    }
    .home-features__item.is-active {
        opacity: 1;
        transform: scale(1);
    }

    /* (Content reset removed — the desktop hairline that this
       override stripped on mobile is now gone at default scope.
       Override would be a no-op.) */

    /* Indicator dots — centered below the deck. */
    .home-features__indicators {
        display: flex;
        justify-content: center;
        align-items: center;
        gap: var(--space-3);
        margin: var(--space-4) 0 0;
        padding: 0;
    }
    .home-features__dot {
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: var(--color-divider-strong);
        border: 0;
        padding: 0;
        cursor: pointer;
        transition: background 0.25s var(--ease-out-expo),
                    transform 0.25s var(--ease-out-expo);
        -webkit-tap-highlight-color: transparent;
    }
    .home-features__dot:hover,
    .home-features__dot:focus-visible {
        background: var(--color-steel-muted);
        outline: none;
    }
    .home-features__dot.is-active {
        background: var(--color-pearl);
        transform: scale(1.15);
    }
    /* Larger tap target for the visually-small dot — hit area
       expands without changing the visual circle. */
    .home-features__dot::before {
        content: '';
        position: absolute;
        inset: -10px;
    }
    .home-features__dot {
        position: relative;
    }
}

/* ═══════════════════════════════════════════════════════════
   BANNER MANIFESTO — full-bleed photo + manifesto line
   The page's second photographic moment after the hero.
   ═══════════════════════════════════════════════════════════ */
/* ─── Banner manifesto (TI4 — split-screen editorial) ───────
   Manifesto text composed on left ~45% cream surface; photo
   anchored on right ~55%. Mobile stacks text on top, photo
   (16/10) below. Replaces the full-bleed billboard.
   ──────────────────────────────────────────────────────── */
.home-banner-manifesto {
    min-height: 50vh;
    display: grid;
    grid-template-columns: 45fr 55fr;
    overflow: hidden;
    isolation: isolate;
}

.home-banner-manifesto__text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--space-16) max(var(--gutter), var(--space-12));
    background: var(--color-onyx);
}

.home-banner-manifesto__line {
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 3.5vw, 3rem);   /* TI5A: -14% from clamp(2rem, 4vw, 3.5rem) */
    font-weight: 400;
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    text-transform: none;                     /* TI4 Q4 option (b.iii) */
    color: var(--color-bone);                  /* warm-dark via token */
    max-width: 18ch;
    margin: 0;
}

.home-banner-manifesto__photo-anchor {
    position: relative;
    overflow: hidden;
    background: var(--color-onyx-warm);       /* cream-warm fallback */
}

.home-banner-manifesto__photo {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 50%;
    display: block;
}

@media (max-width: 768px) {
    .home-banner-manifesto {
        grid-template-columns: 1fr;
        min-height: auto;
    }
    .home-banner-manifesto__photo-anchor {
        aspect-ratio: 16 / 10;
    }
    .home-banner-manifesto__text {
        padding: var(--space-12) var(--gutter);
    }
}

/* ═══════════════════════════════════════════════════════════
   FOUNDING MEMBER QUOTE — testimonial moment
   Editorial treatment, restraint, hero of platinum accents.
   ═══════════════════════════════════════════════════════════ */
.home-find-quote {
    padding-block: var(--section-y-large);
    background: var(--color-onyx-elevated);
    position: relative;
}

.home-find-quote::before,
.home-find-quote::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--gradient-hairline-h);
    opacity: 0.6;
}

.home-find-quote::before { top: 0; }
.home-find-quote::after { bottom: 0; }

.home-find-quote__text {
    margin: var(--space-10) 0 0;
    padding: 0;
    position: relative;
}

.home-find-quote__text p {
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 3.5vw, 2.75rem);
    font-weight: 400;
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--color-pearl);
    margin: 0 0 var(--space-8);
    max-width: 28ch;
}

.home-find-quote__attribution {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--platinum);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
}

.home-find-quote__attribution cite {
    font-style: normal;
    font-weight: var(--weight-semibold);
    color: var(--platinum-bright);
}

.home-find-quote__attribution cite::before {
    content: '— ';
}

.home-find-quote__role {
    color: var(--platinum-muted);
}

.home-find-quote__role::before {
    content: '· ';
    color: var(--platinum-deep);
    margin-right: var(--space-2);
}

/* ═══════════════════════════════════════════════════════════
   STAT STRIP — facility by the numbers
   Four-up grid with massive display numerals + small labels.
   ═══════════════════════════════════════════════════════════ */
/* Moment 3 — By the numbers.
   Background switches from the prior cream-lifted --color-onyx-deep
   to true dark (--color-pearl). Establishes proper cream/dark
   alternation across the page (hero=dark → features=cream →
   STATS=dark → pricing=cream → place=dark → final CTA=cream).
   Numbers become the focal moment; text inverts to warm-white.
   Padding bumped to --section-y-large for "moment of pause" gravity.
   Top/bottom borders removed — the cream-vs-dark contrast IS the
   section boundary, additional borders would clutter. */
.home-stat-strip {
    padding-block: var(--section-y-large);
    /* LITERAL HEX intentional — do NOT replace with var(--color-pearl).
       The scope-flip rule in tokens.css applies to this element itself,
       which flips --color-pearl to #ffffff inside this scope. Using
       the token here would resolve the background to white (the very
       bug Moment 3 round 2 hit). Child text using var(--color-bone)
       and var(--color-pearl) DOES want the flipped warm-white values —
       that's why the scope-flip stays in tokens.css. Only this single
       background declaration needs to bypass it. */
    background: #080706;                     /* warm-true-dark (matches pre-flip --color-pearl) */
    color: var(--color-bone);                /* warm-white via scope-flip — correct for body text */
}
/* Suppress the cream-to-cream boundary hairline (defined globally
   at .home-stat-strip::before, line ~2735). The dark surface flip
   from the preceding cream features section IS the visual boundary;
   the hairline would either be invisible (warm-dark color on dark
   surface) or distracting if inverted. */
.home-stat-strip::before {
    display: none;
}

/* Eyebrow ("BY THE NUMBERS") sits on the new dark surface — invert
   colors so it reads cleanly against near-black. The ::before line
   stays but uses a warm-white tint. */
.home-stat-strip .section-label {
    color: rgba(250, 246, 239, 0.7);
}
.home-stat-strip .section-label::before {
    background: rgba(250, 246, 239, 0.35);
}

.home-stat-strip__list {
    list-style: none;
    padding: 0;
    /* Tighter column gap (was --space-6) and tighter row gap (was
       --space-10) so the four stats read as one unified moment
       rather than four separated items. */
    margin: var(--space-8) 0 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8) var(--space-5);
}

@media (min-width: 880px) {
    .home-stat-strip__list {
        grid-template-columns: repeat(4, 1fr);
        gap: var(--space-8);
    }
}

.home-stat-strip__item {
    text-align: left;
    padding-left: var(--space-4);
    /* Subtle warm-white divider on the dark surface (was platinum-
       deep which was tuned for cream background). 18% alpha gives
       the structural mark without competing with the numbers. */
    border-left: 1px solid rgba(250, 246, 239, 0.18);
}

.home-stat-strip__number {
    font-family: var(--font-display);
    /* Scaled up from clamp(2.5rem, 5vw, 4rem) — 44px floor on
       mobile hits the spec's 45-55px target; 80px ceiling gives
       the desktop "look at this number" weight. */
    font-size: clamp(2.75rem, 6vw, 5rem);
    font-weight: 400;
    color: var(--color-bone);                /* warm-white on dark */
    line-height: 1;
    letter-spacing: var(--tracking-display);
    margin: 0 0 var(--space-3);
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: var(--space-2);
}

/* The counter span itself — same display treatment as the parent
   .home-stat-strip__number, with min-width so the layout doesn't
   reflow as digits are added during the count-up animation
   (prevents the unit "/sq ft" or "/racks" from jumping mid-anim). */
.home-stat-strip__counter {
    display: inline-block;
    min-width: 1ch;
    font-variant-numeric: tabular-nums;       /* monospace digits — width-stable during count */
}

.home-stat-strip__unit {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    /* Warm-white at slight transparency — supporting role, not
       focal. The 0.7 alpha matches the eyebrow's contrast level. */
    color: rgba(250, 246, 239, 0.7);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
}

.home-stat-strip__label {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    /* Muted warm-white — the quietest layer in the stat's hierarchy
       (number > unit > label). */
    color: rgba(250, 246, 239, 0.55);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    margin: 0;
}

/* ═══════════════════════════════════════════════════════════
   EQUIPMENT STRIP — typography-based brand affiliation
   Lightweight proof section, no logos to avoid attribution issues.
   ═══════════════════════════════════════════════════════════ */
.home-equipment-strip {
    padding-block: var(--space-16);
    background: var(--color-onyx-deep);
    border-top: 1px solid var(--chrome-dim);
    border-bottom: 1px solid var(--chrome-dim);
}

.home-equipment-strip .container {
    text-align: center;
}

.home-equipment-strip__label {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--chrome);
    margin: 0 0 var(--space-6);
}

.home-equipment-strip__list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--space-12);
    font-family: var(--font-display);
    font-size: clamp(1.5rem, 3vw, 2.5rem);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: var(--tracking-display);
    color: var(--chrome-bright);
}

.home-equipment-strip__list li {
    position: relative;
}

.home-equipment-strip__list li:not(:last-child)::after {
    content: '·';
    position: absolute;
    right: calc(var(--space-12) / -2);
    top: 50%;
    transform: translate(50%, -50%);
    color: var(--chrome-muted);
    font-size: 0.7em;
}

@media (max-width: 768px) {
    .home-equipment-strip__list {
        gap: var(--space-8);
        flex-direction: row;
    }
    .home-equipment-strip__list li:not(:last-child)::after {
        right: calc(var(--space-8) / -2);
    }
}

/* ═══════════════════════════════════════════════════════════
   PRICING — two-card layout, asymmetric weight
   ═══════════════════════════════════════════════════════════ */
.home-pricing {
    padding-block: var(--section-y);
    background: var(--color-onyx-deep);
}

/* ═══════════════════════════════════════════════════════════════
   Moment 4 — Pricing toggle (tab pattern across both viewports).
   Tab nav above the cards; only the active card is visible. Inactive
   cards stay in the DOM (accessibility) but are absolutely positioned
   + faded so they don't take layout space.
   ═══════════════════════════════════════════════════════════════ */

/* Tab navigation bar — minimal, no pill chrome. Hairline accent above
   the active tab matches the eyebrow's hairline pattern from
   components.css. */
.home-pricing__tabs {
    display: flex;
    justify-content: center;
    align-items: flex-start;
    gap: var(--space-8);
    margin-top: var(--space-10);
    margin-bottom: var(--space-6);
    padding: 0;
}

/* 1-card edge case: hide the tabs entirely. Single card renders
   without a pointless "tab" above it. */
.home-pricing__tabs--single-card {
    display: none;
}

.home-pricing__tab {
    position: relative;
    background: transparent;
    border: 0;
    padding: var(--space-3) 0 0;          /* top padding leaves room for the hairline accent */
    font-family: var(--font-body);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    color: var(--color-steel-muted);
    cursor: pointer;
    transition: color 0.3s var(--ease-out-expo), opacity 0.3s var(--ease-out-expo);
    opacity: 0.7;
    -webkit-tap-highlight-color: transparent;
}

.home-pricing__tab:hover {
    color: var(--color-pearl);
    opacity: 1;
}

/* Active state — dark color + visible hairline accent above. */
.home-pricing__tab.is-active {
    color: var(--color-pearl);
    opacity: 1;
}

/* Hairline accent above active tab — 24px line centered horizontally.
   Matches the eyebrow accent pattern at components.css:182-187 (which
   uses a 32px line). Tighter here because the tab labels are shorter
   inline elements; the accent reads as "this is the chosen tab"
   without overpowering the label below. */
.home-pricing__tab.is-active::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 24px;
    height: 1px;
    background: var(--color-pearl);
}

/* Keyboard focus: same hairline as active, but on the focused tab
   (which may not be the active one). Keeps keyboard users oriented. */
.home-pricing__tab:focus-visible {
    outline: none;
    color: var(--color-pearl);
    opacity: 1;
}
.home-pricing__tab:focus-visible::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    width: 24px;
    height: 1px;
    background: var(--color-pearl);
}

/* Grid — single column always (no more 1.2fr/1fr desktop split since
   only one card is visible at a time and should fill the available
   width regardless of which tab is active). */
.home-pricing__grid {
    position: relative;
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;                                /* gap removed — only one card visible */
    margin-top: var(--space-8);
}

/* ─── Desktop pricing — side-by-side two-card layout (≥769px) ───
   Reverts the toggle pattern at desktop. Both cards visible at once
   for easy comparison; the original asymmetric 1.2fr/1fr split
   gives Single Membership slight visual prominence as the
   recommended path. Tabs hidden — they're a mobile-only affordance
   when only one card can fit. The earlier 880px max-width:560px
   constraint (for centering the singleton toggle card) is removed
   because both cards now fill the container.
   ────────────────────────────────────────────────────────────── */
@media (min-width: 769px) {
    .home-pricing__grid {
        display: grid;
        grid-template-columns: 1.2fr 1fr;
        gap: var(--space-8);
        align-items: stretch;
    }

    /* Override the toggle pattern's card-hide rules. Cards are
       all visible on desktop — no opacity/scale/position tricks.
       !important is necessary because the default `.home-pricing__grid
       .home-pricing__card:not(.is-active)` selector has higher
       specificity than a media-query'd single-class selector;
       reaching that specificity without !important would require
       nesting the override under .home-pricing__grid here too,
       which adds noise without changing intent. */
    .home-pricing__card {
        opacity: 1 !important;
        transform: none !important;
        position: relative !important;
        pointer-events: auto !important;
        /* Reset the grid-cell stacking trick — let cards flow
           naturally into the 1.2fr/1fr columns. */
        grid-column: auto !important;
        grid-row: auto !important;
    }

    /* Tabs hide on desktop — both cards are visible side-by-side,
       so a tab-toggle would be redundant chrome. */
    .home-pricing__tabs {
        display: none;
    }
}

/* Card visibility states. Active card flows normally; inactive cards
   are absolutely positioned + faded so they don't take layout space
   but stay in the DOM for screen readers + keyboard navigation.
   The crossfade combines opacity + subtle scale (0.96→1.0) for the
   premium "I made a choice" feel. */
.home-pricing__grid .home-pricing__card {
    grid-column: 1;
    grid-row: 1;
    width: 100%;
    transition: opacity 0.4s var(--ease-out-expo),
                transform 0.4s var(--ease-out-expo);
}

.home-pricing__grid .home-pricing__card.is-active {
    opacity: 1;
    transform: scale(1);
    pointer-events: auto;
    z-index: 1;
}

.home-pricing__grid .home-pricing__card:not(.is-active) {
    opacity: 0;
    transform: scale(0.96);
    pointer-events: none;
    z-index: 0;
}

/* ── Mobile swipe deck (Moment 4 polish — ≤768px).
      Transforms the desktop toggle into a horizontal scroll-snap
      deck. Tabs still control via tap (scrollIntoView on the
      target), and swipe gestures also update the active tab state
      via main.js's IntersectionObserver. Both interactions
      converge on the same setActiveState() function. Mirrors the
      Moment 2 features deck pattern.

      Section + card spacing tightened so the full composition
      fits more comfortably in a single mobile viewport (iPhone SE
      375×667 - 70px bottom nav = 597px usable). ───────────── */
@media (max-width: 768px) {
    /* Section padding tightened from --section-y (56px) to --space-8 (32px). */
    .home-pricing {
        padding-block: var(--space-8);
    }

    /* Transform the grid into a horizontal scroll deck. Cards sit
       centered (100% container width, no peek of next card on the
       right) — symmetric composition. Swipe gesture still works
       via overflow-x + scroll-snap, but the visual signal of "more
       to swipe" is dropped in favor of premium centered framing.
       Tabs remain the primary discovery path; swipe is for users
       who try it. */
    .home-pricing__grid {
        display: flex;
        flex-direction: row;
        gap: 0;                       /* cards take full width — gap unused */
        margin-top: var(--space-6);
        margin-left: 0;               /* removed negative margin (was full-bleed) */
        margin-right: 0;
        /* Top padding bumped from --space-2 (8px) to --space-5 (20px) so
           the "Most popular" badge (which straddles the primary card's
           top border via translateY(-50%)) has clearance inside the
           grid. With overflow-y:hidden in place to suppress vertical
           scroll on the horizontal swipe deck, the smaller padding
           was clipping the badge's top half. */
        padding: var(--space-5) 0 var(--space-2);
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .home-pricing__grid::-webkit-scrollbar {
        display: none;
    }

    /* Each card takes the full visible deck width — no peek of the
       next card on the right. scroll-snap-align: center reinforces
       the symmetric framing. Override the desktop toggle's
       opacity/transform/grid-cell-stacking rules so all cards stay
       visible in the scroll deck. */
    .home-pricing__grid .home-pricing__card {
        flex: 0 0 100%;
        scroll-snap-align: center;
        scroll-snap-stop: always;
        grid-column: auto;            /* override desktop's grid-cell stacking */
        grid-row: auto;
        opacity: 1;                   /* override desktop's :not(.is-active) hide */
        transform: none;
        pointer-events: auto;
        padding: var(--space-10) var(--space-6);
    }

    /* Tighten internal card margins (cumulative effect: ~40px saved
       across label / price / features). */
    .home-pricing__label {
        margin-bottom: var(--space-5);
    }
    .home-pricing__price {
        margin-bottom: var(--space-6);
    }
    .home-pricing__features {
        margin-bottom: var(--space-6);
    }
    .home-pricing__features li {
        padding: var(--space-2) 0;
    }

    /* Tab bar tightened toward the deck below it. */
    .home-pricing__tabs {
        margin-top: var(--space-6);
        margin-bottom: var(--space-4);
    }

    /* Footnote bumped up so it tucks against the deck rather than
       floating far below the active card. */
    .home-pricing__footnote {
        margin-top: var(--space-6);
    }
}

.home-pricing__card {
    position: relative;
    padding: var(--space-12) var(--space-8);
    border: 1px solid var(--color-divider);
    background: var(--color-onyx-rich);
    display: flex;
    flex-direction: column;
    box-shadow: var(--glow-platinum-sm);
    transition: border-color var(--t-base), box-shadow var(--t-base), transform var(--t-base);
}

.home-pricing__card:hover {
    border-color: var(--color-divider-strong);
    box-shadow: var(--glow-platinum-md);
    transform: translateY(-2px);
}

/* ─── T3: Scroll-into-view entrance ──────────────────────────
   main.js already adds .is-revealed when the card hits the
   IntersectionObserver threshold. We listen for that here and
   wake the card from an opacity-0 / translated-down resting
   state. Primary card gets a 120ms extra delay so the eye lands
   on secondary first and settles on the recommendation last —
   the visual choreography that anchors the choice.

   !important is needed throughout because the desktop reset rule
   above (.home-pricing__card { opacity: 1 !important; transform:
   none !important }) was originally set to override the mobile
   toggle's hidden-card state. Matching its specificity here is the
   cleanest way to coexist without restructuring upstream rules. */
@media (min-width: 769px) {
    .home-pricing__card {
        opacity: 0 !important;
        transform: translateY(24px) !important;
        transition:
            opacity 0.6s var(--ease-out-expo),
            transform 0.6s var(--ease-out-expo),
            border-color var(--t-base),
            box-shadow var(--t-base);
    }
    .home-pricing__card.is-revealed {
        opacity: 1 !important;
        transform: translateY(0) !important;
    }
    .home-pricing__card--primary.is-revealed {
        transform: translateY(-4px) !important;
        transition-delay: 120ms;
    }
    /* Hover continues to override the at-rest transform once revealed. */
    .home-pricing__card.is-revealed:hover {
        transform: translateY(-2px) !important;
    }
    .home-pricing__card--primary.is-revealed:hover {
        transform: translateY(-6px) !important;
    }
}
@media (prefers-reduced-motion: reduce) {
    .home-pricing__card,
    .home-pricing__card.is-revealed,
    .home-pricing__card--primary,
    .home-pricing__card--primary.is-revealed,
    .home-pricing__card.is-revealed:hover,
    .home-pricing__card--primary.is-revealed:hover {
        opacity: 1 !important;
        transform: none !important;
        transition: border-color var(--t-base), box-shadow var(--t-base) !important;
    }
}

/* ─── Primary plan elevation (T1, per UX audit) ────────────────
   The previous primary/secondary distinction was nearly invisible.
   Now the primary card carries: a deep brand-black border, a stronger
   resting shadow, a slight vertical lift, and a "Most popular" badge.
   Reads at a glance as "this is the recommended path" without
   shouting. Secondary card stays clean and quiet by contrast. */
.home-pricing__card--primary {
    border: 1.5px solid #080706;
    box-shadow:
        0 1px 2px rgba(8, 7, 6, 0.06),
        0 12px 32px rgba(8, 7, 6, 0.10);
    /* !important needed — the desktop card-grid override above sets
       `transform: none !important` to neutralize the inactive-card
       scale trick. We restore a small lift here to differentiate
       primary from secondary. */
    transform: translateY(-4px) !important;
}
.home-pricing__card--primary:hover {
    border-color: #080706;
    box-shadow:
        0 2px 4px rgba(8, 7, 6, 0.08),
        0 18px 40px rgba(8, 7, 6, 0.14);
    transform: translateY(-6px) !important;
}
@media (prefers-reduced-motion: reduce) {
    .home-pricing__card,
    .home-pricing__card--primary,
    .home-pricing__card--primary:hover,
    .home-pricing__card:hover {
        transform: none !important;
    }
}

/* "Most popular" badge — compact chip sitting on the top border of
   the primary card. Translated up so it straddles the border line.
   Tightened from the first ship: letter-spacing reduced (tracking-widest
   stretched "MOST POPULAR" almost the full card width on mobile), font
   size dropped to 10px, padding tightened. Reads as a discrete chip
   instead of a banner.
   T3: scale-in entrance keyed to the parent card's .is-revealed state
   so it settles into place ~250ms after the card finishes its rise. */
.home-pricing__badge {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%) scale(0.6);
    opacity: 0;
    padding: 5px 11px;
    background: #080706;
    color: var(--color-onyx);
    font-family: var(--font-body);
    font-size: 10px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.08em;
    line-height: 1.1;
    text-transform: uppercase;
    white-space: nowrap;
    border-radius: 999px;
    box-shadow: 0 2px 6px rgba(8, 7, 6, 0.18);
    z-index: 2;
    transition:
        opacity 350ms ease-out 250ms,
        transform 350ms cubic-bezier(0.34, 1.56, 0.64, 1) 250ms;
}
.home-pricing__card.is-revealed .home-pricing__badge {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}
@media (prefers-reduced-motion: reduce) {
    .home-pricing__badge {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
        transition: none;
    }
}

/* CTA pushed to bottom so both cards align regardless of bullet count */
.home-pricing__card .btn {
    margin-top: auto;
}

/* Deepen the primary CTA to true brand-black so it actually reads
   as the primary action. Default .btn--primary uses var(--chrome)
   which is a muted warm gray — fine for nav but underweight for
   the highest-friction action on the site. */
.home-pricing__card--primary .btn--primary {
    background: #080706;
    border-color: #080706;
}
.home-pricing__card--primary .btn--primary::before {
    background: var(--chrome-bright);
}

/* Reassurance line — sits above the CTA, communicates "no risk"
   terms that previously hid in the bullet list ("Cancel any time").
   Small uppercase chrome-tone, separated from the bullets by spacing.
   Each phrase is wrapped in white-space:nowrap so the line breaks
   at the · separators instead of mid-phrase ("NO ENROLLMENT" + orphan
   "FEE" on the next line). */
.home-pricing__reassurance {
    margin: 0 0 var(--space-4);
    font-family: var(--font-body);
    font-size: 11px;
    font-weight: var(--weight-semibold);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--chrome);
    text-align: center;
    line-height: 1.55;
}
.home-pricing__reassurance-item {
    white-space: nowrap;
}
.home-pricing__reassurance-sep {
    display: inline-block;
    margin: 0 6px;
    color: var(--color-steel);
}

/* ─── T2: Price anchor microcopy ──────────────────────────────
   A small contextual line below the price ("Less than $2/day",
   "Below the KC average") that anchors price perception. Sits
   tight to the price block visually. */
.home-pricing__price-anchor {
    margin: calc(-1 * var(--space-6)) 0 var(--space-8);
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-regular);
    letter-spacing: var(--tracking-wide);
    color: var(--color-steel);
    line-height: 1.4;
}

/* ─── T2: Inline FAQ ────────────────────────────────────────
   Native <details> accordion below the cards. No JS dependency.
   The summary is a flex row with the question on the left and a
   chevron on the right that rotates when the item is opened.

   Sized for readability (16px question, 15px answer) and given a
   max-width so it doesn't stretch unread across a wide desktop.
   ──────────────────────────────────────────────────────────── */
.home-pricing__faq {
    margin-top: var(--space-12);
    padding-top: var(--space-10);
    border-top: 1px solid var(--color-divider);
    max-width: 720px;
    margin-left: auto;
    margin-right: auto;
}
.home-pricing__faq .section-label {
    text-align: center;
    margin-bottom: var(--space-3);
}
.home-pricing__faq-title {
    font-family: var(--font-display);
    font-size: var(--text-3xl);
    letter-spacing: var(--tracking-display);
    color: var(--color-pearl);
    text-align: center;
    margin: 0 0 var(--space-8);
    line-height: 1.1;
    text-transform: uppercase;
}
.home-pricing__faq-list {
    display: flex;
    flex-direction: column;
}
.home-pricing__faq-item {
    border-bottom: 1px solid var(--color-divider);
}
.home-pricing__faq-item:first-child {
    border-top: 1px solid var(--color-divider);
}
.home-pricing__faq-question {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-5) 0;
    cursor: pointer;
    list-style: none;
    font-family: var(--font-body);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--color-pearl);
    transition: color var(--t-base);
}
.home-pricing__faq-question::-webkit-details-marker { display: none; }
.home-pricing__faq-question:hover { color: var(--color-bone); }
.home-pricing__faq-question-text { flex: 1 1 auto; }
.home-pricing__faq-chevron {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    color: var(--chrome);
    transition: transform var(--t-base), color var(--t-base);
}
.home-pricing__faq-chevron svg {
    width: 16px;
    height: 16px;
}
.home-pricing__faq-item[open] .home-pricing__faq-chevron {
    transform: rotate(180deg);
    color: var(--color-pearl);
}
.home-pricing__faq-answer {
    padding: 0 0 var(--space-5);
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-loose);
    color: var(--color-bone);
    max-width: 60ch;
}
.home-pricing__faq-answer p { margin: 0 0 var(--space-3); }
.home-pricing__faq-answer p:last-child { margin: 0; }
.home-pricing__faq-answer a {
    color: var(--color-pearl);
    text-decoration: underline;
    text-underline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
    .home-pricing__faq-chevron { transition: none; }
}
@media (max-width: 640px) {
    .home-pricing__faq { margin-top: var(--space-8); padding-top: var(--space-8); }
    .home-pricing__faq-title { font-size: var(--text-2xl); margin-bottom: var(--space-6); }
    .home-pricing__faq-question { padding: var(--space-4) 0; font-size: var(--text-sm); }
    .home-pricing__faq-answer { font-size: var(--text-sm); }
}

/* ─── T3: A11y + focus polish ────────────────────────────────
   Cards and CTAs need visible keyboard-focus affordances. The
   pricing page is a primary conversion surface; tab-key users
   shouldn't be left guessing where they are. */
.home-pricing__card:focus-within {
    border-color: var(--color-divider-strong);
}
.home-pricing__card--primary:focus-within {
    border-color: #080706;
}
.home-pricing__card .btn:focus-visible {
    outline: 2px solid #080706;
    outline-offset: 3px;
}
.home-pricing__faq-question:focus-visible {
    outline: 2px solid #080706;
    outline-offset: 4px;
    border-radius: 2px;
}

/* ─── T3: Mobile typography rhythm ───────────────────────────
   On very narrow viewports the $55 amount + "per month" period
   were sitting too close — slight tightening for elegance. */
@media (max-width: 480px) {
    .home-pricing__card {
        padding: var(--space-10) var(--space-6);
    }
    .home-pricing__amount {
        font-size: var(--text-4xl);
        letter-spacing: var(--tracking-tight);
    }
    .home-pricing__price {
        gap: var(--space-2);
        margin-bottom: var(--space-6);
    }
    .home-pricing__price-anchor {
        margin-top: calc(-1 * var(--space-4));
        margin-bottom: var(--space-6);
    }
    .home-pricing__features li {
        font-size: var(--text-sm);
    }
}

.home-pricing__label {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--chrome);
    margin: 0 0 var(--space-6);
}

.home-pricing__price {
    margin: 0 0 var(--space-8);
    display: flex;
    align-items: baseline;
    gap: var(--space-3);
}

.home-pricing__amount {
    font-family: var(--font-display);
    font-size: var(--text-5xl);
    color: var(--color-pearl);
    line-height: 1;
    letter-spacing: var(--tracking-display);
}

.home-pricing__period {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--color-steel);
    letter-spacing: var(--tracking-wide);
}

.home-pricing__features {
    list-style: none;
    padding: 0;
    margin: 0 0 var(--space-8);
    flex-grow: 1;
}

.home-pricing__features li {
    font-size: var(--text-base);
    color: var(--color-bone);
    padding: var(--space-2) 0;
    /* T1 (per UX audit): removed the heavy bottom-border between
       bullets — it read as "mutually exclusive options," not as
       an inclusive list. Tightened vertical padding to give the
       rhythm to spacing instead of dividers. */
    position: relative;
    padding-left: 28px;
    line-height: 1.55;
}

/* Check icon — inline SVG via background-image (no template change
   needed, no font dependency). Stroke color #080706 = public brand
   near-black. Sized at 14px so it reads as a complete glyph but
   doesn't compete with text. */
.home-pricing__features li::before {
    content: '';
    position: absolute;
    left: 0;
    top: 11px;
    width: 16px;
    height: 16px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23080706' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='20 6 9 17 4 12'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 14px 14px;
}

.home-pricing__features li:last-child {
    border-bottom: 0;
}

.home-pricing__footnote {
    text-align: center;
    margin-top: var(--space-12);
    font-size: var(--text-sm);
    color: var(--color-steel-muted);
    font-style: italic;
}

/* ═══════════════════════════════════════════════════════════
   GALLERY (CMS-driven, Prompt 4-B-3-F)
   3-column grid on desktop, 1-column on mobile.
   Each photo is a button for keyboard accessibility.
   Lightbox modal handles enlargement.
   ═══════════════════════════════════════════════════════════ */
.home-gallery {
    padding: var(--section-y) 0;
    /* Near-black gallery wall — the photos are the hero and pop against dark,
       matching the site's cinematic language (was cream, the weakest ground). */
    background: #0b0b0e;
}
/* Headings flip light on the dark ground (literal colors — flip-proof). */
.home-gallery .section-label { color: rgba(244, 241, 234, 0.64); }
.home-gallery .section-title { color: #ffffff; }
.home-gallery .section-desc  { color: rgba(244, 241, 234, 0.80); }
/* Focus ring must read on dark too. */
.home-gallery .home-gallery__feature:focus-visible,
.home-gallery .home-gallery__supporting-item:focus-visible,
.home-gallery .cms-gallery__item:focus-visible { outline-color: #f2efe8; }

/* Editorial asymmetric layout — feature photo (left, large) + supporting
   photos (right, stacked). Mobile: feature on top, supporting in 2-col grid. */
.home-gallery__editorial {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-3);             /* TI5C: 16px → 12px */
    margin-top: var(--space-8);      /* TI5C: 40px → 32px */
}

@media (min-width: 880px) {
    .home-gallery__editorial {
        grid-template-columns: 2fr 1fr;
    }
}

.home-gallery__feature,
.home-gallery__supporting-item {
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    overflow: hidden;
    aspect-ratio: 4 / 3;
}

@media (min-width: 880px) {
    .home-gallery__feature {
        aspect-ratio: auto;
        height: 100%;
        min-height: 400px;   /* TI5C: 480px → 400px — preserves 3:1:1 diptych proportion, scales total grid to fit 13" laptop viewport */
    }
}

.home-gallery__feature img,
.home-gallery__supporting-item img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform var(--t-slow), filter var(--t-slow);
}

.home-gallery__feature:hover img,
.home-gallery__feature:focus-visible img {
    transform: scale(1.03);
    filter: brightness(1.05);
}

.home-gallery__supporting-item:hover img,
.home-gallery__supporting-item:focus-visible img {
    transform: scale(1.04);
    filter: brightness(1.05);
}

.home-gallery__feature:focus-visible,
.home-gallery__supporting-item:focus-visible {
    outline: 2px solid var(--platinum-bright);
    outline-offset: 2px;
}

.home-gallery__supporting {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space-4);
}

@media (min-width: 880px) {
    .home-gallery__supporting {
        grid-template-columns: 1fr;
    }
}

/* ── Lightbox ────────────────────────────────────────────── */
.lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(10, 9, 8, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--space-12);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s var(--ease-out-expo);
}

.lightbox[aria-hidden="false"],
.lightbox.is-open {
    opacity: 1;
    pointer-events: auto;
}

.lightbox[hidden] {
    display: none;
}

.lightbox__close,
.lightbox__prev,
.lightbox__next {
    position: absolute;
    background: transparent;
    border: 1px solid var(--chrome-dim);
    color: var(--chrome-bright);
    font-size: var(--text-xl);
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--t-base);
    z-index: 2;
}

.lightbox__close {
    top: var(--space-6);
    right: var(--space-6);
}

.lightbox__prev {
    left: var(--space-6);
    top: 50%;
    transform: translateY(-50%);
}

.lightbox__next {
    right: var(--space-6);
    top: 50%;
    transform: translateY(-50%);
}

.lightbox__close:hover,
.lightbox__prev:hover,
.lightbox__next:hover {
    background: var(--chrome);
    color: var(--color-onyx);
    border-color: var(--chrome);
}

.lightbox__content {
    max-width: min(1200px, 90vw);
    max-height: 85vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--space-4);
}

.lightbox__img {
    max-width: 100%;
    max-height: 80vh;
    object-fit: contain;
    display: block;
}

.lightbox__caption {
    font-family: var(--font-body);
    font-size: var(--text-base);
    color: var(--color-bone);
    text-align: center;
    margin: 0;
    max-width: 80ch;
}

.lightbox__caption:empty {
    display: none;
}

@media (max-width: 768px) {
    .lightbox {
        padding: var(--space-4);
    }
    .lightbox__close,
    .lightbox__prev,
    .lightbox__next {
        width: 40px;
        height: 40px;
        font-size: var(--text-lg);
    }
    .lightbox__close { top: var(--space-3); right: var(--space-3); }
    .lightbox__prev { left: var(--space-3); }
    .lightbox__next { right: var(--space-3); }
}

/* ═══════════════════════════════════════════════════════════
   FIND US — full-bleed map backdrop + floating bone card
   The only light-surface card on the homepage. Deliberate
   editorial moment for the location/information section.
   ═══════════════════════════════════════════════════════════ */
.home-find {
    position: relative;
    /* Height follows the info card + modest padding — no forced full-screen
       band. The old min-height (content-box) stacked on top of the container
       padding and created a screenful of dead space around the card. */
    min-height: 0;
    overflow: hidden;
    isolation: isolate;
    background: var(--color-onyx-deep);
}

/* ─── Full-bleed dark map background ───────────────────── */
.home-find__map-bg {
    position: absolute;
    inset: 0;
    z-index: 1;
}

.home-find__map-bg iframe {
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
    /* Warm monochrome filter chain. Kills color saturation entirely
       (eliminates the muddy green inversion artifact from parks/forest)
       and adds subtle sepia for warm-platinum brand harmony. */
    filter: invert(1) hue-rotate(180deg) brightness(0.8) contrast(1.1) saturate(0) sepia(0.25);
    /* Default pointer-events: auto so desktop visitors can drag/zoom
       the map immediately without clicking the "Click to interact"
       overlay first. The overlay (.home-find__map-interact) still
       renders on desktop as a visual affordance but its previous
       gating role is no longer required.
       Mobile (≤768px) overrides this back to `none` inside the
       mobile media query below — the CTA opens native Maps instead. */
    pointer-events: auto;
    transition: pointer-events 0s;
}

/* Legacy click-to-interact toggle — vestigial after the
   pointer-events default was flipped to auto. JS in main.js still
   adds .is-interactive on click; this rule's value matches the
   default, so the toggle is a no-op. Kept defensively so a future
   reversion (flip the default back to none) would re-enable the
   gating behavior without needing to re-add this rule. */
.home-find__map-bg.is-interactive iframe {
    pointer-events: auto;
}

/* ─── Static dark map (server-cached Static Maps image) ───────────
   A natively dark-styled map with a gold marker, served from our own
   origin. No invert/sepia filter (the image is already dark), so it's
   crisp instead of muddy. A soft left-edge gradient seats the info card
   against the map. Replaces the iframe when the integration is set up. */
.home-find__map-bg--static {
    background: #101010;
}
.home-find__map-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.home-find__map-bg--static::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(90deg, rgba(12, 12, 12, 0.6) 0%, rgba(12, 12, 12, 0.2) 42%, rgba(12, 12, 12, 0) 68%);
}
/* Location pin — small black dot with a white ring, overlaid at the map
   centre (the Static Maps image is centred on the address). Pure CSS, so it
   stays crisp and is easy to restyle. Sits above the gradient. */
.home-find__map-pin {
    position: absolute;
    top: 50%;
    left: 50%;
    z-index: 2;
    width: 16px;
    height: 16px;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: #111;
    border: 3px solid #fff;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
    pointer-events: none;
}

/* ─── Photographic backdrop (primary) ─────────────────────────────
   Replaces the utility map with on-brand atmosphere (the dark onyx-stone
   texture by default). A framing gradient darkens the card side and vignettes
   the edges, so the photo reads as a designed backdrop rather than a raw image
   running flat to the section edges. The card is opaque, so legibility is
   never at risk — the scrim is purely compositional. */
.home-find__map-bg--photo { background: #0b0b0e; }
.home-find__photo {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    /* Slow, subtle drift gives the still image a breath of life without
       distracting from the card. */
    animation: findPhotoDrift 32s ease-in-out infinite alternate;
    will-change: transform;
}
.home-find__map-bg--photo::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background:
        linear-gradient(90deg,
            rgba(11, 11, 14, 0.66) 0%,
            rgba(11, 11, 14, 0.42) 32%,
            rgba(11, 11, 14, 0.26) 58%,
            rgba(11, 11, 14, 0.50) 100%),
        linear-gradient(0deg,
            rgba(11, 11, 14, 0.58) 0%,
            rgba(11, 11, 14, 0) 44%);
}

/* Frosted-onyx card — on the photographic backdrop the info card becomes a
   glass panel: the stone texture blurs through it so the card reads as part of
   the same material rather than a flat block seamed onto the photo. Scoped to
   the photo variant (the adjacent bg element), so the map/inner-page fallback
   keeps its solid card. */
.home-find__map-bg--photo + .home-find__container .home-find__card {
    background: rgba(20, 18, 15, 0.78);
    -webkit-backdrop-filter: blur(16px) saturate(1.08);
    backdrop-filter: blur(16px) saturate(1.08);
    border: 1px solid rgba(255, 255, 255, 0.09);
    box-shadow:
        0 34px 74px rgba(0, 0, 0, 0.52),
        inset 0 1px 0 rgba(255, 255, 255, 0.10);
}
/* Progressive-enhancement guard: if the browser can't blur, keep the panel
   opaque enough that text never rides directly on raw photo. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .home-find__map-bg--photo + .home-find__container .home-find__card {
        background: rgba(20, 18, 15, 0.95);
    }
}
@keyframes findPhotoDrift {
    from { transform: scale(1.06) translate3d(1.5%, 0, 0); }
    to   { transform: scale(1.06) translate3d(-1.5%, 1%, 0); }
}
@media (prefers-reduced-motion: reduce) {
    .home-find__photo { animation: none; transform: scale(1.02); }
}

/* ─── Interactive dark map (Maps JavaScript API) ──────────────────
   Renders OVER the photo layer, which stays as the graceful fallback if Maps
   can't load. Sits above the photo, below the scrim + card. Skipped on mobile
   (the photo is lighter and looks great there). */
.home-find__map-bg--interactive .home-find__gmap {
    position: absolute;
    inset: 0;
    z-index: 1;
    /* Transparent until the map actually initializes, so if Maps JS can't load
       (blocked/misconfigured) the photo backdrop below shows through instead of
       a black box. The dark base only applies once the map is live. */
}
.home-find__map-bg--interactive .home-find__gmap.is-loaded {
    background: #0b0b0e;   /* dark base while tiles paint in */
}
/* Lighter scrim for the map variant — darken the card side, leave the map
   itself clear. Declared after the photo scrim so it wins on the shared ::after. */
.home-find__map-bg--interactive::after {
    z-index: 2;
    background: linear-gradient(90deg,
        rgba(11, 11, 14, 0.86) 0%,
        rgba(11, 11, 14, 0.46) 28%,
        rgba(11, 11, 14, 0) 52%,
        rgba(11, 11, 14, 0) 100%);
}
@media (max-width: 768px) {
    .home-find__gmap { display: none; }   /* photo backdrop shows on phones */
}

/* "Click to interact" affordance overlay */
.home-find__map-interact {
    position: absolute;
    bottom: var(--space-6);
    right: var(--space-6);
    z-index: 5;
    background: rgba(10, 9, 8, 0.85);
    border: 1px solid var(--platinum-muted);
    color: var(--platinum-bright);
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    padding: var(--space-3) var(--space-5);
    cursor: pointer;
    transition: background var(--t-base), border-color var(--t-base);
}

.home-find__map-interact:hover {
    background: rgba(10, 9, 8, 0.95);
    border-color: var(--platinum);
}

.home-find__map-bg.is-interactive .home-find__map-interact {
    display: none;
}

/* ─── Container positioning the card ───────────────────── */
.home-find__container {
    position: relative;
    z-index: 10;
    min-height: 0;
    display: flex;
    align-items: center;
    /* About half the usual section padding — the card has its own padding,
       so the section doesn't need a tall band of breathing room too. */
    padding-block: clamp(1.5rem, 2.5vw, 2.75rem);
}

/* ─── The bone-colored information card ────────────────── */
.home-find__card {
    background: var(--color-bone);
    color: var(--color-onyx);
    width: 100%;
    max-width: 440px;
    padding: var(--space-8) var(--space-10);
    box-shadow:
        0 24px 48px rgba(0, 0, 0, 0.4),
        0 4px 12px rgba(0, 0, 0, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.4);
    position: relative;
}

@media (max-width: 768px) {
    .home-find__card {
        max-width: 100%;
        padding: var(--space-8) var(--space-6);
    }
}

/* ─── Open Now status pill ─────────────────────────────── */
/* Moment 5 migration: the legacy .home-find__status* family was
   deleted in favor of the foundation .status-pill component
   (mobile-foundation.css:62+). The find_us card needs two scoped
   tweaks vs the foundation defaults: (1) preserve the semantic
   GREEN dot (foundation default is warm-white, intended for hero
   on dark video) and (2) keep the card-internal --space-8 bottom
   margin between pill and eyebrow. Both scoped to .home-find__card
   so other .status-pill usages on the site stay default. */
.home-find__card .status-pill {
    margin-bottom: var(--space-5);
}

.home-find__card .status-pill__dot {
    background: #2d7a3d;                                /* warm green — semantic "open" indicator */
    box-shadow: 0 0 0 2px rgba(45, 122, 61, 0.15);
}

/* Staffed-vs-unstaffed variant — when the JS sets data-status,
   override the green dot to a muted platinum on this card.
   The foundation .status-pill[data-status="unstaffed"] rule
   handles the animation reset; this rule overrides JUST the
   color to fit the find_us card's dark surface. */
.home-find__card .status-pill[data-status="unstaffed"] .status-pill__dot {
    background: var(--platinum-deep);
}

/* @keyframes pulse-dot is consumed by both .home-find__status-dot
   (legacy, now removed) and .status-pill__dot (foundation). Kept
   here because removing it would orphan the foundation pill's
   animation reference. */
@keyframes pulse-dot {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
}

/* ─── Card typography ──────────────────────────────────── */
.home-find__eyebrow {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--color-onyx-warm);
    margin: 0 0 var(--space-3);
    position: relative;
    padding-left: var(--space-8);
}

.home-find__eyebrow::before {
    content: '';
    position: absolute;
    left: 0;
    top: 50%;
    width: var(--space-6);
    height: 1px;
    background: var(--color-onyx-warm);
}

.home-find__headline {
    font-family: var(--font-display);
    font-size: clamp(2rem, 4vw, 3rem);
    font-weight: 400;
    line-height: 0.95;
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--color-onyx);
    margin: 0 0 var(--space-4);
}

.home-find__subtitle {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-loose);
    color: var(--color-onyx-warm);
    margin: 0 0 var(--space-2);
    max-width: 32ch;
}

/* ─── Card dividers ─────────────────────────────────────── */
.home-find__divider {
    height: 1px;
    background: rgba(10, 9, 8, 0.12);
    margin: var(--space-4) 0;
}

/* ─── Address block ─────────────────────────────────────── */
.home-find__address {
    font-family: var(--font-body);
    font-style: normal;
    font-size: var(--text-base);
    line-height: var(--leading-snug);
    color: var(--color-onyx);
    margin: 0 0 var(--space-6);
    font-weight: var(--weight-semibold);
}

/* ─── Drive times ──────────────────────────────────────── */
.home-find__drive-times {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
}

.home-find__drive-times li {
    display: flex;
    align-items: baseline;
    gap: var(--space-4);
    font-family: var(--font-body);
    font-size: var(--text-sm);
}

.home-find__drive-mins {
    font-weight: var(--weight-bold);
    color: var(--color-onyx);
    min-width: 4em;
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    font-size: var(--text-xs);
}

.home-find__drive-from {
    color: var(--color-onyx-warm);
    position: relative;
    padding-left: var(--space-4);
}

.home-find__drive-from::before {
    content: '·';
    position: absolute;
    left: 0;
    color: var(--platinum-deep);
}

/* ─── Facility access line (Moment 5) ──────────────────── */
/* Replaces the previous two-row "FACILITY ACCESS / IN-PERSON
   VISITS" dl/dt/dd table. One confident declarative sentence
   reads cleaner than a label/value table on this card. Sized
   to match the address block above so they read as paired
   structural facts about the location. */
.home-find__facility-line {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-snug);
    color: var(--color-onyx);
    margin: 0;
    max-width: 34ch;
}

/* ─── Action buttons ───────────────────────────────────── */
.home-find__actions {
    display: flex;
    flex-direction: column;
    gap: var(--space-4);
    align-items: flex-start;
}

.home-find__cta-primary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    /* Literal colors — the find card sits in a dark-text-flip scope where
       --color-bone resolves LIGHT, which made this label vanish (light-on-cream).
       Literal cream fill + near-black label is flip-proof. */
    background: #faf6ef;
    color: #141414;
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    text-decoration: none;
    padding: var(--space-4) var(--space-8);
    border: 1px solid #faf6ef;
    transition: background var(--t-base), color var(--t-base), transform var(--t-base);
}

.home-find__cta-primary:hover {
    background: #ffffff;
    transform: translateX(2px);
}

.home-find__cta-arrow {
    transition: transform var(--t-base);
}

.home-find__cta-primary:hover .home-find__cta-arrow {
    transform: translateX(2px);
}

/* Secondary map link (Apple Maps) — a quiet uppercase link beneath the primary
   button. Literal light color so it stays visible on the dark card regardless
   of the token-flip scope. */
.home-find__cta-secondary {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    color: #f2efe8;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    text-decoration: none;
    opacity: 0.78;
    transition: opacity var(--t-base);
}
.home-find__cta-secondary:hover {
    opacity: 1;
}
.home-find__cta-secondary:hover .home-find__cta-arrow {
    transform: translateX(2px);
}

.home-find__cta-phone {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--color-onyx);
    text-decoration: none;
    border-bottom: 1px solid var(--color-onyx);
    padding-bottom: 1px;
    letter-spacing: var(--tracking-wide);
    transition: opacity var(--t-base);
}

.home-find__cta-phone:hover {
    opacity: 0.7;
}

.home-find__cta-phone-icon {
    font-size: 0.9em;
}

/* ─── Desktop click-through on the card (≥769px) ──────────────
   The card's visual surface sits over the interactive map iframe.
   Without this rule, the card area would block all map gestures
   (pan, zoom, click-on-pin, embed's own Get Directions button).
   `pointer-events: none` on the card lets clicks/scrolls fall
   through to the map underneath; the interactive children (CTA
   anchor + phone anchor — every `<a>` inside the card) re-enable
   pointer-events so they stay clickable.

   Mobile (≤768px) doesn't need this rule because the iframe is
   `pointer-events: none` there — the card sits over a
   non-interactive map, so blocking events doesn't matter and
   keeping the card interactive lets visitors select/copy text. */
@media (min-width: 769px) {
    .home-find__card {
        pointer-events: none;
    }
    .home-find__card a {
        pointer-events: auto;
    }
}

/* ─── Mobile adjustments — Moment 5 corrected ────────────────
   Map fills the section as background. The card (with its own
   chrome: warm-dark bone bg + multi-layer shadow + padding) sits
   on top of the map. Map is visible around the card on all sides
   (gutter strips left/right, top/bottom of container padding).

   This mirrors the desktop pattern (map full-bleed absolute, card
   floats over) at mobile scale — narrower card max-width, tighter
   card padding, lighter shadow. No gradient overlay; no card-chrome
   stripping; the card's own dark surface handles content legibility.

   z-index hierarchy:
     0 (default)  : .home-find background fallback (--color-pearl)
     1            : .home-find__map-bg (map iframe)
     10           : .home-find__container (positioning context)
     (implicit)   : .home-find__card (above container background)
   ────────────────────────────────────────────────────────── */
@media (max-width: 768px) {
    .home-find {
        min-height: 0;                     /* content height — no full-screen band */
        background: var(--color-pearl);
        overflow: hidden;
    }

    /* Map removed on mobile — stacked, it's redundant (the card already has a
       "Get Directions" button) and added height without value. The photographic
       backdrop stays, though: the card floats on the onyx texture, which reads
       as premium rather than redundant. */
    .home-find__map-bg:not(.home-find__map-bg--photo) {
        display: none;
    }
    .home-find__map-bg--photo {
        position: absolute;
        inset: 0;
    }

    /* Container — normal flow below the map band; the card sits on the
       section's dark surface. */
    .home-find__container {
        position: relative;
        z-index: 10;
        min-height: 0;
        display: block;
        padding: var(--space-8) var(--space-6) var(--space-10);
    }

    /* Card — chrome restored. Mobile-appropriate sizing: full
       container width (so it spans available space; map shows in
       container padding strips), tighter padding than desktop,
       2-layer shadow (matches the pre-Moment-5 mobile shadow
       pattern — desktop's 3-layer treatment too heavy for narrow
       viewports). */
    .home-find__card {
        max-width: 100%;
        background: var(--color-bone);
        padding: var(--space-8) var(--space-6);
        margin: 0;
        box-shadow:
            0 8px 24px rgba(0, 0, 0, 0.3),
            inset 0 1px 0 rgba(255, 255, 255, 0.4);
    }
}

/* ═══════════════════════════════════════════════════════════
   FINAL CTA — full-bleed photo, centered manifesto
   ═══════════════════════════════════════════════════════════ */
.home-final {
    position: relative;
    min-height: 70vh;
    padding: var(--section-y-large) 0;
    overflow: hidden;
    isolation: isolate;
    display: flex;
    align-items: center;
}

.home-final__photo {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-image: var(--hero-image);
    background-size: cover;
    background-position: center;
    background-color: var(--color-onyx);
    filter: brightness(0.55) contrast(1.1);
}

.home-final__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    background: linear-gradient(180deg,
        rgba(11, 11, 14, 0.7) 0%,
        rgba(11, 11, 14, 0.5) 50%,
        rgba(11, 11, 14, 0.8) 100%);
}

.home-final__inner {
    position: relative;
    z-index: 10;
    text-align: center;
}

.home-final__headline {
    font-family: var(--font-display);
    font-size: clamp(2rem, 6vw, 4.5rem);       /* TI5A: -25% from clamp(2.5rem, 8vw, 6rem) */
    font-weight: 400;
    text-transform: none;                     /* TI4 Q4 option (b.iii) */
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    color: var(--color-bone);                  /* warm-dark via token (was --color-pearl over photo) */
    margin: 0 0 var(--space-6);
    max-width: 16ch;
    margin-inline: auto;
    /* text-shadow removed in TI4 — no longer over photo backdrop */
}

.home-final__subtitle {
    font-size: var(--text-lg);
    color: var(--color-bone);
    max-width: 48ch;
    margin: 0 auto var(--space-8);
    line-height: var(--leading-loose);
}

.home-final__actions {
    display: flex;
    gap: var(--space-4);
    flex-wrap: wrap;
    justify-content: center;
}

/* ═══════════════════════════════════════════════════════════
   TRAINERS GRID — curated independent-operator directory.
   (Prompt N Build 2b, per ADR-025.)
   Card grid: 1 col mobile, 2 col tablet (≥768px), 3 col
   desktop (≥1024px). Each card surfaces a trainer's photo,
   name, headline, specialty, bio, and a row of social /
   contact links. Per-trainer data lives in the trainers
   table; the section header copy lives in content_json.
   ═══════════════════════════════════════════════════════════ */
.home-trainers {
    padding-block: var(--section-y);
    background: var(--color-onyx);
}

.home-trainers__grid {
    list-style: none;
    padding: 0;
    margin: var(--space-16) 0 0;
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--space-10);
}

@media (min-width: 768px) {
    .home-trainers__grid {
        grid-template-columns: repeat(2, 1fr);
        gap: var(--space-10);
    }
}

@media (min-width: 1024px) {
    .home-trainers__grid {
        grid-template-columns: repeat(3, 1fr);
        gap: var(--space-10);
    }
}

.home-trainers__card {
    display: flex;
    flex-direction: column;
    background: var(--color-onyx-elevated, var(--color-onyx-rich));
    border: 1px solid var(--chrome-dim);
    border-radius: var(--radius-sm, 2px);
    overflow: hidden;
    /* T1: subtle interactive affordance — border darkens on hover so the
       whole card reads as "alive" before the eye finds the CTA. */
    transition: border-color var(--t-base), box-shadow var(--t-base);
}
.home-trainers__card:hover {
    border-color: var(--chrome);
    box-shadow: 0 4px 18px rgba(8, 7, 6, 0.06);
}

/* Square portrait crop. No `filter: brightness()` — we removed
   that anti-pattern globally in Prompt D Phase 2. Photo content
   shows at full luminance. Focal point is set inline by the
   template via the photos.focal_x / focal_y values. */
.home-trainers__photo {
    width: 100%;
    aspect-ratio: 4 / 3;   /* 1/1 square was too tall; 3/2 clipped heads on a centred focal point; 4/3 trims ~25% while keeping heads in frame */
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
    /* Bias the crop toward the TOP so heads stay in frame on standing-person
       shots (the inline focal point defaults to centre, which lands on the
       torso and clips the head). Overrides only the vertical component, so a
       set focal point's horizontal position is preserved. */
    background-position-y: 12% !important;
    background-color: var(--color-onyx);
    transition: transform var(--t-slow);
}

.home-trainers__photo--placeholder {
    /* When a trainer has no photo_id assigned, the card renders a
       flat dark square so the layout doesn't break. Doug can
       assign a photo later through the admin and the card picks
       it up automatically. */
    background-color: var(--color-onyx);
    background-image: linear-gradient(135deg, var(--color-onyx) 0%, var(--color-onyx-rich, #1a1917) 100%);
}

.home-trainers__card:hover .home-trainers__photo {
    transform: scale(1.02);
}

.home-trainers__content {
    padding: var(--space-6) var(--space-6) var(--space-8);
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.home-trainers__name {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 400;
    line-height: var(--leading-tight);
    letter-spacing: var(--tracking-display);
    text-transform: uppercase;
    color: var(--color-pearl);
    margin: 0;
}

.home-trainers__headline {
    /* T1: this is the trainer's professional positioning line —
       was reading as quiet metadata, now bolder + slightly darker
       so it sits as the second-most-important line on the card
       (after the name). Bumped from text-sm to text-base, weight
       from semibold to bold, color from chrome to color-pearl. */
    font-family: var(--font-body);
    font-size: var(--text-base);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--color-pearl);
    margin: 0;
}

.home-trainers__specialty {
    /* T1: demoted from pill to small-caps label. The pill shape
       implied "tap me" (false affordance); now reads as a quiet
       category tag. No border, no padding, just typography +
       small dot prefix for visual separation from the headline. */
    display: block;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-widest);
    text-transform: uppercase;
    color: var(--chrome);
    position: relative;
}
.home-trainers__specialty::before {
    content: '';
    display: inline-block;
    width: 4px;
    height: 4px;
    margin-right: 10px;
    border-radius: 999px;
    background: currentColor;
    vertical-align: middle;
    opacity: 0.7;
}

.home-trainers__bio {
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-loose);
    color: var(--color-bone);
    margin: var(--space-2) 0 0;
    max-width: 60ch;
    /* Full bio — no line clamp. The coaches' experience is a selling point;
       truncating it undersold them. Cards stay aligned via the CTA's
       margin-top:auto below (anchors the CTA/meta/social to the card bottom),
       so uneven bio lengths don't misalign the buttons. */
}

/* ─── Consultation CTA (migration 0038) ──────────────────────
   The "Schedule consultation" button below the bio. Mode-specific
   variants get different microcopy + iconography in the template:
   --onyx routes through /consultation/{slug} (internal arrow icon)
   --calendly opens the trainer's external URL in a new tab
   (external-link icon). Uses the public site's brand near-black
   (#080706) — admin's indigo is NEVER used on public surfaces. */
.home-trainers__cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    /* auto top margin anchors the CTA (+ the meta/social beneath it) to the
       card bottom, so cards with different bio lengths keep their buttons
       aligned. Falls back to the flex gap for spacing when the card is full. */
    margin: auto 0 0;
    padding: 12px 22px;
    background: #080706;
    color: var(--color-onyx);
    border-radius: 999px;
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 0.01em;
    text-decoration: none;
    line-height: 1;
    white-space: nowrap;
    box-shadow:
        0 1px 2px rgba(8, 7, 6, 0.10),
        0 4px 14px rgba(8, 7, 6, 0.18);
    transition: background 160ms ease, transform 160ms ease, box-shadow 160ms ease;
}
.home-trainers__cta:hover,
.home-trainers__cta:focus-visible {
    background: var(--chrome-bright);
    transform: translateY(-1px);
    box-shadow:
        0 2px 4px rgba(8, 7, 6, 0.14),
        0 8px 20px rgba(8, 7, 6, 0.24);
    text-decoration: none;
    color: var(--color-onyx);
}
.home-trainers__cta-icon {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
}
.home-trainers__cta:focus-visible {
    outline: 2px solid #080706;
    outline-offset: 3px;
}
.home-trainers__cta:active {
    transform: translateY(0);
    box-shadow:
        0 1px 2px rgba(8, 7, 6, 0.18),
        0 2px 6px rgba(8, 7, 6, 0.16);
}
.home-trainers__cta-sublabel {
    /* T1: now a flex container of icon+text pairs separated by ·.
       Each pair carries a small SVG (clock, pin, or external arrow).
       The line is wrap-friendly so narrow cards break naturally
       between phrases instead of mid-text. */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 6px;
    margin: 10px 0 0;
    font-family: var(--font-body);
    font-size: var(--text-xs);
    color: var(--chrome);
    letter-spacing: 0.01em;
    line-height: 1.4;
}
.home-trainers__cta-sublabel-item {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    white-space: nowrap;
}
.home-trainers__cta-sublabel-icon {
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
    color: var(--chrome);
}
.home-trainers__cta-sublabel-sep {
    color: var(--chrome-dim);
    user-select: none;
}

/* Mobile: CTA goes full-width to maximize tap target and read clearly
   on a narrow column. 44px+ height satisfies WCAG AA touch target. */
@media (max-width: 640px) {
    .home-trainers__cta {
        display: flex;
        width: 100%;
        justify-content: center;
        padding: 14px 22px;
    }
}

/* Reduced-motion users get no transform/animation on the CTA or the
   card photo. Color + shadow changes stay because they don't trigger
   vestibular discomfort. */
@media (prefers-reduced-motion: reduce) {
    .home-trainers__cta,
    .home-trainers__cta:hover,
    .home-trainers__cta:focus-visible {
        transition: background-color 160ms ease, box-shadow 160ms ease;
        transform: none !important;
    }
    .home-trainers__photo,
    .home-trainers__card:hover .home-trainers__photo {
        transition: none;
        transform: none !important;
    }
}

/* Social row — horizontal icon strip below the bio. Only shows
   when the trainer has at least one populated link/contact field.
   Display order is fixed in the template (IG, FB, TT, Web, Email,
   Phone). External links open in a new tab; mailto/tel open via
   the browser default. */
.home-trainers__social {
    /* T1: tightened to read as quiet tertiary actions, not equal-weight
       to the primary CTA. Smaller hit targets (32px → still ≥WCAG min
       touch with the icon padding), lighter borders, less gap. */
    list-style: none;
    padding: 0;
    margin: var(--space-4) 0 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-2);
    border-top: 1px solid var(--chrome-dim);
    padding-top: var(--space-4);
}

.home-trainers__social-item {
    margin: 0;
}

.home-trainers__social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 1px solid transparent;
    border-radius: 999px;
    color: var(--chrome-dim);
    text-decoration: none;
    transition: color var(--t-base), border-color var(--t-base), background var(--t-base);
}

.home-trainers__social-link:hover,
.home-trainers__social-link:focus-visible {
    color: var(--color-pearl);
    border-color: var(--chrome-dim);
    background: rgba(8, 7, 6, 0.03);
    outline: none;
}

.home-trainers__social-icon {
    width: 16px;
    height: 16px;
    display: block;
}

/* ════════════════════════════════════════════════════════════
   PROMPT PD2 — Critical pre-launch polish.

   Two changes:
     1. Trainers grid count-based fallback. With 1 or 2 active
        trainers the default 3-col desktop grid would render
        with empty cells. The .home-trainers__grid--count-1 /
        --count-2 modifier classes (emitted by the template)
        collapse the layout into centered compositions so the
        page reads as composed rather than broken.
     2. Section transition gradient. --section-transition is
        defined in tokens.css but never applied; this adds an
        80px gradient strip at the top of every contained
        (non-photo-overlay) section so adjacent same-surface
        sections gain subtle compositional breath. The strip
        sits at z-index: -1 inside an isolation: isolate
        stacking context so it never obscures content.

   Public site only. Admin / login untouched.
   ════════════════════════════════════════════════════════════ */

/* ── Trainers grid count-based fallback ──────────────────── */

@media (min-width: 768px) {
    .home-trainers__grid--count-1 {
        grid-template-columns: minmax(0, 480px);
        justify-content: center;
    }
}

@media (min-width: 1024px) {
    .home-trainers__grid--count-2 {
        grid-template-columns: repeat(2, minmax(0, 480px));
        justify-content: center;
    }
}

/* ── Section transition gradient ─────────────────────────── */
/* Applied to contained (non-photo-overlay) sections only.
   Photo-overlay sections — .hero, .home-quote, .home-banner-manifesto,
   .home-final (with backdrop), .home-find-quote — and the page-entry
   .page-hero are deliberately excluded. .home-find is excluded because
   its full-bleed map IS the section backdrop; a gradient strip on top
   would obscure the map's upper edge. .cms-image-block--bleed is
   excluded for the same reason; --container variant is included. */

.home-standard,
.home-features,
.home-pricing,
.home-stat-strip,
.home-equipment-strip,
.home-gallery,
.home-trainers,
.home-final--flat,
.cms-accordion,
.cms-comparison,
.cms-timeline,
.cms-contact-form,
.cms-rich-text,
.cms-video-embed,
.cms-image-block--container {
    position: relative;
    isolation: isolate;
}

/* TI5D: replaced PD2's invisible cream→cream gradient with a visible
   1px warm-dark hairline. Marks each section boundary clearly on
   cream-to-cream surfaces (Tracksmith / Aesop editorial pattern). Dark
   backdrop sections excluded — their surface flip serves as the visual
   boundary. */
.home-standard::before,
.home-features::before,
.home-pricing::before,
.home-stat-strip::before,
.home-equipment-strip::before,
.home-gallery::before,
.home-trainers::before,
.home-final--flat::before,
.cms-accordion::before,
.cms-comparison::before,
.cms-timeline::before,
.cms-contact-form::before,
.cms-rich-text::before,
.cms-video-embed::before,
.cms-image-block--container::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--color-divider-strong);
    z-index: 0;
    pointer-events: none;
}

/* ════════════════════════════════════════════════════════════
   PROMPT PD3 — Surface depth + typographic depth pass.

   Three sub-blocks below:
     1. Bronze-wash surface tier (Step 4) — one substantive section
        per page gets --color-onyx-bronze-wash for rhythmic depth.
        Dependency: section_anchor_id values; if those change in
        admin the bronze-wash silently no-ops.
     2. Drop cap on first narrative per page (Step 6) — sibling-
        combinator inversion pattern. Apply by default to every
        .home-standard, then revert on any preceded by another
        .home-standard sibling. Edge case verified: 24/7 Access
        has two narratives — only the first gets the cap.
     3. Pull_quote hanging punctuation (Step 5) — HELD until
        pull_quote §65 (homepage) has its wrapping curly quotes
        stripped via admin. The CSS would otherwise render doubled
        opening quotes on the homepage moment.
   ════════════════════════════════════════════════════════════ */

/* ── PD3 Step 4: Bronze-wash placements ──────────────────── */
/* Five anchor-ID targets. If a section's section_anchor_id is
   renamed in admin, the matching rule no-ops silently. */

#history.cms-timeline,
#pillars.home-features,
#compare.cms-comparison,
#scenarios.home-features {
    /* TI5A: switched from --color-onyx-bronze-wash (TI2 collapsed to onyx-deep)
       to --color-onyx-deeper (#F2EDE3 — meaningful warm depth tier). One
       distinguished "premium moment" per page. The bronze-wash token is
       now graveyard; remove in a future polish pass.

       Moment 3 (stats) removed from this list: the stats section was
       upgraded from "bronze-wash cream elevation" to "true dark
       moment" (background: var(--color-pearl) in the .home-stat-strip
       block above). The ID+class specificity of #stats.home-stat-strip
       would override that dark treatment if left in this selector
       list — silent visual regression. */
    background: var(--color-onyx-deeper);
}

/* ── PD3 Step 6: Drop cap on first narrative per page ────── */

.home-standard .home-standard__body > p:first-of-type::first-letter {
    font-family: var(--font-display);
    font-size: 4em;
    line-height: 0.85;
    float: left;
    margin-right: 0.12em;
    margin-top: 0.05em;
    margin-bottom: -0.05em;
    color: var(--color-bone);
    letter-spacing: var(--tracking-display);
    font-feature-settings: "kern" 1, "calt" 1;
}

/* Inversion: any narrative preceded by another narrative sibling
   reverts to inherited body treatment so only the first narrative
   on a page carries the drop cap. */
.home-standard ~ .home-standard .home-standard__body > p:first-of-type::first-letter {
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    float: none;
    margin: 0;
    color: inherit;
    letter-spacing: inherit;
    font-feature-settings: inherit;
}

/* ════════════════════════════════════════════════════════════
   TI5A — BACKDROP VARIANTS
   Opt-in dramatic full-bleed-photo variants for pull_quote,
   banner_manifesto, and cta_strip. Editorial / flat remain the
   defaults. display_mode in content_json selects.

   Common pattern: photo div absolute z:1, cream-tinted overlay
   absolute z:2, content z:10. Text is warm-dark with a subtle
   white text-shadow halo for legibility against the photo wash.

   Forward-compat: each .__backdrop wrapper holds an <img> today;
   wrapping a <video autoplay loop muted playsinline> instead
   would inherit the same overlay + content composition. No CSS
   changes needed for that future case.
   ════════════════════════════════════════════════════════════ */

/* ── pull_quote — backdrop variant ───────────────────────── */
.home-quote--backdrop {
    min-height: 70vh;
    display: flex;
    align-items: center;
    overflow: hidden;
    isolation: isolate;
    position: relative;
    padding: var(--section-y-large) 0;
    background: var(--color-onyx);              /* cream fallback if no photo */
}

.home-quote--backdrop .home-quote__backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
}

.home-quote--backdrop .home-quote__backdrop img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 50%;
    display: block;
}

.home-quote--backdrop .home-quote__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    /* TI5B: dark overlay restored (pre-inversion proven values).
       Text tokens flip to warm-white via .home-quote--backdrop scope
       override in tokens.css. */
    background: linear-gradient(180deg,
        rgba(11, 11, 14, 0.55) 0%,
        rgba(11, 11, 14, 0.35) 50%,
        rgba(11, 11, 14, 0.6) 100%);
    pointer-events: none;
}

.home-quote--backdrop .container {
    position: relative;
    z-index: 10;
}

.home-quote--backdrop .home-quote__text {
    margin: 0;
    max-width: 1100px;
}

.home-quote--backdrop .home-quote__text p {
    font-family: var(--font-display);
    font-size: clamp(2rem, 4vw, 3.5rem);
    font-weight: 400;
    line-height: var(--leading-snug);
    letter-spacing: var(--tracking-display);
    text-transform: none;
    color: var(--color-bone);                  /* warm-white via scope override */
    text-shadow: 0 4px 32px rgba(0, 0, 0, 0.5); /* TI5B: dark-overlay halo, pre-inversion value */
    margin: 0 0 var(--space-6);
}

/* ── banner_manifesto — backdrop variant ─────────────────── */
.home-banner-manifesto--backdrop {
    min-height: 55vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    isolation: isolate;
    position: relative;
    padding: var(--section-y) 0;
    background: var(--color-onyx);
}

.home-banner-manifesto--backdrop .home-banner-manifesto__backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
}

.home-banner-manifesto--backdrop .home-banner-manifesto__backdrop img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: 50% 50%;
    display: block;
}

.home-banner-manifesto--backdrop .home-banner-manifesto__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    /* TI5B: dark overlay restored (pre-inversion proven values). */
    background: linear-gradient(180deg,
        rgba(11, 11, 14, 0.6) 0%,
        rgba(11, 11, 14, 0.4) 50%,
        rgba(11, 11, 14, 0.7) 100%);
    pointer-events: none;
}

.home-banner-manifesto--backdrop .container {
    position: relative;
    z-index: 10;
    text-align: center;
}

.home-banner-manifesto--backdrop .home-banner-manifesto__line {
    color: var(--color-bone);                  /* warm-white via scope override */
    text-shadow: 0 4px 32px rgba(0, 0, 0, 0.5); /* TI5B: dark-overlay halo */
    max-width: 24ch;
    margin: 0 auto;
}

/* ══════════════════════════════════════════════════════════════
   banner_manifesto — CINEMATIC (default)
   A dark, type-led brand moment that needs NO photography. When a
   backdrop photo is uploaded it snaps into the same frame (the <img>
   simply replaces the ghost wordmark). Self-contained colours so it
   reads correctly on the cream page without a token-scope flip.
   ══════════════════════════════════════════════════════════════ */
.home-banner-manifesto--cinematic {
    position: relative;
    min-height: 62vh;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    isolation: isolate;
    padding: var(--section-y-large) 0;
    /* warm-onyx depth gradient — the placeholder "set" */
    background: radial-gradient(135% 115% at 50% 0%, #17120c 0%, #0b0a08 55%, #060504 100%);
}

.home-banner-manifesto--cinematic .home-banner-manifesto__backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Photo state — slow Ken Burns drift for cinema */
.home-banner-manifesto--cinematic .home-banner-manifesto__backdrop img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transform: scale(1.05);
    animation: bmKenBurns 20s var(--ease-standard) infinite alternate;
}
@keyframes bmKenBurns { to { transform: scale(1.14); } }

/* Placeholder state — giant faint brand wordmark as texture */
.home-banner-manifesto__ghost {
    font-family: var(--font-display);
    font-size: clamp(7rem, 33vw, 24rem);
    line-height: 1;
    letter-spacing: -0.05em;
    color: rgba(255, 255, 255, 0.035);
    white-space: nowrap;
    user-select: none;
}

/* Scrim + film grain over whatever's behind */
.home-banner-manifesto--cinematic .home-banner-manifesto__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(6,5,4,0.55) 0%, rgba(6,5,4,0.22) 45%, rgba(6,5,4,0.78) 100%);
}
.home-banner-manifesto--cinematic .home-banner-manifesto__overlay::after {
    content: '';
    position: absolute;
    inset: 0;
    opacity: 0.45;
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    background-size: 140px 140px;
}

.home-banner-manifesto--cinematic .container {
    position: relative;
    z-index: 10;
    text-align: center;
    padding-inline: var(--gutter);
}
.home-banner-manifesto--cinematic .section-label {
    color: rgba(245, 240, 232, 0.62);
    margin: 0 0 var(--space-5);
}
.home-banner-manifesto--cinematic .home-banner-manifesto__line {
    font-family: var(--font-display);
    font-size: clamp(2.25rem, 6vw, 5rem);
    font-weight: 400;
    line-height: 1.05;
    letter-spacing: -0.03em;
    color: #FAF6EF;
    max-width: 20ch;
    margin: 0 auto;
    text-shadow: 0 6px 44px rgba(0, 0, 0, 0.55);
}
/* Stagger the entrance — children get .reveal-on-scroll from the reveal engine */
.home-banner-manifesto--cinematic .moment > *:nth-child(2) { transition-delay: 0.12s; }

@media (prefers-reduced-motion: reduce) {
    .home-banner-manifesto--cinematic .home-banner-manifesto__backdrop img { animation: none; transform: none; }
}

/* ── cta_strip — backdrop variant ────────────────────────── */
.home-final--backdrop {
    min-height: 60vh;
    padding: var(--section-y-large) 0;
    overflow: hidden;
    isolation: isolate;
    display: flex;
    align-items: center;
    position: relative;
    background: var(--color-onyx);              /* cream fallback if no photo */
}

.home-final--backdrop .home-final__photo {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-size: cover;
    background-position: center;
    background-color: var(--color-onyx);
}

.home-final--backdrop .home-final__photo {
    /* TI5B: photo darkening filter (pre-inversion value). */
    filter: brightness(0.55) contrast(1.1);
}

.home-final--backdrop .home-final__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    /* TI5B: dark overlay restored (pre-inversion proven values). */
    background: linear-gradient(180deg,
        rgba(11, 11, 14, 0.7) 0%,
        rgba(11, 11, 14, 0.5) 50%,
        rgba(11, 11, 14, 0.8) 100%);
    pointer-events: none;
}

.home-final--backdrop .home-final__inner {
    position: relative;
    z-index: 10;
    text-align: center;
}

.home-final--backdrop .home-final__headline {
    color: var(--color-pearl);                  /* pure white via scope override */
    text-shadow: 0 4px 40px rgba(0, 0, 0, 0.5); /* TI5B: dark-overlay halo */
}

.home-final--backdrop .home-final__subtitle {
    color: var(--color-bone);                   /* warm-white via scope override */
    text-shadow: 0 2px 16px rgba(0, 0, 0, 0.4);
}

/* ─── Narrative — backdrop variant (TI5B) ──────────────────
   Optional cinematic backdrop for the narrative section. Default
   flat (cream surface, prose-contained text). Backdrop renders
   full-bleed photo + dark overlay + warm-white text. Forward-compat:
   future video would replace the bg-image div. */
.home-standard--backdrop {
    position: relative;
    min-height: 60vh;
    display: flex;
    align-items: center;
    overflow: hidden;
    isolation: isolate;
    padding-block: var(--section-y-large);
}

.home-standard--backdrop .home-standard__backdrop {
    position: absolute;
    inset: 0;
    z-index: 1;
    background-size: cover;
    background-repeat: no-repeat;
    background-color: #0a0908;
}

.home-standard--backdrop .home-standard__overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    background: linear-gradient(180deg,
        rgba(11, 11, 14, 0.6) 0%,
        rgba(11, 11, 14, 0.4) 50%,
        rgba(11, 11, 14, 0.7) 100%);
}

.home-standard--backdrop .home-standard__inner {
    position: relative;
    z-index: 10;
}

.home-standard--backdrop .section-title,
.home-standard--backdrop h2 {
    color: var(--color-bone);                  /* warm-white via scope override */
    text-shadow: 0 4px 32px rgba(0, 0, 0, 0.5);
}

.home-standard--backdrop .home-standard__body,
.home-standard--backdrop .home-standard__body p {
    color: var(--color-bone);                  /* warm-white via scope override */
    text-shadow: 0 2px 16px rgba(0, 0, 0, 0.4);
}

/* ════════════════════════════════════════════════════════════
   TI5E POLISH — section-after-hero padding + FAQ density.

   Three targeted fixes:
     1. Section-after-hero top padding so eyebrows don't clip under
        the 88px fixed header on first scroll.
     2. Accordion section title surgical reduction (same pattern as
        narrative section title in TI5D).
     3. Accordion item closed-state padding 12px → 8px per side.
        Open state stays generous.
   ════════════════════════════════════════════════════════════ */

/* TI5E Step 1: Section-after-hero top padding.
   When a section immediately follows a hero, its top edge sits at
   viewport top — directly under the ~88px fixed header. Eyebrow gets
   clipped on scroll.

   Initially set to var(--space-16) (64px) but that produced ~10–20px
   clearance below the header — visibly tight on the pricing page
   "PLANS" eyebrow. Bumped to var(--space-32) (128px) for ~40px
   clearance below the header — comfortable editorial breath. */
main > section:first-of-type:not(.hero):not(.page-hero):not(.page-hero--backdrop),
.hero + section,
.page-hero + section,
.page-hero--backdrop + section {
    padding-top: var(--space-40);   /* 160px — generous header clearance */
}

/* TI5E Step 2: Accordion section title — surgical reduction.
   "Common questions" / "Frequently asked" shouldn't dominate the FAQ
   list. Same pattern as TI5D narrative headline reduction. */
.cms-accordion .section-title {
    font-size: clamp(1.5rem, 3.5vw, 2.5rem);
    line-height: 1.05;
    max-width: 20ch;
    text-transform: none;
}

/* ════════════════════════════════════════════════════════════
   Members hub — three-up routing cards.

   Drives the /members page: intro headline + N routing cards.
   Each card is an equal-weight first-class choice (no ranking).
   Cream-on-cream subtle elevation matching the confirmation card
   pattern (white surface, divider border, soft shadow).
   ════════════════════════════════════════════════════════════ */
.members-hub {
    padding: var(--space-10) 0 var(--space-12);
}

.members-hub__inner {
    /* Wider than container--prose (720px) so the three cards have
       substantial per-card width (~330px) — "BILLING OR ACCOUNT
       QUESTION" fits 2 lines instead of wrapping to 3. Narrower
       than the full --max-width (1280px) so cards don't sparse
       out at viewport edges. Headline + cards + fallback all share
       this container's axis, so the visual group reads unified. */
    max-width: 1080px;
    display: flex;
    flex-direction: column;
    gap: var(--space-8);
}

.members-hub__intro {
    text-align: center;
}
.members-hub__intro .section-label {
    margin: 0 0 var(--space-3);
}
.members-hub__headline {
    /* Calibrated to utility-page scale, not hero. The previous
       --text-4xl wrapped "HOW CAN WE / HELP?" on standard desktop
       viewports because the prose-width container narrowed it.
       --text-2xl fits on one line at all reasonable widths and
       reads as confident anchor without being theatrical. */
    margin: 0 0 var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-2xl);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    color: var(--color-pearl);
    line-height: 1.1;
}
.members-hub__subtitle {
    margin: 0 auto;
    max-width: 36rem;
    font-family: var(--font-body);
    font-size: var(--text-lg);
    color: var(--color-steel);
    line-height: var(--leading-normal);
}

.members-hub__cards {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-5);
}

.members-hub__card {
    display: flex;
    flex-direction: column;
    padding: var(--space-6);
    background: var(--color-onyx-rich);
    border: 1px solid var(--color-divider);
    box-shadow: 0 1px 3px rgba(8, 7, 6, 0.025), 0 6px 20px rgba(8, 7, 6, 0.04);
}

/* Card icon — small line-art SVG above the headline. Muted color
   (steel) so the icon supports scannability without competing
   with the headline. Matches the trainer-social and bottom-nav
   icon convention: 24×24, currentColor, 1.5px stroke. */
.members-hub__card-icon-wrap {
    margin: 0 0 var(--space-3);
    color: var(--color-steel);
    line-height: 0;
}
.members-hub__card-icon {
    width: 28px;
    height: 28px;
    display: block;
}

.members-hub__card-headline {
    margin: 0 0 var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: 0.01em;
    color: var(--color-pearl);
    line-height: 1.1;
}
.members-hub__card-description {
    margin: 0 0 var(--space-5);
    flex-grow: 1;
    color: var(--color-bone);
    font-size: var(--text-base);
    line-height: var(--leading-relaxed);
}
.members-hub__card-cta {
    margin: 0;
}
.members-hub__card-btn {
    width: 100%;
    justify-content: center;
    padding: 12px 18px;
}
.members-hub__card-sub {
    margin: var(--space-3) 0 0;
    font-size: var(--text-sm);
    color: var(--color-steel-muted);
    line-height: var(--leading-normal);
    text-align: center;
}
.members-hub__card-sub a {
    color: var(--color-steel);
    text-decoration: underline;
    text-underline-offset: 3px;
}
.members-hub__card-sub a:hover {
    color: var(--color-pearl);
}

/* Quiet fallback line below the cards — catches anyone whose need
   isn't covered by the three cards. Centered, small, muted text;
   the mailto link is subtly underlined. Pulls from contact_email
   setting (rendered conditionally — silent if setting is blank). */
.members-hub__fallback {
    margin: 0;
    text-align: center;
    color: var(--color-steel-muted);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
}
.members-hub__fallback a {
    color: var(--color-steel);
    text-decoration: underline;
    text-underline-offset: 3px;
    font-weight: var(--weight-semibold);
}
.members-hub__fallback a:hover {
    color: var(--color-pearl);
}

/* Tablet — 2 columns, last card spans both. */
@media (max-width: 900px) {
    .members-hub__cards {
        grid-template-columns: repeat(2, 1fr);
    }
    .members-hub__card:last-child:nth-child(odd) {
        grid-column: 1 / -1;
    }
}

/* Mobile — single column stack. */
@media (max-width: 600px) {
    .members-hub {
        padding: var(--space-7) 0 var(--space-10);
    }
    .members-hub__inner {
        gap: var(--space-6);
    }
    .members-hub__cards {
        grid-template-columns: 1fr;
        gap: var(--space-4);
    }
    .members-hub__card:last-child:nth-child(odd) {
        grid-column: auto;
    }
    .members-hub__card {
        padding: var(--space-5);
    }
}
