/* ==========================================================================
   DESIGN TOKENS
   Source of truth: Figma file "Portfolio 2026" (fFTZJigMoRnQ6DlxAcfZzq),
   variables pulled directly from the file's variable collection; V3 homepage,
   global grid and theme values from the V3 file (EQ5vs6l8ARkiiJ1YLCnUkV).
   Do not hand-edit values here without checking them against Figma first —
   this file exists so every other stylesheet/component reads from ONE place.
   ========================================================================== */

:root {
  --nav-height: 88px;             /* Sticky nav height (logo 24px + 32px padding above and below, Figma "NEW Nav") */

  /* ---- Color: brand & neutrals --------------------------------------
     Reconciled against the authoritative style-guide token list — every
     value below is an exact supplied token, not an approximation. */
  --color-blue: #0946B8;          /* Figma "Blue V2" — primary accent, links, footer bg (was #1029B7) */
  --color-blue-hover: #001174;    /* Figma "Blue Hover" */
  --color-black: #000000;         /* Black */
  --color-ink: #000000;           /* Text/Headings — was an unapproved #1A171E approximation; style guide's only near-black token is Black #000000 */
  --color-white: #FFFFFF;

  /* Accessibility correction (approved): these two were #777777 (4.48:1 on
     white, 4.07:1 on --color-bg-gray) and #A0A0A0 (2.61:1 on white) — both
     below the WCAG AA 4.5:1 floor for normal-sized text. Darkened to the
     values below, which clear AA on every background they are actually used
     against while keeping the two-tier hierarchy (gray for client/category,
     the lighter gray-2 for the trailing year) as distinct as AA allows.
     Do not lighten these back. */
  --color-gray: #6B6B6B;          /* Gray — secondary label text (card meta) */
  --color-gray-2: #757575;        /* Gray 2 — tertiary label text (e.g. year) */
  --color-gray-3: #DDDDDD;        /* Gray 3 — hairline borders (card image) */

  --color-bg: #FFFFFF;            /* page background */
  --color-bg-gray: #F4F4F4;       /* Background Gray — More Work section bg */
  --color-bg-blue: #F6F7FF;       /* Background Blue — subtle tinted sections */
  --color-bg-near-white: #F9F9F9; /* Background Gray / near-white */
  --color-blue-gray: #5F5F85;     /* Blue Gray — secondary blue-tinted text */
  --color-slate: #575762;         /* Figma "New Gray" — footer signature + copyright */
  --color-yellow-50: #FFFCF8;     /* Yellow 50 */
  --color-light-blue: #BEDEFF;    /* Light Blue — More Work diagnostic-only placeholder fill */

  --color-border: #E9E9E9;        /* border-gray — general hairline border */
  --color-placeholder-blue: #E0F2FF; /* image-loading placeholder fill */
  --color-vibrant-blue-100: #C1E9FF; /* reflection/callout tint background */

  /* ---- Color: themeable semantic roles (V3 light/dark) ----------------
     Components read these roles; [data-theme="dark"] below redefines them
     (plus the text/line palette tokens above). Brand --color-blue is never
     redefined: it stays the fill for the footer, pills and the reflection
     card. Blue used as TEXT reads --color-blue-text, which lightens in dark
     mode because the brand blue on a near-black page is only ~2:1. */
  --color-surface: #FFFFFF;          /* cards, dialogs, footer legal row */
  --color-blue-text: var(--color-blue);
  --color-light-blue-50: #EEF5FC;    /* Figma "Light Blue 50" — topic tag fill */
  --color-band: rgba(238, 245, 252, 0.5); /* More Things band (Figma "Light Blue 50 50%") */
  /* More Things (homepage) tonal system. The band must READ as Light Blue 50
     (#EEF5FC) while the page grid still shows through it, so it is a 50%
     wash of #DDEBF9, which composites to exactly #EEF5FC on the white page.
     Its section rule is Light Blue (#BEDEFF),
     and the control itself is an opaque Light Blue disc, one tonal step
     darker than the band, so it separates from it and no grid line shows
     through. Its ring is the same value (no stronger pale blue exists in the
     palette, so none was invented). Dark mode swaps in its own quiet equivalents below. */
  --color-things-bg: rgba(221, 235, 249, 0.5);
  --color-things-rule: var(--color-light-blue);
  --color-things-control-bg: var(--color-light-blue);
  --color-things-control-border: var(--color-light-blue);
  /* Tonal tile (case-study stat tiles): the same pale-blue step as the
     More Things system, a Light Blue 50 fill with a Light Blue line. */
  --color-tile-bg: #EEF5FC;
  --color-tile-border: var(--color-light-blue);
  /* Page wash (Figma "Blue White gradient"): pale blue at the very top of
     every page, fading to the page background by --page-tint-end. The
     gradient itself is drawn on <body> in base.css. */
  --color-page-tint: #F0F7FF;
  --page-tint-end: 450px;
  /* Line hierarchy: the background grid is the quietest line on the page;
     intentional section rules, dividers and control rings sit one clear
     step above it (--color-rule), so structure reads as its own layer.
     Card borders already use --color-gray-3, which is what --color-rule
     points to, so every intentional line shares one value per theme. */
  --color-grid-line: #EDEDED;        /* vertical page grid only (Figma grid stroke) */
  --color-rule: var(--color-gray-3); /* section rules, dividers, control rings */
  --color-control-bg: var(--color-bg-gray); /* pause toggles, dark-mode disabled pill */
  --color-control-fg: var(--color-black);
  /* Theme/grid utility controls: a frosted 75% surface (same family as the
     scrolled nav's translucent bar), a one-step-darker hover surface, and
     the ring that marks a feature as ON. */
  --color-control-surface: rgba(244, 244, 244, 0.75);
  --color-control-surface-hover: rgba(221, 221, 221, 0.85);
  --color-control-ring: var(--color-gray);
  --color-nav-scrolled: rgba(255, 255, 255, 0.85);
  /* About V5 bands: OFF doodle band (Figma "Light Blue 100") and the OFF
     "Currently" band (Figma "Light Blue 50%", translucent so the grid shows). */
  --color-light-blue-100: #DFEFFF;
  --color-band-blue: rgba(235, 245, 255, 0.5);

  /* ---- Typography: font families -------------------------------------
     Pacaembu is the site's single display + body family (it replaced Neulis
     Sans in the October 2026 redesign); Nitti is the monospace detail/kicker
     face. Both are served by ONE Adobe Fonts (Typekit) web project:
       <link rel="stylesheet" href="https://use.typekit.net/qxj8pbc.css">
     The kit declares family names as lowercase hyphenated slugs ("pacaembu",
     "nitti"), not the human-readable names. Keep the slugs.
     Weight mapping = the Figma text styles, exactly (Megan, 2026-10-01):
       300 Light     body and supporting copy
       400 Regular   headings and titles
       600 Semibold  intentional emphasis only (and the H100 / Stat styles)
       700 Bold      strong emphasis, only where explicitly designed
     Pacaembu reads heavy, so hierarchy comes from the lighter weights. Do not
     shift this to a "conventional" 400 / 600 / 700 ladder. Nothing goes
     above Bold: there is no ExtraBold in this system.
     LOCAL-RENDERING TRAP: a locally activated Pacaembu registers its
     ExtraLight face at weight 300, so font-weight: 300 renders ExtraLight
     on a machine that has the fonts installed but no web kit. That made
     Light look far too thin and once led to an (undone) one-step-heavier
     mapping. Every page therefore carries a tiny inline @font-face BEFORE
     the Typekit <link> that maps weight 300 to local("Pacaembu Light").
     Because the kit's own @font-face rules come later in the cascade, they
     take precedence the moment the kit serves Pacaembu, so production never
     depends on a locally installed font.
     "neulis-sans" stays second in the stack only as a safety net while the
     kit is being updated. Once Pacaembu is in the kit it is never reached. */
  --font-body: "pacaembu", "neulis-sans", -apple-system, "Segoe UI", sans-serif;
  --font-detail: "nitti", ui-monospace, "SFMono-Regular", monospace;

  /* Weight scale (see the mapping above). */
  --weight-light: 300;
  --weight-regular: 400;
  --weight-semibold: 600;
  --weight-bold: 700;

  /* ---- Typography: type scale (names, sizes, weights and leading are the
     Figma text styles) ----------------------------------------------------- */
  --text-h100-size: 34px;   --text-h100-weight: var(--weight-semibold); --text-h100-leading: 1.25; --text-h100-font: var(--font-body);
  --text-h200-size: 28px;   --text-h200-weight: var(--weight-regular);  --text-h200-leading: 1.35; --text-h200-font: var(--font-body);
  --text-h300-size: 20px;   --text-h300-weight: var(--weight-regular);  --text-h300-leading: 1.25; --text-h300-font: var(--font-body);
  --text-h400-size: 18px;   --text-h400-weight: var(--weight-regular);  --text-h400-leading: 1.15; --text-h400-font: var(--font-body);
  --text-stat-size: 32px;   --text-stat-weight: var(--weight-semibold); --text-stat-leading: 1.35; --text-stat-font: var(--font-body);

  /* Display styles. Display100 is the homepage H1: fluid from 30px on
     phones to 46px at a 1200px viewport (2.6vw + 14.8px), then up to its
     Figma size of 50px at 1440px+ (see the min-width: 1200px block below).
     Display200 is 48 Regular. DisplayIntro is 20 Light, on the body leading (1.6). */
  --text-display100-size: clamp(30px, calc(2.6vw + 14.8px), 46px); --text-display100-weight: var(--weight-regular); --text-display100-leading: 1.15;
  --text-display200-size: clamp(32px, calc(2vw + 24px), 48px); --text-display200-weight: var(--weight-regular); --text-display200-leading: 1.15;
  --text-intro-size: 20px;  --text-intro-weight: var(--weight-light); --text-intro-leading: 1.6;

  /* Body is Light, on 160% leading (Megan, 2026-10-02: Pacaembu Light read
     too tight at the earlier 150% / 135%). That 1.6 belongs to the Light
     body and supporting-copy roles ONLY: Body100/200/300 and DisplayIntro.
     Everything compact keeps its own leading: headings, Nitti details, the
     Semibold styles, and UI text that merely inherits from <body>
     (--text-ui-leading: footer, skip link, small labels and captions).
     The two "-medium" styles keep their legacy names for
     compatibility: their weight is Semibold (Figma "Body … Semibold").
     Paragraph-spacing values are applied as margin-top on p+p via the
     .text-body* utility classes. */
  --text-body100-size: 18px; --text-body100-weight: var(--weight-light); --text-body100-leading: 1.6;  --text-body100-font: var(--font-body); --text-body100-paragraph-spacing: 16px;
  --text-body100-medium-size: 18px; --text-body100-medium-weight: var(--weight-semibold); --text-body100-medium-leading: 1.5; --text-body100-medium-font: var(--font-body); --text-body100-medium-paragraph-spacing: 12px;
  --text-body200-size: 16px; --text-body200-weight: var(--weight-light); --text-body200-leading: 1.6;  --text-body200-font: var(--font-body); --text-body200-paragraph-spacing: 12px;
  --text-body200-semibold-weight: var(--weight-semibold); --text-body200-semibold-leading: 1.5;
  --text-ui-leading: 1.5;
  --text-body300-size: 14px; --text-body300-weight: var(--weight-light); --text-body300-leading: 1.6;  --text-body300-font: var(--font-body); --text-body300-paragraph-spacing: 12px;
  --text-body300-medium-size: 14px; --text-body300-medium-weight: var(--weight-semibold); --text-body300-medium-leading: 1.35; --text-body300-medium-font: var(--font-body); --text-body300-medium-paragraph-spacing: 0px;

  --text-details100-size: 16px; --text-details100-weight: 400; --text-details100-leading: 1.5; --text-details100-font: var(--font-detail);
  --text-details200-size: 14px; --text-details200-weight: 400; --text-details200-leading: 1.35; --text-details200-font: var(--font-detail);
  --text-details300-size: 12px; --text-details300-weight: 400; --text-details300-leading: 1.35; --text-details300-font: var(--font-detail);
  --text-legal-size: 12px; --text-legal-weight: var(--weight-light); --text-legal-style: normal; --text-legal-leading: 1.5; --text-legal-font: var(--font-body);

  /* ---- Spacing: 8px base scale (named tokens are the exact Figma pins) - */
  --space-xs:   4px;
  --space-sm:   8px;   /* "Spacing" — base unit */
  --space-md:  12px;   /* "V-padding" */
  --space-lg:  16px;   /* "H-padding" / "Spacing/16" */
  --space-xl:  24px;
  --space-2xl: 32px;
  --space-3xl: 40px;
  --space-4xl: 64px;   /* project-card image↔copy gap */
  --space-gutter: 120px; /* confirmed desktop side padding (Nav/Intro/Footer) */
  /* Shared major-section vertical rhythm: 64px desktop/tablet, 40px mobile
     (explicit spacing decision) — every top-level section's padding-block
     should reference this one token rather than repeating the media query. */
  --space-section-y: var(--space-4xl);

  /* ---- Radius & borders ------------------------------------------------ */
  --radius-card: 16px;   /* project card image, etc. */
  --radius-media: 12px;  /* homepage featured-card image (Figma) */
  --radius-media-lg: 20px;         /* case-study section media (Figma V2 case study) */
  --radius-pill: 999px;  /* tags, buttons, badges */
  --border-width: 1px;

  /* ---- Shadow ----------------------------------------------------------- */
  /* Figma's own "Card Dropshadow" variable is DROP_SHADOW #00000033/16px,
     which is what this used to be — but rendered against the page it read
     as a heavy dark halo, visibly heavier than the supplied mockup.
     Judged against the rendered comparison instead of the raw variable
     value: soft, light, barely-there lift. */
  --shadow-card: 0 4px 16px rgba(0, 0, 0, 0.08);

  /* ---- Layout: container & breakpoints ---------------------------------
     Confirmed: tablet should read as a narrower version of the SAME
     desktop layout (not a distinct stacked layout), stacking to single
     columns only below 840px, matching mobile.
     NOTE: CSS custom properties cannot be used inside @media conditions.
     These are documented here for reference/JS use; every @media rule in
     this codebase must repeat the literal px values below, and should
     link back to this comment if changed.
       mobile:  0    – 839px   (single-column / stacked)
       tablet:  840  – 1199px  (same multi-column layout as desktop, narrower)
       desktop: 1200px and up
     ----------------------------------------------------------------------- */
  --container-max: 1200px;
  --breakpoint-tablet: 840px;
  --breakpoint-desktop: 1200px;

  /* ---- Global vertical grid (V3) ----------------------------------------
     The visible page grid IS the layout grid: 12 columns with 32px gutters
     inside the 1200px content column (Figma V3: lines at x=120, then a pair
     at every gutter, then x=1320). A featured homepage card spans 6
     columns, a More Things card 4, and the case-study .case-grid's 4
     columns land on every third line. Replaces the retired dot grid. Tablet
     keeps 12 columns and the 32px gutter (so case-study columns still land
     on lines); mobile drops to 4 columns with 16px gutters, see below. */
  --page-margin: var(--space-gutter); /* the .container inline padding */
  --grid-columns: 12;
  --grid-gutter: var(--space-2xl);    /* 32px */
  --grid-line-width: 1px;

  /* ---- Motion ------------------------------------------------------------ */
  --ease-standard: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 120ms;   /* cursor position-follow, quick color flips */
  --duration-base: 180ms;   /* hover/focus state changes */
  --duration-slow: 220ms;   /* pill/annotation/modal entrances */
}

