/**
 * MARBL DESIGN SYSTEM v3 - single stylesheet
 * ═══════════════════════════════════════════════════════════════════════════════
 *
 * THIS FILE IS THE SOURCE OF TRUTH. Edit it directly. There is no build step.
 * Assembled 29 July 2026 from the v2 component files, which remain in place,
 * FROZEN, for the sites still on them (Vaulted, TAT, Theia). Do not sync changes
 * between v2 and v3 - they are separate lineages now, and v2 is maintenance-only.
 *
 * CONSUMERS (v3): Marbl Codes · Marbl Racing · Marbl Events · Hub
 * A site is fully v3 or fully v2. Never half - that is how you get a v3 header
 * against a v2 footer and lose an afternoon finding out why.
 *
 * ── THE WIDTH LAW (locked 29 Jul 2026, Richard) ───────────────────────────────
 *   --shell-max   1400px  OUTER bound, padding INCLUDED -> 1320px of content
 *   --shell-wide  1600px  opt-in only, reason recorded in the project brain
 *   --shell-pad     40px  desktop / 20px at <=768px - applied at EVERY width
 *
 *   Header, footer and every section read from these. One container, so a
 *   header/footer mismatch is impossible rather than something a human must spot.
 *   Full detail: MARBL/Brand.md -> "Page width + gutters".
 *
 * ── CONTENTS ──────────────────────────────────────────────────────────────────
 *   01. TOKENS, RESET, PAGE SHELL
 *   02. FONTS
 *   03. BUTTONS
 *   04. SITE HEADER
 *   05. PILL NAV
 *   06. FOOTER + REVEAL BAND
 *   07. HOLDING PAGE
 *
 * ── CONVENTIONS ───────────────────────────────────────────────────────────────
 *   Every value is a token. No raw hex, no raw px. Radii are 0 (Marbl is square);
 *   --radius-round is the only escape hatch. No coloured glows on interactive
 *   elements. Never encode meaning in hue alone - always pair with icon or label.
 *
 *   ⚠️ Do not write an asterisk followed by a slash inside these comments. Doing
 *   that closed a comment early on 29 Jul and silently ate the declaration below
 *   it - the container rendered with no max-width and nothing errored.
 */

/* ═══════════════════════════════════════════════════════════════════════════════
   01. TOKENS, RESET, PAGE SHELL
   Design tokens (colour, type, spacing, widths), the .container shell and
   full-bleed helpers, base reset and utilities. Everything else depends on this.
   ────────────────────────────────────────────────────────────────────────── */
/**
 * Marbl Design System v2.0.0 - token set.
 * RUNTIME MIRROR. Token VALUES are authored in DESIGN.md (the single source).
 * Do NOT hand-edit values here in isolation - edit DESIGN.md first, then sync.
 * (A DESIGN.md -> marbl-v2.css generator is the planned mechanical close.)
 * For: component library, Marbl Codes rebuild, all new Marbl properties.
 * NOT for: legacy live pages (use marbl.css v1) or client sites (own CSS).
 *
 * Source of truth: C:/Claude/INTERNAL/Marbl-Codes/DESIGN.md
 * Created: 21 April 2026
 */

/* ==========================================================================
   Tokens
   ========================================================================== */

