:root {
  color-scheme: dark;

  /* ── Fonts ───────────────────────────────────────────────────────────
     Oxanium is display-only. Its generated fallback carries
     size-adjust:103.86% and line-gap-override:24.07% — metrics drawn for
     72px headlines, previously spent on 12px footer links (66% of all type
     on the site is <=17px). Geist Sans carries running text; Geist_Mono was
     already imported, so the superfamily costs no extra download. */
  --font-sans: var(--font-geist-sans), var(--font-noto-jp), sans-serif;
  --font-display: var(--font-oxanium), var(--font-geist-sans), sans-serif;
  --font-mono: var(--font-geist-mono), ui-monospace, SFMono-Regular, Menlo,
    Consolas, monospace;

  /* ── Backgrounds ─────────────────────────────────────────────────────
     Was four tokens spanning 1.088:1 — perceptually one colour, which is
     why 25 radial glows had to carry section separation. On near-black you
     cannot win a contrast ratio between page bands and should not try:
     bands are separated by --section-y and one --border-subtle hairline,
     and the value range is spent on the card layer instead.
     --bg is UNCHANGED so the hero overlay literals stay in sync. */
  --bg: #0f0f11;           /* the page. one background. */
  --bg-deep: #0a0a0c;      /* footer + hero underlay only */
  --bg-section: var(--bg); /* was #0c0c10. one line unifies 10 consumers */
  --bg-raised: #1b1b20;    /* every card. ~1.12:1 over the page (was 1.007) */
  --bg-elevated: #24242a;  /* hover / focal card. ~1.11:1 over raised */

  /* ── Surfaces ────────────────────────────────────────────────────────
     Elevation comes from lightness, never shadow: rgba(0,0,0,0.25) over
     #0f0f11 darkens to at most ~1.02:1, below any viewing threshold. */
  --surface: var(--bg-raised);
  --surface-hi: var(--bg-elevated);
  --specular: inset 0 1px 0 rgba(255, 255, 255, 0.055);

  /* ── Text ──────────────────────────────────────────────────────────── */
  --text-primary: #ffffff;
  --text-secondary: #acacb4;
  --text-body: #b5b5bc;
  --text-tertiary: #8b8b93;
  --text-muted: #71717a;

  /* ── Brand ───────────────────────────────────────────────────────────
     Hues unchanged. Roles assigned:
       --orange  action       CTAs — the one thing to click
       --blue    information  links, focus ring
       --amber   label        every eyebrow on the site               */
  --blue: #059dff;
  --blue-soft: #6dc8ff;
  --orange: #ce6730;
  --orange-deep: #f2573f;
  --amber: #ffb66a;
  --rose: #c34a68;  /* role byline, e.g. the practitioner title on the homepage */
  /* Channels of --orange, so alpha stays free: rgba(var(--orange-rgb), 0.35).
     Kept in sync with --orange above — it was a separate, slightly different
     orange (245,128,57) before the palette was consolidated. */
  --orange-rgb: 206, 103, 48;

  /* ── Gradients ───────────────────────────────────────────────────────
     --gradient-brand had zero consumers; aliased rather than deleted so
     nothing can break. --gradient-accent survives on .reviewDotOn. */
  --gradient-accent: linear-gradient(90deg, var(--orange), var(--orange-deep));
  --gradient-brand: var(--gradient-accent); /* deprecated */

  /* ── Type scale ──────────────────────────────────────────────────────
     Replaces 60 ad-hoc font-sizes and 31 competing clamp() ramps. */
  --text-2xs: 0.6875rem;                          /* 11  micro labels    */
  --text-xs: 0.75rem;                             /* 12  eyebrows, meta  */
  --text-sm: 0.875rem;                            /* 14  nav, footer     */
  --text-base: 1rem;                              /* 16  UI, card body   */
  --text-md: 1.0625rem;                           /* 17  lead, prose     */
  --text-lg: 1.3125rem;                           /* 21  card titles     */
  --text-xl: clamp(1.5rem, 2.6vw, 1.875rem);      /* 24 -> 30            */
  --display-sm: clamp(1.625rem, 4vw, 2.375rem);   /* 26 -> 38  section h2 */
  --display-md: clamp(2.125rem, 6.5vw, 3.875rem); /* 34 -> 62  page h1    */
  --display-lg: clamp(2.5rem, 7vw, 4.75rem);      /* 40 -> 76  hero h1    */

  --leading-display: 1.05;  /* floor ~1.0: Oxanium ink extent is 0.963em */
  --leading-tight: 1.15;
  --leading-snug: 1.45;
  --leading-body: 1.7;
  --leading-prose: 1.78;

  /* No heading above 48px previously declared negative tracking. */
  --tracking-display: -0.022em;
  --tracking-heading: -0.012em;
  --tracking-eyebrow: 0.08em;  /* the value 5 of 6 page templates use */

  /* Measure in em so it survives any size or family change. Body measure
     previously ran 70ch..106ch on the same role. */
  --measure: 34em;        /* ~68ch  body copy                              */
  --measure-wide: 36em;   /* ~72ch  wider prose columns                    */
  --measure-tight: 22em;  /* ~44ch  headlines and leads. em-based, so this
                             holds the character count steady as display
                             sizes scale - 34em on a 30px headline would run
                             over 1000px.                                  */

  /* ── Space ───────────────────────────────────────────────────────────
     Replaces 21 gap values and 14 single-value paddings. */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;

  --rail: 1240px;   /* the one content rail — the Header's, adopted */
  --gutter: 20px;   /* floor. never step below it on mobile */
  --grid-gap: clamp(16px, 2.5vw, 24px);
  --card-pad: clamp(20px, 4.5vw, 28px);    /* every peer card in a grid  */
  --card-pad-lg: clamp(28px, 5vw, 40px);   /* full-width feature panels  */
  --card-pad-row: 16px;                    /* list rows, chips           */
  --section-y: clamp(72px, 9vw, 120px);    /* one rhythm, was 5 spellings */
  --block-y: var(--space-8);               /* region -> region in a page  */

  /* ── Borders ─────────────────────────────────────────────────────── */
  --border-subtle: rgba(255, 255, 255, 0.06);
  --border-default: rgba(255, 255, 255, 0.1);
  --border-strong: rgba(255, 255, 255, 0.2);

  /* ── Radii ───────────────────────────────────────────────────────────
     The site is square by design. Every scale step resolves to --radius so
     corners can never drift apart again; change --radius alone to round the
     whole site. --radius-full is included deliberately: pills and circles are
     squared too, so there is no second shape language. */
  --radius: 0px;
  --radius-sm: var(--radius);
  --radius-md: var(--radius);
  --radius-lg: var(--radius);
  --radius-xl: var(--radius);
  --radius-full: var(--radius);

  /* ── Elevation ───────────────────────────────────────────────────────
     One shadow, for things that genuinely float OVER content (mobile menu,
     dropdowns). Cards use --surface + --specular and never transition it. */
  --shadow-md: 0 2px 4px rgba(0, 0, 0, 0.55), 0 16px 34px rgba(0, 0, 0, 0.45);
  --shadow-sm: var(--shadow-md);  /* deprecated */
  --shadow-lg: var(--shadow-md);  /* deprecated */

  /* ── Motion ──────────────────────────────────────────────────────────
     cubic-bezier(0.25,0.1,0.25,1) IS the `ease` keyword — the old token was
     the browser default wearing a variable name. Mirrored in Motion.tsx. */
  --speed-fast: 0.16s;  /* colour, opacity, border — perceptual */
  --speed-base: 0.26s;  /* geometry — lifts, icon nudges        */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --lift: -4px;         /* the one hover lift, was six values.
                           apply via `translate`, NOT `transform`:
                           Framer Motion owns transform on Stagger nodes */

  /* ── Focus ─────────────────────────────────────────────────────────── */
  --focus-ring: var(--blue);

  /* Combined height of the chrome sitting above the hero: the black top bar
     (42px) plus the main header (72px). The hero subtracts this from 100svh so
     the landing view fills exactly one screen with no leftover gap and nothing
     pushed below the fold. Update here if either bar's padding changes. */
  --header-stack: 114px;
}

