/* ═══════════════════════════════════════════════════════════
   ONYX FITNESS — COMPONENT STYLES
   Comprehensive component library. Each section commented.

   Section 1: Foundation components (from 4-B-1).
   Section 2: Site chrome — loader, scroll progress, glass nav,
              section nav, mobile bottom nav, grain overlay.
   Section 3: Refactored banner and footer on chrome accent.
   ═══════════════════════════════════════════════════════════ */

/* ─── Skip link ───────────────────────────────────────── */
.skip-link {
  position: absolute;
  top: -40px;
  left: var(--space-4);
  z-index: var(--z-toast);
  padding: var(--space-2) var(--space-4);
  background: var(--chrome-bright);
  color: var(--color-onyx);
  font-weight: var(--weight-semibold);
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  transition: top var(--t-base);
}
.skip-link:focus {
  top: var(--space-4);
}

/* ─── Brand wordmark ──────────────────────────────────────
   Pure-CSS typographic logo. "ONYX" large in Archivo Black,
   "FITNESS" smaller and letter-spaced below. Three sizes,
   plus an inverted variant for light backgrounds. Restored
   in Prompt BR1.1 after BR1's all-PNG approach was reverted
   in favour of symbol-icon + typographic-wordmark composition
   (see .brand-block below).
   ──────────────────────────────────────────────────────── */
.brand-wordmark {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    line-height: 1;
    color: var(--color-bone);
    text-decoration: none;
    font-family: var(--font-display);
    font-weight: 400;
    text-transform: uppercase;
    user-select: none;
    transition: color var(--t-base);
}

.brand-wordmark:hover {
    color: var(--color-pearl);
}

.brand-wordmark__primary {
    font-family: var(--font-display);
    font-weight: 400;
    letter-spacing: -0.01em;
    line-height: 0.9;
    display: block;
}

.brand-wordmark__secondary {
    font-family: var(--font-display);
    font-weight: 400;
    letter-spacing: 0.2em;
    line-height: 1;
    display: block;
    margin-top: 0.2em;
    /* Tracking visually pushes the word right; pull back slightly
       so left edges read as flush. */
    margin-left: -0.05em;
}

/* Size: Small — nav. Sized for anchor presence against the
   tall fixed header (Prompt 18 — was 22/7, raised to 32/9). */
.brand-wordmark--sm .brand-wordmark__primary   { font-size: 32px; }
.brand-wordmark--sm .brand-wordmark__secondary { font-size: 9px;  }

/* Size: Medium — hero brand anchor, admin login */
.brand-wordmark--md .brand-wordmark__primary   { font-size: 32px; }
.brand-wordmark--md .brand-wordmark__secondary { font-size: 9px;  }

/* Size: Large — footer brand block */
.brand-wordmark--lg .brand-wordmark__primary   { font-size: 48px; }
.brand-wordmark--lg .brand-wordmark__secondary { font-size: 13px; }

/* Inverted for light backgrounds */
.brand-wordmark--invert         { color: var(--color-onyx-deep); }
.brand-wordmark--invert:hover   { color: var(--color-onyx); }

@media (max-width: 640px) {
    .brand-wordmark--sm .brand-wordmark__primary   { font-size: 24px; }
    .brand-wordmark--sm .brand-wordmark__secondary { font-size: 7px;  }
}

/* ─── Brand block ─────────────────────────────────────────
   Symbol icon + typographic wordmark composition (Prompt
   BR1.1). The symbol is the designer's chrome mark; the
   wordmark is .brand-wordmark above. Used for public header
   and footer placements. Admin contexts use their own
   image-only treatments (.admin-rail__brand,
   .admin-login__brand) so this composition only applies
   to public chrome.
   ──────────────────────────────────────────────────────── */
.brand-block {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);             /* 12px between symbol + wordmark */
    text-decoration: none;
    color: inherit;
}

.brand-block__mark {
    display: block;
    flex-shrink: 0;
    width: 40px;
    height: 40px;
}

/* Single vector lockup (mark + ONYX FITNESS wordmark in one SVG).
   width:auto keeps the artwork's own aspect; the width/height
   attributes in the markup reserve space (no layout shift). */
.brand-block__logo {
    display: block;
    flex-shrink: 0;
    /* Sized to carry equal visual weight against the bold
       uppercase nav + CTAs in the tall header (pairs the two
       sides rather than the logo reading small/lost). */
    height: 48px;
    width: auto;
}

.brand-block--footer {
    gap: var(--space-4);             /* 16px — more breathing room */
}

