/* ==========================================================================
   app.css: the design system ("Editorial atelier")
   Warm paper, deep ink, one rationed ember accent, and a measuring tape wherever
   something is counted. Serif for headlines, grotesk for actions, mono for numbers.

   Rules for page builders
   * Use tokens (var(--...)) only. No raw hex outside the token blocks below.
   * Light and dark are both driven by tokens: html[data-theme="light|dark|system"].
   * Put an .inverse class on a panel to flip it (ink on a light page, paper on a
     dark page). Tokens are re-scoped inside, so components just work.
   * Ember (--accent*) means "act here" or "this is what you pay". Nothing else.
   * The living reference is /styleguide (ENVIRONMENT=development).

   Contents
     1 Fonts          2 Tokens         3 Base and reset    4 Type
     5 Layout         6 Rules, ruler   7 Brand             8 Buttons, links, icons
     9 Tags, badges  10 Cards         11 Forms            12 Alerts, toasts
    13 Tables        14 Stats         15 Meters (tape)    16 Tabs, segmented
    17 Code, keys    18 Empty, pager, breadcrumb, dialog, tooltip, skeleton
   18b Menu, stepper, disclosure, toolbar
    19 Lists: dl, receipt, timeline   20 Site header/footer
    21 App shells (admin, portal)     22 Docs layout      23 Charts
    24 Utilities     25 Motion, print, forced colors
   ========================================================================== */

/* ==== 1. Fonts (served from /static/fonts, SIL Open Font License 1.1, see LICENSES.md there) ==== */
@font-face {
  font-family: "Fraunces";
  src: url("../fonts/fraunces-latin-opsz-normal.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Fraunces";
  src: url("../fonts/fraunces-latin-opsz-italic.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Schibsted Grotesk";
  src: url("../fonts/schibsted-grotesk-latin-wght-normal.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
/* French narrow no-break space (U+202F: "11,5 M", "41 %", "9 091 637"). None of the brand fonts has it, so
   the browser drew it from a system font (a 0.08 em sliver, gone after negative letter-spacing). nnbsp.woff2
   holds one blank 0.2 em glyph. Each rule repeats its family's weight and style descriptors exactly: with
   different ones, Chrome would match this U+202F-only face and draw every other character in a system font. */
@font-face {
  font-family: "Schibsted Grotesk";
  src: url("../fonts/nnbsp.woff2") format("woff2");
  font-weight: 400 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+202F;
}
@font-face {
  font-family: "Fraunces";
  src: url("../fonts/nnbsp.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+202F;
}
@font-face {
  font-family: "Fraunces";
  src: url("../fonts/nnbsp.woff2") format("woff2");
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+202F;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/nnbsp.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+202F;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("../fonts/nnbsp.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
  unicode-range: U+202F;
}

/* ==== 2. Tokens ==== */
/* Contrast (WCAG 2.x, measured by script, bg / surface / surface-2):
     light text 15.0 / 16.2 / 13.6   muted 6.8 / 7.3 / 6.1   subtle 4.7 / 5.1 / 4.2   accent 5.2 / 5.7 / 4.7
     dark  text 15.4 / 14.4 / 13.0   muted 7.8 / 7.3 / 6.6   subtle 5.5 / 5.1 / 4.6   accent 6.6 / 6.2 / 5.6
     Three text tiers in both themes: muted / subtle differ by 1.44:1 (light) and 1.42:1 (dark).
     Subtle text sits on bg or surface only (not on surface-2 in light).
     border-input (non-text, WCAG 1.4.11) light 3.4 / 3.7, dark 3.8 / 3.6
     chart-bar vs surface light 7.2, dark 6.5; chart-bar-muted light 3.1, dark 3.4 (inverse panels >= 3.3)
     text on accent-fill light 4.7, dark 6.1; status text on its soft tint >= 5.0 in both themes
     Ember vs danger (CIE76 dE): text light 33, dark 35; soft tints light 17, dark 19. Danger is a
     cool crimson (light) / rose (dark) so an error never reads as the ember accent.
     --frame: the strong card frame (ink in light, a quiet line in dark). --edge-shade: scroll edges.
   Chart series (categorical, fixed order, validated for CVD with the dataviz validator):
     light worst adjacent CVD dE 10.4, normal 17.5; dark CVD 9.6, normal 17.5; all >= 3:1 on surface. */
:root {
  /* Font stacks */
  --font-display: "Fraunces", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
  --font-sans: "Schibsted Grotesk", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  /* Display tuning. Optical size is capped for big display text: at opsz above ~72 the
     hairline crossbar of "e" vanishes at 1x (the "Madc to mcasurc" defect). */
  --display-weight: 380;
  --display-weight-strong: 460;
  --display-opsz: 72;

  /* Type scale: fluid display, fixed UI. 12px is the floor for any label. */
  --text-2xs: 0.6875rem;   /* 11px: tape numerals and chart ticks only */
  --text-xs: 0.75rem;      /* 12px: eyebrows, captions, labels */
  --text-sm: 0.875rem;     /* 14px: dense UI */
  --text-base: 1rem;       /* 16px: UI body */
  --text-md: 1.125rem;     /* 18px: long-form body */
  --text-lg: clamp(1.0625rem, 0.95rem + 0.6vw, 1.375rem);   /* lead: 17 to 22px */
  --text-xl: 1.5rem;       /* 24px: card titles */
  --text-2xl: clamp(1.75rem, 1.35rem + 1.4vw, 2.5rem);      /* page heads in the app */
  --text-3xl: clamp(2.25rem, 1.5rem + 2.8vw, 4rem);         /* section heads */
  --text-4xl: clamp(2.75rem, 1.4rem + 5vw, 6rem);           /* hero: 44px mobile, 96px desktop */
  --leading-tight: 1.02;
  --leading-snug: 1.15;
  --leading-normal: 1.5;
  --leading-relaxed: 1.65;
  --tracking-display: -0.022em;
  --tracking-tight: -0.01em;
  --tracking-caps: 0.12em;

  /* Spacing (4px base) */
  --space-0: 0;
  --space-1: 0.25rem;   /* 4 */
  --space-2: 0.5rem;    /* 8 */
  --space-3: 0.75rem;   /* 12 */
  --space-4: 1rem;      /* 16 */
  --space-5: 1.5rem;    /* 24 */
  --space-6: 2rem;      /* 32 */
  --space-7: 3rem;      /* 48 */
  --space-8: 4rem;      /* 64 */
  --space-9: 6rem;      /* 96 */
  --space-10: 8rem;     /* 128 */
  --section-y: clamp(4rem, 2.8rem + 5.5vw, 8.5rem);
  --gutter: clamp(1rem, 0.4rem + 2.6vw, 2.5rem);
  --measure: 38rem;
  --container: 76rem;        /* 1216px */
  --container-narrow: 48rem;
  --container-wide: 90rem;
  --header-h: 4.5rem;
  --sidebar-w: 16rem;

  /* Radii: small and tailored. Pills only for toggles. */
  --radius-1: 2px;
  --radius-2: 4px;
  --radius-3: 8px;
  --radius-4: 12px;
  --radius-pill: 999px;

  /* Borders */
  --hairline: 1px solid var(--border);
  --hairline-strong: 1px solid var(--border-strong);
  --hairline-ink: 1px solid var(--rule);

  /* Motion */
  --dur-1: 120ms;
  --dur-2: 200ms;
  --dur-3: 360ms;
  --dur-4: 700ms;
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-tape: cubic-bezier(0.3, 0.7, 0.2, 1);

  /* Layers */
  --z-sticky: 10;
  --z-header: 20;
  --z-drawer: 30;
  --z-overlay: 40;
  --z-toast: 50;
}

/* ---- Color tokens: light (default) --------------------------------------- */
:root {
  color-scheme: light;
  --bg: #F3EDE2;
  --surface: #FAF6EF;
  --surface-2: #EAE2D4;
  --surface-3: #E1D7C6;
  --surface-raised: #FFFCF7;
  --border: #D8CCBA;
  --border-strong: #B7A992;
  --border-input: #8C7E6A;
  --rule: #1D1915;
  --text: #1D1915;
  --text-muted: #5A5046;
  --text-subtle: #736859;
  --accent: #B23714;
  --accent-fill: #C4441F;
  --accent-hover: #9E2F10;
  --accent-soft: #F9E5D4;
  --accent-line: #E6BEA5;
  --accent-contrast: #FFF7EE;
  --success: #3B6A3A;
  --success-soft: #E4EBDD;
  --warning: #8A560B;
  --warning-soft: #F3E6CC;
  --danger: #A0203F;
  --danger-soft: #F0D9E8;
  --danger-hover: #861934;
  --info: #2D5877;
  --info-soft: #DFE7EC;
  --focus-ring: #C4441F;
  --selection: #F6DDD0;
  --overlay: rgba(29, 25, 21, 0.46);
  --tape-bg: #EFE4CC;
  --tape-edge: #D9C9A8;
  --tape-tick: #1D1915;
  --tape-number: #3A332B;
  --tape-fill: #E6BC9F;
  --tape-hatch: rgba(196, 68, 31, 0.34);
  --chart-bar: #5A5148;
  --chart-bar-strong: #1D1915;
  --chart-bar-muted: #978A76;
  --chart-highlight: #C4441F;
  --chart-grid: #DDD2C1;
  --chart-axis: #675D51;
  --chart-pace: #1D1915;
  --chart-band: rgba(29, 25, 21, 0.13);
  --series-1: #2E6DA4;
  --series-2: #D2562B;
  --series-3: #1F9A7A;
  --series-4: #B07A08;
  --series-5: #A2518F;
  --series-6: #5B8A2E;
  --code-bg: #1D1915;
  --code-text: #EDE5D6;
  --code-muted: #A89C88;
  --code-string: #F2A27F;
  --code-key: #C9D8C0;
  --code-accent: #F2764A;
  --code-border: #1D1915;
  --code-head: #2A241E;
  --shadow-1: 0 1px 0 rgba(60, 40, 20, 0.04), 0 1px 2px rgba(60, 40, 20, 0.06);
  --shadow-2: 0 1px 0 rgba(60, 40, 20, 0.04), 0 6px 16px -6px rgba(60, 40, 20, 0.16);
  --shadow-3: 0 2px 0 rgba(60, 40, 20, 0.04), 0 24px 48px -20px rgba(60, 40, 20, 0.30);
  --shadow-inset: inset 0 1px 2px rgba(60, 40, 20, 0.08);
  --frame: #1D1915;
  --edge-shade: rgba(29, 25, 21, 0.12);
}

/* ---- Color tokens: dark, forced by the theme switch (cookie "theme=dark") -- */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #15120E;
  --surface: #1D1914;
  --surface-2: #27221B;
  --surface-3: #302920;
  --surface-raised: #241F19;
  --border: #3A3229;
  --border-strong: #564B3E;
  --border-input: #7C6F5D;
  --rule: #F0E8DA;
  --text: #F0E8DA;
  --text-muted: #B2A691;
  --text-subtle: #958A77;
  --accent: #F2764A;
  --accent-fill: #EE6A3C;
  --accent-hover: #F68A62;
  --accent-soft: #311F13;
  --accent-line: #5A3320;
  --accent-contrast: #1A0F08;
  --success: #93BF84;
  --success-soft: #1F2A1C;
  --warning: #E2A857;
  --warning-soft: #2E2415;
  --danger: #EF7F8F;
  --danger-soft: #361A2A;
  --danger-hover: #F49AA8;
  --info: #8DB7D8;
  --info-soft: #172431;
  --focus-ring: #F2764A;
  --selection: #4A2A1B;
  --overlay: rgba(0, 0, 0, 0.62);
  --tape-bg: #2A2419;
  --tape-edge: #3D3425;
  --tape-tick: #E9DFCC;
  --tape-number: #CFC3AD;
  --tape-fill: #6E3520;
  --tape-hatch: rgba(238, 106, 60, 0.42);
  --chart-bar: #A89D8B;
  --chart-bar-strong: #F0E8DA;
  --chart-bar-muted: #786C5C;
  --chart-highlight: #EE6A3C;
  --chart-grid: #2F2821;
  --chart-axis: #B2A691;
  --chart-pace: #F0E8DA;
  --chart-band: rgba(240, 232, 218, 0.14);
  --series-1: #4A89C2;
  --series-2: #DB5C2C;
  --series-3: #24987A;
  --series-4: #BA8726;
  --series-5: #B0659E;
  --series-6: #6A9843;
  --code-bg: #0F0D0A;
  --code-text: #EDE5D6;
  --code-muted: #A89C88;
  --code-string: #F2A27F;
  --code-key: #C9D8C0;
  --code-accent: #F2764A;
  --code-border: #3A3229;
  --code-head: #1B1712;
  --shadow-1: 0 1px 0 rgba(0, 0, 0, 0.3);
  --shadow-2: 0 1px 0 rgba(0, 0, 0, 0.3), 0 8px 20px -8px rgba(0, 0, 0, 0.6);
  --shadow-3: 0 2px 0 rgba(0, 0, 0, 0.3), 0 28px 56px -24px rgba(0, 0, 0, 0.8);
  --shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.4);
  --frame: #564B3E;
  --edge-shade: rgba(0, 0, 0, 0.55);
}

/* ---- Color tokens: dark, following the system unless the page forces light - */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #15120E;
    --surface: #1D1914;
    --surface-2: #27221B;
    --surface-3: #302920;
    --surface-raised: #241F19;
    --border: #3A3229;
    --border-strong: #564B3E;
    --border-input: #7C6F5D;
    --rule: #F0E8DA;
    --text: #F0E8DA;
    --text-muted: #B2A691;
    --text-subtle: #958A77;
    --accent: #F2764A;
    --accent-fill: #EE6A3C;
    --accent-hover: #F68A62;
    --accent-soft: #311F13;
    --accent-line: #5A3320;
    --accent-contrast: #1A0F08;
    --success: #93BF84;
    --success-soft: #1F2A1C;
    --warning: #E2A857;
    --warning-soft: #2E2415;
    --danger: #EF7F8F;
    --danger-soft: #361A2A;
    --danger-hover: #F49AA8;
    --info: #8DB7D8;
    --info-soft: #172431;
    --focus-ring: #F2764A;
    --selection: #4A2A1B;
    --overlay: rgba(0, 0, 0, 0.62);
    --tape-bg: #2A2419;
    --tape-edge: #3D3425;
    --tape-tick: #E9DFCC;
    --tape-number: #CFC3AD;
    --tape-fill: #6E3520;
    --tape-hatch: rgba(238, 106, 60, 0.42);
    --chart-bar: #A89D8B;
    --chart-bar-strong: #F0E8DA;
    --chart-bar-muted: #786C5C;
    --chart-highlight: #EE6A3C;
    --chart-grid: #2F2821;
    --chart-axis: #B2A691;
    --chart-pace: #F0E8DA;
    --chart-band: rgba(240, 232, 218, 0.14);
    --series-1: #4A89C2;
    --series-2: #DB5C2C;
    --series-3: #24987A;
    --series-4: #BA8726;
    --series-5: #B0659E;
    --series-6: #6A9843;
    --code-bg: #0F0D0A;
    --code-text: #EDE5D6;
    --code-muted: #A89C88;
    --code-string: #F2A27F;
    --code-key: #C9D8C0;
    --code-accent: #F2764A;
    --code-border: #3A3229;
    --code-head: #1B1712;
    --shadow-1: 0 1px 0 rgba(0, 0, 0, 0.3);
    --shadow-2: 0 1px 0 rgba(0, 0, 0, 0.3), 0 8px 20px -8px rgba(0, 0, 0, 0.6);
    --shadow-3: 0 2px 0 rgba(0, 0, 0, 0.3), 0 28px 56px -24px rgba(0, 0, 0, 0.8);
    --shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.4);
    --frame: #564B3E;
    --edge-shade: rgba(0, 0, 0, 0.55);
  }
}

/* ---- Inverse panels (.inverse): tokens are re-scoped, never mixed. -----------
   On a light page the panel is ink with dark-theme tokens; on a dark page it is a
   dimmed paper with light-theme tokens. Everything inside just uses var(--x). */
.inverse, .toast {
  color-scheme: dark;
  --bg: #1D1915;
  --surface: #1D1915;
  --surface-2: #2A241E;
  --surface-3: #302920;
  --surface-raised: #241F19;
  --border: #3A3229;
  --border-strong: #564B3E;
  --border-input: #7C6F5D;
  --rule: #F0E8DA;
  --text: #F0E8DA;
  --text-muted: #B2A691;
  --text-subtle: #958A77;
  --accent: #F2764A;
  --accent-fill: #EE6A3C;
  --accent-hover: #F68A62;
  --accent-soft: #311F13;
  --accent-line: #5A3320;
  --accent-contrast: #1A0F08;
  --success: #93BF84;
  --success-soft: #1F2A1C;
  --warning: #E2A857;
  --warning-soft: #2E2415;
  --danger: #EF7F8F;
  --danger-soft: #361A2A;
  --danger-hover: #F49AA8;
  --info: #8DB7D8;
  --info-soft: #172431;
  --focus-ring: #F2764A;
  --selection: #4A2A1B;
  --overlay: rgba(0, 0, 0, 0.62);
  --tape-bg: #2A2419;
  --tape-edge: #3D3425;
  --tape-tick: #E9DFCC;
  --tape-number: #CFC3AD;
  --tape-fill: #6E3520;
  --tape-hatch: rgba(238, 106, 60, 0.42);
  --chart-bar: #A89D8B;
  --chart-bar-strong: #F0E8DA;
  --chart-bar-muted: #786C5C;
  --chart-highlight: #EE6A3C;
  --chart-grid: #2F2821;
  --chart-axis: #B2A691;
  --chart-pace: #F0E8DA;
  --chart-band: rgba(240, 232, 218, 0.14);
  --series-1: #4A89C2;
  --series-2: #DB5C2C;
  --series-3: #24987A;
  --series-4: #BA8726;
  --series-5: #B0659E;
  --series-6: #6A9843;
  --code-bg: #0F0D0A;
  --code-text: #EDE5D6;
  --code-muted: #A89C88;
  --code-string: #F2A27F;
  --code-key: #C9D8C0;
  --code-accent: #F2764A;
  --code-border: #3A3229;
  --code-head: #1B1712;
  --shadow-1: 0 1px 0 rgba(0, 0, 0, 0.3);
  --shadow-2: 0 1px 0 rgba(0, 0, 0, 0.3), 0 8px 20px -8px rgba(0, 0, 0, 0.6);
  --shadow-3: 0 2px 0 rgba(0, 0, 0, 0.3), 0 28px 56px -24px rgba(0, 0, 0, 0.8);
  --shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.4);
  --frame: #564B3E;
  --edge-shade: rgba(0, 0, 0, 0.55);
}