:root {
  /* ── Colours ── */
  --marbl-charcoal: #171415;
  --marbl-charcoal-deep: #0d0b0c;
  --marbl-charcoal-darkest: #131112;  /* Dark text on ember CTA — locked 30 Apr 2026 */
  --marbl-charcoal-light: #1d1a1b;
  --marbl-charcoal-lighter: #232021;

  /* Warm dark-elevation ladder (Richard, 15 Jun 2026, square kit) — visibly
     stepped lighter charcoals that keep the espresso warmth (R≥G, no cool tint).
     Used to lift dark sections + layer dark cards above them. Ladder:
     hero/body #171415 → raised section → card → card hover. */
  --marbl-charcoal-raised: #211d1e;       /* lifted dark band (e.g. a section) */
  --marbl-charcoal-card: #2c2829;         /* card on a dark band */
  --marbl-charcoal-card-hover: #363132;   /* card hover */
  /* Accent */
  --marbl-ember: #F35226;
  --marbl-ember-dark: #BB2F09;
  --marbl-crimson: #322A2A;
  --marbl-sandstone: #A69B98;
  --marbl-beige: #F3E2C8;
  --marbl-beige-dark: #DBCBA9;
  --marbl-black: #000000;
  --marbl-white: #FFFFFF;

  /* Text opacity scale (white on dark) */
  --marbl-white-90: rgba(255, 255, 255, 0.9);
  --marbl-white-85: rgba(255, 255, 255, 0.85);  /* Outline button text — locked 30 Apr 2026 */
  --marbl-white-70: rgba(255, 255, 255, 0.7);
  --marbl-white-65: rgba(255, 255, 255, 0.65);  /* Avatar initials fallback */
  --marbl-white-50: rgba(255, 255, 255, 0.5);
  --marbl-white-40: rgba(255, 255, 255, 0.4);
  --marbl-white-30: rgba(255, 255, 255, 0.3);
  --marbl-white-25: rgba(255, 255, 255, 0.25);
  --marbl-white-20: rgba(255, 255, 255, 0.2);
  --marbl-white-15: rgba(255, 255, 255, 0.15);
  --marbl-white-10: rgba(255, 255, 255, 0.1);
  --marbl-white-08: rgba(255, 255, 255, 0.08);
  --marbl-white-06: rgba(255, 255, 255, 0.06);
  --marbl-white-04: rgba(255, 255, 255, 0.04);

  /* Ember opacity scale (ember tinted overlays / hover backgrounds) */
  --marbl-ember-10: rgba(243, 82, 38, 0.1);

  /* Black opacity scale (dark overlays on light surfaces) */
  --marbl-black-15: rgba(0, 0, 0, 0.15);

  /* ── Status — warm Marbl palette (adopted from the Marbl Dash admin theme,
     18 Jun 2026). Replaces the old stock-Tailwind hex (#22c55e / #f59e0b /
     #ef4444 / #3b82f6) with the warm family: sage / honey / terracotta /
     warm-slate. NO clinical blue, NO clinical green. Each role has a solid
     (badges, dots, borders on dark), a -tint (badge/banner fills on light),
     and a -text (accessible text colour on the tint). ── */
  --color-success: #5e8c4f;        /* sage */
  --color-success-tint: #e7ece0;
  --color-success-text: #4a7040;
  --color-warning: #d79a3c;        /* honey */
  --color-warning-tint: #f4ead3;
  --color-warning-text: #8a6420;
  --color-error: #c5341b;          /* terracotta — distinct from the ember CTA */
  --color-error-tint: #f2e1d9;
  --color-error-text: #a32a15;
  --color-info: #6e8389;           /* warm slate — never clinical blue */
  --color-info-tint: #dee7e6;
  --color-info-text: #475a5e;

  /* Notification / badge / pill-title accents (warm equivalents of the stock
     blue/red/orange/teal/purple). Drives badges, tags, toasts, pill titles. */
  --badge-slate: #6e8389;          /* info */
  --badge-terracotta: #c5341b;     /* danger */
  --badge-honey: #d79a3c;          /* warning */
  --badge-sage: #5e8c4f;           /* success */
  --badge-plum: #806572;           /* muted warm plum — the family's "purple" */
  --badge-taupe: #8a807d;          /* neutral */

  /* ── Typography ── */
  --font-heading: 'Urbanist', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-accent: 'Petrona', Georgia, serif;
  /* Weights */
  --font-light: 300;
  --font-regular: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;
  --font-extrabold: 800;

  /* Type scale: fixed for small, fluid clamp() for large */
  --text-xs: 11px;
  --text-sm: 13px;
  --text-base: 15px;
  --text-lg: clamp(16px, 0.9rem + 0.3vw, 18px);
  --text-xl: clamp(19px, 1rem + 0.5vw, 22px);
  --text-2xl: clamp(24px, 1.2rem + 1vw, 32px);
  --text-3xl: clamp(36px, 1.5rem + 2.5vw, 56px);
  --text-4xl: clamp(48px, 2rem + 3.5vw, 80px);
  --text-5xl: clamp(56px, 2.5rem + 5vw, 112px);

  /* ── Spacing: one scale for everything ── */
  /* Gaps, margins, padding, all use this. Core: 10/20/40. */
  --gap-3xs: 4px;   /* Tightest hierarchical step — list/TOC item v-padding — locked 30 Apr 2026 */
  --gap-half: 5px;
  --gap-tight: 6px; /* Typographic micro-rhythm (list-item bottom, label rest) — locked 30 Apr 2026 */
  --gap-2xs: 8px;   /* Tight gap for compact controls (mini buttons) — locked 30 Apr 2026 */
  --gap-xs: 10px;
  --gap-sm: 20px;
  --gap-md: 40px;
  --gap-lg: 60px;
  --gap-xl: 80px;
  --gap-2xl: 100px;
  --gap-3xl: 120px;
  --gap-4xl: 140px;
  --gap-5xl: 160px;

  /* ── Control tokens — buttons, inputs, pills (locked 20 Jun 2026) ──
     Deliberately OFF the layout gap scale: controls have their own rhythm
     (a 1:2 button is 14/28, not 20/40 which reads as a chunky tablet).
     Tokenised so there are NO raw values — use these for EVERY control
     padding/height across all builds, Marbl and client. See MARBL/Brand.md. */
  --control-h: 48px;          /* standard control height (solid/outline button, input) */
  --control-h-sm: 36px;       /* compact / mini control height */
  --control-pad-x: 28px;      /* standard horizontal padding */
  --control-pad-x-sm: 16px;   /* compact / mini control horizontal padding */
  --control-pad-y: 14px;      /* vertical padding for height:auto text/ghost buttons + inputs */

  /* ── Border radius — SQUARE direction (Richard, 15 Jun 2026, new Marbl style kit).
     Everything square: every corner token flattened to 0 — buttons, nav pill, cards,
     inputs, badges, AND former circles (avatars, dots) all go hard-square at source.
     --radius-round kept as the single fully-rounded ESCAPE HATCH for any element that
     genuinely needs a circle/pill again later. Unused by default. ── */
  --radius-2xs: 0;
  --radius-xs: 0;
  --radius-sm: 0;
  --radius: 0;
  --radius-lg: 0;
  --radius-circle: 0;      /* was 50% — squared per "square them all" */
  --radius-full: 0;        /* was 100px — squared (mini nav pill, badges) */
  --radius-round: 9999px;  /* escape hatch: the one token that stays fully round, just in case */

  /* ── Icon sizing ── */
  /* Glyph + container dimensions for icons (separate from gap/spacing).
     Locked 30 Apr 2026 to remove canonical literals. */
  --icon-xs: 11px;
  --icon-sm: 14px;
  --icon-md: 16px;
  --icon-lg: 20px;
  --icon-xl: 22px;
  --icon-2xl: 28px;
  --icon-3xl: 32px;
  --icon-4xl: 48px;

  /* ── Borders ── */
  --border-subtle: 1px solid rgba(255, 255, 255, 0.04);
  --border-standard: 1px solid rgba(255, 255, 255, 0.06);
  --border-visible: 1px solid rgba(255, 255, 255, 0.08);
  --border-interactive: 1px solid rgba(255, 255, 255, 0.15);
  --border-ember: 1px solid rgba(243, 82, 38, 0.15);

  /* ── Transitions ── */
  --transition-fast: 0.15s ease;
  --transition-base: 0.2s ease;
  --transition-slow: 0.3s ease;
  --ease-marbl: cubic-bezier(0.32, 0.72, 0, 1);
  --ease-fast: cubic-bezier(0.16, 1, 0.3, 1);

  /* ── Content widths (200px steps) — the PALETTE layer ── */
  --width-sm: 600px;
  --width-md: 800px;
  --width-lg: 1000px;
  --width-xl: 1200px;
  --width-2xl: 1400px;
  --width-max: 1600px;
  --width-ultra: 1800px;

  /* ── Page shell — the ROLE layer (LOCKED 29 Jul 2026, Richard). Law: MARBL/Brand.md
     → "Page width + gutters". Header, footer and every section read from THESE, never
     from a raw --width-* value, so a header/footer mismatch becomes impossible.

     ⚠️ --shell-max is the OUTER bound and INCLUDES the padding. Content lands at 1320px
     on wide screens. If someone means 1400 of content, they are wrong — say 1320.

     Why this is here and not in a component: before today `.container` was defined in
     footer-reveal.css AND holding-page.css (both 1600) AND two legacy bundles (on the dead
     container-xl and space-6 tokens), while site-header.css had no container at all. The
     header and footer could not match because there was nothing to match on.

     NOTE TO SELF: do not write an asterisk followed by a slash in these comments. Doing
     exactly that here on 29 Jul closed this comment early, which silently ate the
     --shell-max declaration below. The container rendered with NO max-width and nothing
     errored. Caught only by measuring the computed value in a browser. ── */
  --shell-max: var(--width-2xl);    /* 1400px — the default for every surface */
  --shell-wide: var(--width-max);   /* 1600px — opt-in only, reason recorded in the project brain */
  --shell-pad: var(--gap-md);       /* 40px — applied at EVERY width; breathing space, not a fallback */
  /* The actual content width inside the shell: 1400 - 40 - 40 = 1320px. Used by full-width
     bars (header, footer) that need a viewport-wide background but content aligned to
     .container — see the .shell-bar pattern below. */
  --shell-content: calc(var(--shell-max) - var(--shell-pad) * 2);

  /* ── Light palette (warm paper/marble) — promoted from Marbl Events 20 Jun 2026.
     The source-of-truth sibling for all Marbl sites. Used by .band--light surfaces
     and the .accordion--line / .accordion--light variants. Additive: nothing renders
     light until an element opts in via .band--light or a --light component variant. ── */
  --marbl-paper: #F5F6EA;        /* light band background */
  --marbl-marble: #E9EADE;       /* card / open-accordion surface on light */
  --marbl-ink: #171415;          /* primary text on light */
  --marbl-ink-muted: #5F5653;    /* secondary text on light */
  --marbl-paper-border: #E8E5DF; /* hairline on light */
  --marbl-ink-border: rgba(23, 20, 21, 0.15); /* stronger ink hairline on light (buttons/pills) */
  --ember-on-light: var(--marbl-ember); /* ember stays true on light (Richard's override, 15 Jun) */

  /* ── Breakpoints (CSS custom properties can't be used in @media,
       but documented here as canonical reference) ── */
  /* --bp-mobile: 480px;   */
  /* --bp-tablet: 768px;   */
  /* --bp-desktop: 1024px; */
  /* --bp-wide: 1440px;    */
  /* --bp-ultra: 1800px;   */

  /* ── Layout ── */
  --section-pad-y: var(--gap-xl);
  --section-pad-x: var(--gap-md);

  /* ── Z-index ── */
  --z-base: 0;
  --z-above: 10;
  --z-dropdown: 100;
  --z-sticky: 200;
  --z-modal: 300;
  --z-toast: 400;
  --z-tooltip: 500;
}

/* ==========================================================================
   Reset
   ========================================================================== */

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

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  scrollbar-width: thin;
  scrollbar-color: var(--marbl-ember) var(--marbl-charcoal);
  /* Native smooth-scroll for in-page anchors. Reduced-motion override below
   * disables this for users who prefer no animation. Locked 30 Apr 2026. */
  scroll-behavior: smooth;
}

/* Desktop only — `scrollbar-gutter: stable` reserves horizontal space for a
 * vertical scrollbar even when one isn't visible, preventing layout shift on
 * long pages. On mobile (touch / pointer:coarse), scrollbars are overlay so
 * they don't take horizontal space — and reserving the gutter interacts badly
 * with mobile Chrome's address-bar-collapse-on-scroll, causing visible page
 * jumps. Scoped to pointer:fine (mouse/trackpad devices) to keep desktops
 * stable while leaving mobile alone. Locked 30 Apr 2026. */
@media (pointer: fine) {
  html { scrollbar-gutter: stable; }
}