.brand-block--footer .brand-block__mark {
    width: 56px;
    height: 56px;
}

.brand-block__logo--footer {
    height: 52px;
}

@media (max-width: 768px) {
    .brand-block__mark {
        width: 36px;
        height: 36px;
    }
    .brand-block--footer .brand-block__mark {
        width: 48px;
        height: 48px;
    }
    .brand-block__logo {
        height: 40px;
    }
    .brand-block__logo--footer {
        height: 44px;
    }
}

/* ─── Section labels and titles ───────────────────────────
   Used at the top of every major section.
   .section-label — small uppercase eyebrow with hairline
   .section-title — large display headline with em italics
   ──────────────────────────────────────────────────────── */
.section-label {
  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);  /* TI3: 300 → 500 — Light too thin on cream surface; Medium reads as intentional editorial label (TI1 §1.5) */
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--chrome);
  margin-bottom: var(--space-6);
}
.section-label::before {
  content: '';
  width: 32px;
  height: 1px;
  background: var(--chrome-muted);
}

.section-title {
  font-family: var(--font-display);
  font-size: var(--text-4xl);
  font-weight: 400;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-display);
  color: var(--color-bone);
  text-transform: uppercase;
  margin-bottom: var(--space-6);
  max-width: 18ch;
}

.section-desc {
  font-size: var(--text-lg);
  color: var(--color-steel);
  line-height: var(--leading-loose);
  max-width: var(--max-width-prose);
  margin-bottom: var(--space-8);
}

/* ─── Eyebrow standalone (when not part of section-label) ─ */
.eyebrow {
  display: inline-block;
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);  /* TI3: 300 → 500 — consistent with .section-label on cream surface */
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  color: var(--chrome);
}

/* ─── Buttons ────────────────────────────────────────────
   Slide-fill effect on primary CTA — pseudo-element fills
   from bottom on hover, text color inverts.
   ──────────────────────────────────────────────────────── */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-8);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  text-decoration: none;
  border: 1px solid var(--chrome);
  background: transparent;
  color: var(--chrome);
  cursor: pointer;
  overflow: hidden;
  transition: color var(--t-smooth), transform var(--t-base), box-shadow var(--t-base);
  white-space: nowrap;
  z-index: 1;
}

.btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--chrome);
  transform: translateY(101%);
  transition: transform var(--t-smooth);
  z-index: -1;
}

.btn:hover {
  color: var(--color-onyx);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md), var(--glow-chrome-sm);
}

.btn:hover::before {
  transform: translateY(0);
}

/* Primary — chrome filled by default, brightens on hover */
.btn--primary {
  background: var(--chrome);
  color: var(--color-onyx);
  border-color: var(--chrome);
}
.btn--primary::before {
  background: var(--chrome-bright);
}
.btn--primary:hover {
  color: var(--color-onyx);
}

/* Ghost — alias for default outline (intentionally empty) */
.btn--ghost {
  /* uses default .btn styles */
}

/* Small variant */
.btn--small {
  padding: var(--space-2) var(--space-6);
  font-size: var(--text-xs);
}

/* Full width */
.btn--full {
  width: 100%;
}

/* ─── Divider ────────────────────────────────────────────── */
.divider {
  height: 1px;
  border: 0;
  background: linear-gradient(90deg, transparent 0%, var(--color-divider-strong) 50%, transparent 100%);
  margin-block: var(--space-12);
}

/* ─── Form base ──────────────────────────────────────────── */
.form-group {
  margin-bottom: var(--space-6);
}

.form-label {
  display: block;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--chrome);
  margin-bottom: var(--space-2);
}

.form-input,
.form-textarea {
  width: 100%;
  padding: var(--space-3) 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--color-steel-dark);
  color: var(--color-bone);
  transition: border-color var(--t-base);
}

.form-input:focus,
.form-textarea:focus {
  outline: none;
  border-bottom-color: var(--chrome);
}

/* Suppress Chrome / Edge autofill yellow background — it ignores
   `background: transparent` above and renders its own canary fill
   that looks broken on the dark admin login + password screens.
   The 5000s transition is a documented hack to delay the actual
   browser fill long enough that the inset box-shadow keeps winning.
   (Prompt 30) */
.form-input:-webkit-autofill,
.form-input:-webkit-autofill:hover,
.form-input:-webkit-autofill:focus,
.form-input:-webkit-autofill:active {
  -webkit-text-fill-color: var(--color-bone);
  -webkit-box-shadow: 0 0 0 1000px transparent inset;
  transition: background-color 5000s ease-in-out 0s;
  caret-color: var(--color-bone);
}