/* Wide desktop: the homepage H1 grows from 46px (1200) to 50px (1440+). */
@media (min-width: 1200px) {
  :root { --text-display100-size: clamp(46px, calc(1.6667vw + 26px), 50px); }
}
/* Page margin tiers — the same literal breakpoints .container always used. */
@media (max-width: 1199px) {
  :root { --page-margin: 48px; }
}
/* Mobile override for the shared section rhythm — see --space-section-y
   above — plus the 4-column mobile grid. NOTE: this repeats the 839px
   boundary used sitewide (see the breakpoint comment above); keep them in
   sync if either ever changes. */
@media (max-width: 839px) {
  :root {
    --space-section-y: var(--space-3xl);
    --page-margin: 24px;
    --grid-columns: 4;
    --grid-gutter: var(--space-lg); /* 16px */
  }
}

/* ---- Dark theme ----------------------------------------------------------
   Applied by the inline <head> bootstrap (html[data-theme="dark"]), from the
   visitor's saved choice or, with none saved, the OS preference. Tokens only:
   no filter/invert anywhere, so images and video are never altered. Every
   text role below clears WCAG AA on every dark surface it sits on
   (ink 15:1+, gray 6.3:1+, gray-2 5.6:1+, blue text 12:1+, tag text 8:1+).
   Brand --color-blue is deliberately NOT redefined: filled blue surfaces
   carrying white text (footer, cursor pills, Reflection card, skip link)
   keep the dark brand blue in both themes. */
