/* ═══════════════════════════════════════════════════
   DESIGN TOKENS — THREE-TIER TAXONOMY
     Tier 1: Primitive (raw values)
   Tier 2: Semantic  (purpose-driven)
   Tier 3: Component (UI-element-specific)
═══════════════════════════════════════════════════ */

:root {
  /* ═══════════════════════════════════════════════
     TIER 1 — PRIMITIVE (raw values)
  ═══════════════════════════════════════════════ */

  /* ── primitive colors ───────────────────────── */
  --color-orange-500:   #e3290c;
  --color-magenta-500:  #f00ba0;
  --color-gold-500:     #e67c00;
  --color-neutral-100:  #FAFAFA;
  --color-neutral-900:  #050505;
  /* blue-500/emerald-500 nudged slightly for WCAG AA — see WCAG-AA-CONTRAST-FIXES
     note below the semantic brand block; each is single-use so the primitive
     itself could be adjusted without any other consumer needing a workaround. */
  --color-blue-500:   #2d85a3;
  --color-crimson-500: #c81e4a;
  --color-emerald-500: #197c53;
  --color-yellow-500:  #caa907;  /* warm yellow, hsl(50, 93%, 41%) */
  --color-blue-600:    #2060d0;  /* true blue, hsl(220, 73%, 47%) */
  
  --color-neutral-100-rgb: 250, 250, 250;
  --color-neutral-900-rgb: 5, 5, 5;
  --color-orange-500-rgb:  227, 41, 12;
  --color-magenta-500-rgb: 240, 11, 160;
  --color-gold-500-rgb:    230, 124, 0;
  --color-brand-primary-rgb:  var(--color-orange-500-rgb);

  /* ── primitive font families ────────────────── */
  --font-family-display: 'Big Shoulders Display', system-ui, sans-serif;
  --font-family-body:    'DM Sans', system-ui, sans-serif;

  /* ── primitive font weights ─────────────────── */
  --font-weight-300: 300;
  --font-weight-400: 400;
  --font-weight-500: 500;
  --font-weight-700: 700;
  --font-weight-800: 800;
  --font-weight-900: 900;
  --font-weight-display-light: var(--font-weight-300);

  /* ── primitive font sizes ───────────────────── */
  --font-size-label-xs:   clamp(0.750rem, 0.80vw, 0.813rem);
  --font-size-label-sm:   clamp(0.844rem, 0.93vw, 0.906rem);
  --font-size-label-md:   clamp(0.938rem, 1.05vw, 1.000rem);
  --font-size-label-lg:   clamp(1.063rem, 1.25vw, 1.188rem);
  --font-size-label-xl:   clamp(1.250rem, 1.60vw, 1.375rem);
  --font-size-caption:    clamp(0.875rem, 0.95vw, 0.938rem);
  --font-size-body-sm:    clamp(1.000rem, 1.15vw, 1.125rem);
  --font-size-body:       clamp(1.125rem, 1.35vw, 1.250rem);
  --font-size-body-lg:    clamp(1.250rem, 1.75vw, 1.500rem);
  --font-size-body-xl:    clamp(1.375rem, 2.00vw, 1.750rem);
  --font-size-lede:       clamp(1.375rem, 2.20vw, 1.875rem);
  --font-size-heading-2xs: clamp(1rem,     1vw,   1.5rem);   /* h5 */
  --font-size-heading-xs:  clamp(1.375rem, 1.5vw, 2rem);     /* h4 */
  --font-size-heading-sm:  clamp(2rem,     3.5vw, 3rem);     /* h3 */
  --font-size-heading-md:  clamp(2.75rem,  3.5vw, 4.5rem);
  --font-size-heading-lg:  clamp(3rem,     5vw,   6rem);     /* h2 */
  --font-size-heading-xl:  clamp(4.5rem,   7.5vw, 9rem);     /* h1 */
  --font-size-heading-2xl: clamp(6.5rem,  11vw,  13rem);
  --font-size-root:      16px;
  --font-size-display:    clamp(12.50rem, 28.0vw, 27.50rem);

  /* ── primitive letter-spacing (tracking) ────── */
  --tracking-tight-xs:    -.040em;
  --tracking-tight-sm:    -.025em;
  --tracking-tight-md:    -.020em;
  --tracking-normal-xs:   -.015em;
  --tracking-normal-sm:   -.010em;
  --tracking-normal-md:   0em;
  --tracking-normal-lg:   .010em;
  --tracking-normal-xl:   .020em;
  --tracking-loose-xs:    .030em;
  --tracking-loose-sm:    .040em;
  --tracking-loose-md:    .060em;
  --tracking-loose-lg:    .080em;
  --tracking-loose-xl:    .090em;
  --tracking-loose-xxl:   .120em;


  /* ── primitive spacing ──────────────────────── */
  --space-0:  0;
  --space-1:  1px;
  --space-2:  2px;
  --space-4:  4px;
  --space-6:  6px;
  --space-7:  7px;
  --space-8:  8px;
  --space-10: 10px;
  --space-12: 12px;
  --space-14: 14px;
  --space-16: 16px;
  --space-18: 18px;
  --space-20: 20px;
  --space-24: 24px;
  --space-26: 26px;
  --space-28: 28px;
  --space-32: 32px;
  --space-36: 36px;
  --space-40: 40px;
  --space-44: 44px;
  --space-48: 48px;
  --space-52: 52px;
  --space-56: 56px;
  --space-62: 62px;
  --space-64: 64px;
  --space-80: 80px;
  --space-96: 96px;
  --space-120: 120px;
  --space-160: 160px;
  --space-220: 220px;
  --space-240: 240px;
  --space-260: 260px;

  /* ── primitive border-radius ────────────────── */
  --radius-2:      2px;
  --radius-pill:   999px;
  --radius-circle: 50%;

  /* ── primitive border-width ─────────────────── */
  --border-width-default:  1px;
  --border-width-emphasis: 2px;

  /* ── primitive z-index ──────────────────────── */
  --z-index-0:   0;
  --z-index-1:   1;
  --z-index-2:   2;
  --z-index-3:   3;
  --z-index-4:   4;
  --z-index-100: 100;

  /* ── primitive line-height ──────────────────── */
  --line-height-1:    1;
  --line-height-xs:   1.1;
  --line-height-sm:   1.2;
  --line-height-125:  1.25;
  --line-height-130:  1.3;
  --line-height-md:   1.4;
  --line-height-lg:   1.5;
  --line-height-xl:   1.6;
  --line-height-xxl:  1.8;

  /* ═══════════════════════════════════════════════
     TIER 2 — SEMANTIC (purpose-driven)
  ═══════════════════════════════════════════════ */

  /* ── semantic brand ─────────────────────────── */
  /* WCAG-AA-CONTRAST-FIXES — brand-primary/accent/highlight are darkened
     here (not at the orange-500/magenta-500/gold-500 primitives) because
     each primitive also feeds an on-dark chart/accent use (chart-series-2/3/8,
     the capability-radial ring colors, brand-*-tint/-on-dark) that needs to
     stay bright. Darkening only the semantic token keeps those consumers
     untouched while fixing every solid-fill + white/near-white-text pairing
     (buttons, links, section-brand body copy, pills, nav-brand, eyebrows):
       brand-primary   e3290c -> effectively c1230a (white text 4.38:1 -> 5.73:1)
       brand-accent    f00ba0 -> effectively cc0988 (white text 3.82:1 -> 5.17:1)
       brand-highlight e67c00 -> effectively ac5d00 (on white 2.78:1 -> 4.66:1,
                                                       on black 7.03:1 -> 4.19:1) */
  --color-brand-primary:            color-mix(in srgb, var(--color-orange-500) 85%, black);
  --color-brand-accent:             color-mix(in srgb, var(--color-magenta-500) 85%, black);
  --color-brand-highlight:          color-mix(in srgb, var(--color-gold-500) 95%, black);
  --color-brand-primary-tint:       color-mix(in srgb, var(--color-orange-500) 80%, white);
  --color-brand-highlight-tint:     color-mix(in srgb, var(--color-gold-500) 20%, white);
  --color-brand-highlight-on-dark:  color-mix(in srgb, var(--color-gold-500) 40%, white);
  --color-brand-primary-on-dark:    color-mix(in srgb, var(--color-orange-500) 50%, white);
  --color-brand-highlight-faint:    color-mix(in srgb, var(--color-gold-500) 50%, white);

  --gradient-brand: radial-gradient(
    circle 200vh at 150% 100%,
    var(--color-brand-accent),
    color-mix(in srgb, var(--color-brand-accent) 50%, var(--color-brand-primary)) 10%,
    var(--color-brand-primary)
  );

  /* ── semantic backgrounds ───────────────────── */
  --color-background-page:       var(--color-neutral-100);
  --color-background-nav-dark:   rgba(var(--color-neutral-900-rgb), .4);
  --color-background-nav-brand:  color-mix(in srgb, var(--color-brand-primary) 40%, transparent);
  
  --color-background-surface:    var(--color-neutral-100);
  --color-background-surface-hover: color-mix(in srgb, var(--color-neutral-100) 95%, black);
  --color-background-surface-brand: color-mix(in srgb, var(--color-brand-primary) 92%, white);
  --color-background-subtle:       color-mix(in srgb, var(--color-neutral-100) 96%, black);
  --color-background-subtle-hover: color-mix(in srgb, var(--color-neutral-100) 91%, black);

  /* ── semantic text on light backgrounds ──────── */
  /* WCAG-AA-CONTRAST-FIXES — the old 50/60/50% mixes resolved to
     (125,125,125)/(150,150,150)/(125,125,125): text-primary and text-muted
     were identical, and none of the three reached 4.5:1 on the page
     background (3.94:1 / 2.83:1 / 3.94:1). Mixed toward neutral-900 instead
     of the literal `black` keyword (same near-black result, but built from
     an existing token) and reweighted so primary > secondary > muted in
     emphasis, all clearing 4.5:1 with margin. */
  --color-text-primary:    color-mix(in srgb, var(--color-neutral-100) 25%, var(--color-neutral-900));
  --color-text-secondary:  color-mix(in srgb, var(--color-neutral-100) 35%, var(--color-neutral-900));
  --color-text-muted:      color-mix(in srgb, var(--color-neutral-100) 42%, var(--color-neutral-900));

  /* ── semantic text on dark backgrounds ───────── */
  --color-text-inverse-primary:  color-mix(in srgb, var(--color-neutral-100) 50%, white);
  --color-text-inverse-secondary:  color-mix(in srgb, var(--color-neutral-100) 70%, white);
  --color-text-inverse-tertiary:   color-mix(in srgb, var(--color-neutral-100) 100%, white);

  /* ── semantic fills (neutral-100 on dark / neutral-900 on light) ── */
  --color-fill-inverse-opacity-100: rgba(var(--color-neutral-100-rgb), 1);
  --color-fill-inverse-opacity-80:  rgba(var(--color-neutral-100-rgb), .8);
  --color-fill-inverse-opacity-60:  rgba(var(--color-neutral-100-rgb), .6);
  --color-fill-inverse-opacity-40:  rgba(var(--color-neutral-100-rgb), .4);
  --color-fill-inverse-opacity-20:  rgba(var(--color-neutral-100-rgb), .2);
  --color-fill-inverse-opacity-10:  rgba(var(--color-neutral-100-rgb), .1);
  --color-fill-inverse-opacity-5:  rgba(var(--color-neutral-100-rgb), .05);

  --color-fill-opacity-100: rgba(var(--color-neutral-900-rgb), 1);
  --color-fill-opacity-80:  rgba(var(--color-neutral-900-rgb), .8);
  --color-fill-opacity-60:  rgba(var(--color-neutral-900-rgb), .6);
  --color-fill-opacity-40:  rgba(var(--color-neutral-900-rgb), .4);
  --color-fill-opacity-20:  rgba(var(--color-neutral-900-rgb), .2);
  --color-fill-opacity-10:  rgba(var(--color-neutral-900-rgb), .1);

  /* ── semantic borders ────────────────────────── */
  --color-border-light:        rgba(var(--color-neutral-900-rgb), .2);
  --color-border-dark:         rgba(var(--color-neutral-100-rgb), .4);
  --color-border-subtle-dark:  rgba(var(--color-neutral-100-rgb), .1);

  /* ── semantic chart palette (categorical data series, aligned to brand) ──
     Purpose-named by sequence, not hue — see naming-taxonomy rules. ── */
  --color-chart-series-1: var(--color-crimson-500);  /* rose       hsl(348, 71%, 47%) */
  --color-chart-series-2: var(--color-orange-500);   /* orange     hsl(16,  90%, 47%) */
  --color-chart-series-3: var(--color-gold-500);     /* amber      hsl(32, 100%, 45%) */
  --color-chart-series-4: var(--color-yellow-500);   /* yellow     hsl(50,  93%, 41%) */
  --color-chart-series-5: var(--color-emerald-500);  /* green      hsl(158, 65%, 33%) */
  --color-chart-series-6: var(--color-blue-500);     /* teal       hsl(195, 57%, 39%) */
  --color-chart-series-7: var(--color-blue-600);     /* blue       hsl(220, 73%, 47%) */
  --color-chart-series-8: var(--color-magenta-500);  /* magenta    hsl(321, 91%, 49%) */

  /* ── semantic links ─────────────────────────── */
  --color-text-link:       var(--color-brand-primary);
  --color-text-link-hover: color-mix(in srgb, var(--color-brand-primary) 80%, black);

  /* ── semantic signal (problem / solution framing) ── */
  --color-signal-negative: var(--color-crimson-500);
  --color-signal-positive: var(--color-emerald-500);

  /* ── semantic elevation (box-shadow) ────────── */
  --elevation-0: 0 1px 2px rgba(var(--color-neutral-900-rgb), .04),
                 0 0   1px rgba(var(--color-neutral-900-rgb), .03);
  --elevation-1: 0 1px 3px rgba(var(--color-neutral-900-rgb), .08),
                 0 1px 2px rgba(var(--color-neutral-900-rgb), .06);
  --elevation-2: 0 4px 12px rgba(var(--color-neutral-900-rgb), .10),
                 0 2px 4px rgba(var(--color-neutral-900-rgb), .06);
  --elevation-3: 0 8px 28px rgba(var(--color-neutral-900-rgb), .12),
                 0 4px 8px rgba(var(--color-neutral-900-rgb), .08);
  --elevation-translate-0: 0;
  --elevation-translate-1: -1px;
  --elevation-translate-2: -2px;
  --elevation-translate-3: -4px;

   /* ────────── semantic image hover  ─────────── */
  --image-scale-hover: 1.03;

  /* ── semantic reveal ───────────────────────── */
  --reveal-offset: 12px;
  --reveal-threshold: 0.08;
  --reveal-root-margin: 0px 0px -30px 0px;

  /* ── semantic magnetic hover ───────────────── */
  --magnetic-strength: 5;  /* px max pull */

  /* ── semantic shadow build ─────────────────── */
  --shadow-build-layers: 32;
  --shadow-build-accent-duration-ms: 2200;  /* accent (brand) text-shadow build */
  --shadow-build-glow-duration-ms: 6000;    /* color-dodge glow clone settle */
  --shadow-build-glow-offset: -5;
  --shadow-build-glow-opacity: 0.50;
  --shadow-build-easing-accent: 4;
  --shadow-build-easing-glow: 3;

  /* ── semantic nav ──────────────────────────── */
  --nav-mobile-breakpoint: 680;  /* px — matches JS toggle */

  /* ── semantic line-height ──────────────────── */
  --line-height-body:    var(--line-height-xl);   /* 1.6 — body text */
  --line-height-heading: var(--line-height-1);    /* 1   — display headings */
  --line-height-label:   var(--line-height-1);    /* 1   — labels / pills */
  --line-height-lede:    var(--line-height-lg);   /* 1.5 — intro paragraphs */
  --line-height-heading-display: 0.9;             /* tight — h1-h5 display headings */

  /* ── semantic transition ───────────────────── */
  --transition-duration-instant: 0.08s;
  --transition-duration-fast:    0.15s;
  --transition-duration-default: 0.2s;
  --transition-duration-slow:    0.25s;
  --transition-duration-medium:  0.3s;
  --transition-duration-long:    0.4s;
  --transition-duration-xl:      0.6s;
  --transition-duration-xxl:     0.75s;
  --transition-easing-default:   ease;
  --transition-easing-out:       ease-out;
  --transition-easing-spring:    cubic-bezier(0.34, 1.56, 0.64, 1);
  --transition-easing-smooth:    cubic-bezier(0.4, 0, 0.2, 1);

  /* ── semantic blur ─────────────────────────── */
  --blur-nav: 12px;

  /* ── semantic animation ────────────────────── */
  --animation-blink-duration: 2s;

  /* ── semantic spacing ──────────────────────── */
  --section-padding: var(--space-56);  /* .wrap padding, section gaps, pin backdrop — overridden at breakpoints */

  /* ── semantic misc ─────────────────────────── */
  --heading-margin-top: 1em;
  --hero-title-letter-spacing-adjust: -0.03em;
  --button-icon-margin-left: 0.15em;
  --link-arrow-top-adjust: -0.06em;
  --pagination-link-max-width: 22rem;
  --post-pagination-title-offset: -0.55em;

  /* ── semantic font-weight ──────────────────── */
  --font-weight-body:        var(--font-weight-300);  /* body text, descriptions, captions */
  --font-weight-body-strong: var(--font-weight-500);  /* pull quotes, emphasized body */
  --font-weight-label:       var(--font-weight-700);  /* pills, labels, eyebrow, h4/h5 */
  --font-weight-button:      var(--font-weight-800);  /* buttons, CTAs, prominent actions */
  --font-weight-subheading:     var(--font-weight-700);  /* sub headings, display */
  --font-weight-heading:     var(--font-weight-900);  /* main headings, nav logo, display */

  /* ── semantic focus ─────────────────────────── */
  --focus-ring-color:   var(--color-brand-primary);
  --focus-ring-width:   var(--border-width-emphasis);
  --focus-ring-offset:  var(--space-2);

  /* ── semantic icon sizes ────────────────────── */
  --icon-sm: 0.85em;
  --icon-md: 1.1em;
  --icon-lg: 1.35em;
  --icon-xl: 1.6em;

  /* ── semantic icon colours ──────────────────── */
  --icon-color:           var(--color-text-secondary);
  --icon-color-dark:      var(--color-fill-inverse-opacity-60);
  --icon-color-brand:     var(--color-fill-inverse-opacity-80);

  /* ═══════════════════════════════════════════════
     TIER 3 — COMPONENT (UI-element-specific)
  ═══════════════════════════════════════════════ */

  /* ── nav ─────────────────────────────────────── */
  --nav-background:              var(--color-background-nav-dark);
  --nav-background-brand:        var(--color-background-nav-brand);
  --nav-border-color:            var(--color-border-subtle-dark);
  --nav-height:                  var(--space-62);
  --nav-z-index:                 var(--z-index-100);
  --nav-logo-color:              var(--color-neutral-100);
  --nav-link-color:              var(--color-neutral-100);
  --nav-link-hover-color:        var(--color-brand-highlight-on-dark);
  --nav-background-light:        var(--color-fill-inverse-opacity-80);
  --nav-border-light:            var(--color-border-light);
  --nav-logo-color-light:        var(--color-neutral-900);
  --nav-link-color-light:        var(--color-text-secondary);
  --nav-link-hover-color-light:  var(--color-brand-primary);

  /* ── nav toggle (hamburger) ─────────────────── */
  --nav-toggle-size:          var(--space-44);
  --nav-toggle-bar-width:     var(--space-24);
  --nav-toggle-bar-height:    var(--border-width-emphasis);
  --nav-toggle-bar-gap:       var(--space-6);
  --nav-toggle-color:         var(--nav-link-color);
  --nav-toggle-color-light:   var(--nav-link-color-light);

  /* ── nav mobile menu ────────────────────────── */
  --nav-menu-background:      var(--color-background-nav-dark);
  --nav-menu-border-color:    var(--nav-border-color);
  --nav-menu-link-color:      var(--nav-link-color);
  --nav-menu-link-hover-color: var(--nav-link-hover-color);
  --nav-menu-backdrop-color:  rgba(var(--color-neutral-900-rgb), .5);
  --nav-menu-z-index:         var(--nav-z-index);
  --nav-menu-transition-duration: var(--transition-duration-medium);
  --nav-menu-transition-easing:   var(--transition-easing-smooth);

  /* ── pill ───────────────────────────────────── */
  --pill-light-bg:        var(--color-fill-opacity-10);
  --pill-light-color:     var(--color-text-secondary);
  /* WCAG-AA-CONTRAST-FIXES: brand-primary-tint (a light salmon) only gave
     3.19-3.56:1 against the white/near-white pill text below. Swapping to
     the (now-darkened) brand-primary clears 4.5:1 for both .pill-lt and
     .pill-hi (5.83:1 / 5.25:1). */
  --pill-highlight-bg:    var(--color-brand-primary);
  --pill-highlight-color: color-mix(in srgb, var(--color-neutral-100) 96%, black);

  --dot-glow:         0 0 6px var(--color-brand-accent);
  
  /* ── button ─────────────────────────────────── */
  --button-primary-bg:         var(--color-brand-primary);
  --button-primary-color:      var(--color-neutral-100);
  --button-primary-border:     var(--color-brand-primary);
  --button-primary-hover-bg:   color-mix(in srgb, var(--color-brand-primary) 85%, white);
  --button-primary-hover-border: color-mix(in srgb, var(--color-brand-primary) 85%, white);
  --button-inverse-bg:         var(--color-neutral-100);
  --button-inverse-color:      var(--color-brand-primary);
  --button-inverse-border:     var(--color-neutral-100);
  --button-inverse-hover-bg:   color-mix(in srgb, var(--color-neutral-100) 96%, var(--color-brand-primary));
  --button-inverse-hover-border: color-mix(in srgb, var(--color-neutral-100) 96%, var(--color-brand-primary));
  --button-outline-color:      var(--color-fill-inverse-opacity-80);
  --button-outline-border:     var(--color-fill-inverse-opacity-40);
  --button-outline-hover-bg:   var(--color-fill-inverse-opacity-10);
  --button-outline-hover-color: var(--color-fill-inverse-opacity-100);
  --button-outline-hover-border: var(--color-fill-inverse-opacity-60);

  /* ── hero ────────────────────────────────────── */
  --hero-background:             var(--gradient-brand);
  --hero-title-margin-bottom:    var(--space-44);
  --hero-bar-gap:                var(--space-40);
  --hero-bar-border-color:       var(--color-fill-inverse-opacity-20);
  --hero-bar-desc-color:         var(--color-fill-inverse-opacity-100);
  --hero-avail-color:            var(--color-neutral-100);
  --hero-avail-dot-bg:           var(--color-neutral-100);
  --hero-video-x-offset: 0;
  --hero-video-y-offset: 0;
  --hero-video-bound-inset-y: 200;
  --hero-video-bound-inset-x: 200;

  /* ── video scrubber ──────────────────────────── */
  --scrub-weight-x:        0.20;
  --scrub-weight-y:        0.20;
  --scrub-weight-scroll:   0.50;
  --scrub-weight-idle:     0.10;

  --scrub-idle-speed:      0.2;
  --scrub-idle-ramp:       1.8;

  --scrub-reach-x:         0.6; /* fraction of active area at which the video reaches the final frame. */
  --scrub-reach-y:         0.6;

  --scrub-bar-height:      var(--space-6);

  /* ── scrolly pips & radial ──────────────────── */
  --scrolly-pips-duration: 0.35s;
  --scrolly-pips-easing:   var(--transition-easing-smooth);

  /* ── section title ──────────────────────────── */
  --section-title-min-height:    calc(50vh + var(--nav-height));
  --section-title-min-height-md: calc(38vh + var(--nav-height));
  --section-title-min-height-sm: auto;

  /* ── article / case study content ───────────── */
  --article-max-width:            56rem;
  --article-max-width-wide:       72rem;
  --article-heading-gap:          var(--space-48);
  --article-figure-radius:        var(--radius-2);
  --article-figure-caption-color: var(--color-text-muted);
  /* figure size variants — detail-dense artefacts need to
     break out of the 56rem text measure to stay legible */
  --article-figure-width-inset:   48rem;
  --article-figure-width-wide:    72rem;
  --article-figure-board-bg:      var(--color-background-subtle);
  --article-figure-board-border:  var(--color-border-light);
  --article-figure-board-padding: var(--space-16);
  --note-card-bg:                 var(--color-background-subtle);
  --note-card-bg-dark:            var(--color-fill-inverse-opacity-10);
  --note-card-border-width:       var(--border-width-emphasis);
  --list-numbered-marker-color:            var(--color-brand-highlight);
  --list-numbered-marker-color-light:      var(--color-brand-primary);
  --pagination-border-color:      var(--section-border, var(--color-border-light));

  /* ── section themes ──────────────────────────── */

  /* dark: neutral-900 background, inverse text */
  --section-dark-background:      var(--color-neutral-900);
  --section-dark-text:            var(--color-text-inverse-secondary);
  --section-dark-text-muted:      var(--color-text-inverse-tertiary);
  --section-dark-title:           var(--color-brand-highlight-on-dark);
  --section-dark-border:          var(--color-fill-inverse-opacity-10);
  --section-dark-eyebrow-color:   var(--color-text-inverse-secondary);
  --section-grey-background:      var(--color-background-subtle);

  /* brand: orange background, inverse text */
  --section-brand-background:     var(--color-brand-primary);
  --section-brand-text:           var(--color-text-inverse-primary);
  --section-brand-text-muted:     var(--color-text-inverse-secondary);
  --section-brand-title:          var(--color-brand-highlight);
  --section-brand-border:         var(--color-fill-inverse-opacity-10);

  /* light: white background, dark text */
  --section-light-background:     var(--color-background-surface);
  --section-light-text:           var(--color-text-primary);
  --section-light-text-muted:     var(--color-text-muted);
  --section-light-title:          var(--color-brand-highlight);
  --section-light-border:         var(--color-border-light);

  /* footer: dark surface, subtle border */
  --section-footer-background:    var(--color-neutral-900);
  --section-footer-border:        var(--color-fill-inverse-opacity-10);

  /* ── stats ───────────────────────────────────── */
  --stats-number-color:       var(--color-brand-highlight-on-dark);
  --stats-label-color:        var(--color-text-secondary);

  /* ── work row ────────────────────────────────── */
  --work-card-hover-bg:           rgba(var(--color-neutral-900-rgb), .02);
  --work-card-number-color:       var(--color-text-muted);
  --work-card-title-color:        var(--color-text-secondary);
  --work-card-stat-color:         var(--color-brand-highlight);
  --work-card-link-hover-color:   var(--color-text-link-hover);

  /* ── capability radial chart (ring color per proficiency level) ──
     Read by JS via getComputedStyle — see initCapabilityRadial(). ── */
  --capability-level-learning-color:    var(--color-chart-series-6);
  --capability-level-emerging-color:    var(--color-chart-series-4);
  --capability-level-practising-color:  var(--color-chart-series-3);
  /* WCAG-AA-CONTRAST-FIXES: raw chart-series-2 (orange-500) only reaches
     4.45:1 as small text on the radial's near-black center circle —
     brand-primary-on-dark (already used by --stats-number-color for this
     same section) clears it with room to spare (9.04:1). */
  --capability-level-advanced-color:    var(--color-brand-primary-on-dark);
  --capability-level-leading-color:     var(--color-chart-series-8);
  /* text-muted is tuned for light backgrounds (5.04:1 on white) but this
     token is only ever rendered on the radial's dark backdrop, where it'd
     read at <4:1; text-inverse-secondary is the equivalent for dark
     surfaces. Currently unreachable (every capability level in the data
     matches a named color above) but fixed for when that's no longer true. */
  --capability-level-default-color:     var(--color-text-inverse-secondary);

  /* ── heading ─────────────────────────────────── */
  --heading-font:                     var(--font-family-display);
  --heading-color:                    var(--color-brand-highlight);
  --heading-highlight-color:          var(--color-brand-primary-tint);
  --heading-highlight-color-brand:    var(--color-brand-highlight-tint);
  --heading-highlight-color-dark:     var(--color-fill-inverse-opacity-100);
  --heading-highlight-color-faint:    var(--color-brand-highlight-faint);
 


  /* ── eyebrow ─────────────────────────────────── */
  /* WCAG-AA-CONTRAST-FIXES: the flat opacity fills resolved to
     (152,152,152) and (201,201,201) on the page background — 2.76:1 and
     1.59:1 as small uppercase label text (".title-eyebrow", used for the
     "← Case studies" back-link and filter label on every page). Reusing
     the already-fixed text-secondary token, and brand-primary for the
     highlighted word, clears 4.5:1 (6.51:1 / 5.73:1). */
  --eyebrow-color:            var(--color-text-secondary);
  --eyebrow-highlight-color:  var(--color-brand-primary);
}

