/**
 * Fluid Theme - Design Tokens
 * @layer tokens
 *
 * Three kinds of rule, in this order:
 *  1. KNOBS (the first :root rule, knobs only): the values a site, or an AI
 *     editing a site, is meant to change. Set them on :root in the site's
 *     own stylesheet (`themes` layer) or the stack's injected tokens.
 *  2. SCALES (a plain :root rule): type, space, radius, motion, shadow and
 *     z-index steps the knobs and the components draw on.
 *  3. THE ROLE SCOPE: every colour role, declared once, on :root AND on each
 *     dark band (.section[data-bg="inverse"], .hero[data-theme="dark"],
 *     .site-footer[data-dark]) and on the nav, inverse by default (not
 *     data-bg="plain" or transparent).
 *     The build lowers light-dark() to variables that resolve where a role
 *     is declared, so a role declared only on :root would not flip on a band
 *     that sets color-scheme: dark. Declaring the roles on the band too
 *     re-resolves the same light-dark() values there.
 *
 * Colour is OKLCH, derived from --accent and --neutral-tint. Dark mode follows
 * the OS; <html data-theme="light"> or "dark" overrides it (read on <html>).
 */

@layer tokens {
  :root {
    color-scheme: light dark;

    /* ========================================
       KNOBS
       ======================================== */

    /* --- Colour ---
       --accent       the brand colour as a FILL (primary button, accent-strong
                      band, active marks). Any OKLCH colour; a spice, never a
                      default background.
       --on-accent    text ON an accent fill: white below L 0.575, near black
                      above. An accent between L 0.55 and 0.60 clears 4.5:1
                      with neither for some hues: avoid that band or set this.
       --accent-ink   the accent as TEXT and focus ring (derived; it lives in
                      the role scope below so it flips on dark bands).
       --neutral-tint the colour the greys lean toward. Only its hue and chroma
                      are used; surfaces set their own lightness. */
    --accent: oklch(42% 0.15 22);          /* deep oxblood; white on it ≈ 8.5:1 */
    --on-accent: oklch(from var(--accent) clamp(0, (0.575 - l) * 1000, 1) 0 0);
    --neutral-tint: oklch(50% 0.01 75);    /* warm paper */

    /* --- Type ---
       --font-heading  the main face knob: display, h1-h3, lede, card titles,
                       stat numerals, nav brand. Newsreader when the fonts file
                       (dist/fluid-fonts.min.css) is linked; a system serif without it.
       --font-display  the display face; follows --font-heading. Set it only
                       when the display face differs from the heading face.
       --font-body     text, h4-h6, labels, nav links, buttons, forms, tables.
       --text-min / --text-max  body size at 360px and at 1440px, in rem
                       (unitless); every step of the scale is built on them.
       --type-ratio    the desktop scale ratio (phones use min(1.25, ratio)).
       --weight-display  weight of display, h1 and h2 (h3 is +100, at most
                       700 unless the display is heavier).
       --weight-heading  (optional, no default) one weight for h2 and h3
                       instead of the display ladder; legacy-1x sets it.
       --h1-size, --h2-size, --h3-size  (optional, no default) a heading's
                       size outright, instead of its step; legacy-1x sets them.
       --display-max   the cap on a display headline's size. --fit 8 at
                       10rem fills an 80rem column exactly, so the cap and
                       --container-content agree; a headline straight in a
                       .content-grid fits the reading column instead.
       --measure       the reading width of prose (58ch is about 72
                       characters of the body face).
       --hero-headline-size  has NO default in v2: .display and .hero__headline
                       fit their column (--fit). Setting it on :root still wins. */
    --font-heading: "Newsreader Variable", "Newsreader Fallback", "Iowan Old Style", "Sitka Heading",
                    Charter, "Palatino Linotype", "URW Palladio L", P052, Georgia, serif;
    --font-display: var(--font-heading);
    --font-body: "Schibsted Grotesk Variable", "Schibsted Fallback", "Helvetica Neue",
                 "Segoe UI Variable Text", "Arial Nova", "Nimbus Sans", Arial, sans-serif;
    --text-min: 1.0625;       /* 17px */
    --text-max: 1.25;         /* 20px */
    --type-ratio: 1.414;
    --weight-display: 400;
    --display-max: 10rem;
    --measure: 58ch;

    /* --- Shape --- */
    --radius-card: 0;
    --radius-control: 0;      /* buttons, inputs, selects, nav links, tabs, badges */
    --radius-pill: 9999px;    /* chips, data-pill buttons */
    --border-width: 1px;
    --shadow-style: 0;        /* 0 = none, 1 = soft, 2 = hard (offset, no blur) */
    --shadow-offset: 4px;     /* how far a hard shadow sits from its box */

    /* --- Space --- */
    --space-section: var(--space-2xl);   /* block padding of a band: 72 → 160px */
    /* --space-gutter is the 1.x knob: the page edge on BOTH sides together.
       Each side gets half of it, never less than 3vi (--page-edge). */
    --space-gutter: clamp(2.5rem, 1rem + 6.6667vi, 7rem);   /* 40 → 112px, so 20 → 56px a side */
    --container-content: 80rem;
    --rail: 0rem;   /* start-side label track of .content-grid; widen it to hang labels */

    /* --- Motion --- (speed per element: data-motion="reduced|slow|fast") */
    --motion-base: 320ms;

    /* The inverse band's paint, resolved here on purpose (a band cannot
       resolve its own background from its flipped roles). */
    --band-inverse: light-dark(
      oklch(from var(--neutral-tint) 0.17 c h),
      oklch(from var(--neutral-tint) 0.09 c h)
    );
  }

  :root {
    font-synthesis: none;
    font-kerning: normal;
    font-optical-sizing: auto;

    /* ========================================
       TYPOGRAPHY
       ======================================== */

    --font-system: system-ui, -apple-system, "Segoe UI", Roboto,
                   "Helvetica Neue", Arial, sans-serif;
    --font-serif: "Iowan Old Style", "Palatino Linotype", Palatino,
                  Georgia, serif;
    --font-mono: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace;

    /* The scale: one generator, one knob. Fluid from 360px to 1440px, flat
       outside. Phones use min(1.25, --type-ratio), desktops --type-ratio.
       Every value keeps a rem term, so zoom works (WCAG 1.4.4). Steps 0-4
       stay within max <= 2.5 × min; 5 and 6 are display-only.

       Resolved at the default ratio 1.414 (px; phones use 1.25):
         token      360px   1440px  used for
         --step--2   13      13     label voice, legal
         --step--1   14      14     caption, meta, TOC
         --step-0    17      20     body
         --step-1    21.3    28.3   lede, h3, card title, blockquote
         --step-2    26.6    40     h2 in prose
         --step-3    33.2    56.5   section heading, pull quote
         --step-4    41.5    80     h1, stat numeral, display floor
         --step-5    51.9    113    large display
         --step-6    64.8    160    the biggest display
       At --type-ratio 1.25 the 1440px column is 20/25/31.3/39.1/48.8/61/76.3.
       Do not register these (@property): they hold vi and must stay unresolved. */
    --_r: min(1.25, var(--type-ratio));     /* phone ratio; never above the desktop one */
    --_lo: var(--text-min);                 /* body at 360px, in rem */
    --_hi: var(--text-max);                 /* body at 1440px, in rem */
    --_t: calc((100vi - 22.5rem) / 67.5);   /* 0 at 360px, 1rem at 1440px */
    --step--2: 0.8125rem;
    --step--1: 0.875rem;
    --step-0: clamp(calc(var(--_lo) * 1rem), calc(var(--_lo) * 1rem + (var(--_hi) - var(--_lo)) * var(--_t)), calc(var(--_hi) * 1rem));
    --step-1: clamp(
      calc(var(--_lo) * pow(var(--_r), 1) * 1rem),
      calc(var(--_lo) * pow(var(--_r), 1) * 1rem + (var(--_hi) * pow(var(--type-ratio), 1) - var(--_lo) * pow(var(--_r), 1)) * var(--_t)),
      calc(var(--_hi) * pow(var(--type-ratio), 1) * 1rem));
    --step-2: clamp(
      calc(var(--_lo) * pow(var(--_r), 2) * 1rem),
      calc(var(--_lo) * pow(var(--_r), 2) * 1rem + (var(--_hi) * pow(var(--type-ratio), 2) - var(--_lo) * pow(var(--_r), 2)) * var(--_t)),
      calc(var(--_hi) * pow(var(--type-ratio), 2) * 1rem));
    --step-3: clamp(
      calc(var(--_lo) * pow(var(--_r), 3) * 1rem),
      calc(var(--_lo) * pow(var(--_r), 3) * 1rem + (var(--_hi) * pow(var(--type-ratio), 3) - var(--_lo) * pow(var(--_r), 3)) * var(--_t)),
      calc(var(--_hi) * pow(var(--type-ratio), 3) * 1rem));
    --step-4: clamp(
      calc(var(--_lo) * pow(var(--_r), 4) * 1rem),
      calc(var(--_lo) * pow(var(--_r), 4) * 1rem + (var(--_hi) * pow(var(--type-ratio), 4) - var(--_lo) * pow(var(--_r), 4)) * var(--_t)),
      calc(var(--_hi) * pow(var(--type-ratio), 4) * 1rem));
    --step-5: clamp(
      calc(var(--_lo) * pow(var(--_r), 5) * 1rem),
      calc(var(--_lo) * pow(var(--_r), 5) * 1rem + (var(--_hi) * pow(var(--type-ratio), 5) - var(--_lo) * pow(var(--_r), 5)) * var(--_t)),
      calc(var(--_hi) * pow(var(--type-ratio), 5) * 1rem));
    --step-6: clamp(
      calc(var(--_lo) * pow(var(--_r), 6) * 1rem),
      calc(var(--_lo) * pow(var(--_r), 6) * 1rem + (var(--_hi) * pow(var(--type-ratio), 6) - var(--_lo) * pow(var(--_r), 6)) * var(--_t)),
      calc(var(--_hi) * pow(var(--type-ratio), 6) * 1rem));

    /* Legacy names, still read by consumers. xs-lg follow the new scale;
       xl-5xl keep their 1.x values so UI and admin text does not drift
       (headings use --step-*). */
    --font-size-xs: var(--step--2);
    --font-size-sm: var(--step--1);
    --font-size-base: var(--step-0);
    --font-size-lg: clamp(1.1875rem, 1.125rem + 0.2778vi, 1.375rem);
    --font-size-xl: clamp(1.25rem, 1.12rem + 0.63vw, 1.5rem);
    --font-size-2xl: clamp(1.5rem, 1.29rem + 1.04vw, 1.875rem);
    --font-size-3xl: clamp(1.75rem, 1.43rem + 1.61vw, 2.375rem);
    --font-size-4xl: clamp(2rem, 1.5rem + 2.5vw, 3rem);
    --font-size-5xl: clamp(2.25rem, 1.5rem + 3.75vw, 3.75rem);

    --leading-none: 1;
    --leading-tight: 1.2;
    --leading-snug: 1.35;
    --leading-normal: 1.65;
    --leading-relaxed: 1.8;
    --leading-body: 1.6;
    --leading-heading: calc(1em + 0.2rem);   /* tightens as size grows: 1.11 at 28px, 1.02 at 160px */

    --tracking-tight: -0.025em;
    --tracking-normal: -0.01em;
    --tracking-wide: 0.04em;
    --tracking-wider: 0.05em;
    --tracking-display: -0.03em;
    --tracking-heading: -0.015em;
    --tracking-caps: 0.14em;

    --weight-light: 350;
    --weight-normal: 400;
    --weight-medium: 500;
    --weight-semibold: 600;
    --weight-bold: 700;
    --_dark-weight: 0;   /* 30 in dark mode and on dark bands: thin strokes survive light-on-dark */


    /* ========================================
       SPACING
       Fixed 4px steps for components; fluid steps (360 → 1440px) for layout.
       ======================================== */

    --space-0-5: 0.125rem;   /* 2px */
    --space-1: 0.25rem;      /* 4px */
    --space-1-5: 0.375rem;   /* 6px */
    --space-2: 0.5rem;       /* 8px */
    --space-3: 0.75rem;      /* 12px */
    --space-4: 1rem;         /* 16px */
    --space-5: 1.25rem;      /* 20px */
    --space-6: 1.5rem;       /* 24px */
    --space-8: 2rem;         /* 32px */
    --space-10: 2.5rem;      /* 40px */
    --space-12: 3rem;        /* 48px */
    --space-16: 4rem;        /* 64px */
    --space-20: 5rem;        /* 80px */
    --space-24: 6rem;        /* 96px */

    --space-xs: clamp(0.5rem, 0.4583rem + 0.1852vi, 0.625rem);    /*  8 → 10 */
    --space-s: clamp(0.75rem, 0.6667rem + 0.3704vi, 1rem);        /* 12 → 16 */
    --space-m: clamp(1.25rem, 1.0833rem + 0.7407vi, 1.75rem);     /* 20 → 28 */
    --space-l: clamp(2rem, 1.6667rem + 1.4815vi, 3rem);           /* 32 → 48 */
    --space-xl: clamp(3rem, 2.3333rem + 2.963vi, 5rem);           /* 48 → 80 */
    --space-2xl: clamp(4.5rem, 2.6667rem + 8.1481vi, 10rem);      /* 72 → 160 */
    /* Per side, everywhere: half the gutter knob, with a 3vi floor (so at
       1440px a gutter under ~86px total has no effect). */
    --page-edge: max(var(--space-gutter) / 2, 3vi);


    /* ========================================
       CONTAINERS
       ======================================== */

    --container-sm: 32rem;     /* 512px */
    --container-md: 48rem;     /* 768px */
    --container-lg: 64rem;     /* 1024px */
    --container-xl: 80rem;     /* 1280px */
    --container-2xl: 96rem;    /* 1536px */
    --container-prose: var(--measure);


    /* MOTION: the durations are in their own rule below (data-motion). */
    --ease-fluid: cubic-bezier(0.33, 0, 0.2, 1);
    --ease-settle: cubic-bezier(0.22, 1, 0.36, 1);


    /* ========================================
       RADIUS SCALE
       The steps follow the knobs; --radius-full stays for true circles
       (avatars, radio buttons, dots, spinners).
       ======================================== */

    --radius-sm: var(--radius-control);
    --radius-md: var(--radius-control);
    --radius-lg: var(--radius-card);
    --radius-xl: var(--radius-card);
    --radius-full: 9999px;

    --border-width-thick: calc(var(--border-width) * 2);
    /* Every focus outline: var(--focus-ring-width) solid var(--color-focus).
       Only the width is a token: the colour must resolve where it is used,
       so a band that re-points --color-focus (accent-strong) is followed. */
    --focus-ring-width: 2px;


    /* ========================================
       SHADOWS
       --shadow-style picks the family: each step is a soft (blurred) part
       scaled by --_soft plus a hard (offset) part scaled by --_hard, so
       0 (the v2 default) turns both off, 1 is soft only and 2 is hard only.
       ======================================== */

    --_soft: clamp(0, min(var(--shadow-style), 2 - var(--shadow-style)), 1);
    --_hard: clamp(0, var(--shadow-style) - 1, 1);
    --shadow-color: oklch(from var(--neutral-tint) 0.22 calc(c * 7) h);
    --_hard-2: calc(var(--shadow-offset) * var(--_hard));

    /* v2 reads only --shadow-md (the elevated card; compare.css), so
       --shadow-style changes only that. The other 1.x steps had no reader
       in core and were removed (base v2): --shadow-xs, --shadow-sm,
       --shadow-lg, --shadow-xl, --shadow-glow, --_hard-1, --_hard-3. A page
       that still reads one gets no shadow, as it did at --shadow-style 0. */
    --shadow-md:
      0 4px 8px oklch(from var(--shadow-color) l c h / calc(0.04 * var(--_soft))),
      0 8px 20px oklch(from var(--shadow-color) l c h / calc(0.07 * var(--_soft))),
      var(--_hard-2) var(--_hard-2) 0 var(--_hard-color);
    --_hard-color: light-dark(
      oklch(from var(--neutral-tint) 0.18 c h),
      oklch(from var(--neutral-tint) 0.45 c h)
    );


    /* ========================================
       Z-INDEX
       ======================================== */

    --z-base: 0;
    --z-raised: 1;
    --z-dropdown: 1000;
    --z-sticky: 1100;
    --z-overlay: 1200;
    --z-modal: 1300;
    --z-popover: 1400;
    --z-toast: 1500;
    --z-tooltip: 1600;
    --z-max: 9999;
  }


  /* ========================================
     COLOUR ROLES: THE ROLE SCOPE
     Every role is declared here, once. To add a dark surface later, add its
     selector here and to the band rule below; nothing else changes.
     ======================================== */

  :root,
  :is(.section, section)[data-bg="inverse"],
  .hero[data-theme="dark"],
  .site-footer[data-dark],
  .nav:not([data-bg="plain"], [data-variant="transparent"]), .nav[data-bg="inverse"] {
    --black: oklch(0% 0 0);
    --white: oklch(100% 0 0);

    /* Dark: lifted to L 0.78 with the chroma capped, so a deep accent
       reads as a dusty tint of itself, not salmon. */
    --accent-ink: light-dark(
      oklch(from var(--accent) min(l, 0.45) c h),
      oklch(from var(--accent) max(l, 0.78) min(c, 0.08) h)
    );

    --color-text: light-dark(
      oklch(from var(--neutral-tint) 0.17 c h),
      oklch(from var(--neutral-tint) 0.93 c h)
    );
    --color-text-muted: light-dark(
      oklch(from var(--neutral-tint) 0.44 c h),
      oklch(from var(--neutral-tint) 0.74 c h)
    );
    --color-text-subtle: light-dark(
      oklch(from var(--neutral-tint) 0.48 c h),
      oklch(from var(--neutral-tint) 0.68 c h)
    );

    --color-background: light-dark(
      oklch(from var(--neutral-tint) 0.99 calc(c * 0.75) h),
      oklch(from var(--neutral-tint) 0.145 calc(c * 1.5) h)
    );
    --color-surface: light-dark(
      oklch(from var(--neutral-tint) 0.955 c h),
      oklch(from var(--neutral-tint) 0.19 calc(c * 1.5) h)
    );
    --color-surface-raised: light-dark(
      oklch(from var(--neutral-tint) 1 calc(c * 0.4) h),
      oklch(from var(--neutral-tint) 0.22 calc(c * 1.5) h)
    );

    /* --color-border is decoration (hairlines); --color-border-strong is ink:
       rules that mean something, and field edges. */
    --color-border: light-dark(
      oklch(from var(--neutral-tint) 0.86 c h),
      oklch(from var(--neutral-tint) 0.30 calc(c * 1.75) h)
    );
    --color-border-subtle: light-dark(
      oklch(from var(--neutral-tint) 0.92 calc(c * 0.75) h),
      oklch(from var(--neutral-tint) 0.22 calc(c * 1.5) h)
    );
    --color-border-strong: light-dark(
      oklch(from var(--neutral-tint) 0.17 c h),
      oklch(from var(--neutral-tint) 0.93 c h)
    );

    /* A warm wash, not a pink: 7% (oklab: an oklch mix takes the
       near-neutral hue path; blue + warm paper gave olive). */
    --accent-subtle: color-mix(in oklab, var(--accent) 7%, var(--color-background));
    /* Hover moves the fill away from its text: darker under white text,
       lighter under dark text. */
    --accent-hover: oklch(from var(--accent) calc(l - 0.06 + 0.12 * clamp(0, (l - 0.575) * 1000, 1)) c h);

    /* The fill of a primary action (button, nav CTA). Light: the accent.
       Dark: only an accent darker than L 0.5 is lifted, to 0.5, so it
       stands off the near-black page and stays deep (0.62 turned oxblood
       salmon and moved every brand at 0.45-0.6). Its text is --on-accent
       in both schemes: white clears 4.5:1 on any hue at L 0.5, and an
       accent the lift leaves alone keeps the text its theme chose. */
    --accent-fill: light-dark(var(--accent), oklch(from var(--accent) max(l, 0.5) c h));
    --on-accent-fill: var(--on-accent);
    --accent-fill-hover: oklch(from var(--accent-fill) calc(l - 0.06 + 0.12 * clamp(0, (l - 0.575) * 1000, 1)) c h);

    --color-focus: var(--accent-ink);
    --color-selection: var(--accent-subtle);

    /* Feedback. The plain colour is for text and icons (it clears 4.5:1 on
       the page); -fill is a solid background, -on its text; -subtle a tint. */
    --color-success: light-dark(oklch(45% 0.13 145), oklch(78% 0.14 145));
    --color-warning: light-dark(oklch(48% 0.11 70), oklch(82% 0.13 80));
    --color-error: light-dark(oklch(48% 0.17 25), oklch(76% 0.13 25));
    --color-info: light-dark(oklch(46% 0.12 240), oklch(78% 0.10 240));

    --color-success-fill: oklch(48% 0.13 145);
    --color-warning-fill: oklch(80% 0.15 80);
    --color-error-fill: oklch(52% 0.19 25);
    --color-info-fill: oklch(50% 0.12 240);

    --color-success-on: var(--white);
    --color-warning-on: oklch(20% 0.03 70);
    --color-error-on: var(--white);
    --color-info-on: var(--white);

    --color-success-subtle: light-dark(oklch(95% 0.03 145), oklch(24% 0.05 145));
    --color-warning-subtle: light-dark(oklch(95% 0.04 70), oklch(24% 0.05 70));
    --color-error-subtle: light-dark(oklch(95% 0.03 25), oklch(24% 0.05 25));
    --color-info-subtle: light-dark(oklch(95% 0.02 240), oklch(24% 0.04 240));

    --color-rating: oklch(75% 0.18 85);   /* star glyphs; decorative, paired with text */

  }

  /* The dark bands: the scheme and the weight boost only. The paint and
     the text colour are in the layouts layer (src/fluid.css, the band
     rules); the hero and the footer paint their own. The page colour
     follows the band's paint, so fields, rings and --accent-subtle (mixed
     with --color-background) match the surface they sit on. */
  :is(.section, section)[data-bg="inverse"],
  .hero[data-theme="dark"],
  .site-footer[data-dark] {
    color-scheme: dark;
    --_dark-weight: 30;
    --color-background: var(--band-inverse);
  }

  /* The OS decides unless the page says otherwise. */
  :root[data-theme="light"] { color-scheme: light; }
  :root[data-theme="dark"] { color-scheme: dark; --_dark-weight: 30; }

  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) { --_dark-weight: 30; }
  }

  /* The nav is the page's other scheme by default, roles and all: a dark
     bar on a light page, a light bar on a dark one (not the band paint,
     which stays dark in dark mode). data-bg="plain" or a transparent bar
     keeps the page's colours; data-bg="inverse" still forces it. */
  .nav:not([data-bg="plain"], [data-variant="transparent"]), .nav[data-bg="inverse"] {
    color-scheme: dark;
    --_dark-weight: 30;
    /* Plain text and icons in the bar follow its ink (nav.css). */
    color: var(--nav-ink, var(--color-text));
    /* A band's button inversion (accent-strong) is not the bar's. */
    --_btn-color: initial;
    --_btn-bg: initial;
    --_btn-bg-hover: initial;
  }
  :root[data-theme="dark"] :is(.nav:not([data-bg="plain"], [data-variant="transparent"]), .nav[data-bg="inverse"]) { color-scheme: light; --_dark-weight: 0; }

  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) :is(.nav:not([data-bg="plain"], [data-variant="transparent"]), .nav[data-bg="inverse"]) { color-scheme: light; --_dark-weight: 0; }
  }

  /* Legacy floor. The roles derive from the knobs with relative colour
     (Safari 18, Firefox 128, Chrome 119). An older browser cannot compute
     them and would lose text and surface colours, so it gets plain light
     values with the default tint instead: readable, not themed. Dark bands
     go light with no paint. */
  @supports not (color: oklch(from red min(l, 0.5) c h)) {
    :root,
    :root[data-theme],
    :is(.section, section)[data-bg="inverse"],
    .hero[data-theme="dark"],
    .site-footer[data-dark],
    :root :is(.nav:not([data-bg="plain"], [data-variant="transparent"]), .nav[data-bg="inverse"]) {
      color-scheme: light;
      --color-text: oklch(17% 0.01 75);
      --color-text-muted: oklch(44% 0.01 75);
      --color-text-subtle: oklch(48% 0.01 75);
      --color-background: oklch(99% 0.0075 75);
      --color-surface: oklch(95.5% 0.01 75);
      --color-surface-raised: oklch(100% 0.004 75);
      --color-border: oklch(86% 0.01 75);
      --color-border-subtle: oklch(92% 0.0075 75);
      --color-border-strong: oklch(17% 0.01 75);
      --accent-ink: color-mix(in oklch, var(--accent) 45%, var(--color-text));
      --on-accent: var(--white);   /* a site with a light accent sets --on-accent itself */
      --accent-hover: color-mix(in oklch, var(--accent) 85%, var(--black));
      --accent-fill: var(--accent);
      --on-accent-fill: var(--on-accent);
      --accent-fill-hover: var(--accent-hover);
      --_dark-weight: 0;
    }

    :is(.section, section)[data-bg="inverse"],
    .hero[data-theme="dark"],
    .site-footer[data-dark] {
      --band-inverse: var(--color-background);
      background: none;
    }
  }


  /* ========================================
     USER PREFERENCES
     ======================================== */

  @media (prefers-contrast: more) {
    :root,
    :is(.section, section)[data-bg="inverse"],
    .hero[data-theme="dark"],
    .site-footer[data-dark],
    .nav:not([data-bg="plain"], [data-variant="transparent"]), .nav[data-bg="inverse"] {
      --color-border: var(--color-border-strong);
      --color-text-muted: var(--color-text);
      --color-text-subtle: var(--color-text);
    }
  }

  /* ========================================
     MOTION
     Every duration derives from --motion-base (fast ×0.73, slow ×1.37),
     times a speed (--_motion) set per page or section by data-motion:
     <html data-motion="slow"> or <section data-motion="fast">.
       reduced  0 (all durations 0ms)
       slow     1.5× (deliberate)
       fast     0.5× (snappy)
     Timing only; prefers-reduced-motion always wins. The durations are
     declared again on each [data-motion] element: a custom property
     inherits its resolved value, so a speed set lower down needs them
     recomputed where it is set.
     ======================================== */

  :root,
  [data-motion] {
    --duration-fast: calc(var(--motion-base) * 0.73 * var(--_motion, 1));
    --duration-normal: calc(var(--motion-base) * var(--_motion, 1));
    --duration-slow: calc(var(--motion-base) * 1.37 * var(--_motion, 1));
    --duration-slower: calc(var(--motion-base) * 1.73 * var(--_motion, 1));
  }

  [data-motion="reduced"] { --_motion: 0; }
  [data-motion="slow"] { --_motion: 1.5; }
  [data-motion="fast"] { --_motion: 0.5; }

  @media (prefers-reduced-motion: reduce) {
    :root,
    [data-motion] { --_motion: 0; }
  }


  /* PAGE TRANSITIONS are opt-in and not in this file. A site that wants
     cross-document transitions adds, in its own stylesheet:
       @media (prefers-reduced-motion: no-preference) {
         @view-transition { navigation: auto; }
       }
     and gets the browser's own short cross-fade. */
}