:root[data-theme="dark"] {
  color-scheme: dark;
  --color-bg: #0E0F13;
  --color-surface: #17181D;
  --color-ink: #ECEDF1;
  --color-gray: #A3A4AE;
  --color-gray-2: #9A9BA5;
  /* Structural rules/borders (--color-rule follows gray-3): #373943 sits a
     clear step above the 6.5% grid (~#1E1F24) and still well under text. */
  --color-gray-3: #373943;
  --color-border: #373943;
  --color-bg-gray: #17181D;
  --color-bg-blue: #1C2140;
  /* Supporting blue-gray text (intro, section labels, tag text, card lines)
     is a quieter tone of the ONE dark accent below, not a second blue: 82% of
     --color-blue-text over the page (#9EB9D4, 9.4:1). It was a periwinkle
     (#B3B8DE) that read as a competing accent next to the logo and H1. */
  --color-blue-gray: color-mix(in srgb, var(--color-blue-text) 82%, var(--color-bg));
  --color-slate: #A3A4AE;
  --color-blue-text: #BEDEFF;          /* THE dark accent (13.8:1 on the page): logo, blue text, numbers, links, focus rings, cursor dot */
  --color-light-blue-50: #1C2140;
  --color-band: rgba(190, 222, 255, 0.04);
  /* More Things in dark: the same faint accent wash and the standard rule.
     The pause control is an opaque disc of the band's own colour (4% accent
     over the page) with a ring one step up (25% accent). */
  --color-things-bg: var(--color-band);
  --color-things-rule: var(--color-rule);
  --color-things-control-bg: #15171C;
  --color-things-control-border: #3F4955;
  --color-tile-bg: rgba(190, 222, 255, 0.05);
  --color-tile-border: #3F4955;
  --color-page-tint: #131A2C;          /* the same top-of-page wash, as a quiet navy */
  --color-light-blue-100: #18203F;
  --color-band-blue: rgba(190, 222, 255, 0.035);
  --color-grid-line: rgba(255, 255, 255, 0.065); /* ~#1E1F24 on the page: visible, still clearly under the #373943 rules */
  --color-control-bg: #23252C;
  --color-control-fg: var(--color-ink);
  --color-control-surface: rgba(35, 37, 44, 0.75);
  --color-control-surface-hover: rgba(58, 60, 70, 0.85);
  --color-nav-scrolled: rgba(14, 15, 19, 0.85);
  --shadow-card: 0 4px 16px rgba(0, 0, 0, 0.4);
}

