/*
  Design tokens - palette revised 2026-07-05 at the user's request (the
  original muted Tract Blue/Green/Contrast Gold system read as too flat -
  "nothing makes the page stand out apart from content"). Confirmed
  through three rounds of a side-by-side comparison artifact, not
  guessed at in place. Every color/type decision elsewhere in the CSS
  should trace back to a variable defined here, not a new hard-coded
  value.

  Palette rationale (kept here, not just in memory, so it survives a
  fresh read of the codebase). Token NAMES and UI ROLES below are
  unchanged from the original web2 rationale; the actual hex VALUES were
  replaced 2026-07-25 with web3.1's real measured colors (see the
  "visible palette swap" note further down) - the role each token plays
  is the same, only which real color fills that role changed:
    --color-field-white   canvas/page background
    --color-bone-ink      primary ink - body text color
    --color-soft-tissue   muted/secondary text
    --color-navy-deep     primary UI chrome - nav bar, primary buttons, site anchor color
    --color-navy-mid      cranial axis (blue = brain, the conventional read); secondary UI, links
    --color-teal          spine axis - muted, grounded in real CSF-flow/myelin-contrast false-color imaging (not neon)
    --color-oxblood       pain axis - red = nociception/inflammation, an intuitive rather than arbitrary mapping
    --color-brass         NOT an axis color - hairline rules and small captions only, deliberately
                          low-contrast against the other accents so it never reads as a fourth "loud" color
                          (unchanged - no web3.1 equivalent needed, still does its job either way)

  Nav breakpoint is 1024px (see nav.css) - not a variable here because
  it's consumed inside @media, where custom properties can't be used.

  --- 2026-07-25: merge with web3.1's design system -----------------------
  Section 2 below (space/radius/shadow/blur/motion/opacity/grid/z-index)
  is new, ported from /var/www/shtml/web3.1/tokens.css. Only the *token
  system discipline* crossed over, not web3.1's own hues - the palette
  above stays web2's own (content/backend layer wins on substance per
  the merge decision). Shadow/idle-thread bases were recomputed from
  --color-bone-ink's own RGB, not copied from web3.1's ocean-950 numbers,
  so they sit correctly against *this* palette. z-index values were
  fitted against the real hardcoded numbers already live in nav.css
  (100/90/95) and consent.css (200) rather than importing web3.1's
  scale blind - see DECISIONS.md for the audit.

  --- 2026-07-25: axis-color reconciliation (Phase 5) ---------------------
  web3.1 deliberately retired a third decorative accent (Verdigris) for
  reading as "noisy" competing with Oxblood on the same page. That does
  NOT apply here: --color-navy-mid/--color-teal/--color-oxblood are
  data-model-driven (SpecialtyAxis::Cranial/Spine/Pain), consumed only on
  small bounded surfaces - hotspot fills, tag/chip borders, teaser-card
  rules (grep-audited across content.css/nav.css: zero decorative/
  page-wide usage found) - never a full-page accent the way web3.1's
  third color would have been. No hex values changed as a result: a
  direct RGB-distance check found --color-navy-mid is nearly identical to
  web3.1's --ocean-600 (deltaE-ish distance ~10 of ~441 max) and
  --color-teal sits in the same muted family as web3.1's retired
  --green-700/Verdigris (~33) - the two palettes had already converged on
  the same "Cranial=navy-blue, Spine=muted-teal" territory independently,
  so importing new numbers would trade a verified-close match for an
  unverified new one with no real benefit. Pain/--color-oxblood is
  unchanged, already doing double duty as both the Pain axis and the
  sitewide CTA/action color (see nav.css .locale-toggle button
  [aria-pressed] and content.css's CTA rules) - a precedent already in
  place before this merge, left as-is.

  --- 2026-07-25: visible palette swap (superseding the note above) ------
  The Phase 5 conclusion above was about whether web2's *existing* hex
  values needed retuning for internal harmony - they didn't, by measured
  distance. It did NOT mean the visible result should look identical to
  pre-merge web2, which is what actually shipped at first and is not what
  was wanted: the whole point of this merge is that web3.1's design
  system is the visible/UI basis. Every value in section 1 below (PALETTE)
  now holds web3.1's own real measured colors (Ocean ramp, retuned
  Verdigris, the mockup-measured Oxblood, the warm-paper neutral scale) -
  same token NAMES and UI ROLES as web2 always had (so every component
  file's var() references below needed zero changes), different actual
  colors. --color-bone-ink only ever serves as text color on every
  currently-live page (grep-confirmed - its one background use is in
  wayfinder.css, deferred/unhooked since Phase 4), so it was safe to
  match it to web3.1's own measured --text-display ink rather than a
  darker "ground" tone. Shadow and --thread-idle bases (section 6/12
  below) were recomputed again from this new ink RGB, same reasoning as
  Phase 1's original computation.
*/