/* Header.module.css hides .headerTopBar at exactly this breakpoint, so the
   stack drops to the main header alone. Keep the two in sync. */
@media (max-width: 767px) {
  :root {
    --header-stack: 72px;
  }
}

/* Headings are the display face, tracked optically. Previously every heading
   fell through to the UA default weight and zero letter-spacing — the fastest
   visual tell between a designed headline and a developer's headline. */
h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-heading);
}

h1,
h2,
h3 {
  text-wrap: balance;
}

p,
li {
  text-wrap: pretty;
}

/* lucide emits stroke-width as a presentation attribute, so this single rule
   overrides all 63 call sites. At the library default of 2 in a 14-16px box
   the stroke is ~14% of the glyph, and icons visually outweigh their labels. */
.lucide {
  stroke-width: 1.5px;
}

.grecaptcha-badge {
  z-index: -1;
}

html,
body {
  max-width: 100vw;
  overflow-x: hidden;
}

body {
  color: var(--text-primary);
  background: var(--bg);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

a {
  color: inherit;
  text-decoration: none;
}

:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 3px;
  border-radius: var(--radius);
}

/* No prefers-reduced-motion handling anywhere in this site, by decision:
   motion is treated as core to the brand and plays for every visitor,
   including under OS "reduce motion" and battery-saver modes. Do not
   reintroduce a reduced-motion gate here or in any component. */