/* ==========================================================================
   SITE SYSTEM 2026 (Figma "Homepage | Hero 1 | Desktop 1440 | Classic",
   EQ5vs6l8ARkiiJ1YLCnUkV node 372:9689, approved October 2026).
   The Figma variable collection "Homepage Modes" maps 1:1 to the roles below.
   Pages on the new system load /css/system.css and read ONLY these roles, so a
   colour mode is one block of overrides. Five launch modes: Classic (light,
   default), Bright, Dark, Racing and Duke Dog (the last three at the end of
   this file).
   ========================================================================== */
:root {
  --sys-bg: #FFFFFF;
  --sys-surface: #FFFFFF;
  --sys-hero: #777777;          /* hero + About statement base (large text only: 4.48:1, AA large) */
  --sys-emphasis: #000000;      /* "products", "brands", "me." */
  --sys-heading: #000000;       /* section H2s */
  --sys-ink: #000000;           /* titles, links, body ink */
  --sys-secondary: #6B6B6B;     /* Nitti meta, nav links, numbers (5.33:1) */
  --sys-supporting: #6B6B6B;    /* Light body copy */
  --sys-accent: #0946B8;        /* hover / interactive accent, focus ring */
  --sys-rule: #DDDDDD;          /* dividers between rows */
  --sys-rule-strong: #000000;   /* hero meta line, About callout rules */
  --sys-slash: #B5B5B5;         /* decorative separators (aria-hidden) */
  --sys-tint: #F2F2F2;          /* hover surfaces on icon controls */
  --sys-media-bg: #F4F4F4;      /* image placeholder fill */
  /* the arrow / plus discs on project thumbnails: white with a black glyph in
     EVERY mode (they sit on artwork, not on the page), so no mode overrides them */
  --sys-icon-bg: #FFFFFF;
  --sys-icon-fg: #000000;
  /* Utility bar (colour mode + grid): an opaque surface one step off the page,
     a visible hairline, a strong inactive icon and a hover/active fill, so it
     reads on the page, on photos and on the footer in every mode. */
  --sys-util-bg: #EFEFEF;
  --sys-util-border: #ABABAB;
  --sys-util-fg: #555555;      /* 6.5:1 on the bar */
  --sys-util-hover: #CECECE;   /* ink 13.3:1 */
  --sys-band: #F5F5F5;          /* neutral section band (case-study Key Insights) */

  --sys-footer-bg: #0B0C10;
  --sys-footer-hi: #FFFFFF;
  --sys-footer-dim: rgba(255, 255, 255, 0.5);
  --sys-footer-rule: rgba(255, 255, 255, 0.18);
  --sys-menu-bg: #111216;
  --sys-menu-ink: #FFFFFF;
  --sys-menu-caption: rgba(255, 255, 255, 0.68);
  --sys-menu-highlight: rgba(255, 255, 255, 0.1);
  --sys-grid: #E2E2E2;           /* raised from #EDEDED: visible on retina, still under the #DDD rules */
  --sys-scrim: rgba(8, 10, 18, 0.66);
  --sys-modal-bg: #FFFFFF;
  --sys-nav-scrolled: rgba(255, 255, 255, 0.85);

  /* Type (Figma text styles on the approved frame) */
  --sys-nav-name: 500 18px/1 var(--font-detail);  /* Figma 14, raised on review: 16 (2026-10-14), then 18 */
  --sys-detail: 400 12px/1.35 var(--font-detail);       /* uppercase via class */
  --sys-detail-14: 400 14px/1.35 var(--font-detail);
  --sys-hero-size: clamp(38px, 3.122vw + 26.29px, 70px); /* 70 from 1400 up, 38 at 375 */
  --sys-h2-size: clamp(40px, 4.39vw + 23.54px, 85px);    /* 85 from 1400 up */
  --sys-minor-h2-size: clamp(28px, 1.11vw + 24px, 40px);
  --sys-statement-size: clamp(30px, 1.56vw + 24.15px, 46px); /* 46 from 1400 up */
  --sys-footer-phrase: clamp(64px, 19vw, 300px);        /* JS fits it to the column */

  /* Layout (1440 frame: 120 margin, 1200 content, 12 x 32 gutter) */
  --sys-section-y: 160px;
  --sys-nav-height: 72px;
  --sys-radius-card: 16px;
  --sys-radius-tile: 14px;
  --sys-radius-media: 20px;
}
@media (max-width: 1199px) { :root { --sys-section-y: 128px; } }
@media (max-width: 839px)  { :root { --sys-section-y: 96px; --sys-nav-height: 64px; --sys-radius-card: 12px; --sys-radius-tile: 12px; --sys-radius-media: 12px; } }