/* ═══════════════════════════════════════════════════
   RESET
═══════════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: var(--font-size-root); scroll-behavior: smooth; scroll-snap-type: y proximity; }
body {
  font-family: var(--font-family-body);
  background: var(--color-background-page);
  color: var(--color-text-primary);
  -webkit-font-smoothing: antialiased;
}
img { display: block; max-width: 100%; }
a { text-decoration: none; color: inherit; }
a:not([class]) {
  color: var(--color-text-link);
  transition: color var(--transition-duration-fast);
}
a:not([class]):hover {
  color: var(--color-text-link-hover);
}
:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* ── visually hidden (accessibility) ────────────
   Standard "sr-only" pattern: content stays in the accessibility
   tree and reachable by screen readers, but removed from visual
   layout. Use for accessible names/context that would be visual
   clutter — e.g. "(opens in a new tab)" on a link, or the text
   label inside an icon-only button. Never use to hide content
   that sighted keyboard users also need. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ── skip-to-content (accessibility) ────────────
   Visually hidden until focused. When activated,
   adds .scrolly-skipped to <body> to reveal all
   scrollytelling steps instantly. */
.skip-link {
  position: fixed;
  top: var(--space-12);
  left: 50%;
  transform: translateX(-50%) translateY(-120%);
  z-index: calc(var(--nav-z-index) + 1);
  padding: var(--space-12) var(--space-24);
  background: var(--color-neutral-900);
  color: var(--color-neutral-100);
  border-radius: var(--radius-2);
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-label);
  font-size: var(--font-size-body-sm);
  letter-spacing: var(--tracking-loose-sm);
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: var(--elevation-3);
  transition: transform var(--transition-duration-fast);
}

.skip-link:focus {
  transform: translateX(-50%) translateY(0);
}

dl, dt, dd { margin: 0; padding: 0; }
.wrap { max-width: 1360px; margin-inline: auto; padding: var(--section-padding); }
p,
ul:not([class]),
ol:not([class]) {
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-body);
  margin-bottom: var(--space-16);
}
ul:not([class]), ol:not([class]) { padding-left: var(--space-24); }

/* ── paragraph size modifiers ────────────────── */
.p-sm  { font-size: var(--font-size-body-sm); }
.p-md  { font-size: var(--font-size-body); }
.p-lg  { font-size: var(--font-size-body-lg); }
.p-xl { font-size: var(--font-size-body-xl); }

/* ── lede paragraph ──────────────────────────── */
.lede {
  font-size: var(--font-size-lede);
  line-height: var(--line-height-lede);
  font-weight: var(--font-weight-body);
  color: var(--color-text-primary);
}
.section-dark .lede,
.section-brand .lede {
  color: var(--section-text);
}

/* ═══════════════════════════════════════════════════
   SHARED
═══════════════════════════════════════════════════ */

/* ── icon base ───────────────────────────────── */
i[class*="fa-"] {
  color: var(--icon-color, var(--color-text-secondary));
}

/* ── icon size utilities ─────────────────────── */
.icon-sm { font-size: var(--icon-sm); }
.icon-md { font-size: var(--icon-md); }
.icon-lg { font-size: var(--icon-lg); }
.icon-xl { font-size: var(--icon-xl); }

/* ── pill ──────────────────────────────────────── */
.pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--radius-pill);
  padding: 0.4em 0.85em;
  font-family: var(--font-family-display);
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-sm);
  text-transform: uppercase;
}
.pill-lt { background: var(--pill-highlight-bg); color: var(--color-text-inverse-primary); }
.pill-hi { background: var(--pill-highlight-bg); color: var(--pill-highlight-color); }

.filter-pill {
  background: transparent;
  color: var(--color-text-muted);
  border: var(--border-width-default) solid var(--color-border-light);
  cursor: pointer;
  transition: color .15s, border-color .15s;
}
.filter-pill:hover,
.filter-pill[aria-pressed="true"] {
  color: var(--color-text-secondary);
  border-color: var(--color-fill-opacity-40);
}

/* ── filter-pill on section-brand ──────────────── */
.section-brand .filter-pill {
  color: var(--color-text-inverse-secondary);
  border-color: var(--color-fill-inverse-opacity-20);
  background: transparent;
}
.section-brand .filter-pill:hover {
  color: var(--color-text-inverse-primary);
  border-color: var(--color-fill-inverse-opacity-40);
  background: var(--color-fill-inverse-opacity-10);
}
.section-brand .pill-hi {
  background: var(--color-neutral-100);
  color: var(--color-brand-primary);
}

.section-brand .filter-pill[aria-pressed="true"] {
  color: var(--color-neutral-100);
  border-color: var(--color-brand-highlight);
  /* WCAG-AA-CONTRAST-FIXES: the -20 white wash lightened the orange bg
     enough that white text dropped to 4.25:1; -10 keeps the highlight
     wash while staying at 5.01:1. Live on portfolio.php's discipline filter. */
  background: var(--color-fill-inverse-opacity-10);
  font-weight: var(--font-weight-700);
}

/* ── button ────────────────────────────────────── */
.btn {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-button);
  letter-spacing: var(--tracking-normal-xl);
  text-transform: uppercase;
  border-radius: var(--radius-2);
  display: inline-flex;
  align-items: baseline;
  justify-content: center;
  border: var(--border-width-default) solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--transition-duration-long) var(--transition-easing-spring),
    background var(--transition-duration-fast),
    border-color var(--transition-duration-fast),
    color var(--transition-duration-fast);
}
.btn span {
  display: inline-block;
  vertical-align: middle;
  margin-left: 0.15em;
}

/* ── button sizes ─────────────────────────────── */
.btn-sm { padding: .25em .55em .2em; font-size: var(--font-size-caption); }
.btn-md { padding: .4em .8em .35em; font-size: var(--font-size-caption); }
.btn-lg { padding: .5em 1em .45em; font-size: var(--font-size-body); }
.btn-xl { padding: .6em 1.2em .55em; font-size: var(--font-size-body-xl); }

/* primary — solid fill, light sections */
.btn-primary {
  background: var(--color-brand-primary);
  color: var(--color-neutral-100);
  border-color: var(--color-brand-primary);
}

.btn-primary:hover {
  background: color-mix(in srgb, var(--color-brand-primary) 85%, white);
  border-color: color-mix(in srgb, var(--color-brand-primary) 85%, white);
}

/* primary-inverse — solid fill, dark sections */
.btn-primary-dk {
  background: var(--color-neutral-100);
  color: var(--color-brand-primary);
  border-color: var(--color-neutral-100);
}

.btn-primary-dk:hover {
  background: var(--color-brand-primary);
  border-color: var(--color-brand-primary);
  color: var(--color-neutral-100);
  border-color: var(--color-neutral-100);
}

/* secondary-inverse — outline, dark sections */
.btn-secondary-dk {
  background: transparent;
  color: var(--color-fill-inverse-opacity-80);
  border-color: var(--color-fill-inverse-opacity-40);
}

.btn-secondary-dk:hover {
  background: var(--color-fill-inverse-opacity-10);
  color: var(--color-fill-inverse-opacity-100);
  border-color: var(--color-fill-inverse-opacity-60);
}

/* ── button subclasses ────────────────────────── */

/* download — file download action
   Styles the <span> child (file size / type metadata)
   distinctly from the button's primary label. */
.btn--download span {
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-body);
  letter-spacing: var(--tracking-normal-md);
  text-transform: none;
  opacity: 0.7;
}

/* external — opens off-site or in a new tab
   Appends an outward arrow using existing tokens. */
.btn--external::after {
  content: " ↗";
  display: inline-block;
  font-family: var(--font-family-body);
  font-weight: var(--font-weight-body);
  transition: transform var(--transition-duration-long) var(--transition-easing-spring);
}
.btn--external:hover::after {
  transform: translate(var(--space-2), calc(-1 * var(--space-2)));
}