:root[data-theme="dark"] .inverse, :root[data-theme="dark"] .toast {
  color-scheme: light;
  --bg: #ECE3D4;
  --surface: #ECE3D4;
  --surface-2: #E2D8C7;
  --surface-3: #E1D7C6;
  --surface-raised: #FFFCF7;
  --border: #D8CCBA;
  --border-strong: #B7A992;
  --border-input: #8C7E6A;
  --rule: #1D1915;
  --text: #1D1915;
  --text-muted: #574D42;
  --text-subtle: #675D51;
  --accent: #B23714;
  --accent-fill: #C4441F;
  --accent-hover: #9E2F10;
  --accent-soft: #F9E5D4;
  --accent-line: #E6BEA5;
  --accent-contrast: #FFF7EE;
  --success: #3B6A3A;
  --success-soft: #E4EBDD;
  --warning: #8A560B;
  --warning-soft: #F3E6CC;
  --danger: #A0203F;
  --danger-soft: #F0D9E8;
  --danger-hover: #861934;
  --info: #2D5877;
  --info-soft: #DFE7EC;
  --focus-ring: #C4441F;
  --selection: #F6DDD0;
  --overlay: rgba(29, 25, 21, 0.46);
  --tape-bg: #EFE4CC;
  --tape-edge: #D9C9A8;
  --tape-tick: #1D1915;
  --tape-number: #3A332B;
  --tape-fill: #E6BC9F;
  --tape-hatch: rgba(196, 68, 31, 0.34);
  --chart-bar: #5A5148;
  --chart-bar-strong: #1D1915;
  --chart-bar-muted: #857864;
  --chart-highlight: #C4441F;
  --chart-grid: #DDD2C1;
  --chart-axis: #675D51;
  --chart-pace: #1D1915;
  --chart-band: rgba(29, 25, 21, 0.13);
  --series-1: #2E6DA4;
  --series-2: #D2562B;
  --series-3: #1A8A6C;
  --series-4: #A06E06;
  --series-5: #A2518F;
  --series-6: #5B8A2E;
  --code-bg: #1D1915;
  --code-text: #EDE5D6;
  --code-muted: #A89C88;
  --code-string: #F2A27F;
  --code-key: #C9D8C0;
  --code-accent: #F2764A;
  --code-border: #1D1915;
  --code-head: #2A241E;
  --shadow-1: 0 1px 0 rgba(60, 40, 20, 0.04), 0 1px 2px rgba(60, 40, 20, 0.06);
  --shadow-2: 0 1px 0 rgba(60, 40, 20, 0.04), 0 6px 16px -6px rgba(60, 40, 20, 0.16);
  --shadow-3: 0 2px 0 rgba(60, 40, 20, 0.04), 0 24px 48px -20px rgba(60, 40, 20, 0.30);
  --shadow-inset: inset 0 1px 2px rgba(60, 40, 20, 0.08);
  --frame: #1D1915;
  --edge-shade: rgba(29, 25, 21, 0.12);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .inverse, :root:not([data-theme="light"]) .toast {
    color-scheme: light;
    --bg: #ECE3D4;
    --surface: #ECE3D4;
    --surface-2: #E2D8C7;
    --surface-3: #E1D7C6;
    --surface-raised: #FFFCF7;
    --border: #D8CCBA;
    --border-strong: #B7A992;
    --border-input: #8C7E6A;
    --rule: #1D1915;
    --text: #1D1915;
    --text-muted: #574D42;
    --text-subtle: #675D51;
    --accent: #B23714;
    --accent-fill: #C4441F;
    --accent-hover: #9E2F10;
    --accent-soft: #F9E5D4;
    --accent-line: #E6BEA5;
    --accent-contrast: #FFF7EE;
    --success: #3B6A3A;
    --success-soft: #E4EBDD;
    --warning: #8A560B;
    --warning-soft: #F3E6CC;
    --danger: #A0203F;
    --danger-soft: #F0D9E8;
    --danger-hover: #861934;
    --info: #2D5877;
    --info-soft: #DFE7EC;
    --focus-ring: #C4441F;
    --selection: #F6DDD0;
    --overlay: rgba(29, 25, 21, 0.46);
    --tape-bg: #EFE4CC;
    --tape-edge: #D9C9A8;
    --tape-tick: #1D1915;
    --tape-number: #3A332B;
    --tape-fill: #E6BC9F;
    --tape-hatch: rgba(196, 68, 31, 0.34);
    --chart-bar: #5A5148;
    --chart-bar-strong: #1D1915;
    --chart-bar-muted: #857864;
    --chart-highlight: #C4441F;
    --chart-grid: #DDD2C1;
    --chart-axis: #675D51;
    --chart-pace: #1D1915;
    --chart-band: rgba(29, 25, 21, 0.13);
    --series-1: #2E6DA4;
    --series-2: #D2562B;
    --series-3: #1A8A6C;
    --series-4: #A06E06;
    --series-5: #A2518F;
    --series-6: #5B8A2E;
    --code-bg: #1D1915;
    --code-text: #EDE5D6;
    --code-muted: #A89C88;
    --code-string: #F2A27F;
    --code-key: #C9D8C0;
    --code-accent: #F2764A;
    --code-border: #1D1915;
    --code-head: #2A241E;
    --shadow-1: 0 1px 0 rgba(60, 40, 20, 0.04), 0 1px 2px rgba(60, 40, 20, 0.06);
    --shadow-2: 0 1px 0 rgba(60, 40, 20, 0.04), 0 6px 16px -6px rgba(60, 40, 20, 0.16);
    --shadow-3: 0 2px 0 rgba(60, 40, 20, 0.04), 0 24px 48px -20px rgba(60, 40, 20, 0.30);
    --shadow-inset: inset 0 1px 2px rgba(60, 40, 20, 0.08);
    --frame: #1D1915;
    --edge-shade: rgba(29, 25, 21, 0.12);
  }
}

/* ==== 3. Base and reset ==== */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Anchors and focused elements land below the sticky bar of each layout (WCAG 2.4.11). */
  --sticky-offset: calc(var(--header-h) + 1rem);
  scroll-padding-top: var(--sticky-offset);
  hanging-punctuation: first last;
}
html:has(> body.app-portal) { --sticky-offset: 8rem; }
html:has(> body.app-admin) { --sticky-offset: 6rem; }
html:has(> body.styleguide) { --sticky-offset: 5rem; }
@media (max-width: 960px) { html:has(> body.app-admin) { --sticky-offset: 5rem; } }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  font-feature-settings: "kern", "liga";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}
body, h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd, pre { margin: 0; }
img, svg, video, canvas { display: block; max-width: 100%; }
img, video { height: auto; }
svg { flex: none; }
a { color: inherit; text-decoration-skip-ink: auto; }
button, input, select, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
button { cursor: pointer; }
button:disabled, [aria-disabled="true"] { cursor: not-allowed; }
table { border-collapse: collapse; }
ul[role="list"], ol[role="list"] { list-style: none; margin: 0; padding: 0; }
hr { border: 0; border-top: var(--hairline); margin: var(--space-6) 0; }
[hidden] { display: none !important; }
::selection { background: var(--selection); color: var(--text); }
:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 3px; border-radius: var(--radius-1); }
abbr[title] { text-decoration: underline dotted; text-underline-offset: 0.2em; cursor: help; }

.skip-link {
  position: absolute;
  left: var(--gutter);
  top: -4rem;
  z-index: var(--z-toast);
  padding: 0.6rem 1rem;
  background: var(--text);
  color: var(--bg);
  border-radius: var(--radius-2);
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus { top: 0.75rem; }

/* ==== 4. Type ==== */
h1, h2, h3, h4, .display-1, .display-2, .h1, .h2, .h3, .h4 {
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  font-optical-sizing: auto;
  letter-spacing: var(--tracking-display);
  line-height: var(--leading-snug);
  text-wrap: balance;
}
h5, h6 { font-size: var(--text-base); font-weight: 600; }
h1 em, h2 em, h3 em, h4 em, .display-1 em, .display-2 em, .h1 em, .h2 em, .h3 em { font-style: italic; font-weight: inherit; }

/* Display sizes: optical size capped, weight raised (legible "e" at 1x). */
.display-1 {
  font-size: var(--text-4xl);
  line-height: 0.98;
  letter-spacing: -0.026em;
  font-weight: 400;
  font-variation-settings: "opsz" var(--display-opsz);
}
.display-2 {
  font-size: var(--text-3xl);
  line-height: 1.02;
  letter-spacing: -0.024em;
  font-weight: 390;
  font-variation-settings: "opsz" var(--display-opsz);
}
.display-1 .accent-dot, .display-2 .accent-dot, .accent-dot { color: var(--accent); font-style: normal; }
.h1 { font-size: var(--text-2xl); line-height: 1.05; letter-spacing: -0.026em; }
.h2 { font-size: clamp(1.5rem, 1.25rem + 0.8vw, 1.875rem); line-height: 1.1; letter-spacing: -0.02em; }
.h3 { font-size: 1.375rem; line-height: 1.15; letter-spacing: -0.015em; font-weight: 420; }
.h4 { font-size: 1.125rem; line-height: 1.25; letter-spacing: -0.01em; font-weight: 460; }
p { text-wrap: pretty; }

.eyebrow {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--space-3);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--text-muted);
}
/* The rule is centered on the first line (0.5lh), so a wrapped eyebrow keeps it beside its first words. */
.eyebrow::before { content: ""; width: 1.5rem; height: 1px; margin-top: 0.75em; margin-top: calc(0.5lh - 0.5px); background: var(--accent); flex: none; }
.eyebrow.plain::before { display: none; }
.kicker {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.125rem;
  font-weight: 400;
  color: var(--accent);
}
.lead { font-size: var(--text-lg); line-height: 1.5; color: var(--text-muted); letter-spacing: -0.005em; max-width: var(--measure); }
.lead strong, .lead b { color: var(--text); font-weight: 560; }
.muted { color: var(--text-muted); }
.subtle { color: var(--text-subtle); }
.accent { color: var(--accent); }
.small { font-size: var(--text-sm); }
.text-xs { font-size: var(--text-xs); }
.mono { font-family: var(--font-mono); }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.caps { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; }
.nowrap { white-space: nowrap; }
.strike { text-decoration: line-through; text-decoration-thickness: 1px; }

/* Long-form reading (legal pages, docs, emails preview) */
.prose { font-size: var(--text-md); line-height: var(--leading-relaxed); max-width: 42rem; }
.prose > * + * { margin-top: 1em; }
.prose > :first-child { margin-top: 0; }
.prose h2 { font-size: var(--text-2xl); line-height: 1.1; margin-top: 2.2em; }
.prose h3 { font-size: 1.375rem; margin-top: 1.8em; font-weight: 420; }
.prose h4 { font-size: 1.125rem; margin-top: 1.5em; font-weight: 460; }
.prose h2 + *, .prose h3 + *, .prose h4 + * { margin-top: 0.6em; }
/* Body links look the same everywhere: the .link treatment (ink text, quiet underline, ember on hover). */
.prose a { color: var(--text); text-decoration-color: var(--border-input); text-decoration-thickness: 1px; text-underline-offset: 0.22em; transition: text-decoration-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out); }
.prose a:hover { color: var(--accent); text-decoration-color: var(--accent); }
.prose ul, .prose ol { padding-left: 1.3em; }
.prose li + li { margin-top: 0.35em; }
.prose li::marker { color: var(--text-muted); }
.prose blockquote { padding-left: 1.2em; border-left: 2px solid var(--accent-fill); color: var(--text-muted); font-family: var(--font-display); font-style: italic; font-size: 1.25rem; line-height: 1.45; }
.prose code:not(pre code) { font-size: 0.85em; }
.prose pre { font-size: var(--text-sm); }
.prose table { width: 100%; font-size: var(--text-sm); }
.prose th, .prose td { text-align: left; padding: 0.55rem 0.75rem 0.55rem 0; border-bottom: var(--hairline); vertical-align: top; }
.prose th { font-weight: 600; border-bottom: var(--hairline-ink); }

/* ==== 5. Layout primitives ==== */
.container { width: 100%; max-width: calc(var(--container) + 2 * var(--gutter)); margin-inline: auto; padding-inline: var(--gutter); }
.container-narrow { max-width: calc(var(--container-narrow) + 2 * var(--gutter)); }
.container-wide { max-width: calc(var(--container-wide) + 2 * var(--gutter)); }
.section { padding-block: var(--section-y); }
.section-sm { padding-block: clamp(2.5rem, 2rem + 2.5vw, 4rem); }

/* Stack: vertical rhythm. Gap from the modifier or --stack-gap. */
.stack { display: flex; flex-direction: column; gap: var(--stack-gap, var(--space-4)); }
.stack > * { margin-block: 0; }
.stack-2xs { --stack-gap: var(--space-1); }
.stack-xs { --stack-gap: var(--space-2); }
.stack-sm { --stack-gap: var(--space-3); }
.stack-lg { --stack-gap: var(--space-6); }
.stack-xl { --stack-gap: var(--space-8); }

/* Cluster: a wrapping row (buttons, tags, meta). */
.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cluster-gap, var(--space-3)); }
.cluster-sm { --cluster-gap: var(--space-2); }
.cluster-lg { --cluster-gap: var(--space-5); }
.cluster-between { justify-content: space-between; }
.cluster-end { justify-content: flex-end; }
.cluster-start { align-items: flex-start; }
.cluster-baseline { align-items: baseline; }
.push { margin-left: auto; }

/* Grid: auto-fit cards by default; fixed column variants collapse on small screens. */
.grid { display: grid; gap: var(--grid-gap, var(--space-5)); grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min, 16rem), 100%), 1fr)); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-tight { --grid-gap: var(--space-4); }
.grid-12 { display: grid; gap: var(--grid-gap, 1.25rem); grid-template-columns: repeat(12, minmax(0, 1fr)); }
.grid-12 > * { grid-column: span 12; min-width: 0; }
.grid-12 > .span-3 { grid-column: span 3; }
.grid-12 > .span-4 { grid-column: span 4; }
.grid-12 > .span-5 { grid-column: span 5; }
.grid-12 > .span-6 { grid-column: span 6; }
.grid-12 > .span-7 { grid-column: span 7; }
.grid-12 > .span-8 { grid-column: span 8; }
.grid-12 > .span-9 { grid-column: span 9; }
.grid-12 > .span-12 { grid-column: span 12; }
@media (max-width: 1100px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-12 > .span-3, .grid-12 > .span-4 { grid-column: span 6; }
  .grid-12 > .span-5, .grid-12 > .span-6, .grid-12 > .span-7, .grid-12 > .span-8, .grid-12 > .span-9 { grid-column: span 12; }
}
@media (max-width: 760px) {
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .grid-12 > [class*="span-"] { grid-column: span 12; }
}