/* Hide Edge's password-reveal eye + IE's clear-x on admin password
   inputs — the underline-only treatment doesn't have room for them
   and they break visual rhythm. */
.form-input::-ms-reveal,
.form-input::-ms-clear {
  display: none;
}

.form-textarea {
  min-height: 8rem;
  resize: vertical;
}

.form-error {
  color: var(--color-warning);
  font-size: var(--text-sm);
  margin-top: var(--space-2);
}

/* ─── Surface utility ────────────────────────────────────
   Adds the grain texture overlay to any element via ::before.
   Used on dark sections for tactile material feel.
   ──────────────────────────────────────────────────────── */
.surface--textured {
  position: relative;
  isolation: isolate;
}

.surface--textured::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E");
  pointer-events: none;
  opacity: 0.5;
  z-index: -1;
}

/* ─── Slate surface utility (TI4 — simplified) ────────────
   Was a polished-stone composition (grain + polish + vignette)
   designed for the prior dark surface. The dark stone effect
   doesn't translate to warm cream. Now a subtle lifted-cream
   tier (--color-onyx-deep vs page --color-onyx) per operator
   decision Q5 / option 3.

   The /assets/img/textures/slate-*.svg files remain on disk
   in case a future polish pass reintroduces a cream-friendly
   texture, but they are no longer referenced.
   ──────────────────────────────────────────────────────── */
.surface--slate {
    background-color: var(--color-onyx-deep);
}

/* ═══════════════════════════════════════════════════════════
   SITE CHROME — Premium interactive elements
   ═══════════════════════════════════════════════════════════ */

/* ─── Grain texture overlay ──────────────────────────────
   Site-wide subtle film grain. Fixed positioning so it
   doesn't scroll. Sits above content but below interactive
   elements (z-index 50, nav is 40, but grain has
   pointer-events: none).
   ──────────────────────────────────────────────────────── */
.site-grain {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 50;
  opacity: 0.35;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.92' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E");
}

/* ─── Scroll Progress Bar ─────────────────────────────────
   Revived 2026-06-29 (was removed in TI5A). A thin near-black
   (#1A1A1A) bar pinned to the very top of the viewport that
   fills left→right as the page scrolls. JS sets scaleX
   (main.js). Sits just above the header; the preview-mode
   rules below offset it. Colour is a single line on
   .scroll-progress__bar — swap to change it. */
.scroll-progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    z-index: 60;          /* above header (40) AND the film-grain overlay (50), so the gold stays crisp */
    pointer-events: none;
}
.scroll-progress__bar {
    display: block;          /* the bar is a <span> (inline by default); block makes width/height apply */
    height: 100%;
    width: 100%;
    transform: scaleX(0);
    transform-origin: left center;
    background: #1A1A1A;                 /* brand near-black */
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
    will-change: transform;
}

/* ─── Site Header — premium fitness convention ───────────
   Tall, full-width, fixed. No morph on scroll. Stable
   architectural presence. Glassmorphism backdrop survives
   from prior iteration; only the shape and content change.
   Subtle background deepening at >32px scroll provides
   affordance without changing geometry.
   ──────────────────────────────────────────────────────── */
.site-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: var(--z-nav);
    padding: var(--space-6) var(--space-12);
    /* TI5D: pure white nav with warm-dark hairline beneath. White against
       cream page creates intentional Equinox-style nav banding; the hairline
       softens the transition. */
    background-color: var(--color-onyx-rich);
    border-bottom: 1px solid var(--color-divider-strong);
    backdrop-filter: var(--blur-lg);
    -webkit-backdrop-filter: var(--blur-lg);
    transition: background var(--t-base), border-color var(--t-base), box-shadow var(--t-base), top var(--t-base);
}

/* ─── Preview-mode banner (Prompt 23, Phase 4d) ──────────────
   Fixed at the very top of the viewport; pushes the site header
   and any other top-anchored UI down by its height so nothing
   overlaps. Only renders when an authenticated admin loads a
   page with ?preview=1 — invisible to ordinary visitors. */
.preview-banner {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: calc(var(--z-nav) + 5);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-4);
    flex-wrap: wrap;
    padding: var(--space-2) var(--space-4);
    background: linear-gradient(90deg, #d97757, #b85b3f);
    color: var(--color-onyx);
    font-family: var(--font-body);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    border-bottom: 1px solid rgba(0, 0, 0, 0.25);
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
}

.preview-banner__label {
    background: var(--color-onyx);
    color: #f3d2b9;
    padding: 2px var(--space-2);
    border-radius: var(--radius-sm);
    letter-spacing: var(--tracking-widest);
}