/*
  EB Garamond + Commissioner (Phase 6) - self-hosted, replacing Alegreya/
  Noto Sans entirely (old files removed, not kept as a fallback chain).
  Downloaded 2026-07-25 directly from Google Fonts' css2 API using the
  exact family/weight/style spec web3.1's index.html requested
  (Commissioner wght@300;350;400;450;500;600;700, EB Garamond
  ital,wght@0,400;0,500;0,600;1,400), then re-hosted here - not run
  through a separate subsetting tool, since Google's own css2 response
  already splits each family into per-script @font-face blocks with
  their own unicode-range and woff2 URL; only the latin and greek blocks
  were kept (greek-ext/cyrillic/vietnamese/latin-ext dropped, matching
  the simpler two-script convention the old Alegreya/Noto Sans blocks
  already used here).

  Both normal styles are genuine variable fonts (confirmed by inspecting
  the downloaded files' fvar table: Commissioner wght 100-900,
  EB Garamond wght 400-800) - Google served the identical file for every
  discrete weight requested in one range, which is why one @font-face
  per script covers the whole 300-700 / 400-600 range instead of one
  rule per weight. EB Garamond italic has no variable axis (static,
  weight 400 only) - matches the single requested italic weight and
  Alegreya's old italic block's same static-single-weight shape.
*/
@font-face {
  font-family: 'EB Garamond';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  unicode-range: U+0000-00FF, U+2018-2019, U+2013-2014;
  src: url('../fonts/eb-garamond-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'EB Garamond';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  unicode-range: U+0370-03FF;
  src: url('../fonts/eb-garamond-greek.woff2') format('woff2');
}
@font-face {
  font-family: 'EB Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+2018-2019, U+2013-2014;
  src: url('../fonts/eb-garamond-italic-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'EB Garamond';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0370-03FF;
  src: url('../fonts/eb-garamond-italic-greek.woff2') format('woff2');
}
@font-face {
  font-family: 'Commissioner';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+2018-2019, U+2013-2014;
  src: url('../fonts/commissioner-latin.woff2') format('woff2');
}
@font-face {
  font-family: 'Commissioner';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0370-03FF;
  src: url('../fonts/commissioner-greek.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF;
  src: url('../fonts/ibm-plex-mono-400.woff2') format('woff2');
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0000-00FF;
  src: url('../fonts/ibm-plex-mono-500.woff2') format('woff2');
}

:root {
  /* --- 1. PALETTE - now holding web3.1's real measured colors (2026-07-25
     visible palette swap, see note above). Same token names/roles web2
     always had; only the hex values are web3.1's now. -------------------- */
  --color-field-white: #F4F4F2;   /* web3.1 --n-50, warm paper canvas */
  --color-field-raised: #EDEDEA;  /* web3.1 --n-100 */
  --color-bone-ink: #202A36;      /* web3.1 --text-display, measured ink */
  --color-ink-soft: #454F5A;      /* web3.1 --text-body */
  --color-soft-tissue: #6E7880;   /* web3.1 --text-muted */
  --color-tissue-line: rgba(110, 120, 128, 0.22);
  --color-navy-deep: #04101E;     /* web3.1 --ocean-950 */
  --color-navy-deep-wash: rgba(4, 16, 30, 0.08);
  --color-navy-deep-glass: rgba(4, 16, 30, 0.88); /* header "glass" scroll state - see nav.css */
  --color-navy-mid: #17384F;      /* web3.1 --ocean-700 */
  --color-navy-mid-wash: rgba(23, 56, 79, 0.09);
  --color-teal: #2E6F68;          /* web3.1 --green-700, retired Verdigris re-tuned for functional axis use (Phase 5) */
  --color-teal-wash: rgba(46, 111, 104, 0.09);
  --color-oxblood: #521522;       /* web3.1 --ox-700, measured primary-CTA fill */
  --color-oxblood-wash: rgba(82, 21, 34, 0.08);
  --color-brass: #856231;         /* unchanged - no web3.1 equivalent needed */

  /* --- 2. TYPE: families (font-display/font-body repointed to the merge's
     chosen faces once self-hosted - see Phase 6) ------------------------- */
  --font-display: 'EB Garamond', serif;
  --font-body: 'Commissioner', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', Consolas, monospace;

  /* --- 3. TYPE: fluid scale (mechanism unchanged from web2 - clamp(),
     not web3.1's fixed-step + @media override; bounds retuned toward
     web3.1's rendered sizes at each viewport extreme, display steps only -
     body/label/caption were already close and are left as-is. This is an
     approximation, not a measurement: verify visually before trusting it. */
  --fs-2xl: clamp(3rem, 2.2rem + 3.2vw, 4.5rem);      /* hero display, ~48px -> 72px */
  --fs-xl: clamp(2rem, 1.7rem + 1.6vw, 3rem);          /* large display, ~32px -> 48px */
  --fs-l: clamp(1.5rem, 1.3rem + 0.9vw, 2.25rem);      /* h1-equivalent, ~24px -> 36px */
  --fs-m: clamp(1.25rem, 1.15rem + 0.4vw, 1.5rem);     /* h3/h4-equivalent, ~20px -> 24px */
  --fs-body-l: clamp(1.1rem, 1.05rem + 0.2vw, 1.25rem);
  --fs-body: 1rem;
  --fs-body-s: 0.875rem;
  --fs-label: 0.72rem;
  --fs-mono: 0.8rem;

  /* --- 4. SPACE (ported as-is from web3.1) ------------------------------- */
  --s-0: 0;
  --s-1: 0.25rem;   /* 4   */
  --s-2: 0.5rem;    /* 8   */
  --s-3: 0.75rem;   /* 12  */
  --s-4: 1rem;      /* 16  */
  --s-5: 1.5rem;    /* 24  */
  --s-6: 2rem;      /* 32  */
  --s-7: 2.5rem;    /* 40  */
  --s-8: 3.5rem;    /* 56  */
  --s-9: 4.5rem;    /* 72  */
  --s-10: 6rem;     /* 96  */
  --s-11: 8rem;     /* 128 */
  --s-12: 11.25rem; /* 180 */
  --s-13: 15rem;    /* 240 */

  /* --- 5. RADIUS (ported as-is; web2's few existing radii, e.g. the
     .wayfinder 2px, are local exceptions on a dark instrument panel and
     are left alone rather than forced onto this scale) ------------------- */
  --r-xs: 4px;
  --r-sm: 8px;
  --r-md: 16px;    /* cards  */
  --r-lg: 24px;    /* images */
  --r-xl: 32px;
  --r-pill: 999px; /* buttons */

  /* --- 6. ELEVATION - layered only, never a single shadow. Base color
     recomputed from --color-bone-ink's own rgb(20,26,33), not copied from
     web3.1's ocean-950 numbers, so it sits correctly against this palette. */
  --shadow-1:
    0 1px 2px rgba(32,42,54,.04),
    0 2px 8px rgba(32,42,54,.045);
  --shadow-2:
    0 1px 2px rgba(32,42,54,.04),
    0 4px 10px rgba(32,42,54,.05),
    0 12px 28px rgba(32,42,54,.05);
  --shadow-3:
    0 2px 4px rgba(32,42,54,.05),
    0 10px 24px rgba(32,42,54,.07),
    0 28px 60px rgba(32,42,54,.08);
  --shadow-float:
    0 2px 6px rgba(32,42,54,.05),
    0 18px 40px rgba(32,42,54,.10),
    0 44px 90px rgba(32,42,54,.09);
  --shadow-overlay:
    0 1px 0 rgba(32,42,54,.05),
    0 20px 50px rgba(32,42,54,.12),
    0 60px 120px rgba(32,42,54,.10);

  /* --- 7. BLUR (ported as-is; not yet consumed anywhere, available for
     the re-skinned header's glass state in Phase 2) ----------------------- */
  --blur-xs: 4px;
  --blur-sm: 8px;
  --blur-md: 14px;
  --blur-lg: 22px;
  --blur-xl: 40px;

  /* --- 8. MOTION (ported as-is) ------------------------------------------ */
  --m-fast: 150ms;
  --m-normal: 280ms;
  --m-gentle: 500ms;
  --m-story: 900ms;
  --m-ambient: 20000ms;

  --ease-precision: cubic-bezier(.20, 0, 0, 1);
  --ease-human: cubic-bezier(.32, .72, 0, 1);
  --ease-editorial: cubic-bezier(.16, 1, .30, 1);
  --ease-neural: cubic-bezier(.65, 0, .35, 1);

  /* --- 9. OPACITY (ported as-is) ----------------------------------------- */
  --o-4: .04; --o-8: .08; --o-12: .12; --o-20: .20;
  --o-40: .40; --o-60: .60; --o-80: .80;

  /* --- 10. GRID (ported as-is) -------------------------------------------- */
  --container: 82.5rem;   /* 1320 */
  --container-narrow: 46rem;
  --gutter: var(--s-6);
  --margin-desktop: var(--s-10);
  --margin-tablet: var(--s-7);
  --margin-mobile: var(--s-5);

  /* --- 11. LAYERS - fitted against web2's real, already-live hardcoded
     z-index values rather than importing web3.1's scale blind:
       content.css inline elements : 1   (untouched, pre-existing)
       wayfinder tooltip           : 5   (untouched, pre-existing; component
                                           is unhooked from live pages in
                                           Phase 4 but the value stays valid)
       thread (new, Phase 3)       : 20  -- sits above page content, well
                                           below any nav/overlay chrome
       nav scrim                   : 90  (pre-existing, now named)
       nav panel                   : 95  (pre-existing, now named)
       site header                 : 100 (pre-existing, now named)
       consent banner              : 200 (pre-existing, now named; always
                                           topmost, unaffected by this scale) */
  --z-thread: 20;
  --z-nav-scrim: 90;
  --z-nav-panel: 95;
  --z-header: 100;
  --z-consent: 200;

  /* --- 12. SIGNATURE (Neural Thread, Phase 3) - live color repointed at
     web2's own oxblood, not web3.1's --ox-700; idle color derived from
     --color-bone-ink the same way the shadow base above is. --------------- */
  --thread-w: 0.75px;
  --thread-idle: rgba(32,42,54,.22);
  --thread-live: var(--color-oxblood);

  /* --- 13. SEMANTIC BRIDGE ALIASES - map web3.1-style semantic names onto
     web2's real hex values, so component CSS ported/rewritten in later
     phases can use familiar names instead of a selector-by-selector value
     hunt. --ground-cool is the one net-new approximated value (no existing
     web2 equivalent): a light navy-mid tint over field-white, ~5% mix,
     hand-computed - flag for a visual check, not measured. -------------- */
  --text-display: var(--color-bone-ink);
  --text-body: var(--color-ink-soft);
  --text-muted: var(--color-soft-tissue);
  --text-onDark: var(--color-field-white);
  --text-onDarkMuted: rgba(243, 245, 246, 0.7);

  --canvas: var(--color-field-white);
  --ground-warm: var(--color-field-raised);
  --ground-cool: #EBECEF;
  --ground-dark: var(--color-navy-deep);
  --surface: var(--color-field-raised);

  --line-hair: var(--color-tissue-line);
  --line-onDark: rgba(243, 245, 246, 0.16);

  --focus-ring: var(--color-oxblood);
}

/* specialty-axis color mapping - the single source of truth SpecialtyAxis::colorToken()
   points at conceptually; nav/wayfinder/content-tag CSS reads these classes
   rather than hard-coding a color per feature. Values retuned in Phase 5 -
   see DECISIONS.md for the Cranial/Ocean and Spine/Verdigris mapping. */
.axis-cranial { --axis-color: var(--color-navy-mid); --axis-wash: var(--color-navy-mid-wash); }
.axis-spine { --axis-color: var(--color-teal); --axis-wash: var(--color-teal-wash); }
.axis-pain { --axis-color: var(--color-oxblood); --axis-wash: var(--color-oxblood-wash); }

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

html {
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--color-field-white);
  color: var(--color-bone-ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

::selection {
  background: var(--color-navy-mid-wash);
  color: var(--color-bone-ink);
}

a {
  color: var(--color-navy-mid);
}

/* Visible keyboard focus throughout (PAGE.md accessibility requirement) -
   defined once here so no component needs to re-declare it. Oxblood
   rather than an axis color since focus rings need one unambiguous
   sitewide meaning, not one that changes per content axis. */
a:focus-visible,
button:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--color-oxblood);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/*
  Scroll-reveal system (reveal.js, IntersectionObserver-driven, per
  PAGE.md's vanilla-JS requirement). [data-reveal] is the opt-in marker
  any template can add to any element - not homepage-specific. Starts
  visible-by-default (progressive enhancement: content isn't hidden if
  JS fails to load) - reveal.js is what adds .js-reveal-ready, and only
  once that's present does the pre-reveal state actually apply.
  data-reveal-delay="1"/"2" staggers a second/third element slightly
  behind the first without needing per-element inline styles.
*/
.js-reveal-ready [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.js-reveal-ready [data-reveal-delay="1"] {
  transition-delay: 0.12s;
}
.js-reveal-ready [data-reveal-delay="2"] {
  transition-delay: 0.24s;
}
.js-reveal-ready [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .js-reveal-ready [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