/* arrow — button containing a .link-arrow indicator
   Adds a hover slide animation to the arrow. */
.btn--arrow .link-arrow {
  display: inline-block;
  transition: transform var(--transition-duration-long) var(--transition-easing-spring);
}
.btn--arrow:hover .link-arrow {
  transform: translateX(var(--space-4));
}

/* ── headings ──────────────────────────────────── */
h1, h2, h3, h4, h5 {
  font-family: var(--heading-font);
  font-weight: var(--font-weight-heading);
  letter-spacing: var(--tracking-tight-xs);
  line-height: var(--line-height-heading-display);
  text-transform: uppercase;
  color: var(--heading-color);
  margin-bottom: var(--space-24);
  margin-top: var(--heading-margin-top);
}
h1 { font-size: var(--font-size-heading-xl); }
h2 { font-size: var(--font-size-heading-lg); }
h3 { font-size: var(--font-size-heading-sm); }
h4 { font-size: var(--font-size-heading-xs); font-weight: var(--font-weight-label); letter-spacing: var(--tracking-normal-md); line-height: inherit; margin-bottom: var(--space-16); }
h5 { font-size: var(--font-size-heading-2xs); font-weight: var(--font-weight-label); letter-spacing: var(--tracking-normal-md); line-height: inherit; margin-bottom: var(--space-16); }

/* Visual "sub-head" treatment, decoupled from element level. Case-study
   articles need this look one level deeper than an h4 would sit in their
   outline (h2 section > h3 sub-point), so the class carries h4's look onto
   whichever heading level the content actually calls for. Pick the level
   by document structure, then apply this class for appearance. */
.heading-subhead {
  font-size: var(--font-size-heading-xs);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-normal-md);
  line-height: inherit;
  margin-bottom: var(--space-16);
}

:is(h1, h2, h3, h4, h5) span.pill { vertical-align: middle; margin: 0 0.2em 0.2em 0.9em; }

/* nudges to align different fonts left */
h1, h2 { margin-left: -0.03em; }
.title-eyebrow { margin-left: 0.08em; }

/* small top nudges align text cap-height with adjacent column first line */
h1:first-child, h2:first-child, h3:first-child, h4:first-child, h5:first-child { margin-top: 0; }
.lede:first-child { margin-top: var(--space-4); }

.wrap > :first-child { margin-top: 0; }

.highlight { color: var(--heading-highlight-color); }
.faint { color: var(--heading-highlight-color-faint); }

/* ── heading size modifiers ──────────────────── */
.h-xs { font-size: var(--font-size-heading-xs); }
.h-sm { font-size: var(--font-size-heading-sm); }
.h-md { font-size: var(--font-size-heading-md); }
.h-lg { font-size: var(--font-size-heading-lg); }
.h-xl { font-size: var(--font-size-heading-xl); }
.h-2xl { font-size: var(--font-size-heading-2xl); }

/* ── label — shared type style ──────────────── */
.label {
  display: inline-block;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-sm);
  text-transform: uppercase;
  line-height: var(--line-height-label);
}
.label-xs { font-size: var(--font-size-label-xs); }
.label-sm { font-size: var(--font-size-label-sm); }
.label-md { font-size: var(--font-size-label-md); }
.label-lg { font-size: var(--font-size-label-lg); }
.label-xl { font-size: var(--font-size-label-xl); }


/* ═══════════════════════════════════════════════════
   NAV
═══════════════════════════════════════════════════ */
nav.site-nav,
nav[id="mainNav"] {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  max-width: 100%;
  z-index: var(--nav-z-index);
  height: var(--nav-height);
  display: flex;
  align-items: center;
  background: var(--nav-background);
  -webkit-backdrop-filter: blur(var(--blur-nav));
  backdrop-filter: blur(var(--blur-nav));
  border-bottom: var(--border-width-default) solid var(--nav-border-color);
  transition: background var(--transition-duration-default);
  transform: translateZ(0);
  will-change: background;
}
nav .wrap { display: flex; align-items: center; justify-content: space-between; width: 100%; min-width: 0; }

.nav-logo {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-heading);
  font-size: var(--font-size-body-xl);
  letter-spacing: var(--tracking-normal-sm);
  align-items: baseline;
  text-transform: uppercase;
  color: var(--nav-logo-color);
  white-space: nowrap;
}

.nav-actions { display: flex; align-items: center; gap: var(--space-32); }

.button-row-links { list-style: none; display: flex; align-items: center; gap: var(--space-28); }
.button-row-links a {
  font-family: var(--font-family-display);
  font-size: var(--font-size-label-lg);
  font-weight: var(--font-weight-label);
  text-transform: uppercase;
  color: var(--nav-link-color);
  letter-spacing: var(--tracking-normal-xl);
  line-height: var(--line-height-1);
  transition: color var(--transition-duration-fast);
}
.button-row-links a:hover { color: var(--nav-link-hover-color); }

nav.nav-lt {
  background: var(--nav-background-light);
  border-bottom-color: var(--nav-border-light);
}
nav.nav-lt .nav-logo { color: var(--nav-logo-color-light); }
nav.nav-lt .button-row-links a { color: var(--nav-link-color-light); }
nav.nav-lt .button-row-links a:hover { color: var(--nav-link-hover-color-light); }
nav.nav-lt .btn-primary-dk {
  color: var(--color-neutral-100);
  background-color: var(--color-brand-primary);
}
nav.nav-lt .hero-avail {
  color: var(--color-text-secondary);
}
nav.nav-lt .hero-avail-dot {
  background: var(--color-brand-primary);
  box-shadow: 0 0 4px var(--color-brand-primary);
}

nav.nav-brand {
  background: var(--nav-background-brand);
  border-bottom-color: var(--nav-border-color);
}
nav.nav-brand .nav-logo { color: var(--nav-logo-color); }
nav.nav-brand .button-row-links a { color: var(--nav-link-color); }
nav.nav-brand .button-row-links a:hover { color: var(--nav-link-hover-color); }

/* ── nav toggle (hamburger) ──────────────────────
   Hidden by default; enabled at the mobile breakpoint.
   Bars use currentColor so the theme classes below
   (nav-lt / nav-brand) recolor it automatically.
═══════════════════════════════════════════════════ */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: var(--nav-toggle-size);
  height: var(--nav-toggle-size);
  margin-right: calc(-1 * var(--space-10));
  padding: 0;
  background: transparent;
  border: none;
  color: var(--nav-toggle-color);
  cursor: pointer;
}
nav.nav-lt .nav-toggle { color: var(--nav-toggle-color-light); }
nav.nav-brand .nav-toggle { color: var(--nav-toggle-color); }

.nav-toggle-bars {
  position: relative;
  display: block;
  width: var(--nav-toggle-bar-width);
  height: calc(var(--nav-toggle-bar-height) * 3 + var(--nav-toggle-bar-gap) * 2);
}
.nav-toggle-bar {
  position: absolute;
  left: 0;
  width: 100%;
  height: var(--nav-toggle-bar-height);
  background: currentColor;
  border-radius: var(--radius-2);
}
.nav-toggle-bar:nth-child(1) { top: 0; }
.nav-toggle-bar:nth-child(2) { top: calc(var(--nav-toggle-bar-height) + var(--nav-toggle-bar-gap)); }
.nav-toggle-bar:nth-child(3) { top: calc((var(--nav-toggle-bar-height) + var(--nav-toggle-bar-gap)) * 2); }

@media (prefers-reduced-motion: no-preference) {
  .nav-toggle-bar {
    transition: transform var(--nav-menu-transition-duration) var(--nav-menu-transition-easing),
                opacity var(--transition-duration-default) var(--transition-easing-default);
  }
}
/* bars morph into an X when the menu is open */
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) {
  transform: translateY(calc(var(--nav-toggle-bar-height) + var(--nav-toggle-bar-gap))) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) {
  opacity: 0;
  transform: scaleX(0);
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) {
  transform: translateY(calc(-1 * (var(--nav-toggle-bar-height) + var(--nav-toggle-bar-gap)))) rotate(-45deg);
}

/* ── nav mobile menu ──────────────────────────────
   A single fixed-style flyout (independent of the
   scroll-driven nav-lt/nav-dk/nav-brand theming) so
   it stays legible against whatever content sits
   beneath it while open.
═══════════════════════════════════════════════════ */
.nav-menu-backdrop {
  position: fixed;
  inset: var(--nav-height) 0 0 0;
  background: var(--nav-menu-backdrop-color);
  z-index: var(--nav-menu-z-index);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.nav-menu {
  position: fixed;
  top: var(--nav-height);
  left: 0;
  right: 0;
  z-index: var(--nav-menu-z-index);
  display: flex;
  flex-direction: column;
  gap: var(--space-28);
  max-height: calc(100dvh - var(--nav-height));
  overflow-y: auto;
  padding: var(--space-24);
  background: var(--nav-menu-background);
  -webkit-backdrop-filter: blur(var(--blur-nav));
  backdrop-filter: blur(var(--blur-nav));
  border-bottom: var(--border-width-default) solid var(--nav-menu-border-color);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-8px);
}
@media (prefers-reduced-motion: no-preference) {
  .nav-menu-backdrop {
    transition: opacity var(--nav-menu-transition-duration) var(--nav-menu-transition-easing),
                visibility var(--nav-menu-transition-duration) var(--nav-menu-transition-easing);
  }
  .nav-menu {
    transition: opacity var(--nav-menu-transition-duration) var(--nav-menu-transition-easing),
                transform var(--nav-menu-transition-duration) var(--nav-menu-transition-easing),
                visibility var(--nav-menu-transition-duration) var(--nav-menu-transition-easing);
  }
}
.nav-menu-backdrop.is-open,
.nav-menu.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateY(0);
}

.nav-menu-links {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-20);
}
.nav-menu-links a {
  font-family: var(--font-family-display);
  font-size: var(--font-size-body-lg);
  font-weight: var(--font-weight-label);
  text-transform: uppercase;
  letter-spacing: var(--tracking-normal-xl);
  color: var(--nav-menu-link-color);
  transition: color var(--transition-duration-fast);
}
.nav-menu-links a:hover { color: var(--nav-menu-link-hover-color); }

.nav-menu-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-16);
  padding-top: var(--space-20);
  border-top: var(--border-width-default) solid var(--nav-menu-border-color);
}
.nav-menu-footer .hero-avail { color: var(--nav-menu-link-color); }


/* ═══════════════════════════════════════════════════
   HERO
═══════════════════════════════════════════════════ */

.hero-video-wrap {
  position: absolute;
  inset: 0;
  pointer-events: none; z-index: var(--z-index-1);
  overflow: hidden;
}
.hero-poster,
.hero-video {
  position: absolute;
  inset: 0;
  width: calc(100% - var(--hero-video-x-offset));
  height: 100%;
  max-height: 100dvh;
  min-height: calc(100dvh - var(--nav-height));
  object-fit: cover;
  transform: translate(var(--hero-video-x-offset), var(--hero-video-y-offset));
}
/* Poster is the source of truth for what's visible while loading — it is
   never left to the browser's native poster-attribute swap timing. It only
   fades once JS confirms the video has buffered enough to play/seek
   smoothly (see .is-revealed, set by the scrubber's reveal()). Sharing the
   same offset/size rules as .hero-video keeps the two layers pixel-aligned
   during the crossfade, so revealing doesn't visibly shift the framing. */
.hero-poster {
  z-index: 2;
  transition: opacity .5s ease;
  /* Global `img { max-width: 100% }` (theme.css:520) would otherwise clamp
     this back down whenever --hero-video-x-offset is negative and the
     shared width formula computes to >100%, breaking alignment with
     .hero-video (which isn't an <img> and isn't subject to that rule). */
  max-width: none;
}
.hero-video {
  z-index: 1;
  opacity: 0;
  transition: opacity .5s ease;
}
.hero-video.is-ready { opacity: 1; }
.hero-video-wrap.is-revealed .hero-poster { opacity: 0; pointer-events: none; }

/* Reduced motion: keep the poster as the permanent, static visual —
   regardless of JS class state — no crossfade, no motion. */
@media (prefers-reduced-motion: reduce) {
  .hero-video { opacity: 0 !important; }
}
  
.hero-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--section-padding);
  max-width: 1360px;
  margin-inline: auto;
  z-index: var(--z-index-2);
  width: 100%;
}

.hero-title {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-heading);
  font-size: clamp(5rem, 13.5vw, 9rem);
  line-height: .88;
  letter-spacing: var(--tracking-tight-md);
  margin-top: 0;
  margin-bottom: var(--hero-title-margin-bottom);
  margin-left: var(--hero-title-letter-spacing-adjust);
  text-transform: uppercase;
}
h1.hero-title .highlight, .hero-bar-desc .highlight { color: var(--color-brand-highlight-tint); }

.hero-subtitle {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-subheading);
  font-size: var(--font-size-body-lg);
  line-height: var(--line-height-body-lg);
  letter-spacing: var(--tracking-normal-md);
  margin-bottom: var(--space-32);
  text-transform: uppercase;
}

.container-spacer-with-chat-icon {
  margin-right: 60px;
}

.text-wrap { display: block; }

.text-faint { color: var(--color-text-inverse-tertiary); }

.text-center { text-align: center; }

.shadow-3d {
  position: relative;
}

.gradient-text {
  /* ── local shadow constants (tune the whole animation here) ── */
  --gt-ox-init: 5px;  --gt-oy-init: 5px;   /* exploded, frame 0%   */
  --gt-ox-final: 3px;  --gt-oy-final: 3px;    /* settled, matches .text-shadow  */
  --gt-glow-blur-initial:     8px;  /* matches .text-shadow glow blur */
  --gt-glow-blur-final:       2px;  /* matches .text-shadow glow blur */
  /* glow blur per keyframe phase (rumble → settle) */
  --gt-glow-blur-flash:    20px;  /*  6% */
  --gt-glow-blur-rumble1:  15px;  /* 13% */
  --gt-glow-blur-rumble2:  20px;  /* 20% */
  --gt-glow-blur-rumble3:  15px;  /* 28% */
  --gt-glow-blur-rumble4:  5px;  /* 36% */
  --gt-glow-blur-converge: 8px;  /* 52% */
  --gt-glow-blur-settle:   5px;  /* 85% */
  /* alpha boundary values */
  --gt-shadow-alpha-start: 1;
  --gt-shadow-alpha-end:   0.15;   /* matches .text-shadow dark offset */
  --gt-glow-alpha-start:   0.1;
  --gt-glow-alpha-end:     0.2;    /* matches .text-shadow light glow */
  /* glow alpha per keyframe phase */
  --gt-glow-alpha-flash:    0.55;  /*  6% */
  --gt-glow-alpha-rumble1:  0.08;  /* 13% */
  --gt-glow-alpha-rumble2:  0.40;  /* 20% */
  --gt-glow-alpha-rumble3:  0.04;  /* 28% */
  --gt-glow-alpha-rumble4:  0.30;  /* 36% */
  --gt-glow-alpha-converge: 0.15;  /* 52% */
  --gt-glow-alpha-settle:   0.00;  /* 85% */
  /* shadow alpha per keyframe phase */
  --gt-shadow-alpha-flash:    0.35;  /*  6% */
  --gt-shadow-alpha-rumble1:  0.18;  /* 13% */
  --gt-shadow-alpha-rumble2:  0.28;  /* 20% */
  --gt-shadow-alpha-rumble3:  0.12;  /* 28% */
  --gt-shadow-alpha-rumble4:  0.22;  /* 36% */
  --gt-shadow-alpha-converge: 0.12;  /* 52% */
  --gt-shadow-alpha-settle:   0.10;  /* 85% */
  /* colour sources — rumble-phase tints (brand) vs settled (matches .text-shadow) */
  --gt-glow-color:         color-mix(in oklch, var(--color-gold-500) 90%, white);
  --gt-shadow-color:       color-mix(in oklch, var(--color-gold-500) 95%, white);
  --gt-glow-color-final:   color-mix(in oklch, var(--color-gold-500) 90%, white);
  --gt-shadow-color-final: var(--color-neutral-900);   /* rgba(neutral-900, 0.15) */
  /* gradient endpoints */
  --gt-gradient-start: color-mix(in oklch, var(--color-gold-500) 30%, white);                                   /* pure gold */
  --gt-gradient-end:   color-mix(in oklch, var(--color-gold-500) 55%, white);  /* deep burnt orange */

  background: linear-gradient(to bottom right, var(--gt-gradient-start), var(--gt-gradient-end));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(var(--gt-ox-final) var(--gt-oy-final) 0
            color-mix(in srgb, var(--gt-shadow-color-final) calc(var(--gt-shadow-alpha-end) * 100%), transparent))
          drop-shadow(0 0 var(--gt-glow-blur-final)
            color-mix(in srgb, var(--gt-glow-color-final) calc(var(--gt-glow-alpha-end) * 100%), transparent));
}

/* ── gradient-text reveal: glitch-flash rumble → smooth settle ──
   Each offset is a lerp between init (factor 0) and final (factor 1).
   Factors < 0 overshoot opposite; factors > 1 overshoot past final. ── */
.gradient-text.revealed {
  animation-name: revealGradientText;
  animation-duration: 1.5s;
  animation-timing-function: var(--transition-easing-smooth);
}