.preview-banner__text {
    text-transform: none;
    font-weight: var(--weight-regular);
    letter-spacing: 0;
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
}

.preview-banner__exit {
    color: var(--color-onyx);
    text-decoration: underline;
    text-underline-offset: 2px;
    flex-shrink: 0;
}
.preview-banner__exit:hover {
    color: var(--color-pearl);
}

/* When preview mode is active, push fixed top-anchored UI down
   so the banner doesn't overlap the header or scroll-progress
   bar. The section-nav is centered vertically (top: 50%) so it
   doesn't need adjustment. */
body.is-preview-mode .site-header {
    top: 40px;
}
body.is-preview-mode .scroll-progress {
    top: 40px;
}

@media (max-width: 640px) {
    .preview-banner {
        padding: var(--space-2) var(--space-3);
        gap: var(--space-2);
    }
    .preview-banner__text {
        flex: 1 0 100%;
        order: 3;
    }
    /* Banner is taller on narrow screens because the explanation
       wraps to its own row — bump the offset accordingly. */
    body.is-preview-mode .site-header,
    body.is-preview-mode .scroll-progress {
        top: 72px;
    }
}

/* Subtle background deepening on scroll — no shape morph.
   TI3: hardcoded dark rgba replaced with cream rgba so scroll
   state slightly opacifies the warm-cream nav on light page,
   matching the inverted glass-nav token in tokens.css. */
.site-header.is-scrolled {
    /* TI5D: stays white on scroll (no darkening shift) — shadow elevation
       does the work of confirming scroll state. */
    background-color: rgba(255, 255, 255, 0.95);
    border-bottom-color: var(--color-divider-strong);
    box-shadow: var(--shadow-sm);
}

.site-header__inner {
    display: flex;
    /* The brand is now a single SVG lockup (an <img>), not a
       two-line text wordmark, so the old baseline trick no longer
       applies — an image has no text baseline and would float
       the logo upward. Center the logo against the nav cluster
       so the two read as one balanced bar. */
    align-items: center;
    justify-content: space-between;
    gap: var(--space-12);
    max-width: var(--max-width);
    margin-inline: auto;
}

.site-header__brand {
    text-decoration: none;
    flex-shrink: 0;
    transition: opacity var(--t-base);
}

.site-header__brand:hover {
    opacity: 0.85;
}

/* ─── Primary Navigation ───────────────────────────────── */
.site-nav {
    display: flex;
    align-items: center;
    gap: var(--space-12);
}

.site-nav__list {
    display: flex;
    align-items: center;
    gap: var(--space-10);
    list-style: none;
    padding: 0;
    margin: 0;
}

.site-nav__link {
    position: relative;
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    color: var(--color-bone);
    text-decoration: none;
    padding-block: var(--space-2);
    transition: color var(--t-base);
}

.site-nav__link:hover {
    color: var(--chrome-bright);
}

/* Underline indicator — appears on hover and active */
.site-nav__link::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--chrome-bright);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--t-smooth);
}

.site-nav__link:hover::after,
.site-nav__link[aria-current="page"]::after {
    transform: scaleX(1);
}

.site-nav__link[aria-current="page"] {
    color: var(--chrome-bright);
}

/* CTA — Join Now treated prominently */
.site-nav__cta {
    margin-left: var(--space-2);
}

.site-nav__cta .btn {
    padding: var(--space-3) var(--space-8);
    font-weight: var(--weight-bold);
    letter-spacing: var(--tracking-wider);
    border-width: 1px;
}

/* ─── Mobile hamburger toggle ──────────────────────────── */
.site-nav__toggle {
    display: none;
    width: 44px;
    height: 44px;
    position: relative;
    background: transparent;
    border: none;
    cursor: pointer;
    z-index: 3;
    -webkit-tap-highlight-color: transparent;
}

.site-nav__toggle-bar {
    display: block;
    width: 24px;
    height: 1.5px;
    background: var(--color-bone);
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    transition: all var(--t-smooth);
    transform-origin: center;
}

.site-nav__toggle-bar:nth-child(1) { top: 15px; }
.site-nav__toggle-bar:nth-child(2) { top: 22px; }
.site-nav__toggle-bar:nth-child(3) { top: 29px; }

