
/* === src/assets/vendor/marbl-fonts/marbl-fonts.css === */
/* ===================================================================
   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/vendor/marbl-fonts/assets/inter/inter-variable.woff2') format('woff2-variations'),
       url('/assets/vendor/marbl-fonts/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/vendor/marbl-fonts/assets/urbanist/urbanist-variable.woff2') format('woff2-variations'),
       url('/assets/vendor/marbl-fonts/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/vendor/marbl-fonts/assets/petrona/petrona-variable.woff2') format('woff2-variations'),
       url('/assets/vendor/marbl-fonts/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/vendor/marbl-fonts/assets/petrona/petrona-variable-italic.woff2') format('woff2-variations'),
       url('/assets/vendor/marbl-fonts/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); }

/* === src/assets/vendor/core/marbl-v2.css === */
/**
 * Marbl Design System v2.0.0
 * Clean token set built from BRAND.md (canonical source of truth).
 * 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: Marbl/design-system/BRAND.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;
  --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 */
  --color-success: #22c55e;
  --color-warning: #f59e0b;
  --color-error: #ef4444;
  --color-info: #3b82f6;

  /* ── Typography ── */
  --font-heading: 'Urbanist', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-accent: 'Petrona', Georgia, serif;

  --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;

  /* ── Border radius ── */
  --radius-2xs: 2px;       /* Tightest — small UI utility rails (slider tracks) */
  --radius-xs: 4px;        /* Small focus ring radius */
  --radius-sm: 8px;        /* Compact controls (mini buttons) */
  --radius: 10px;          /* Default */
  --radius-lg: 20px;
  --radius-circle: 50%;    /* Round shapes — locked 30 Apr 2026 */
  --radius-full: 9999px;

  /* ── 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) ── */
  --width-sm: 600px;
  --width-md: 800px;
  --width-lg: 1000px;
  --width-xl: 1200px;
  --width-2xl: 1400px;
  --width-max: 1600px;
  --width-ultra: 1800px;

  /* ── 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;
  }
}

/* ── 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;
  border-radius: 4px;
}

.btn-icon-social svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* === src/assets/vendor/site-header/site-header.css === */
/**
 * 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)
 */

.site-header {
  position: static;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--gap-sm, 20px) clamp(20px, 1.5625vw + 15px, 40px);
  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. Documented in site-header.md but the implementation was
 * missing until 25 April 2026 (caught when subscribe.marbl.codes' 100vh
 * layout lost its footer after a hidden `.site-header { position: fixed }`
 * hack in local menu.css was removed). Now properly canonical.
 *
 * 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: 50%;
}

.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: 50%;
  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);
  border-radius: 1px;
  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);
}

/* Mobile */
@media (max-width: 768px) {
  .site-header {
    padding: var(--gap-xs, 10px) var(--gap-sm, 20px);
  }
}

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

/* === src/assets/vendor/site-footer/site-footer.css === */
/**
 * Site Footer
 * Harvested from subscribe.marbl.codes 20 April 2026.
 * Depends on: core/marbl-v2.css tokens + base .site-footer rules.
 *
 * IMPORTANT: static-positioned by default. Apply .site-footer--fixed
 * modifier (defined in marbl.css) if you need fixed positioning.
 */

.site-footer {
  position: static;
  background: var(--marbl-charcoal, #171415);
  border-top: 1px solid var(--marbl-white-04, rgba(255, 255, 255, 0.04));
  padding: var(--gap-sm, 20px) var(--gap-md, 40px);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--gap-sm, 20px);
  flex-wrap: wrap;
}

/* Left half */
.footer-left {
  display: flex;
  align-items: center;
  gap: var(--gap-xs, 10px);
}

/* .footer-avatar: footer-positioning concerns only.
   Avatar primitive (size, radius, border, hover) is canonical in
   ui-items/avatar.css — consumers must load that and apply
   `.avatar avatar--40` on the same element. Reconciled 28 Apr 2026
   (was duplicating 36px width/border rules; now matches canonical 40px
   from .avatar--40). The fallback rules below kick in if avatar.css
   isn't loaded — they match avatar.css exactly so no visual drift. */
.footer-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Visible avatar size is 40 (--gap-md) and content-box keeps the
     1px border outside the 40px content so the rendered avatar is a
     true 40x40. Locked 30 Apr 2026 (previously border-box squeezed
     visible content to 38x38). Tokenised to --gap-md. */
  box-sizing: content-box;
  width: var(--gap-md, 40px);
  height: var(--gap-md, 40px);
  border-radius: var(--radius-full, 9999px);
  overflow: hidden;
  border: 1px solid var(--marbl-white-15, rgba(255, 255, 255, 0.15));
  background: transparent;
  padding: 0;
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color var(--transition-fast, 0.15s ease);
  -webkit-appearance: none;
  appearance: none;
}