/* Split: a side column and a main column (settings pages, detail pages). */
.split { display: grid; gap: var(--split-gap, var(--space-6)); grid-template-columns: minmax(0, var(--split-side, 18rem)) minmax(0, 1fr); align-items: start; }
.split-reverse { grid-template-columns: minmax(0, 1fr) minmax(0, var(--split-side, 20rem)); }
.split-even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .split, .split-reverse, .split-even { grid-template-columns: minmax(0, 1fr); }
}
.sticky { position: sticky; top: calc(var(--header-h) + var(--space-4)); }

/* Page head: serif title + one line + actions (admin and portal pages) */
.page-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--space-4) var(--space-5); padding-block: var(--space-5) var(--space-6); }
.page-head h1, .page-head .page-title { font-size: var(--text-2xl); line-height: 1.02; letter-spacing: -0.028em; font-weight: 360; }
.page-head p { margin-top: 0.5rem; color: var(--text-muted); max-width: 44rem; }
.page-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }

/* Section head (site): number + label on the left, big serif headline on the right */
.section-head { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--space-6); align-items: end; margin-bottom: clamp(2.5rem, 1.5rem + 3vw, 4.5rem); }
.section-head > .section-label { grid-column: 1 / span 4; display: grid; gap: 0.9rem; align-self: start; padding-top: 0.6rem; }
.section-head > h2 { grid-column: 5 / span 8; font-size: var(--text-3xl); line-height: 1.04; letter-spacing: -0.028em; font-weight: 360; }
.section-head > .section-sub { grid-column: 5 / span 7; font-size: var(--text-md); color: var(--text-muted); margin-top: -0.75rem; }
@media (max-width: 900px) {
  .section-head { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; }
  .section-head > * { grid-column: 1 !important; }
  .section-head > .section-sub { margin-top: 0; }
}

/* ==== 6. Rules, ruler, dimension lines ==== */
.rule { border: 0; border-top: var(--hairline-ink); margin: 0; }
.rule-soft { border: 0; border-top: var(--hairline); margin: 0; }
/* Ruler: a hairline with tape ticks every 8px, taller every 40px and 200px */
.ruler {
  height: 14px;
  border-top: var(--hairline-ink);
  background-image:
    linear-gradient(to right, var(--rule) 1px, transparent 1px),
    linear-gradient(to right, var(--rule) 1px, transparent 1px),
    linear-gradient(to right, var(--rule) 1px, transparent 1px);
  background-size: 200px 13px, 40px 8px, 8px 4px;
  background-repeat: repeat-x;
  opacity: 0.9;
}
.ruler-soft { opacity: 0.35; }
/* Dimension line: a hairline with end ticks, the mark a tailor draws beside a measure */
.dim {
  display: inline-block;
  width: var(--dim-w, 0.9rem);
  height: 7px;
  flex: none;
  background:
    linear-gradient(currentColor, currentColor) 0 50% / 100% 1px no-repeat,
    linear-gradient(currentColor, currentColor) 0 0 / 1px 100% no-repeat,
    linear-gradient(currentColor, currentColor) 100% 0 / 1px 100% no-repeat;
  color: var(--text-muted);
}
.dim-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.dim-list > li { display: grid; grid-template-columns: 0.9rem minmax(0, 1fr); gap: 0.6rem; }
.dim-list > li::before {
  content: "";
  height: 7px;
  margin-top: 0.5em;
  background:
    linear-gradient(var(--text-muted), var(--text-muted)) 0 50% / 100% 1px no-repeat,
    linear-gradient(var(--text-muted), var(--text-muted)) 0 0 / 1px 100% no-repeat,
    linear-gradient(var(--text-muted), var(--text-muted)) 100% 0 / 1px 100% no-repeat;
}

/* ==== 7. Brand ==== */
/* The mark is drawn on a 56 x 36 pixel grid: at --mark-h 36px it is pixel-exact on a 1x screen.
   Sizes: md (headers) mark 36 / name 28, sm 32 / 24, lg (sign-in pages) 48 / 36; phones one step down. */
.brand { --mark-h: 36px; --brand-name: 1.75rem; display: inline-flex; align-items: center; gap: 0.625rem; min-height: 44px; text-decoration: none; color: var(--text); flex: none; border-radius: var(--radius-2); }
.brand-mark { display: block; flex: none; height: var(--mark-h); width: calc(var(--mark-h) * 14 / 9); color: var(--text); }
.brand-mark .hook { fill: var(--accent-fill); }
.brand-name {
  font-family: var(--font-display);
  font-size: var(--brand-name);
  font-weight: 460;
  font-variation-settings: "opsz" 36;
  letter-spacing: -0.028em;
  line-height: 1;
  white-space: nowrap;
}
.brand-sm { --mark-h: 32px; --brand-name: 1.5rem; gap: 0.55rem; }
.brand-lg { --mark-h: 48px; --brand-name: 2.25rem; gap: 0.8rem; }
@media (max-width: 600px) {
  .brand { --mark-h: 32px; --brand-name: 1.5625rem; gap: 0.55rem; }
  .brand-sm { --mark-h: 28px; --brand-name: 1.375rem; }
  .brand-lg { --mark-h: 40px; --brand-name: 1.875rem; }
}

/* Language switch (ui.lang_switch): "EN / FR", the current one inked. Same height as the theme switch. */
.lang-switch { display: inline-flex; flex: none; align-items: stretch; border: 1px solid var(--border-input); border-radius: var(--radius-2); overflow: hidden; font-family: var(--font-mono); font-size: 0.75rem; font-weight: 500; letter-spacing: 0.06em; line-height: 1; }
.lang-switch a { display: inline-grid; place-items: center; min-width: 2.25rem; height: 2rem; padding: 0 0.5rem; color: var(--text-muted); text-decoration: none; }
.lang-switch a + a { border-left: 1px solid var(--border-input); }
.lang-switch a:hover { color: var(--text); background: var(--surface-2); }
.lang-switch a:focus-visible { outline-offset: -3px; }
.lang-switch a[aria-current="true"], .lang-switch a[aria-current="true"]:hover { background: var(--text); color: var(--bg); }

/* Language suggestion bar (base.html): slim, above the header, gone once a language is chosen. */
/* Demonstration instance banner (DEMO_MODE, templates/base.html): on every page of a demo instance. */
.demo-banner { background: var(--warning-soft); color: var(--text); border-bottom: 1px solid var(--warning); font-size: var(--text-sm); }
.demo-banner-inner { display: flex; align-items: center; gap: 0.55rem; min-height: 2.5rem; padding-block: 0.4rem; }
.demo-banner-inner > .icon { --icon-size: 1.125rem; flex: none; color: var(--warning); }
.demo-banner p { margin: 0; }
.demo-banner strong { font-weight: 650; }
.lang-suggest { background: var(--surface-2); border-bottom: var(--hairline); font-size: var(--text-sm); }
.lang-suggest-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 0.85rem; min-height: 3rem; padding-block: 0.45rem; }
.lang-suggest-inner > .icon { --icon-size: 1.125rem; color: var(--text-muted); }
.lang-suggest p { margin: 0; color: var(--text); font-weight: 520; }
.lang-suggest-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1.1rem; margin-left: auto; }
@media (max-width: 600px) {
  .lang-suggest-inner > .icon { display: none; }
  .lang-suggest-actions { margin-left: 0; }
}

/* ==== 8. Buttons, links, icons ==== */
.icon { width: var(--icon-size, 1.125rem); height: var(--icon-size, 1.125rem); flex: none; stroke-width: 1.75; fill: none; stroke: currentColor; vertical-align: middle; }
.icon-sm { --icon-size: 0.875rem; }
.icon-lg { --icon-size: 1.5rem; }

.btn {
  --btn-bg: transparent;
  --btn-fg: var(--text);
  --btn-bd: var(--border-input);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  min-height: 2.75rem;
  padding: 0 1.15rem;
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius-2);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 580;
  letter-spacing: -0.005em;
  line-height: 1.1;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  transition: background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out), transform var(--dur-1) var(--ease-out);
}
.btn:hover { --btn-bd: var(--text); }
.btn:active { transform: translateY(1px); }
.btn .icon { --icon-size: 1rem; transition: transform var(--dur-2) var(--ease-out); }
.btn:hover .icon-after { transform: translateX(3px); }
.btn-primary { --btn-bg: var(--accent-fill); --btn-fg: var(--accent-contrast); --btn-bd: var(--accent-fill); }
.btn-primary:hover { --btn-bg: var(--accent-hover); --btn-bd: var(--accent-hover); }
.btn-secondary { --btn-bg: var(--surface); }
.btn-ink { --btn-bg: var(--text); --btn-fg: var(--bg); --btn-bd: var(--text); }
.btn-ink:hover { --btn-bg: var(--text-muted); --btn-bd: var(--text-muted); }
.btn-ghost { --btn-bd: transparent; padding-inline: 0.65rem; }
.btn-ghost:hover { --btn-bd: transparent; --btn-bg: var(--surface-2); }
.btn-danger { --btn-bg: var(--danger); --btn-fg: var(--surface); --btn-bd: var(--danger); }
.btn-danger:hover { --btn-bg: var(--danger-hover); --btn-bd: var(--danger-hover); }
.btn-danger-ghost { --btn-fg: var(--danger); --btn-bd: transparent; }
.btn-danger-ghost:hover { --btn-bg: var(--danger-soft); --btn-bd: transparent; }
.btn-sm { min-height: 2.25rem; padding: 0 0.8rem; font-size: var(--text-sm); gap: 0.4rem; }
.btn-sm .icon { --icon-size: 0.9375rem; }
.btn-lg { min-height: 3.25rem; padding: 0 1.5rem; font-size: 1rem; }
.btn-block { display: flex; width: 100%; }
.btn-icon { padding: 0; width: 2.75rem; }
.btn-icon.btn-sm { width: 2.25rem; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; pointer-events: none; }
/* Loading: add .is-loading (app.js does it on submit). The label keeps the width and stays in the
   accessibility tree (opacity, never visibility or display), so a busy button keeps its name. */
.btn.is-loading { color: transparent; pointer-events: none; }
.btn.is-loading > * { opacity: 0; }
.btn.is-loading::after {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 1rem;
  height: 1rem;
  margin: -0.5rem 0 0 -0.5rem;
  border-radius: 50%;
  border: 2px solid var(--btn-fg);
  border-right-color: transparent;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.link {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--border-input);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  transition: text-decoration-color var(--dur-2) var(--ease-out), color var(--dur-2) var(--ease-out);
}
.link:hover { text-decoration-color: var(--accent); color: var(--accent); }
.link-quiet { text-decoration: none; }
.link-quiet:hover { color: var(--accent); }
.link-arrow { display: inline-flex; align-items: center; gap: 0.35rem; font-weight: 580; text-decoration: none; }
.link-arrow .icon { --icon-size: 1rem; transition: transform var(--dur-2) var(--ease-out); }
.link-arrow:hover { color: var(--accent); }
.link-arrow:hover .icon { transform: translateX(3px); }
button.link { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }

/* ==== 9. Tags and badges ==== */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0.5rem 0.22rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-1);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  line-height: 1.2;
  white-space: nowrap;
}
.tag-accent { border-color: var(--accent); color: var(--accent); }
.tag-solid { background: var(--text); border-color: var(--text); color: var(--bg); }

/* Status badges: a shape plus a word, never color alone.
   success = dot, warning = triangle, danger = diamond, info = square, neutral = ring, accent = dot + halo,
   credit = plus in a dashed outline (free credit: no money received, unlike the info "Plan fee") */
.badge {
  --b-fg: var(--text-muted);
  --b-bg: var(--surface-2);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0.55rem 0.22rem 0.45rem;
  border-radius: var(--radius-1);
  background: var(--b-bg);
  color: var(--b-fg);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: 620;
  letter-spacing: 0.01em;
  line-height: 1.3;
  white-space: nowrap;
  vertical-align: middle;
}
.badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.badge-success { --b-fg: var(--success); --b-bg: var(--success-soft); }
.badge-warning { --b-fg: var(--warning); --b-bg: var(--warning-soft); }
.badge-warning::before { border-radius: 0; width: 8px; height: 7px; clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.badge-danger { --b-fg: var(--danger); --b-bg: var(--danger-soft); }
.badge-danger::before { border-radius: 1px; transform: rotate(45deg); }
.badge-info { --b-fg: var(--info); --b-bg: var(--info-soft); }
.badge-info::before { border-radius: 1px; }
.badge-accent { --b-fg: var(--bg); --b-bg: var(--text); }
.badge-accent::before { box-shadow: 0 0 0 2px color-mix(in oklab, currentColor 35%, transparent); }
.badge-neutral::before { background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; width: 7px; height: 7px; }
.badge-credit { --b-fg: var(--text); --b-bg: transparent; outline: 1px dashed var(--border-input); outline-offset: -1px; }
.badge-credit::before { width: 8px; height: 8px; border-radius: 0; clip-path: polygon(37.5% 0, 62.5% 0, 62.5% 37.5%, 100% 37.5%, 100% 62.5%, 62.5% 62.5%, 62.5% 100%, 37.5% 100%, 37.5% 62.5%, 0 62.5%, 0 37.5%, 37.5% 37.5%); }
.badge-plain::before { display: none; }
.badge-live::before { animation: breathe 1.8s var(--ease-in-out) infinite alternate; }
@keyframes breathe { from { transform: scale(0.7); } to { transform: scale(1.15); } }
/* Small count bubble (nav items, tabs) */
.count {
  display: inline-grid;
  place-items: center;
  min-width: 1.35rem;
  height: 1.35rem;
  padding: 0 0.35rem;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.count-accent { background: var(--accent-fill); color: var(--accent-contrast); }

/* ==== 10. Cards and panels ==== */
.card {
  position: relative;
  background: var(--surface);
  border: var(--hairline);
  border-radius: var(--radius-3);
  box-shadow: var(--shadow-1);
  min-width: 0;
}
.card-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: 0.75rem 1rem; padding: 1.4rem 1.4rem 0; }
.card-head > :first-child { min-width: 0; }
/* A tag or badge beside the title never wraps under it. */
.card-head:has(> .tag:last-child, > .badge:last-child) { flex-wrap: nowrap; }
.card-head:has(> .tag:last-child, > .badge:last-child) > :first-child { flex: 1 1 0; }
.card-head > .tag, .card-head > .badge { flex: none; margin-top: 0.3rem; }
.card-title { font-family: var(--font-display); font-size: 1.375rem; line-height: 1.15; letter-spacing: -0.015em; font-weight: 420; }
.card-sub { font-size: var(--text-sm); color: var(--text-muted); margin-top: 0.25rem; }
.card-body { padding: 1.1rem 1.4rem 1.4rem; }
.card-body + .card-body { border-top: var(--hairline); }
.card-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; padding: 0.9rem 1.4rem; border-top: var(--hairline); background: color-mix(in oklab, var(--surface-2) 45%, var(--surface)); border-radius: 0 0 var(--radius-3) var(--radius-3); font-size: var(--text-sm); color: var(--text-muted); }
.card-pad { padding: 1.4rem; }
.card-flush > .card-body { padding: 0; }
.card-accent::before { content: ""; position: absolute; left: -1px; right: -1px; top: -1px; height: 3px; background: var(--accent-fill); border-radius: var(--radius-3) var(--radius-3) 0 0; }
.card-strong { border-color: var(--frame); box-shadow: var(--shadow-2); }
.card-dashed { background: transparent; box-shadow: none; border: 1px dashed var(--border-strong); }
a.card, .card-link { text-decoration: none; color: inherit; transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
a.card:hover, .card-link:hover { border-color: var(--border-strong); box-shadow: var(--shadow-2); }
.inverse { background: var(--surface); color: var(--text); border-color: var(--border); }
.card.inverse { box-shadow: none; }

/* ==== 11. Forms ==== */
.form { display: grid; gap: 1.25rem; }
.form-grid { display: grid; gap: 1.25rem 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.form-grid > .span-2, .form-grid > .field-full { grid-column: 1 / -1; }
@media (max-width: 640px) { .form-grid { grid-template-columns: minmax(0, 1fr); } }
.fieldset { border: 0; margin: 0; padding: 0; min-width: 0; display: grid; gap: 0.6rem; }
.legend, .fieldset > legend { padding: 0; margin-bottom: 0.1rem; font-size: var(--text-sm); font-weight: 620; color: var(--text); }
.form-section { display: grid; gap: 1.25rem; padding-top: 1.5rem; border-top: var(--hairline); }
.form-section-title { font-family: var(--font-display); font-size: 1.25rem; font-weight: 420; letter-spacing: -0.01em; }

.field { display: grid; gap: 0.4rem; align-content: start; min-width: 0; }
.label { font-size: var(--text-sm); font-weight: 620; color: var(--text); }
.label .opt { font-weight: 400; color: var(--text-muted); }
.label .req { color: var(--accent); font-weight: 600; margin-left: 0.1rem; }
.help { font-size: 0.8125rem; line-height: 1.45; color: var(--text-muted); }
.field-error { display: flex; align-items: flex-start; gap: 0.35rem; font-size: 0.8125rem; line-height: 1.45; color: var(--danger); font-weight: 560; }
.field-error .icon { --icon-size: 0.875rem; margin-top: 0.15rem; }

.input, .textarea, .select {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.55rem 0.8rem;
  background: var(--surface);
  border: 1px solid var(--border-input);
  border-radius: var(--radius-2);
  color: var(--text);
  font-size: var(--text-base);
  line-height: 1.4;
  box-shadow: var(--shadow-inset);
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out);
}
.input::placeholder, .textarea::placeholder { color: var(--text-subtle); opacity: 1; }
.input:hover, .textarea:hover, .select:hover { border-color: var(--text-muted); }
/* Focus: the same 2px ring as buttons (>= 3:1 on every surface), 1px off the field, plus an ember border. */
.input:focus, .textarea:focus, .select:focus { outline: 2px solid var(--focus-ring); outline-offset: 1px; border-color: var(--accent); box-shadow: none; }
/* Read only: a solid well with a quiet hairline, text stays full ink (it can be read and copied).
   Disabled: no fill, dashed border, muted text. The two differ by border style in both themes. */
.input[readonly], .textarea[readonly] { background: var(--surface-2); border-color: var(--border-strong); box-shadow: none; }
.input:disabled, .textarea:disabled, .select:disabled { background: transparent; border-style: dashed; border-color: var(--border-input); color: var(--text-muted); box-shadow: none; }
.input:disabled::placeholder, .textarea:disabled::placeholder { color: var(--text-muted); }
.input-mono, .input[type="number"] { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.textarea { min-height: 7.5rem; resize: vertical; line-height: 1.55; }
.select {
  appearance: none;
  padding-right: 2.4rem;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%), linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
  background-position: calc(100% - 1.15rem) 52%, calc(100% - 0.8rem) 52%;
  background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
  background-repeat: no-repeat;
}
.select-sm, .input-sm { min-height: 2.25rem; font-size: var(--text-sm); padding-block: 0.35rem; }
.field.is-invalid .input, .field.is-invalid .textarea, .field.is-invalid .select, .input[aria-invalid="true"], .textarea[aria-invalid="true"], .select[aria-invalid="true"] { border-color: var(--danger); }
.field.is-invalid .input:focus, .field.is-invalid .textarea:focus, .field.is-invalid .select:focus,
.input[aria-invalid="true"]:focus, .textarea[aria-invalid="true"]:focus, .select[aria-invalid="true"]:focus { outline-color: var(--danger); border-color: var(--danger); }

/* Input group: prefix / suffix (currency, units, rate) */
.input-group { display: flex; align-items: stretch; width: 100%; border: 1px solid var(--border-input); border-radius: var(--radius-2); background: var(--surface); box-shadow: var(--shadow-inset); transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out); }
.input-group:hover { border-color: var(--text-muted); }
.input-group:focus-within { outline: 2px solid var(--focus-ring); outline-offset: 1px; border-color: var(--accent); }
.input-group > .input { border: 0; box-shadow: none; background: transparent; min-width: 0; flex: 1; }
.input-group > .input:focus { outline: none; box-shadow: none; }
.input-group > .btn:focus-visible { outline-offset: -3px; }
.affix { display: inline-flex; align-items: center; padding: 0 0.75rem; color: var(--text-muted); font-family: var(--font-mono); font-size: var(--text-sm); white-space: nowrap; background: var(--surface-2); }
.affix:first-child { border-right: var(--hairline); border-radius: var(--radius-2) 0 0 var(--radius-2); }
.affix:last-child { border-left: var(--hairline); border-radius: 0 var(--radius-2) var(--radius-2) 0; }
.field.is-invalid .input-group { border-color: var(--danger); }
.field.is-invalid .input-group:focus-within { outline-color: var(--danger); }
.input-group > .btn { border: 0; border-left: 1px solid var(--border-input); border-radius: 0 var(--radius-2) var(--radius-2) 0; min-height: auto; }