.site-nav__toggle[aria-expanded="true"] .site-nav__toggle-bar { background: var(--chrome); }
.site-nav__toggle[aria-expanded="true"] .site-nav__toggle-bar:nth-child(1) {
    top: 22px; transform: translateX(-50%) rotate(45deg);
}
.site-nav__toggle[aria-expanded="true"] .site-nav__toggle-bar:nth-child(2) {
    opacity: 0; transform: translateX(-50%) scaleX(0);
}
.site-nav__toggle[aria-expanded="true"] .site-nav__toggle-bar:nth-child(3) {
    top: 22px; transform: translateX(-50%) rotate(-45deg);
}

/* ─── Mobile responsive ────────────────────────────────── */
@media (max-width: 880px) {
    .site-header {
        padding: var(--space-4) var(--space-6);
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
    .site-header__inner {
        /* Centered on every breakpoint now that the brand is an
           SVG lockup (desktop matches; see the base rule). Just
           tighten the gap on mobile. */
        align-items: center;
        gap: var(--space-4);
    }
    .site-nav__toggle {
        display: block;
    }
    .site-nav {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        /* TI3: drawer surface bumped from --color-onyx-deep to
           --color-onyx-rich (white) for max contrast against the
           cream page surface. Shadow adds elevation so the drawer
           reads as a layer above the page, not a continuation. */
        background: var(--color-onyx-rich);
        box-shadow: var(--shadow-lg);
        backdrop-filter: var(--blur-lg);
        -webkit-backdrop-filter: var(--blur-lg);
        padding: 6rem var(--gutter) var(--space-12);
        max-height: 0;
        overflow: hidden;
        opacity: 0;
        visibility: hidden;
        transition: max-height var(--t-smooth), opacity var(--t-base), visibility var(--t-base);
        z-index: 1;
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-6);
    }
    .site-nav[data-open="true"] {
        max-height: 100vh;
        opacity: 1;
        visibility: visible;
    }
    .site-nav__list {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-4);
        width: 100%;
    }
    .site-nav__link {
        font-size: var(--text-xl);
        padding-block: var(--space-3);
    }
    .site-nav__link::after { display: none; }
    .site-nav__cta {
        margin-left: 0;
        margin-top: var(--space-4);
        width: 100%;
    }
    .site-nav__cta .btn {
        width: 100%;
        text-align: center;
        justify-content: center;
    }
}

/* ════════════════════════════════════════════════════════════
   Members dropdown — primary-nav child item that expands to
   reveal Member Portal + Member Help.

   Desktop: absolute-positioned panel below the trigger. Opens
   on hover OR click (data-members-open="true" toggled by JS in
   main.js). Closes on outside-click, Escape, or item-click.

   Mobile: lives inside the hamburger drawer. The trigger toggles
   an inline accordion (max-height transition). The same
   data-members-open attribute drives both states; CSS just
   renders different geometry per breakpoint.
   ════════════════════════════════════════════════════════════ */
.site-nav__members {
    position: relative;
}
.site-nav__members-trigger {
    /* Trigger inherits .site-nav__link visual treatment but is a
       button element — reset native button chrome and align the
       caret inline with the label. */
    background: transparent;
    border: 0;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font: inherit;
    color: inherit;
    -webkit-tap-highlight-color: transparent;
}
.site-nav__members-caret {
    display: inline-block;
    font-size: 0.75em;
    transition: transform var(--t-smooth);
}
.site-nav__members[data-members-open="true"] .site-nav__members-caret {
    transform: rotate(180deg);
}

/* Desktop panel ────────────────────────────────────────────── */
.site-nav__members-panel {
    /* Hidden by default. Reveal via the [data-members-open] attribute
       toggled by JS. Use opacity + visibility (not display:none) so
       focus management + transitions work cleanly. */
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 220px;
    padding: var(--space-3) 0;
    background: var(--color-onyx-rich);
    border: 1px solid var(--color-divider);
    box-shadow: 0 4px 16px rgba(8, 7, 6, 0.08), 0 12px 32px rgba(8, 7, 6, 0.06);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    transition: opacity var(--t-base), visibility var(--t-base), transform var(--t-base);
    z-index: 10;
}
.site-nav__members[data-members-open="true"] .site-nav__members-panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.site-nav__members-item {
    display: block;
    padding: var(--space-3) var(--space-5);
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wider);
    text-transform: uppercase;
    color: var(--color-bone);
    text-decoration: none;
    transition: background var(--t-base), color var(--t-base);
}
.site-nav__members-item:hover,
.site-nav__members-item:focus-visible {
    background: rgba(8, 7, 6, 0.04);
    color: var(--color-pearl);
    outline: none;
}
.site-nav__members-item[aria-current="page"] {
    color: var(--color-pearl);
}