/* Honour prefers-reduced-motion: disable native smooth-scroll for users with
 * the OS-level reduced-motion preference. Locked 30 Apr 2026. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--font-regular);
  line-height: 1.6;
  color: var(--marbl-white);
  background-color: var(--marbl-charcoal);
}

/* ── Universal focus ring ── */
:focus-visible {
  outline: 2px solid var(--marbl-ember);
  outline-offset: 2px;
}

:focus:not(:focus-visible) {
  outline: none;
}

/* ── Links ── */
a {
  color: var(--marbl-ember);
  text-decoration: none;
  transition: color var(--transition-fast);
}

a:hover {
  color: var(--marbl-white);
}

/* ── Images ── */
img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* ── Scrollbar (desktop only) ── */
/* Track matches body charcoal (no visible track), solid ember thumb. Simple. */
::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: var(--marbl-charcoal);
}

::-webkit-scrollbar-thumb {
  background: var(--marbl-ember);
  border-radius: var(--radius-full);
}

::-webkit-scrollbar-thumb:hover {
  background: var(--marbl-ember-dark);
}

/* Firefox scrollbar styling is declared in the primary html {} rule above (merged to avoid two separate html blocks) */

/* ── Reduced motion ── */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ══ PAGE SHELL ══ LOCKED 29 Jul 2026 (Richard). Law: MARBL/Brand.md → "Page width + gutters".
   THE single container. Header, footer and every section use this class. Owning it here — rather
   than in whichever component happened to need it first — is the whole point: it is what makes a
   header/footer width mismatch impossible instead of something a human has to notice.
   Padding is applied at EVERY width (40px / 20px), on the --gap-* scale. Breathing space, not a
   narrow-screen fallback. ── */
.container {
  width: 100%;
  max-width: var(--shell-max);           /* 1400px OUTER, padding included → 1320px of content */
  margin-inline: auto;
  padding-inline: var(--shell-pad);
  box-sizing: border-box;
}

/* Opt-in wider shell. Only where the project's brain file says why. */
.container--wide { max-width: var(--shell-wide); }

/* ── Full-bleed: the pattern that stops a divider ending where the text ends ──
   A border or background on an element INSIDE .container can only ever be as wide as the
   container. To span the viewport the WRAPPER goes full width and the CONTENT stays in the
   shell. Colour and rules on the outside, content on the inside.

     <footer class="footer">              full width — borders/backgrounds live here
       <div class="container">…</div>     constrained content
       <div class="bleed-rule"></div>     edge-to-edge divider
     </footer>                                                                              ── */
.bleed-rule {
  width: 100%;
  height: 1px;
  border: 0;
  background: var(--marbl-white-15, rgba(255, 255, 255, 0.15));
}

/* ── .shell-bar: full-width background, content aligned to .container, NO inner wrapper ──
   For bars whose content sits directly in the element (the site header is a flex row with
   no inner div). Adding a wrapper would mean a markup change on every consuming site; this
   gets identical alignment from padding alone.

   The padding grows to keep the content column at --shell-content (1320px) and never drops
   below --shell-pad (40/20px) on narrow screens. Verified to land on the same pixel as
   .container at 1200 / 1440 / 1920.                                                        ── */
.shell-bar {
  padding-inline: max(var(--shell-pad), calc((100% - var(--shell-content)) / 2));
  box-sizing: border-box;
}

@media (max-width: 768px) {
  :root { --shell-pad: var(--gap-sm); }  /* 20px */
}

/* ── Screen reader only ── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ── Logo (canonical) ── */
/* Outer anchor for the animated logo. MarblLogo.init() in marbl-core-v2.js
   finds `[data-logo-animate]` elements and injects a `.marbl-logo-animated`
   wrapper inside. This class sets the anchor's display + colour baseline.
   Restored here 22 April 2026 after burger menu preview showed logo not
   rendering (v2 migration left these behind in marbl.css v1). */
.marbl-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-xs, 10px);
  text-decoration: none;
  color: var(--marbl-white);
}

.marbl-logo:hover {
  color: var(--marbl-white);
}

/* Wrapper injected by marbl-core-v2.js MarblLogo.createLogo(). Inline styles
   set explicit width + height in JS; this class provides the display mode
   and positioning context as a fallback. */
.marbl-logo-animated {
  display: inline-flex;
  align-items: center;
  position: relative;
}

/* Larger header variant (used by some marketing pages). */
.marbl-logo-lg .marbl-logo-animated {
  transform: scale(1.2);
  transform-origin: left center;
}

/* ── Social icon button (canonical) ── */
/* Used by site-footer, burger menu, and anywhere a row of bare social icons
   appears. Bare SVG (no circle bg). White-50 at rest. Ember colour +
   translateY(-2px) lift on hover. Previously lived in marbl.css v1 only —
   restored here 22 April 2026 after footer regression (site-footer.css
   expects this class to exist in v2). */
.btn-icon-social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  color: var(--marbl-white-50);
  background: transparent;
  text-decoration: none;
  transition: color 0.15s ease, transform 0.15s ease;
}

.btn-icon-social:hover {
  color: var(--marbl-ember);
  transform: translateY(-2px);
}

.btn-icon-social:focus-visible {
  outline: 2px solid var(--marbl-ember);
  outline-offset: 2px;
  /* Was a hardcoded 4px - a ROUNDED focus ring in a square kit, live since the
     June square realign and never caught because marbl-v2.css is in stylelint's
     ignore list. v3 is linted, so it surfaced immediately. (29 Jul 2026.) */
  border-radius: var(--radius);
}

.btn-icon-social svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* Fathom Analytics injects an unsized 1x1 tracking pixel <img> into the body
   on each pageview. Without size hints it pushes a layout shift the moment
   the request resolves (CLS ≈ 0.37 on the worst TAT pages). Pin out of flow
   so it can never affect layout. Same applies to any future tracker that
   posts back via an unsized image. */
img[src*="cdn.usefathom.com"] {
  position: absolute;
  width: 1px;
  height: 1px;
  pointer-events: none;
  visibility: hidden;
}

/* ═══════════════════════════════════════════════════════════════════════════════
   02. FONTS
   Self-hosted @font-face: Urbanist (headings), Inter (body), Petrona (accent).
   ────────────────────────────────────────────────────────────────────────── */
/* ===================================================================
   Marbl Fonts — Self-hosted variable woff2 stack
   ===================================================================
   Inter        body / UI       wght 100-900
   Urbanist     display         wght 100-900
   Petrona      accent / italic wght 100-900 + italic
   Latin subset only. Total payload: ~167 KB across 4 woff2 files.
   Single source of truth for every Marbl-owned and Marbl-built site.
   =================================================================== */

/* -------------------------------------------------------------------
   Inter - body, UI, microcopy
   ------------------------------------------------------------------- */