.footer-avatar:hover {
  border-color: var(--marbl-ember, #F35226);
}

.footer-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.footer-links {
  display: flex;
  align-items: center;
  /* Tight container gap because each link has 8px horizontal padding
     for tap target. Visual text-to-text spacing = container gap +
     2x link padding = 4 + 16 = 20px (matches original tight feel).
     Locked 1 May 2026. */
  gap: var(--gap-3xs, 4px);
  flex-wrap: wrap;
}

.footer-links a,
.footer-link-button {
  color: var(--marbl-white-50, rgba(255, 255, 255, 0.5));
  text-decoration: none;
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-sm, 13px);
  font-weight: var(--font-regular, 400);
  line-height: 1;
  background: none;
  border: none;
  /* Padding gives the inline footer links a 24px+ tap target on touch
     devices (WCAG 2.5.8). Container gap (--gap-sm, 20px) plus each
     link's horizontal padding gives adjacent-target spacing well over
     24px. Locked 1 May 2026 (negative-margin trick removed - it
     cancelled the spacing). */
  padding: var(--gap-2xs, 8px);
  cursor: pointer;
  transition: color var(--transition-fast, 0.15s ease);
}

.footer-links a:hover,
.footer-link-button:hover {
  color: var(--marbl-white, #ffffff);
}

/* Thou Art That sits alongside the other footer links — same colour,
   same weight, same hover. No ember highlight (footer is quiet chrome). */

/* Right half */
.footer-right {
  display: flex;
  align-items: center;
  gap: var(--gap-3xs, 4px);
}

/* .btn-icon-social is defined in core/marbl-v2.css - canonical across the site.
   Don't re-declare here. */

/* Impressum tooltip - hidden by default, reveals on hover or focus */
.footer-impressum {
  position: relative;
}

/* Reset browser <button> chrome - no border, no shading. Colour comes from
   the .btn-icon-social class applied alongside this one (grey at rest, ember
   on hover). Do NOT set color here — `color: inherit` was walking up to the
   body and winning over .btn-icon-social, turning the icon white. */
.footer-impressum__trigger {
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  border: none;
  padding: 0;
  box-shadow: none;
}

/* Universal :focus-visible from marbl.css handles the ember ring.
   Extra offset for this small icon button. */
.footer-impressum__trigger:focus-visible {
  outline-offset: 2px;
  border-radius: var(--radius-xs, 4px);
}

/* Focus-visible on footer links (matches hover states) */
.footer-links a:focus-visible,
.footer-link-button:focus-visible {
  color: var(--marbl-ember, #F35226);
}

.footer-avatar:focus-visible {
  outline-offset: 2px;
  border-radius: var(--radius-circle, 50%);
}

/* Quiet impressum tooltip: blends with page chrome.
   Same bg as main (--marbl-charcoal), smaller padding + font, lighter weight. */
.footer-impressum__tooltip {
  position: absolute;
  bottom: calc(100% + var(--gap-xs, 10px));
  right: 0;
  min-width: 240px;
  padding: var(--gap-xs, 10px) 14px;
  background: var(--marbl-charcoal, #171415);
  border: 1px solid var(--marbl-white-08, rgba(255, 255, 255, 0.08));
  border-radius: var(--radius, 10px);
  font-size: var(--text-xs, 11px);
  font-weight: var(--font-light, 300);
  line-height: 1.6;
  color: var(--marbl-white-50, rgba(255, 255, 255, 0.5));
  opacity: 0;
  transform: translateY(4px);
  transition: opacity var(--transition-base, 0.2s ease), transform var(--transition-base, 0.2s ease);
  pointer-events: none;
  z-index: 10;
}

.footer-impressum:hover .footer-impressum__tooltip,
.footer-impressum:focus-within .footer-impressum__tooltip,
.footer-impressum__trigger:focus + .footer-impressum__tooltip,
.footer-impressum.is-pinned .footer-impressum__tooltip {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Mobile tooltip base transform aligns with desktop (translateY 4px) */

/* Mobile */
@media (max-width: 768px) {
  .site-footer {
    flex-direction: column;
    gap: var(--gap-sm, 20px);
    padding: var(--gap-sm, 20px);
    text-align: center;
  }

  /* Avatar on its own line, then links stack vertically centred.
     Every child aligns to the column cross-axis. */
  .footer-left {
    flex-direction: column;
    align-items: center;
    gap: var(--gap-sm, 20px);
    width: 100%;
  }

  .footer-links {
    flex-direction: column;
    align-items: center;
    gap: var(--gap-xs, 10px);
    width: 100%;
  }

  /* Thou Art That: white + bold on mobile only.
     Higher specificity than .footer-links a to override its font: inherit. */
  .footer-links .footer-link-featured {
    color: var(--marbl-white, #ffffff) !important;
    font-weight: var(--font-bold, 700) !important;
  }

  .footer-right {
    width: 100%;
    justify-content: center;
  }

  .footer-impressum__tooltip {
    right: auto;
    left: 50%;
    transform: translate(-50%, 4px);
  }

  .footer-impressum:hover .footer-impressum__tooltip,
  .footer-impressum:focus-within .footer-impressum__tooltip,
  .footer-impressum.is-pinned .footer-impressum__tooltip {
    transform: translate(-50%, 0);
  }
}

/* === src/assets/vendor/menu/menu.css === */
/**
 * Marbl Codes — Fullscreen Menu (v2)
 * 40/60 split: nav left, clock + contact + connect right
 * Inspired by Fundamental Studio (fundamental.bg)
 */

/* ==========================================================================
   Menu Overlay
   ========================================================================== */

.menu-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal, 300);
  pointer-events: none;
  visibility: hidden;
  overflow-x: hidden;
}

.menu-overlay.is-open {
  pointer-events: auto;
  visibility: visible;
}

.menu-overlay__panel {
  position: absolute;
  inset: 0;
  clip-path: inset(0 0 100% 0);
}

/* Panels match the header background (var(--marbl-charcoal)) so there's no
   "menu is darker than header" weirdness when the overlay opens. */
.menu-overlay__panel--back  { background: var(--marbl-charcoal, #171415); }
.menu-overlay__panel--front { background: var(--marbl-charcoal, #171415); }

/* ==========================================================================
   Content — 40/60 Split
   ========================================================================== */

.menu-overlay__content {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 40% 30% 30%;
  height: 100vh;
  height: 100dvh;
  max-width: var(--content-max, 1600px);
  margin: 0 auto;
  padding: clamp(100px, 12vh, 140px) clamp(20px, 1.5625vw + 15px, 40px) clamp(20px, 1.5625vw + 15px, 40px);
  opacity: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* ==========================================================================
   Left Column — 40% Navigation
   ========================================================================== */

.menu-overlay__left {
  grid-column: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-right: clamp(20px, 1.5625vw + 15px, 40px);
}

.menu-overlay__nav {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
}

/* Group labels (About / Agents / Agency) - Brand Kit Label Style */
.menu-overlay__nav-label {
  display: block;
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-xs, 11px);
  font-weight: var(--font-semibold, 600);
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--marbl-ember, #F35226);
  margin: clamp(12px, 1vw + 6px, 20px) 0 clamp(6px, 0.5vw + 2px, 12px);
}

.menu-overlay__nav-label:first-child {
  margin-top: 0;
}

/* Dividers are invisible spacing elements only - the nav-label's own top margin
   provides the visual gap between groups. */
.menu-overlay__nav-divider {
  list-style: none;
  height: clamp(8px, 0.6vw + 4px, 12px);
}

.menu-overlay__nav-item a {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-heading, 'Urbanist', sans-serif);
  font-size: clamp(28px, 4vw, 64px);
  font-weight: var(--font-bold, 700);
  line-height: 1.15;
  color: var(--marbl-white, #ffffff);
  text-decoration: none;
  padding: clamp(2px, 0.4vh, 6px) 0;
  transition: transform 0.3s cubic-bezier(0.77, 0, 0.175, 1),
              color var(--transition-slow, 0.3s ease);
}

.menu-overlay__nav-item a::before {
  content: '';
  display: inline-block;
  width: 0;
  height: 0.7em;
  margin-right: 0;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 557 877' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M305.166 876.706H0L251.392 0H556.558L305.166 876.706Z' fill='%23f35227'/%3E%3C/svg%3E");
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  transition: width 0.4s cubic-bezier(0.77, 0, 0.175, 1),
              margin-right 0.4s cubic-bezier(0.77, 0, 0.175, 1);
  flex-shrink: 0;
}

.menu-overlay__nav-item a:hover {
  transform: translateX(10px);
}

.menu-overlay__nav-item a:hover::before {
  width: 0.35em;
  margin-right: var(--gap-xs, 10px);
}

.menu-overlay__nav-item .char {
  display: inline-block;
  opacity: 0;
  transform: translateY(100%);
}

/* ==========================================================================
   Right Column — 60% Clock / Contact / Connect
   ========================================================================== */

/* Centre column — clock */
.menu-overlay__centre {
  grid-column: 2;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Right column — contact + connect + legal stacked */
.menu-overlay__right {
  grid-column: 3;
  display: flex;
  flex-direction: column;
  justify-content: center;
  margin-right: calc(-1 * clamp(20px, 1.5625vw + 15px, 40px));
  padding-right: clamp(20px, 1.5625vw + 15px, 40px);
  overflow: hidden;
}

/* Shared section styles */
.menu-overlay__section {
  padding: clamp(20px, 1.5625vw + 15px, 40px) 0;
}

.menu-overlay__section + .menu-overlay__section {
  border-top: 1px solid var(--marbl-white-08, rgba(255, 255, 255, 0.08));
}

.menu-overlay__section-label {
  display: block;
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-xs, 11px);
  font-weight: var(--font-semibold, 600);
  letter-spacing: 2px;
  text-transform: uppercase;
  color: var(--marbl-ember, #f35227);
  margin-bottom: clamp(10px, 0.78vw + 7.5px, 20px);
}

/* ==========================================================================
   Clock
   ========================================================================== */

.menu-overlay__section--clock {
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 1;
}

.menu-clock {
  position: relative;
  width: clamp(200px, 20vw, 320px);
  height: clamp(200px, 20vw, 320px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.menu-clock__face {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Tick marks styled via JS — base styles */
.menu-clock__tick {
  stroke: rgba(255, 255, 255, 0.12);
  stroke-width: 1.5;
  stroke-linecap: round;
  transition: stroke var(--transition-slow, 0.3s ease);
}

.menu-clock__tick--active {
  stroke: var(--marbl-ember, #f35227);
}

.menu-clock__digital {
  position: relative;
  z-index: 1;
  font-family: var(--font-heading, 'Urbanist', sans-serif);
  font-size: clamp(32px, 3.5vw, 56px);
  font-weight: var(--font-bold, 700);
  color: var(--marbl-white, #ffffff);
  letter-spacing: 4px;
}

/* ==========================================================================
   Contact
   ========================================================================== */

.menu-overlay__section-links {
  display: flex;
  flex-direction: column;
  gap: var(--gap-xs, 10px);
}

.menu-overlay__section-links a {
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: var(--text-base, 15px);
  color: var(--marbl-white, #ffffff);
  text-decoration: none;
  transition: color var(--transition-slow, 0.3s ease);
}

.menu-overlay__section-links a:hover {
  color: var(--marbl-ember, #f35227);
}

/* Agency links — inline horizontal row (matches social-icons spacing).
   Bigger type + 50% white at rest (mirrors footer .btn-icon-social
   colour) so they read as quietly clickable, not shouting. Hover →
   ember matches the rest of the menu. */
.menu-overlay__section--agency .menu-overlay__section-links {
  flex-direction: row;
  flex-wrap: wrap;
  gap: clamp(10px, 0.78vw + 7.5px, 20px);
}

.menu-overlay__section--agency .menu-overlay__section-links a {
  font-size: var(--text-xl, 20px);
  color: var(--marbl-white, #ffffff);
}

.menu-overlay__section--agency .menu-overlay__section-links a:hover {
  color: var(--marbl-ember, #f35227);
}

/* Legal links — smaller, subdued */
.menu-overlay__section--legal .menu-overlay__section-links a {
  font-size: var(--text-xs, 11px);
  color: var(--marbl-white-40, rgba(255, 255, 255, 0.4));
}

.menu-overlay__section--legal .menu-overlay__section-links a:hover {
  color: var(--marbl-ember, #f35227);
}

/* ==========================================================================
   Connect — Social Icons
   ========================================================================== */

.menu-overlay__social {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(10px, 0.78vw + 7.5px, 20px);
}

.menu-overlay__social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  font-size: var(--text-xl, 20px);
  color: var(--marbl-white-50, rgba(255, 255, 255, 0.5));
  text-decoration: none;
  transition: color var(--transition-slow, 0.3s ease), transform var(--transition-slow, 0.3s ease);
}

.menu-overlay__social a svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
  display: block;
}

.menu-overlay__social a:hover {
  color: var(--marbl-ember, #f35227);
  transform: translateY(-2px);
}

/* Header + menu-toggle styles live in site-header.css (canonical single source).
   They used to be duplicated here - removed 20 April 2026 to stop cascade fights
   that were forcing a border-bottom Richard had explicitly turned off. */

/* ==========================================================================
   Mobile
   ========================================================================== */

@media (max-width: 768px) {
  /* .site-header mobile padding lives in site-header.css (canonical owner) */

  .menu-overlay__content {
    display: flex;
    flex-direction: column;
    padding: 100px var(--gap-sm, 20px) var(--gap-sm, 20px);
    gap: var(--gap-md, 40px);
  }

  .menu-overlay__left {
    flex: none;
  }

  /* Hide clock on mobile */
  .menu-overlay__centre {
    display: none;
  }

  /* Blur header background when menu is open */
  .site-header.menu-is-open {
    background: rgba(19, 17, 18, 0.8);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
  }

  .menu-overlay__right {
    flex: none;
    margin-right: 0;
    padding-right: 0;
  }

  .menu-overlay__nav-item a {
    font-size: clamp(28px, 9vw, 48px);
    padding: var(--gap-half, 5px) 0;
  }
}

/* ==========================================================================
   Focus states (keyboard navigation)
   Universal :focus-visible from marbl.css provides the ember ring.
   These ensure interactive elements inside the overlay are visible on tab.
   ========================================================================== */

.menu-overlay__nav-item a:focus-visible {
  outline-offset: 4px;
}

.menu-overlay__social a:focus-visible,
.menu-overlay__section-links a:focus-visible {
  outline-offset: 2px;
}

/* ==========================================================================
   Body scroll-lock + content-shift compensation when the overlay is open.

   menu.js adds `.menu-is-open` to .site-header (NOT to <body>) on open.
   So we cannot select body.menu-is-open — that selector never matches.
   Instead, use :has() to react to the descendant header state.

   Why padding-top: when the menu opens, .site-header gets .menu-is-open
   and goes position:fixed (canonical pin behaviour, see site-header.css).
   That removes ~90px of flow space and the page content jumps up — the
   classic "skip" you see in amateur burger implementations. Holding the
   body padding while open keeps content in place. Built into the canonical
   menu so consumer sites don't have to know about it.

   :has() support: Chrome 105+, Safari 15.4+, Firefox 121+ (well-supported
   for our audience). Older browsers degrade gracefully — they still see
   the jump, but no other breakage.

   (Reconciled 28 Apr 2026 — earlier version selected body.menu-is-open
   directly, which never matched because menu.js doesn't class the body.)
   ========================================================================== */
body:has(.site-header.menu-is-open) {
  overflow: hidden;
  padding-top: 90px;
}

/* ==========================================================================
   Reduced Motion — covers every transition, animation, and transform used
   by the overlay, its children, and the clock.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .menu-overlay,
  .menu-overlay *,
  .menu-overlay *::before,
  .menu-overlay *::after {
    animation-duration: 0.01s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01s !important;
  }
  .menu-overlay__panel { transition: none; }
  .menu-overlay__nav-item .char { opacity: 1; transform: none; }
  .menu-clock__tick,
  .menu-clock__digital,
  .menu-overlay__nav-item a,
  .menu-overlay__section-links a,
  .menu-overlay__social a {
    transition: none;
    transform: none;
  }
}

/* === src/assets/vendor/cookie-consent/cookie-consent.css === */
/**
 * Cookie Consent Banner
 * Bottom-right banner injected by marbl-core.js. Styling aligned with
 * Brand Kit + UI Items (Apr 2026): canonical card container, canonical
 * solid-mini button hover, footer-style quiet links.
 *
 * !important on positioning / radius / padding fights the inline styles
 * marbl-core.js sets when it injects the element.
 */

.cookie-consent {
  position: fixed !important;
  bottom: var(--gap-sm, 20px) !important;
  right: var(--gap-sm, 20px) !important;
  left: auto !important;
  top: auto !important;
  width: auto !important;
  max-width: 420px !important;
  padding: var(--gap-sm, 20px) !important;
  background: var(--marbl-charcoal, #171415) !important;
  border: 1px solid var(--marbl-white-08, rgba(255, 255, 255, 0.08)) !important;
  border-radius: var(--radius, 10px) !important;
  box-shadow: none !important;
  z-index: 200 !important;
  text-align: left !important;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.25s ease-out, transform 0.25s ease-out;
  pointer-events: none;
}

.cookie-consent.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

/* Inner content stack - 10px gaps between label, text, footer (brand-kit gap-xs).
   align-items: stretch + text-align: left are defensive against any legacy
   core rule that might try to centre the flex children horizontally (the
   v1 `marbl.css` block that used to live here did exactly that, and its
   ghost haunted the banner on 24 Apr 2026 until the dead block was
   deleted). Keep these !important so the banner reads left-aligned. */
.cookie-consent-content {
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  gap: var(--gap-xs, 10px) !important;
  text-align: left !important;
  margin: 0 !important;
}

.cookie-consent.is-hidden {
  opacity: 0;
  transform: translateY(8px);
  transition-duration: 0.2s;
}

/* Greeting label - on its own line, white uppercase (Label Style but in white
   rather than ember for a warmer tone). */
.cookie-consent-label {
  display: block !important;
  font-family: var(--font-body, 'Inter', sans-serif) !important;
  font-size: var(--text-xs, 11px) !important;
  font-weight: var(--font-semibold, 600) !important;
  letter-spacing: 2px !important;
  text-transform: uppercase !important;
  line-height: 1 !important;
  color: var(--marbl-ember, #F35226) !important; /* Label Style — ember per canonical UI Items labels */
  margin: 0 !important;
}

.cookie-consent-text {
  font-family: var(--font-body, 'Inter', sans-serif) !important;
  font-size: var(--text-base, 15px) !important;
  font-weight: var(--font-light, 300) !important;
  line-height: 1.55 !important;
  color: var(--marbl-white-70, rgba(255, 255, 255, 0.7)) !important;
  margin: 0 !important;
}

/* "lovely bis-cu-its?" accent - Petrona italic, white, a couple of ems
   larger than statement text */
.cookie-consent-accent {
  font-family: var(--font-accent, 'Petrona', serif);
  font-style: italic;
  font-weight: var(--font-medium, 500);
  font-size: 1.3em;
  line-height: 1;
  color: var(--marbl-white, #ffffff);
}

/* Footer row: links left, button right, sits flush against the statement text. */
.cookie-consent-footer {
  display: flex;
  align-items: center;
  gap: var(--gap-sm, 20px);
  flex-wrap: wrap;
  width: 100%;
  justify-content: space-between;
  margin-top: 0;
}

.cookie-consent-links {
  font-size: var(--text-xs, 11px) !important;
  font-weight: var(--font-light, 300) !important;
  margin: 0 !important;
  display: flex;
  gap: var(--gap-sm, 20px);
  flex-wrap: wrap;
}

.cookie-consent-links a,
.cookie-consent-text a {
  color: rgba(255, 255, 255, 0.6) !important; /* AA: 5.0:1 on charcoal, was 0.5 (4.07:1, failed AA) */
  text-decoration: none;
  transition: color var(--transition-fast, 0.15s ease);
}

.cookie-consent-links a:hover,
.cookie-consent-text a:hover {
  color: var(--marbl-white, #ffffff) !important;
}

/* Canonical Outline button from UI Items: white outline at rest, border +
   text go ember on hover, circle-wrapped arrow icon rotates up-right to right. */
.cookie-consent-btn {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  height: 36px !important;
  padding: 0 var(--gap-sm, 20px) !important;
  font-family: var(--font-body, 'Inter', sans-serif) !important;
  font-size: var(--text-xs, 12px) !important;
  font-weight: var(--font-semibold, 600) !important;
  color: rgba(255, 255, 255, 0.85);
  background: transparent !important;
  border: 1px solid var(--marbl-white-15, rgba(255, 255, 255, 0.15));
  border-radius: var(--radius, 10px) !important;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--transition-base, 0.2s ease), border-color var(--transition-base, 0.2s ease);
}

/* Cookie icon: bare SVG (no circle bg), angled up at rest, rotates + turns
   ember on hover. */
.cookie-consent-btn__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  margin-left: var(--gap-xs, 10px);
  color: #ffffff;
  flex-shrink: 0;
  transform: rotate(-15deg);
  transition: color var(--transition-slow, 0.3s ease), transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

.cookie-consent-btn__icon svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
}

.cookie-consent-btn:hover {
  color: var(--marbl-ember, #F35226);
  border-color: var(--marbl-ember, #F35226);
}

.cookie-consent-btn:hover .cookie-consent-btn__icon {
  color: var(--marbl-ember, #F35226);
  transform: rotate(10deg);
}

.cookie-consent-btn:focus-visible {
  outline: 2px solid var(--marbl-ember, #F35226);
  outline-offset: 2px;
}

/* Reduced motion - no transitions */
@media (prefers-reduced-motion: reduce) {
  .cookie-consent,
  .cookie-consent-btn,
  .cookie-consent-btn__icon,
  .cookie-consent-btn__icon svg {
    transition: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════
   Confetti burst: 16 ember-shade particles in mixed shapes arc up
   from the bottom-right when Accept is clicked. Smooth cubic-bezier
   physics - rise, peak, drift + tumble + fall.
   ═══════════════════════════════════════════════════════════════ */
/* Container is a 1px anchor that JS positions at the button's centre
   before firing the burst. All crumbs start from this exact point and
   explode outward - so the burst reads as coming from the button. */
.cookie-crumbs {
  position: fixed;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
  z-index: 9999;
}

.crumb {
  position: absolute;
  top: 0;
  left: 0;
  width: 6px;
  height: 6px;
  margin-left: -3px;
  margin-top: -3px;
  background: var(--marbl-ember, #F35226);
  opacity: 0;
  will-change: transform, opacity;
}

/* Radial spread: drift-x (-140 to +140) + upward arc (160-260px).
   Colours across 5 ember shades. Shapes: circles, squares, thin ribbons. */
.crumb--1  { width: 6px;  height: 6px;  border-radius: 50%; background: #FF7B4A; --drift-x: -120px; --arc-h: 180px; --spin: 420deg; }
.crumb--2  { width: 4px;  height: 8px;  border-radius: 1px; background: #F35226; --drift-x: -90px;  --arc-h: 230px; --spin: -540deg; }
.crumb--3  { width: 5px;  height: 5px;  border-radius: 1px; background: #BB2F09; --drift-x: -60px;  --arc-h: 250px; --spin: 360deg; }
.crumb--4  { width: 3px;  height: 10px; border-radius: 1px; background: #FFA17A; --drift-x: -30px;  --arc-h: 210px; --spin: -300deg; }
.crumb--5  { width: 7px;  height: 7px;  border-radius: 50%; background: #F35226; --drift-x: 10px;   --arc-h: 260px; --spin: 480deg; }
.crumb--6  { width: 4px;  height: 4px;  border-radius: 50%; background: #BB2F09; --drift-x: 40px;   --arc-h: 200px; --spin: -420deg; }
.crumb--7  { width: 3px;  height: 9px;  border-radius: 1px; background: #FF7B4A; --drift-x: 70px;   --arc-h: 220px; --spin: 540deg; }
.crumb--8  { width: 6px;  height: 6px;  border-radius: 1px; background: #8F2206; --drift-x: 110px;  --arc-h: 190px; --spin: -360deg; }
.crumb--9  { width: 3px;  height: 11px; border-radius: 1px; background: #F35226; --drift-x: -140px; --arc-h: 160px; --spin: 300deg; }
.crumb--10 { width: 5px;  height: 5px;  border-radius: 50%; background: #FFA17A; --drift-x: -70px;  --arc-h: 270px; --spin: -480deg; }
.crumb--11 { width: 4px;  height: 8px;  border-radius: 1px; background: #BB2F09; --drift-x: -15px;  --arc-h: 240px; --spin: 420deg; }
.crumb--12 { width: 8px;  height: 4px;  border-radius: 1px; background: #FF7B4A; --drift-x: 30px;   --arc-h: 195px; --spin: -540deg; }
.crumb--13 { width: 5px;  height: 5px;  border-radius: 50%; background: #F35226; --drift-x: 80px;   --arc-h: 280px; --spin: 360deg; }
.crumb--14 { width: 3px;  height: 10px; border-radius: 1px; background: #8F2206; --drift-x: 130px;  --arc-h: 170px; --spin: -300deg; }
.crumb--15 { width: 7px;  height: 3px;  border-radius: 1px; background: #FFA17A; --drift-x: 145px;  --arc-h: 215px; --spin: 480deg; }
.crumb--16 { width: 4px;  height: 4px;  border-radius: 50%; background: #F35226; --drift-x: 0px;    --arc-h: 285px; --spin: -360deg; }

.cookie-crumbs.is-bursting .crumb {
  animation: confetti-burst 1.1s cubic-bezier(0.22, 0.75, 0.38, 1) forwards;
}

/* All crumbs fire together - no stagger = single puff burst, fewer
   animation start events for the compositor to schedule. */

/* Lean 3-keyframe arc - GPU-composited via translate3d. Browser
   interpolates smoothly between origin, peak, fall. No per-keyframe
   calc() churn. */
@keyframes confetti-burst {
  0% {
    transform: translate3d(0, 0, 0) rotate(0deg);
    opacity: 1;
  }
  50% {
    transform: translate3d(calc(var(--drift-x, 0px) * 0.5), calc(var(--arc-h, 220px) * -1), 0) rotate(calc(var(--spin, 360deg) * 0.5));
    opacity: 1;
  }
  100% {
    transform: translate3d(var(--drift-x, 0px), 60px, 0) rotate(var(--spin, 360deg));
    opacity: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cookie-crumbs { display: none; }
}

/* Mobile - stretch full-width with side gutters */
@media (max-width: 600px) {
  .cookie-consent {
    right: var(--gap-sm, 20px) !important;
    left: var(--gap-sm, 20px) !important;
    max-width: none !important;
  }
}

/* === src/assets/vendor/ui-items/button.css === */
/* ===================================================================
   Canonical Marbl buttons — ui-items §1-3
   Extracted from ui-items/preview.html, 23 April 2026 (subscribe rollout)
   Source of truth. Consumers: subscribe.marbl.codes, luma, atlas, etc.
   =================================================================== */

/* ═══════════════════════════════════════════════════════
   BUTTONS — SHARED BASE
   ═══════════════════════════════════════════════════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--gap-xs, 10px);
  height: 48px;
  padding: 0 28px;
  font-family: var(--font-body, 'Inter', sans-serif);
  font-size: 15px;
  font-weight: 700;
  border: none;
  border-radius: var(--radius, 10px);
  cursor: pointer;
  text-decoration: none;
  position: relative;
  overflow: hidden;
  white-space: nowrap;
}

/* Icon circle */
.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, 50%);
  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);
}

/* ── FILL UP (outline, fills from bottom) ── */
.btn--fill-up {
  background: transparent;
  color: var(--marbl-ember, #F35226);
  border: 1px solid var(--marbl-ember, #F35226);
  z-index: 1;
  transition: color 0.3s ease, border-color 0.3s ease;
}
.btn--fill-up::before {
  content: '';
  position: absolute;
  inset: -1px;
  background: var(--marbl-ember, #F35226);
  border-radius: var(--radius, 10px);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
  z-index: -1;
}
.btn--fill-up .btn__icon { background: var(--marbl-ember-10, rgba(243,82,38,0.1)); color: var(--marbl-ember, #F35226); }
.btn--fill-up:hover::before { transform: scaleY(1); }
.btn--fill-up:hover { color: var(--marbl-charcoal-darkest, #131112); border-color: var(--marbl-ember, #F35226); }
.btn--fill-up:hover .btn__icon { background: var(--marbl-black-15, rgba(0,0,0,0.15)); color: var(--marbl-charcoal-darkest, #131112); }
.btn--fill-up:hover .btn__icon svg { transform: rotate(45deg); }

/* ── SOLID (filled ember, darkens on hover) ── */
.btn--solid {
  background: var(--marbl-ember, #F35226);
  color: var(--marbl-charcoal-darkest, #131112);
  border: 1px solid var(--marbl-ember, #F35226);
  z-index: 1;
  transition: color 0.3s ease, border-color 0.3s ease;
}
.btn--solid::before {
  content: '';
  position: absolute;
  inset: -1px;
  background: var(--marbl-ember-dark, #BB2F09);
  border-radius: var(--radius, 10px);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 0.45s cubic-bezier(0.16, 1, 0.3, 1);
  z-index: -1;
}
.btn--solid .btn__icon { background: var(--marbl-black-15, rgba(0,0,0,0.15)); color: var(--marbl-charcoal-darkest, #131112); }
.btn--solid:hover::before { transform: scaleY(1); }
.btn--solid:hover { color: var(--marbl-white, #fff); border-color: var(--marbl-ember-dark, #BB2F09); }
.btn--solid:hover .btn__icon { background: var(--marbl-white-15, rgba(255,255,255,0.15)); color: var(--marbl-white, #fff); }
.btn--solid:hover .btn__icon svg { transform: rotate(45deg); }

/* ── OUTLINE (white border, goes ember) ── */
.btn--outline {
  background: transparent;
  color: var(--marbl-white-85, rgba(255,255,255,0.85));
  border: 1px solid var(--marbl-white-15, rgba(255,255,255,0.15));
  transition: border-color 0.2s ease, color 0.2s ease;
}
.btn--outline .btn__icon { background: var(--marbl-white-06, rgba(255,255,255,0.06)); color: var(--marbl-white-85, rgba(255,255,255,0.85)); }
.btn--outline:hover { border-color: var(--marbl-ember, #F35226); color: var(--marbl-ember, #F35226); }
.btn--outline:hover .btn__icon { background: var(--marbl-ember-10, rgba(243,82,38,0.1)); color: var(--marbl-ember, #F35226); }
.btn--outline:hover .btn__icon svg { transform: rotate(45deg); }

/* ── GHOST (text + arrow, no bg/border) ── */
.btn--ghost {
  background: transparent;
  color: var(--marbl-white-70, rgba(255,255,255,0.7));
  height: auto;
  padding: 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: 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: 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); }

/* ── MINI (compact height — uses --gap-2xs gap, --radius-sm radius) ── */
.btn--mini {
  height: 36px;
  padding: 0 16px;
  font-size: 12px;
  font-weight: 600;
  gap: var(--gap-2xs, 8px);
  border-radius: var(--radius-sm, 8px);
}
.btn--mini::before { border-radius: var(--radius-sm, 8px) !important; }
.btn--mini .btn__icon { width: var(--icon-xl, 22px); height: var(--icon-xl, 22px); }
.btn--mini .btn__icon svg { width: var(--icon-xs, 11px); height: var(--icon-xs, 11px); }

/* 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.
   Locked 1 May 2026. */
.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 BUTTONS (icon left or right with text — no circle bg)
   ═══════════════════════════════════════════════════════ */
.btn__icon--bare {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: transform 0.3s ease;
}
.btn__icon--bare svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ═══════════════════════════════════════════════════════
   ICON-ONLY BUTTONS
   ═══════════════════════════════════════════════════════ */
.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius, 10px);
  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, 50%); }
.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, 30 Apr 2026).
   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, 10px);
}
.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, 50%); }

/* === src/assets/vendor/ui-items/avatar.css === */
/* ============================================================================
   Avatar — canonical UI primitive, spec at ui-items.md §20.
   Was previously inline in ui-items/preview.html only — promoted to a
   loadable file 2026-04-28 so every consumer site can use the canonical
   classes instead of hardcoding width/height/border per-page.

   To consume: <link rel="stylesheet" href="https://marbl.codes/components/ui-items/avatar.css">

   Sizes: --40 / --60 / --80 / --100 (px, square).
   Border: 1px solid var(--marbl-white-15) (canonical interactive border).
   Hover: border becomes ember (avatar reads as interactive when wrapped
   in <a>).
   ============================================================================ */

.avatar {
  /* content-box so the named size (40 / 60 / 80 / 100) refers to the
     visible avatar (the inner content area), not the bordered outer.
     Without this, global `* { box-sizing: border-box }` + 1px border
     squeezes a "40px" avatar to 38x38 visible. Locked 30 Apr 2026. */
  box-sizing: content-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-full, 9999px);
  border: 1px solid var(--marbl-white-15, rgba(255, 255, 255, 0.15));
  overflow: hidden;
  flex-shrink: 0;
  transition: border-color 0.2s ease;
  background: var(--marbl-charcoal-lighter, #232021);
}

.avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Sizes — the number is the visible diameter. Tokenised to the
   canonical spacing scale (--gap-md/lg/xl/2xl). */
.avatar--40 { width: var(--gap-md, 40px); height: var(--gap-md, 40px); font-size: var(--text-sm, 13px); }
.avatar--60 { width: var(--gap-lg, 60px); height: var(--gap-lg, 60px); font-size: var(--icon-md, 16px); }
.avatar--80 { width: var(--gap-xl, 80px); height: var(--gap-xl, 80px); font-size: var(--icon-xl, 22px); }
.avatar--100 { width: var(--gap-2xl, 100px); height: var(--gap-2xl, 100px); font-size: var(--icon-2xl, 28px); }

/* Initials fallback (no image) */
.avatar--initials {
  background: var(--marbl-charcoal-lighter, #232021);
  color: var(--marbl-white-65, rgba(255, 255, 255, 0.65));
  font-family: var(--font-heading, 'Urbanist', sans-serif);
  font-weight: var(--font-semibold, 600);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* When the avatar is interactive (wrapped in <a>), border goes ember on hover */
a > .avatar:hover,
a:hover > .avatar,
.avatar.is-interactive:hover {
  border-color: var(--marbl-ember, #F35226);
}

/* Stack — author/team strip with overlap effect */
.avatar-stack {
  display: inline-flex;
  flex-direction: row-reverse;
}
.avatar-stack .avatar {
  margin-left: calc(var(--gap-2xs, 8px) * -1);
  border: 2px solid var(--marbl-charcoal, #171415);
}
.avatar-stack .avatar:last-child {
  margin-left: 0;
}