/* Mobile accordion variant ─────────────────────────────────── */
@media (max-width: 880px) {
    .site-nav__members-panel {
        /* Inside the hamburger drawer: drop the absolute positioning,
           expand inline instead of float above. The accordion uses
           max-height for the open/close transition. */
        position: static;
        top: auto;
        right: auto;
        min-width: 0;
        width: 100%;
        padding: 0;
        background: transparent;
        border: 0;
        box-shadow: none;
        transform: none;
        max-height: 0;
        overflow: hidden;
        opacity: 1;
        visibility: visible;
        transition: max-height var(--t-smooth);
    }
    .site-nav__members[data-members-open="true"] .site-nav__members-panel {
        /* Generous max-height that fits the 2 items + padding on any
           reasonable viewport. Used in lieu of auto for the transition. */
        max-height: 240px;
        padding: var(--space-3) 0 var(--space-2);
    }
    .site-nav__members-item {
        padding: var(--space-3) var(--space-4);
        font-size: var(--text-lg);
        /* Slight indent to read as nested under the trigger. */
        padding-left: var(--space-5);
    }
    .site-nav__members-item:hover,
    .site-nav__members-item:focus-visible {
        background: rgba(8, 7, 6, 0.04);
    }
}

/* ─── Vertical Section Nav — removed in TI5A ─────────────
   Right-side floating dots were a dark-site sophistication.
   Reference brands (Tracksmith, Equinox) don't use them.
   Removed to de-clutter the right edge of every page. See
   main.js for the removed JS populate/tracking logic. */

/* ─── Mobile Bottom Nav ──────────────────────────────────
   Fixed bottom bar with 4 primary destinations.
   Visible only on mobile (≤768px). Adjusts content padding
   on the page body so it doesn't overlap content.
   ──────────────────────────────────────────────────────── */
.mobile-bottom-nav {
  display: none;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 35;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: var(--blur-lg);
  -webkit-backdrop-filter: var(--blur-lg);
  border-top: 1px solid var(--chrome-dim);
  padding: var(--space-2) 0;
  padding-bottom: max(var(--space-2), env(safe-area-inset-bottom));
}

@media (max-width: 768px) {
  .mobile-bottom-nav {
    display: flex;
    justify-content: space-around;
    align-items: center;
  }
  body { padding-bottom: 70px; }
}

.mobile-bottom-nav__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  flex: 1;
  padding: var(--space-2);
  text-decoration: none;
  color: var(--color-steel-muted);
  font-family: var(--font-body);
  font-size: 0.6rem;
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  transition: color var(--t-base);
  -webkit-tap-highlight-color: transparent;
}

.mobile-bottom-nav__icon {
  width: 20px;
  height: 20px;
  transition: transform var(--t-base);
}

.mobile-bottom-nav__item.is-active {
  color: var(--chrome-bright);
}
.mobile-bottom-nav__item.is-active .mobile-bottom-nav__icon {
  transform: translateY(-2px);
}

/* ─── Banner ─────────────────────────────────────────────
   Refactored from Prompt 3 — uses chrome accent system.
   Sits above the site header. Position is relative so the
   header's fixed positioning offsets correctly via JS.
   ──────────────────────────────────────────────────────── */
.banner {
  position: relative;
  z-index: var(--z-banner);
  background: var(--color-onyx-deep);
  color: var(--color-bone);
  border-bottom: 1px solid var(--chrome-dim);
  font-size: var(--text-sm);
}

.banner[hidden] { display: none; }

.banner__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-3);
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.banner__text {
  margin: 0;
  flex: 1;
  text-align: center;
  letter-spacing: var(--tracking-wide);
  max-width: none;
}

.banner__link {
  color: var(--chrome);
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
  transition: color var(--t-base);
}
.banner__link:hover {
  color: var(--chrome-bright);
  border-bottom-color: transparent;
}

.banner__dismiss {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-lg);
  line-height: 1;
  color: var(--color-steel-muted);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: color var(--t-base);
}
.banner__dismiss:hover {
  color: var(--chrome);
}

/* ═══════════════════════════════════════════════════════════
   FOOTER (Prompt 15 — three-band composition)
   Brand close → service columns → quiet legal close.
   Tagline renders in proper Archivo Black uppercase, never italic
   (Archivo Black has no italic glyphs).
   ═══════════════════════════════════════════════════════════ */

.footer {
    background: var(--color-onyx-deep);
    color: var(--color-bone);
    padding-block: var(--space-20) 0;
    margin-top: var(--space-24);
    position: relative;
}