/* Checkbox and radio rows (native controls, tinted) */
.check { display: flex; align-items: flex-start; gap: 0.7rem; cursor: pointer; font-size: var(--text-sm); }
.check input { flex: none; width: 1.125rem; height: 1.125rem; margin: 0.12rem 0 0; accent-color: var(--accent-fill); cursor: pointer; }
.check-text { display: grid; gap: 0.1rem; }
.check-text strong { font-weight: 620; }
.check-text span { color: var(--text-muted); font-size: 0.8125rem; }

/* Toggle: a real checkbox with role="switch" */
.toggle { display: flex; align-items: flex-start; gap: 0.8rem; cursor: pointer; }
.toggle input {
  appearance: none;
  flex: none;
  position: relative;
  width: 2.5rem;
  height: 1.4rem;
  margin: 0.05rem 0 0;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  border: 1px solid var(--border-input);
  cursor: pointer;
  transition: background-color var(--dur-2) var(--ease-out), border-color var(--dur-2) var(--ease-out);
}
.toggle input::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: var(--text-muted);
  transition: transform var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out);
}
.toggle input:checked { background: var(--accent-fill); border-color: var(--accent-fill); }
.toggle input:checked::after { transform: translateX(1.1rem); background: var(--accent-contrast); }
.toggle input:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.toggle input:disabled { opacity: 0.5; }
.toggle-text { display: grid; gap: 0.1rem; }
.toggle-text strong { font-size: var(--text-sm); font-weight: 620; }
.toggle-text span { font-size: 0.8125rem; color: var(--text-muted); }

/* Radio cards: big choices (plans, amounts, agent types) */
.radio-cards { --rc-gap: 0.75rem; display: grid; gap: var(--rc-gap); grid-template-columns: repeat(auto-fit, minmax(min(var(--rc-min, 12rem), 100%), 1fr)); }
/* ui.radio_cards sets --rc-n (the option count): all options on one row when they fit, otherwise one per row,
   or two per row for an even count. So three plans never wrap as two plus an orphan. */
.radio-cards.rc-fit {
  --rc-row: calc(var(--rc-n) * var(--rc-min, 12rem) + (var(--rc-n) - 1) * var(--rc-gap));
  --rc-fallback: 100%;
  grid-template-columns: repeat(auto-fit, minmax(clamp(calc(100% / (var(--rc-n) + 1) + 0.1%), calc((var(--rc-row) - 100%) * 999), var(--rc-fallback)), 1fr));
}
.radio-cards.rc-fit.rc-even { --rc-fallback: clamp(34%, calc((2 * var(--rc-min, 12rem) + var(--rc-gap) - 100%) * 999), 100%); }
.radio-card { position: relative; display: grid; gap: 0.3rem; align-content: start; padding: 1rem 1.1rem 1rem 2.85rem; background: var(--surface); border: 1px solid var(--border-input); border-radius: var(--radius-3); cursor: pointer; transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2) var(--ease-out), background-color var(--dur-2) var(--ease-out); }
.radio-card:hover { border-color: var(--text-muted); }
.radio-card input { position: absolute; left: 1.05rem; top: 1.12rem; width: 1.05rem; height: 1.05rem; margin: 0; accent-color: var(--accent-fill); cursor: pointer; }
.radio-card-title { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.3rem 0.5rem; font-weight: 620; font-size: 0.9375rem; }
.radio-card-title > :first-child { text-wrap: balance; }
/* The tag sits top right when there is room, else on its own line under the title (never past the edge). */
.radio-card-title > .tag, .radio-card-title > .badge { flex: none; padding: 0.12rem 0.4rem; letter-spacing: 0.06em; }
.radio-card-text { font-size: 0.8125rem; color: var(--text-muted); }
/* A price never breaks mid-phrase ("€199 / month"). */
.radio-card-meta { margin-top: 0.35rem; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text); font-variant-numeric: tabular-nums; white-space: nowrap; }
.radio-card:has(input:checked) { border-color: var(--text); box-shadow: inset 0 0 0 1px var(--text); background: var(--surface-raised); }
.radio-card:has(input:checked) .radio-card-meta { color: var(--accent); }
.radio-card:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.radio-card input:focus-visible, .choices input:focus-visible, .seg > label input:focus-visible { outline: none; }
.radio-card:has(input:disabled) { opacity: 0.55; cursor: not-allowed; }

/* Segmented choices (radio buttons that fill with ink) */
.choices { display: grid; grid-template-columns: repeat(var(--choices, 4), minmax(0, 1fr)); border: 1px solid var(--border-input); border-radius: var(--radius-2); overflow: hidden; background: var(--surface); }
.choices label { position: relative; display: grid; place-items: center; min-height: 2.75rem; padding: 0 0.5rem; font-family: var(--font-mono); font-size: var(--text-sm); cursor: pointer; border-left: 1px solid var(--border-input); transition: background-color var(--dur-2) var(--ease-out); text-align: center; }
.choices label:first-child { border-left: 0; }
.choices label:hover { background: var(--surface-2); }
.choices input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.choices label:has(input:checked) { background: var(--text); color: var(--bg); }
.choices label:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: -4px; }

.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; padding-top: 1.25rem; border-top: var(--hairline); }
.form-actions .note { margin-left: auto; font-size: 0.8125rem; color: var(--text-muted); }
.form-actions-danger { margin-left: auto; }
/* Fallback submit shown only without JavaScript (auto-submit selects) */
@media (scripting: enabled) { .noscript-only { display: none !important; } }

/* ==== 12. Alerts, flash, toasts ==== */
.alert {
  --a-fg: var(--info);
  --a-bg: var(--info-soft);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.75rem;
  align-items: start;
  padding: 0.85rem 1rem;
  border: 1px solid color-mix(in oklab, var(--a-fg) 32%, transparent);
  border-left: 3px solid var(--a-fg);
  border-radius: var(--radius-2);
  background: var(--a-bg);
  color: var(--text);
  font-size: var(--text-sm);
  line-height: 1.5;
}
.alert > .icon { color: var(--a-fg); --icon-size: 1.125rem; margin-top: 0.05rem; }
.alert-title { font-weight: 650; margin-bottom: 0.1rem; }
.alert-body > * + * { margin-top: 0.35rem; }
.alert-body a { color: inherit; text-underline-offset: 0.2em; }
.alert-close { display: inline-grid; place-items: center; width: 1.75rem; height: 1.75rem; margin: -0.25rem -0.4rem -0.25rem 0; border: 0; border-radius: var(--radius-2); background: transparent; color: var(--text-muted); }
.alert-close:hover { background: color-mix(in oklab, var(--a-fg) 14%, transparent); color: var(--text); }
.alert-success { --a-fg: var(--success); --a-bg: var(--success-soft); }
.alert-warning { --a-fg: var(--warning); --a-bg: var(--warning-soft); }
.alert-danger { --a-fg: var(--danger); --a-bg: var(--danger-soft); }
/* "accent" tone = good news to notice (agent live, key sent). Ink, not ember: ember is for actions,
   and an ember tint next to the crimson error tint would read as an error. */
.alert-accent { --a-fg: var(--text); --a-bg: var(--surface-2); border-color: var(--border-strong); border-left-color: var(--text); }
.alert:not(:has(> .icon)) { grid-template-columns: minmax(0, 1fr) auto; }
.flash-stack { display: grid; gap: 0.6rem; margin-bottom: 1.25rem; }
/* app.js moves focus to an error flash after a redirect: the usual ring for keyboard users, none after a click. */
.alert[tabindex="-1"]:focus { outline: none; }
.alert[tabindex="-1"]:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; border-radius: var(--radius-2); }

/* Toasts: an inverse slab (tokens re-scoped like .inverse, see section 2) with a tone rule and icon.
   app.js announces them (errors assertively), pauses the timer on hover and focus, and moves the
   region into an open modal dialog so a toast is never stuck under the backdrop. */
.toasts { position: fixed; z-index: var(--z-toast); right: 1rem; bottom: 1rem; left: auto; display: grid; gap: 0.5rem; width: min(24rem, calc(100vw - 2rem)); margin: 0; padding: 0; pointer-events: none; }
.toast {
  --t-fg: var(--info);
  pointer-events: auto;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 0.7rem;
  align-items: start;
  padding: 0.8rem 0.9rem 0.8rem 0.8rem;
  border-radius: var(--radius-3);
  border-left: 4px solid var(--t-fg);
  background: var(--surface);
  color: var(--text);
  font-size: var(--text-sm);
  box-shadow: var(--shadow-3);
  animation: toast-in var(--dur-3) var(--ease-out);
}
.toast .icon { --icon-size: 1.05rem; margin-top: 0.05rem; color: var(--t-fg); }
.toast-success { --t-fg: var(--success); }
.toast-warning { --t-fg: var(--warning); }
.toast-danger { --t-fg: var(--danger); }
.toast-danger > div { font-weight: 560; }
.toast .alert-close { color: inherit; opacity: 0.75; }
.toast .alert-close .icon { color: inherit; }
.toast .alert-close:hover { background: transparent; opacity: 1; color: inherit; }
.toast.is-leaving { opacity: 0; transform: translateY(6px); transition: opacity var(--dur-2), transform var(--dur-2); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ==== 13. Tables (scroll inside .table-wrap, never the page) ==== */
.table-wrap {
  --wrap-bg: var(--bg);
  position: relative;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  background:
    linear-gradient(to right, var(--wrap-bg), var(--wrap-bg)) left / 1.5rem 100% no-repeat local,
    linear-gradient(to left, var(--wrap-bg), var(--wrap-bg)) right / 1.5rem 100% no-repeat local,
    linear-gradient(to right, var(--edge-shade), transparent) left / 0.75rem 100% no-repeat scroll,
    linear-gradient(to left, var(--edge-shade), transparent) right / 0.75rem 100% no-repeat scroll;
}
.card .table-wrap, .stat-tile .table-wrap { --wrap-bg: var(--surface); }
.table-wrap:focus-visible { outline-offset: -2px; }
.table-wrap > .table { min-width: var(--table-min, 40rem); }
.table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); font-variant-numeric: lining-nums; }
.table th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  padding: 0.7rem 1rem 0.65rem;
  border-bottom: var(--hairline-ink);
  white-space: nowrap;
  vertical-align: bottom;
}
.table td { padding: 0.85rem 1rem; border-bottom: var(--hairline); vertical-align: middle; }
.table tbody tr:last-child td { border-bottom: 0; }
.table tbody tr { transition: background-color var(--dur-1) var(--ease-out); }
.table tbody tr:hover { background: color-mix(in oklab, var(--surface-2) 55%, transparent); }
.table th:first-child, .table td:first-child { padding-left: 0; }
.table th:last-child, .table td:last-child { padding-right: 0; }
.card .table th:first-child, .card .table td:first-child { padding-left: 1.4rem; }
.card .table th:last-child, .card .table td:last-child { padding-right: 1.4rem; }
.table .num, .table th.num { text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.table td.num { font-size: 0.8125rem; }
.table .actions { text-align: right; white-space: nowrap; width: 1%; }
/* Row actions never scroll out of reach: in a .table-wrap the actions cells are pinned to the right edge on the
   wrap's background. While the table overflows (app.js: .is-scrollable) a hairline sets them apart, and a shade
   shows while columns are hidden behind them (.is-fade-end). Give the tfoot cell under them class="actions" too. */
.table-wrap .table .actions { position: sticky; right: 0; z-index: 1; background: var(--wrap-bg); }
.table-wrap .table tbody tr:hover > .actions { background: color-mix(in oklab, var(--surface-2) 55%, var(--wrap-bg)); }
.table-wrap.is-scrollable .table .actions { box-shadow: inset 1px 0 0 var(--border); }
.table-wrap.is-fade-end .table .actions::before { content: ""; position: absolute; top: 0; bottom: 0; right: 100%; width: 0.75rem; background: linear-gradient(to left, var(--edge-shade), transparent); pointer-events: none; }
.table .cell-title { display: grid; gap: 0.1rem; }
.table .cell-title strong, .table .cell-title a { font-weight: 620; }
/* Both lines stay on one line: a slug or an email broken at a hyphen reads worse than a table that scrolls
   (and the row actions stay pinned while it does). Keep the second line short. */
.table .cell-title > * { white-space: nowrap; }
.table .cell-title span, .table .cell-title code { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); }
.table code { font-family: var(--font-mono); font-size: 0.8125rem; }
.table a:not(.btn) { text-decoration: none; }
.table a:not(.btn):hover { color: var(--accent); text-decoration: underline; text-underline-offset: 0.2em; }
.table tfoot td, .table .total td { border-top: var(--hairline-ink); border-bottom: 0; font-weight: 620; }
.table-compact td { padding-block: 0.55rem; }
.table-compact th { padding-block: 0.5rem; }
.table-foot { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.5rem 1rem; padding: 0.8rem 0 0; border-top: var(--hairline); font-size: 0.8125rem; color: var(--text-muted); }
.card .table-foot { padding: 0.8rem 1.4rem; }
.table-foot .num { color: var(--text); }
tr.is-muted td { color: var(--text-muted); }
tr.is-muted .strike, tr.is-revoked code { text-decoration: line-through; }