@keyframes revealGradientText {
  /* ── hidden, shadow at init position (factor 0) ── */
  0% {
    opacity: 0;
    transform: translateY(var(--reveal-offset));
    text-shadow: 0 0 var(--gt-glow-blur-initial) transparent,
                 var(--gt-ox-init) var(--gt-oy-init) 0 transparent;
  }
  /* ── flash on — bright overexposed glow (x:0, y:2.2 past) ── */
  6% {
    opacity: 1;
    transform: translateY(calc(var(--reveal-offset) * 0.4));
    text-shadow: 0 0 var(--gt-glow-blur-flash) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-flash) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * 0)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * 2.2)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-flash) * 100%), transparent);
  }
  /* ── rumble 1 — jerk left, dim flicker (x:2.9 past, y:0.22) ── */
  13% {
    opacity: 0.55;
    text-shadow: 0 0 var(--gt-glow-blur-rumble1) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-rumble1) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * 2.9)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * 0.22)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-rumble1) * 100%), transparent);
  }
  /* ── rumble 2 — jerk right, bright spike (x:-0.45, y:2.0 past) ── */
  20% {
    opacity: 1;
    text-shadow: 0 0 var(--gt-glow-blur-rumble2) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-rumble2) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * -0.45)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * 2.0)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-rumble2) * 100%), transparent);
  }
  /* ── rumble 3 — drop down, faint (x:2.0 past, y:-0.22 opposite) ── */
  28% {
    opacity: 0.4;
    text-shadow: 0 0 var(--gt-glow-blur-rumble3) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-rumble3) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * 2.0)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * -0.22)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-rumble3) * 100%), transparent);
  }
  /* ── rumble 4 — last jolt up-right (x:0.22, y:2.7 past) ── */
  36% {
    opacity: 0.85;
    text-shadow: 0 0 var(--gt-glow-blur-rumble4) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-rumble4) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * 0.22)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * 2.7)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-rumble4) * 100%), transparent);
  }
  /* ── convergence — pulling inward (x:0.67, y:0.78) ── */
  42% {
    opacity: 1;
    transform: translateY(0);
    text-shadow: 0 0 var(--gt-glow-blur-converge) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-converge) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * 0.67)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * 0.78)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-converge) * 100%), transparent);
  }
  /* ── nearly settled (x:0.89, y:1.0) ── */
  65% {
    text-shadow: 0 0 var(--gt-glow-blur-settle) color-mix(in srgb, var(--gt-glow-color) calc(var(--gt-glow-alpha-settle) * 100%), transparent),
                 calc(var(--gt-ox-init) + (var(--gt-ox-final) - var(--gt-ox-init)) * 0.89)
                 calc(var(--gt-oy-init) + (var(--gt-oy-final) - var(--gt-oy-init)) * 1.0)
                 0 color-mix(in srgb, var(--gt-shadow-color) calc(var(--gt-shadow-alpha-settle) * 100%), transparent);
  }
  /* ── final settled — clear text-shadow, drop-shadow filter takes over ── */
  100% {
    opacity: 1;
    transform: translateY(0);
    text-shadow: none;
  }
}

.text-shadow {
  text-shadow: 0 0 var(--space-10) rgba(var(--color-neutral-100-rgb), 0.2), 3px 3px 0 rgba(var(--color-neutral-900-rgb), 0.15); 
}

.shadow-3d-blue {
  position: absolute;
  inset: 0;
  transform: translate(-10px, -10px);
  color: var(--color-blue-500);
  mix-blend-mode: color-burn;
  opacity: 1;
  pointer-events: none;
  user-select: none;
}

.hero-bar {
  display: grid;
  grid-template-columns: 1fr auto auto;
  align-items: end;
  gap: var(--hero-bar-gap);
  padding-top: var(--space-4);
  border-top: var(--border-width-default) solid var(--hero-bar-border-color);
  justify-content: flex-end;
}
.hero-bar-desc {
  font-family: var(--font-family-display);
  font-size: var(--font-size-body-xl);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-normal-lg);
  color: var(--hero-bar-desc-color);
  text-transform: uppercase;
  line-height: var(--line-height-sm);
  margin-bottom: 0;
}
.button-row, .button-row-right, .button-row-separator {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  flex-wrap: wrap;
  justify-content: flex-start;
  list-style: none;
}
/* Add bottom space when the next sibling is a paragraph or heading */
.button-row:has(+ :is(p, h1, h2, h3, h4, h5, h6)) {
  margin-bottom: var(--space-24);
}

.button-row-right { justify-content: flex-end; }

.button-row-separator > li:not(:last-child)::after {
  content: "\00B7";
  color: var(--color-text-muted);
  display: inline-block;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-sm);
  text-transform: uppercase;
  line-height: var(--line-height-label);
  margin-bottom: var(--space-8);
}

.hero-avail {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  font-weight: var(--font-weight-button);
  font-size: var(--font-size-label-lg);
  letter-spacing: var(--tracking-normal-xl);
  color: var(--hero-avail-color);
  margin-bottom: 0;
}
.hero-avail-dot {
  display: inline-block;
  width: var(--space-6); height: var(--space-6); border-radius: var(--radius-circle);
  background: var(--hero-avail-dot-bg);
  box-shadow: var(--dot-glow);
}
@media (prefers-reduced-motion: no-preference) {
  .hero-avail-dot {
    animation: blink var(--animation-blink-duration) infinite;
  }
}
@keyframes blink { 0%,100%{opacity:1} 50%{opacity:0.3} }

/* ── hero sticky CTA ─────────────────────────── */
.hero-cta {
  position: sticky;
  bottom: var(--space-24);
  align-self: flex-end;
  margin-top: var(--space-20);
}

/* ── shared scrub progress bar ───────────────── */
.scrub-bar {
  width: 100%;
  height: var(--scrub-bar-height);
  pointer-events: none;
  position: relative;
  overflow: hidden;
}
.scrub-bar::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--color-brand-primary);
  transform: scaleX(var(--scrub-progress, 0));
  transform-origin: left;
  opacity: 0.75;
  border-right: var(--color-gold-500) solid 10px;
}

/* hero: absolute bottom, white bg, high z-index */
.hero-scrub-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  background: var(--color-fill-inverse-opacity-60);
  z-index: var(--z-index-2);
}

/* scrolly: full-width, sticky to viewport bottom */
.scrolly-scrub-bar {
  grid-column: 1 / -1;
  position: sticky;
  bottom: 0;
  background: var(--color-fill-opacity-40);
  z-index: 3;
  border-bottom: 1px solid var(--color-fill-opacity-40);
}

/* ═══════════════════════════════════════════════════
   REVEAL-ON-SCROLL
   IntersectionObserver adds .revealed to trigger
   fade-in + 12px rise. Uses animation (not transition)
   so hover transitions stay fully decoupled.
═══════════════════════════════════════════════════ */

.reveal, .reveal-slow {
  opacity: 0;
  transform: translateY(var(--reveal-offset));
}

.revealed {
  animation: revealIn 0.75s ease-out forwards;
}

@keyframes revealIn {
  to { opacity: 1; transform: translateY(0); }
}

/* Staggered reveals for lists — standard nth-child delays */
/* Staggered reveals for lists — applied via nth-child */
.reveal { animation-delay: calc((sibling-index() - 1) * 0.2s); }
.reveal-slow { animation-delay: calc((sibling-index() - 1) * 0.5s + 0.5s); }

/* ── work reveal: exaggerated assembly ─────────
   Larger rise (48px vs default 12px), spring
   easing, and staggered card/image children that
   assemble into place. Scoped to .work-row only. */
.work-row.reveal {
  opacity: 0;
  transform: translateY(64px);
}
.work-row.revealed {
  animation: workRevealIn 1.2s var(--transition-easing-smooth) forwards;
}

@keyframes workRevealIn {
  to { opacity: 1; transform: translateY(0); }
}

/* card slides in from the left */
.work-row.reveal .work-card {
  opacity: 0;
  transform: translateX(-48px);
}
.work-row.revealed .work-card {
  animation: workCardAssemble 0.7s 0.15s var(--transition-easing-smooth) forwards;
}

@keyframes workCardAssemble {
  to { opacity: 1; transform: translateX(0); }
}

/* image scales up into place */
.work-row.reveal .work-card-img-wrap {
  opacity: 0;
  transform: scale(0.78);
}
.work-row.revealed .work-card-img-wrap {
  animation: workImageAssemble 0.7s 0.35s var(--transition-easing-smooth) forwards;
}

@keyframes workImageAssemble {
  to { opacity: 1; transform: scale(1); }
}

/* alternate rows: card slides from right instead */
.work-items > li:nth-child(even) .work-row.reveal .work-card {
  transform: translateX(48px);
}


/* ═══════════════════════════════════════════════════
   SCROLLYTELLING — scroll-driven sequenced reveals
   .section-scrolly wraps .scrolly-step children.
   When a step enters the viewport it animates in.
   Subclasses on the section control the animation
   style; .scrolly-step modifiers control timing.
═══════════════════════════════════════════════════ */

.section-scrolly {
  --scrolly-duration: 0.2s;
  --scrolly-easing:   var(--transition-easing-smooth);
  --scrolly-distance: 40px;
  /* Real rendered height of .scrolly-pin-top's content (eyebrow line +
     space-12 + heading line — not just the heading alone). Used by
     .scrolly-step's clearance padding below. The single heading-line
     estimate undercounts the pin by the eyebrow's height, which is what
     was collapsing the h2→h3 gap toward 0 instead of the site's
     space-24 rhythm. JS (initScrollyScrubBar) measures the pin and
     overwrites this with the exact px value on load/resize; this
     formula is only the pre-JS/no-JS fallback. */
  --pin-content-height: calc(
    var(--font-size-body-xl) * var(--line-height-xs) + var(--space-12) +
    var(--font-size-heading-lg) * var(--line-height-heading-display)
  );
  position: relative;
}

.scrolly-step-card {
  width: 100%;
}

/* ── pin: sticky intro that fixes after animation ── */
.scrolly-pin,
.scrolly-pin-top {
  position: sticky;
  top: calc(var(--nav-height) );
  min-height: auto;
  z-index: 5;
  /* always visible — not part of the scrollytelling fade animation */
  opacity: 1;
  transform: none;
  transition: none;
}
.scrolly-pin-top {
  padding-top: 0;
  padding-bottom: 0;
  overflow: visible;
}

/* Keep the title above the backdrop div, which precedes it in source order. */
.scrolly-pin-top > .scrolly-step-card {
  position: relative;
  z-index: 1;
}

/* ── full-width gradient backdrop behind the capabilities title ──
   A real element (was .scrolly-pin-top::before) so JS can hold a direct
   reference to it and set styles on it, rather than reaching it indirectly
   through custom properties on its host.
   Positioned against .scrolly-pin-top, which is position:sticky and therefore
   the containing block. That host sits inside a centred, max-width .wrap, so
   its distance from the viewport edge changes with viewport width and can't
   be hardcoded — updateMaskBleed() measures it and sets left/width inline.
   The values here are only the pre-JS initial state. */
.scrolly-mask {
  position: absolute;
  /* Extend above into the section padding and below through the heading
     margin so the gradient backdrop covers the full title area. */
  top: calc(-1 * var(--section-padding));
  bottom: calc(-1 * var(--space-24));
  /* Pre-JS fallback: at viewport widths where .wrap hasn't hit its
     max-width, this alone reaches the true viewport edge (section-padding
     is exactly how far .scrolly-pin-top sits from it). Hardcoding the
     desktop --space-56 here left the mask short of the edge at narrower
     breakpoints until updateMaskBleed() ran and corrected it. Beyond
     .wrap's max-width, JS still has to take over — centring adds extra
     margin no CSS var here can know about. */
  left: calc(-1 * var(--section-padding));
  width: 100vw;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    172deg,
    var(--color-brand-primary) 30%,
    transparent 60%
  );
  /* Progressive horizontal slide, driven by scroll. The element is exactly
     one viewport wide, so -100% parks it fully off screen to the left and
     0% lands it in its natural full-bleed position. */
  transform: translateX(-100%);
  transition: transform 0.15s linear;
}

.section-dark .scrolly-mask {
  background: linear-gradient(
    to bottom,
    var(--color-neutral-900) 0%,
    var(--color-neutral-900) 85%,
    transparent 100%
  );
}

.section-light .scrolly-mask {
  background: linear-gradient(
    to bottom,
    var(--color-background-surface) 0%,
    var(--color-background-surface) 85%,
    transparent 100%
  );
}
.scrolly-pin-bottom {
  position: sticky;
  bottom: 0;
  min-height: auto;
  z-index: 2;
  opacity: 1;
  transform: none;
  transition: none;
}
/* pin-left: content anchored to the left side of the viewport */
.scrolly-pin-left {
  justify-content: center;
  align-items: flex-start;
}
/* pin-right: content anchored to the right side of the viewport */
.scrolly-pin-right {
  justify-content: center;
  align-items: flex-start;
}

/* ── scrolly gradient backdrops ──────────────────
   Out-of-flow backdrop that fills the section via
   position:absolute + inset:0 (parent has position:relative).
   z-index: 1 sits behind steps but below .scrolly-pin-top (2).
   pointer-events: none so it never blocks interaction.
   Brand → transparent top-to-bottom.
═══════════════════════════════════════════════════ */
.scrolly-background, .scrolly-gradient-brand, .scrolly-gradient-light, .scrolly-gradient-dark {
  position: absolute;
  z-index: 1;
  inset: 0;
  pointer-events: none;
}

.scrolly-gradient-brand {
  background: linear-gradient(
    to bottom,
    var(--color-brand-primary) 10%,
    var(--color-brand-primary) 60%,
    transparent 100%
  );
}
.scrolly-gradient-dark {
  background: linear-gradient(
    to bottom,
    var(--color-neutral-900) 0%,
    var(--color-neutral-900) 30%,
    transparent 100%
  );
}
.scrolly-gradient-light {
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    var(--color-background-surface) 0%,
    var(--color-background-surface) 30%,
    transparent 100%
  );
}

/* ── step base state (hidden, default rise) ──── */
.scrolly-step {
  min-height: 100dvh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  scroll-snap-align: start;
  scroll-snap-stop: always;

  /* Clear the sticky pin-top: once stuck it sits at exactly `top: nav-height`
     (its position:sticky offset) — section-padding plays no part in that,
     it only mattered before the pin engaged, so it doesn't belong here.
     nav-height + the pin's real content height (--pin-content-height,
     measured by JS — see .section-scrolly) reaches the pin's stuck bottom
     edge; h2's own margin-bottom (space-24) is what supplies the visual
     rhythm to the first h3 from there. It collapses out of
     .scrolly-pin-top's box (no padding to stop it), so it has to be added
     back here explicitly rather than assumed to already be part of the
     pin's height. */
  padding-top: calc(var(--nav-height) + var(--pin-content-height) + var(--space-24));
  opacity: 0;
  transform: translateY(var(--scrolly-distance));
  transition:
    opacity   var(--scrolly-duration) var(--scrolly-easing),
    transform var(--scrolly-duration) var(--scrolly-easing);
}

/* ── last step scrolls past without snapping ── */
.scrolly-step:last-child { scroll-snap-align: none; }

/* ── animation subclasses override initial transform ── */
.scrolly-rise .scrolly-step {
  transform: translateY(var(--scrolly-distance));  /* explicit duplicate of default */
}
.scrolly-fade .scrolly-step {
  transform: none;
}
.scrolly-from-left .scrolly-step {
  transform: translateX(calc(-1 * var(--scrolly-distance)));
}
.scrolly-from-right .scrolly-step {
  transform: translateX(var(--scrolly-distance));
}
.scrolly-scale .scrolly-step {
  transform: scale(0.92);
}

/* ── step active state (revealed by JS) ─────────
   Must come AFTER all animation subclasses (same specificity 0,2,0 —
   source-order tie-break gives .is-active the win). */
.scrolly-step.is-active {
  opacity: 1;
  transform: none;
}

/* Dim any previously-active step when a later step activates.
   Creates a natural "reading position" — only the latest card
   renders at full saturation and opacity. */

/* ── stagger: auto-delay via nth-child ────────── */
.scrolly-stagger .scrolly-step:nth-child(1) { transition-delay: 0s; }
.scrolly-stagger .scrolly-step:nth-child(2) { transition-delay: 0.12s; }
.scrolly-stagger .scrolly-step:nth-child(3) { transition-delay: 0.24s; }
.scrolly-stagger .scrolly-step:nth-child(4) { transition-delay: 0.36s; }
.scrolly-stagger .scrolly-step:nth-child(5) { transition-delay: 0.48s; }
.scrolly-stagger .scrolly-step:nth-child(6) { transition-delay: 0.60s; }
.scrolly-stagger .scrolly-step:nth-child(7) { transition-delay: 0.72s; }
.scrolly-stagger .scrolly-step:nth-child(8) { transition-delay: 0.84s; }
.scrolly-stagger .scrolly-step:nth-child(9) { transition-delay: 0.96s; }

/* ── card-content stagger: children reveal sequentially ── */
.scrolly-stagger-content .scrolly-step-card > article > * {
  opacity: 0;
  transform: translateY(8px);
  transition:
    opacity   0.4s var(--transition-easing-smooth),
    transform 0.4s var(--transition-easing-smooth);
}

.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > * {
  opacity: 1;
  transform: none;
}