/* Dark: the site's existing dark palette, mapped to the same roles. */
:root[data-theme="dark"] {
  --sys-bg: #0E0F13;
  --sys-surface: #17181D;
  --sys-hero: #8E9099;          /* 6.1:1 */
  --sys-emphasis: #FFFFFF;
  --sys-heading: #ECEDF1;
  --sys-ink: #ECEDF1;
  --sys-secondary: #A3A4AE;     /* 7.9:1 */
  --sys-supporting: #A3A4AE;
  --sys-accent: #BEDEFF;
  --sys-rule: #2A2C33;
  --sys-rule-strong: #4A4D57;
  --sys-slash: #4A4C55;
  --sys-tint: #1C1E24;
  --sys-media-bg: #17181D;
  --sys-band: #15161B;
 
 
  --sys-footer-bg: #1A1C22;
  --sys-footer-dim: #8E9099;
  --sys-footer-rule: rgba(255, 255, 255, 0.14);
  --sys-menu-bg: #24262E;
  --sys-menu-caption: #A3A4AE;
  --sys-menu-highlight: rgba(255, 255, 255, 0.08);
  --sys-grid: rgba(255, 255, 255, 0.11);
  --sys-scrim: rgba(0, 0, 0, 0.78);
  --sys-modal-bg: #1E2028;       /* a lifted surface, clearly apart from page and scrim */
  --sys-nav-scrolled: rgba(14, 15, 19, 0.85);
  --sys-util-bg: #2A2C34; --sys-util-border: #5A5D69; --sys-util-fg: #B8B9C2; --sys-util-hover: #45474E;
}
/* Bright, Racing and Duke Dog (launch modes, October 2026). The Round 10
   study palettes, unchanged. Each fills the roles the study left out: a band
   one step DARKER than the page (light text gains contrast on it), the modal
   on the page colour and a translucent nav.
   AA (measured): white on page 8.1 / 8.0 / 13.2, accent on page 4.9 / 6.1 /
   7.6, accent on band 6.0 / 7.6 / 8.5, white on band 9.9 / 9.9 / 14.9. */