/* ==== 14. Stats (KPI strip and tiles) ==== */
.stats { display: grid; grid-template-columns: repeat(var(--stats, 4), minmax(0, 1fr)); background: var(--surface); border: var(--hairline); border-radius: var(--radius-3); box-shadow: var(--shadow-1); }
.stats > .stat + .stat { border-left: var(--hairline); }
.stat { display: grid; align-content: start; gap: 0.5rem; padding: 1.3rem 1.4rem 1.25rem; min-width: 0; }
.stat-tile { background: var(--surface); border: var(--hairline); border-radius: var(--radius-3); box-shadow: var(--shadow-1); }
.stat-label { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; font-size: var(--text-sm); font-weight: 560; color: var(--text-muted); }
.stat-label .icon { --icon-size: 1rem; color: var(--text-subtle); }
.stat-value { font-family: var(--font-sans); font-size: clamp(1.75rem, 1.4rem + 0.9vw, 2.125rem); line-height: 1.05; font-weight: 580; letter-spacing: -0.035em; font-variant-numeric: lining-nums proportional-nums; overflow-wrap: anywhere; }
.stat-value small { font-size: 0.95rem; font-weight: 500; letter-spacing: -0.01em; color: var(--text-muted); margin-left: 0.2rem; }
.stat-meta { font-size: 0.8125rem; color: var(--text-muted); }
.stat-meta .num { color: var(--text); }
.delta { display: inline-flex; align-items: center; gap: 0.2rem; font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; color: var(--text-muted); }
.delta .icon { --icon-size: 0.8rem; stroke-width: 2.25; }
.delta-good { color: var(--success); }
.delta-bad { color: var(--danger); }
@media (max-width: 1180px) {
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .stats > .stat:nth-child(odd) { border-left: 0; }
  .stats > .stat:nth-child(n+3) { border-top: var(--hairline); }
  /* An odd last stat spans the row instead of sitting beside an empty cell. */
  .stats > .stat:last-child:nth-child(odd) { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .stats { grid-template-columns: minmax(0, 1fr); }
  .stats > .stat + .stat { border-left: 0; border-top: var(--hairline); }
}

/* ==== 15. Meters: the measuring tape (fill always means "used") ==== */
.tape { position: relative; --value: 0; --divs: 5; }
.tape-track {
  position: relative;
  height: 2.25rem;
  background-color: var(--tape-bg);
  border-block: 1px solid var(--tape-edge);
  overflow: hidden;
}
/* Graduations: major every 1/divs, half every 1/(2 divs), minor every 1/(10 divs) */
.tape-track::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background-image:
    linear-gradient(to right, var(--tape-tick) 1px, transparent 1px),
    linear-gradient(to right, var(--tape-tick) 1px, transparent 1px),
    linear-gradient(to right, color-mix(in oklab, var(--tape-tick) 55%, transparent) 1px, transparent 1px);
  background-size: calc(100% / var(--divs)) 42%, calc(100% / (var(--divs) * 2)) 28%, calc(100% / (var(--divs) * 10)) 16%;
  background-repeat: repeat-x;
  background-position: 0 0;
  border-right: 1px solid var(--tape-tick);
}
.tape-fill {
  position: absolute;
  inset: 0 auto 0 0;
  z-index: 1;
  width: calc(min(var(--value), 1) * 100%);
  background: var(--tape-fill);
  box-shadow: inset 0 -3px 0 var(--accent-fill);
  transition: width var(--dur-4) var(--ease-tape);
}
.tape-needle {
  position: absolute;
  z-index: 3;
  top: -6px;
  bottom: -6px;
  left: calc(min(var(--value), 1) * 100%);
  width: 2px;
  margin-left: -1px;
  background: var(--accent-fill);
  transition: left var(--dur-4) var(--ease-tape);
}
.tape-bodyrow { position: relative; }
.tape-flag {
  position: absolute;
  z-index: 3;
  bottom: calc(100% + 8px);
  left: calc(min(var(--value), 1) * 100%);
  transform: translateX(-50%);
  padding: 0.16rem 0.45rem;
  background: var(--accent-fill);
  color: var(--accent-contrast);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  border-radius: var(--radius-1);
  white-space: nowrap;
}
.tape-flag::after { content: ""; position: absolute; top: 100%; left: 50%; margin-left: -4px; border: 4px solid transparent; border-top-color: var(--accent-fill); }
.tape-has-flag { padding-top: 2rem; }
/* Projection tick: where usage lands at period end at the current pace */
.tape-proj { position: absolute; z-index: 3; top: -4px; bottom: -4px; left: calc(min(var(--proj), 1) * 100%); width: 0; border-left: 2px dotted var(--text); }
.tape-proj-over { border-left-color: var(--danger); }
/* Segments: one per finished job; the in-progress one is hatched */
.tape-seg { position: absolute; z-index: 1; top: 0; bottom: 0; left: calc(var(--from) * 100%); width: calc((var(--to) - var(--from)) * 100%); background: var(--tape-fill); box-shadow: inset 0 -3px 0 var(--accent-fill), inset -1px 0 0 var(--rule); }
.tape-seg.is-live { background: repeating-linear-gradient(135deg, var(--tape-hatch) 0 4px, transparent 4px 8px); box-shadow: inset 0 -3px 0 var(--accent-fill); }
.tape-scale { position: relative; height: 1.1rem; margin-top: 0.35rem; font-family: var(--font-mono); font-size: var(--text-2xs); color: var(--tape-number); font-variant-numeric: tabular-nums; }
.tape-scale span { position: absolute; top: 0; transform: translateX(-50%); white-space: nowrap; }
.tape-scale span:first-child { transform: none; }
.tape-scale span:last-child { transform: translateX(-100%); }
.tape-legend { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.25rem 1rem; margin-top: 0.5rem; font-size: 0.8125rem; color: var(--text-muted); }
.tape-legend .num { color: var(--text); }
.tape-sm .tape-track { height: 1.4rem; }
.tape-sm .tape-needle { top: -4px; bottom: -4px; }
.tape-sm .tape-track::before { background-size: calc(100% / var(--divs)) 50%, calc(100% / (var(--divs) * 2)) 30%, calc(100% / (var(--divs) * 10)) 0; }
.tape-sm .tape-scale { margin-top: 0.25rem; }
.tape.is-warning { --accent-fill: var(--warning); }
.tape.is-danger { --accent-fill: var(--danger); }

/* Bar meter: a quiet single-line meter for tables (share of tokens, quotas) */
.bar-meter { display: flex; align-items: center; gap: 0.6rem; min-width: 7rem; }
.bar-meter-track { position: relative; flex: 1; height: 6px; background: var(--surface-2); border-radius: 3px; overflow: hidden; box-shadow: inset 0 0 0 1px var(--border); }
.bar-meter-fill { position: absolute; inset: 0 auto 0 0; width: calc(min(var(--value, 0), 1) * 100%); background: var(--text); border-radius: 3px; }
.bar-meter-label { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); min-width: 2.75rem; text-align: right; font-variant-numeric: tabular-nums; }
.bar-meter.is-accent .bar-meter-fill { background: var(--accent-fill); }
.bar-meter.is-warning .bar-meter-fill { background: var(--warning); }
.bar-meter.is-danger .bar-meter-fill { background: var(--danger); }

/* ==== 16. Tabs and segmented controls ==== */
/* Tabs scroll sideways when they do not fit. Each tab carries a little side padding (pulled back by the
   list's negative margin, so text still lines up) so the focus ring is drawn inside the scroller, never clipped.
   app.js adds .is-fade-start / .is-fade-end while there is more to scroll, and scrolls the current tab into view. */
/* The list pulls back its side padding (labels align with the column) but its rule stays on the column: the border
   is drawn by a border-image inset by --tab-pad. A row that spans a card on purpose sets border-image: none. */
.tabs { --tab-pad: 0.375rem; display: flex; gap: 0.25rem calc(1.5rem - 2 * var(--tab-pad)); margin-inline: calc(-1 * var(--tab-pad)); border-bottom: var(--hairline); border-image: linear-gradient(to right, transparent var(--tab-pad), var(--border) var(--tab-pad), var(--border) calc(100% - var(--tab-pad)), transparent calc(100% - var(--tab-pad))) 0 0 1 0; overflow-x: auto; scrollbar-width: none; }
.tabs::-webkit-scrollbar { display: none; }
.tabs.is-fade-end, .portal-nav.is-fade-end { -webkit-mask-image: linear-gradient(to right, black calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, black calc(100% - 3rem), transparent); }
.tabs.is-fade-start, .portal-nav.is-fade-start { -webkit-mask-image: linear-gradient(to right, transparent, black 3rem); mask-image: linear-gradient(to right, transparent, black 3rem); }
.tabs.is-fade-start.is-fade-end, .portal-nav.is-fade-start.is-fade-end { -webkit-mask-image: linear-gradient(to right, transparent, black 3rem, black calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, transparent, black 3rem, black calc(100% - 3rem), transparent); }
.tab {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 0.45rem;
  padding: 0.7rem var(--tab-pad, 0.375rem) 0.75rem;
  border: 0;
  background: none;
  color: var(--text-muted);
  font-size: 0.9375rem;
  font-weight: 560;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.tab:hover { color: var(--text); }
.tab:focus-visible { outline-offset: -2px; border-radius: var(--radius-2); }
.tab[aria-selected="true"], .tab[aria-current="page"], .tab.is-active { color: var(--text); }
/* The underline spans the label, not the side padding, so the first one starts on the column like the rule. */
.tab[aria-selected="true"]::after, .tab[aria-current="page"]::after, .tab.is-active::after { content: ""; position: absolute; left: var(--tab-pad, 0); right: var(--tab-pad, 0); bottom: -1px; height: 2px; background: var(--accent-fill); }
.tab .count { height: 1.25rem; min-width: 1.25rem; }
.tabs-mono .tab { font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 500; }
.tab-panel { padding-top: 1.25rem; }
.tab-panel:focus-visible { outline-offset: 4px; }
@media (scripting: none) {
  [role="tabpanel"][hidden] { display: block !important; }
  [role="tablist"][data-tabs] { display: none; }
}

.seg { display: inline-flex; border: 1px solid var(--border-input); border-radius: var(--radius-2); overflow: hidden; background: var(--surface); max-width: 100%; }
.seg > a, .seg > button, .seg > label { display: inline-flex; align-items: center; gap: 0.35rem; white-space: nowrap; min-height: 2.125rem; padding: 0 0.75rem; border: 0; background: none; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); text-decoration: none; cursor: pointer; position: relative; }
.seg > * + * { border-left: 1px solid var(--border-input) !important; }
.seg > a:hover, .seg > button:hover, .seg > label:hover { color: var(--text); background: var(--surface-2); }
.seg > [aria-current="true"], .seg > [aria-current="page"], .seg > [aria-pressed="true"], .seg > [aria-checked="true"], .seg > label:has(input:checked) { background: var(--text); color: var(--bg); }
.seg > label input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.seg > label:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: -3px; }
.seg .icon { --icon-size: 0.95rem; }

/* ==== 17. Code, keys ==== */
code, kbd, samp { font-family: var(--font-mono); }
:not(pre) > code { font-size: 0.875em; padding: 0.1em 0.35em; border-radius: var(--radius-1); background: var(--surface-2); color: var(--text); }
kbd { display: inline-block; padding: 0.05em 0.4em; border: 1px solid var(--border-strong); border-bottom-width: 2px; border-radius: var(--radius-2); font-size: 0.8em; background: var(--surface); }
.code-block { position: relative; border-radius: var(--radius-3); background: var(--code-bg); border: 1px solid var(--code-border); color: var(--code-text); min-width: 0; }
.code-head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; min-height: 2.5rem; padding: 0.3rem 0.4rem 0.3rem 1rem; border-bottom: 1px solid color-mix(in oklab, var(--code-text) 12%, transparent); background: var(--code-head); border-radius: var(--radius-3) var(--radius-3) 0 0; }
.code-lang { font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--code-muted); }
.code-head .tabs { border: 0; gap: calc(1rem - 2 * var(--tab-pad)); }
.code-head-tabs > .tabs { flex: 1 1 auto; min-width: 0; }
.code-head > .code-copy { flex: none; }
.code-head .tab { color: var(--code-muted); font-family: var(--font-mono); font-size: var(--text-xs); padding: 0.55rem var(--tab-pad); font-weight: 500; }
.code-head .tab:hover, .code-head .tab[aria-selected="true"] { color: var(--code-text); }
.code-copy { --btn-fg: var(--code-text); --btn-bd: transparent; --btn-bg: transparent; min-height: 2rem; font-size: var(--text-xs); }
.code-copy:hover { --btn-bg: color-mix(in oklab, var(--code-text) 12%, transparent); --btn-bd: transparent; }
/* Phones: the tabs get the head row. Copy is icon-only (its label stays for screen readers and comes back for
   "Copied"), tabs are tighter, so four short tabs fit in about 300px; longer ones wrap to a second row, never
   hidden behind a scroll. */
@media (max-width: 480px) {
  .code-head-tabs { gap: 0.25rem; padding-left: 0.75rem; }
  .code-head .tabs { flex-wrap: wrap; gap: 0 0.125rem; --tab-pad: 0.3rem; }
  .code-head-tabs > .code-copy { min-width: 2rem; padding-inline: 0.45rem; gap: 0; }
  .code-head-tabs > .code-copy:not(.is-copied) [data-copy-label] { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .code-head-tabs > .code-copy.is-copied { gap: 0.35rem; }
}
pre.code, .code-block pre {
  margin: 0;
  padding: 1rem 1.2rem 1.1rem;
  overflow-x: auto;
  font-family: var(--font-mono);
  font-size: 0.8125rem;
  line-height: 1.7;
  tab-size: 2;
  color: var(--code-text);
  background: transparent;
  scrollbar-width: thin;
}
pre.code { background: var(--code-bg); border: 1px solid var(--code-border); border-radius: var(--radius-3); }
.code-block pre:focus-visible { outline-offset: -2px; }
.code-block > .code-copy { position: absolute; top: 0.4rem; right: 0.4rem; }
/* ui.code_tabs keeps its Copy button in the head row now, so panels need no room for a floating one
   (this also neutralizes older page rules that padded the code under it on phones). */
.code-block > .code-tab-panel > pre { padding: 1rem 1.2rem 1.1rem; }
/* Long lines: the same edge fade as .tabs while there is more to scroll (app.js sets the classes). */
.code-block pre.is-fade-end { -webkit-mask-image: linear-gradient(to right, black calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, black calc(100% - 3rem), transparent); }
.code-block pre.is-fade-start { -webkit-mask-image: linear-gradient(to right, transparent, black 3rem); mask-image: linear-gradient(to right, transparent, black 3rem); }
.code-block pre.is-fade-start.is-fade-end { -webkit-mask-image: linear-gradient(to right, transparent, black 3rem, black calc(100% - 3rem), transparent); mask-image: linear-gradient(to right, transparent, black 3rem, black calc(100% - 3rem), transparent); }
.code .c, .code-block .c { color: var(--code-muted); }
.code .s, .code-block .s { color: var(--code-string); }
.code .k, .code-block .k { color: var(--code-key); }
.code .a, .code-block .a { color: var(--code-accent); }
.code-foot { display: flex; flex-wrap: wrap; gap: 0.35rem 1.25rem; padding: 0.6rem 1.2rem 0.7rem; border-top: 1px solid color-mix(in oklab, var(--code-text) 12%, transparent); font-family: var(--font-mono); font-size: var(--text-xs); color: var(--code-muted); }
.code-foot b { color: var(--code-text); font-weight: 500; }
.code-panel-label { display: none; }
/* Without JavaScript: no dead Copy or Show buttons, code tabs become labelled blocks, masked keys are readable. */
@media (scripting: none) {
  [data-copy], [data-copy-target], [data-reveal-target] { display: none !important; }
  .code-head-tabs { display: none; }
  .code-panel-label { display: block; padding: 0.75rem 1.2rem 0; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--code-muted); }
  .code-tab-panel + .code-tab-panel { border-top: 1px solid color-mix(in oklab, var(--code-text) 12%, transparent); }
  .keyfield.is-masked code { filter: none; user-select: all; }
}