.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(1)  { transition-delay: 0s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(2)  { transition-delay: 0.06s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(3)  { transition-delay: 0.12s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(4)  { transition-delay: 0.18s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(5)  { transition-delay: 0.24s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(6)  { transition-delay: 0.30s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(7)  { transition-delay: 0.36s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(8)  { transition-delay: 0.42s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(9)  { transition-delay: 0.48s; }
.scrolly-stagger-content .scrolly-step.is-active .scrolly-step-card > article > :nth-child(10) { transition-delay: 0.54s; }

/* ── skip mode: show all steps instantly ──────── */
.scrolly-skipped .scrolly-step,
.scrolly-skipped .scrolly-step.is-active {
  opacity: 1;
  transform: none;
  transition: none;
}
.scrolly-skipped .scrolly-step-card > article > * {
  opacity: 1;
  transform: none;
  transition: none;
}

/* ── reduced motion: instant reveal ───────────── */
@media (prefers-reduced-motion: reduce) {
  /* generic reveal-on-scroll */
  .reveal,
  .reveal-slow,
  .revealed {
    opacity: 1;
    transform: none;
    animation: none;
    animation-delay: 0s;
  }

  /* work-row reveal */
  .work-row.reveal {
    opacity: 1;
    transform: none;
  }
  .work-row.revealed {
    animation: none;
  }
  .work-row.reveal .work-card,
  .work-row.revealed .work-card,
  .work-items > li:nth-child(even) .work-row.reveal .work-card,
  .work-items > li:nth-child(even) .work-row.revealed .work-card {
    opacity: 1;
    transform: none;
    animation: none;
  }
  .work-row.reveal .work-card-img-wrap,
  .work-row.revealed .work-card-img-wrap {
    opacity: 1;
    transform: none;
    animation: none;
  }

  /* gradient-text reveal */
  .gradient-text.revealed {
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* scrollytelling steps */
  .scrolly-step,
  .scrolly-step.is-active {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .scrolly-step-card > article > * {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ═══════════════════════════════════════════════════
   SCROLLY PIPS — bottom-centre dot navigation
   Sticks to the bottom of the scrolly section as
   the user scrolls through the steps.
═══════════════════════════════════════════════════ */

.scrolly-pips {
  position: sticky;
  bottom: var(--space-20);
  margin-bottom: var(--space-12);
  z-index: 10;
  display: flex;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--scrolly-pips-duration) var(--scrolly-pips-easing);
}

.scrolly-pips.is-visible {
  opacity: 1;
}

.scrolly-pips-inner {
  display: flex;
  gap: var(--space-12);
  padding: var(--space-8) var(--space-16);
  border-radius: var(--radius-pill);
  background: rgba(var(--color-neutral-900-rgb), .55);
  -webkit-backdrop-filter: blur(var(--blur-nav));
  backdrop-filter: blur(var(--blur-nav));
  pointer-events: auto;
}

.scrolly-pip {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--space-24);
  height: var(--space-24);
  border-radius: var(--radius-circle);
  border: none;
  background: transparent;
  padding: 0;
  cursor: pointer;
  position: relative;
}

/* Visual dot — pseudo-element keeps the 8px appearance
   while the button provides a 24px touch target. */
.scrolly-pip::after {
  content: '';
  display: block;
  width: var(--space-8);
  height: var(--space-8);
  border-radius: var(--radius-circle);
  border: var(--border-width-default) solid var(--color-fill-inverse-opacity-40);
  background: transparent;
  transition:
    background 0.25s var(--transition-easing-smooth),
    border-color 0.25s var(--transition-easing-smooth),
    transform 0.2s var(--transition-easing-spring);
}

.scrolly-pip:hover::after {
  border-color: var(--color-fill-inverse-opacity-80);
  transform: scale(1.35);
}

.scrolly-pip.is-active-pip::after {
  background: var(--color-brand-highlight-on-dark);
  border-color: var(--color-brand-highlight-on-dark);
  transform: scale(1.2);
}

.scrolly-pip.is-active-pip:hover::after {
  transform: scale(1.5);
}

/* ── reduced motion / skip: hide pips ────────── */
.scrolly-skipped .scrolly-pips {
  display: none;
}

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

/* ═══════════════════════════════════════════════════
   CAPABILITY RADIAL CHART — fixed donut showing
   proficiency levels across all 8 capabilities.
   Lives inside a .cap-radial grid cell; sticks on scroll.
═══════════════════════════════════════════════════ */

/* ── radial chart grid cell ──────────────────── */
.cap-radial {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  position: sticky;
  top: var(--nav-height);
  height: calc(100dvh - var(--nav-height));
  padding-top: var(--space-24);
  padding-bottom: var(--space-24);
  gap: var(--space-20);
  z-index: 1;
  opacity: 0;
  transition: opacity var(--scrolly-pips-duration) var(--scrolly-pips-easing);
}

/* Sync radial visibility with pips */
.section-scrolly:has(.scrolly-pips.is-visible) .cap-radial {
  opacity: 1;
}

.cap-radial-wrapper {
  position: relative;
  width: min(100%, 340px);
  flex-shrink: 0;
  aspect-ratio: 1;
  transition: transform 0.15s linear;

  border-radius: var(--radius-circle);
  /* WCAG-AA-CONTRAST-FIXES: at -10 this backdrop was still >90% the orange
     section background showing through, so several ring colors (especially
     the "advanced" orange ring) were nearly the same hue as their own
     backdrop (as low as 1.19:1). -60 keeps the glass-panel look but darkens
     it enough that every capability-level ring/label clears 3:1. */
  background: var(--color-fill-opacity-20);
  box-shadow: var(--elevation-2);
  -webkit-backdrop-filter: blur(var(--blur-nav));
  backdrop-filter: blur(var(--blur-nav));
}

.cap-radial-wrapper svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* background ring — all rings dimmed */
.cap-radial-bg-ring {
  stroke: var(--color-fill-opacity-10);
}

/* progress rings — colored by level, dim by default */
.cap-radial-fill-ring {
  opacity: 0.8;
  stroke-dashoffset: 0;
  transition:
    stroke-dashoffset 0.8s cubic-bezier(0.34, 1.2, 0.64, 1),
    opacity 0.3s ease,
    stroke 0.3s ease;
}

/* active ring — bright with glow + pulse */
.cap-radial-fill-ring.is-active-ring {
  opacity: 1;
  filter: drop-shadow(0 0 4px currentColor);
  animation: ring-pulse 0.6s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes ring-pulse {
  0%   { stroke-width: 4; }
  40%  { stroke-width: 6; }
  100% { stroke-width: 4; }
}

/* center circle */
.cap-radial-center {
  fill: var(--color-neutral-900);
}

/* center labels */
.cap-radial-label {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-label);
  fill: var(--color-fill-inverse-opacity-80);
  text-transform: uppercase;
}
.cap-radial-label--name {
  font-size: var(--font-size-body-md);
  letter-spacing: var(--tracking-normal-sm);
}
.cap-radial-label--level {
  font-size: var(--font-size-label-sm);
  letter-spacing: var(--tracking-normal-md);
  fill: var(--cap-level-color, var(--color-neutral-100));
}

/* ── capability badges — reuses cs-stats pattern ── */

.capability-badges .cs-stat {
  border-top: var(--border-width-default) solid var(--color-fill-inverse-opacity-20);
}

.capability-badges .cs-num { margin-bottom: var(--space-18); }


.section-brand .cs-stat:hover .cs-stat-content,
.section-brand .cs-stat:focus-visible .cs-stat-content {
  background: color-mix(in srgb, var(--color-background-surface-brand) 50%, transparent);
  border-top-color: var(--color-brand-highlight-on-dark);
}

.section-dark .cs-stat-detail p, .section-brand .cs-stat-detail p {
  color: var(--color-text-inverse-tertiary);
}


/* ═══════════════════════════════════════════════════
   STATS STRIP
═══════════════════════════════════════════════════ */
.cs-stats.columns {
 gap: 0;
}
.cs-stat {
  --stat-pad-x:      var(--space-32);
  --stat-pad-top:    var(--space-28);
  --stat-pad-bottom: var(--space-32);
  /* Reserves the card's closed-state footprint so the grid
     row never resizes when .cs-stat-content grows on hover
     to reveal the detail text — see .cs-stat-content below. */
  --stat-closed-height: calc(
    var(--border-width-emphasis) +
    var(--stat-pad-top) + var(--stat-pad-bottom) +
    (var(--font-size-heading-sm) * 1) + var(--space-4) +
    (var(--font-size-body-sm) * 1.2)
  );

  position: relative;
  min-height: var(--stat-closed-height);
  border-right: var(--border-width-default) solid var(--color-fill-opacity-10);
}
.cs-stat:first-child { border-left: none; }
.cs-stat:last-child { border-right: none; }
.cs-stat:hover, .cs-stat:focus-visible { border-right-color: transparent; z-index: var(--z-index-4); }
.cs-stat:has(+ .cs-stat:hover), .cs-stat:has(+ .cs-stat:focus-visible) { border-right-color: transparent; }

/* ── when a cs-stat is hovered or keyboard-focused, establish a
   stacking context on its section so the expansion paints above
   the next sibling (e.g. .section-scrolly, which has position:relative). ── */
section:has(.cs-stat:hover), section:has(.cs-stat:focus-visible) {
  position: relative;
  z-index: 1;
}

/* ── reveal-on-scroll, redirected: .cs-stat carries .reveal/.revealed
   (JS + the sibling-index() stagger delay below both target the <li>),
   but the fade/rise must not actually animate on .cs-stat itself — an
   animated ancestor gets layer-promoted and stays that way even once
   the animation finishes, which silently blocks .cs-stat-content's
   backdrop-filter from sampling the section background behind it (no
   more blur on hover). So: cancel the generic effect on .cs-stat and
   replay it on .cs-stat-content instead. sibling-index() only resolves
   .cs-stat's real position among its <li> siblings — .cs-stat-content
   has none — so its delay is captured in a custom property and passed
   down via inheritance. ── */
.cs-stat.reveal {
  opacity: 1;
  transform: none;
  --reveal-stagger-delay: calc((sibling-index() - 1) * 0.2s);
}
.cs-stat.revealed { animation: none; }
.cs-stat.reveal .cs-stat-content {
  opacity: 0;
  transform: translateY(var(--reveal-offset));
}
.cs-stat.revealed .cs-stat-content {
  animation: revealIn 0.75s ease-out forwards;
  animation-delay: var(--reveal-stagger-delay, 0s);
}

/* ── content: owns padding, the hover background, and the
   shadow. It's an absolutely-positioned overlay (pinned to
   the top of .cs-stat, height auto) so its own box — summary
   only when closed, summary + detail when open — never
   affects the li's box or the shared grid row. ── */
.cs-stat-content {
  position: absolute;
  inset: 0 0 auto 0;
  z-index: var(--z-index-1);
  padding: var(--stat-pad-top) var(--stat-pad-x) var(--stat-pad-bottom);
  border-top: var(--border-width-emphasis) solid transparent;
  -webkit-backdrop-filter: blur(var(--blur-nav));
  backdrop-filter: blur(var(--blur-nav));
  transition: background-color var(--transition-duration-default) ease, border-top-color var(--transition-duration-default) ease, box-shadow var(--transition-duration-default) ease;
}
.cs-stat:hover .cs-stat-content,
.cs-stat:focus-visible .cs-stat-content {
  background: color-mix(in srgb, var(--color-background-surface-hover) 10%, transparent);
  border-top-color: var(--color-brand-primary);
  box-shadow: var(--elevation-2);
}
.cs-stat:hover .cs-num,
.cs-stat:focus-visible .cs-num {
  color: var(--color-brand-highlight-tint);
  transition: color var(--transition-duration-default) ease 0s;
}
.cs-stat:hover .cs-label,
.cs-stat:focus-visible .cs-label {
  color: var(--color-text-primary);
  transition: color var(--transition-duration-default) ease 0.06s;
}

/* ── displace variant: in-flow hover expansion ──
   Switches .cs-stat-content from absolute overlay to
   relative in-flow so the detail text pushes sibling
   elements down instead of overlapping them.
   Shares the same CSS as the single-column override
   in the xs breakpoint below. */
.cs-stat--displace {
  min-height: unset;
}
.cs-stat--displace .cs-stat-content {
  position: relative;
  inset: auto;
}

.cs-num {
  font-family: var(--font-family-display);
  font-size: var(--font-size-heading-sm);
  font-weight: var(--font-weight-heading);
  letter-spacing: var(--tracking-tight-xs);
  color: var(--stats-number-color);
  line-height: var(--line-height-heading);
  margin: 0 0 var(--space-4) 0;
  display: block;
}
.cs-label {
  font-weight: var(--font-weight-button);
  letter-spacing: var(--tracking-loose-lg);
  color: var(--stats-label-color);
  margin: 0;
  line-height: var(--line-height-sm);
}
/* ── detail: a CSS-only accordion (grid-rows 0fr → 1fr)
   that expands inside .cs-stat-content's own flow — no
   absolute positioning, no negative-margin overlap hack,
   no guessed max-height. ── */
.cs-stat-detail {
  display: grid;
  grid-template-rows: 0fr;
  margin-top: 0;
}
.cs-stat-detail > p {
  overflow: hidden;
  min-height: 0;
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-lede);
  color: var(--color-text-muted);
  opacity: 0;
}
.cs-stat:hover .cs-stat-detail,
.cs-stat:focus-visible .cs-stat-detail {
  grid-template-rows: 1fr;
  margin-top: var(--space-12);
}
.cs-stat:hover .cs-stat-detail > p,
.cs-stat:focus-visible .cs-stat-detail > p {
  opacity: 1;
}
.section-light .cs-stat .cs-num {
  color: var(--color-brand-highlight);
}

.section-dark .cs-stat .cs-num {
  color: var(--color-brand-highlight-on-dark);
}
.section-dark .cs-stat:hover .cs-label,
.section-dark .cs-stat:focus-visible .cs-label {
  color: var(--color-fill-inverse-opacity-100);
}

/* WCAG-AA-CONTRAST-FIXES: these two rules referenced an undefined
   --color-brand-secondary-on-dark, which made the declaration invalid and
   silently fell back to the (also failing, 2.03:1) --stats-number-color
   cascade for .section-brand. brand-highlight-on-dark — the same token
   .section-dark already uses for this — clears 3:1 against the orange
   section background (3.4:1) for these large stat numbers. */
.section-brand .cs-stat .cs-num {
  color: var(--color-brand-highlight-on-dark);
}
.section-brand .cs-stat:hover .cs-num,
.section-brand .cs-stat:focus-visible .cs-num {
  color: var(--color-brand-highlight-on-dark);
}
.section-brand .cs-stat:hover .cs-label,
.section-brand .cs-stat:focus-visible .cs-label {
  color: var(--color-fill-inverse-opacity-100);
}




@media (prefers-reduced-motion: no-preference) {
  .cs-stat-detail {
    transition: grid-template-rows var(--transition-duration-slow) ease, margin-top var(--transition-duration-slow) ease;
  }
  .cs-stat-detail > p {
    transition: opacity var(--transition-duration-default) ease;
  }
}


.title-eyebrow {
  font-family: var(--font-family-display);
  font-size: var(--font-size-body-xl);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-normal-md);
  line-height: var(--line-height-xs);
  text-transform: uppercase;
  color: var(--eyebrow-color);
  margin-bottom: var(--space-12);
}
.title-eyebrow .highlight { color: var(--eyebrow-highlight-color); }

/* ── anchor scroll offset — compensate for fixed nav ── */
[id="practice"],
[id="contact"] {
  scroll-margin-top: calc(var(--nav-height) + var(--space-24));
}

/* ═══════════════════════════════════════════════════
   GENERIC SECTION THEMES
   Reusable surface classes — apply to any section.
   Sets background, text colour, and border-colour via
   local overrides so child components inherit the
   right contextual values automatically.
═══════════════════════════════════════════════════ */


.section-dark {
  background: var(--section-dark-background);
  color: var(--section-dark-text);
  --section-bg:                var(--section-dark-background);
  --section-text:              var(--section-dark-text);
  --section-text-muted:        var(--section-dark-text-muted);
  --section-title:             var(--section-dark-title);
  --section-border:            var(--section-dark-border);
  --eyebrow-color:             var(--section-dark-eyebrow-color);
  --icon-color:                var(--icon-color-dark);
}


.section-light {
  background: var(--section-light-background);
  color: var(--section-light-text);
  --section-bg:          var(--section-light-background);
  --section-text:        var(--section-light-text);
  --section-text-muted:  var(--section-light-text-muted);
  --section-title:       var(--section-light-title);
  --section-border:      var(--section-light-border);
  --icon-color:          var(--icon-color);
  --stats-number-color:  var(--color-brand-primary);
}

.section-brand {
  background: var(--gradient-brand);
  background-attachment: fixed;
  color: var(--section-brand-text);
  --section-bg:          var(--section-brand-background);
  --section-text:        var(--section-brand-text);
  --section-text-muted:  var(--section-brand-text-muted);
  --section-title:       var(--section-brand-title);
  --section-border:      var(--section-brand-border);
  --heading-color:             color-mix(in srgb, var(--color-gold-500) 30%, white);
  --heading-highlight-color:   var(--heading-highlight-color-brand);
  --eyebrow-color:             var(--color-text-inverse-secondary);
  --eyebrow-highlight-color:   var(--color-brand-highlight-tint);
  /* WCAG-AA-CONTRAST-FIXES: brand-primary-on-dark only reaches 2.44:1 against
     the orange section background — matches the .cs-stat .cs-num fix above. */
  --stats-number-color:        var(--color-brand-highlight-on-dark);
  --stats-label-color:         var(--color-text-inverse-secondary);
  --icon-color:                var(--icon-color-brand);
}

.section-hero {
  background: var(--hero-background);
  background-attachment: fixed;
  height: 100dvh;
  padding-top: var(--nav-height);
  display: flex;
  flex-direction: column;
  position: relative;
  
  color: var(--section-brand-text);
  --section-bg:          var(--section-brand-background);
  --section-text:        var(--section-brand-text);
  --section-text-muted:  var(--section-brand-text-muted);
  --section-title:       var(--section-brand-title);
  --section-border:      var(--section-brand-border);
  --heading-color:             color-mix(in srgb, var(--color-gold-500) 30%, white);
  --heading-highlight-color:   var(--heading-highlight-color-brand);
  --eyebrow-color:             var(--color-text-inverse-secondary);
  --eyebrow-highlight-color:   var(--color-brand-highlight-tint);
  --stats-number-color:        var(--color-brand-highlight-tint);
  --stats-label-color:         var(--color-text-inverse-secondary);
  --icon-color:                var(--icon-color-brand);
}

.section-grey {
  background: var(--section-grey-background);
}

.section-title {
  display: flex;
  align-items: center;
  font-size: var(--font-size-heading-sm);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-normal-md);
  min-height: var(--section-title-min-height);
}

/* ═══════════════════════════════════════════════════
   WORK
═══════════════════════════════════════════════════ */
.work-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--space-16);
}
.label-link {
  transition: gap var(--transition-duration-default), color var(--transition-duration-fast);
}
.label-link::after {
  content: "\2192";
  position: relative;
  top: -0.06em;
  margin-left: 0.15em;
}
.label-link:hover, a:hover .label-link { color: var(--color-text-link-hover); }

.section-dark .label-link:hover,
.section-dark a:hover .label-link,
.section-brand .label-link:hover,
.section-brand a:hover .label-link {
  color: var(--color-brand-highlight-on-dark);
}

.work-items {
  list-style: none;
}
.work-row {
  display: grid;
  overflow: hidden;
  cursor: pointer;
  transition: background var(--transition-duration-fast), box-shadow var(--transition-duration-default) ease;
  text-decoration: none;
  color: inherit;
}
.work-row:hover {
  background: var(--work-card-hover-bg);
  box-shadow: var(--elevation-2);
}
.work-card {
  padding: var(--space-36) var(--space-40);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  transition: box-shadow var(--transition-duration-medium) ease, transform var(--transition-duration-medium) ease;
}
.work-card-body { margin-bottom: var(--space-24);}
.work-card-eyebrow {
  font-family: var(--font-family-body);
  font-size: var(--font-size-label-sm);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-xs);
  text-transform: uppercase;
  color: var(--color-text-muted);
  margin-bottom: var(--space-8);
}
.work-card-challenge {
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  font-style: italic;
  color: var(--color-text-muted);
  margin-bottom: var(--space-8);
  line-height: var(--line-height-md);
}
.work-card-title {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-tight-sm);
  line-height: var(--line-height-xs);
  color: var(--work-card-title-color);
  margin-bottom: var(--space-10);
}
.work-card-client {
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  color: var(--section-light-text);
  font-style: italic;
}
.work-card-bottom {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
.work-card-bottom .button-row-separator {
  align-items: flex-start;
}
.button-row-separator > li, .button-row-links > li {
  display: contents; /* eliminating the extra box layer that was causing the pixel offset. */
}
.work-card-stat-n {
  font-family: var(--font-family-display);
  font-size: var(--font-size-heading-sm);
  font-weight: var(--font-weight-heading);
  letter-spacing: var(--tracking-tight-xs);
  color: var(--work-card-stat-color);
  line-height: var(--line-height-heading);
}
.work-card-stat-t {
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-body);
  color: var(--work-card-stat-color);
  letter-spacing: var(--tracking-normal-xl);
  margin-top: var(--space-2);
}
.work-row:hover .work-card-link { color: var(--work-card-link-hover-color); gap: var(--space-10); }
.work-row:hover work-card { box-shadow: var(--elevation-2); transform: translateY(var(--elevation-translate-2)); }
.work-card-img-wrap {
  overflow: hidden;
  position: relative;
  min-height: var(--space-260);
}
.work-card-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--transition-duration-xl) ease;
  filter: saturate(.9);
}
.work-row:hover .work-card-img { transform: scale(var(--image-scale-hover)); }
.work-row.columns { gap: 0; }

/* ── alternate row layout ──────────────────────
   On 2-column rows, flip card ↔ image every other
   item so the visual rhythm alternates. */
@media (min-width: 1024px) {
  .work-items > li:nth-child(even) .work-card {
    order: 2;
  }
  .work-items > li:nth-child(even) .work-card-img-wrap {
    order: 1;
  }
}

/* ── section-brand work card overrides ──────────
   Work cards on a brand (orange) background need a
   light, self-contained surface and dark text so they
   remain legible against the saturated backdrop.
   All values use existing design tokens only. */
.section-brand .work-card {
  background: var(--color-background-surface);
}
.section-brand .work-card-img-wrap {
  background: var(--color-background-surface);
}
.section-brand .work-row:hover {
  background: var(--color-background-surface-hover);
}

/* ── text legibility ── */
.section-brand .work-card-title {
  color: var(--color-text-primary);
}
.section-brand .work-card-client {
  color: var(--color-text-secondary);
}
.section-brand .work-card .label {
  color: var(--color-text-muted);
}
.section-brand .work-card .label-link {
  color: var(--color-text-link);
}
.section-brand .work-card .label-link:hover,
.section-brand .work-row:hover .label-link {
  color: var(--work-card-link-hover-color);
}
.section-brand .work-card dd {
  color: var(--color-text-secondary);
}
.section-brand .work-card .pill-lt {
  /* WCAG-AA-CONTRAST-FIXES: matches the --pill-highlight-bg fix above. */
  background: var(--color-brand-primary);
}
.section-brand .button-row-separator > li:not(:last-child)::after {
  color: var(--color-text-muted);
}

/* ═══════════════════════════════════════════════════
   IMPACT CARD — Challenge / Decision / Outcome
   Reusable 3-col pattern for work rows and case studies.
═══════════════════════════════════════════════════ */

.title-bar dt { margin-bottom: var(--space-12);}
.title-bar dd {
  margin: 0;
  font-size: var(--font-size-body);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-body);
  color: var(--section-text, var(--color-text-secondary));
}