@font-face {
  font-family: 'Inter';
  src: url('./assets/inter/inter-variable.woff2') format('woff2-variations'),
       url('./assets/inter/inter-variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -------------------------------------------------------------------
   Urbanist - display, headings, hero titles
   ------------------------------------------------------------------- */
@font-face {
  font-family: 'Urbanist';
  src: url('./assets/urbanist/urbanist-variable.woff2') format('woff2-variations'),
       url('./assets/urbanist/urbanist-variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -------------------------------------------------------------------
   Petrona - accent, Label Style, italic emphasis
   ------------------------------------------------------------------- */
@font-face {
  font-family: 'Petrona';
  src: url('./assets/petrona/petrona-variable.woff2') format('woff2-variations'),
       url('./assets/petrona/petrona-variable.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Petrona';
  src: url('./assets/petrona/petrona-variable-italic.woff2') format('woff2-variations'),
       url('./assets/petrona/petrona-variable-italic.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* -------------------------------------------------------------------
   Marbl font stack tokens
   System-font fallbacks render instantly while web fonts load (swap).
   ------------------------------------------------------------------- */
:root {
  --marbl-font-body: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --marbl-font-display: 'Urbanist', 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --marbl-font-accent: 'Petrona', Georgia, 'Times New Roman', serif;
  --marbl-font-mono: ui-monospace, 'SF Mono', 'Cascadia Mono', 'Roboto Mono', Menlo, Consolas, monospace;
}

/* -------------------------------------------------------------------
   Utility classes
   For quick application without writing custom rules.
   ------------------------------------------------------------------- */
.marbl-text-body { font-family: var(--marbl-font-body); }
.marbl-text-display { font-family: var(--marbl-font-display); }
.marbl-text-accent { font-family: var(--marbl-font-accent); font-style: italic; }
.marbl-text-mono { font-family: var(--marbl-font-mono); }

/* -------------------------------------------------------------------
   Display title accent — the brand-canonical word-accent pattern.

   Wrap a single word inside a display heading in <span class="marbl-accent">
   to stamp it with Petrona italic, ember colour, and a 120% upscale.

   Sizing rule: ALWAYS 120% of whatever parent text it sits inside.
   This makes the accent track parent sizing perfectly — a clamp()
   hero at 96px gives ~115px accent; a smaller H2 at 32px gives ~38px
   accent — proportional everywhere with one rule.

   The accent is ALWAYS larger than its surrounding text. Never smaller.

   Sourced from brand-kit.md "Title Accent (Petrona italic)" — the
   canonical Marbl visual spec. If anything diverges, brand-kit wins.

   Use on display-scale headings (h1 / large h2). Avoid on body copy
   — for italic emphasis on body copy use .marbl-text-accent instead.
   ------------------------------------------------------------------- */
.marbl-accent {
  font-family: var(--marbl-font-accent);
  font-style: italic;
  font-weight: 800;
  font-size: 120%;
  color: var(--marbl-ember);
}

/* ═══════════════════════════════════════════════════════════════════════════════
   03. BUTTONS
   The split-button family. Replaced .btn--fill-up / --solid / --outline / --mini
   on 16 Jul 2026 - those are retired, do not reintroduce them.
   ────────────────────────────────────────────────────────────────────────── */
/* ===================================================================
   Canonical Marbl buttons - ui-items §1-3
   Source of truth. Consumers: marbl.codes, events, agency site, etc.

   16 Jul 2026: the SPLIT family (two-cell colour-blocked button)
   replaced fill-up, solid, classic outline, bare icon-with-text and
   .btn--mini as the CTA + utility set. Old variants retired to
   _BIN/2026-07-16-split-button-replaces-cta-family/ (+ git history).
   Ghost, Read More, icon-only buttons and back-link are unchanged.
   =================================================================== */

/* ═══════════════════════════════════════════════════════
   BUTTONS - SHARED BASE
   (ghost + read-more ride on this; the split family does not)
   ═══════════════════════════════════════════════════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-xs, 10px);
  height: var(--control-h, 48px);
  padding: 0 var(--control-pad-x, 28px);
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-base, 15px);
  font-weight: 700;
  border: none;
  border-radius: var(--radius, 0);
  cursor: pointer;
  text-decoration: none;
  position: relative;
  overflow: hidden;
  white-space: nowrap;
}

/* Icon chip (ghost + read-more) */
.btn__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--icon-2xl, 28px);
  height: var(--icon-2xl, 28px);
  border-radius: var(--radius-circle, 0);
  flex-shrink: 0;
  transition: background 0.3s ease;
}
.btn__icon svg {
  width: var(--icon-sm, 14px);
  height: var(--icon-sm, 14px);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

/* ═══════════════════════════════════════════════════════
   SPLIT (the CTA + utility family, adopted 16 Jul 2026)
   Two full-height cells, hard square: text cell + icon cell.
   Standalone anatomy - NOT a .btn modifier.
   Default = dark surfaces (ember + ember-dark cell).
   Only the icon animates on hover: arrows rotate 45deg from
   up-right to right (the Marbl motion signature); non-arrow
   icons take .btn-split__icon--roll and roll through the cell
   (exit top, re-enter from below - icon appears twice, see below).
   The icon cell always sits AFTER the text (right side).
   ═══════════════════════════════════════════════════════ */
.btn-split {
  display: inline-flex;
  align-items: stretch;
  height: var(--control-h, 48px);
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-body, 'Inter', sans-serif);
  /* Label voice (16 Jul 2026): same treatment as the header Sign In CTA */
  font-size: var(--text-xs, 11px);
  font-weight: var(--font-semibold, 600);
  letter-spacing: 1.5px;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}
.btn-split__text {
  display: flex;
  align-items: center;
  padding: 0 var(--gap-sm, 20px);
  background: var(--marbl-ember, #F35226);
  color: var(--marbl-charcoal-darkest, #131112);
}
.btn-split__icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--control-h, 48px); /* square cell: matches button height */
  flex-shrink: 0;
  background: var(--marbl-ember-dark, #BB2F09);
  color: var(--marbl-charcoal-darkest, #131112); /* dark icons on dark-surface buttons (16 Jul) */
  transition: background 0.3s ease;
}
.btn-split__icon svg {
  width: var(--icon-md, 16px);
  height: var(--icon-md, 16px);
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.btn-split:hover .btn-split__icon svg { transform: rotate(45deg); }

/* Non-arrow icons (download, mail, share, filter...) don't rotate -
   they ROLL on hover: the icon exits through the top and re-enters
   from the bottom. Markup contract: the icon SVG appears TWICE in
   the cell, the second copy with class "dup". */
.btn-split__icon--roll { position: relative; overflow: hidden; }
.btn-split__icon--roll svg { transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1); }
.btn-split__icon--roll svg.dup { position: absolute; inset: 0; margin: auto; transform: translateY(250%); }
.btn-split:hover .btn-split__icon--roll svg:not(.dup) { transform: translateY(-250%); }
.btn-split:hover .btn-split__icon--roll svg.dup { transform: translateY(0); }

/* Forward arrow (right-facing, slides right on hover - the read-more move).
   Use for continue / next / go-somewhere actions; the up-right arrow
   stays the default for CTAs. */
.btn-split__icon--forward svg { transition: transform 0.3s ease; }
.btn-split:hover .btn-split__icon--forward svg { transform: translateX(3px); }

/* ── Ink (light backgrounds): ember + darkest-charcoal icon cell ── */
.btn-split--ink .btn-split__icon {
  background: var(--marbl-charcoal-darkest, #131112);
  color: var(--marbl-ember, #F35226);
}
.btn-split--ink:hover .btn-split__icon { background: var(--marbl-black, #000); }

/* ── Outline (secondary partner) ── */
.btn-split--outline .btn-split__text {
  background: transparent;
  border: 1px solid var(--marbl-white-15, rgba(255,255,255,0.15));
  color: var(--marbl-white-85, rgba(255,255,255,0.85));
  transition: border-color 0.2s ease, color 0.2s ease;
}
/* drop the shared edge only when an icon cell follows the text cell */
.btn-split--outline .btn-split__text:not(:last-child) { border-right: none; }
.btn-split--outline .btn-split__icon {
  background: transparent;
  border: 1px solid var(--marbl-white-15, rgba(255,255,255,0.15));
  color: var(--marbl-white-85, rgba(255,255,255,0.85));
  transition: border-color 0.2s ease, color 0.2s ease;
}
.btn-split--outline:hover .btn-split__text,
.btn-split--outline:hover .btn-split__icon {
  border-color: var(--marbl-ember, #F35226);
  color: var(--marbl-ember, #F35226);
}

/* ── Mini (36px compact) - same type as full size (label voice) ── */
.btn-split--mini {
  height: var(--control-h-sm, 36px);
}
.btn-split--mini .btn-split__text { padding: 0 var(--control-pad-x-sm, 16px); }
.btn-split--mini .btn-split__icon { width: var(--control-h-sm, 36px); }
.btn-split--mini .btn-split__icon svg {
  width: var(--icon-xs, 11px);
  height: var(--icon-xs, 11px);
}

/* ── GHOST (text + arrow, no bg/border) ── */
.btn--ghost {
  background: transparent;
  color: var(--marbl-white-70, rgba(255,255,255,0.7));
  height: auto;
  padding: var(--control-pad-y, 14px) 0;
  border-radius: 0;
  transition: color 0.2s ease;
}
.btn--ghost .btn__icon { background: var(--marbl-white-06, rgba(255,255,255,0.06)); color: var(--marbl-white-70, rgba(255,255,255,0.7)); width: var(--icon-3xl, 32px); height: var(--icon-3xl, 32px); }
.btn--ghost:hover { color: var(--marbl-ember, #F35226); }
.btn--ghost:hover .btn__icon { background: var(--marbl-ember-10, rgba(243,82,38,0.1)); color: var(--marbl-ember, #F35226); }
.btn--ghost:hover .btn__icon svg { transform: rotate(45deg); }

.btn--ghost-text {
  background: transparent;
  color: var(--marbl-white-70, rgba(255,255,255,0.7));
  height: auto;
  padding: var(--control-pad-y, 14px) 0;
  border-radius: 0;
  transition: color 0.2s ease;
  gap: 0;
}
.btn--ghost-text:hover { color: var(--marbl-ember, #F35226); }

/* ── Read More (right arrow, slides right on hover) ── */
.btn--read-more {
  background: transparent;
  color: var(--marbl-white-70, rgba(255,255,255,0.7));
  height: auto;
  padding: var(--control-pad-y, 14px) 0;
  border-radius: 0;
  transition: color 0.2s ease;
}
.btn--read-more .btn__icon { background: var(--marbl-white-06, rgba(255,255,255,0.06)); color: var(--marbl-white-70, rgba(255,255,255,0.7)); width: var(--icon-3xl, 32px); height: var(--icon-3xl, 32px); }
.btn--read-more:hover { color: var(--marbl-ember, #F35226); }
.btn--read-more:hover .btn__icon { background: var(--marbl-ember-10, rgba(243,82,38,0.1)); color: var(--marbl-ember, #F35226); }
.btn--read-more:hover .btn__icon svg { transform: translateX(3px); }

/* Modifier: opt out of the 45deg hover rotate.
   The default .btn__icon svg rotates on hover - reads as "open in new
   tab / external link" affordance. For non-action icons (chat bubble,
   info, status) the rotate is wrong. Apply this modifier to keep the
   icon static while the rest of the .btn hover treatment still fires.
    */
.btn__icon--no-rotate svg,
.btn__icon--no-rotate:hover svg,
*:hover > .btn__icon--no-rotate svg,
.btn:hover .btn__icon--no-rotate svg { transform: none !important; }

/* ═══════════════════════════════════════════════════════
   ICON-ONLY BUTTONS
   ═══════════════════════════════════════════════════════ */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-h, 48px);
  height: var(--control-h, 48px);
  border-radius: var(--radius, 0);
  border: 1px solid var(--marbl-white-15, rgba(255,255,255,0.15));
  background: transparent;
  color: var(--marbl-white-70, rgba(255,255,255,0.7));
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease;
}
.btn-icon svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.btn-icon:hover {
  border-color: var(--marbl-ember, #F35226);
  color: var(--marbl-ember, #F35226);
}
.btn-icon--circle { border-radius: var(--radius-circle, 0); }
.btn-icon--filled {
  background: var(--marbl-ember, #F35226);
  border-color: var(--marbl-ember, #F35226);
  color: var(--marbl-charcoal-darkest, #131112);
  transition: background 0.15s ease, filter 0.15s ease;
}
.btn-icon--filled:hover {
  background: var(--marbl-ember-dark, #BB2F09);
  border-color: var(--marbl-ember-dark, #BB2F09);
  color: var(--marbl-white, #fff);
  filter: none;
}
/* Mini icon button — 40px outer (Marbl size token alignment, ).
   Was 36/16/8 — non-token values. Now --gap-md / --text-lg / --radius. */
.btn-icon--mini {
  width: var(--gap-md, 40px);
  height: var(--gap-md, 40px);
  border-radius: var(--radius, 0);
}
.btn-icon--mini svg {
  width: var(--text-lg, 18px);
  height: var(--text-lg, 18px);
}
.btn-icon--mini.btn-icon--circle { border-radius: var(--radius-circle, 0); }

/* ── BACK LINK (left arrow + text, slides left on hover) ──
   Consistent "back" affordance across pages. Default = on dark surfaces;
   add .back-link--ink on light bands. Captured from Marbl Events, 18 Jun 2026. */
.back-link {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-2xs, 8px);
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-sm, 13px);
  font-weight: 600;
  text-decoration: none;
  color: var(--marbl-white-50, rgba(255,255,255,0.5));
  transition: color 0.2s ease;
}
.back-link svg {
  width: 16px; height: 16px;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.3s ease;
}
.back-link:hover { color: var(--marbl-ember, #F35226); }
.back-link:hover svg { transform: translateX(-3px); }
.back-link--ink { color: var(--marbl-ink-muted, #5F5653); }

/* ═══════════════════════════════════════════════════════
   DISABLED STATES (canonical - ui-items §States)
   35% opacity, no pointer events. Applied via the `disabled` attribute.
   ═══════════════════════════════════════════════════════ */
.btn:disabled, .btn-split:disabled, .btn-icon:disabled, .btn-carousel:disabled {
  opacity: 0.35;
  cursor: not-allowed;
  pointer-events: none;
}

/* ═══════════════════════════════════════════════════════════════════════════════
   04. SITE HEADER
   Full-width bar, content aligned to .container (1320px) via the padding formula.
   ────────────────────────────────────────────────────────────────────────── */
/**
 * Site Header - canonical, single source for header + menu-toggle styles.
 * Depends on: core/marbl-v2.css (tokens, logo animation).
 *
 * IMPORTANT:
 * - static-positioned by default (use .site-header--fixed from marbl.css for sticky)
 * - NO border-bottom by default (use .site-header--bordered if you want one)
 */

/* Width: the header is a full-width bar whose CONTENT aligns to .container (1320px).
   Was `clamp(20px, 1.5625vw + 15px, 40px)` with no max-width at all — i.e. edge-to-edge,
   which is why it never matched the footer's 1600 container. The .shell-bar padding formula
   in marbl-v2.css does the alignment without needing an inner wrapper (the header's content
   sits directly in this flex row, so a wrapper would be a markup change on every site).
   Locked 29 Jul 2026 — MARBL/Brand.md → "Page width + gutters". */
.site-header {
  position: static;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--gap-sm, 20px);
  padding-inline: max(var(--shell-pad, 40px), calc((100% - var(--shell-content, 1320px)) / 2));
  background: var(--marbl-charcoal, #171415);
  border-bottom: none;
  box-sizing: border-box;
}

/* Optional border-bottom modifier */
.site-header--bordered {
  border-bottom: 1px solid var(--marbl-white-06, rgba(255, 255, 255, 0.06));
}

/* Optional sticky-fixed modifier — pins header above scrolling content.
 * Use sparingly. NOTE: consumer pages using --fixed must top-pad
 * downstream content by the header height (~90px) to avoid underlap. */
.site-header--fixed {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-fixed, 200);
}

/* Menu-open state: pin header above the menu overlay so logo + close (X)
   stay visible and reachable. menu.js toggles this class on open/close. */
.site-header.menu-is-open {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: calc(var(--z-modal, 300) + 10);
  background: transparent;
  border-bottom-color: transparent;
}

.site-header__left,
.site-header__right {
  display: flex;
  align-items: center;
}

.site-header__left .marbl-logo {
  display: inline-flex;
  align-items: center;
  min-width: 28px;
  min-height: 28px;
  color: var(--marbl-ember, #F35226);
}

/* ==========================================================================
   Menu Toggle (burger)
   Circular border with 3 decorative lines (18/13/18) that morph to X when open.
   Full menu behaviour lives in menu.css + menu.js.
   ========================================================================== */

.menu-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  -webkit-appearance: none;
  appearance: none;
  border-radius: var(--radius-circle, 0);
}

.menu-toggle:focus-visible {
  outline: 2px solid var(--marbl-ember);
  outline-offset: 2px;
}

.menu-toggle:focus:not(:focus-visible) {
  outline: none;
}

.menu-toggle__circle {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-half, 5px);
  width: 50px;
  height: 50px;
  border-radius: var(--radius-circle, 0);
  border: 1px solid var(--marbl-white-30, rgba(255, 255, 255, 0.3));
  background: transparent;
  transition: border-color var(--transition-base, 0.2s ease);
}

.menu-toggle:hover .menu-toggle__circle {
  border-color: var(--marbl-white-70, rgba(255, 255, 255, 0.7));
}

.menu-toggle__line {
  display: block;
  height: 1.5px;
  background: var(--marbl-white, #ffffff);
  /* stylelint-disable-next-line declaration-property-value-disallowed-list */
  border-radius: 1px; /* hairline radius — no token at 1px (smallest is --radius-2xs at 2px) */
  transition: transform 0.4s cubic-bezier(0.77, 0, 0.175, 1),
              opacity 0.4s cubic-bezier(0.77, 0, 0.175, 1),
              width 0.4s cubic-bezier(0.77, 0, 0.175, 1);
  transform-origin: center;
}

/* Decorative 20/15/20 line widths (middle line shorter, hover levels them) */
.menu-toggle__line:nth-child(1) { width: 20px; }
.menu-toggle__line:nth-child(2) { width: 15px; }
.menu-toggle__line:nth-child(3) { width: 20px; }

.menu-toggle:hover .menu-toggle__line:nth-child(2) { width: 20px; }

/* X morph when menu is open (menu.js toggles .is-open on .menu-toggle) */
.menu-toggle.is-open .menu-toggle__line:nth-child(1) {
  transform: translateY(6.5px) rotate(45deg);
}

.menu-toggle.is-open .menu-toggle__line:nth-child(2) {
  opacity: 0;
  width: 0;
}

.menu-toggle.is-open .menu-toggle__line:nth-child(3) {
  transform: translateY(-6.5px) rotate(-45deg);
}

/* ==========================================================================
   Header button variant — logo + button INSTEAD of the burger.
   For pages with no menu overlay: legal pages, holding/interstitial pages.
   Sits in .site-header__right. Captured here 2 Jun 2026 (previously duplicated
   in legal/legal-page.css + components/holding-page/holding-page.css).
   ========================================================================== */
.legal-back-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-xs, 10px);
  height: 44px;
  padding: 0 var(--gap-sm, 20px);
  background: transparent;
  border: 1px solid var(--marbl-white-15, rgba(255, 255, 255, 0.15));
  border-radius: var(--radius, 0);
  color: var(--marbl-white-85, rgba(255, 255, 255, 0.85));
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-sm, 13px);
  font-weight: var(--font-semibold, 600);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color var(--transition-base, 0.2s ease), color var(--transition-base, 0.2s ease);
}
.legal-back-btn:hover { border-color: var(--marbl-ember, #F35226); color: var(--marbl-ember, #F35226); }
.legal-back-btn:focus-visible { outline: 2px solid var(--marbl-ember, #F35226); outline-offset: 2px; }
.legal-back-btn svg { width: var(--icon-md, 16px); height: var(--icon-md, 16px); transition: transform var(--transition-base, 0.2s ease); }
.legal-back-btn:hover svg { transform: translateX(-2px); }

/* Mobile — match desktop's vertical breathing room. The 10px collapse felt
   too tight against the 50px burger circle on phones.
   --gap-sm (20px) on both axes mirrors the desktop block-padding so the
   header reads as the same component, just with tighter side gutters. */
@media (max-width: 768px) {
  .site-header {
    padding: var(--gap-sm, 20px);
  }
}

/* Reduced motion: no burger line animation */
@media (prefers-reduced-motion: reduce) {
  .menu-toggle__line {
    transition: none;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════════
   05. PILL NAV
   ────────────────────────────────────────────────────────────────────────── */
/**
 * Pill Nav - self-revealing burger navigation.
 *
 * Resting state = [burger][CTA] pill. On desktop, hover / focus-within reveals
 * the nav links (max-width + opacity) while the burger collapses to zero width.
 * On mobile (<=600px) it is CLICK-only: the burger stays put, its bars morph to
 * an X, and the links drop as a compact floating panel.
 *
 * Tokens from core/marbl-v2.css. SQUARE system - radius tokens are flattened to
 * 0, so every border-radius here is var(--radius*, 0) and renders hard-square.
 * Never hardcode a radius. Per the no-glow rule, no box-shadow on the pill.
 *
 * Extracted from Marbl Events (PublicLayout.astro) 18 June 2026.
 */

/* The pill shell: flush-left (children own their left inset), CTA hugs the right
   with a 4px (--gap-3xs) rest so the focus ring never clips the border. */
.nav-pill {
  display: inline-flex;
  align-items: center;
  gap: 0;
  padding: var(--gap-3xs) var(--gap-3xs) var(--gap-3xs) 0;
  border: 1px solid var(--marbl-white-15);
  border-radius: var(--radius, 0); /* square system - radius tokens flattened to 0 */
}

/* Only the burger area opens the menu - hovering the CTA does NOT. */
.nav-menu {
  display: inline-flex;
  align-items: center;
}

/* Expanded links. Insets live on the links themselves (clipped when collapsed),
   NOT on .nav-links - its padding would survive max-width:0 under border-box and
   leave dead space before the bars. max-width:0 + opacity:0 is the collapsed
   rest state; the reveal animates max-width with --ease-marbl. */
.nav-links {
  display: inline-flex;
  align-items: center;
  gap: var(--gap-sm);
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-width 0.7s var(--ease-marbl, cubic-bezier(0.32, 0.72, 0, 1)),
              opacity 0.5s ease 0.1s;
}

.nav-links a {
  display: inline-flex;
  align-items: center;
  height: 34px; /* bespoke - matches burger + CTA control height; full pill is the >=44px touch target */
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  letter-spacing: 1.5px; /* bespoke - tracked nav label, between --text-xs label specs */
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--marbl-white-70);
  text-decoration: none;
  transition: color var(--transition-fast, 0.15s ease);
}

/* 20px (--gap-sm) inset on the outer edges; --gap-sm between links does the rest. */
.nav-links a:first-child { padding-left: var(--gap-sm); }
.nav-links a:last-child { padding-right: var(--gap-sm); }
.nav-links a:hover { color: var(--marbl-white); }

/* Resting burger: 10px (--gap-xs) each side of the bars. Collapses to max-width:0
   + padding:0 on reveal. max-width:60px is a bespoke clamp wide enough for the
   bars + padding but tight enough to animate cleanly to zero. */
.nav-burger {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--gap-3xs); /* 4px - tight rhythm for the 1.5px bars */
  height: 34px; /* bespoke - control height, see .nav-links a */
  padding: 0 var(--gap-xs);
  max-width: 60px; /* bespoke - collapse clamp */
  overflow: hidden;
  flex-shrink: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  border-radius: var(--radius-sm, 0); /* square system */
  transition: max-width 0.7s var(--ease-marbl, cubic-bezier(0.32, 0.72, 0, 1)),
              padding 0.7s var(--ease-marbl, cubic-bezier(0.32, 0.72, 0, 1)),
              opacity 0.45s ease;
}

.nav-burger span {
  display: block;
  width: 18px; /* bespoke - burger bar length */
  height: 1.5px; /* bespoke - burger bar thickness */
  background: var(--marbl-white-70);
  cursor: pointer;
  transition: background 0.2s ease;
}

.nav-burger:hover span { background: var(--marbl-white); }

/* CTA: ember solid, dark charcoal text (canonical ember-CTA text colour). */
.nav-pill__cta {
  display: inline-flex;
  align-items: center;
  height: 34px; /* bespoke - control height, see .nav-links a */
  padding: 0 var(--gap-sm);
  border-radius: var(--radius-sm, 0); /* square system */
  font-size: var(--text-xs);
  font-weight: var(--font-bold);
  letter-spacing: 1.5px; /* bespoke - tracked label, matches .nav-links a */
  text-transform: uppercase;
  text-decoration: none;
  background: var(--marbl-ember);
  color: var(--marbl-charcoal-darkest);
  transition: background var(--transition-fast, 0.15s ease),
              color var(--transition-fast, 0.15s ease);
}

.nav-pill__cta:hover {
  background: var(--marbl-ember-dark);
  color: var(--marbl-white);
}

/* CTA can render as a <button> (e.g. a disabled / coming-soon sign-in). */
button.nav-pill__cta {
  border: 0;
  cursor: pointer;
  font: inherit;
}

/* ---- Desktop reveal: hover / focus-within / .is-open expand the links and
   collapse the burger. max-width:320px is a bespoke clamp comfortably wider than
   the three-link row so the spring never visibly clips. ---- */
.nav-menu:hover .nav-links,
.nav-menu:focus-within .nav-links,
.nav-menu.is-open .nav-links {
  max-width: 320px; /* bespoke - reveal clamp, > widest link row */
  opacity: 1;
}

.nav-menu:hover .nav-burger,
.nav-menu:focus-within .nav-burger,
.nav-menu.is-open .nav-burger {
  max-width: 0;
  padding: 0;
  opacity: 0;
  pointer-events: none;
}

/* ---- Reduced motion: drop the reveal transitions entirely. ---- */
@media (prefers-reduced-motion: reduce) {
  .nav-links,
  .nav-burger,
  .nav-burger span { transition-duration: 0.01s !important; }
}

/* Very small screens: tighten link / CTA horizontal padding. */
@media (max-width: 480px) {
  .nav-links a,
  .nav-pill__cta { padding: 0 var(--gap-xs); }
}

/* ---- Mobile (<=600px): CLICK only (no hover / focus reveal on touch). The
   burger stays put and morphs into an X; the links drop as a compact panel that
   FLOATS over the content (absolute, anchored just below the pill) - it does not
   push the page down. Charcoal, right-aligned to the pill. ---- */
@media (max-width: 600px) {
  .nav-pill { position: relative; }

  /* Links sit OUT of flow at all times on mobile, so the pill's flex row only
     ever holds the burger + CTA - opening / closing can't reflow it (no jump).
     A seamless continuation of the pill: right:-1px + min-width span its exact
     border-box width; top:100% leaves the pill's own bottom border as the seam. */
  .nav-links {
    position: absolute;
    top: 100%;
    right: -1px; /* bespoke - aligns panel edge to the pill border */
    flex-direction: column;
    align-items: stretch;
    min-width: calc(100% + 2px); /* bespoke - >= pill border-box width */
    width: max-content; /* grows to fit the longest link */
    max-width: 80vw; /* bespoke - never wider than most of the viewport */
    overflow: hidden;
    z-index: var(--z-dropdown, 100);
    background: var(--marbl-charcoal);
    border: 1px solid var(--marbl-white-15);
    padding: var(--gap-2xs);
    gap: var(--gap-3xs);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px); /* bespoke - small pre-drop offset */
    transition: opacity 0.25s ease,
                transform 0.25s var(--ease-marbl, cubic-bezier(0.32, 0.72, 0, 1)),
                visibility 0s linear 0.25s;
  }

  /* Click only: neutralise the desktop hover / focus reveal; the burger never
     collapses on mobile (it morphs to an X instead). */
  .nav-menu:hover .nav-links,
  .nav-menu:focus-within .nav-links {
    opacity: 0;
    visibility: hidden;
  }
  .nav-menu:hover .nav-burger,
  .nav-menu:focus-within .nav-burger,
  .nav-menu.is-open .nav-burger {
    max-width: 60px; /* bespoke - restore resting burger width */
    padding: 0 var(--gap-xs);
    opacity: 1;
    pointer-events: auto;
  }
  .nav-menu.is-open .nav-links {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition: opacity 0.25s ease,
                transform 0.25s var(--ease-marbl, cubic-bezier(0.32, 0.72, 0, 1));
  }
  .nav-links a,
  .nav-links a:first-child,
  .nav-links a:last-child {
    height: auto;
    width: 100%;
    padding: var(--gap-xs) var(--gap-sm);
    white-space: nowrap;
  }

  /* Burger bars morph to an X on open. 3 bars, 1.5px tall, 4px gap = 5.5px shift
     to centre the outer bars before they rotate. */
  .nav-burger span {
    transition: transform 0.3s var(--ease-marbl, cubic-bezier(0.32, 0.72, 0, 1)),
                opacity 0.2s ease,
                background 0.2s ease;
  }
  .nav-menu.is-open .nav-burger span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
  .nav-menu.is-open .nav-burger span:nth-child(2) { opacity: 0; }
  .nav-menu.is-open .nav-burger span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }
}

/* ═══════════════════════════════════════════════════════════════════════════════
   06. FOOTER + REVEAL BAND
   Includes the full-bleed .footer-rule. Use .footer-rule--inset for the older
   content-width divider.
   ────────────────────────────────────────────────────────────────────────── */
/**
 * Site Footer — TALL canonical footer (Marbl square kit, 15 Jun 2026).
 * Depends on: core/marbl-v2.css tokens + .btn-icon-social (canonical).
 *
 * Structure: brand + link columns + subscribe (.footer-top), a visible
 * legal/meta row (.footer-meta — no hover box, no avatar), and a giant
 * MARBL wordmark that rises into view on scroll over an ember band.
 * Square throughout (radius tokens are 0 in this kit).
 */

/* Reveal-footer geometry: the page clears this much at the bottom so the fixed
   wordmark layer behind it is exposed when you reach the end. */
body { --footer-reveal-h: clamp(160px, 16vw, 320px); }
.page {
  position: relative;
  z-index: 1;
  background: var(--marbl-charcoal, #171415);
  margin-bottom: var(--footer-reveal-h);
}

/* .container is defined once, in section 01 above. */

.site-footer {
  position: static;
  background: var(--marbl-charcoal, #171415);
  color: var(--marbl-white-90, rgba(255, 255, 255, 0.9));
  padding-bottom: var(--gap-md, 40px);
  /* NO overflow-x here, deliberately. An earlier fix used `overflow-x: clip` to contain a
     100vw breakout; Richard's call, and he is right: correct structure and widths produce
     no horizontal scrollbar in the first place, so a clip is masking a fault rather than
     removing it. The divider is now `.footer-divider` - full width by nature. */
}

/* ── Top: brand + nav columns + subscribe ───────────────────────────── */
.footer-top {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr 1.7fr;
  gap: var(--gap-lg, 60px) var(--gap-md, 40px);
  padding-block: var(--gap-xl, 80px) var(--gap-lg, 60px);
  align-items: start;
}

.footer-brand { display: flex; flex-direction: column; gap: var(--gap-sm, 20px); }
.footer-logo { display: inline-flex; height: 52px; width: auto; }
.footer-tagline {
  margin: 0;
  max-width: 28ch;
  color: var(--marbl-white-50, rgba(255, 255, 255, 0.5));
  font-size: var(--text-sm, 13px);
  line-height: 1.6;
}

.footer-col { display: flex; flex-direction: column; }
.footer-col__title {
  margin: 0 0 var(--gap-sm, 20px);
  font-size: var(--text-xs, 11px);
  font-weight: var(--font-bold, 700);
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--marbl-white-40, rgba(255, 255, 255, 0.4));
}
.footer-col a {
  color: var(--marbl-white-70, rgba(255, 255, 255, 0.7));
  text-decoration: none;
  font-size: var(--text-sm, 13px);
  line-height: 1;
  padding: var(--gap-tight, 6px) 0;
  width: fit-content;
  transition: color var(--transition-fast, 0.15s ease);
}
.footer-col a:hover,
.footer-col a:focus-visible { color: var(--marbl-ember, #F35226); }

/* ── Subscribe (Sympos-style underline + square ember submit) ────────── */
.footer-subscribe { display: flex; flex-direction: column; }
.footer-subscribe__hint {
  margin: 0 0 var(--gap-sm, 20px);
  max-width: 32ch;
  color: var(--marbl-white-50, rgba(255, 255, 255, 0.5));
  font-size: var(--text-sm, 13px);
  line-height: 1.6;
}
.footer-subscribe__form { display: flex; flex-direction: column; }
/* Input + submit share one underline; the Turnstile sits BELOW this row so it
   never steals the button's right-edge alignment. */
.footer-subscribe__field {
  display: flex;
  align-items: flex-end;
  gap: var(--gap-xs, 10px);
  border-bottom: 1px solid var(--marbl-white-15, rgba(255, 255, 255, 0.15));
  transition: border-color var(--transition-fast, 0.15s ease);
}
.footer-subscribe__field:focus-within { border-bottom-color: var(--marbl-ember, #F35226); }
/* Canonical underline input (ui-items): transparent bg, hairline underline,
   ember focus border. */
.footer-subscribe__input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: 0;
  color: var(--marbl-white, #fff);
  font: inherit;
  font-size: var(--text-base, 15px);
  padding: var(--gap-xs, 10px) 0;
}
.footer-subscribe__input::placeholder { color: var(--marbl-white-40, rgba(255, 255, 255, 0.4)); }
.footer-subscribe__input:focus { outline: none; }
.footer-subscribe__btn {
  flex-shrink: 0;
  /* 10px gap between the button's bottom and the underline (matches input padding). */
  margin-bottom: var(--gap-xs, 10px);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--marbl-ember, #F35226);
  color: var(--marbl-charcoal-darkest, #131112);
  border: 0;
  border-radius: var(--radius, 0);
  cursor: pointer;
  transition: background var(--transition-fast, 0.15s ease), color var(--transition-fast, 0.15s ease);
}
.footer-subscribe__btn:hover { background: var(--marbl-ember-dark, #BB2F09); color: var(--marbl-white, #fff); }
.footer-subscribe__btn svg { width: 18px; height: 18px; transition: transform var(--transition-base, 0.2s ease); }
.footer-subscribe__btn:hover svg { transform: translateX(2px); }
.footer-subscribe__msg {
  margin: var(--gap-xs, 10px) 0 0;
  min-height: 1.2em;
  font-size: var(--text-sm, 13px);
  color: var(--marbl-ember, #F35226);
}

/* ── Meta row: visible legal/copyright (no hover box) + social ──────── */
/* ── FULL-WIDTH DIVIDER — the structural way (Richard, 29 Jul 2026) ──────────────────
   `.footer-divider` is a full-width block INSIDE the full-width footer, wrapping the
   max-width `.container`. Its border-top therefore spans the viewport because the
   element already does. No breakout, no 100vw, no scrollbar, nothing to suppress.

     <footer class="site-footer">
       <div class="container footer-top">…</div>
       <div class="footer-divider">          ← full width, carries the border
         <div class="container footer-meta">…</div>   ← max-width content
       </div>
     </footer>

   ⚠️ THIS REPLACES an <hr class="footer-rule"> that escaped its container with
   `margin-inline: calc(50% - 50vw)`. That worked, but 100vw INCLUDES the scrollbar, so it
   rendered 1920px in a 1910px viewport and pushed a horizontal scrollbar onto the page.
   The first patch was `overflow-x: clip` on the footer — Richard, correctly: *"using clip
   is just masking a problem. If you are using the right structure and widths you should
   not get any horizontal scrollbars at all."* He is right. Structure, not suppression. ── */
.footer-divider {
  border-top: 1px solid var(--marbl-white-08, rgba(255, 255, 255, 0.08));
}

/* Retained so v2-era markup still renders sensibly if it lands on a v3 page: a plain
   inset rule, no breakout. New builds use .footer-divider. */
.footer-rule {
  border: 0;
  border-top: 1px solid var(--marbl-white-08, rgba(255, 255, 255, 0.08));
  margin: 0;
}
.footer-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--gap-sm, 20px);
  padding-block: var(--gap-md, 40px);
}
.footer-copy {
  margin: 0;
  color: var(--marbl-white-40, rgba(255, 255, 255, 0.4));
  font-size: var(--text-sm, 13px);
  line-height: 1.6;
}
.footer-social { display: flex; align-items: center; gap: var(--gap-2xs, 8px); }

/* ── Fixed reveal layer: full-width Marbl wordmark on ember, behind page ──
   .page is opaque charcoal and carries margin-bottom = reveal height, so the
   document scrolls past it and exposes the fixed wordmark beneath. */
.footer-reveal {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 0;
  height: var(--footer-reveal-h);
  background: var(--marbl-charcoal, #171415);
  overflow: hidden;
  display: flex;
  align-items: center;
}
/* Ember wordmark via mask (the source SVG is a single charcoal fill), so it
   reads orange on the charcoal band. cover = full-bleed, cropped (cut-off).

   ⚠️ THE URL MUST NOT BE ROOT-RELATIVE. This was `url('/marbl/marblcodes.svg')`, which
   resolves against the CONSUMING site, not against marbl.codes where this stylesheet
   lives. On marbl.racing it pointed at marbl.racing/marbl/marblcodes.svg - a 404 - so
   the reveal band silently lost its wordmark. v3 is served cross-origin by design, so
   every asset URL in this file must be absolute or overridable. (29 Jul 2026.)

   --reveal-mark lets each site supply its OWN wordmark, which also settles the taste
   problem flagged 28 Jul: a giant "marblcodes" wordmark on a Racing domain. Set it in
   a page-level block:  :root { --reveal-mark: url('/assets/my-logo.svg'); }            */
.footer-reveal__mark {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--marbl-ember, #F35226);
  -webkit-mask: var(--reveal-mark, url('https://marbl.codes/marbl/marblcodes.svg')) center / cover no-repeat;
          mask: var(--reveal-mark, url('https://marbl.codes/marbl/marblcodes.svg')) center / cover no-repeat;
  user-select: none;
  pointer-events: none;
}

/* ── Responsive ─────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  .footer-top { grid-template-columns: 1fr 1fr; gap: var(--gap-md, 40px); padding-block: var(--gap-lg, 60px) var(--gap-md, 40px); }
  .footer-brand { grid-column: 1 / -1; }
  .footer-subscribe { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .footer-top { grid-template-columns: 1fr; }
  .footer-meta { flex-direction: column; align-items: flex-start; }
}

/* ═══════════════════════════════════════════════════════════════════════════════
   07. HOLDING PAGE
   Only needed on holding/placeholder pages. Harmless elsewhere.
   ────────────────────────────────────────────────────────────────────────── */
/* Holding Page - page-specific styles only. Header, footer, button, tokens and
   fonts are linked from the canonical library; this styles only the centre
   message, the sticky-footer scaffold, and the return button. Docs: holding-page.md */

/* Canonical container - the footer reveal (and any canonical section) uses it for
   edge padding. The holding page loads marbl-v2.css (tokens) but NOT the marbl-core
   bundle that normally provides .container, so it is defined here. Max-width 1600px,
   padding-inline 40px desktop / 20px mobile. */
/* .container is defined once, in section 01 above. */
@media (max-width: 520px) {
  .container { padding-inline: var(--gap-sm, 20px); }
}

/* .page is the footer-reveal wrapper (charcoal + bottom margin exposing the
   reveal band). These rules add the sticky-footer column so the holding
   message centres and the footer sits at the bottom. */
.page {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}

.hp-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--gap-md, 40px) var(--gap-sm, 20px);
  gap: var(--gap-sm, 20px);
}
.hp-eyebrow {
  font-size: var(--text-xs, 11px);
  font-weight: 600;
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--marbl-white, #ffffff);
  line-height: 1;
}
.hp-title {
  font-family: var(--font-heading, 'Urbanist', sans-serif);
  font-weight: var(--font-bold, 700);
  font-size: var(--text-4xl, clamp(48px, 2rem + 3.5vw, 80px));
  line-height: 1.05;
  color: var(--marbl-white, #ffffff);
  max-width: 16ch;
}
.hp-message {
  font-size: var(--text-lg, clamp(16px, 0.9rem + 0.3vw, 18px));
  line-height: 1.6;
  color: var(--marbl-white-50, rgba(255, 255, 255, 0.5));
  max-width: 52ch;
}
.hp-cta-row { margin-top: var(--gap-xs, 10px); }

/* Return button (.legal-back-btn) is now canonical in site-header.css, which
   this page links - no local copy needed. Only the mobile-hide override is
   page-specific. */

/* Mobile: hide the header return button (Richard, 2 Jun 2026). */
@media (max-width: 768px) {
  .legal-back-btn { display: none; }
}