/* Key reveal: shown once */
.keybox { display: grid; gap: 0.75rem; padding: 1rem 1rem 1.1rem; border: 1px solid var(--accent-line); border-radius: var(--radius-3); background: var(--accent-soft); }
.keybox-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem 0.75rem; }
.keybox-head strong { font-size: var(--text-sm); font-weight: 650; }
.keyfield { display: flex; align-items: stretch; background: var(--surface); border: 1px solid var(--border-input); border-radius: var(--radius-2); box-shadow: var(--shadow-inset); overflow: hidden; }
.keyfield code { flex: 1; min-width: 0; padding: 0.75rem 0.9rem; background: none; font-size: 0.875rem; letter-spacing: 0.02em; word-break: break-all; user-select: all; border-radius: 0; }
.keyfield.is-masked code { filter: blur(5px); user-select: none; }
.keybox-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.keybox-note { display: flex; gap: 0.5rem; align-items: flex-start; font-size: 0.8125rem; color: var(--text); }
.keybox-note .icon { --icon-size: 1rem; color: var(--accent); margin-top: 0.1rem; }
.key-prefix { display: inline-flex; align-items: center; gap: 0.3rem; padding: 0.12rem 0.45rem; border: 1px solid var(--border); border-radius: var(--radius-1); background: var(--surface-2); font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text); white-space: nowrap; }
.key-prefix.is-revoked { text-decoration: line-through; color: var(--text-muted); }

/* ==== 18. Empty state, pagination, breadcrumb, dialog, tooltip, skeleton ==== */
.empty { display: grid; justify-items: center; gap: 0.6rem; padding: clamp(2rem, 1.5rem + 3vw, 3.5rem) 1.5rem; text-align: center; }
.empty-icon { display: grid; place-items: center; width: 3rem; height: 3rem; margin-bottom: 0.25rem; border: 1px dashed var(--border-strong); border-radius: 50%; color: var(--text-muted); }
.empty-icon .icon { --icon-size: 1.3rem; }
.empty-title { font-family: var(--font-display); font-size: 1.375rem; font-weight: 420; letter-spacing: -0.015em; }
.empty-text { max-width: 28rem; color: var(--text-muted); font-size: var(--text-sm); }
.empty .btn { margin-top: 0.5rem; }
.empty-bordered { border: 1px dashed var(--border-strong); border-radius: var(--radius-3); }

.pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem; font-size: var(--text-sm); }
.pagination-pages { display: flex; flex-wrap: wrap; gap: 0.25rem; list-style: none; margin: 0; padding: 0; }
.page-link { display: inline-grid; place-items: center; min-width: 2.25rem; height: 2.25rem; padding: 0 0.6rem; border: 1px solid transparent; border-radius: var(--radius-2); font-family: var(--font-mono); font-size: var(--text-sm); color: var(--text-muted); text-decoration: none; }
a.page-link:hover { border-color: var(--border-input); color: var(--text); }
.page-link[aria-current="page"] { background: var(--text); color: var(--bg); }
.page-link.is-disabled { opacity: 0.4; }
.pagination-info { color: var(--text-muted); min-width: 0; }
/* Phones: previous, "Page 12 of 30", next. The page numbers would wrap onto a second line. */
@media (max-width: 480px) {
  .pagination { flex-wrap: nowrap; }
  .pagination-pages { flex-wrap: nowrap; }
  .pagination-pages > li:not(:first-child):not(:last-child) { display: none; }
}

.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 0; padding: 0; list-style: none; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); }
.crumbs li { display: inline-flex; align-items: center; gap: 0.5rem; min-width: 0; overflow-wrap: anywhere; }
/* The "/" ends the previous item, so a long last crumb that wraps starts its line with its own text. */
.crumbs li:not(:last-child)::after { content: "/"; color: var(--text-subtle); }
.crumbs a { text-decoration: none; }
.crumbs a:hover { color: var(--accent); }
.crumbs [aria-current="page"] { color: var(--text); font-weight: 500; min-width: 0; overflow-wrap: anywhere; }

dialog.dialog {
  width: min(32rem, calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
  padding: 0;
  border: var(--hairline);
  border-radius: var(--radius-4);
  background: var(--surface-raised);
  color: var(--text);
  box-shadow: var(--shadow-3);
  overflow: auto;
}
dialog.dialog-lg { width: min(48rem, calc(100vw - 2rem)); }
dialog.dialog::backdrop { background: var(--overlay); }
dialog.dialog[open] { animation: dialog-in var(--dur-3) var(--ease-out); }
@keyframes dialog-in { from { opacity: 0; transform: translateY(10px) scale(0.99); } to { opacity: 1; transform: none; } }
.dialog-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; padding: 1.25rem 1.4rem 0; }
.dialog-title { font-family: var(--font-display); font-size: 1.5rem; line-height: 1.15; font-weight: 420; letter-spacing: -0.02em; }
.dialog-body { padding: 0.9rem 1.4rem 1.25rem; color: var(--text-muted); }
.dialog-body > * + * { margin-top: 0.75rem; }
.dialog-foot { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.6rem; padding: 1rem 1.4rem; border-top: var(--hairline); background: var(--surface); }

[data-tooltip] { position: relative; }
[data-tooltip]:hover::after, [data-tooltip]:focus-visible::after {
  content: attr(data-tooltip);
  position: absolute;
  z-index: var(--z-overlay);
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  width: max-content;
  max-width: min(16rem, calc(100vw - 2rem));
  padding: 0.4rem 0.6rem;
  border-radius: var(--radius-2);
  background: var(--text);
  color: var(--bg);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0;
  text-transform: none;
  white-space: normal;
  text-wrap: pretty;
  text-align: left;
  pointer-events: none;
  animation: tip-in var(--dur-2) var(--ease-out) 0.25s both;
}
@keyframes tip-in { from { opacity: 0; } to { opacity: 1; } }
/* Content only exists while shown, so an idle tooltip never widens a scroll area. */
[data-tooltip-pos="bottom"]:hover::after, [data-tooltip-pos="bottom"]:focus-visible::after { bottom: auto; top: calc(100% + 8px); }
[data-tooltip-pos="left"]:hover::after, [data-tooltip-pos="left"]:focus-visible::after { left: auto; right: 0; transform: none; }
/* app.js sets data-tip-x / data-tip-y on hover and focus when a centered tooltip would leave the viewport. */
[data-tip-x="start"]:hover::after, [data-tip-x="start"]:focus-visible::after { left: 0; right: auto; transform: none; }
[data-tip-x="end"]:hover::after, [data-tip-x="end"]:focus-visible::after { left: auto; right: 0; transform: none; }
[data-tip-y="bottom"]:hover::after, [data-tip-y="bottom"]:focus-visible::after { bottom: auto; top: calc(100% + 8px); }

.skeleton { display: block; border-radius: var(--radius-2); background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%) 0 0 / 200% 100%; animation: shimmer 1.4s linear infinite; }
.skeleton-text { height: 0.8em; margin-block: 0.35em; }
.skeleton-title { height: 1.6rem; width: 45%; }
.skeleton-block { height: 8rem; }
@keyframes shimmer { to { background-position: -200% 0; } }

/* ==== 18b. Menu, stepper, disclosure, toolbar ==== */
/* Menu (ui.menu): a button with popovertarget opens a list of links or buttons in the top layer, so a
   menu in a scrolling table is never clipped. Light dismiss and Escape come from the browser; app.js places
   it under its button, moves focus into it and adds arrow keys. Without JavaScript it opens centered. */
.menu-pop {
  min-width: 12rem;
  max-width: min(20rem, calc(100vw - 1rem));
  max-height: min(24rem, calc(100vh - 2rem));
  padding: 0.35rem;
  border: var(--hairline);
  border-radius: var(--radius-3);
  background: var(--surface-raised);
  color: var(--text);
  box-shadow: var(--shadow-3);
  overflow: auto;
}
.menu-pop.is-placed { inset: auto; margin: 0; }
.menu-pop:popover-open { animation: menu-in var(--dur-2) var(--ease-out); }
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.menu-list { display: grid; gap: 1px; margin: 0; padding: 0; list-style: none; }
.menu-list form { margin: 0; }
.menu-item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  min-height: 2.5rem;
  padding: 0.45rem 0.7rem;
  border: 0;
  border-radius: var(--radius-2);
  background: none;
  color: var(--text);
  font: inherit;
  font-size: var(--text-sm);
  font-weight: 540;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.menu-item:hover, .menu-item:focus-visible { background: var(--surface-2); }
.menu-item:focus-visible { outline-offset: -2px; }
.menu-item .icon { --icon-size: 1rem; color: var(--text-muted); }
.menu-item.is-danger { color: var(--danger); }
.menu-item.is-danger .icon { color: currentColor; }
.menu-sep { height: 1px; margin: 0.3rem 0.25rem; background: var(--border); }
.menu-label { padding: 0.45rem 0.7rem 0.2rem; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); }
.menu-button[aria-expanded="true"] { --btn-bg: var(--surface-2); }

/* Stepper (ui.stepper): an ordered list, the current step has aria-current="step". Ink, never ember.
   Wide rows are a grid of auto columns: each step starts at its min-content width (longest word) and the free room
   goes equally to the steps that still want more. Never an ellipsis ("Réalisation et tests" read "Réalisation e...").
   Narrow rows use the compact mode below, which starts at the width the full row needs (see .stepper-wrap), so a label
   never wraps in the wide row: a wrapped label keeps the full width of its grid column (CSS cannot shrink a wrapped
   box to its longest line), which left uneven gaps before the next connector. Balance stays as the fallback for
   browsers without container queries between 641 px and that width. */
.stepper { display: grid; grid-auto-flow: column; grid-auto-columns: auto; justify-content: start; align-items: center; column-gap: 0.6rem; margin: 0; padding: 0; list-style: none; font-size: var(--text-sm); }
.step { display: flex; align-items: center; gap: 0.55rem; min-width: 0; color: var(--text-muted); }
.step + .step::before { content: ""; flex: none; width: clamp(1rem, 4vw, 2.5rem); height: 1px; margin-right: 0.05rem; background: var(--border-strong); }
.step.is-done + .step::before { background: var(--text); }
.step-mark { display: inline-grid; place-items: center; flex: none; width: 1.75rem; height: 1.75rem; border: 1px solid var(--border-input); border-radius: 50%; background: var(--surface); font-family: var(--font-mono); font-size: var(--text-xs); font-variant-numeric: tabular-nums; color: var(--text-muted); }
.step-mark .icon { --icon-size: 0.85rem; stroke-width: 2.25; }
.step.is-done { color: var(--text); }
.step.is-done .step-mark { border-color: var(--text); color: var(--text); }
.step[aria-current="step"] { color: var(--text); font-weight: 620; }
.step[aria-current="step"] .step-mark { border-color: var(--text); background: var(--text); color: var(--bg); }
.step-label { line-height: 1.25; text-wrap: balance; }
.stepper-count { display: none; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); }
/* Compact: numbered marks for every step, the label of the current one, and "Step 2 of 4" above. Only the current step
   gives way: its label wraps, and a word breaks only when it cannot fit at all (320 px). It applies on phones and in
   any container narrower than the full row needs (never under 34rem, where the row would crowd); the two blocks below
   carry the same rules (the media query covers browsers without container queries).
   The wrap fills its container and is never sized by its content: the container query reads its width, and inline-size
   containment makes its content width 0, so in a shrink-to-fit context (a flex item, a grid auto track, inline-block,
   fit-content) it would collapse to 0 px and break the label one letter per line. inline-size: 100% fills a flex row or
   a grid track; contain-intrinsic-inline-size gives inline-block and fit-content the width of the full row (34.5em: a hair over
   the switch at 34em, so it never lands in compact mode).
   --stepper-fit (set by the macro from the step count and label lengths, in rem, at least 34) is the width the full row
   needs. The wrap's font-size carries it (1em = fit / 34 rem), so one query in em switches each stepper at its own width;
   the count and the list set their sizes in rem, so this font-size never shows in the text. */
.stepper-wrap { container: stepper / inline-size; inline-size: 100%; contain-intrinsic-inline-size: 34.5em; font-size: calc(1rem * var(--stepper-fit, 34) / 34); }
@media (max-width: 640px) {
  .stepper-count { display: block; margin-bottom: 0.5rem; }
  .stepper { display: flex; gap: 0.4rem; }
  .step { gap: 0.4rem; }
  .step:not([aria-current="step"]) { flex: none; }
  .step:not([aria-current="step"]) .step-label { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .step[aria-current="step"] .step-label { min-width: 0; overflow-wrap: break-word; hyphens: auto; }
  .step + .step::before { width: clamp(0.75rem, 3vw, 1.5rem); }
}
@container stepper (max-width: 34em) {
  .stepper-count { display: block; margin-bottom: 0.5rem; }
  .stepper { display: flex; gap: 0.4rem; }
  .step { gap: 0.4rem; }
  .step:not([aria-current="step"]) { flex: none; }
  .step:not([aria-current="step"]) .step-label { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .step[aria-current="step"] .step-label { min-width: 0; overflow-wrap: break-word; hyphens: auto; }
  .step + .step::before { width: clamp(0.75rem, 3vw, 1.5rem); }
}
/* Tight: phones under 400 px, and any stepper under 20rem (a narrow side card on a desktop), as the phone. */
@media (max-width: 400px) { .stepper, .step { gap: 0.3rem; } .step + .step::before { width: 0.5rem; } .step-mark { width: 1.5rem; height: 1.5rem; } }
@container stepper (max-width: 20rem) { .stepper, .step { gap: 0.3rem; } .step + .step::before { width: 0.5rem; } .step-mark { width: 1.5rem; height: 1.5rem; } }

/* Disclosure (ui.disclosure): a styled details / summary. Stack several in .disclosures for an FAQ. */
.disclosures { border-top: var(--hairline); }
.disclosure { border-bottom: var(--hairline); }
.disclosure > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.05rem 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: 1.1875rem;
  font-weight: 420;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.disclosure > summary::-webkit-details-marker { display: none; }
.disclosure > summary .icon { flex: none; color: var(--text-muted); transition: transform var(--dur-2) var(--ease-out); }
.disclosure > summary:hover .icon { color: var(--text); }
.disclosure[open] > summary .icon { transform: rotate(180deg); }
.disclosure > summary:focus-visible { outline-offset: 2px; }
.disclosure-body { max-width: 44rem; padding: 0 0 1.35rem; color: var(--text-muted); }
.disclosure-body > * + * { margin-top: 0.6rem; }
.disclosure-body a { color: var(--text); }
.disclosure-sm > summary { font-family: var(--font-sans); font-size: var(--text-base); font-weight: 600; letter-spacing: 0; padding: 0.8rem 0; }

/* Toolbar: a filter row above a table (selects, search, date range) with actions at the end (Export CSV).
   Put it in a GET form so filters work without JavaScript; autosubmit selects show "Apply" without it. */
.toolbar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.75rem 1rem; padding: 0.9rem 1rem; border: var(--hairline); border-radius: var(--radius-3); background: var(--surface); }
.card > .toolbar { border: 0; border-bottom: var(--hairline); border-radius: var(--radius-3) var(--radius-3) 0 0; padding-inline: 1.4rem; }
.toolbar > .field { flex: 1 1 9.5rem; max-width: 15rem; gap: 0.3rem; }
.toolbar > .field-grow { max-width: 22rem; flex-grow: 2; }
.toolbar .label { font-size: 0.8125rem; }
.toolbar-end { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-left: auto; }
.toolbar-note { flex-basis: 100%; font-size: 0.8125rem; color: var(--text-muted); }
@media (max-width: 560px) {
  .toolbar > .field { flex-basis: 100%; max-width: none; }
  .toolbar-end { margin-left: 0; }
}

/* ==== 19. Lists: definition list, receipt, timeline ==== */
.dl { display: grid; grid-template-columns: minmax(8rem, max-content) minmax(0, 1fr); gap: 0; margin: 0; font-size: var(--text-sm); }
.dl > dt, .dl > div > dt { padding: 0.65rem 1.5rem 0.65rem 0; color: var(--text-muted); border-bottom: var(--hairline); }
.dl > dd, .dl > div > dd { margin: 0; padding: 0.65rem 0; border-bottom: var(--hairline); min-width: 0; overflow-wrap: anywhere; }
.dl > div { display: contents; }
.dl-stacked { grid-template-columns: minmax(0, 1fr); }
.dl-stacked > dt, .dl-stacked > div > dt { padding-bottom: 0; border-bottom: 0; font-size: var(--text-xs); font-family: var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; }
.dl-stacked > dd, .dl-stacked > div > dd { padding-top: 0.15rem; }
@media (max-width: 520px) {
  .dl { grid-template-columns: minmax(0, 1fr); }
  .dl > dt, .dl > div > dt { padding-bottom: 0; border-bottom: 0; }
  .dl > dd, .dl > div > dd { padding-top: 0.1rem; }
}
/* Receipt: dotted leaders and mono figures, like a neat bill */
.receipt { display: grid; gap: 0.45rem; margin: 0; padding: 0.9rem 1rem; background: var(--bg); border: 1px dashed var(--border-strong); border-radius: var(--radius-2); font-size: var(--text-sm); }
.receipt > div { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.1rem 0.5rem; color: var(--text-muted); }
.receipt > div::before { content: ""; order: 1; flex: 1; min-width: 1rem; border-bottom: 1px dotted var(--border-input); transform: translateY(-0.25rem); }
/* The label keeps at least 8.5rem and takes free room before the leader does (up to its own width); a value that
   does not fit beside it drops to its own line, right-aligned, instead of crushing the label ("Tarif, / paiement à /
   l'usage" next to "12,00 € le million" on a phone). A value wider than the whole row wraps rather than overflowing. */
.receipt dt { order: 0; flex: 99 1 8.5rem; max-width: max-content; }
.receipt dd { order: 2; margin: 0 0 0 auto; font-family: var(--font-mono); color: var(--text); font-variant-numeric: tabular-nums; text-align: right; }
.receipt .receipt-total { padding-top: 0.5rem; margin-top: 0.15rem; border-top: var(--hairline-ink); color: var(--text); font-weight: 620; }
.receipt .receipt-total dd { font-weight: 500; font-size: var(--text-base); }
.receipt .receipt-eq { display: block; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); }
.receipt .receipt-eq::before { display: none; }
.receipt .receipt-eq dd { margin: 0; text-align: left; }