:root[data-theme="bright"] {
  --sys-bg: #0946B8; --sys-surface: #0A4CC6; --sys-hero: #8FD0FF; --sys-emphasis: #FFFFFF; --sys-heading: #8FD0FF; --sys-ink: #FFFFFF;
  --sys-secondary: #8FD0FF; --sys-supporting: #FFFFFF; --sys-accent: #8FD0FF; --sys-rule: rgba(143, 208, 255, 0.3); --sys-rule-strong: rgba(143, 208, 255, 0.45);
  --sys-slash: rgba(143, 208, 255, 0.45); --sys-tint: rgba(143, 208, 255, 0.14); --sys-media-bg: #0A4CC6; --sys-footer-bg: #062F7E;
  --sys-footer-dim: #8FD0FF; --sys-menu-bg: #062F7E; --sys-menu-caption: #8FD0FF; --sys-grid: rgba(143, 208, 255, 0.24);
  --sys-band: #073B9C; --sys-modal-bg: #0946B8;
  --sys-util-bg: #2B60C2; --sys-util-border: #6B90D4; --sys-util-fg: #CDEAFF; --sys-util-hover: #4976CB;
  --sys-nav-scrolled: rgba(9, 70, 184, 0.88); --sys-menu-highlight: rgba(143, 208, 255, 0.14);
}
:root[data-theme="racing"] {
  --sys-bg: #0B5D3B; --sys-surface: #0D6843; --sys-hero: #FFE04D; --sys-emphasis: #FFFFFF; --sys-heading: #FFE04D; --sys-ink: #FFFFFF;
  --sys-secondary: #FFE04D; --sys-supporting: #FFFFFF; --sys-accent: #FFE04D; --sys-rule: rgba(255, 224, 77, 0.26); --sys-rule-strong: rgba(255, 224, 77, 0.4);
  --sys-slash: rgba(255, 224, 77, 0.45); --sys-tint: rgba(255, 224, 77, 0.1); --sys-media-bg: #0D6843; --sys-footer-bg: #073F28;
  --sys-footer-dim: #FFE04D; --sys-menu-bg: #073F28; --sys-menu-caption: #FFE04D; --sys-grid: rgba(255, 224, 77, 0.2);
  --sys-band: #094D31; --sys-modal-bg: #0B5D3B;
  --sys-util-bg: #2D7456; --sys-util-border: #6D9E89; --sys-util-fg: #FFF1AF; --sys-util-hover: #4A876E;
  --sys-nav-scrolled: rgba(11, 93, 59, 0.88); --sys-menu-highlight: rgba(255, 224, 77, 0.12);
}
:root[data-theme="duke"] {
  --sys-bg: #450084; --sys-surface: #520098; --sys-hero: #FFB627; --sys-emphasis: #FFFFFF; --sys-heading: #FFB627; --sys-ink: #FFFFFF;
  --sys-secondary: #FFB627; --sys-supporting: #FFFFFF; --sys-accent: #FFB627; --sys-rule: rgba(255, 182, 39, 0.26); --sys-rule-strong: rgba(255, 182, 39, 0.4);
  --sys-slash: rgba(255, 182, 39, 0.45); --sys-tint: rgba(255, 182, 39, 0.1); --sys-media-bg: #520098; --sys-footer-bg: #2E005A;
  --sys-footer-dim: #FFB627; --sys-menu-bg: #2E005A; --sys-menu-caption: #FFB627; --sys-grid: rgba(255, 182, 39, 0.2);
  --sys-band: #3A0070; --sys-modal-bg: #450084;
  --sys-util-bg: #5F2495; --sys-util-border: #8F66B5; --sys-util-fg: #FFDE9E; --sys-util-hover: #7543A4;
  --sys-nav-scrolled: rgba(69, 0, 132, 0.88); --sys-menu-highlight: rgba(255, 182, 39, 0.12);
}