/* ═══════════════════════════════════════════════════
   PRACTICE
═══════════════════════════════════════════════════ */


/* ═══════════════════════════════════════════════════
   ABOUT
═══════════════════════════════════════════════════ */

.about-img {
  width: clamp(8rem, 15vw, 15rem);
  aspect-ratio: 1;
  object-fit: cover;
  object-position: center top;
  filter: saturate(.85);
  position: relative;
  z-index: var(--z-index-1);
  border-radius: var(--radius-pill);
}

/* ── pull-quote ──────────────────────────────── */
.pull-quote {
  font-family: var(--font-family-display);
  font-size: var(--font-size-body-lg);
  font-weight: var(--font-weight-body-strong);
  line-height: var(--line-height-lede);
  color: var(--color-text-primary);
  border-left: var(--border-width-emphasis) solid var(--color-brand-primary);
  padding-left: var(--space-16);
  margin: var(--space-8) 0 var(--space-24);
}

/* ═══════════════════════════════════════════════════
   CLIENTS
═══════════════════════════════════════════════════ */

.list-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: var(--space-32) var(--space-48);
  list-style: none;
  margin: 0 0;
  align-items: start;
}
.list-grid ul {
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}
.list-grid-heading {
  opacity: 0.70;
  margin-top: 0;
  margin-bottom: 0;
}
.list-links {
  border-top: var(--border-width-default) solid var(--section-dark-border);
  list-style: none;
}
.list-link {
  display: flex;
  align-items: center;
  gap: var(--space-16);
  padding: var(--space-18) 0;
  border-bottom: var(--border-width-default) solid var(--section-dark-border);
  transition: padding-left var(--transition-duration-default);
}
a.list-link:hover { padding-left: var(--space-8); }

.list-link-val {
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  color: var(--section-dark-text);
  transition: color var(--transition-duration-fast);
}
a.list-link:hover .list-link-val { color: var(--color-fill-inverse-opacity-80); }

/* ═══════════════════════════════════════════════════
   CONTACT
═══════════════════════════════════════════════════ */
.contact-right { padding-top: var(--space-80); }

.contact-eyebrow {
  font-family: var(--font-family-display);
  font-size: var(--font-size-label-sm);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-xxl);
  text-transform: uppercase;
  color: var(--section-text-muted, var(--color-text-muted));
  margin-bottom: var(--space-12);
}

.list-button {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
  list-style: none;
}
.list-button .btn { width: 100%; }
.about-left .columns { gap: 0; }
.avail-row {
  display: flex;
  align-items: center;
  gap: var(--space-7);
  margin-top: var(--space-16);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-xxl);
  color: var(--section-dark-text-muted);
}

/* ═══════════════════════════════════════════════════
   PAGES
═══════════════════════════════════════════════════ */


.section-title .title-eyebrow {
  margin-bottom: var(--space-24);
}

.section-title a.title-eyebrow:hover,
.section-title a.title-eyebrow:hover .link-arrow,
.section-title a.title-eyebrow:hover .highlight {
  color: var(--color-neutral-100);
}

.section-title .title-eyebrow .link-arrow {
  color: var(--color-text-inverse-primary);
  margin-left: -0.15em;
}

.section-title .columns:not(.title-bar) > :first-child {
  border-right: var(--border-width-emphasis) solid var(--color-fill-inverse-opacity-40); padding-right: var(--space-20); 
}

.section-title .wrap {
  margin-top: var(--nav-height);
  width: 100%;
}

.section-title .lede {
  font-size: var(--font-size-body-xl);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-lede);
  color: var(--section-text-muted, var(--color-text-muted));
  margin-bottom: var(--space-20);
}

/* On breakpoints where the heading and lede stack (see xs/sm overrides
   below), a right-hand divider has nothing to divide and reads as a
   stray line. Swap it for a bottom rule that sits under the heading
   instead, and reclaim the horizontal padding as vertical spacing. */
@media (max-width: 767px) {
  .section-title .columns:not(.title-bar) > :first-child {
    border-right: none;
    padding-right: 0;
    padding-bottom: 0;
    border-bottom: var(--border-width-emphasis) solid var(--color-brand-primary);
    margin-bottom: 0;
  }
  .section-title .title-eyebrow { margin-bottom: var(--space-12); }
  .section-title .lede { margin-bottom: var(--space-12); }
  .section-title .title-bar { margin-top: 0; }
}

/* ═══════════════════════════════════════════════════
   ARTICLE 
   Component layer for long-form content pages (case
   study write-ups, articles). Built entirely on the
   Tier 1/2/3 tokens above — no new colors or sizes are
   introduced here that don't already exist as a token —
   and on the section/wrap/columns primitives already
   used by the rest of the site, so it inherits section
   theming (dark/light/brand) automatically.
═══════════════════════════════════════════════════ */

/* ── prose column ─────────────────────────────── */
.article-body {
  max-width: var(--article-max-width);
  margin: 0 auto;
}

/* wide variant for sections that hold multi-column  */
.article-body--wide { 
  max-width: var(--article-max-width-wide); 
  margin: 0 auto;
}

.article-body > *:first-child { margin-top: 0; }

.article-body h1:first-child,
.article-body h2:first-child,
.article-body h3:first-child,
.article-body h4:first-child,
.article-body h5:first-child,
.article-body h6:first-child { margin-top: 0; }

.article-body p {
  color: var(--section-text, var(--color-text-primary));
  margin-bottom: var(--space-16);
}

.article-body .lede {
  text-align: center;
  margin-bottom: var(--space-24);
}

.article-body ul:not([class]),
.article-body ol:not([class]) {
  margin-bottom: var(--space-20);
  padding-left: var(--space-24);
}

.article-body li {
  margin-bottom: var(--space-8);
  line-height: var(--line-height-lg);
}

/* ── numbered fact list — replaces icon "pillars" ── */
.list-numbered {
  list-style: none;
  display: grid;
  gap: var(--space-20);
  counter-reset: fact;
}
.list-numbered li {
  position: relative;
  padding-left: var(--space-40);
  font-family: var(--font-family-display);
  font-size: var(--font-size-body-lg);
  font-weight: var(--font-weight-body-strong);
  line-height: var(--line-height-130);
  color: var(--section-text, var(--color-text-secondary));
}
.list-numbered li::before {
  counter-increment: fact;
  content: counter(fact, decimal-leading-zero);
  position: absolute;
  top: 0;
  left: 0;
  font-weight: var(--font-weight-heading);
  color: var(--list-numbered-marker-color);
}
.section-light .list-numbered li::before { color: var(--list-numbered-marker-color-light); }

/* ── note cards — replaces red/green "sticky notes" ── */
.list-grid--note {
  display: grid;
  gap: var(--space-16);
}

.note-card {
  flex: 1;
  background: var(--note-card-bg);
  border-left: var(--note-card-border-width) solid var(--color-signal-negative);
  padding: var(--space-16) var(--space-20);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-lg);
  color: var(--color-text-primary);
  text-align: left;
}
.note-card--positive { border-left-color: var(--color-signal-positive); }
.section-dark .note-card {
  background: var(--note-card-bg-dark);
  color: var(--section-dark-text);
}

.list-note-card li, .list-note-card>div {
  background: var(--note-card-bg);
  border-left: var(--note-card-border-width) solid var(--color-signal-negative);
  padding: var(--space-16) var(--space-20);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-lg);
  color: var(--color-text-primary);
  text-align: left;
}
.list-note-card--positive li { border-left-color: var(--color-signal-positive); }
.section-dark .list-note-card li {
  background: var(--note-card-bg-dark);
  color: var(--section-dark-text);
}

/* ── figure / caption ──────────────────────────── */
.article-figure { margin: var(--space-32) 0; }
.article-figure img {
  width: 100%;
  height: auto;
  border-radius: var(--article-figure-radius);
  box-shadow: var(--elevation-1);
  /* match the saturation treatment used on work-card images */
  filter: saturate(.9);
}
.article-figure figcaption {
  margin-top: var(--space-12);
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-body);
  color: var(--article-figure-caption-color);
  text-align: center;
}

/* ── figure size variants ──────────────────────────
   Detail-dense artefacts (board exports, journey maps,
   flow diagrams) are unreadable when squeezed into the
   text column.

   Case study figures sit in `.col-span-3` of a `.col-4`
   grid — the left column holds only the section heading
   and is empty alongside the figure. These variants
   reclaim that empty gutter rather than overflowing the
   page, so nothing about the grid or page rhythm changes.

   Given a 4-col grid of equal tracks and gap G, the
   parent (3 tracks + 2 gaps) has width P, and one
   track + one gap resolves to exactly (P + G) / 3.
   At the 72rem article width that is 294px, taking the
   figure to 1152px — the full grid, never wider.
─────────────────────────────────────────────────── */
.article-figure--inset { max-width: var(--article-figure-width-inset); }

@media (min-width: 768px) {
  .article-figure--wide {
    margin-left: calc(-1 * (100% + var(--space-24)) / 3);
    width: auto;
    max-width: var(--article-figure-width-wide);
  }
}

/* ── board treatment ───────────────────────────────
   Board/canvas exports read as documents, not as
   full-bleed imagery. Sit them on a neutral surface
   with padding so the edges of the artefact are legible.

   Note: the lightbox wraps <img> in a .article-figure-zoom
   button, so this must match at either nesting depth.
─────────────────────────────────────────────────── */
.article-figure--board img {
  box-sizing: border-box;
  background: var(--article-figure-board-bg);
  border: var(--border-width-default) solid var(--article-figure-board-border);
  padding: var(--article-figure-board-padding);
  box-shadow: none;
}

/* ── caption notes ─────────────────────────────────
   Redaction / NDA / context notes belong in the caption,
   not baked into the bitmap.
─────────────────────────────────────────────────── */
.article-figure-note {
  display: block;
  margin-top: var(--space-6);
  font-size: var(--font-size-caption);
  color: var(--article-figure-caption-color);
  opacity: .8;
  font-style: italic;
}

/* ── zoom affordance ───────────────────────────────
   Applied only when JS has enhanced the figure.
─────────────────────────────────────────────────── */
.article-figure[data-zoomable] .article-figure-zoom {
  display: block;
  position: relative;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: var(--article-figure-radius);
}
.article-figure[data-zoomable] .article-figure-zoom::after {
  content: attr(data-zoom-label);
  position: absolute;
  right: var(--space-12);
  bottom: var(--space-12);
  padding: var(--space-6) var(--space-10);
  font-size: var(--font-size-caption);
  line-height: 1;
  color: var(--color-neutral-100);
  background: rgba(var(--color-neutral-900-rgb), .72);
  border-radius: var(--article-figure-radius);
  opacity: 0;
  pointer-events: none;
}
.article-figure[data-zoomable] .article-figure-zoom:hover::after,
.article-figure[data-zoomable] .article-figure-zoom:focus-visible::after { opacity: 1; }
.article-figure[data-zoomable] .article-figure-zoom:focus-visible {
  outline: var(--border-width-emphasis) solid var(--color-brand-highlight);
  outline-offset: var(--space-4);
}

/* ── figure lightbox ───────────────────────────────
   Full-resolution view for detail-dense artefacts.
─────────────────────────────────────────────────── */
.figure-lightbox {
  position: fixed;
  inset: 0;
  z-index: calc(var(--nav-z-index) + 2);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-24);
  background: rgba(var(--color-neutral-900-rgb), .92);
  opacity: 0;
  visibility: hidden;
}
.figure-lightbox[data-open="true"] { opacity: 1; visibility: visible; }
.figure-lightbox-stage {
  max-width: 100%;
  max-height: 100%;
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}
.figure-lightbox-stage img {
  display: block;
  max-width: none;      /* allow 1:1 inspection */
  width: auto;
  height: auto;
  border-radius: var(--article-figure-radius);
  background: var(--color-neutral-100);
}
.figure-lightbox-caption {
  position: absolute;
  left: var(--space-24);
  right: var(--space-24);
  bottom: var(--space-16);
  text-align: center;
  font-size: var(--font-size-caption);
  color: rgba(var(--color-neutral-100-rgb), .82);
  pointer-events: none;
}
.figure-lightbox-close {
  position: absolute;
  top: var(--space-16);
  right: var(--space-16);
  width: var(--space-40);
  height: var(--space-40);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--font-size-body);
  line-height: 1;
  color: var(--color-neutral-100);
  background: rgba(var(--color-neutral-100-rgb), .12);
  border: 0;
  border-radius: var(--article-figure-radius);
  cursor: pointer;
}
.figure-lightbox-close:hover { background: rgba(var(--color-neutral-100-rgb), .22); }
.figure-lightbox-close:focus-visible {
  outline: var(--border-width-emphasis) solid var(--color-brand-highlight);
  outline-offset: var(--space-2);
}
body[data-lightbox-open="true"] { overflow: hidden; }

@media (prefers-reduced-motion: no-preference) {
  .article-figure[data-zoomable] .article-figure-zoom::after {
    transition: opacity var(--transition-duration-medium) ease;
  }
  .figure-lightbox {
    transition: opacity var(--transition-duration-medium) ease,
                visibility var(--transition-duration-medium) ease;
  }
}

@media (max-width: 767px) {
  /* grid collapses to a single column — no gutter to reclaim,
     so variants sit flush and never overflow the viewport */
  .article-figure--wide,
  .article-figure--inset { max-width: 100%; margin-left: 0; }
  .article-figure--board img { padding: var(--space-10); }
}

/* ── prev/next post pagination ─────────────────── */
.link-arrow {
  display: inline;
  position: relative;
  top: -0.06em;
  white-space: nowrap;
}
.post-pagination {
  position: static;
  display: flex;
  justify-content: space-between;
  gap: var(--space-24);
  border-top: var(--border-width-default) solid var(--pagination-border-color);
  padding-top: var(--space-32);
  margin-top: var(--space-48);
}
.post-pagination-link {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  max-width: var(--pagination-link-max-width);
  transition: opacity var(--transition-duration-fast);
}
.post-pagination-link:hover { opacity: .7; }
.post-pagination-link--next { text-align: right; margin-left: auto; align-items: flex-end; }
.post-pagination-label {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  font-family: var(--font-family-display);
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-lg);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

.post-pagination-title {
  font-family: var(--font-family-display);
  font-size: var(--font-size-body-lg);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-normal-xs);
  line-height: var(--line-height-125);
  color: var(--color-text-primary);
}

/* ── author card + related posts (article footer) ── */
.article-footer-grid { align-items: start; }
.author-card { display: flex; gap: var(--space-16); align-items: start; }
.author-card-img {
  width: var(--space-64);
  height: var(--space-64);
  object-fit: cover;
  border-radius: var(--radius-circle);
  flex-shrink: 0;
}
.author-card-body p { margin-bottom: var(--space-8); }
.author-card-body p:last-child { margin-bottom: 0; }

@media (max-width: 767px) {
  .post-pagination { flex-direction: column; }
  .post-pagination-link--next { text-align: left; align-items: flex-start; margin-left: 0; }
  .post-pagination-link--next .post-pagination-label { flex-direction: row; }
}