.timeline { list-style: none; margin: 0; padding: 0; position: relative; }
.timeline-item { position: relative; display: grid; grid-template-columns: 1.5rem minmax(0, 1fr) auto; gap: 0 0.85rem; padding-bottom: 1.1rem; }
.timeline-item::before { content: ""; position: absolute; left: calc(0.75rem - 0.5px); top: 1.2rem; bottom: 0; width: 1px; background: var(--border); }
.timeline-item:last-child { padding-bottom: 0; }
.timeline-item:last-child::before { display: none; }
.timeline-dot { position: relative; z-index: 1; display: grid; place-items: center; width: 1.5rem; height: 1.5rem; border-radius: 50%; background: var(--surface); border: 1px solid var(--border-strong); color: var(--text-muted); }
.timeline-dot .icon { --icon-size: 0.8rem; stroke-width: 2; }
.timeline-dot.is-accent { border-color: var(--text); color: var(--bg); background: var(--text); }
.timeline-dot.is-success { border-color: var(--success); color: var(--success); background: var(--success-soft); }
.timeline-dot.is-danger { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }
.timeline-body { font-size: var(--text-sm); padding-top: 0.1rem; min-width: 0; }
.timeline-body strong { font-weight: 620; }
.timeline-body p { color: var(--text-muted); font-size: 0.8125rem; margin-top: 0.1rem; }
.timeline-time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); white-space: nowrap; padding-top: 0.2rem; }

/* Activity list: date, what, amount + badge (billing activity) */
.activity { list-style: none; margin: 0; padding: 0; }
.activity > li { display: grid; grid-template-columns: 3.5rem minmax(0, 1fr) auto; gap: 0.25rem 0.85rem; align-items: center; padding: 0.75rem 0; border-bottom: var(--hairline); }
.activity > li:first-child { padding-top: 0.2rem; }
.activity > li:last-child { border-bottom: 0; padding-bottom: 0; }
.activity time { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--text-muted); line-height: 1.3; }
.activity-what { font-size: var(--text-sm); font-weight: 580; line-height: 1.3; min-width: 0; }
.activity-what small { display: block; font-weight: 400; color: var(--text-muted); font-size: 0.8125rem; margin-top: 0.1rem; }
.activity-amt { display: grid; gap: 0.3rem; justify-items: end; text-align: right; }
.activity-amt b { font-family: var(--font-mono); font-weight: 500; font-size: var(--text-sm); font-variant-numeric: tabular-nums; }

/* ==== 20. Site header and footer ==== */
.site-header { position: sticky; top: 0; z-index: var(--z-header); background: var(--bg); border-bottom: var(--hairline); }
.site-header > .container { display: flex; align-items: center; gap: var(--space-6); height: var(--header-h); position: relative; }
.site-nav { display: flex; align-items: center; gap: 1.75rem; margin-left: auto; }
.site-nav a:not(.btn) { position: relative; padding-block: 0.4rem; font-size: 0.9375rem; color: var(--text-muted); text-decoration: none; transition: color var(--dur-2) var(--ease-out); }
.site-nav a:not(.btn):hover, .site-nav a:not(.btn)[aria-current="page"] { color: var(--text); }
.site-nav a:not(.btn)::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--accent); transform: scaleX(0); transform-origin: left; transition: transform var(--dur-3) var(--ease-out); }
.site-nav a:not(.btn):hover::after, .site-nav a:not(.btn)[aria-current="page"]::after { transform: scaleX(1); }
.site-nav .nav-sep { width: 1px; height: 1.25rem; background: var(--border); }
.site-nav .nav-portal { display: inline-flex; align-items: center; gap: 0.45rem; color: var(--text); }
.site-nav .nav-portal .icon { --icon-size: 1rem; }
.site-menu { display: none; margin-left: auto; }
.site-menu > summary { list-style: none; display: inline-flex; align-items: center; gap: 0.5rem; min-height: 2.5rem; padding: 0 0.85rem; border: 1px solid var(--border-input); border-radius: var(--radius-2); font-size: var(--text-sm); font-weight: 620; cursor: pointer; }
.site-menu > summary::-webkit-details-marker { display: none; }
.site-menu > summary .icon { --icon-size: 1rem; }
.site-menu[open] > summary { background: var(--surface-2); }
.site-menu-panel { position: absolute; left: 0; right: 0; top: 100%; display: grid; padding: 0.5rem var(--gutter) 1.5rem; background: var(--bg); border-bottom: var(--hairline); box-shadow: var(--shadow-2); }
.site-menu-links { display: grid; }
.site-menu-links a:not(.btn) { display: flex; justify-content: space-between; align-items: center; padding: 0.95rem 0; border-bottom: var(--hairline); text-decoration: none; font-family: var(--font-display); font-size: 1.375rem; letter-spacing: -0.01em; }
.site-menu-links a:not(.btn) .icon { color: var(--text-muted); }
.site-menu-links .btn { margin-top: 1.25rem; }
.site-menu-lang { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-top: 1.25rem; padding-top: 1rem; border-top: var(--hairline); font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-muted); }
.site-menu-lang .lang-switch a { min-width: 2.75rem; height: 2.5rem; }
.site-header .site-lang { margin-left: calc(-1 * var(--space-6) + 1.25rem); }
.site-nav a { white-space: nowrap; }
@media (max-width: 1180px) {
  .site-header > .container { gap: var(--space-5); }
  .site-nav { gap: 1.25rem; }
  .site-header .site-lang { margin-left: -0.25rem; }
}
/* The phone menu takes over when the links no longer fit on one line: French labels are about 20% longer. */
@media (max-width: 900px) {
  .site-nav, .site-header .site-lang { display: none; }
  .site-menu { display: block; }
}
@media (max-width: 1040px) {
  html[lang="fr"] .site-nav, html[lang="fr"] .site-header .site-lang { display: none; }
  html[lang="fr"] .site-menu { display: block; }
}
.site-main { display: block; }
.site-footer { padding-block: 4rem 2.5rem; border-top: var(--hairline); position: relative; }
.site-footer::before { content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 10px; background-image: linear-gradient(to right, var(--rule) 1px, transparent 1px), linear-gradient(to right, var(--rule) 1px, transparent 1px); background-size: 40px 10px, 8px 5px; background-repeat: repeat-x; opacity: 0.35; }
.foot-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr)); gap: 2rem; }
.foot-tagline { margin-top: 1rem; font-family: var(--font-display); font-style: italic; font-size: 1.25rem; line-height: 1.3; max-width: 18rem; }
.foot-col h2 { margin: 0 0 1rem; font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-muted); }
.foot-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; font-size: 0.9375rem; }
.foot-col a { color: var(--text); text-decoration: none; }
.foot-col a:hover { color: var(--accent); }
.foot-bottom { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 0.75rem 2rem; margin-top: 3.5rem; padding-top: 1.25rem; border-top: var(--hairline); font-size: 0.8125rem; color: var(--text-muted); }
/* Company disclosure (ui.company_line): registered name, form, register and number, registered office, as one line of
   fine print under the footer's bottom row (site, docs) or as the portal footer's last row. UK law asks for characters
   readable with the naked eye (SI 2015/17 reg. 20): 12 px at the muted ink (AA in both themes), a generous leading
   and a measure. Its two sentences (company, registered office) are inline blocks: side by side when they fit, else
   the office starts the next line whole; on a phone each wraps inside its own block, and an unbreakable string may
   break anywhere rather than widen the page. */
.company-line { margin: 0; max-width: 64rem; font-size: var(--text-xs); line-height: 1.6; color: var(--text-muted); overflow-wrap: anywhere; }
.company-line > span { display: inline-block; max-width: 100%; text-wrap: pretty; }
.foot-bottom + .company-line { margin-top: 0.9rem; }
@media (max-width: 900px) {
  .foot-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .foot-brand { grid-column: 1 / -1; }
}

/* Theme switch: three small segmented buttons (light, dark, system) */
.theme-switch { display: inline-flex; flex: none; border: 1px solid var(--border-input); border-radius: var(--radius-2); overflow: hidden; }
.theme-switch button { display: inline-grid; place-items: center; flex: none; width: 2.25rem; height: 2rem; border: 0; background: none; color: var(--text-muted); }
.theme-switch button:focus-visible { outline-offset: -3px; }
.theme-switch button + button { border-left: 1px solid var(--border-input); }
.theme-switch button:hover { color: var(--text); background: var(--surface-2); }
.theme-switch button[aria-pressed="true"] { background: var(--text); color: var(--bg); }
.theme-switch .icon { --icon-size: 0.95rem; }
@media (scripting: none) { .theme-switch { display: none; } }

/* ==== 21. App shells ==== */
/* Admin: sidebar + topbar. Mobile: the sidebar becomes a top bar; the menu button expands the nav. */
.shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); min-height: 100vh; }
.sidebar { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; gap: 1.5rem; padding: 1.4rem 1rem 1rem; background: var(--bg); overflow-y: auto; z-index: var(--z-drawer); }
.sidebar > .brand { padding: 0 0.6rem; }
.sidebar-label { padding: 0 0.6rem; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-muted); }
.sidebar-toggle { display: none; }
.sidebar-nav { display: grid; gap: 0.1rem; }
.nav-group { display: grid; gap: 0.1rem; }
.nav-group + .nav-group { margin-top: 1rem; }
.nav-group-label { padding: 0 0.6rem 0.35rem; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-subtle); }
.nav-item { position: relative; display: flex; align-items: center; gap: 0.7rem; min-height: 2.5rem; padding: 0.45rem 0.6rem; border-radius: var(--radius-2); color: var(--text-muted); font-size: 0.9375rem; font-weight: 540; text-decoration: none; white-space: nowrap; transition: background-color var(--dur-1) var(--ease-out), color var(--dur-1) var(--ease-out); }
.nav-item .icon { --icon-size: 1.1rem; }
.nav-item:hover { background: var(--surface-2); color: var(--text); }
.nav-item[aria-current="page"] { background: var(--surface); color: var(--text); box-shadow: var(--shadow-1), inset 0 0 0 1px var(--border); }
.nav-item .count { margin-left: auto; }
.nav-item .nav-ext { margin-left: auto; --icon-size: 0.85rem; color: var(--text-subtle); }
.sidebar-foot { margin-top: auto; display: grid; gap: 0.75rem; padding-top: 1rem; border-top: var(--hairline); }
.sidebar-foot form { margin: 0; }
.sidebar-foot .nav-item { width: 100%; border: 0; background: none; font: inherit; font-size: 0.9375rem; font-weight: 540; text-align: left; }
.sidebar-foot .nav-item:hover { background: var(--surface-2); }
.shell-main { min-width: 0; display: flex; flex-direction: column; border-left: var(--hairline); }
.sidebar-foot .link-quiet { display: inline-flex; align-items: center; gap: 0.25rem; white-space: nowrap; }
.topbar { position: sticky; top: 0; z-index: var(--z-sticky); display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1rem; min-height: 4rem; padding: 0.75rem clamp(1rem, 0.5rem + 2vw, 2.5rem); background: var(--bg); border-bottom: var(--hairline); }
.topbar-title { display: flex; align-items: center; gap: 0.75rem; min-width: 0; }
/* Two lines before the clamp: a long client name reads in full on a phone. */
.topbar-title h1, .topbar-title .page-title { font-size: 1.5rem; line-height: 1.1; letter-spacing: -0.02em; font-weight: 400; overflow: hidden; overflow-wrap: break-word; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; }
.topbar-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
.shell-content { flex: 1; width: 100%; max-width: 88rem; padding: 1.5rem clamp(1rem, 0.5rem + 2vw, 2.5rem) 4rem; }
.shell-content > * + * { margin-top: 1.25rem; }
.shell-content > .page-head { padding-top: 0.5rem; }

@media (max-width: 960px) {
  /* The sticky bar keeps its own height; short pages leave the space to the content row. */
  .shell { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; align-content: start; }
  .shell-main { border-left: 0; }
  .sidebar { position: sticky; top: 0; height: auto; max-height: 100vh; display: grid; grid-template-columns: minmax(0, 1fr) auto; grid-template-areas: "brand toggle" "nav nav" "foot foot"; gap: 0 0.75rem; align-items: center; padding: 0.7rem 1rem; border-right: 0; border-bottom: var(--hairline); }
  .sidebar > .brand { grid-area: brand; padding: 0; }
  .sidebar-toggle { grid-area: toggle; display: inline-flex; }
  .sidebar-label, .sidebar-extra { display: none; }
  .sidebar-nav { grid-area: nav; display: none; padding-top: 0.75rem; }
  .sidebar-foot { grid-area: foot; display: none; margin-top: 0.5rem; }
  .sidebar[data-open="true"] .sidebar-nav, .sidebar[data-open="true"] .sidebar-foot { display: grid; }
  .sidebar[data-open="true"] { overflow-y: auto; box-shadow: var(--shadow-3); }
  .topbar { position: static; }
}
/* Without JavaScript the nav stays reachable as a scrolling row. */
@media (max-width: 960px) and (scripting: none) {
  .sidebar-toggle { display: none; }
  .sidebar { grid-template-areas: "brand brand" "nav nav" "foot foot"; }
  .sidebar-nav { display: flex; overflow-x: auto; gap: 0.25rem; padding-top: 0.6rem; }
  .sidebar-foot { display: flex; }
  .nav-group { display: contents; }
  .nav-group-label { display: none; }
}