.footer::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: var(--gradient-hairline-h);
}

/* ─── Band 1: Brand close ────────────────────────────────── */
.footer__brand-band {
    padding-bottom: var(--space-16);
}

.footer__brand-block {
    max-width: 320px;
}

.footer__tagline {
    font-family: var(--font-display);
    /* Sized down ~20% from clamp(1.5rem, 2.5vw, 2rem) so the
       tagline reads as a supporting brand line, not a third
       row of the wordmark (Prompt 18). */
    font-size: clamp(1.25rem, 2vw, 1.5rem);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: var(--tracking-display);
    color: var(--color-pearl);
    line-height: 1;
    /* Increased gap from --space-6 (24px) to --space-12 (48px)
       — establishes hierarchy between wordmark and tagline. */
    margin: var(--space-12) 0 0;
    /* No italic — Archivo Black has no italic glyphs */
    font-style: normal;
    transform: none;
}

/* ─── Band 2: Service columns ────────────────────────────── */
.footer__service-band {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-12);
    padding-bottom: var(--space-16);
}

.footer__column {
    min-width: 0;
}

.footer__column-title {
    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-5);
    padding-bottom: var(--space-3);
    border-bottom: 1px solid var(--color-divider);
}

.footer__address {
    font-family: var(--font-body);
    font-size: var(--text-base);
    font-style: normal;
    color: var(--color-bone);
    line-height: var(--leading-loose);
    margin: 0 0 var(--space-4);
}

.footer__drive-times {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--platinum-muted);
    margin: 0 0 var(--space-5);
    line-height: var(--leading-loose);
}

.footer__links {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
}

.footer__link {
    font-family: var(--font-body);
    font-size: var(--text-base);
    color: var(--color-bone);
    text-decoration: none;
    transition: color var(--t-base);
    display: inline-block;
    line-height: var(--leading-snug);
}

.footer__link:hover {
    color: var(--platinum-bright);
}

.footer__social-band {
    display: flex;
    justify-content: center;
    gap: var(--space-5);
    padding: var(--space-6) 0 var(--space-4);
}

.footer__social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--color-bone);
    text-decoration: none;
    transition: color var(--t-base);
}

.footer__social-link:hover,
.footer__social-link:focus-visible {
    color: var(--platinum-bright);
    outline: none;
}

.footer__social-icon {
    width: 20px;
    height: 20px;
    display: block;
}

.footer__link--cta {
    font-weight: var(--weight-semibold);
    color: var(--platinum);
    margin-top: var(--space-2);
}

.footer__link--cta:hover {
    color: var(--platinum-bright);
}

.footer__link-arrow {
    display: inline-block;
    transition: transform var(--t-base);
    margin-left: var(--space-1);
}

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

.footer__link--inline {
    border-bottom: 1px solid var(--platinum-deep);
    padding-bottom: 1px;
}

.footer__link--inline:hover {
    border-bottom-color: var(--platinum-bright);
}

.footer__founding-note {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--platinum-muted);
    line-height: var(--leading-loose);
    margin: var(--space-6) 0 0;
    max-width: 28ch;
}

/* ─── Hairline between bands ─────────────────────────────── */
.footer__hairline {
    border: 0;
    height: 1px;
    background: var(--gradient-hairline-h);
    margin: 0 0 var(--space-6);
}

/* ─── Band 3: Legal close ────────────────────────────────── */
.footer__legal-band {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: var(--space-4);
    padding-bottom: var(--space-8);
    flex-wrap: wrap;
}

.footer__copyright {
    font-family: var(--font-body);
    font-size: var(--text-xs);
    color: var(--platinum-muted);
    margin: 0;
    line-height: var(--leading-snug);
    /* No mid-phrase wrap on desktop */
    white-space: nowrap;
}

/* Admin link in the legal-links row — slightly more muted than its
   peers (Privacy / Terms / Accessibility) so it reads as utility
   for site staff rather than a peer-level link visitors should
   click. Replaces the "invisible link in copyright" approach
   from Prompt 19 (Prompt 24). */
.footer__legal-link--admin {
    opacity: 0.7;
}
.footer__legal-link--admin:hover,
.footer__legal-link--admin:focus {
    opacity: 1;
}

.footer__legal-links {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-5);
}

.footer__legal-link {
    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);
    text-decoration: none;
    transition: color var(--t-base);
}

.footer__legal-link:hover {
    color: var(--platinum-bright);
}

/* ─── Responsive ─────────────────────────────────────────── */
@media (max-width: 960px) {
    .footer__service-band {
        grid-template-columns: repeat(2, 1fr);
        gap: var(--space-10);
    }

    .footer__column--connect {
        grid-column: 1 / -1;
    }
}