/* The older page tokens (--color-*: case studies, About, shared components)
   follow the active mode's roles, so every page changes with one switch and
   nothing keeps a Classic colour. Brand --color-blue stays the brand fill. */
:root[data-theme="bright"],
:root[data-theme="racing"],
:root[data-theme="duke"] {
  color-scheme: dark;
  --color-bg: var(--sys-bg);
  --color-surface: var(--sys-band);
  --color-ink: var(--sys-ink);
  --color-gray: var(--sys-secondary);
  --color-gray-2: var(--sys-secondary);
  --color-gray-3: var(--sys-rule);
  --color-border: var(--sys-rule);
  --color-rule: var(--sys-rule);
  --color-bg-gray: var(--sys-band);
  --color-bg-blue: var(--sys-band);
  --color-blue-gray: var(--sys-supporting);
  --color-slate: var(--sys-secondary);
  --color-blue-text: var(--sys-accent);
  --color-light-blue: var(--sys-rule);
  --color-light-blue-50: var(--sys-band);
  --color-light-blue-100: var(--sys-band);
  --color-band: var(--sys-band);
  --color-band-blue: var(--sys-band);
  --color-things-bg: var(--sys-band);
  --color-things-rule: var(--sys-rule);
  --color-things-control-bg: var(--sys-band);
  --color-things-control-border: var(--sys-rule-strong);
  --color-tile-bg: var(--sys-band);
  --color-tile-border: var(--sys-rule);
  --color-page-tint: var(--sys-bg);
  --color-grid-line: var(--sys-grid);
  --color-control-bg: var(--sys-band);
  --color-control-fg: var(--sys-ink);
  --color-nav-scrolled: var(--sys-nav-scrolled);
  --shadow-card: 0 4px 16px rgba(0, 0, 0, 0.3);
}

/* All duration tokens collapse to ~0 under reduced motion. Every transition
   in the codebase should reference var(--duration-*) rather than a literal
   number so this one override is enough to strip motion sitewide. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 0.01ms;
    --duration-base: 0.01ms;
    --duration-slow: 0.01ms;
  }
}