/* ═══════════════════════════════════════════════════
   FOOTER
═══════════════════════════════════════════════════ */
.footer {
  background: var(--section-footer-background);
  border-top: var(--border-width-default) solid var(--section-footer-border);
  padding: var(--space-24) 0;
}
.footer .wrap { display: flex; align-items: center; justify-content: space-between; }
.footer .nav-logo {
  font-size: var(--font-size-body);
}
.footer-copy { font-size: var(--font-size-label-sm); font-weight: var(--font-weight-body); color: var(--section-brand-text-muted); }
.footer-links { list-style: none; display: flex; gap: var(--space-20); justify-content: flex-end; }
.footer-links a {
  font-family: var(--font-family-display);
  font-size: var(--font-size-label-sm);
  font-weight: var(--font-weight-label);
  letter-spacing: var(--tracking-loose-xl);
  text-transform: uppercase;
  color: var(--section-brand-text-muted);
  transition: color .15s;
}
.footer-links a:hover { color: var(--section-brand-text); }
.footer-links a .link-arrow {
  display: inline-block;
  transition: transform var(--transition-duration-long) var(--transition-easing-spring);
}
.footer-links a:hover .link-arrow {
  transform: translateX(var(--space-4));
}

/* ═══════════════════════════════════════════════════
   RESPONSIVE
   Breakpoints match the columns grid system:
   xs < 480  |  sm: 480–767  |  md: 768–1023  |  lg ≥ 1024
═══════════════════════════════════════════════════ */

@media (min-width: 1024px) {
  :root {
    --hero-video-x-offset: -10vw;
    --hero-video-y-offset: 0;
    --hero-video-bound-inset-y: 0;
    --hero-video-bound-inset-x: 0;
  }

  .cap-radial-wrapper {
    width: min(130%, 480px);
  }
}
@media (min-width: 1280px) {
  .cap-radial-wrapper {
    width: min(120%, 540px);
  }
}
@media (min-width: 768px) and (max-width: 1023px) {
  :root {
    --hero-video-x-offset: -20vw;
    --hero-video-y-offset: 0;
    --hero-video-bound-inset-y: 0;
    --hero-video-bound-inset-x: 0;
    --section-padding: var(--space-24);
  }
  .hero-body { grid-template-columns: 1fr; }
  .hero-video { min-height: 100dvh; max-height: 100dvh; }

  .work-row { margin-bottom: var(--space-40); }
  .work-row:last-child { margin-bottom: 0; border-bottom: none; }
  .work-card { order: 2; margin-bottom: var(--space-12); }
  .work-card-img-wrap { order: 1; }
  .work-card-link { margin-bottom: var(--space-12); }
  .about-img { max-width: var(--space-220); }
  .contact-right { padding-top: 0; }
  .practice-hd { grid-template-columns: 1fr; gap: var(--space-24); }

  /* 50vh of empty space reads as intentional editorial breathing room on
     a wide desktop viewport, but on tablet it just pushes the content
     down without adding anything. Ease it back and give the heading a
     bit more of the row so it doesn't wrap awkwardly. */
  .section-title { min-height: var(--section-title-min-height-md); }

  .cap-radial-wrapper {
    width: min(100%, 480px);
  }
  }
@media (min-width: 480px) and (max-width: 767px) {
  :root {
    --hero-video-x-offset: -20vw;
    --hero-video-y-offset: 0vh;
    --hero-video-bound-inset-y: 0vh;
    --hero-video-bound-inset-x: 0vw;
    --section-padding: var(--space-12);
  }

  .nav-actions { display: none; }
  .nav-toggle { display: flex; }

  .hero-body { grid-template-columns: 1fr; }
  .hero-video { min-height: 100dvh; max-height: 100dvh; }
  
  .cs-stats.columns { grid-template-columns: 1fr 1fr; }
  .cs-stat:first-child { border-left: none; }
  .cs-stat:nth-child(2n) { border-right: none; }
  .cs-stat:nth-child(n+3) { border-top: var(--border-width-default) solid var(--color-fill-opacity-10); }
  
  .work-card { padding: var(--space-20) var(--space-24); }
  .work-row { margin-bottom: var(--space-32); }
  .work-row:last-child { margin-bottom: 0; border-bottom: none; }
  .work-card { order: 2; margin-bottom: var(--space-12); }
  .work-card-img-wrap { order: 1; }
  .work-card-link { margin-bottom: var(--space-12); }
  .work-card-title { margin-top: 0; }
 
  .list-grid li:not(:last-child)::after { margin: 0 var(--space-16); }
  .footer .wrap { gap: var(--space-20); }
  h4, .title-eyebrow { margin-bottom: var(--space-12); }

  /* Let the section size to its content instead of forcing 50vh of
     mostly-empty space above/below the heading. */
  .section-title { min-height: var(--section-title-min-height-sm); }
  .section-title .columns { gap: var(--space-12); }

  /* Capabilities chart: steps run full-width in natural order;
     the radial chart un-docks from the grid and floats as a
     small pinned badge so it no longer eats a full screen of
     height above the content. */
  #practice .columns.col-2 { grid-template-columns: 1fr; }
  .scrolly-step { min-height: auto; }

  .cap-radial {
    position: fixed;
    top: calc(var(--nav-height) + var(--space-6));
    right: var(--space-16);
    width: 40vw;
    height: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
    pointer-events: none;
   
  }
  #practice .cap-radial-wrapper {
    border-radius: var(--radius-circle);
    background: var(--color-fill-opacity-10);
    box-shadow: var(--elevation-3);
    -webkit-backdrop-filter: blur(var(--blur-nav));
    backdrop-filter: blur(var(--blur-nav));
  }
  #practice .cap-radial-label--name { font-size: 16px; letter-spacing: var(--tracking-normal-sm); }
  #practice .cap-radial-label--level { font-size: 18px; letter-spacing: var(--tracking-normal-sm); transform: translateY(4px); }
  
  }
@media (max-width: 479px) {
  :root {
    --hero-video-x-offset: -20vw;
    --hero-video-y-offset: 0vh;
    --hero-video-bound-inset-y: 10svh;
    --hero-video-bound-inset-x: 18vw;
    --section-padding: var(--space-12);
  }

  .nav-actions { display: none; }
  .nav-toggle { display: flex; }

  .hero-body { grid-template-columns: 1fr; }
  .hero-video { min-height: 100dvh; max-height: 100dvh; }

  .cs-stats.columns { grid-template-columns: 1fr; }
  .cs-stat {
    --stat-pad-x: var(--space-12);
    --stat-pad-top: var(--space-12);
    --stat-pad-bottom: var(--space-12);
    min-height: unset;
    border-right: none;
    border-bottom: var(--border-width-default) solid var(--color-fill-opacity-10);
  }
  .cs-stat:last-child { border-bottom: none; }
  /* Single column: switch from absolute overlay to in-flow so hover
     displaces the content below instead of overlapping it.
     Shares the same rules as the opt-in .cs-stat--displace modifier. */
  .cs-stat--displace .cs-stat-content,
  .cs-stat-content {
    position: relative;
    inset: auto;
  }
  .work-card { padding: var(--space-12); }
  .work-row { margin-bottom: var(--space-24); }
  .work-row:last-child { margin-bottom: 0; border-bottom: none; }
  .work-card { order: 2; margin-bottom: var(--space-12); }
  .work-card-img-wrap { order: 1; }
  .work-card-link { margin-bottom: var(--space-12); }
  .work-card-title { margin-top: 0; }
  
  .list-grid { row-gap: var(--space-12); }
  .list-grid li:not(:last-child)::after { margin: 0 var(--space-12); }
  .contact-row { padding: var(--space-12) 0; }
  .footer { padding: var(--space-12) 0; }
  .footer .wrap { gap: var(--space-12); }
  h4, .title-eyebrow { margin-bottom: var(--space-12); }

  /* Same fix as sm: don't force half the viewport of empty space on the
     smallest screens, where it's most costly. */
  .section-title { min-height: var(--section-title-min-height-sm); }
  .section-title .columns { gap: var(--space-12); }

  /* Capabilities chart: steps run full-width in natural order;
     the radial chart un-docks from the grid and floats as a
     small pinned badge, sized down further for narrow screens. */
  #practice .columns.col-2 { grid-template-columns: 1fr; }
  #practice .scrolly-pin-top { top: calc(var(--nav-height)); }
  .scrolly-step { min-height: auto; }

  .cap-radial {
    position: fixed;
    top: calc(var(--nav-height) - 12px);
    right: var(--space-8);
    width: 160px;
    height: auto;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 5;
    pointer-events: none;
  }
  #practice .cap-radial-wrapper {
    border-radius: var(--radius-circle);
    background: var(--color-fill-opacity-10);
    box-shadow: var(--elevation-3);
    -webkit-backdrop-filter: blur(var(--blur-nav));
    backdrop-filter: blur(var(--blur-nav));
  }
  #practice .cap-radial-center { r: 50px; }
  #practice .cap-radial-label--name { font-size: 20px; letter-spacing: var(--tracking-normal-sm); }
  #practice .cap-radial-label--level { font-size: 22px; letter-spacing: var(--tracking-normal-sm); transform: translateY(8px); }
}


/* ── responsive grid columns ───────────────────── */
.columns, .columns-flex, .columns-tight, .columns-fill {
  display: grid;
  gap: var(--space-24);
  list-style: none;
  padding-left: 0;
}

.columns-flex {
    display: flex;
    flex-wrap: wrap;
}

.columns-tight {
  margin-top: 0;
  margin-bottom: var(--space-24);
}

.columns-fill {
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
}

.columns-gap-0  { gap: 0; }
.columns-gap-xs { gap: var(--space-6); }
.columns-gap-sm { gap: var(--space-12); }
.columns-gap-md { gap: var(--space-24); }
.columns-gap-lg { gap: var(--space-36); }
.columns-gap-xl { gap: var(--space-48); }

.columns.columns-align-start    { align-items: start; }
.columns.columns-align-center   { align-items: center; }
.columns.columns-align-end      { align-items: end; }
.columns.columns-align-stretch  { align-items: stretch; }
.columns.columns-align-baseline { align-items: baseline; }

/* Modifier: columns size to content — honours col-max-* on children.
   auto tracks shrink to the item's intrinsic width (bounded by max-width);
   justify-content:start stops leftover space stretching the tracks. */
.columns-intrinsic                  { justify-content: start; }
.columns-intrinsic.col-1            { grid-template-columns: auto; }
.columns-intrinsic.col-2            { grid-template-columns: auto auto; }
.columns-intrinsic.col-3            { grid-template-columns: auto auto auto; }
.columns-intrinsic.col-4            { grid-template-columns: auto auto auto auto; }
.columns-intrinsic.col-5            { grid-template-columns: auto auto auto auto auto; }
.columns-intrinsic.col-6            { grid-template-columns: auto auto auto auto auto auto; }

/* default (xs): 1–6 columns */
.col-1 { grid-template-columns: 1fr; }
.col-2 { grid-template-columns: repeat(2, 1fr); }
.col-3 { grid-template-columns: repeat(3, 1fr); }
.col-4 { grid-template-columns: repeat(4, 1fr); }
.col-5 { grid-template-columns: repeat(5, 1fr); }
.col-6 { grid-template-columns: repeat(6, 1fr); }

/* xs < 480px */
@media (max-width: 479px) {
  .col-1-xs { grid-template-columns: 1fr; }
  .col-2-xs { grid-template-columns: repeat(2, 1fr); }
  .col-3-xs { grid-template-columns: repeat(3, 1fr); }
  .col-4-xs { grid-template-columns: repeat(4, 1fr); }
  .col-5-xs { grid-template-columns: repeat(5, 1fr); }
  .col-6-xs { grid-template-columns: repeat(6, 1fr); }
  .columns-intrinsic.col-1-xs { grid-template-columns: auto; }
  .columns-intrinsic.col-2-xs { grid-template-columns: auto auto; }
  .columns-intrinsic.col-3-xs { grid-template-columns: auto auto auto; }
  .columns-intrinsic.col-4-xs { grid-template-columns: auto auto auto auto; }
  .columns-intrinsic.col-5-xs { grid-template-columns: auto auto auto auto auto; }
  .columns-intrinsic.col-6-xs { grid-template-columns: auto auto auto auto auto auto; }
}

/* sm: 480–767px */
@media (min-width: 480px) and (max-width: 767px) {
  .col-1-sm { grid-template-columns: 1fr; }
  .col-2-sm { grid-template-columns: repeat(2, 1fr); }
  .col-3-sm { grid-template-columns: repeat(3, 1fr); }
  .col-4-sm { grid-template-columns: repeat(4, 1fr); }
  .col-5-sm { grid-template-columns: repeat(5, 1fr); }
  .col-6-sm { grid-template-columns: repeat(6, 1fr); }
  .columns-intrinsic.col-1-sm { grid-template-columns: auto; }
  .columns-intrinsic.col-2-sm { grid-template-columns: auto auto; }
  .columns-intrinsic.col-3-sm { grid-template-columns: auto auto auto; }
  .columns-intrinsic.col-4-sm { grid-template-columns: auto auto auto auto; }
  .columns-intrinsic.col-5-sm { grid-template-columns: auto auto auto auto auto; }
  .columns-intrinsic.col-6-sm { grid-template-columns: auto auto auto auto auto auto; }
}

/* md: 768–1023px */
@media (min-width: 768px) and (max-width: 1023px) {
  .col-1-md { grid-template-columns: 1fr; }
  .col-2-md { grid-template-columns: repeat(2, 1fr); }
  .col-3-md { grid-template-columns: repeat(3, 1fr); }
  .col-4-md { grid-template-columns: repeat(4, 1fr); }
  .col-5-md { grid-template-columns: repeat(5, 1fr); }
  .col-6-md { grid-template-columns: repeat(6, 1fr); }
  .columns-intrinsic.col-1-md { grid-template-columns: auto; }
  .columns-intrinsic.col-2-md { grid-template-columns: auto auto; }
  .columns-intrinsic.col-3-md { grid-template-columns: auto auto auto; }
  .columns-intrinsic.col-4-md { grid-template-columns: auto auto auto auto; }
  .columns-intrinsic.col-5-md { grid-template-columns: auto auto auto auto auto; }
  .columns-intrinsic.col-6-md { grid-template-columns: auto auto auto auto auto auto; }
}

/* lg ≥ 1024px */
@media (min-width: 1024px) {
  .col-1-lg { grid-template-columns: 1fr; }
  .col-2-lg { grid-template-columns: repeat(2, 1fr); }
  .col-3-lg { grid-template-columns: repeat(3, 1fr); }
  .col-4-lg { grid-template-columns: repeat(4, 1fr); }
  .col-5-lg { grid-template-columns: repeat(5, 1fr); }
  .col-6-lg { grid-template-columns: repeat(6, 1fr); }
  .columns-intrinsic.col-1-lg { grid-template-columns: auto; }
  .columns-intrinsic.col-2-lg { grid-template-columns: auto auto; }
  .columns-intrinsic.col-3-lg { grid-template-columns: auto auto auto; }
  .columns-intrinsic.col-4-lg { grid-template-columns: auto auto auto auto; }
  .columns-intrinsic.col-5-lg { grid-template-columns: auto auto auto auto auto; }
  .columns-intrinsic.col-6-lg { grid-template-columns: auto auto auto auto auto auto; }
}

/* ── child span classes (apply to grid children) ── */
.col-span-1 { grid-column: span 1; }
.col-span-2 { grid-column: span 2; }
.col-span-3 { grid-column: span 3; }
.col-span-4 { grid-column: span 4; }
.col-span-5 { grid-column: span 5; }
.col-span-6 { grid-column: span 6; }
.col-span-full { grid-column: 1 / -1; }

/* ── child max-width classes (apply to grid children) ── */
.col-max-xs  { min-width: 4rem;  max-width: 4rem;  } /* ~80px   — narrow label / sidebar */
.col-max-sm  { min-width: 6rem; max-width: 6rem; } /* ~192px  — compact form / card    */
.col-max-md  { min-width: 12rem; max-width: 12rem; } /* ~384px  — short-form content      */
.col-max-lg  { min-width: 24rem; max-width: 24rem; } /* ~512px  — body-text column        */
.col-max-xl  { min-width: 32rem; max-width: 32rem; } /* ~768px  — wide content column     */

/* ── child height classes (apply to grid children) ── */
.col-min-h-25   { height: 25vh; }
.col-min-h-33   { height: 33.333vh; }
.col-min-h-50   { height: 50vh; }
.col-min-h-66   { height: 66.666vh; }
.col-min-h-75   { height: 75vh; }
.col-min-h-100  { height: 100dvh; }
.col-min-h-auto { height: auto; }
.col-min-h-full { height: 100%; }
.col-min-h-content { height: min-content; }

/* ── child height classes (apply to grid children) ── */
.col-offset-h-25   { margin-top: -25vh; }
.col-offset-h-33   { margin-top: -33.333vh; }
.col-offset-h-50   { margin-top: -50vh; }
.col-offset-h-66   { margin-top: -66.666vh; }
.col-offset-h-75   { margin-top: -75vh; }
.col-offset-h-100  { margin-top: -100dvh; }
.col-offset-h-auto { margin-top: calc(-1 * auto); }
.col-offset-h-full { margin-top: -100%; }
.col-offset-h-content { margin-top: calc(-1 * min-content); }

/* ── breakout: child exceeds its grid-cell parent width ── */
.col-breakout {
  width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
}

/* ── z-index utilities (use existing tokens) ─── */
.z-0   { z-index: var(--z-index-0); }
.z-1   { z-index: var(--z-index-1); }
.z-2   { z-index: var(--z-index-2); }
.z-3   { z-index: var(--z-index-3); }
.z-4   { z-index: var(--z-index-4); }
.z-100 { z-index: var(--z-index-100); }

/* xs < 480px */
@media (max-width: 479px) {
  .col-span-1-xs { grid-column: span 1; }
  .col-span-2-xs { grid-column: span 2; }
  .col-span-3-xs { grid-column: span 3; }
  .col-span-4-xs { grid-column: span 4; }
  .col-span-5-xs { grid-column: span 5; }
  .col-span-6-xs { grid-column: span 6; }
  .col-span-full-xs { grid-column: 1 / -1; }
}