@media (max-width: 640px) {
    .footer {
        padding-top: var(--space-12);
    }

    .footer__brand-band {
        padding-bottom: var(--space-10);
    }

    .footer__service-band {
        grid-template-columns: 1fr;
        gap: var(--space-8);
    }

    .footer__column--connect {
        grid-column: auto;
    }

    .footer__legal-band {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--space-4);
    }

    .footer__copyright {
        white-space: normal;
    }
}

/* ─── Mobile redesign — hide footer redundancies (≤768px) ───
   Three footer elements duplicate content presented elsewhere on
   the mobile experience:

     - .footer__tagline reads as a display-scale "TRAIN WHERE IT
       MATTERS." line that the final CTA section above already owns
       (the operator's brand_tagline setting happens to match the
       final CTA's headline). Hiding the tagline on mobile cuts the
       redundancy without losing the line on desktop.

     - .footer__column--visit duplicates address + drive times +
       directions link — content the place section (Moment 5)
       already presents on mobile. The address remains accessible
       to all users (including screen readers) via the place section
       on the same page.

   With visit hidden, the existing .footer__service-band 2-col grid
   at 641-768px would render a lopsided "Begin + empty + Connect-
   spans-below" layout. Force single column at ≤768px (mirroring
   the existing ≤640px rule) so Begin and Connect stack cleanly.

   Brand-band padding tightened from --space-16 (64px) to --space-10
   (40px) on mobile so the logo doesn't float above the service band
   with the tagline removed.

   Desktop (≥769px) renders identically to before — all hide rules
   are mobile-scoped. */
@media (max-width: 768px) {
    .footer__tagline {
        display: none;
    }
    .footer__brand-band {
        padding-bottom: var(--space-10);
    }
    .footer__column--visit {
        display: none;
    }
    .footer__service-band {
        grid-template-columns: 1fr;
        gap: var(--space-8);
    }
    .footer__column--connect {
        grid-column: auto;
    }
}

/* ────────────────────────────────────────────────────────────
   Cookie consent banner (Wave 2 — Tier 3)
   Fixed bottom strip. Hidden by default via the [hidden]
   attribute server-side; assets/js/cookie-consent.js unhides
   it for first-visit users. Sits above the mobile bottom nav
   (z-index 35 vs 30) so it doesn't get covered on phones.
   ──────────────────────────────────────────────────────── */
.cookie-banner {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 36;
    background: var(--color-onyx-rich);
    border-top: 1px solid var(--color-divider);
    box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.08);
    padding: var(--space-4) var(--gutter);
}
.cookie-banner[hidden] { display: none; }

.cookie-banner__inner {
    max-width: var(--container-max);
    margin: 0 auto;
    display: flex;
    align-items: center;
    gap: var(--space-5);
    flex-wrap: wrap;
}

.cookie-banner__text {
    margin: 0;
    flex: 1 1 280px;
    font-family: var(--font-body);
    font-size: var(--text-sm);
    color: var(--platinum);
    line-height: var(--leading-normal);
}

.cookie-banner__link {
    color: var(--platinum-bright);
    text-decoration: underline;
}
.cookie-banner__link:hover { color: var(--color-onyx); }

.cookie-banner__actions {
    display: flex;
    gap: var(--space-2);
    flex: 0 0 auto;
}

.cookie-banner__btn {
    font-family: var(--font-body);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    padding: var(--space-3) var(--space-5);
    border: 1px solid var(--platinum);
    cursor: pointer;
    transition: background var(--t-base), color var(--t-base);
}
.cookie-banner__btn--decline {
    background: transparent;
    color: var(--platinum);
}
.cookie-banner__btn--decline:hover {
    background: var(--color-onyx-warm);
    color: var(--color-onyx);
}
.cookie-banner__btn--accept {
    background: var(--platinum-bright);
    color: var(--color-onyx-rich);
    border-color: var(--platinum-bright);
}
.cookie-banner__btn--accept:hover {
    background: var(--color-onyx);
    border-color: var(--color-onyx);
}

@media (max-width: 640px) {
    .cookie-banner { padding: var(--space-3) var(--space-4); }
    .cookie-banner__inner { gap: var(--space-3); }
    .cookie-banner__text { flex: 1 1 100%; font-size: var(--text-xs); }
    .cookie-banner__actions { flex: 1 1 100%; }
    .cookie-banner__btn { flex: 1; padding: var(--space-3); }
}