/* Portal: brand bar + tab nav, content in a container */
.portal-bar { position: sticky; top: 0; z-index: var(--z-header); background: var(--bg); border-bottom: var(--hairline); }
.portal-bar-top { display: flex; align-items: center; gap: 1rem 1.25rem; min-height: 4rem; padding-block: 0.6rem; }
.portal-client { display: flex; align-items: baseline; gap: 0.6rem; min-width: 0; padding-left: 1.25rem; border-left: var(--hairline); }
.portal-client .caps { color: var(--text-muted); white-space: nowrap; }
.portal-client strong { font-family: var(--font-display); font-weight: 440; font-size: 1.125rem; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.portal-bar-actions { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }
.portal-bar-actions form { margin: 0; }
.portal-nav { --tab-pad: 0.375rem; display: flex; gap: calc(1.75rem - 2 * var(--tab-pad)); margin-inline: calc(-1 * var(--tab-pad)); overflow-x: auto; scrollbar-width: none; margin-bottom: -1px; }
.portal-nav::-webkit-scrollbar { display: none; }
.portal-nav .tab { font-size: 0.9375rem; padding-block: 0.55rem 0.8rem; }
.portal-nav .tab .icon { --icon-size: 1rem; }
.portal-main { padding-block: 1.5rem 4rem; }
.portal-main > .container > * + * { margin-top: 1.25rem; }
.portal-foot { border-top: var(--hairline); }
.portal-foot-inner { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.75rem 2rem; padding-block: 2rem 2.5rem; font-size: 0.8125rem; color: var(--text-muted); }
/* Legal links (terms, privacy, legal notice) on every portal page, billing included: a direct, permanent route to
   the seller's identity and the terms of sale. Same gap as the cluster, footer text size; padding gives a 24 px target. */
.portal-foot-legal { display: flex; flex-wrap: wrap; gap: 0 var(--space-3); }
.portal-foot-legal .link { padding-block: 0.2rem; }
.portal-foot-theme { display: none; }
.portal-foot-inner > .company-line { flex: 1 1 100%; }
@media (max-width: 1023px) {
  /* Tablets and phones: the bar drops the "Client portal" caps, the Sign out label and the theme switch (it moves
     to the footer below 1024 px), so the client name keeps its room on tablets ("Cabinet Durand et Associés"
     read "C..." at 768 px in French). The 600 px block below brings the caps back on the name's own row. */
  .portal-client .caps { display: none; }
  .portal-client { padding-left: 0.9rem; }
  /* Icon-only Sign out keeps its accessible name: the label is hidden visually, not removed. */
  .portal-bar-actions .btn-label { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  .portal-bar-actions .btn { padding-inline: 0.55rem; }
  .portal-bar-actions .theme-switch { display: none; }
  .portal-foot-theme { display: inline-flex; align-items: center; gap: 0.6rem; }
}
@media (max-width: 720px) {
  .portal-nav { gap: calc(1.25rem - 2 * var(--tab-pad)); }
  .portal-nav .tab { font-size: var(--text-sm); }
}
@media (max-width: 600px) {
  /* Phones: the full lockup (mark + wordmark) and both language links stay on the first row; the client name
     moves to a slim row of its own under them instead of being squeezed to a few letters. */
  .portal-bar-top { flex-wrap: wrap; row-gap: 0; min-height: 0; padding-block: 0.5rem 0.35rem; }
  .portal-bar-actions { gap: 0.375rem; }
  .portal-bar .lang-switch a { min-width: 2rem; padding: 0 0.4rem; }
  .portal-client { order: 3; flex: 1 0 100%; align-items: baseline; gap: 0.5rem; padding-left: 0; border-left: 0; }
  .portal-client .caps { display: inline; }
  .portal-client strong { font-size: 1rem; }
}

/* ==== 22. Docs layout: sticky table of contents ==== */
.docs { display: grid; grid-template-columns: 15rem minmax(0, 1fr); gap: clamp(2rem, 1rem + 3vw, 4rem); align-items: start; padding-block: 2.5rem 5rem; }
.docs-toc { position: sticky; top: calc(var(--header-h) + 1.5rem); max-height: calc(100vh - var(--header-h) - 3rem); overflow-y: auto; padding-right: 0.5rem; scrollbar-width: thin; }
.toc-title { margin-bottom: 0.75rem; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; color: var(--text-muted); }
.toc ol, .toc ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.1rem; }
.toc ol ol, .toc ul ul { padding-left: 0.85rem; margin-top: 0.1rem; }
.toc a { display: block; padding: 0.3rem 0 0.3rem 0.75rem; border-left: 1px solid var(--border); color: var(--text-muted); font-size: var(--text-sm); line-height: 1.35; text-decoration: none; }
.toc a:hover { color: var(--text); border-left-color: var(--border-strong); }
.toc a:focus-visible { outline-offset: -2px; }
.toc a[aria-current="true"], .toc a.is-active { color: var(--text); border-left: 2px solid var(--accent-fill); padding-left: calc(0.75rem - 1px); font-weight: 560; }
.docs-toc-mobile { display: none; }
.docs-content { min-width: 0; }
.docs-content > section + section { margin-top: 3.5rem; padding-top: 3rem; border-top: var(--hairline); }
@media (max-width: 960px) {
  .docs { grid-template-columns: minmax(0, 1fr); padding-top: 1.5rem; }
  .docs-toc { display: none; }
  .docs-toc-mobile { display: block; margin-bottom: var(--space-6); border: var(--hairline); border-radius: var(--radius-3); background: var(--surface); }
  .docs-toc-mobile > summary { display: flex; justify-content: space-between; align-items: center; padding: 0.8rem 1rem; cursor: pointer; font-weight: 620; font-size: var(--text-sm); list-style: none; }
  .docs-toc-mobile > summary::-webkit-details-marker { display: none; }
  .docs-toc-mobile[open] > summary .icon { transform: rotate(180deg); }
  .docs-toc-mobile .toc { padding: 0 1rem 1rem; }
}

/* ==== 23. Charts (rendered by /static/js/charts.js) ==== */
.chart { position: relative; width: 100%; min-height: var(--chart-h, 15rem); font-family: var(--font-mono); }
.chart[data-chart="spark"] { min-height: 0; height: var(--chart-h, 2rem); }
.chart[data-chart="ring"] { min-height: 0; width: var(--ring-size, 9rem); height: var(--ring-size, 9rem); }
.chart-canvas { position: relative; width: 100%; overflow-x: auto; overflow-y: hidden; scrollbar-width: thin; }
.chart-canvas:focus-visible { outline-offset: 2px; }
.chart-yaxis { position: absolute; left: 0; z-index: 1; pointer-events: none; }
.chart-yaxis rect { fill: var(--surface); }
.chart svg { display: block; overflow: visible; max-width: none; }
.chart .c-grid { stroke: var(--chart-grid); stroke-width: 1; shape-rendering: crispEdges; }
.chart .c-base { stroke: var(--rule); stroke-width: 1; shape-rendering: crispEdges; }
.chart .c-axis { fill: var(--chart-axis); font-size: 11px; font-variant-numeric: tabular-nums; }
.chart .c-axis-hl { fill: var(--accent); font-weight: 500; }
.chart .c-bar { fill: var(--chart-bar); transition: fill var(--dur-1) var(--ease-out), opacity var(--dur-1) var(--ease-out); }
.chart .c-bar.is-peak { fill: var(--chart-bar-strong); }
.chart .c-bar.is-hl { fill: var(--chart-highlight); }
.chart .c-bar.is-compare { fill: var(--chart-bar-muted); }
.chart .c-mark.is-hover .c-bar:not(.is-hl) { fill: var(--chart-bar-strong); }
.chart .c-mark.is-hover .c-bar.is-hl { fill: var(--accent-hover); }
.chart.is-multi .c-mark.is-hover .c-bar { opacity: 0.82; }
.chart .c-hit { fill: transparent; outline: none; }
.chart .c-mark:focus { outline: none; }
.chart .c-mark:focus-visible .c-hit, .chart .c-hit:focus-visible { stroke: var(--focus-ring); stroke-width: 2; }
.chart .c-label { fill: var(--text); font-size: 11px; font-weight: 500; paint-order: stroke; stroke: var(--surface); stroke-width: 4px; stroke-linejoin: round; }
.chart .c-label-muted { fill: var(--text-muted); font-weight: 400; }
.chart .c-pace { stroke: var(--chart-pace); stroke-width: 1; stroke-dasharray: 4 3; opacity: 0.7; shape-rendering: crispEdges; }
.chart .c-band-line { stroke: var(--chart-band); stroke-width: 1; }
.chart .c-hatch-line { stroke: var(--chart-band); stroke-width: 1.5; }
.chart .c-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart .c-area { opacity: 0.1; }
.chart .c-dot { stroke: var(--surface); stroke-width: 2; }
.chart .c-cross { stroke: var(--text-muted); stroke-width: 1; shape-rendering: crispEdges; }
.chart .c-ring-track { fill: none; stroke: var(--surface-2); }
.chart .c-ring-val { fill: none; stroke: var(--accent-fill); stroke-linecap: butt; transition: stroke-dashoffset var(--dur-4) var(--ease-tape); }
.chart .c-ring-val.is-warning { stroke: var(--warning); }
.chart .c-ring-val.is-danger { stroke: var(--danger); }
.chart .c-ring-tick { stroke: var(--surface); stroke-width: 2; }
.chart-ring-center { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; text-align: center; pointer-events: none; }
.chart-ring-value { font-family: var(--font-sans); font-size: calc(var(--ring-size, 9rem) * 0.19); font-weight: 600; letter-spacing: -0.03em; line-height: 1; color: var(--text); }
.chart-ring-label { margin-top: 0.3rem; font-family: var(--font-sans); font-size: var(--text-xs); color: var(--text-muted); max-width: 70%; line-height: 1.25; }
.chart-tooltip {
  position: absolute;
  z-index: var(--z-overlay);
  top: 0;
  left: 0;
  min-width: 8rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-2);
  background: var(--surface-raised);
  border: var(--hairline);
  box-shadow: var(--shadow-2);
  font-family: var(--font-sans);
  font-size: var(--text-xs);
  color: var(--text-muted);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease-out);
  white-space: nowrap;
}
.chart-tooltip.is-visible { opacity: 1; }
.chart-tooltip-title { margin-bottom: 0.25rem; color: var(--text-muted); }
.chart-tooltip-row { display: flex; align-items: center; gap: 0.45rem; }
.chart-tooltip-row b { font-family: var(--font-mono); font-weight: 500; font-size: var(--text-sm); color: var(--text); font-variant-numeric: tabular-nums; }
.chart-tooltip-key { width: 10px; height: 2px; flex: none; border-radius: 1px; }
.chart-legend { display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; margin: 0 0 0.75rem; padding: 0; list-style: none; font-family: var(--font-sans); font-size: var(--text-xs); color: var(--text-muted); }
.chart-legend li { display: inline-flex; align-items: center; gap: 0.4rem; }
.chart-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; }
.chart-legend i.is-line { height: 2px; }
.chart-legend i.is-dash { height: 0; border-top: 1px dashed var(--chart-pace); width: 14px; border-radius: 0; }
.chart-legend i.is-hatch { background: repeating-linear-gradient(135deg, var(--chart-band) 0 2px, transparent 2px 4px); box-shadow: inset 0 0 0 1px var(--chart-band); }
/* Empty chart: the .empty structure (icon ring, serif title, muted line) in a dashed box the chart's height. */
.chart-empty { align-content: center; min-height: inherit; font-family: var(--font-sans); }
.chart-table { width: 100%; margin-top: 0.75rem; font-family: var(--font-sans); }
/* Server-rendered fallback inside .chart (ui.chart / ui.ring / ui.sparkline). charts.js replaces it;
   it only shows when scripting is off. */
.chart-fallback { display: none; font-family: var(--font-sans); }
.chart-fallback-note { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem; font-size: 0.8125rem; color: var(--text-muted); }
.chart-fallback .table-wrap { max-height: 22rem; overflow-y: auto; }
.chart-fallback .table th:first-child, .chart-fallback .table td:first-child { padding-left: 0; }
.chart-fallback .table th:last-child, .chart-fallback .table td:last-child { padding-right: 0.25rem; }
.chart-fallback tbody th { font-family: var(--font-sans); font-size: var(--text-sm); font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--text); border-bottom: var(--hairline); vertical-align: middle; }
.chart-fallback-value { font-size: var(--text-sm); color: var(--text-muted); }
.chart-fallback-value b { font-family: var(--font-mono); font-weight: 500; color: var(--text); }
@media (scripting: none) {
  .chart, .chart[data-chart="spark"], .chart[data-chart="ring"] { min-height: 0; height: auto; width: auto; }
  .chart-fallback { display: block; }
}
.chart.is-refreshing svg { opacity: 0.5; transition: opacity var(--dur-2); }
.chart-foot { display: grid; grid-template-columns: repeat(var(--cols, 4), minmax(0, 1fr)); margin-top: 1rem; border-top: var(--hairline); }
.chart-foot > div { display: grid; gap: 0.2rem; padding: 0.85rem 0 0; }
.chart-foot > div + div { padding-left: 1.1rem; border-left: var(--hairline); }
.chart-foot span { font-size: var(--text-xs); color: var(--text-muted); }
.chart-foot b { font-family: var(--font-mono); font-weight: 500; font-size: 0.9375rem; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) {
  .chart-foot { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .chart-foot > div:nth-child(odd) { padding-left: 0; border-left: 0; }
}

/* ==== 23b. Payment processing (A01, macro pay_processing, app.js data-pay-form) ==== */
/* Idle: out of sight but still in the accessibility tree, so the role=status line is announced when app.js fills it. */
.pay-processing { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.pay-processing .pay-mark { display: none; }
.pay-processing.is-on { position: absolute; inset: 0; z-index: 3; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.9rem; padding: 1.5rem; text-align: center;
  background: color-mix(in srgb, var(--surface) 94%, transparent); border-radius: inherit; animation: pay-fade 0.2s ease-out; }
.pay-processing.is-on .pay-mark { display: block; color: var(--text); }
.pay-processing-inline.is-on { position: static; z-index: auto; flex-direction: row; justify-content: flex-start; padding: 0; background: none; animation: none; }
.pay-processing-inline .pay-mark { width: 42px; height: 27px; }
.pay-processing-text { margin: 0; max-width: 28ch; font-weight: 500; color: var(--text); }
.pay-processing-inline .pay-processing-text { max-width: none; }
.pay-mark-hook { fill: var(--accent-fill); }
.pay-mark-tape { transform-box: fill-box; transform-origin: left center; }
.is-on .pay-mark-tape { animation: pay-tape 1.8s ease-in-out infinite; }
.is-on .pay-mark-hook { animation: pay-hook 1.8s ease-in-out infinite; }
/* The tape runs out of the case and back: 0 and 100% are the resting mark, so a stopped animation shows it whole. */
@keyframes pay-tape { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(0.12); } }
@keyframes pay-hook { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(-22px); } }
@keyframes pay-fade { from { opacity: 0; } to { opacity: 1; } }
[aria-busy="true"] > :not(.pay-processing) { pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .is-on .pay-mark-tape, .is-on .pay-mark-hook, .pay-processing.is-on { animation: none; }
}
@media (forced-colors: active) {
  .pay-processing.is-on { background: Canvas; border: 1px solid CanvasText; }
  .pay-mark-hook { fill: CanvasText; }
}

/* ==== 24. Utilities ==== */
.sr-only, .visually-hidden { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.w-full { width: 100%; }
.text-center { text-align: center; }
.text-right { text-align: right; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.mt-0 { margin-top: 0 !important; }
.mt-2 { margin-top: var(--space-2); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mb-4 { margin-bottom: var(--space-4); }
.flex-1 { flex: 1; min-width: 0; }
.divider-text { display: flex; align-items: center; gap: 0.75rem; font-size: var(--text-xs); color: var(--text-muted); font-family: var(--font-mono); letter-spacing: 0.08em; text-transform: uppercase; }
.divider-text::before, .divider-text::after { content: ""; flex: 1; border-top: var(--hairline); }
.example-tag { display: inline-flex; align-items: center; gap: 0.45rem; padding: 0.25rem 0.55rem 0.27rem; background: var(--text); color: var(--bg); border-radius: var(--radius-1); font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.1em; text-transform: uppercase; font-weight: 500; }
.example-tag::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--accent-fill); }

/* ==== 25. Motion, print, forced colors ==== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}
@media (forced-colors: active) {
  .badge::before, .tape-needle, .tape-fill, .bar-meter-fill, .count-accent { forced-color-adjust: none; background: CanvasText; }
  .count-accent { color: Canvas; }
  .tape-track { border: 1px solid CanvasText; }
  .btn, .input, .select, .textarea, .card, .alert, .keyfield { border: 1px solid CanvasText; }
  .nav-item[aria-current="page"], .tab[aria-selected="true"], .page-link[aria-current="page"], .lang-switch a[aria-current="true"] { outline: 2px solid Highlight; }
  .theme-switch button[aria-pressed="true"] { outline: 2px solid Highlight; outline-offset: -2px; }
  .brand-mark .hook { fill: currentColor; }
  :focus-visible { outline: 2px solid Highlight; }
}
@media print {
  .site-header, .site-footer, .sidebar, .topbar-actions, .portal-bar, .toasts, .btn, .theme-switch, .lang-switch, .lang-suggest { display: none !important; }
  .shell { display: block; }
  .card { box-shadow: none; }
}