/* sm: 480–767px */
@media (min-width: 480px) and (max-width: 767px) {
  .col-span-1-sm { grid-column: span 1; }
  .col-span-2-sm { grid-column: span 2; }
  .col-span-3-sm { grid-column: span 3; }
  .col-span-4-sm { grid-column: span 4; }
  .col-span-5-sm { grid-column: span 5; }
  .col-span-6-sm { grid-column: span 6; }
  .col-span-full-sm { grid-column: 1 / -1; }
}

/* md: 768–1023px */
@media (min-width: 768px) and (max-width: 1023px) {
  .col-span-1-md { grid-column: span 1; }
  .col-span-2-md { grid-column: span 2; }
  .col-span-3-md { grid-column: span 3; }
  .col-span-4-md { grid-column: span 4; }
  .col-span-5-md { grid-column: span 5; }
  .col-span-6-md { grid-column: span 6; }
  .col-span-full-md { grid-column: 1 / -1; }
}

/* lg ≥ 1024px */
@media (min-width: 1024px) {
  .col-span-1-lg { grid-column: span 1; }
  .col-span-2-lg { grid-column: span 2; }
  .col-span-3-lg { grid-column: span 3; }
  .col-span-4-lg { grid-column: span 4; }
  .col-span-5-lg { grid-column: span 5; }
  .col-span-6-lg { grid-column: span 6; }
  .col-span-full-lg { grid-column: 1 / -1; }
}


/* ═══════════════════════════════════════════════════
   CHATBOT SIMULATION — adapted to existing design tokens
   Follows the site's Tier 1/2/3 pattern: a small block of
   new Tier 3 (component) tokens, built from existing Tier 1/2
   primitives, then the component rules underneath.
═══════════════════════════════════════════════════ */

:root {
  /* ── chatbot component tokens ─────────────────────
     Nothing in the existing scale covers a "soft, rounded
     conversational card" — the site's language is otherwise
     pill (999px) or near-square (2px). These three radii are
     the only genuinely NEW primitives this component needs;
     everything else below is reuse. */
  --chatbot-radius-shell:   var(--space-24);  /* 24px, was 1.5rem  */
  --chatbot-radius-bubble:  var(--space-20);  /* 20px, was 1.3rem  */
  --chatbot-radius-tail:    var(--radius-2);  /* 2px  tucked corner */

  /* ── surfaces, on a light section ────────────────── */
  --chatbot-shell-bg:        var(--color-background-surface);
  --chatbot-shell-border:    var(--color-fill-opacity-10);
  --chatbot-shell-shadow:    var(--elevation-2);

  --chatbot-bubble-bot-bg:      var(--color-background-subtle);
  --chatbot-bubble-bot-color:   var(--color-text-primary);
  --chatbot-bubble-user-bg:     var(--color-brand-highlight-tint);
  --chatbot-bubble-user-color:  var(--color-text-primary);

  --chatbot-chip-bg:            var(--color-background-surface);
  --chatbot-chip-border:        var(--color-border-light);
  --chatbot-chip-color:         var(--color-text-secondary);
  --chatbot-chip-hover-bg:      var(--color-brand-highlight-tint);
  --chatbot-chip-hover-color:   var(--color-brand-primary);
  --chatbot-chip-hover-border:  var(--color-brand-primary-tint);

  --chatbot-link-bg:            var(--color-background-subtle);

  --chatbot-secondary-color:        var(--color-text-muted);
  --chatbot-secondary-hover-color:  var(--color-text-secondary);

  --chatbot-transition-height:  var(--transition-duration-xxl) var(--transition-easing-smooth);
  --chatbot-transition-item:    var(--transition-duration-xl) var(--transition-easing-out);
}

/* Progressive enhancement: hide the semantic fallback tree
   once JS has built the interactive widget. Uses the site's
   existing .has-js convention (set on <html> by theme.js). */
.has-js .chatbot-tree {
  display: none;
}

.chatbot-sim {
  margin: var(--space-24) 0;
}

.chatbot-shell {
  max-width: var(--article-max-width, 46rem);
  border: var(--border-width-default) solid var(--chatbot-shell-border);
  border-radius: var(--chatbot-radius-shell);
  background: var(--chatbot-shell-bg);
  padding: clamp(var(--space-14), 1.8vw, var(--space-20));
  box-shadow: var(--chatbot-shell-shadow);
  transition: height var(--chatbot-transition-height);
  will-change: height;
}

.chatbot-shell-inner {
  display: grid;
}

.chatbot-messages {
  display: flex;
  flex-direction: column;
  gap: var(--space-12);
}

.chatbot-messages > *,
.chatbot-actions > * {
  animation: chatbot-item-enter var(--chatbot-transition-item) both;
}

.chatbot-turn {
  display: flex;
  width: 100%;
}

.chatbot-turn.is-bot {
  justify-content: flex-start;
}

.chatbot-turn.is-user {
  justify-content: flex-end;
}

.chatbot-bubble {
  max-width: min(85%, 34rem);
  padding: var(--space-12) var(--space-16);
  border-radius: var(--chatbot-radius-bubble);
  background: var(--chatbot-bubble-bot-bg);
  color: var(--chatbot-bubble-bot-color);
  font-family: var(--font-family-body);
  font-size: var(--font-size-body-sm);
  font-weight: var(--font-weight-body);
  line-height: var(--line-height-body);
}

.chatbot-turn.is-bot .chatbot-bubble {
  border-bottom-left-radius: var(--chatbot-radius-tail);
}

.chatbot-turn.is-user .chatbot-bubble {
  background: var(--chatbot-bubble-user-bg);
  color: var(--chatbot-bubble-user-color);
  border-bottom-right-radius: var(--chatbot-radius-tail);
}

.chatbot-bubble.is-typing::after {
  content: '';
  display: inline-block;
  width: var(--space-6);
  height: 1em;
  margin-left: var(--space-2);
  border-right: var(--border-width-emphasis) solid currentColor;
  vertical-align: text-bottom;
  animation: chatbot-caret var(--animation-blink-duration) step-end infinite;
}

.chatbot-actions {
  display: grid;
  gap: var(--space-12);
  margin-top: var(--space-16);
}

.chatbot-options,
.chatbot-utility {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-8);
}

.chatbot-recommendations {
  display: grid;
  gap: var(--space-8);
}

.chatbot-recommendation {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-8);
}

.chatbot-recommendation-label {
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-label);
  font-size: var(--font-size-caption);
  letter-spacing: var(--tracking-loose-sm);
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* Quick-reply chips and recommendation links share the same
   pill treatment as .filter-pill, but need a solid resting
   surface (they sit on chat bubbles' background, not a bare
   section), a hover-highlight state, and a lift-on-hover
   micro-interaction consistent with .btn's spring easing. */
.chatbot-options button,
.chatbot-link,
.chatbot-secondary {
  appearance: none;
  border: var(--border-width-default) solid var(--chatbot-chip-border);
  border-radius: var(--radius-pill);
  background: var(--chatbot-chip-bg);
  color: var(--chatbot-chip-color);
  padding: var(--space-10) var(--space-16);
  text-decoration: none;
  font-family: var(--font-family-body);
  font-size: var(--font-size-caption);
  font-weight: var(--font-weight-body-strong);
  line-height: var(--line-height-125);
  cursor: pointer;
  box-shadow: none;
  transition:
    transform var(--transition-duration-long) var(--transition-easing-spring),
    background var(--transition-duration-fast),
    border-color var(--transition-duration-fast),
    color var(--transition-duration-fast);
}

.chatbot-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  background: var(--chatbot-link-bg);
}

.chatbot-link-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-16);
  height: var(--space-16);
  font-size: 0.85em;
  color: var(--color-brand-primary);
  opacity: 0.85;
}

.chatbot-options button:hover,
.chatbot-options button:focus-visible,
.chatbot-link:hover,
.chatbot-link:focus-visible,
.chatbot-secondary:hover,
.chatbot-secondary:focus-visible {
  transform: translateY(var(--elevation-translate-1));
  background: var(--chatbot-chip-hover-bg);
  color: var(--chatbot-chip-hover-color);
  border-color: var(--chatbot-chip-hover-border);
}

.chatbot-secondary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  background: transparent;
  border-color: transparent;
  color: var(--chatbot-secondary-color);
  padding-left: var(--space-8);
  padding-right: var(--space-8);
}

.chatbot-secondary:hover,
.chatbot-secondary:focus-visible {
  background: transparent;
  border-color: transparent;
  color: var(--chatbot-secondary-hover-color);
}

.chatbot-control-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-16);
  height: var(--space-16);
  font-size: 0.9em;
  opacity: 0.78;
}

.chatbot-secondary.is-back .chatbot-control-icon {
  font-size: 1em;
}

.chatbot-secondary.is-restart .chatbot-control-icon {
  font-size: 0.95em;
}

/* ── dark / brand section support ─────────────────
   New: the source CSS only ever assumed a white card on a
   light page. This site reuses sections on dark and brand
   backgrounds (.section-dark / .section-brand), so the shell
   needs an inverse surface or it will render as a jarring
   white box. Uses the same --section-* custom properties the
   rest of the site swaps per section variant. */
.section-dark .chatbot-shell,
.section-brand .chatbot-shell {
  background: var(--color-fill-inverse-opacity-10);
  border-color: var(--color-fill-inverse-opacity-20);
}

.section-dark .chatbot-bubble,
.section-brand .chatbot-bubble {
  background: var(--color-fill-inverse-opacity-10);
  color: var(--section-text);
}

.section-dark .chatbot-turn.is-user .chatbot-bubble,
.section-brand .chatbot-turn.is-user .chatbot-bubble {
  background: var(--color-fill-inverse-opacity-20);
  color: var(--color-text-inverse-primary);
}

.section-dark .chatbot-options button,
.section-dark .chatbot-link,
.section-brand .chatbot-options button,
.section-brand .chatbot-link {
  background: transparent;
  border-color: var(--color-fill-inverse-opacity-40);
  color: var(--color-fill-inverse-opacity-80);
}

.section-dark .chatbot-options button:hover,
.section-dark .chatbot-link:hover,
.section-brand .chatbot-options button:hover,
.section-brand .chatbot-link:hover {
  background: var(--color-fill-inverse-opacity-10);
  border-color: var(--color-fill-inverse-opacity-60);
  color: var(--color-fill-inverse-opacity-100);
}

@keyframes chatbot-caret {
  50% {
    opacity: 0;
  }
}

@keyframes chatbot-item-enter {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@media (max-width: 767px) {
  .chatbot-shell {
    padding: var(--space-16);
  }

  .chatbot-bubble {
    max-width: 92%;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chatbot-bubble.is-typing::after,
  .chatbot-messages > *,
  .chatbot-actions > * {
    animation: none;
  }

  .chatbot-shell {
    transition: none;
  }

  .chatbot-options button:hover,
  .chatbot-link:hover,
  .chatbot-secondary:hover {
    transform: none;
  }
}


/* ═══════════════════════════════════════════════════
   CHATBOT OVERLAY — FAB trigger + slide-up panel
   Injected into every page by theme.js. The tree data
   lives in JS so no per-page HTML changes are needed.
   Z-index sits just below the nav so the nav always
   renders on top.
═══════════════════════════════════════════════════ */

:root {
  --chatbot-fab-size:    56px;
  --chatbot-fab-radius:  var(--space-16);
  --chatbot-fab-offset:  var(--space-24);
  --chatbot-panel-width: 23rem;
  --chatbot-panel-max-h: min(580px, 80vh);
  --chatbot-overlay-z:   calc(var(--nav-z-index) - 1);
}

/* ── FAB trigger button ──────────────────────────── */
.chatbot-fab {
  position: fixed;
  bottom: var(--chatbot-fab-offset);
  right: var(--chatbot-fab-offset);
  z-index: var(--chatbot-overlay-z);
  width: var(--chatbot-fab-size);
  height: var(--chatbot-fab-size);
  border-radius: var(--chatbot-fab-radius);
  background: var(--color-brand-primary);
  color: var(--color-neutral-100);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: var(--elevation-3);
  /* hidden until JS shows it */
  opacity: 0;
  transform: scale(0.7) translateY(12px);
  pointer-events: none;
  transition:
    opacity var(--transition-duration-xl) var(--transition-easing-out),
    transform var(--transition-duration-xl) var(--transition-easing-spring),
    background var(--transition-duration-fast),
    box-shadow var(--transition-duration-fast);
}

.chatbot-fab.is-visible {
  opacity: 1;
  transform: scale(1) translateY(0);
  pointer-events: auto;
}

.chatbot-fab:hover {
  background: color-mix(in srgb, var(--color-brand-primary) 85%, white);
  transform: scale(1.06) translateY(-2px);
  box-shadow: var(--elevation-3),
              0 0 0 5px color-mix(in srgb, var(--color-brand-primary) 20%, transparent);
}

.chatbot-fab:focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring-color);
  outline-offset: var(--focus-ring-offset);
}

/* Attention nudge — fires after a delay if the user hasn't
   opened the panel yet, repeats every 6 s */
.chatbot-fab.wants-attention {
  animation: chatbot-fab-nudge 6s var(--transition-easing-spring) infinite;
}

@keyframes chatbot-fab-nudge {
  0%, 55%, 100% { transform: scale(1) translateY(0); }
  8%            { transform: scale(1.14) translateY(-5px); }
  18%           { transform: scale(0.95) translateY(2px); }
  28%           { transform: scale(1.07) translateY(-3px); }
  38%           { transform: scale(0.98) translateY(1px); }
}

/* ── unread badge ──────────────────────────────────── */
.chatbot-fab-badge {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: var(--space-18);
  height: var(--space-18);
  border-radius: var(--radius-pill);
  background: var(--color-brand-accent);
  color: var(--color-neutral-100);
  font-size: 0.6rem;
  font-weight: var(--font-weight-button);
  font-family: var(--font-family-display);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 var(--space-4);
  border: 2px solid var(--color-background-page);
  opacity: 0;
  transform: scale(0.4);
  animation: chatbot-badge-pop var(--transition-duration-xl) var(--transition-easing-spring) forwards;
  animation-delay: 2.4s;
}

/* hide badge once the user has seen the panel */
.chatbot-fab.has-seen .chatbot-fab-badge {
  display: none;
}

@keyframes chatbot-badge-pop {
  to { opacity: 1; transform: scale(1); }
}

/* ── overlay panel ──────────────────────────────────── */
.chatbot-overlay {
  position: fixed;
  bottom: calc(var(--chatbot-fab-offset) + var(--chatbot-fab-size) + var(--space-12));
  right: var(--chatbot-fab-offset);
  z-index: var(--chatbot-overlay-z);
  width: var(--chatbot-panel-width);
  max-height: var(--chatbot-panel-max-h);
  display: flex;
  flex-direction: column;
  background: var(--color-background-surface);
  border: var(--border-width-default) solid var(--color-border-light);
  border-radius: var(--chatbot-radius-shell);
  box-shadow: var(--elevation-3);
  /* closed state */
  opacity: 0;
  transform: translateY(20px) scale(0.96);
  transform-origin: bottom right;
  pointer-events: none;
  transition:
    opacity var(--transition-duration-medium) var(--transition-easing-smooth),
    transform var(--transition-duration-medium) var(--transition-easing-spring);
}

.chatbot-overlay.is-open {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

/* ── panel header ──────────────────────────────────── */
.chatbot-overlay-header {
  display: flex;
  align-items: center;
  gap: var(--space-12);
  padding: var(--space-14) var(--space-20);
  background: var(--color-brand-primary);
  border-radius: var(--chatbot-radius-shell) var(--chatbot-radius-shell) 0 0;
  color: var(--color-neutral-100);
  flex-shrink: 0;
}

.chatbot-overlay-avatar {
  width: var(--space-32);
  height: var(--space-32);
  border-radius: var(--radius-circle);
  background: color-mix(in srgb, var(--color-neutral-100) 18%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  flex-shrink: 0;
}

.chatbot-overlay-title {
  flex: 1;
  min-width: 0;
}

.chatbot-overlay-name {
  display: block;
  font-family: var(--font-family-display);
  font-weight: var(--font-weight-heading);
  font-size: var(--font-size-body-sm);
  letter-spacing: var(--tracking-loose-xs);
  text-transform: uppercase;
  color: var(--color-neutral-100);
  line-height: var(--line-height-1);
}

.chatbot-overlay-status {
  display: block;
  font-size: var(--font-size-label-sm);
  color: color-mix(in srgb, var(--color-neutral-100) 72%, transparent);
  margin-top: var(--space-2);
}

.chatbot-overlay-close {
  appearance: none;
  background: transparent;
  border: none;
  color: color-mix(in srgb, var(--color-neutral-100) 75%, transparent);
  cursor: pointer;
  padding: var(--space-6);
  border-radius: var(--radius-2);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: calc(-1 * var(--space-6));
  transition:
    color var(--transition-duration-fast),
    background var(--transition-duration-fast);
}

.chatbot-overlay-close:hover {
  color: var(--color-neutral-100);
  background: color-mix(in srgb, var(--color-neutral-100) 15%, transparent);
}

.chatbot-overlay-close:focus-visible {
  outline: var(--focus-ring-width) solid
    color-mix(in srgb, var(--color-neutral-100) 60%, transparent);
  outline-offset: var(--focus-ring-offset);
}

/* ── panel body (scrollable chatbot area) ──────────── */
.chatbot-overlay-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-16) var(--space-20) var(--space-20);
  scroll-behavior: smooth;
}

/* reset shell inside the panel — fills width, no outer border */
.chatbot-overlay-body .chatbot-shell {
  max-width: none;
  border: none;
  border-radius: 0;
  background: transparent;
  padding: 0;
  box-shadow: none;
}

/* ── mobile: full-width bottom sheet ────────────────── */
@media (max-width: 479px) {
  .chatbot-overlay {
    left: var(--space-8);
    right: var(--space-8);
    bottom: calc(var(--chatbot-fab-offset) + var(--chatbot-fab-size) + var(--space-8));
    width: auto;
    max-height: 74vh;
  }
}

/* ── reduced motion ──────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .chatbot-fab.wants-attention { animation: none; }
  .chatbot-fab-badge           { animation: none; opacity: 1; transform: scale(1); }
  .chatbot-fab {
    transition:
      opacity var(--transition-duration-fast),
      background var(--transition-duration-fast);
    transform: none;
  }
  .chatbot-fab.is-visible      { transform: none; }
  .chatbot-overlay {
    transition: opacity var(--transition-duration-fast);
    transform: none;
  }
  .chatbot-overlay.is-open     { transform: none; }
}