/* ===== tokens/colors.css ===== */
/* ============================================================
   Prism · Color system  (OKLCH / wide-gamut P3)
   ------------------------------------------------------------
   EVERY color in Prism is authored in oklch() — no hex, no rgb.
   This unlocks vivid wide-gamut (Display P3) colors on capable
   screens while staying perceptually uniform, so ramps step
   evenly and contrast is predictable. Translucent values use
   oklch(L C H / alpha).

   Aesthetic: VIBRANT foreground on a SOFT, WARM canvas. The
   default brand is a very vibrant blue (~#0022ee) — blue reads
   as "interactive" for links, buttons and focus everywhere.

   Layers:
   1. PALETTE   raw ramps (never reference directly in UI)
   2. BRAND     the one ramp a customer overrides to re-skin
   3. SEMANTIC  role aliases the components actually consume

   Semantic state colors are ALWAYS paired with an icon or text —
   never hue alone — for color-blind users.
   ============================================================ */

:root {
  /* ---------- PALETTE · Warm neutral (sand / stone) ---------- */
  --gray-0:    oklch(1 0 0);
  --gray-25:   oklch(0.992 0.002 80);
  --gray-50:   oklch(0.973 0.003 80);  /* faintly warm near-white — page canvas */
  --gray-100:  oklch(0.949 0.004 80);
  --gray-150:  oklch(0.919 0.005 80);
  --gray-200:  oklch(0.873 0.007 80);
  --gray-300:  oklch(0.793 0.009 78);
  --gray-400:  oklch(0.673 0.010 76);
  --gray-500:  oklch(0.553 0.009 72);
  --gray-600:  oklch(0.463 0.008 70);
  --gray-700:  oklch(0.383 0.007 68);
  --gray-800:  oklch(0.303 0.006 66);
  --gray-900:  oklch(0.235 0.005 64);
  --gray-950:  oklch(0.188 0.004 62);
  --gray-1000: oklch(0 0 0);

  /* ---------- PALETTE · Cobalt (Prism default brand — vibrant P3 blue) ---------- */
  /* Cobalt is the base primary. Chroma is capped at 0.165 so it reads as a
     considered ink rather than the browser's default link blue: high-chroma
     blue vibrates on white and haloes on dark. Hue 258 keeps it blue, not
     violet. White ink on 500 clears AA with margin. */
  --cobalt-50:  oklch(0.965 0.014 258);
  --cobalt-100: oklch(0.930 0.032 258);
  --cobalt-200: oklch(0.860 0.065 258);
  --cobalt-300: oklch(0.750 0.110 258);
  --cobalt-400: oklch(0.640 0.140 258);
  --cobalt-500: oklch(0.500 0.165 258);  /* primary action · white ink AA */
  --cobalt-600: oklch(0.445 0.160 258);  /* hover / link text */
  --cobalt-700: oklch(0.395 0.145 258);
  --cobalt-800: oklch(0.340 0.115 258);
  --cobalt-900: oklch(0.290 0.085 258);

  /* ---------- PALETTE · Positive (emerald) ---------- */
  --green-50:  oklch(0.962 0.030 158);
  --green-100: oklch(0.910 0.070 158);
  --green-200: oklch(0.845 0.120 157);
  --green-300: oklch(0.745 0.155 156);
  --green-400: oklch(0.680 0.165 156);
  --green-500: oklch(0.600 0.155 156);
  --green-600: oklch(0.520 0.135 156);
  --green-700: oklch(0.440 0.115 156);

  /* ---------- PALETTE · Notice (amber) ---------- */
  --amber-50:  oklch(0.964 0.034 85);
  --amber-100: oklch(0.910 0.080 82);
  --amber-200: oklch(0.845 0.130 78);
  --amber-300: oklch(0.785 0.150 70);
  --amber-400: oklch(0.720 0.150 64);
  --amber-500: oklch(0.620 0.130 60);
  --amber-600: oklch(0.520 0.110 58);
  --amber-700: oklch(0.440 0.092 56);

  /* ---------- PALETTE · Negative (red) ---------- */
  --red-50:  oklch(0.954 0.020 25);
  --red-100: oklch(0.892 0.055 25);
  --red-200: oklch(0.805 0.120 26);
  --red-300: oklch(0.700 0.185 27);
  --red-400: oklch(0.625 0.225 27);
  --red-500: oklch(0.560 0.240 28);
  --red-600: oklch(0.490 0.215 28);
  --red-700: oklch(0.420 0.175 28);

  /* ---------- PALETTE · Informative (sky — a clear, friendly blue, distinct from brand & green) ---------- */
  --sky-50:  oklch(0.962 0.028 235);
  --sky-100: oklch(0.910 0.060 236);
  --sky-200: oklch(0.835 0.105 237);
  --sky-300: oklch(0.740 0.135 238);
  --sky-400: oklch(0.665 0.150 240);
  --sky-500: oklch(0.585 0.150 240);
  --sky-600: oklch(0.505 0.130 240);
  --sky-700: oklch(0.425 0.110 240);

  /* ---------- PALETTE · Violet (primary section accent — bold, lively) ---------- */
  --violet-50:  oklch(0.967 0.018 300);
  --violet-100: oklch(0.930 0.045 300);
  --violet-200: oklch(0.870 0.085 300);
  --violet-300: oklch(0.770 0.140 300);
  --violet-400: oklch(0.660 0.190 300);
  --violet-500: oklch(0.560 0.205 300);
  --violet-600: oklch(0.485 0.190 300);
  --violet-700: oklch(0.410 0.160 300);

  /* ---------- PALETTE · Teal (secondary section accent — fresh, calm) ---------- */
  --teal-50:  oklch(0.965 0.025 185);
  --teal-100: oklch(0.918 0.055 184);
  --teal-200: oklch(0.850 0.085 183);
  --teal-300: oklch(0.755 0.105 182);
  --teal-400: oklch(0.680 0.105 182);
  --teal-500: oklch(0.595 0.095 182);
  --teal-600: oklch(0.500 0.080 182);
  --teal-700: oklch(0.420 0.066 182);

  /* ---------- PALETTE · Rose (warm highlight) ---------- */
  --rose-50:  oklch(0.965 0.020 12);
  --rose-100: oklch(0.920 0.045 12);
  --rose-200: oklch(0.860 0.085 12);
  --rose-300: oklch(0.755 0.140 12);
  --rose-400: oklch(0.670 0.180 12);
  --rose-500: oklch(0.600 0.205 12);
  --rose-600: oklch(0.520 0.185 12);
  --rose-700: oklch(0.440 0.155 12);

  /* ============================================================
     CHART / INFOGRAPHIC PALETTE  (modeled on IBM Carbon data-viz)
     ------------------------------------------------------------
     Comprehensive viz system: a 14-step CATEGORICAL sequence in a
     fixed, perceptually-ordered run (use 1..N in order — adjacent
     swatches stay distinct, and lightness is staggered so series
     also separate in greyscale / under colour-vision deficiency);
     plus SCIENTIFIC (Okabe–Ito) and INDUSTRIAL alternates, MONO &
     two-tone SEQUENTIAL ramps for intensity, and a DIVERGING ramp
     for deviation from a midpoint. All OKLCH/P3.
     Carbon ref: carbondesignsystem.com/data-visualization/color-palettes
     ============================================================ */
  /* ---------- Data series · one hue family per chart ----------
     Available in EVERY theme, not just Industry: a chart is not a bag of
     unrelated colours, it picks ONE hue family and steps within it, so the
     whole graphic reads as one material rather than children's blocks.

     Six steps spaced by measured sRGB LUMINANCE in even 28/255 increments
     (210 → 70) — the quantity a greyscale conversion actually reports.
     Desaturate any chart and its series stay ordered and distinct. Do NOT
     respace by oklch L: at high chroma the two diverge badly (two colours
     0.07 L apart can be the same grey). To retune, render each step and
     measure 0.2126R + 0.7152G + 0.0722B, requiring every PAIR to differ
     by ≥ 20.

     Default family is AZURE. Switch per chart, card or page with
     data-series="violet|magenta|cyan|green|amber|orange".

     --chart-* stays the 14-colour categorical run below: use the family
     when the categories are ordered (funnel stages, tiers, cohorts) and
     --chart-* when they are genuinely unrelated (product lines, regions). */
  --series-1: oklch(0.881 0.115 270); /* luma 210 @kind color */
  --series-2: oklch(0.813 0.180 261); /* luma 182 @kind color */
  --series-3: oklch(0.766 0.225 253); /* luma 154 @kind color */
  --series-4: oklch(0.660 0.250 244); /* luma 126 @kind color */
  --series-5: oklch(0.523 0.235 235); /* luma 97  @kind color */
  --series-6: oklch(0.401 0.205 227); /* luma 71  @kind color */
  /* Unlit / context marks. Industry overrides these with dark glass; on a
     light surface the track is a plain recessed neutral. */
  --series-track: oklch(0.918 0.004 250); /* @kind color */
  --series-gap: oklch(0.965 0.002 250);   /* @kind color */

  /* CATEGORICAL · 14-colour ordered run (Carbon sequence, oklch) */
  --chart-1: oklch(0.483 0.21 295);  /* luma 74 @kind color */
  --chart-2: oklch(0.742 0.14 245);  /* luma 164 @kind color */
  --chart-3: oklch(0.473 0.07 195);  /* luma 88 @kind color */
  --chart-4: oklch(0.455 0.18 0);  /* luma 45 @kind color */
  --chart-5: oklch(0.665 0.2 22);  /* luma 117 @kind color */
  --chart-6: oklch(0.549 0.15 150);  /* luma 103 @kind color */
  --chart-7: oklch(0.416 0.2 268);  /* luma 59 @kind color */
  --chart-8: oklch(0.739 0.175 357);  /* luma 150 @kind color */
  --chart-9: oklch(0.766 0.13 90);  /* luma 175 @kind color */
  --chart-10: oklch(0.648 0.11 190);  /* luma 131 @kind color */
  --chart-11: oklch(0.30 0.10 245);  /* cyan 90   */
  --chart-12: oklch(0.48 0.13 55);   /* orange 70 */
  --chart-13: oklch(0.66 0.20 300);  /* purple 50 */
  --chart-14: oklch(0.30 0.13 25);   /* red 90    */
  /* Sequential ramp (single-hue, low→high) for heatmaps / intensity */
  --chart-seq-1: oklch(0.93 0.04 264);
  --chart-seq-2: oklch(0.83 0.09 264);
  --chart-seq-3: oklch(0.72 0.15 264);
  --chart-seq-4: oklch(0.60 0.22 264);
  --chart-seq-5: oklch(0.47 0.32 264);
  /* Two-tone sequential (hue shifts low→high) — Carbon-style */
  --chart-seq2-1: oklch(0.92 0.05 190);
  --chart-seq2-2: oklch(0.78 0.11 215);
  --chart-seq2-3: oklch(0.62 0.16 250);
  --chart-seq2-4: oklch(0.47 0.20 280);
  --chart-seq2-5: oklch(0.36 0.19 295);

  /* --- SCIENTIFIC (colour-vision-deficiency safe; Okabe–Ito basis) ---
     The reference categorical set for publication figures: every pair
     is distinguishable under protan/deutan/tritan simulation. */
  --chart-sci-1: oklch(0.36 0.01 250);  /* near-black grey */
  --chart-sci-2: oklch(0.76 0.150 75);  /* orange */
  --chart-sci-3: oklch(0.74 0.110 235); /* sky blue */
  --chart-sci-4: oklch(0.63 0.130 165); /* bluish green */
  --chart-sci-5: oklch(0.90 0.160 105); /* yellow */
  --chart-sci-6: oklch(0.52 0.130 245); /* blue */
  --chart-sci-7: oklch(0.58 0.180 45);  /* vermillion */
  --chart-sci-8: oklch(0.67 0.120 350); /* reddish purple */

  /* --- INDUSTRIAL (muted, professional; lower chroma for dense dashboards) --- */
  --chart-ind-1: oklch(0.50 0.075 250); /* steel blue */
  --chart-ind-2: oklch(0.62 0.100 70);  /* ochre */
  --chart-ind-3: oklch(0.55 0.070 190); /* teal grey */
  --chart-ind-4: oklch(0.50 0.120 35);  /* brick */
  --chart-ind-5: oklch(0.60 0.070 130); /* olive */
  --chart-ind-6: oklch(0.46 0.045 260); /* slate */
  --chart-ind-7: oklch(0.52 0.090 330); /* plum */
  --chart-ind-8: oklch(0.70 0.050 80);  /* sand */

  /* --- DIVERGING (deviation from a midpoint: low ← neutral → high) ---
     Colour-blind-safe red↔blue with a light neutral centre. */
  --chart-div-1: oklch(0.55 0.200 25);  /* strong low (red) */
  --chart-div-2: oklch(0.75 0.110 45);  /* light low (orange) */
  --chart-div-3: oklch(0.94 0.012 90);  /* neutral midpoint */
  --chart-div-4: oklch(0.74 0.100 235); /* light high (blue) */
  --chart-div-5: oklch(0.50 0.150 250); /* strong high (blue) */

  /* ============================================================
     BRAND LAYER
     The single ramp a customer re-maps to re-skin Prism. Default
     is the vibrant Cobalt above. Override --brand-* at :root or
     any scope to theme an entire product.
     ============================================================ */
  --brand-50:  var(--cobalt-50);
  --brand-100: var(--cobalt-100);
  --brand-200: var(--cobalt-200);
  --brand-300: var(--cobalt-300);
  --brand-400: var(--cobalt-400);
  --brand-500: var(--cobalt-500);
  --brand-600: var(--cobalt-600);
  --brand-700: var(--cobalt-700);
  --brand-800: var(--cobalt-800);
  --brand-900: var(--cobalt-900);
  /* Logo mark HEIGHT in the app header (and other brand slots). A customer's
     logomark is sized by height, with inline-size:auto — so a square mark and a
     wide wordmark both fit. Override alongside --brand-* when re-skinning. */
  --brand-mark-height: 22px;
  /* Text color guaranteed legible ON a filled brand surface */
  --brand-on:  oklch(1 0 0);

  /* ============================================================
     DOMAIN HUES · canonical per-product identities (theme-independent)
     The single source of truth for each platform's signature accent.
     A product signature (see tokens/signatures.css) maps --brand-* /
     --accent to one of these so a whole app re-skins from one line.
     ============================================================ */
  --domain-commerce:    oklch(0.55 0.20 255);  /* cobalt — admin / ERP */
  --domain-campus:      oklch(0.52 0.20 290);  /* indigo-violet — education */
  --domain-health:      oklch(0.56 0.115 200); /* calm cyan-teal — clinical */
  --domain-media:       oklch(0.56 0.24 330);  /* magenta — entertainment */
  --domain-finance:     oklch(0.55 0.145 158); /* emerald — money */
  --domain-hospitality: oklch(0.64 0.15 55);   /* warm amber — hotels */
  --domain-estate:      oklch(0.53 0.13 30);   /* terracotta clay — real estate */

  /* ============================================================
     ROLE HUES · who is using the product (theme-independent)
     A stable per-persona hue for role-aware UI: avatar rings,
     "viewing as" banners, scope chips, audit attribution, queue
     ownership. NOT for status — a role hue says *who*, status tones
     say *what happened*. Derived -text/-subtle/-border tints below
     resolve per-theme via color-mix, so each role works in light
     and dark from this one base. Hues are chosen to stay mutually
     distinguishable and CVD-tolerant.
     ============================================================ */
  --role-student:  oklch(0.52 0.20 290);  /* indigo-violet — applicants */
  --role-parent:   oklch(0.55 0.15 322);  /* plum — guardians */
  --role-admin:    oklch(0.55 0.20 255);  /* cobalt — system administrators */
  --role-reviewer: oklch(0.56 0.13 200);  /* teal — assessors / graders */
  --role-doctor:   oklch(0.50 0.11 193);  /* deep clinical teal — clinicians */
  --role-guest:    oklch(0.64 0.15 55);   /* amber — hotel / venue guests */
  --role-customer: oklch(0.57 0.13 150);  /* green — shoppers / account holders */
  --role-operator: oklch(0.52 0.07 250);  /* slate-blue — front-desk / fulfilment */
  --role-finance:  oklch(0.55 0.145 158); /* emerald — finance / treasury */
  --role-support:  oklch(0.58 0.19 352);  /* pink — support / success agents */
}

/* ============================================================
   ROLE · derived tints (theme-aware via color-mix)
   Each role gets a readable text colour, a subtle chip/banner fill,
   and a border — all mixed against the LIVE theme surfaces, so this
   single block serves both light and dark. Use:
     background: var(--role-doctor-subtle);
     color:      var(--role-doctor-text);
     border:     1px solid var(--role-doctor-border);
   ============================================================ */
:root {
  --role-student-text:    color-mix(in oklab, var(--role-student)  68%, var(--text-primary));
  --role-student-subtle:  color-mix(in oklab, var(--role-student)  14%, var(--surface-card));
  --role-student-border:  color-mix(in oklab, var(--role-student)  32%, var(--surface-card));
  --role-parent-text:     color-mix(in oklab, var(--role-parent)   68%, var(--text-primary));
  --role-parent-subtle:   color-mix(in oklab, var(--role-parent)   14%, var(--surface-card));
  --role-parent-border:   color-mix(in oklab, var(--role-parent)   32%, var(--surface-card));
  --role-admin-text:      color-mix(in oklab, var(--role-admin)    68%, var(--text-primary));
  --role-admin-subtle:    color-mix(in oklab, var(--role-admin)    14%, var(--surface-card));
  --role-admin-border:    color-mix(in oklab, var(--role-admin)    32%, var(--surface-card));
  --role-reviewer-text:   color-mix(in oklab, var(--role-reviewer) 68%, var(--text-primary));
  --role-reviewer-subtle: color-mix(in oklab, var(--role-reviewer) 14%, var(--surface-card));
  --role-reviewer-border: color-mix(in oklab, var(--role-reviewer) 32%, var(--surface-card));
  --role-doctor-text:     color-mix(in oklab, var(--role-doctor)   68%, var(--text-primary));
  --role-doctor-subtle:   color-mix(in oklab, var(--role-doctor)   14%, var(--surface-card));
  --role-doctor-border:   color-mix(in oklab, var(--role-doctor)   32%, var(--surface-card));
  --role-guest-text:      color-mix(in oklab, var(--role-guest)    72%, var(--text-primary));
  --role-guest-subtle:    color-mix(in oklab, var(--role-guest)    16%, var(--surface-card));
  --role-guest-border:    color-mix(in oklab, var(--role-guest)    34%, var(--surface-card));
  --role-customer-text:   color-mix(in oklab, var(--role-customer) 68%, var(--text-primary));
  --role-customer-subtle: color-mix(in oklab, var(--role-customer) 14%, var(--surface-card));
  --role-customer-border: color-mix(in oklab, var(--role-customer) 32%, var(--surface-card));
  --role-operator-text:   color-mix(in oklab, var(--role-operator) 68%, var(--text-primary));
  --role-operator-subtle: color-mix(in oklab, var(--role-operator) 14%, var(--surface-card));
  --role-operator-border: color-mix(in oklab, var(--role-operator) 32%, var(--surface-card));
  --role-finance-text:    color-mix(in oklab, var(--role-finance)  68%, var(--text-primary));
  --role-finance-subtle:  color-mix(in oklab, var(--role-finance)  14%, var(--surface-card));
  --role-finance-border:  color-mix(in oklab, var(--role-finance)  32%, var(--surface-card));
  --role-support-text:    color-mix(in oklab, var(--role-support)  68%, var(--text-primary));
  --role-support-subtle:  color-mix(in oklab, var(--role-support)  14%, var(--surface-card));
  --role-support-border:  color-mix(in oklab, var(--role-support)  32%, var(--surface-card));
}

/* ============================================================
   SEMANTIC LAYER · LIGHT (default)
   data-theme="system" starts here too; its dark half is generated
   after the dark block below.
   ============================================================ */
:root,
[data-theme="light"],
[data-theme="system"] {
  color-scheme: light;

  /* Surfaces — warm near-white canvas, white cards float above it */
  --surface-page:      var(--gray-25);
  --surface-sunken:    var(--gray-100);
  --surface-card:      var(--gray-0);
  --surface-raised:    var(--gray-0);
  --surface-overlay:   var(--gray-0);
  --surface-inverse:   var(--gray-900);
  --surface-scrim:     oklch(0.235 0.010 60 / 0.5);

  /* Subtle fills for hover/selected zones */
  --fill-subtle:       var(--gray-100);
  --fill-subtle-hover: var(--gray-150);
  --fill-muted:        var(--gray-200);
  --surface-stripe:    var(--gray-50);  /* subtle zebra striping for tables */

  /* Text */
  --text-primary:    var(--gray-900);
  --text-secondary:  var(--gray-600);
  --text-tertiary:   var(--gray-500);
  /* A placeholder is not content — it is an example of content. It must read
     as ABSENT, so it sits BELOW tertiary rather than sharing it: reuse tertiary
     and a hinted field looks filled in. Never put required information in one;
     the label and description carry meaning, which is why this role is allowed
     to fall below 4.5:1. */
  --text-placeholder: var(--gray-400);
  --text-disabled:   var(--gray-400);
  --text-on-inverse: var(--gray-50);
  --text-link:       var(--brand-600);
  --text-link-hover: var(--brand-700);

  /* Borders */
  --border-subtle:  var(--gray-150);
  --border-default: var(--gray-200);
  --border-strong:  var(--gray-300);
  --border-inverse: var(--gray-700);

  /* Brand / accent roles */
  --accent:           var(--brand-500);
  --accent-hover:     var(--brand-600);
  --accent-active:    var(--brand-700);
  --accent-text:      var(--brand-600);
  --accent-on:        var(--brand-on);
  --accent-subtle:    var(--brand-50);
  --accent-subtle-hover: var(--brand-100);
  --accent-border:    var(--brand-200);

  /* Positive */
  --positive:        var(--green-500);
  --positive-hover:  var(--green-600);
  --positive-text:   var(--green-600);
  --positive-on:     oklch(1 0 0);
  --positive-subtle: var(--green-50);
  --positive-border: var(--green-200);

  /* Notice */
  --notice:        var(--amber-400);
  --notice-hover:  var(--amber-500);
  --notice-text:   var(--amber-600);
  --notice-on:     oklch(1 0 0);
  --notice-subtle: var(--amber-50);
  --notice-border: var(--amber-200);

  /* Negative */
  --negative:        var(--red-500);
  --negative-hover:  var(--red-600);
  --negative-text:   var(--red-600);
  --negative-on:     oklch(1 0 0);
  --negative-subtle: var(--red-50);
  --negative-border: var(--red-200);

  /* Informative */
  --info:        var(--sky-500);
  --info-hover:  var(--sky-600);
  --info-text:   var(--sky-600);
  --info-on:     oklch(1 0 0);
  --info-subtle: var(--sky-50);
  --info-border: var(--sky-200);

  /* Focus ring — the single most important a11y affordance */
  --focus-ring:        var(--brand-500);
  --focus-ring-offset: var(--gray-0);

  /* ----- Section accents — tint whole sections to set them apart -----
     A 3-step ATTENTION HIERARCHY: PRIMARY commands the most attention,
     SECONDARY less, TERTIARY the least (but still pleasant). Attention
     falls as chroma drops and lightness rises across the three. Each
     carries an `-on` text and `-border` token, AA-tuned. */
  --section-primary:        oklch(0.918 0.078 300);
  --section-primary-on:     var(--violet-700);
  --section-primary-border: oklch(0.858 0.110 300);
  --section-secondary:        oklch(0.948 0.050 184);
  --section-secondary-on:     var(--teal-700);
  --section-secondary-border: oklch(0.900 0.066 184);
  --section-tertiary:        oklch(0.966 0.042 88);
  --section-tertiary-on:     oklch(0.470 0.092 70);
  --section-tertiary-border: oklch(0.922 0.060 85);

  /* ----- Intent — communicative accents beyond the 4 status tones -----
     brand: the primary action hue (re-pointed by signatures).
     discovery: new / AI / beta / what's-new.  premium: upgrade / pro. */
  --intent-brand:        var(--accent);
  --intent-brand-text:   var(--accent-text);
  --intent-brand-on:     var(--accent-on);
  --intent-brand-subtle: var(--accent-subtle);
  --intent-brand-border: var(--accent-border);
  --intent-discovery:        var(--violet-500);
  --intent-discovery-text:   var(--violet-700);
  --intent-discovery-on:     oklch(1 0 0);
  --intent-discovery-subtle: var(--violet-50);
  --intent-discovery-border: var(--violet-200);
  --intent-premium:        var(--amber-500);
  --intent-premium-text:   var(--amber-700);
  --intent-premium-on:     oklch(1 0 0);
  --intent-premium-subtle: var(--amber-50);
  --intent-premium-border: var(--amber-200);
}

/* ============================================================
   SEMANTIC LAYER · DARK
   Warm near-black canvas; brand shifts one stop lighter so the
   vibrant blue still pops on dark surfaces.
   The Industry theme (tokens/theme-industry.css) extends this
   layer — it inherits the whole dark role set, then re-points
   surfaces, accent, material and geometry.
   data-theme="system" (follow the OS) mirrors this block under
   prefers-color-scheme: dark, in the GENERATED region right after
   it (prism-docs/scripts/generate-system-theme.cjs).
   ============================================================ */
[data-theme="dark"],
[data-theme="industry"] {
  color-scheme: dark;

  --brand-on: oklch(1 0 0);

  /* Surfaces lifted +5 L pts off the near-black base so drop shadows read
     and elevation steps stay distinct (was page .188 / card .235 / raised
     .285 / overlay .32). Sunken stays below page so recessed wells read. */
  /* Dark surfaces are near-neutral (chroma ≤ 0.005): warmer values read as
     brown once cards stack. Elevation is lightness. */
  --surface-page:    oklch(0.238 0.003 62);
  --surface-sunken:  oklch(0.205 0.004 58);
  --surface-card:    oklch(0.285 0.004 64);
  --surface-raised:  oklch(0.335 0.005 60);
  --surface-overlay: oklch(0.370 0.005 60);
  --surface-inverse: var(--gray-50);
  --surface-scrim:   oklch(0 0 0 / 0.66);

  --fill-subtle:       oklch(0.97 0.01 80 / 0.05);
  --fill-subtle-hover: oklch(0.97 0.01 80 / 0.09);
  --fill-muted:        oklch(0.97 0.01 80 / 0.14);
  --surface-stripe:    oklch(0.97 0.01 80 / 0.03);

  --text-primary:    var(--gray-50);
  --text-secondary:  var(--gray-300);
  --text-tertiary:   var(--gray-400);
  --text-placeholder: var(--gray-500);
  --text-disabled:   var(--gray-600);
  --text-on-inverse: var(--gray-900);
  --text-link:       var(--cobalt-300);
  --text-link-hover: var(--cobalt-200);

  --border-subtle:  oklch(0.97 0.01 80 / 0.08);
  --border-default: oklch(0.97 0.01 80 / 0.15);
  --border-strong:  oklch(0.97 0.01 80 / 0.26);
  --border-inverse: var(--gray-300);

  /* The accent is a fill under white ink: deep enough for 4.5:1 (cobalt-400
     was 3.39). Hover and press go deeper still, never lighter, so the ink
     keeps its contrast; --accent-text and the focus ring stay bright. */
  --accent:           oklch(0.555 0.155 258);
  --accent-hover:     oklch(0.525 0.158 258);
  --accent-active:    oklch(0.495 0.160 258);
  --accent-text:      var(--cobalt-300);
  --accent-on:        oklch(1 0 0);
  --accent-subtle:    oklch(0.640 0.140 258 / 0.18);
  --accent-subtle-hover: oklch(0.640 0.140 258 / 0.28);
  --accent-border:    oklch(0.750 0.110 258 / 0.40);

  --positive:        var(--green-400);
  --positive-hover:  var(--green-300);
  --positive-text:   var(--green-300);
  --positive-on:     oklch(0.18 0.04 156);
  --positive-subtle: oklch(0.680 0.165 156 / 0.16);
  --positive-border: oklch(0.745 0.155 156 / 0.36);

  --notice:        var(--amber-300);
  --notice-hover:  var(--amber-200);
  --notice-text:   var(--amber-200);
  --notice-on:     oklch(0.2 0.05 70);
  --notice-subtle: oklch(0.785 0.150 70 / 0.16);
  --notice-border: oklch(0.845 0.130 78 / 0.34);

  --negative:        var(--red-400);
  --negative-hover:  var(--red-300);
  --negative-text:   var(--red-300);
  --negative-on:     oklch(0.2 0.05 27);
  --negative-subtle: oklch(0.625 0.225 27 / 0.18);
  --negative-border: oklch(0.805 0.120 26 / 0.34);

  --info:        var(--sky-300);
  --info-hover:  var(--sky-200);
  --info-text:   var(--sky-200);
  --info-on:     oklch(0.18 0.05 240);
  --info-subtle: oklch(0.665 0.150 240 / 0.18);
  --info-border: oklch(0.740 0.135 238 / 0.34);

  --focus-ring:        var(--cobalt-400);
  --focus-ring-offset: var(--gray-950);

  /* Section accents (dark) — translucent washes; alpha falls primary→tertiary */
  --section-primary:        oklch(0.560 0.205 300 / 0.20);
  --section-primary-on:     var(--violet-200);
  --section-primary-border: oklch(0.770 0.140 300 / 0.36);
  --section-secondary:        oklch(0.595 0.095 182 / 0.15);
  --section-secondary-on:     var(--teal-200);
  --section-secondary-border: oklch(0.755 0.105 182 / 0.30);
  --section-tertiary:        oklch(0.760 0.130 80 / 0.12);
  --section-tertiary-on:     oklch(0.880 0.080 88);
  --section-tertiary-border: oklch(0.800 0.110 82 / 0.26);

  /* Intent (dark) — brand follows accent; discovery/premium go translucent */
  --intent-brand:        var(--accent);
  --intent-brand-text:   var(--accent-text);
  --intent-brand-on:     var(--accent-on);
  --intent-brand-subtle: var(--accent-subtle);
  --intent-brand-border: var(--accent-border);
  --intent-discovery:        var(--violet-400);
  --intent-discovery-text:   var(--violet-200);
  --intent-discovery-on:     oklch(1 0 0);
  --intent-discovery-subtle: oklch(0.560 0.205 300 / 0.20);
  --intent-discovery-border: oklch(0.770 0.140 300 / 0.36);
  --intent-premium:        var(--amber-300);
  --intent-premium-text:   var(--amber-200);
  --intent-premium-on:     oklch(0.2 0.05 70);
  --intent-premium-subtle: oklch(0.785 0.150 70 / 0.16);
  --intent-premium-border: oklch(0.845 0.130 78 / 0.34);
}

/* >>> GENERATED · data-theme="system" dark half — do not edit; source is the block above. Run `cd prism-docs && npm run gen`. >>> */
@media (prefers-color-scheme: dark) {
  [data-theme="system"] {
    color-scheme: dark;

    --brand-on: oklch(1 0 0);

    /* Surfaces lifted +5 L pts off the near-black base so drop shadows read
       and elevation steps stay distinct (was page .188 / card .235 / raised
       .285 / overlay .32). Sunken stays below page so recessed wells read. */
    /* Dark surfaces are near-neutral (chroma ≤ 0.005): warmer values read as
       brown once cards stack. Elevation is lightness. */
    --surface-page:    oklch(0.238 0.003 62);
    --surface-sunken:  oklch(0.205 0.004 58);
    --surface-card:    oklch(0.285 0.004 64);
    --surface-raised:  oklch(0.335 0.005 60);
    --surface-overlay: oklch(0.370 0.005 60);
    --surface-inverse: var(--gray-50);
    --surface-scrim:   oklch(0 0 0 / 0.66);

    --fill-subtle:       oklch(0.97 0.01 80 / 0.05);
    --fill-subtle-hover: oklch(0.97 0.01 80 / 0.09);
    --fill-muted:        oklch(0.97 0.01 80 / 0.14);
    --surface-stripe:    oklch(0.97 0.01 80 / 0.03);

    --text-primary:    var(--gray-50);
    --text-secondary:  var(--gray-300);
    --text-tertiary:   var(--gray-400);
    --text-placeholder: var(--gray-500);
    --text-disabled:   var(--gray-600);
    --text-on-inverse: var(--gray-900);
    --text-link:       var(--cobalt-300);
    --text-link-hover: var(--cobalt-200);

    --border-subtle:  oklch(0.97 0.01 80 / 0.08);
    --border-default: oklch(0.97 0.01 80 / 0.15);
    --border-strong:  oklch(0.97 0.01 80 / 0.26);
    --border-inverse: var(--gray-300);

    /* The accent is a fill under white ink: deep enough for 4.5:1 (cobalt-400
       was 3.39). Hover and press go deeper still, never lighter, so the ink
       keeps its contrast; --accent-text and the focus ring stay bright. */
    --accent:           oklch(0.555 0.155 258);
    --accent-hover:     oklch(0.525 0.158 258);
    --accent-active:    oklch(0.495 0.160 258);
    --accent-text:      var(--cobalt-300);
    --accent-on:        oklch(1 0 0);
    --accent-subtle:    oklch(0.640 0.140 258 / 0.18);
    --accent-subtle-hover: oklch(0.640 0.140 258 / 0.28);
    --accent-border:    oklch(0.750 0.110 258 / 0.40);

    --positive:        var(--green-400);
    --positive-hover:  var(--green-300);
    --positive-text:   var(--green-300);
    --positive-on:     oklch(0.18 0.04 156);
    --positive-subtle: oklch(0.680 0.165 156 / 0.16);
    --positive-border: oklch(0.745 0.155 156 / 0.36);

    --notice:        var(--amber-300);
    --notice-hover:  var(--amber-200);
    --notice-text:   var(--amber-200);
    --notice-on:     oklch(0.2 0.05 70);
    --notice-subtle: oklch(0.785 0.150 70 / 0.16);
    --notice-border: oklch(0.845 0.130 78 / 0.34);

    --negative:        var(--red-400);
    --negative-hover:  var(--red-300);
    --negative-text:   var(--red-300);
    --negative-on:     oklch(0.2 0.05 27);
    --negative-subtle: oklch(0.625 0.225 27 / 0.18);
    --negative-border: oklch(0.805 0.120 26 / 0.34);

    --info:        var(--sky-300);
    --info-hover:  var(--sky-200);
    --info-text:   var(--sky-200);
    --info-on:     oklch(0.18 0.05 240);
    --info-subtle: oklch(0.665 0.150 240 / 0.18);
    --info-border: oklch(0.740 0.135 238 / 0.34);

    --focus-ring:        var(--cobalt-400);
    --focus-ring-offset: var(--gray-950);

    /* Section accents (dark) — translucent washes; alpha falls primary→tertiary */
    --section-primary:        oklch(0.560 0.205 300 / 0.20);
    --section-primary-on:     var(--violet-200);
    --section-primary-border: oklch(0.770 0.140 300 / 0.36);
    --section-secondary:        oklch(0.595 0.095 182 / 0.15);
    --section-secondary-on:     var(--teal-200);
    --section-secondary-border: oklch(0.755 0.105 182 / 0.30);
    --section-tertiary:        oklch(0.760 0.130 80 / 0.12);
    --section-tertiary-on:     oklch(0.880 0.080 88);
    --section-tertiary-border: oklch(0.800 0.110 82 / 0.26);

    /* Intent (dark) — brand follows accent; discovery/premium go translucent */
    --intent-brand:        var(--accent);
    --intent-brand-text:   var(--accent-text);
    --intent-brand-on:     var(--accent-on);
    --intent-brand-subtle: var(--accent-subtle);
    --intent-brand-border: var(--accent-border);
    --intent-discovery:        var(--violet-400);
    --intent-discovery-text:   var(--violet-200);
    --intent-discovery-on:     oklch(1 0 0);
    --intent-discovery-subtle: oklch(0.560 0.205 300 / 0.20);
    --intent-discovery-border: oklch(0.770 0.140 300 / 0.36);
    --intent-premium:        var(--amber-300);
    --intent-premium-text:   var(--amber-200);
    --intent-premium-on:     oklch(0.2 0.05 70);
    --intent-premium-subtle: oklch(0.785 0.150 70 / 0.16);
    --intent-premium-border: oklch(0.845 0.130 78 / 0.34);
  }
}
/* <<< GENERATED · data-theme="system" <<< */

/* >>> GENERATED · print uses the light theme — do not edit; source is the light block. Run `cd prism-docs && npm run gen`. >>> */
@media print {
  [data-theme="dark"],
  [data-theme="system"],
  [data-theme="industry"] {
    color-scheme: light;

    /* Surfaces — warm near-white canvas, white cards float above it */
    --surface-page:      var(--gray-25);
    --surface-sunken:    var(--gray-100);
    --surface-card:      var(--gray-0);
    --surface-raised:    var(--gray-0);
    --surface-overlay:   var(--gray-0);
    --surface-inverse:   var(--gray-900);
    --surface-scrim:     oklch(0.235 0.010 60 / 0.5);

    /* Subtle fills for hover/selected zones */
    --fill-subtle:       var(--gray-100);
    --fill-subtle-hover: var(--gray-150);
    --fill-muted:        var(--gray-200);
    --surface-stripe:    var(--gray-50);  /* subtle zebra striping for tables */

    /* Text */
    --text-primary:    var(--gray-900);
    --text-secondary:  var(--gray-600);
    --text-tertiary:   var(--gray-500);
    /* A placeholder is not content — it is an example of content. It must read
       as ABSENT, so it sits BELOW tertiary rather than sharing it: reuse tertiary
       and a hinted field looks filled in. Never put required information in one;
       the label and description carry meaning, which is why this role is allowed
       to fall below 4.5:1. */
    --text-placeholder: var(--gray-400);
    --text-disabled:   var(--gray-400);
    --text-on-inverse: var(--gray-50);
    --text-link:       var(--brand-600);
    --text-link-hover: var(--brand-700);

    /* Borders */
    --border-subtle:  var(--gray-150);
    --border-default: var(--gray-200);
    --border-strong:  var(--gray-300);
    --border-inverse: var(--gray-700);

    /* Brand / accent roles */
    --accent:           var(--brand-500);
    --accent-hover:     var(--brand-600);
    --accent-active:    var(--brand-700);
    --accent-text:      var(--brand-600);
    --accent-on:        var(--brand-on);
    --accent-subtle:    var(--brand-50);
    --accent-subtle-hover: var(--brand-100);
    --accent-border:    var(--brand-200);

    /* Positive */
    --positive:        var(--green-500);
    --positive-hover:  var(--green-600);
    --positive-text:   var(--green-600);
    --positive-on:     oklch(1 0 0);
    --positive-subtle: var(--green-50);
    --positive-border: var(--green-200);

    /* Notice */
    --notice:        var(--amber-400);
    --notice-hover:  var(--amber-500);
    --notice-text:   var(--amber-600);
    --notice-on:     oklch(1 0 0);
    --notice-subtle: var(--amber-50);
    --notice-border: var(--amber-200);

    /* Negative */
    --negative:        var(--red-500);
    --negative-hover:  var(--red-600);
    --negative-text:   var(--red-600);
    --negative-on:     oklch(1 0 0);
    --negative-subtle: var(--red-50);
    --negative-border: var(--red-200);

    /* Informative */
    --info:        var(--sky-500);
    --info-hover:  var(--sky-600);
    --info-text:   var(--sky-600);
    --info-on:     oklch(1 0 0);
    --info-subtle: var(--sky-50);
    --info-border: var(--sky-200);

    /* Focus ring — the single most important a11y affordance */
    --focus-ring:        var(--brand-500);
    --focus-ring-offset: var(--gray-0);

    /* ----- Section accents — tint whole sections to set them apart -----
       A 3-step ATTENTION HIERARCHY: PRIMARY commands the most attention,
       SECONDARY less, TERTIARY the least (but still pleasant). Attention
       falls as chroma drops and lightness rises across the three. Each
       carries an `-on` text and `-border` token, AA-tuned. */
    --section-primary:        oklch(0.918 0.078 300);
    --section-primary-on:     var(--violet-700);
    --section-primary-border: oklch(0.858 0.110 300);
    --section-secondary:        oklch(0.948 0.050 184);
    --section-secondary-on:     var(--teal-700);
    --section-secondary-border: oklch(0.900 0.066 184);
    --section-tertiary:        oklch(0.966 0.042 88);
    --section-tertiary-on:     oklch(0.470 0.092 70);
    --section-tertiary-border: oklch(0.922 0.060 85);

    /* ----- Intent — communicative accents beyond the 4 status tones -----
       brand: the primary action hue (re-pointed by signatures).
       discovery: new / AI / beta / what's-new.  premium: upgrade / pro. */
    --intent-brand:        var(--accent);
    --intent-brand-text:   var(--accent-text);
    --intent-brand-on:     var(--accent-on);
    --intent-brand-subtle: var(--accent-subtle);
    --intent-brand-border: var(--accent-border);
    --intent-discovery:        var(--violet-500);
    --intent-discovery-text:   var(--violet-700);
    --intent-discovery-on:     oklch(1 0 0);
    --intent-discovery-subtle: var(--violet-50);
    --intent-discovery-border: var(--violet-200);
    --intent-premium:        var(--amber-500);
    --intent-premium-text:   var(--amber-700);
    --intent-premium-on:     oklch(1 0 0);
    --intent-premium-subtle: var(--amber-50);
    --intent-premium-border: var(--amber-200);
  }
}
/* <<< GENERATED · print <<< */

/* ============================================================
   Data-series families — one ordered hue run each, all spaced to the
   same luminance ladder, so swapping family changes hue and NOTHING
   else about readability. Theme-agnostic: set data-series anywhere.
   ============================================================ */
[data-series="azure"] {
  --series-1: oklch(0.881 0.115 270); /* luma 210 @kind color */
  --series-2: oklch(0.813 0.18 261); /* luma 182 @kind color */
  --series-3: oklch(0.766 0.225 253); /* luma 154 @kind color */
  --series-4: oklch(0.66 0.25 244); /* luma 126 @kind color */
  --series-5: oklch(0.523 0.235 235); /* luma 97 @kind color */
  --series-6: oklch(0.401 0.205 227); /* luma 71 @kind color */
}
[data-series="violet"] {
  --series-1: oklch(0.889 0.115 324); /* luma 211 @kind color */
  --series-2: oklch(0.822 0.18 315); /* luma 182 @kind color */
  --series-3: oklch(0.751 0.225 307); /* luma 154 @kind color */
  --series-4: oklch(0.673 0.25 298); /* luma 127 @kind color */
  --series-5: oklch(0.567 0.235 289); /* luma 99 @kind color */
  --series-6: oklch(0.456 0.205 281); /* luma 70 @kind color */
}
[data-series="magenta"] {
  --series-1: oklch(0.914 0.115 356); /* luma 210 @kind color */
  --series-2: oklch(0.858 0.18 347); /* luma 182 @kind color */
  --series-3: oklch(0.785 0.225 339); /* luma 154 @kind color */
  --series-4: oklch(0.703 0.25 330); /* luma 126 @kind color */
  --series-5: oklch(0.601 0.235 321); /* luma 98 @kind color */
  --series-6: oklch(0.487 0.205 313); /* luma 70 @kind color */
}
[data-series="cyan"] {
  --series-1: oklch(0.88 0.115 228); /* luma 210 @kind color */
  --series-2: oklch(0.842 0.18 219); /* luma 182 @kind color */
  --series-3: oklch(0.706 0.225 211); /* luma 154 @kind color */
  --series-4: oklch(0.583 0.25 202); /* luma 126 @kind color */
  --series-5: oklch(0.474 0.235 193); /* luma 98 @kind color */
  --series-6: oklch(0.368 0.205 185); /* luma 71 @kind color */
}
[data-series="green"] {
  --series-1: oklch(0.864 0.115 164); /* luma 209 @kind color */
  --series-2: oklch(0.801 0.18 155); /* luma 182 @kind color */
  --series-3: oklch(0.744 0.225 147); /* luma 153 @kind color */
  --series-4: oklch(0.639 0.25 138); /* luma 127 @kind color */
  --series-5: oklch(0.504 0.235 129); /* luma 98 @kind color */
  --series-6: oklch(0.392 0.205 121); /* luma 69 @kind color */
}
[data-series="amber"] {
  --series-1: oklch(0.865 0.115 108); /* luma 210 @kind color */
  --series-2: oklch(0.8 0.18 99); /* luma 182 @kind color */
  --series-3: oklch(0.715 0.225 91); /* luma 154 @kind color */
  --series-4: oklch(0.641 0.25 82); /* luma 126 @kind color */
  --series-5: oklch(0.566 0.235 73); /* luma 98 @kind color */
  --series-6: oklch(0.478 0.205 65); /* luma 70 @kind color */
}
[data-series="orange"] {
  --series-1: oklch(0.893 0.115 66); /* luma 210 @kind color */
  --series-2: oklch(0.851 0.18 57); /* luma 181 @kind color */
  --series-3: oklch(0.818 0.225 49); /* luma 154 @kind color */
  --series-4: oklch(0.765 0.25 40); /* luma 126 @kind color */
  --series-5: oklch(0.652 0.235 31); /* luma 97 @kind color */
  --series-6: oklch(0.548 0.205 23); /* luma 70 @kind color */
}

/* ===== tokens/signatures.css ===== */
/* ============================================================
   Prism · Product signatures
   ------------------------------------------------------------
   One attribute re-skins a whole app to a platform's identity:

     <html data-signature="health" data-density="compact">
     <div  data-signature="finance"> … scoped region … </div>

   Each signature re-points the accent roles (and chart series 1)
   to a canonical --domain-* hue, and exposes a --signature-gradient
   for heroes. The derived roles are computed once in the shared
   [data-signature] block via color-mix against the LIVE
   --surface-card / --text-primary, so the SAME definition works in
   both light and dark themes. A recommended density is noted per
   signature — set it with data-density alongside.
   ============================================================ */

/* pick the hue per signature */
[data-signature="commerce"]    { --sig: var(--domain-commerce); }     /* density: comfortable */
[data-signature="campus"]      { --sig: var(--domain-campus); }       /* density: relaxed */
[data-signature="health"]      { --sig: var(--domain-health); }       /* density: compact */
[data-signature="media"]       { --sig: var(--domain-media); }        /* density: comfortable (cinema tier on TV) */
[data-signature="finance"]     { --sig: var(--domain-finance); }      /* density: compact */
[data-signature="hospitality"] { --sig: var(--domain-hospitality); } /* amber takes dark ink — set after the shared block below */
[data-signature="estate"]      { --sig: var(--domain-estate); }       /* density: comfortable */

/* shared derived roles — resolved against the active theme */
[data-signature] {
  --accent:              var(--sig);
  --accent-hover:        color-mix(in oklab, var(--sig) 86%, var(--text-primary));
  --accent-active:       color-mix(in oklab, var(--sig) 76%, var(--text-primary));
  --accent-text:         color-mix(in oklab, var(--sig) 72%, var(--text-primary));
  --accent-on:           oklch(1 0 0);
  --accent-subtle:       color-mix(in oklab, var(--sig) 12%, var(--surface-card));
  --accent-subtle-hover: color-mix(in oklab, var(--sig) 20%, var(--surface-card));
  --accent-border:       color-mix(in oklab, var(--sig) 30%, var(--surface-card));
  --focus-ring:          var(--sig);
  --text-link:           var(--accent-text);
  --text-link-hover:     var(--accent-hover);

  /* keep the intent-brand alias in sync */
  --intent-brand:        var(--accent);
  --intent-brand-text:   var(--accent-text);
  --intent-brand-on:     var(--accent-on);
  --intent-brand-subtle: var(--accent-subtle);
  --intent-brand-border: var(--accent-border);

  /* first chart series follows the brand for on-brand dashboards */
  --chart-1: var(--sig);

  /* hero gradient + a raw hue handle for custom work */
  --signature-hue: var(--sig);
  --signature-gradient: linear-gradient(135deg,
    color-mix(in oklch, var(--sig) 90%, black) 0%,
    var(--sig) 45%,
    color-mix(in oklab, var(--sig) 60%, var(--surface-card)) 100%);
}

/* Fill contrast. --accent is a FILL under --accent-on (buttons, solid
   badges, checked controls), so it must hold 4.5:1 against that ink. Some
   brand hues are too light for white ink (health, finance; hospitality is
   too dark for its dark ink), so the fill's lightness is capped — or, for a
   dark-ink signature, floored — while hue and chroma stay the brand's.
   Links (--accent-text), the focus ring and chart 1 keep the exact --sig.
   Without relative colour syntax the color-mix values above stay.
   (The cap is 0.5, not the ~0.57 that oklch L suggests: for greens and teals
   WCAG luminance runs higher than L predicts.) */

/* Hospitality's amber takes dark ink. It has to follow the shared block
   above, which sets white ink for every other signature — before 2.8.1 the
   shared block won and amber buttons had white text at 3.5:1. */
[data-signature="hospitality"] { --accent-on: oklch(0.24 0.04 60); --intent-brand-on: var(--accent-on); }

@supports (color: oklch(from red l c h)) {
  [data-signature] {
    --accent:        oklch(from var(--sig) min(l, 0.5) c h);
    --accent-hover:  oklch(from var(--sig) calc(min(l, 0.5) - 0.035) c h);
    --accent-active: oklch(from var(--sig) calc(min(l, 0.5) - 0.07) c h);
  }
  [data-signature="hospitality"] {
    --accent:        oklch(from var(--sig) max(l, 0.74) c h);
    --accent-hover:  oklch(from var(--sig) calc(max(l, 0.74) - 0.025) c h);
    --accent-active: oklch(from var(--sig) calc(max(l, 0.74) - 0.05) c h);
  }
}

/* ------------------------------------------------------------
   Secondary brand colour — fine detail only
   ------------------------------------------------------------
   A logo's second colour (a gold, a silver) set as --sig-2 beside --sig,
   on <html> (where data-theme is):

     :root { --sig: #0b3d91; --sig-2: #c9a227; }

   Prism uses it for hairlines and small text, never to fill an area:
   the AppHeader current-item bar, the Sidebar current-item marker, the
   PageHeader eyebrow and Divider variant="accent". Raw gold or silver is
   too light to read on a light page, so components read derived roles
   (tokens/hues.css) that keep its hue and cap its lightness per theme:

     --sig-2-line   rules, bars, markers   (≥ 3:1 on page and card)
     --sig-2-text   small text             (≥ 4.5:1 on page and card)

   The dark theme gets its own lighter values automatically. To pick a
   different dark colour, set --sig-2 again in [data-theme="dark"]; to
   hand-tune, override --sig-2-line / --sig-2-text directly.
   ------------------------------------------------------------ */

/* ===== tokens/hues.css ===== */
/* ============================================================
   Prism · Categorical hues
   ------------------------------------------------------------
   Eight named hues for identity: per-module colour, chart series,
   avatars, tags. Each hue has five roles:

     --hue-teal           solid fill (chart marks, avatar fill, band)
     --hue-teal-on        ink on the solid fill
     --hue-teal-text      text on the page, on a card AND on the tint
     --hue-teal-surface   tint background (chips, avatars, banners)
     --hue-teal-border    tint border

   Contrast (WCAG, measured in sRGB) holds in every theme:
     text on card / page / its own surface  ≥ 4.5
     on-ink on the solid                    ≥ 4.5
     solid against card and page            ≥ 3   (graphics)
   tokens/hues.card.html measures the rendered pixels.

   data-hue on ANY element re-points that container's accent roles
   to one hue, the way data-signature does for a product:

     <section data-hue="teal"> …buttons, links, focus, chart 1… </section>

   Inside it, --hue / --hue-on / --hue-text / --hue-surface /
   --hue-border name the active hue, so component CSS can tint
   without knowing which hue it is.
   ============================================================ */

:root,
[data-theme="light"],
[data-theme="system"],
[data-theme="laboratory"] {
  --hue-rose:            oklch(0.55 0.17 15);    /* @kind color */
  --hue-rose-on:         oklch(1 0 0);           /* @kind color */
  --hue-rose-text:       oklch(0.47 0.14 15);    /* @kind color */
  --hue-rose-surface:    oklch(0.955 0.022 15);  /* @kind color */
  --hue-rose-border:     oklch(0.84 0.07 15);    /* @kind color */
  --hue-orange:          oklch(0.55 0.144 50);   /* @kind color */
  --hue-orange-on:       oklch(1 0 0);           /* @kind color */
  --hue-orange-text:     oklch(0.47 0.124 50);   /* @kind color */
  --hue-orange-surface:  oklch(0.955 0.024 50);  /* @kind color */
  --hue-orange-border:   oklch(0.84 0.07 50);    /* @kind color */
  --hue-amber:           oklch(0.54 0.11 80);    /* @kind color */
  --hue-amber-on:        oklch(1 0 0);           /* @kind color */
  --hue-amber-text:      oklch(0.47 0.096 80);   /* @kind color */
  --hue-amber-surface:   oklch(0.955 0.03 80);   /* @kind color */
  --hue-amber-border:    oklch(0.84 0.07 80);    /* @kind color */
  --hue-green:           oklch(0.53 0.146 150);  /* @kind color */
  --hue-green-on:        oklch(1 0 0);           /* @kind color */
  --hue-green-text:      oklch(0.47 0.128 150);  /* @kind color */
  --hue-green-surface:   oklch(0.955 0.03 150);  /* @kind color */
  --hue-green-border:    oklch(0.84 0.07 150);   /* @kind color */
  --hue-teal:            oklch(0.53 0.09 190);   /* @kind color */
  --hue-teal-on:         oklch(1 0 0);           /* @kind color */
  --hue-teal-text:       oklch(0.47 0.08 190);   /* @kind color */
  --hue-teal-surface:    oklch(0.955 0.03 190);  /* @kind color */
  --hue-teal-border:     oklch(0.84 0.07 190);   /* @kind color */
  --hue-blue:            oklch(0.55 0.154 250);  /* @kind color */
  --hue-blue-on:         oklch(1 0 0);           /* @kind color */
  --hue-blue-text:       oklch(0.47 0.132 250);  /* @kind color */
  --hue-blue-surface:    oklch(0.955 0.022 250); /* @kind color */
  --hue-blue-border:     oklch(0.84 0.07 250);   /* @kind color */
  --hue-violet:          oklch(0.55 0.17 295);   /* @kind color */
  --hue-violet-on:       oklch(1 0 0);           /* @kind color */
  --hue-violet-text:     oklch(0.47 0.14 295);   /* @kind color */
  --hue-violet-surface:  oklch(0.955 0.022 295); /* @kind color */
  --hue-violet-border:   oklch(0.84 0.07 295);   /* @kind color */
  --hue-magenta:         oklch(0.55 0.17 340);   /* @kind color */
  --hue-magenta-on:      oklch(1 0 0);           /* @kind color */
  --hue-magenta-text:    oklch(0.47 0.14 340);   /* @kind color */
  --hue-magenta-surface: oklch(0.955 0.03 340);  /* @kind color */
  --hue-magenta-border:  oklch(0.84 0.07 340);   /* @kind color */

  /* Secondary brand colour (--sig-2, set by the app; see signatures.css).
     Its hue and chroma kept, its lightness capped so any logo colour reads:
     a line ≥ 3:1 and text ≥ 4.5:1 on page and card. -inverse is for the
     inverse AppHeader bar (dark on a light page). Unset --sig-2 leaves all
     three invalid, so components fall back to what they drew before. */
  --sig-2-line:          oklch(from var(--sig-2) min(l, 0.6) c h);
  --sig-2-text:          oklch(from var(--sig-2) min(l, 0.5) c h);
  --sig-2-line-inverse:  oklch(from var(--sig-2) max(l, 0.72) c h);
}

[data-theme="dark"],
[data-theme="industry"] {
  --hue-rose:            oklch(0.72 0.14 15);
  --hue-rose-on:         oklch(0.2 0.03 15);
  --hue-rose-text:       oklch(0.8 0.11 15);
  --hue-rose-surface:    oklch(0.33 0.045 15);
  --hue-rose-border:     oklch(0.45 0.08 15);
  --hue-orange:          oklch(0.72 0.14 50);
  --hue-orange-on:       oklch(0.2 0.03 50);
  --hue-orange-text:     oklch(0.8 0.11 50);
  --hue-orange-surface:  oklch(0.33 0.045 50);
  --hue-orange-border:   oklch(0.45 0.08 50);
  --hue-amber:           oklch(0.72 0.14 80);
  --hue-amber-on:        oklch(0.2 0.03 80);
  --hue-amber-text:      oklch(0.8 0.11 80);
  --hue-amber-surface:   oklch(0.33 0.045 80);
  --hue-amber-border:    oklch(0.45 0.08 80);
  --hue-green:           oklch(0.72 0.14 150);
  --hue-green-on:        oklch(0.2 0.03 150);
  --hue-green-text:      oklch(0.8 0.11 150);
  --hue-green-surface:   oklch(0.33 0.045 150);
  --hue-green-border:    oklch(0.45 0.08 150);
  --hue-teal:            oklch(0.72 0.124 190);
  --hue-teal-on:         oklch(0.2 0.03 190);
  --hue-teal-text:       oklch(0.8 0.11 190);
  --hue-teal-surface:    oklch(0.33 0.045 190);
  --hue-teal-border:     oklch(0.45 0.076 190);
  --hue-blue:            oklch(0.72 0.14 250);
  --hue-blue-on:         oklch(0.2 0.03 250);
  --hue-blue-text:       oklch(0.8 0.104 250);
  --hue-blue-surface:    oklch(0.33 0.045 250);
  --hue-blue-border:     oklch(0.45 0.08 250);
  --hue-violet:          oklch(0.72 0.14 295);
  --hue-violet-on:       oklch(0.2 0.03 295);
  --hue-violet-text:     oklch(0.8 0.11 295);
  --hue-violet-surface:  oklch(0.33 0.045 295);
  --hue-violet-border:   oklch(0.45 0.08 295);
  --hue-magenta:         oklch(0.72 0.14 340);
  --hue-magenta-on:      oklch(0.2 0.03 340);
  --hue-magenta-text:    oklch(0.8 0.11 340);
  --hue-magenta-surface: oklch(0.33 0.045 340);
  --hue-magenta-border:  oklch(0.45 0.08 340);
  --sig-2-line:          oklch(from var(--sig-2) max(l, 0.68) c h);
  --sig-2-text:          oklch(from var(--sig-2) max(l, 0.76) c h);
  --sig-2-line-inverse:  oklch(from var(--sig-2) min(l, 0.55) c h);
}

/* >>> GENERATED · data-theme="system" dark half — do not edit; source is the block above. Run `cd prism-docs && npm run gen`. >>> */
@media (prefers-color-scheme: dark) {
  [data-theme="system"] {
    --hue-rose:            oklch(0.72 0.14 15);
    --hue-rose-on:         oklch(0.2 0.03 15);
    --hue-rose-text:       oklch(0.8 0.11 15);
    --hue-rose-surface:    oklch(0.33 0.045 15);
    --hue-rose-border:     oklch(0.45 0.08 15);
    --hue-orange:          oklch(0.72 0.14 50);
    --hue-orange-on:       oklch(0.2 0.03 50);
    --hue-orange-text:     oklch(0.8 0.11 50);
    --hue-orange-surface:  oklch(0.33 0.045 50);
    --hue-orange-border:   oklch(0.45 0.08 50);
    --hue-amber:           oklch(0.72 0.14 80);
    --hue-amber-on:        oklch(0.2 0.03 80);
    --hue-amber-text:      oklch(0.8 0.11 80);
    --hue-amber-surface:   oklch(0.33 0.045 80);
    --hue-amber-border:    oklch(0.45 0.08 80);
    --hue-green:           oklch(0.72 0.14 150);
    --hue-green-on:        oklch(0.2 0.03 150);
    --hue-green-text:      oklch(0.8 0.11 150);
    --hue-green-surface:   oklch(0.33 0.045 150);
    --hue-green-border:    oklch(0.45 0.08 150);
    --hue-teal:            oklch(0.72 0.124 190);
    --hue-teal-on:         oklch(0.2 0.03 190);
    --hue-teal-text:       oklch(0.8 0.11 190);
    --hue-teal-surface:    oklch(0.33 0.045 190);
    --hue-teal-border:     oklch(0.45 0.076 190);
    --hue-blue:            oklch(0.72 0.14 250);
    --hue-blue-on:         oklch(0.2 0.03 250);
    --hue-blue-text:       oklch(0.8 0.104 250);
    --hue-blue-surface:    oklch(0.33 0.045 250);
    --hue-blue-border:     oklch(0.45 0.08 250);
    --hue-violet:          oklch(0.72 0.14 295);
    --hue-violet-on:       oklch(0.2 0.03 295);
    --hue-violet-text:     oklch(0.8 0.11 295);
    --hue-violet-surface:  oklch(0.33 0.045 295);
    --hue-violet-border:   oklch(0.45 0.08 295);
    --hue-magenta:         oklch(0.72 0.14 340);
    --hue-magenta-on:      oklch(0.2 0.03 340);
    --hue-magenta-text:    oklch(0.8 0.11 340);
    --hue-magenta-surface: oklch(0.33 0.045 340);
    --hue-magenta-border:  oklch(0.45 0.08 340);
    --sig-2-line:          oklch(from var(--sig-2) max(l, 0.68) c h);
    --sig-2-text:          oklch(from var(--sig-2) max(l, 0.76) c h);
    --sig-2-line-inverse:  oklch(from var(--sig-2) min(l, 0.55) c h);
  }
}
/* <<< GENERATED · data-theme="system" <<< */

/* >>> GENERATED · print uses the light theme — do not edit; source is the light block. Run `cd prism-docs && npm run gen`. >>> */
@media print {
  [data-theme="dark"],
  [data-theme="system"],
  [data-theme="industry"] {
    --hue-rose:            oklch(0.55 0.17 15);    /* @kind color */
    --hue-rose-on:         oklch(1 0 0);           /* @kind color */
    --hue-rose-text:       oklch(0.47 0.14 15);    /* @kind color */
    --hue-rose-surface:    oklch(0.955 0.022 15);  /* @kind color */
    --hue-rose-border:     oklch(0.84 0.07 15);    /* @kind color */
    --hue-orange:          oklch(0.55 0.144 50);   /* @kind color */
    --hue-orange-on:       oklch(1 0 0);           /* @kind color */
    --hue-orange-text:     oklch(0.47 0.124 50);   /* @kind color */
    --hue-orange-surface:  oklch(0.955 0.024 50);  /* @kind color */
    --hue-orange-border:   oklch(0.84 0.07 50);    /* @kind color */
    --hue-amber:           oklch(0.54 0.11 80);    /* @kind color */
    --hue-amber-on:        oklch(1 0 0);           /* @kind color */
    --hue-amber-text:      oklch(0.47 0.096 80);   /* @kind color */
    --hue-amber-surface:   oklch(0.955 0.03 80);   /* @kind color */
    --hue-amber-border:    oklch(0.84 0.07 80);    /* @kind color */
    --hue-green:           oklch(0.53 0.146 150);  /* @kind color */
    --hue-green-on:        oklch(1 0 0);           /* @kind color */
    --hue-green-text:      oklch(0.47 0.128 150);  /* @kind color */
    --hue-green-surface:   oklch(0.955 0.03 150);  /* @kind color */
    --hue-green-border:    oklch(0.84 0.07 150);   /* @kind color */
    --hue-teal:            oklch(0.53 0.09 190);   /* @kind color */
    --hue-teal-on:         oklch(1 0 0);           /* @kind color */
    --hue-teal-text:       oklch(0.47 0.08 190);   /* @kind color */
    --hue-teal-surface:    oklch(0.955 0.03 190);  /* @kind color */
    --hue-teal-border:     oklch(0.84 0.07 190);   /* @kind color */
    --hue-blue:            oklch(0.55 0.154 250);  /* @kind color */
    --hue-blue-on:         oklch(1 0 0);           /* @kind color */
    --hue-blue-text:       oklch(0.47 0.132 250);  /* @kind color */
    --hue-blue-surface:    oklch(0.955 0.022 250); /* @kind color */
    --hue-blue-border:     oklch(0.84 0.07 250);   /* @kind color */
    --hue-violet:          oklch(0.55 0.17 295);   /* @kind color */
    --hue-violet-on:       oklch(1 0 0);           /* @kind color */
    --hue-violet-text:     oklch(0.47 0.14 295);   /* @kind color */
    --hue-violet-surface:  oklch(0.955 0.022 295); /* @kind color */
    --hue-violet-border:   oklch(0.84 0.07 295);   /* @kind color */
    --hue-magenta:         oklch(0.55 0.17 340);   /* @kind color */
    --hue-magenta-on:      oklch(1 0 0);           /* @kind color */
    --hue-magenta-text:    oklch(0.47 0.14 340);   /* @kind color */
    --hue-magenta-surface: oklch(0.955 0.03 340);  /* @kind color */
    --hue-magenta-border:  oklch(0.84 0.07 340);   /* @kind color */

    /* Secondary brand colour (--sig-2, set by the app; see signatures.css).
       Its hue and chroma kept, its lightness capped so any logo colour reads:
       a line ≥ 3:1 and text ≥ 4.5:1 on page and card. -inverse is for the
       inverse AppHeader bar (dark on a light page). Unset --sig-2 leaves all
       three invalid, so components fall back to what they drew before. */
    --sig-2-line:          oklch(from var(--sig-2) min(l, 0.6) c h);
    --sig-2-text:          oklch(from var(--sig-2) min(l, 0.5) c h);
    --sig-2-line-inverse:  oklch(from var(--sig-2) max(l, 0.72) c h);
  }
}
/* <<< GENERATED · print <<< */

/* pick the hue per container */
[data-hue="rose"]    { --hue: var(--hue-rose);    --hue-on: var(--hue-rose-on);    --hue-text: var(--hue-rose-text);    --hue-surface: var(--hue-rose-surface);    --hue-border: var(--hue-rose-border); }
[data-hue="orange"]  { --hue: var(--hue-orange);  --hue-on: var(--hue-orange-on);  --hue-text: var(--hue-orange-text);  --hue-surface: var(--hue-orange-surface);  --hue-border: var(--hue-orange-border); }
[data-hue="amber"]   { --hue: var(--hue-amber);   --hue-on: var(--hue-amber-on);   --hue-text: var(--hue-amber-text);   --hue-surface: var(--hue-amber-surface);   --hue-border: var(--hue-amber-border); }
[data-hue="green"]   { --hue: var(--hue-green);   --hue-on: var(--hue-green-on);   --hue-text: var(--hue-green-text);   --hue-surface: var(--hue-green-surface);   --hue-border: var(--hue-green-border); }
[data-hue="teal"]    { --hue: var(--hue-teal);    --hue-on: var(--hue-teal-on);    --hue-text: var(--hue-teal-text);    --hue-surface: var(--hue-teal-surface);    --hue-border: var(--hue-teal-border); }
[data-hue="blue"]    { --hue: var(--hue-blue);    --hue-on: var(--hue-blue-on);    --hue-text: var(--hue-blue-text);    --hue-surface: var(--hue-blue-surface);    --hue-border: var(--hue-blue-border); }
[data-hue="violet"]  { --hue: var(--hue-violet);  --hue-on: var(--hue-violet-on);  --hue-text: var(--hue-violet-text);  --hue-surface: var(--hue-violet-surface);  --hue-border: var(--hue-violet-border); }
[data-hue="magenta"] { --hue: var(--hue-magenta); --hue-on: var(--hue-magenta-on); --hue-text: var(--hue-magenta-text); --hue-surface: var(--hue-magenta-surface); --hue-border: var(--hue-magenta-border); }

/* shared: the container's accent roles follow its hue. Listed by name so an
   unknown value (a typo, "auto") leaves the inherited accent alone. */
:is([data-hue="rose"], [data-hue="orange"], [data-hue="amber"], [data-hue="green"],
    [data-hue="teal"], [data-hue="blue"], [data-hue="violet"], [data-hue="magenta"]) {
  --accent:              var(--hue);
  --accent-hover:        color-mix(in oklab, var(--hue) 86%, var(--text-primary));
  --accent-active:       color-mix(in oklab, var(--hue) 76%, var(--text-primary));
  --accent-text:         var(--hue-text);
  --accent-on:           var(--hue-on);
  --accent-subtle:       var(--hue-surface);
  --accent-subtle-hover: color-mix(in oklab, var(--hue) 20%, var(--surface-card));
  --accent-border:       var(--hue-border);
  --focus-ring:          var(--hue);
  --text-link:           var(--hue-text);
  --text-link-hover:     var(--accent-hover);

  --intent-brand:        var(--accent);
  --intent-brand-text:   var(--accent-text);
  --intent-brand-on:     var(--accent-on);
  --intent-brand-subtle: var(--accent-subtle);
  --intent-brand-border: var(--accent-border);

  --chart-1: var(--hue);
}

/* Browsers without relative colour syntax (Chrome < 119, Firefox < 128):
   mix the secondary colour toward the live text colour instead — darker on
   light themes, lighter on dark ones. Mid-tone golds and silvers pass;
   a very pale one may fall under 3:1 here, so set --sig-2-line yourself. */
@supports not (color: oklch(from red l c h)) {
  :root, [data-theme] {
    --sig-2-line:         color-mix(in oklab, var(--sig-2) 60%, var(--text-primary));
    --sig-2-text:         color-mix(in oklab, var(--sig-2) 45%, var(--text-primary));
    --sig-2-line-inverse: color-mix(in oklab, var(--sig-2) 80%, var(--text-on-inverse));
  }
}

/* ===== tokens/gradients.css ===== */
/* ============================================================
   Prism · Gradient & background library  (OKLCH / P3)
   ------------------------------------------------------------
   A cross-industry set of gradients and background styles built
   on the palette. Five families:
     1. SUBTLE     low-chroma washes for surfaces & sections
     2. VIBRANT    expressive hero / marketing fills
     3. DUOTONE    two-stop brand-forward blends
     4. MESH       layered angled linear gradients (fade to transparent)
     5. INDUSTRY   signature fills per product vertical
   Plus PATTERN backgrounds (dots / grid / diagonal) as token +
   helper-class pairs. Gradients meant to carry white text are
   mid-to-dark; subtle ones take normal --text-* colours.
   ============================================================ */

:root {
  /* ---------- 1 · SUBTLE (light washes; use normal text colours) ---------- */
  --grad-subtle-neutral: linear-gradient(180deg, var(--gray-0), var(--gray-50)); /* @kind color */
  --grad-subtle-brand:   linear-gradient(160deg, var(--brand-50), oklch(0.985 0.006 264)); /* @kind color */
  --grad-subtle-cool:    linear-gradient(160deg, var(--sky-50), var(--teal-50)); /* @kind color */
  --grad-subtle-warm:    linear-gradient(160deg, var(--amber-50), var(--rose-50)); /* @kind color */
  --grad-subtle-violet:  linear-gradient(160deg, var(--violet-50), oklch(0.975 0.012 300)); /* @kind color */

  /* ---------- 2 · VIBRANT (expressive; carry white text) ---------- */
  --grad-vibrant-brand:  linear-gradient(135deg, oklch(0.62 0.24 264), oklch(0.52 0.26 296)); /* @kind color */
  --grad-vibrant-sunset: linear-gradient(135deg, oklch(0.74 0.18 60), oklch(0.62 0.24 18), oklch(0.50 0.23 330)); /* @kind color */
  --grad-vibrant-ocean:  linear-gradient(135deg, oklch(0.72 0.14 200), oklch(0.50 0.21 250)); /* @kind color */
  --grad-vibrant-forest: linear-gradient(135deg, oklch(0.74 0.17 150), oklch(0.52 0.13 195)); /* @kind color */
  --grad-vibrant-candy:  linear-gradient(135deg, oklch(0.70 0.20 330), oklch(0.62 0.22 12)); /* @kind color */

  /* ---------- 3 · DUOTONE (two-stop, brand-forward) ---------- */
  --grad-duo-brand-teal:  linear-gradient(120deg, var(--brand-500), var(--teal-500)); /* @kind color */
  --grad-duo-violet-rose: linear-gradient(120deg, var(--violet-500), var(--rose-500)); /* @kind color */
  --grad-duo-amber-rose:  linear-gradient(120deg, var(--amber-400), var(--rose-500)); /* @kind color */
  --grad-duo-sky-violet:  linear-gradient(120deg, var(--sky-500), var(--violet-500)); /* @kind color */

  /* ---------- 4 · MESH (layered angled gradients fading to transparency) ---------- */
  --grad-mesh-aurora: linear-gradient(115deg, oklch(0.72 0.20 300 / 0.55), transparent 55%),
                      linear-gradient(245deg, oklch(0.72 0.16 205 / 0.55), transparent 55%),
                      linear-gradient(15deg, oklch(0.74 0.17 150 / 0.45), transparent 60%),
                      linear-gradient(160deg, oklch(0.965 0.02 264), oklch(0.95 0.03 300)); /* @kind color */
  --grad-mesh-dawn:   linear-gradient(120deg, oklch(0.82 0.14 60 / 0.6), transparent 58%),
                      linear-gradient(250deg, oklch(0.76 0.16 12 / 0.5), transparent 58%),
                      linear-gradient(160deg, oklch(0.97 0.02 60), oklch(0.95 0.03 20)); /* @kind color */
  --grad-mesh-twilight: linear-gradient(125deg, oklch(0.48 0.22 290 / 0.85), transparent 60%),
                      linear-gradient(245deg, oklch(0.46 0.24 320 / 0.8), transparent 60%),
                      linear-gradient(20deg, oklch(0.42 0.20 250 / 0.8), transparent 62%),
                      linear-gradient(160deg, oklch(0.26 0.06 285), oklch(0.18 0.04 270)); /* @kind color */

  /* ---------- 5 · INDUSTRY signatures ----------
     Most verticals take a confident mid-dark fill (white text via
     --grad-on). EDUCATION & HEALTH are intentionally SOFT & GENTLE —
     light, low-chroma tints taking normal --text-* colours — out of
     sensitivity to their users' cognitive load and vulnerability. */
  --grad-education:  linear-gradient(135deg, oklch(0.955 0.035 292), oklch(0.945 0.045 262)); /* @kind color */
  --grad-health:     linear-gradient(135deg, oklch(0.962 0.032 186), oklch(0.952 0.038 162)); /* @kind color */
  --grad-commerce:   linear-gradient(135deg, oklch(0.52 0.20 255), oklch(0.44 0.15 222)); /* @kind color */
  --grad-media:      linear-gradient(135deg, oklch(0.50 0.24 300), oklch(0.46 0.22 8)); /* @kind color */
  --grad-finance:    linear-gradient(135deg, oklch(0.46 0.13 168), oklch(0.36 0.10 205)); /* @kind color */
  --grad-realestate: linear-gradient(135deg, oklch(0.58 0.12 62), oklch(0.44 0.10 34)); /* @kind color */
  --grad-technology: linear-gradient(135deg, oklch(0.44 0.18 264), oklch(0.40 0.21 292)); /* @kind color */
  --grad-hospitality: linear-gradient(135deg, oklch(0.56 0.16 40), oklch(0.46 0.17 12)); /* @kind color */
  /* Text colour to use on any vibrant / duotone / mesh-twilight / industry fill */
  --grad-on: oklch(1 0 0); /* @kind color */

  /* ---------- PATTERN backgrounds (pair each image token with its size) ---------- */
  --pattern-dots:      radial-gradient(oklch(0.55 0.01 70 / 0.18) 1.2px, transparent 1.2px); /* @kind other */
  --pattern-dots-size: 16px 16px;                                  /* @kind other */
  --pattern-grid:      linear-gradient(oklch(0.55 0.01 70 / 0.12) 1px, transparent 1px),
                       linear-gradient(90deg, oklch(0.55 0.01 70 / 0.12) 1px, transparent 1px); /* @kind other */
  --pattern-grid-size: 24px 24px;                                  /* @kind other */
  --pattern-diag:      repeating-linear-gradient(45deg, oklch(0.55 0.01 70 / 0.10) 0 1.5px, transparent 1.5px 11px); /* @kind other */
  --pattern-graph:     linear-gradient(oklch(0.55 0.01 70 / 0.07) 1px, transparent 1px),
                       linear-gradient(90deg, oklch(0.55 0.01 70 / 0.07) 1px, transparent 1px); /* @kind other */
  --pattern-graph-size: 8px 8px;                                   /* @kind other */
  --pattern-stripes:     repeating-linear-gradient(90deg, oklch(0.55 0.01 70 / 0.10) 0 1px, transparent 1px 12px); /* @kind other */
  --pattern-diagstripe:  repeating-linear-gradient(45deg, oklch(0.55 0.01 70 / 0.08) 0 8px, transparent 8px 16px); /* @kind other */
  --pattern-crosshatch:  repeating-linear-gradient(45deg, oklch(0.55 0.01 70 / 0.09) 0 1px, transparent 1px 10px),
                         repeating-linear-gradient(-45deg, oklch(0.55 0.01 70 / 0.09) 0 1px, transparent 1px 10px); /* @kind other */
  --pattern-checks:      repeating-conic-gradient(oklch(0.55 0.01 70 / 0.07) 0% 25%, transparent 0% 50%); /* @kind other */
  --pattern-checks-size: 22px 22px;                                /* @kind other */
  --pattern-iso:         repeating-linear-gradient(0deg, oklch(0.55 0.01 70 / 0.07) 0 1px, transparent 1px 18px),
                         repeating-linear-gradient(60deg, oklch(0.55 0.01 70 / 0.07) 0 1px, transparent 1px 18px),
                         repeating-linear-gradient(-60deg, oklch(0.55 0.01 70 / 0.07) 0 1px, transparent 1px 18px); /* @kind other */
  --pattern-confetti:    radial-gradient(oklch(0.55 0.01 70 / 0.16) 1.5px, transparent 1.5px),
                         radial-gradient(oklch(0.55 0.01 70 / 0.12) 1.5px, transparent 1.5px); /* @kind other */
  --pattern-confetti-size: 30px 30px;                              /* @kind other */
}

/* Pattern helper classes (need image + size together) */
.prism-bg-dots  { background-image: var(--pattern-dots);  background-size: var(--pattern-dots-size); }
.prism-bg-grid  { background-image: var(--pattern-grid);  background-size: var(--pattern-grid-size); }
.prism-bg-graph { background-image: var(--pattern-graph); background-size: var(--pattern-graph-size); }
.prism-bg-diag  { background-image: var(--pattern-diag); }
.prism-bg-stripes    { background-image: var(--pattern-stripes); }
.prism-bg-diagstripe { background-image: var(--pattern-diagstripe); }
.prism-bg-crosshatch { background-image: var(--pattern-crosshatch); }
.prism-bg-checks     { background-image: var(--pattern-checks); background-size: var(--pattern-checks-size); }
.prism-bg-iso        { background-image: var(--pattern-iso); }
.prism-bg-confetti   { background-image: var(--pattern-confetti); background-size: var(--pattern-confetti-size); background-position: 0 0, 15px 15px; }

/* ===== tokens/typography.css ===== */
/* ============================================================
   Prism · Typography
   ------------------------------------------------------------
   Display → Roboto Flex (optical-sizing auto for the Display cut)
   Text/UI → Atkinson Hyperlegible Next  (hyperlegible body)
   Mono    → Atkinson Hyperlegible Mono

   SIZE RULE: every font size MUST be a step of the Prism modular
   scale — never an in-between value. Steps (--type-*) and semantic
   roles (--fs-*) are GENERATED per size tier from
   tokens/scale.config.json into tokens/scales.css (body × ratio^step:
   mobile 16px·1.125, tablet 17px·1.2, desktop 18px·1.2, cinema
   24px·1.25). This file holds only the non-computed type primitives:
   families, weights, line-height/tracking primitives, measure.
   Sizes are rem so OS / user text-zoom always wins.
   ============================================================ */

:root {
  /* ---------- Families ---------- */
  --font-display: "Roboto Flex", "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-body: "Atkinson Hyperlegible Next", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Atkinson Hyperlegible Mono", ui-monospace, "SFMono-Regular", monospace;

  /* ---------- Weights ---------- */
  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;

  /* (The former frozen Tailwind --text-* ramp is gone. Modular steps
     --type-* live in GENERATED tokens/scales.css; legacy --text-* names
     survive there as deprecated aliases onto the new steps.) */

  /* ---------- Line-heights (multipliers, for fluid text) ---------- */
  --leading-none:    1;
  --leading-tight:   1.15;   /* large display headings */
  --leading-snug:    1.3;    /* sub-headings */
  --leading-normal:  1.55;   /* body — roomy for low vision + i18n */
  --leading-relaxed: 1.7;    /* long-form reading */

  /* ---------- Letter-spacing ---------- */
  --tracking-tighter: -0.025em; /* display — tight, not compressed */
  --tracking-tight:   -0.015em; /* headings */
  --tracking-normal:  0em;
  --tracking-wide:    0.02em;
  --tracking-caps:    0.06em;   /* all-caps eyebrows / overlines */

  /* ---------- Semantic role bundles (font shorthands) ---------- */
  --display-font:   var(--font-display);
  --heading-font:   var(--font-display);
  --body-font:      var(--font-body);
  --label-font:     var(--font-body);
  --code-font:      var(--font-mono);

  /* ---------- Marketing display ----------
     One size above --fs-hero for public-site heroes: fluid from 56px on a
     phone to 96px on a wide desktop (rem ends, so text zoom still counts).
     Not on the generated scale: app UI never needs it. */
  --fs-showcase: clamp(3.5rem, 2.6rem + 3.8vw, 6rem);  /* @kind other */
  --lh-showcase: 1.02;                                 /* @kind other */
  --tracking-showcase: -0.035em;                       /* @kind other */

  /* Paragraph measure for readable long-form */
  --measure: 68ch;  /* @kind other */
}

/* ------------------------------------------------------------------ *
   COMPAT — Tailwind-step type names mapped onto our refined scale.
   The Industry-theme snapshot's components are authored against a
   --text-* / --lh-* idiom (fixed Tailwind steps). We keep our refined
   per-tier modular scale (--type-* / --fs-* in scales.css) as the source
   of truth and alias those names onto it, so ported components resolve
   with OUR sizes — which re-anchor responsively per breakpoint — rather
   than fixed Tailwind px. Adjust the pairings here if a level reads off.
 * ------------------------------------------------------------------ */
:root {
  --text-xs:   var(--type-n2);   /* @kind other */
  --text-sm:   var(--type-n1);   /* @kind other */
  --text-base: var(--type-0);    /* @kind other */
  --text-lg:   var(--type-1);    /* @kind other */
  --text-xl:   var(--type-2);    /* @kind other */
  --text-2xl:  var(--type-3);    /* @kind other */
  --text-3xl:  var(--type-4);    /* @kind other */
  --text-4xl:  var(--type-5);    /* @kind other */
  --text-5xl:  var(--type-6);    /* @kind other */
  --text-6xl:  var(--type-7);    /* @kind other */
  --text-7xl:  var(--type-8);    /* @kind other */
  --text-8xl:  var(--type-8);    /* @kind other */
  --text-9xl:  var(--type-8);    /* @kind other */
  --text-x:    var(--type-0);    /* @kind other */

  --lh-xs:   var(--leading-none);     /* @kind other */
  --lh-sm:   var(--leading-normal);   /* @kind other */
  --lh-base: var(--leading-normal);   /* @kind other */
  --lh-lg:   var(--leading-snug);     /* @kind other */
  --lh-xl:   var(--leading-snug);     /* @kind other */
  --lh-2xl:  var(--leading-tight);    /* @kind other */
  --lh-3xl:  var(--leading-tight);    /* @kind other */
  --lh-4xl:  var(--leading-tight);    /* @kind other */
  --lh-x:    var(--leading-normal);   /* @kind other */
}

/* ============================================================
   INDUSTRY + LABORATORY — Geist typeface family
   ------------------------------------------------------------
   These two instrument themes replace the base families with Geist
   (sans, for both display AND body) and Geist Mono. Only the three
   ROOT family tokens are re-pointed; every role bundle above
   (--heading-font, --body-font, --code-font, …) resolves var() at
   use, so they pick up Geist automatically inside a themed subtree.
   The @font-face faces live in fonts.css. Base themes keep Atkinson
   Hyperlegible / Roboto Flex — this override is scoped, not global.
   ============================================================ */
:is([data-theme="industry"], [data-theme="laboratory"]) {
  --font-display: "Geist", "Roboto Flex", "Inter", ui-sans-serif, system-ui, sans-serif;
  --font-body:    "Geist", "Atkinson Hyperlegible Next", ui-sans-serif, system-ui, sans-serif;
  --font-mono:    "Geist Mono", "Atkinson Hyperlegible Mono", ui-monospace, "SFMono-Regular", monospace;
}

/* ===== tokens/spacing.css ===== */
/* ============================================================
   Prism · Spacing, sizing & radius
   ------------------------------------------------------------
   Spacing is a 4px base grid expressed in rem so it scales with
   user text-zoom. Naming is t-shirt + numeric so both reading
   styles work. Control heights honour a 44px minimum hit-target
   (--size-touch) for accessibility on touch + TV remotes.
   ============================================================ */

:root {
  /* ---------- Spacing scale (4px grid) ---------- */
  --space-0:   0;
  --space-px:  1px;
  --space-0-5: 0.125rem; /* 2 · half-rung for dense insets (segmented/chip/tick gaps) */
  --space-1:   0.25rem;  /* 4  */
  --space-1-5: 0.375rem; /* 6 · half-rung for icon↔text gaps and chip insets */
  --space-2:   0.5rem;   /* 8  */
  --space-3:   0.75rem;  /* 12 */
  --space-4:   1rem;     /* 16 */
  --space-5:   1.25rem;  /* 20 */
  --space-6:   1.5rem;   /* 24 */
  --space-8:   2rem;     /* 32 */
  --space-10:  2.5rem;   /* 40 */
  --space-12:  3rem;     /* 48 */
  --space-16:  4rem;     /* 64 */
  --space-20:  5rem;     /* 80 */
  --space-24:  6rem;     /* 96 */
  --space-32:  8rem;     /* 128 */

  /* ---------- Radius ---------- */
  --radius-none: 0;
  --radius-xs:   3px;
  --radius-sm:   5px;
  --radius-md:   8px;    /* default control / input radius */
  --radius-lg:   12px;   /* cards */
  --radius-xl:   16px;   /* large surfaces, modals */
  --radius-2xl:  24px;
  --radius-pill: 999px;  /* pills, switches, avatars */

  /* ---------- Control heights & hit targets ---------- */
  --size-touch:    44px;  /* WCAG 2.5.5 minimum target */
  --control-sm:    32px;
  --control-md:    40px;  /* default */
  --control-lg:    48px;
  --control-xl:    56px;  /* TV / remote-friendly */

  /* ---------- Icon sizes ---------- */
  --icon-xs: 14px;
  --icon-sm: 16px;
  --icon-md: 20px;  /* default */
  --icon-lg: 24px;
  --icon-xl: 32px;
  /* UI icon stroke. Lucide ships at 2; 1.75 sits with Atkinson's regular weight. */
  --icon-stroke: 1.75; /* @kind other */

  /* ---------- Layout ---------- */
  --container-sm:  640px;
  --container-md:  860px;
  --container-lg:  1100px;
  --container-xl:  1320px;
  --sidebar-width: 264px;
  --topbar-height: 60px;

  /* ---------- Field widths ----------
     Maximum widths for a form field's `width` prop. A field still fills its
     container up to the cap, so on a phone (or in a narrow FormRow column)
     it shrinks with the screen. */
  --field-width-xs: 8rem;   /* a year, a count, an OTP, a PIN */
  --field-width-sm: 12rem;  /* a date, a time, a phone number */
  --field-width-md: 20rem;  /* a name, most selects */
  --field-width-lg: 36rem;  /* a search box, an email, a URL */
  /* A readable single-column form (FormSection measure). */
  --form-measure: 40rem;

  /* ---------- Border widths ---------- */
  --border-width:        1px;
  --border-width-strong: 2px;

  /* ---------- Focus ring geometry ---------- */
  --focus-ring-width:  2px;
  --focus-ring-offset-width: 2px;

  /* ---------- Z-index scale ---------- */
  --z-base:     0;    /* @kind other */
  --z-sticky:   100;  /* @kind other */
  --z-dropdown: 300;  /* @kind other */
  --z-overlay:  400;  /* @kind other */
  --z-modal:    500;  /* @kind other */
  --z-toast:    600;  /* @kind other */
  --z-tooltip:  700;  /* @kind other */
}

/* ===== tokens/scales.css ===== */
/* ============================================================
   Prism · Responsive & density scales   ★ GENERATED — DO NOT EDIT ★
   ------------------------------------------------------------
   Source: tokens/scale.config.json — edit THAT file, then run
   `cd prism-docs && npm run gen` (or ./update-ds.sh --regen).

   TYPE  — one modular scale per size tier. Every size is
           body × ratio^step, rounded to tidy px, floored at 12px:
             mobile  16px body · ratio 1.125
             tablet  17px body · ratio 1.2
             desktop 18px body · ratio 1.2
             cinema  24px body · ratio 1.25
           Roles (--fs-*) bind to steps ONCE; tiers re-anchor the
           steps, so the whole ramp reflows per breakpoint.
           Only caption / small / body-sm may sit below body.

   SPACE — the PROXIMITY LADDER (Gestalt: distance encodes
           relationship). Strictly increasing:
             gap-inline < gap-stack < gap-group < gap-section < gap-page
           Plus insets: layout-gutter, pad-card, pad-surface,
           pad-control-x/y. LAW: a container's padding ≥ the largest
           gap inside it; space BETWEEN groups > space WITHIN groups.

   SIZE TIERS (auto by viewport width; force with data-scale):
     mobile < 640px · tablet ≥ 640px · desktop ≥ 1024px (holds at any wider width)
     cinema — APPLICATION-DRIVEN ONLY: set [data-scale="cinema"|"tv"] (10-foot UIs)

   DENSITY (data-density on <html> or any scope):
     compact · neutral (default) · relaxed
   ============================================================ */

:root {
  /* ---------- TYPE STEPS · mobile (16px · 1.125) ---------- */
  --type-n2: 0.8125rem;           /* 13px */
  --type-n1: 0.875rem;            /* 14px */
  --type-0: 1rem;                 /* 16px */
  --type-1: 1.125rem;             /* 18px */
  --type-2: 1.25rem;              /* 20px */
  --type-3: 1.4375rem;            /* 23px */
  --type-4: 1.625rem;             /* 26px */
  --type-5: 1.75rem;              /* 28px */
  --type-6: 2rem;                 /* 32px */
  --type-7: 2.25rem;              /* 36px */
  --type-8: 2.625rem;             /* 42px */

  /* ---------- FONT ROLES — bound to steps once, reflow per tier ---------- */
  --fs-caption: var(--type-n2);     /* step -2 · 13→15px */
  --fs-small: var(--type-n1);       /* step -1 · 14→19px */
  --fs-body-sm: var(--type-n1);     /* step -1 · 14→19px */
  --fs-body: var(--type-0);         /* step +0 · 16→24px */
  --fs-lead: var(--type-1);         /* step +1 · 18→30px */
  --fs-body-lg: var(--type-1);      /* step +1 · 18→30px */
  --fs-h6: var(--type-1);           /* step +1 · 18→30px */
  --fs-h5: var(--type-2);           /* step +2 · 20→38px */
  --fs-h4: var(--type-3);           /* step +3 · 23→46px */
  --fs-h3: var(--type-4);           /* step +4 · 26→60px */
  --fs-h2: var(--type-5);           /* step +5 · 28→72px */
  --fs-h1: var(--type-6);           /* step +6 · 32→92px */
  --fs-display: var(--type-7);      /* step +7 · 36→116px */
  --fs-hero: var(--type-8);         /* step +8 · 42→144px */

  /* Per-role line-height (multiplier — loosens as size shrinks) */
  --lh-hero: 1.05;
  --lh-display: 1.1;
  --lh-h1: 1.15;
  --lh-h2: 1.2;
  --lh-h3: 1.25;
  --lh-h4: 1.3;
  --lh-h5: 1.35;
  --lh-h6: 1.4;
  --lh-lead: 1.5;
  --lh-body-lg: 1.5;
  --lh-body: 1.55;
  --lh-body-sm: 1.5;
  --lh-small: 1.45;
  --lh-caption: 1.4;

  /* Per-role letter-spacing (tightens as size grows) */
  --ls-hero: -0.03em;
  --ls-display: -0.025em;
  --ls-h1: -0.02em;
  --ls-h2: -0.015em;
  --ls-h3: -0.012em;
  --ls-h4: -0.008em;
  --ls-h5: -0.004em;
  --ls-h6: 0em;
  --ls-lead: 0em;
  --ls-body-lg: 0em;
  --ls-body: 0em;
  --ls-body-sm: 0em;
  --ls-small: 0.005em;
  --ls-caption: 0.01em;

  /* ---------- DEPRECATED --text-* aliases ----------
     Legacy Tailwind-ramp names now resolve to modular steps (and thus
     reflow per tier). Migrate to --fs-* roles; these will be removed. */
  --text-xs: var(--type-n2);
  --text-sm: var(--type-n1);
  --text-base: var(--type-0);
  --text-lg: var(--type-1);
  --text-xl: var(--type-2);
  --text-2xl: var(--type-3);
  --text-3xl: var(--type-4);
  --text-4xl: var(--type-5);
  --text-5xl: var(--type-6);
  --text-6xl: var(--type-7);
  --text-7xl: var(--type-8);
  --text-8xl: var(--type-8);
  --text-9xl: var(--type-8);

  /* ---------- SPACE ROLES · neutral density / mobile ---------- */
  --gap-inline: var(--space-2);         /* 8px — parts of ONE unit — icon+label, buttons in a group */
  --gap-stack: var(--space-3);          /* 12px — lines inside one block — label→input, heading→text */
  --gap-group: var(--space-6);          /* 24px — sibling blocks — field→field, card→card in a grid */
  --gap-section: var(--space-8);        /* 32px — between page sections */
  --gap-page: var(--space-12);          /* 48px — above/below the whole content column */
  --layout-gutter: var(--space-4);      /* 16px — page edge padding */
  --pad-card: var(--space-4);           /* 16px — inside a card */
  --pad-surface: var(--space-5);        /* 20px — inside a modal / drawer / panel */
  --pad-control-x: var(--space-4);      /* 16px — control horizontal padding */
  --pad-control-y: var(--space-2);      /* 8px — control vertical padding */
  --control-height: var(--control-md);  /* 40px */  /* @kind spacing */

  /* ---------- RADIUS ROLES · mobile ---------- */
  --radius-control: var(--radius-sm);   /* 5px */
  --radius-card: var(--radius-md);      /* 8px */
  --radius-surface: var(--radius-lg);   /* 12px */
  --radius-media: var(--radius-md);     /* 8px */

  /* Nested-radius law: inner = outer − inset (floored) so nested
     corners stay concentric. Use for media/wells inside padded boxes. */
  --radius-inset-card: max(var(--radius-xs), calc(var(--radius-card) - var(--pad-card)));       /* @kind radius */
  --radius-inset-surface: max(var(--radius-xs), calc(var(--radius-surface) - var(--pad-surface))); /* @kind radius */

  /* ---------- ELEVATION ROLES — altitude names, shadow + z paired ---------- */
  --elevation-flat: none;  /* @kind other */
  --elevation-raised: var(--shadow-sm);  /* pair with z-index: var(--z-base) */  /* @kind other */
  --elevation-overlay: var(--shadow-md);  /* pair with z-index: var(--z-dropdown) */  /* @kind other */
  --elevation-modal: var(--shadow-xl);  /* pair with z-index: var(--z-modal) */  /* @kind other */
  --elevation-toast: var(--shadow-lg);  /* pair with z-index: var(--z-toast) */  /* @kind other */
}

/* ---------- TABLET ≥ 640px (17px · 1.2) ---------- */
@media (min-width: 640px) {
  :root {
    --type-n2: 0.75rem;           /* 12px */
    --type-n1: 0.875rem;          /* 14px */
    --type-0: 1.0625rem;          /* 17px */
    --type-1: 1.25rem;            /* 20px */
    --type-2: 1.5rem;             /* 24px */
    --type-3: 1.875rem;           /* 30px */
    --type-4: 2.25rem;            /* 36px */
    --type-5: 2.625rem;           /* 42px */
    --type-6: 3.25rem;            /* 52px */
    --type-7: 3.75rem;            /* 60px */
    --type-8: 4.5rem;             /* 72px */

    --gap-inline: var(--space-2);       /* 8px — parts of ONE unit — icon+label, buttons in a group */
    --gap-stack: var(--space-4);        /* 16px — lines inside one block — label→input, heading→text */
    --gap-group: var(--space-6);        /* 24px — sibling blocks — field→field, card→card in a grid */
    --gap-section: var(--space-10);     /* 40px — between page sections */
    --gap-page: var(--space-16);        /* 64px — above/below the whole content column */
    --layout-gutter: var(--space-6);    /* 24px — page edge padding */
    --pad-card: var(--space-5);         /* 20px — inside a card */
    --pad-surface: var(--space-6);      /* 24px — inside a modal / drawer / panel */
    --pad-control-x: var(--space-4);    /* 16px — control horizontal padding */
    --pad-control-y: var(--space-2);    /* 8px — control vertical padding */
    --control-height: var(--control-md);  /* 40px */  /* @kind spacing */

    --radius-control: var(--radius-md); /* 8px */
    --radius-card: var(--radius-lg);    /* 12px */
    --radius-surface: var(--radius-xl); /* 16px */
    --radius-media: var(--radius-lg);   /* 12px */
  }
}

/* ---------- DESKTOP ≥ 1024px (18px · 1.2) ---------- */
@media (min-width: 1024px) {
  :root {
    --type-n2: 0.8125rem;         /* 13px */
    --type-n1: 0.9375rem;         /* 15px */
    --type-0: 1.125rem;           /* 18px */
    --type-1: 1.375rem;           /* 22px */
    --type-2: 1.625rem;           /* 26px */
    --type-3: 2rem;               /* 32px */
    --type-4: 2.375rem;           /* 38px */
    --type-5: 2.75rem;            /* 44px */
    --type-6: 3.25rem;            /* 52px */
    --type-7: 4rem;               /* 64px */
    --type-8: 4.75rem;            /* 76px */

    --gap-inline: var(--space-2);       /* 8px — parts of ONE unit — icon+label, buttons in a group */
    --gap-stack: var(--space-4);        /* 16px — lines inside one block — label→input, heading→text */
    --gap-group: var(--space-6);        /* 24px — sibling blocks — field→field, card→card in a grid */
    --gap-section: var(--space-12);     /* 48px — between page sections */
    --gap-page: var(--space-20);        /* 80px — above/below the whole content column */
    --layout-gutter: var(--space-8);    /* 32px — page edge padding */
    --pad-card: var(--space-6);         /* 24px — inside a card */
    --pad-surface: var(--space-8);      /* 32px — inside a modal / drawer / panel */
    --pad-control-x: var(--space-4);    /* 16px — control horizontal padding */
    --pad-control-y: var(--space-2);    /* 8px — control vertical padding */
    --control-height: var(--control-md);  /* 40px */  /* @kind spacing */

    --radius-control: var(--radius-md); /* 8px */
    --radius-card: var(--radius-lg);    /* 12px */
    --radius-surface: var(--radius-xl); /* 16px */
    --radius-media: var(--radius-lg);   /* 12px */
  }
}

/* ============================================================
   CINEMA TIER (24px · 1.25) — 10-foot UIs (in-room entertainment,
   kiosks). APPLICATION-DRIVEN ONLY: there is no viewport auto-trigger, so a
   wide desktop monitor stays on the desktop scale. Cinema applies solely when
   data-scale="cinema" (alias: data-scale="tv") is set on <html> or any scope.
   ============================================================ */
[data-scale="cinema"], [data-scale="tv"] {
  --type-n2: 0.9375rem;           /* 15px */
  --type-n1: 1.1875rem;           /* 19px */
  --type-0: 1.5rem;               /* 24px */
  --type-1: 1.875rem;             /* 30px */
  --type-2: 2.375rem;             /* 38px */
  --type-3: 2.875rem;             /* 46px */
  --type-4: 3.75rem;              /* 60px */
  --type-5: 4.5rem;               /* 72px */
  --type-6: 5.75rem;              /* 92px */
  --type-7: 7.25rem;              /* 116px */
  --type-8: 9rem;                 /* 144px */

  --gap-inline: var(--space-3);         /* 12px — parts of ONE unit — icon+label, buttons in a group */
  --gap-stack: var(--space-6);          /* 24px — lines inside one block — label→input, heading→text */
  --gap-group: var(--space-10);         /* 40px — sibling blocks — field→field, card→card in a grid */
  --gap-section: var(--space-16);       /* 64px — between page sections */
  --gap-page: var(--space-24);          /* 96px — above/below the whole content column */
  --layout-gutter: var(--space-16);     /* 64px — page edge padding */
  --pad-card: var(--space-10);          /* 40px — inside a card */
  --pad-surface: var(--space-12);       /* 48px — inside a modal / drawer / panel */
  --pad-control-x: var(--space-6);      /* 24px — control horizontal padding */
  --pad-control-y: var(--space-3);      /* 12px — control vertical padding */
  --control-height: var(--control-xl);  /* 56px */  /* @kind spacing */

  --radius-control: var(--radius-lg);   /* 12px */
  --radius-card: var(--radius-xl);      /* 16px */
  --radius-surface: var(--radius-2xl);  /* 24px */
  --radius-media: var(--radius-xl);     /* 16px */

  /* icons scale up with everything else (~1.4×) for distance viewing */
  --icon-xs: 20px;
  --icon-sm: 22px;
  --icon-md: 28px;
  --icon-lg: 34px;
  --icon-xl: 44px;

  /* ---- TV / 10-foot affordances ----
     Overscan-safe insets (TVs crop ~5% of each edge), a thick high-
     contrast focus ring, and the focus-lift transform tokens used by
     focusable cards. Consume via env-free vars so any TV surface can
     pad to the title-safe area and adopt the same focus signature. */
  --tv-safe-x: 5.5%;      /* title-safe horizontal inset */
  --tv-safe-y: 6.5%;      /* title-safe vertical inset (full-bleed overlays) */
  --tv-safe-top: 3.5%;    /* tighter top inset for the pinned top bar */
  --tv-focus-ring:  3px;  /* ring thickness (scales via cqw in apps) */
  --tv-focus-color: oklch(1 0 0 / 0.95);
  --tv-focus-lift:  1.08; /* @kind other */ /* scale applied to the focused card */
  --tv-focus-shadow: 0 1.6cqw 4cqw oklch(0 0 0 / 0.55);
}

/* ============================================================
   DENSITY · RELAXED — more whitespace, low cognitive load
   (applications, onboarding, single-task wizards)
   ============================================================ */
[data-density="relaxed"] {
  --gap-stack: var(--space-4);          /* 16px — lines inside one block — label→input, heading→text */
  --gap-group: var(--space-8);          /* 32px — sibling blocks — field→field, card→card in a grid */
  --gap-section: var(--space-16);       /* 64px — between page sections */
  --gap-page: var(--space-20);          /* 80px — above/below the whole content column */
  --pad-card: var(--space-8);           /* 32px — inside a card */
  --pad-surface: var(--space-10);       /* 40px — inside a modal / drawer / panel */
  --pad-control-x: var(--space-5);      /* 20px — control horizontal padding */
  --pad-control-y: var(--space-3);      /* 12px — control vertical padding */
  --control-height: var(--control-lg);  /* 48px */  /* @kind spacing */
}
@media (min-width: 1024px) {
  [data-density="relaxed"] {
    --gap-section: var(--space-20);     /* 80px — between page sections */
    --gap-page: var(--space-24);        /* 96px — above/below the whole content column */
    --pad-card: var(--space-10);        /* 40px — inside a card */
  }
}

/* ============================================================
   DENSITY · COMPACT — high information density
   (admin resource tables, reports, dashboards)
   ============================================================ */
[data-density="compact"] {
  --gap-inline: var(--space-1);         /* 4px — parts of ONE unit — icon+label, buttons in a group */
  --gap-stack: var(--space-2);          /* 8px — lines inside one block — label→input, heading→text */
  --gap-group: var(--space-4);          /* 16px — sibling blocks — field→field, card→card in a grid */
  --gap-section: var(--space-6);        /* 24px — between page sections */
  --gap-page: var(--space-8);           /* 32px — above/below the whole content column */
  --pad-card: var(--space-3);           /* 12px — inside a card */
  --pad-surface: var(--space-4);        /* 16px — inside a modal / drawer / panel */
  --pad-control-x: var(--space-3);      /* 12px — control horizontal padding */
  --pad-control-y: var(--space-1);      /* 4px — control vertical padding */
  --control-height: var(--control-sm);  /* 32px */  /* @kind spacing */
  --fs-lead: var(--type-0);  /* lead reads as body in dense UIs */
}

/* ===== tokens/elevation.css ===== */
/* ============================================================
   Prism · Elevation, shadow & motion
   ------------------------------------------------------------
   Shadows are soft, cool-tinted and layered (key + ambient).
   They stay subtle in light and lean on borders in dark, where
   shadow is barely visible. Motion is quick and confident with
   no bounce — every transition has a clear focus/hover/active
   target so state changes are obvious. All motion collapses
   under prefers-reduced-motion (see styles base).
   ============================================================ */

:root {
  /* ---------- Shadows (light · warm-tinted) ---------- */
  --shadow-xs: 0 1px 2px oklch(0.22 0.02 60 / 0.06);
  --shadow-sm: 0 1px 2px oklch(0.22 0.02 60 / 0.06),
               0 1px 3px oklch(0.22 0.02 60 / 0.10);
  --shadow-md: 0 2px 4px oklch(0.22 0.02 60 / 0.06),
               0 4px 10px oklch(0.22 0.02 60 / 0.10);
  --shadow-lg: 0 4px 8px oklch(0.22 0.02 60 / 0.06),
               0 12px 24px oklch(0.22 0.02 60 / 0.12);
  --shadow-xl: 0 8px 16px oklch(0.22 0.02 60 / 0.08),
               0 24px 48px oklch(0.22 0.02 60 / 0.16);

  /* Inner shadow for pressed / inset wells */
  --shadow-inset: inset 0 1px 2px oklch(0.22 0.02 60 / 0.10);

  /* ---------- Tactile / subtle-3D system (not skeuomorphic) ----------
     A light sheen + beveled edges make raised controls feel physical;
     a recessed "well" makes inputs/tracks feel inset; "press" gives a
     pushed-in active state. Kept deliberately subtle. */
  --sheen:      linear-gradient(oklch(1 0 0 / 0.16), oklch(1 0 0 / 0) 55%);             /* @kind other */
  --bevel:      inset 0 1px 0 oklch(1 0 0 / 0.28), inset 0 -1.5px 0 oklch(0 0 0 / 0.14); /* @kind other */
  --bevel-soft: inset 0 1px 0 oklch(1 0 0 / 0.55);                                       /* @kind other */
  --well:       inset 0 1.5px 2px oklch(0 0 0 / 0.11), inset 0 0 0 9999px oklch(0 0 0 / 0); /* @kind other */
  --press:      inset 0 2px 4px oklch(0 0 0 / 0.22);                                     /* @kind other */

  /* ---------- Material contract · base no-ops ----------
     The Industry theme materialises the library by REDEFINING these token
     values, not by adding a rule per component. For that to work, every
     material token must also exist here, so a component's own base CSS can
     safely name it: `box-shadow: var(--bevel), var(--shadow-contact)` is
     inert in the base themes and machined under Industry, with no entry in
     components/themes/industry.css.

     This matters more than it looks. A var() that resolves to nothing is
     the *guaranteed-invalid value*, which invalidates the WHOLE declaration
     — so one Industry-only token in a comma-separated box-shadow silently
     deletes the working shadows beside it. Declaring the no-ops here is
     what makes the material contract safe to use everywhere.

     Adding a material token to the Industry theme? Add its base value here
     in the same commit. See docs/INDUSTRY_THEME.md §4. */
  --grain: none;             /* @kind other */
  --grain-size: auto;        /* @kind other */
  --skeuo-card: none;        /* @kind other */
  --skeuo-raised: none;      /* @kind other */
  --skeuo-raised-soft: none; /* @kind other */
  --skeuo-well-grad: none;   /* @kind other */
  --skeuo-accent: none;      /* @kind other */
  /* A large single-character cell needs a deeper well than a text input: at
     52×64 the standard --well reads as a hairline. Base themes keep them the
     same; Industry deepens it. */
  --well-deep: var(--well);                              /* @kind shadow */
  --shadow-contact: var(--shadow-xs);                    /* @kind shadow */
  --edge-light: inset 0 1px 0 oklch(1 0 0 / 0.40);       /* @kind shadow */

  /* Emissive layer. In the base themes "lit" is simply the accent — state
     reads through colour and an icon, exactly as it does under Industry;
     Industry adds the glow on top.

     Glow/halo no-ops are `0 0 0 transparent`, NOT `none`: `none` is only
     legal as the SOLE value of box-shadow, so `var(--well), var(--led-glow)`
     would be an invalid declaration — and an invalid declaration is dropped
     whole, taking the well with it. A zero-size transparent shadow composes
     in a list and paints nothing. */
  --led:          var(--accent);   /* @kind color */
  --led-dim:      var(--border-strong); /* @kind color */
  --led-positive: var(--positive); /* @kind color */
  --led-notice:   var(--notice);   /* @kind color */
  --led-negative: var(--negative); /* @kind color */
  /* Line-art stroke colours from base neutrals, so instrument controls whose
     STRUCTURE is drawn in line-art render unthemed too (RulerPicker's tick
     gradient was invisible without these). Industry/Laboratory override with
     their tuned strokes. */
  --lineart-stroke:       var(--text-secondary); /* @kind color */
  --lineart-stroke-quiet: var(--border-strong);  /* @kind color */
  --led-glow:  0 0 0 transparent;          /* @kind other */
  --led-glow-soft:  0 0 0 transparent;     /* @kind other */
  --led-glow-strong:  0 0 0 transparent;   /* @kind other */
  --led-glow-positive:  0 0 0 transparent; /* @kind other */
  --led-glow-notice:  0 0 0 transparent;   /* @kind other */
  --led-glow-negative:  0 0 0 transparent; /* @kind other */
  --led-text-glow: 0 0 0 transparent; /* drop-shadow() needs a length @kind other */
  --halo-accent:  0 0 0 transparent;       /* @kind other */
  --halo-positive:  0 0 0 transparent;     /* @kind other */
  --halo-notice:  0 0 0 transparent;       /* @kind other */
  --halo-negative:  0 0 0 transparent;     /* @kind other */
  --shadow-tint: var(--shadow-sm);          /* @kind shadow */
  --shadow-tint-accent: var(--shadow-sm);   /* @kind shadow */
  --shadow-tint-positive: var(--shadow-sm); /* @kind shadow */
  --shadow-tint-notice: var(--shadow-sm);   /* @kind shadow */
  --shadow-tint-negative: var(--shadow-sm); /* @kind shadow */
  /* A filled track is flat colour in the base themes; Industry brightens it. */
  /* One ramp token serves a horizontal track and a vertical fader: components
     override --ramp-angle locally (0deg = bottom→top for a fader, 270deg under
     dir="rtl"). Declared here so the default is documented in one place. */
  --ramp-angle: 90deg; /* @kind other */
  --value-ramp: linear-gradient(var(--ramp-angle, 90deg), var(--accent), var(--accent)); /* @kind color */

  /* ---------- Motion · durations ---------- */
  --duration-instant: 80ms;   /* @kind other */
  --duration-fast:    140ms;  /* @kind other */
  --duration-normal:  220ms;  /* @kind other */
  --duration-slow:    340ms;  /* @kind other */

  /* ---------- Motion · easings ---------- */
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);     /* @kind other */
  --ease-emphasized: cubic-bezier(0.3, 0, 0, 1);   /* @kind other */
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);         /* @kind other */
  --ease-out: cubic-bezier(0, 0, 0.2, 1);          /* @kind other */
  /* A physical part travelling to a new position and coming to rest: a long
     decelerating tail, no overshoot. Used when a click or a key moves a thumb,
     cap or pointer — never while a pointer is dragging it. */
  --duration-settle: 260ms;                        /* @kind other */
  --ease-settle: cubic-bezier(0.2, 0.7, 0.2, 1);   /* @kind other */

  /* Reusable transitions */
  --transition-colors: color var(--duration-fast) var(--ease-standard),
                       background-color var(--duration-fast) var(--ease-standard),
                       border-color var(--duration-fast) var(--ease-standard),
                       box-shadow var(--duration-fast) var(--ease-standard); /* @kind other */
  --transition-transform: transform var(--duration-fast) var(--ease-standard); /* @kind other */
}

/* The value ramp is a physical gradient, so it has to turn with the writing
   mode — once, here, rather than per component. A vertical fader sets 0deg
   locally and is unaffected. */
[dir="rtl"] {
  --ramp-angle: 270deg; /* @kind other */
}

[data-theme="dark"],
[data-theme="industry"] {
  --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.5);
  --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.5);
  --shadow-md: 0 4px 10px oklch(0 0 0 / 0.55);
  --shadow-lg: 0 12px 24px oklch(0 0 0 / 0.6);
  --shadow-xl: 0 24px 48px oklch(0 0 0 / 0.66);
  --shadow-inset: inset 0 1px 2px oklch(0 0 0 / 0.5);
}

/* >>> GENERATED · data-theme="system" dark half — do not edit; source is the block above. Run `cd prism-docs && npm run gen`. >>> */
@media (prefers-color-scheme: dark) {
  [data-theme="system"] {
    --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.5);
    --shadow-sm: 0 1px 3px oklch(0 0 0 / 0.5);
    --shadow-md: 0 4px 10px oklch(0 0 0 / 0.55);
    --shadow-lg: 0 12px 24px oklch(0 0 0 / 0.6);
    --shadow-xl: 0 24px 48px oklch(0 0 0 / 0.66);
    --shadow-inset: inset 0 1px 2px oklch(0 0 0 / 0.5);
  }
}
/* <<< GENERATED · data-theme="system" <<< */

/* >>> GENERATED · print uses the light theme — do not edit; source is the light block. Run `cd prism-docs && npm run gen`. >>> */
@media print {
  [data-theme="dark"],
  [data-theme="system"],
  [data-theme="industry"] {
    /* ---------- Shadows (light · warm-tinted) ---------- */
    --shadow-xs: 0 1px 2px oklch(0.22 0.02 60 / 0.06);
    --shadow-sm: 0 1px 2px oklch(0.22 0.02 60 / 0.06),
                 0 1px 3px oklch(0.22 0.02 60 / 0.10);
    --shadow-md: 0 2px 4px oklch(0.22 0.02 60 / 0.06),
                 0 4px 10px oklch(0.22 0.02 60 / 0.10);
    --shadow-lg: 0 4px 8px oklch(0.22 0.02 60 / 0.06),
                 0 12px 24px oklch(0.22 0.02 60 / 0.12);
    --shadow-xl: 0 8px 16px oklch(0.22 0.02 60 / 0.08),
                 0 24px 48px oklch(0.22 0.02 60 / 0.16);

    /* Inner shadow for pressed / inset wells */
    --shadow-inset: inset 0 1px 2px oklch(0.22 0.02 60 / 0.10);

    /* ---------- Tactile / subtle-3D system (not skeuomorphic) ----------
       A light sheen + beveled edges make raised controls feel physical;
       a recessed "well" makes inputs/tracks feel inset; "press" gives a
       pushed-in active state. Kept deliberately subtle. */
    --sheen:      linear-gradient(oklch(1 0 0 / 0.16), oklch(1 0 0 / 0) 55%);             /* @kind other */
    --bevel:      inset 0 1px 0 oklch(1 0 0 / 0.28), inset 0 -1.5px 0 oklch(0 0 0 / 0.14); /* @kind other */
    --bevel-soft: inset 0 1px 0 oklch(1 0 0 / 0.55);                                       /* @kind other */
    --well:       inset 0 1.5px 2px oklch(0 0 0 / 0.11), inset 0 0 0 9999px oklch(0 0 0 / 0); /* @kind other */
    --press:      inset 0 2px 4px oklch(0 0 0 / 0.22);                                     /* @kind other */

    /* ---------- Material contract · base no-ops ----------
       The Industry theme materialises the library by REDEFINING these token
       values, not by adding a rule per component. For that to work, every
       material token must also exist here, so a component's own base CSS can
       safely name it: `box-shadow: var(--bevel), var(--shadow-contact)` is
       inert in the base themes and machined under Industry, with no entry in
       components/themes/industry.css.

       This matters more than it looks. A var() that resolves to nothing is
       the *guaranteed-invalid value*, which invalidates the WHOLE declaration
       — so one Industry-only token in a comma-separated box-shadow silently
       deletes the working shadows beside it. Declaring the no-ops here is
       what makes the material contract safe to use everywhere.

       Adding a material token to the Industry theme? Add its base value here
       in the same commit. See docs/INDUSTRY_THEME.md §4. */
    --grain: none;             /* @kind other */
    --grain-size: auto;        /* @kind other */
    --skeuo-card: none;        /* @kind other */
    --skeuo-raised: none;      /* @kind other */
    --skeuo-raised-soft: none; /* @kind other */
    --skeuo-well-grad: none;   /* @kind other */
    --skeuo-accent: none;      /* @kind other */
    /* A large single-character cell needs a deeper well than a text input: at
       52×64 the standard --well reads as a hairline. Base themes keep them the
       same; Industry deepens it. */
    --well-deep: var(--well);                              /* @kind shadow */
    --shadow-contact: var(--shadow-xs);                    /* @kind shadow */
    --edge-light: inset 0 1px 0 oklch(1 0 0 / 0.40);       /* @kind shadow */

    /* Emissive layer. In the base themes "lit" is simply the accent — state
       reads through colour and an icon, exactly as it does under Industry;
       Industry adds the glow on top.

       Glow/halo no-ops are `0 0 0 transparent`, NOT `none`: `none` is only
       legal as the SOLE value of box-shadow, so `var(--well), var(--led-glow)`
       would be an invalid declaration — and an invalid declaration is dropped
       whole, taking the well with it. A zero-size transparent shadow composes
       in a list and paints nothing. */
    --led:          var(--accent);   /* @kind color */
    --led-dim:      var(--border-strong); /* @kind color */
    --led-positive: var(--positive); /* @kind color */
    --led-notice:   var(--notice);   /* @kind color */
    --led-negative: var(--negative); /* @kind color */
    /* Line-art stroke colours from base neutrals, so instrument controls whose
       STRUCTURE is drawn in line-art render unthemed too (RulerPicker's tick
       gradient was invisible without these). Industry/Laboratory override with
       their tuned strokes. */
    --lineart-stroke:       var(--text-secondary); /* @kind color */
    --lineart-stroke-quiet: var(--border-strong);  /* @kind color */
    --led-glow:  0 0 0 transparent;          /* @kind other */
    --led-glow-soft:  0 0 0 transparent;     /* @kind other */
    --led-glow-strong:  0 0 0 transparent;   /* @kind other */
    --led-glow-positive:  0 0 0 transparent; /* @kind other */
    --led-glow-notice:  0 0 0 transparent;   /* @kind other */
    --led-glow-negative:  0 0 0 transparent; /* @kind other */
    --led-text-glow: 0 0 0 transparent; /* drop-shadow() needs a length @kind other */
    --halo-accent:  0 0 0 transparent;       /* @kind other */
    --halo-positive:  0 0 0 transparent;     /* @kind other */
    --halo-notice:  0 0 0 transparent;       /* @kind other */
    --halo-negative:  0 0 0 transparent;     /* @kind other */
    --shadow-tint: var(--shadow-sm);          /* @kind shadow */
    --shadow-tint-accent: var(--shadow-sm);   /* @kind shadow */
    --shadow-tint-positive: var(--shadow-sm); /* @kind shadow */
    --shadow-tint-notice: var(--shadow-sm);   /* @kind shadow */
    --shadow-tint-negative: var(--shadow-sm); /* @kind shadow */
    /* A filled track is flat colour in the base themes; Industry brightens it. */
    /* One ramp token serves a horizontal track and a vertical fader: components
       override --ramp-angle locally (0deg = bottom→top for a fader, 270deg under
       dir="rtl"). Declared here so the default is documented in one place. */
    --ramp-angle: 90deg; /* @kind other */
    --value-ramp: linear-gradient(var(--ramp-angle, 90deg), var(--accent), var(--accent)); /* @kind color */

    /* ---------- Motion · durations ---------- */
    --duration-instant: 80ms;   /* @kind other */
    --duration-fast:    140ms;  /* @kind other */
    --duration-normal:  220ms;  /* @kind other */
    --duration-slow:    340ms;  /* @kind other */

    /* ---------- Motion · easings ---------- */
    --ease-standard: cubic-bezier(0.2, 0, 0, 1);     /* @kind other */
    --ease-emphasized: cubic-bezier(0.3, 0, 0, 1);   /* @kind other */
    --ease-exit: cubic-bezier(0.4, 0, 1, 1);         /* @kind other */
    --ease-out: cubic-bezier(0, 0, 0.2, 1);          /* @kind other */
    /* A physical part travelling to a new position and coming to rest: a long
       decelerating tail, no overshoot. Used when a click or a key moves a thumb,
       cap or pointer — never while a pointer is dragging it. */
    --duration-settle: 260ms;                        /* @kind other */
    --ease-settle: cubic-bezier(0.2, 0.7, 0.2, 1);   /* @kind other */

    /* Reusable transitions */
    --transition-colors: color var(--duration-fast) var(--ease-standard),
                         background-color var(--duration-fast) var(--ease-standard),
                         border-color var(--duration-fast) var(--ease-standard),
                         box-shadow var(--duration-fast) var(--ease-standard); /* @kind other */
    --transition-transform: transform var(--duration-fast) var(--ease-standard); /* @kind other */
  }
}
/* <<< GENERATED · print <<< */

/* ===== tokens/theme-industry.css ===== */
/* ============================================================
   Prism · INDUSTRY theme — tokens (the anthracite instrument face)
   ------------------------------------------------------------
   A dark-only theme for hardware-adjacent software: appliance and
   machine HMIs, vehicle dashboards, industrial control panels, pro
   AV, studio and lab tooling — anything that should feel like a
   well-made physical instrument rather than a web page.

     <html data-theme="industry">

   The reference is a contemporary hardware product, not a skin:
   a matte soft-touch anthracite body, keys that sit a step lighter
   than the body they are seated in, one blue-cyan for action and
   state, and indicators that read as small real LEDs.

   THE BRIEF (docs/MATERIAL_SPEC.md)
   • Real surfaces under ONE soft light. Edge lights are blurred
     1.5px ramps, never 1px lines; faces take a soft top light;
     casts are large and diffuse.
   • Depth is spent on what a hand touches. Keys, knobs, caps and
     thumbs get the full material (edge, side wall, contact
     occlusion, soft cast, press travel). Bodies — cards, panels,
     tables — are a quiet tier so the keys have something to stand
     on.
   • Emission is a filament: a domed LED core with a 1px collar and
     a 4–6px soft edge. No blooms, no halos.
   • Travel is shown by motion: a pressed key moves 1.5px and its
     wall collapses.
   • No grain, no painted gradients, no gloss, no uppercase legends.

   INHERITANCE
   Industry extends the dark semantic layer: tokens/colors.css and
   tokens/elevation.css both match [data-theme="industry"] in their
   dark blocks, and this file (imported after them) re-points what
   makes Industry itself. Industry OWNS the accent — product
   signatures inside it resolve to the Industry blue, because a
   machine has one indicator colour, not six.

   The SHARED INSTRUMENT BLOCK at the bottom of this file (keyed to
   both instrument faces) turns the tactile kit into the material
   contract every component already consumes (--bevel, --well,
   --press, --led-glow…), so Laboratory only has to supply values.
   ============================================================ */

[data-theme="industry"] {
  color-scheme: dark;

  /* ---------- Surfaces · anthracite soft-touch, near-neutral ----------
     Deep grey, never black, so soft shadows and lifted keys are visible.
     Keys (--surface-raised) sit LIGHTER than the body they are seated in —
     elevation is lightness first, shadow second. Chroma is a whisper. */
  --surface-page:    oklch(0.215 0.004 250);
  --surface-sunken:  oklch(0.190 0.004 250);
  --surface-card:    oklch(0.260 0.004 250);
  --surface-raised:  oklch(0.330 0.005 250);
  --surface-overlay: oklch(0.370 0.005 250);
  --surface-inverse: oklch(0.955 0.003 250);
  --surface-scrim:   oklch(0.10 0.010 250 / 0.74);
  --surface-stripe:  oklch(0.98 0.005 250 / 0.025);

  --fill-subtle:       oklch(0.98 0.005 250 / 0.045);
  --fill-subtle-hover: oklch(0.98 0.005 250 / 0.080);
  --fill-muted:        oklch(0.98 0.005 250 / 0.130);

  /* ---------- Text · cool neutral, never pure white ---------- */
  --text-primary:    oklch(0.962 0.002 250);
  --text-secondary:  oklch(0.792 0.004 250);
  /* tertiary is solved against the LIGHTEST surface it can sit on, not the
     page — see the AA note in git history for the measured ratios. */
  --text-tertiary:   oklch(0.745 0.005 250);
  --text-placeholder: oklch(0.605 0.005 250);
  --text-disabled:   oklch(0.472 0.005 250);
  --text-on-inverse: oklch(0.225 0.006 250);

  /* ---------- Borders · hairline seams ---------- */
  --border-subtle:  oklch(1 0 0 / 0.06);
  --border-default: oklch(1 0 0 / 0.11);
  --border-strong:  oklch(1 0 0 / 0.20);
  --border-inverse: oklch(0.70 0.005 250);

  /* ---------- Accent · one hue knob ----------
     THE PRIMARY COLOUR IS ONE NUMBER. Set --accent-hue on any scope
     — :root, a tenant wrapper, a single panel — and all fifteen
     derived roles follow:

       [data-theme="industry"] { --accent-hue: 295; }   <- violet

     Hue is the ONLY knob, and the reason is measured, not assumed.
     Fixing oklch L does NOT fix contrast: L is perceptual lightness,
     WCAG measures sRGB luminance, and at chroma 0.185 the two diverge
     by hue. White-on-fill at a fixed L 0.505 swings 4.68 (cyan-green
     190°) to 6.55 (blue-violet 265°) — a 1.4x spread.

     So --accent-l is pinned at the value where the WORST hue still
     clears AA, not where the default blue happens to look nice. The
     ceiling is L 0.515 (4.50 at 190°); 0.505 is the default because it
     keeps a little margin. Raise --accent-l and you silently break
     white ink at cyan and green. Verified across all 360 degrees by
     tokens/accent-hue.card.html, which measures rendered pixels.

     This is also why --accent-hover goes DOWN, not up. A lighter fill
     at L 0.578 measures 3.52 at 190° — a fail at every hue past cyan.
     Hover seats the key deeper; the visible hover is the key catching
     a little more light (see the shared block).

     --accent-chroma is the second knob, for a muted or greyscale brand
     (drop it to ~0.02). Every ratio holds because L is untouched.

     Two roles, the way real hardware works: --accent is the deep FILL
     a key is made of, --led is the bright emissive colour an
     indicator EMITS. Never use --led as a fill behind text.

     Semantics do NOT follow the knob. --positive stays green 152 and
     --notice stays amber 82, because "this succeeded" must not change
     meaning when a tenant rebrands. Pick an accent hue at least ~40°
     off both, or a green primary makes "confirm" and "success" the
     same colour. */
  --accent-hue:          240;   /* @kind other */
  --accent-chroma:       0.160; /* @kind other */
  /* AA ceiling is 0.515 — see the note above before raising this. */
  --accent-l:            0.505; /* @kind other */
  --industry-accent:     oklch(var(--accent-l) var(--accent-chroma) var(--accent-hue)); /* @kind color */
  --accent:              var(--industry-accent);
  --accent-hover:        oklch(calc(var(--accent-l) - 0.037) calc(var(--accent-chroma) * 1.05) var(--accent-hue));
  --accent-active:       oklch(calc(var(--accent-l) - 0.077) calc(var(--accent-chroma) * 0.94) var(--accent-hue));
  --accent-text:         oklch(0.795 calc(var(--accent-chroma) * 0.70) calc(var(--accent-hue) - 5));
  --accent-on:           oklch(1 0 0);
  --accent-subtle:       oklch(0.60 calc(var(--accent-chroma) * 1.03) calc(var(--accent-hue) - 2) / 0.16);
  --accent-subtle-hover: oklch(0.60 calc(var(--accent-chroma) * 1.03) calc(var(--accent-hue) - 2) / 0.24);
  --accent-border:       oklch(0.72 calc(var(--accent-chroma) * 0.81) calc(var(--accent-hue) - 4) / 0.38);
  --focus-ring:          oklch(0.735 calc(var(--accent-chroma) * 0.89) calc(var(--accent-hue) - 6));
  --focus-ring-offset:   oklch(0.16 0.005 250);
  --text-link:           var(--accent-text);
  --text-link-hover:     oklch(0.845 calc(var(--accent-chroma) * 0.54) calc(var(--accent-hue) - 5));

  /* Industry owns the accent — a signature set inside it still
     resolves to Industry blue. One machine, one indicator hue. */
  --sig: var(--accent);
  --signature-hue: var(--accent);
  /* The machine body carries a whisper of the accent hue and nothing
     more — panels are soft-touch polymer, not brand colour. */
  --signature-gradient: linear-gradient(150deg,
    oklch(0.29 0.028 var(--accent-hue)) 0%,
    oklch(0.235 0.008 250) 55%,
    oklch(0.215 0.005 250) 100%); /* @kind color */
  --intent-brand:        var(--accent);
  --intent-brand-text:   var(--accent-text);
  --intent-brand-on:     var(--accent-on);
  --intent-brand-subtle: var(--accent-subtle);
  --intent-brand-border: var(--accent-border);
  --chart-1: var(--led);

  /* ---------- LED colours · what an indicator EMITS ----------
     Tone variants exist so status still reads without colour alone
     (components pair them with an icon or label). The glow recipes are
     in the shared block: a dome, a 1px collar, a tight soft edge. */
  --led:          oklch(0.740 calc(var(--accent-chroma) * 0.88) calc(var(--accent-hue) - 4)); /* @kind color */
  --led-dim:      oklch(0.420 calc(var(--accent-chroma) * 0.20) var(--accent-hue));           /* @kind color */
  --led-positive: oklch(0.780 0.185 152);  /* @kind color */
  --led-notice:   oklch(0.830 0.165 82);   /* @kind color */
  --led-negative: oklch(0.680 0.215 26);   /* @kind color */

  /* ---------- Shadows · soft, deep, diffuse ----------
     Large blur, moderate alpha — a body resting under one soft light in a
     dim room, not a hard drop shadow. */
  --shadow-xs: 0 1px 2px oklch(0 0 0 / 0.35);
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.30), 0 4px 12px oklch(0 0 0 / 0.26);
  --shadow-md: 0 2px 6px oklch(0 0 0 / 0.32), 0 12px 32px oklch(0 0 0 / 0.34);
  --shadow-lg: 0 4px 12px oklch(0 0 0 / 0.34), 0 24px 56px oklch(0 0 0 / 0.40);
  --shadow-xl: 0 8px 24px oklch(0 0 0 / 0.38), 0 40px 90px oklch(0 0 0 / 0.46);

  /* ---------- Tactile kit · the dark face's values ----------
     Eleven values feed every recipe in the shared block. Tune these
     before touching any recipe. */
  --t-hi:      oklch(1 0 0 / 0.16);         /* soft top edge light            @kind color */
  --t-hi-soft: oklch(1 0 0 / 0.09);         /* the same, restrained           @kind color */
  --t-lo:      oklch(0 0 0 / 0.30);         /* soft lower inner shade         @kind color */
  --t-wall:    oklch(0.215 0.004 250);      /* side wall, first step          @kind color */
  --t-wall-2:  oklch(0.165 0.004 250);      /* side wall, second step         @kind color */
  --t-ao:      oklch(0 0 0 / 0.45);         /* contact / ambient occlusion    @kind color */
  --t-cast:    oklch(0 0 0 / 0.50);         /* soft cast                      @kind color */
  --t-seam:    oklch(1 0 0 / 0.05);         /* hairline seam around a body    @kind color */
  --t-key:     var(--surface-raised);       /* key face                       @kind color */
  --t-key-face:  linear-gradient(180deg, var(--t-hi-soft), transparent 48%, var(--t-lo));                       /* @kind other */
  --t-body-face: linear-gradient(180deg, oklch(1 0 0 / 0.03), transparent 42%);                                  /* @kind other */
  --t-well-fill: var(--surface-sunken);                                                                           /* @kind color */
  --t-well-face: linear-gradient(180deg, oklch(0 0 0 / 0.22), transparent 45%);                                  /* @kind other */
  --t-well-face-soft: linear-gradient(180deg, oklch(0 0 0 / 0.14), transparent 38%);                             /* @kind other */
  --t-hover: 1.08; /* brightness() a key takes on hover — the key catches more light @kind other */

  /* ---------- Series · unlit marks are recessed, not pale ---------- */
  --series-track: oklch(0.185 0.004 250); /* @kind color */
  --series-gap:   oklch(0.130 0.008 250); /* the slot between ring segments @kind color */

  /* ---------- Glass ----------
     Modals and menus are frosted panels over the live screen, the way a
     device overlay dims and blurs the UI behind it rather than hiding it. */
  --surface-glass: oklch(0.29 0.005 250 / 0.74); /* @kind color */
  --glass-blur: 28px;   /* @kind other */
  --scrim-blur: 6px;    /* @kind other */

  /* ---------- Data series · one hue family per chart ----------
     A chart is not a bag of unrelated colours. It picks ONE hue family
     and steps within it, so the whole graphic reads as a single matte
     material and never as children's building blocks.

     Six steps per family, spaced by measured sRGB LUMINANCE in even
     28/255 increments (210 → 70) — the quantity greyscale conversion
     actually reports. Desaturate any chart and its series stay ordered
     and distinct. Do NOT respace by oklch L: at high chroma the two
     diverge badly (two colours 0.07 L apart can be the same grey).
     To retune, render each step and measure 0.2126R + 0.7152G + 0.0722B,
     requiring every PAIR to differ by ≥ 20.

     Default family is AZURE: the chart belongs to the panel, and the
     panel is blue. Switch per chart, card or page with
     data-series="violet|magenta|cyan|green|amber|orange". */
  --series-1: oklch(0.881 0.115 270); /* luma 210 @kind color */
  --series-2: oklch(0.813 0.180 261); /* luma 182 @kind color */
  --series-3: oklch(0.766 0.225 253); /* luma 154 @kind color */
  --series-4: oklch(0.660 0.250 244); /* luma 126 @kind color */
  --series-5: oklch(0.523 0.235 235); /* luma 97  @kind color */
  --series-6: oklch(0.401 0.205 227); /* luma 71  @kind color */
  /* Muted marks are the body colour, a shade up — never a pale tint of the
     series hue (a faded colour still reads as a category). */
  --series-muted:      oklch(0.335 0.005 250); /* @kind color */
  --series-muted-deep: oklch(0.280 0.005 250); /* @kind color */

  /* the shipped charts follow the active family */
  --chart-1: var(--series-1);
  --chart-2: var(--series-2);
  --chart-3: var(--series-3);
  --chart-4: var(--series-4);
  --chart-5: var(--series-5);
  --chart-6: var(--series-6);
  /* Beyond six series the family has no more rungs, so the run CYCLES rather
     than borrowing a foreign hue. Repeating a rung is the honest failure: it
     tells you to change chart type. */
  --chart-7:  var(--series-1);
  --chart-8:  var(--series-2);
  --chart-9:  var(--series-3);
  --chart-10: var(--series-4);
  --chart-11: var(--series-5);
  --chart-12: var(--series-6);
  --chart-13: var(--series-1);
  --chart-14: var(--series-2);

  /* Intensity ramps run light→saturated for a light canvas, so on the dark
     instrument canvas their low end glows near-white. Re-anchor them
     DARK→BRIGHT: low magnitude recedes into the panel, high magnitude lifts. */
  --chart-seq-1: oklch(0.315 0.045 264); /* @kind color */
  --chart-seq-2: oklch(0.420 0.115 264); /* @kind color */
  --chart-seq-3: oklch(0.545 0.195 264); /* @kind color */
  --chart-seq-4: oklch(0.665 0.255 264); /* @kind color */
  --chart-seq-5: oklch(0.795 0.180 264); /* @kind color */
  --chart-seq2-1: oklch(0.320 0.050 195); /* @kind color */
  --chart-seq2-2: oklch(0.440 0.110 215); /* @kind color */
  --chart-seq2-3: oklch(0.560 0.160 250); /* @kind color */
  --chart-seq2-4: oklch(0.670 0.210 275); /* @kind color */
  --chart-seq2-5: oklch(0.790 0.170 290); /* @kind color */
  --chart-div-1: oklch(0.660 0.230 25);  /* strong low (red)   @kind color */
  --chart-div-2: oklch(0.500 0.140 40);  /* light low          @kind color */
  --chart-div-3: oklch(0.315 0.008 250); /* dark neutral centre @kind color */
  --chart-div-4: oklch(0.520 0.130 245); /* light high         @kind color */
  --chart-div-5: oklch(0.680 0.190 250); /* strong high (blue) @kind color */

  /* ---------- Technical line art ----------
     Illustrations are minimalist but BOLD: thin monochrome outlines of the
     real hardware, drawn in ISOMETRIC so a solid reads as a solid from its
     silhouette alone. One stroke weight per drawing, round joins, no fills,
     no shading, no hatching. The only colour is a single callout. */
  --lineart-stroke: oklch(0.86 0.004 250 / 0.82); /* @kind color */
  --lineart-stroke-quiet: oklch(0.86 0.004 250 / 0.38); /* @kind color */
  --lineart-width: 1.5px;      /* @kind spacing */
  --lineart-width-lg: 2px;     /* @kind spacing */
  --lineart-width-bold: 3px;   /* @kind spacing */
  --lineart-width-hairline: 1px; /* @kind spacing */
  --lineart-callout: var(--led); /* @kind color */
}


/* ============================================================
   SHARED INSTRUMENT BLOCK · both faces
   ------------------------------------------------------------
   Industry and Laboratory are one material system with two value
   sets. This block reads each face's tactile kit (--t-*) and turns
   it into (1) the recipes the shared structural layer in
   components/themes/industry.css names, and (2) the material
   contract every component already consumes (--bevel, --well,
   --press, --led-glow, --shadow-contact…), so a component that only
   names the contract re-materialises in both faces with no edits.

   Every contract token has a base no-op in tokens/elevation.css, so
   naming one in a component's own sheet is inert in the base themes.
   ============================================================ */
:is([data-theme="industry"], [data-theme="laboratory"]) {
  /* ---------- Recipes ---------- */
  /* Soft-edge bevel: blurred insets, never a hard 1px line. */
  --t-edge:      inset 0 1.5px 1.5px var(--t-hi), inset 0 -1.5px 2px var(--t-lo); /* @kind shadow */
  --t-edge-soft: inset 0 1px 1px var(--t-hi-soft);                                /* @kind shadow */
  /* T2 key: edge + two-step side wall + contact occlusion + soft cast. */
  --t-key-shadow: var(--t-edge),
    0 1px 0 var(--t-wall), 0 2px 0 var(--t-wall-2),
    0 3px 2px -1px var(--t-ao), 0 10px 18px -10px var(--t-cast); /* @kind shadow */
  /* Pressed: the key travels 1.5px, the wall collapses, the cast shortens. */
  --t-key-shadow-down: inset 0 1px 1px var(--t-hi-soft), inset 0 -1px 1px var(--t-lo),
    0 0.5px 0 var(--t-wall), 0 1px 1px -0.5px var(--t-ao), 0 3px 6px -4px var(--t-cast); /* @kind shadow */
  /* Small key (thumb, cap, selected segment): one-step wall. */
  --t-key-shadow-sm: var(--t-edge), 0 1px 0 var(--t-wall), 0 2px 2px -1px var(--t-ao), 0 6px 10px -6px var(--t-cast); /* @kind shadow */
  /* Wells: inner occlusion, a lit lower lip, a hairline of light on the rim. */
  --t-well:      inset 0 2px 3px var(--t-ao), inset 0 1px 0 var(--t-lo), inset 0 -1px 0 var(--t-hi-soft), 0 1px 0 var(--t-hi-soft); /* @kind shadow */
  --t-well-deep: inset 0 3px 6px var(--t-ao), inset 0 1px 1px var(--t-lo), inset 0 -1px 0 var(--t-hi-soft), 0 1px 0 var(--t-hi-soft); /* @kind shadow */
  --t-well-soft: inset 0 1.5px 2px var(--t-ao), inset 0 -1px 0 var(--t-hi-soft), 0 1px 0 var(--t-hi-soft); /* @kind shadow */
  /* LED: dome (top light, bottom shade) + 1px collar + tight soft edge. */
  --t-led-glow:      inset 0 1px 0 oklch(1 0 0 / 0.55), inset 0 -1px 1px oklch(0 0 0 / 0.18),
                     0 0 0 1px color-mix(in oklch, var(--led) 22%, transparent), 0 0 6px color-mix(in oklch, var(--led) 60%, transparent); /* @kind shadow */
  --t-led-glow-soft: 0 0 0 1px color-mix(in oklch, var(--led) 18%, transparent), 0 0 4px color-mix(in oklch, var(--led) 45%, transparent); /* @kind shadow */
  /* T1 body: a hairline seam, a soft top light, one ambient shadow. */
  --t-body-shadow: inset 0 1px 0 var(--t-hi-soft), 0 0 0 1px var(--t-seam), 0 2px 4px -2px var(--t-ao), 0 14px 30px -16px var(--t-cast); /* @kind shadow */
  /* Accent ring: state rings mix from the LIVE accent, so a signature that
     recolours the accent recolours its rings. */
  --t-ring: 0 0 0 1px var(--accent), 0 0 0 4px color-mix(in oklch, var(--accent) 16%, transparent); /* @kind shadow */

  /* ---------- The material contract, pointed at the recipes ---------- */
  --bevel:          var(--t-edge);          /* @kind shadow */
  --bevel-soft:     var(--t-edge-soft);     /* @kind shadow */
  --edge-light:     var(--t-edge-soft);     /* @kind shadow */
  --well:           var(--t-well);          /* @kind shadow */
  --well-deep:      var(--t-well-deep);     /* @kind shadow */
  --press:          var(--t-key-shadow-down); /* @kind shadow */
  --shadow-contact: 0 1px 0 var(--t-wall), 0 2px 3px -1px var(--t-ao), 0 8px 14px -9px var(--t-cast); /* @kind shadow */
  --shadow-inset:   var(--t-well);          /* @kind shadow */
  --led-glow:          var(--t-led-glow);      /* @kind shadow */
  --led-glow-soft:     var(--t-led-glow-soft); /* @kind shadow */
  --led-glow-strong:   var(--t-led-glow);      /* @kind shadow */
  --led-glow-positive: 0 0 0 1px color-mix(in oklch, var(--led-positive) 22%, transparent), 0 0 5px color-mix(in oklch, var(--led-positive) 55%, transparent); /* @kind shadow */
  --led-glow-notice:   0 0 0 1px color-mix(in oklch, var(--led-notice) 22%, transparent),   0 0 5px color-mix(in oklch, var(--led-notice) 55%, transparent);   /* @kind shadow */
  --led-glow-negative: 0 0 0 1px color-mix(in oklch, var(--led-negative) 22%, transparent), 0 0 5px color-mix(in oklch, var(--led-negative) 55%, transparent); /* @kind shadow */
  --led-text-glow:     0 0 0 transparent;   /* numerals carry weight, not glow @kind other */
  --halo-accent:   0 0 0 3px color-mix(in oklch, var(--accent) 18%, transparent);   /* @kind shadow */
  --halo-positive: 0 0 0 3px color-mix(in oklch, var(--positive) 18%, transparent); /* @kind shadow */
  --halo-notice:   0 0 0 3px color-mix(in oklch, var(--notice) 18%, transparent);   /* @kind shadow */
  --halo-negative: 0 0 0 3px color-mix(in oklch, var(--negative) 18%, transparent); /* @kind shadow */
  --shadow-tint:          var(--shadow-contact); /* @kind shadow */
  --shadow-tint-accent:   var(--shadow-contact); /* @kind shadow */
  --shadow-tint-positive: var(--shadow-contact); /* @kind shadow */
  --shadow-tint-notice:   var(--shadow-contact); /* @kind shadow */
  --shadow-tint-negative: var(--shadow-contact); /* @kind shadow */

  /* Painted material is retired. These stay declared so the many component
     rules that stack `var(--grain), var(--skeuo-*)` resolve to a clean face. */
  --grain: none;             /* @kind other */
  --grain-size: auto;        /* @kind other */
  --sheen: none;             /* @kind other */
  --skeuo-card: none;        /* @kind other */
  --skeuo-raised: none;      /* @kind other */
  --skeuo-raised-soft: none; /* @kind other */
  --skeuo-well-grad: none;   /* @kind other */
  --skeuo-accent: none;      /* @kind other */
  --skeuo-hi:      var(--t-hi);      /* @kind color */
  --skeuo-hi-soft: var(--t-hi-soft); /* @kind color */
  --skeuo-lo:      var(--t-lo);      /* @kind color */
  --skeuo-lo-soft: var(--t-ao);      /* @kind color */

  /* Gel and extrusion are retired: a data mark is a matte solid with a
     2px thickness (components/themes/industry.css). The names stay declared
     because industry-charts.css reads them. */
  --extrude-depth: 2px;                  /* @kind spacing */
  --extrude-top:   var(--c, var(--accent));                                  /* @kind color */
  --extrude-face:  var(--c, var(--accent));                                  /* @kind color */
  --extrude-wall:  color-mix(in oklch, var(--c, var(--accent)) 74%, black);  /* @kind color */
  --extrude-sweep: linear-gradient(var(--c, var(--accent)), var(--c, var(--accent))); /* @kind color */
  --extrude-bevel: inset 0 1px 0 oklch(1 0 0 / 0.25);                        /* @kind shadow */
  --extrude-glow:  0 0 0 transparent;                                        /* @kind shadow */
  --extrude-cast:  0 2px 4px -1px var(--t-ao);                               /* @kind shadow */
  --gel-body:      linear-gradient(var(--c, var(--accent)), var(--c, var(--accent))); /* @kind color */
  --gel-streak:    none;                                                     /* @kind other */
  --gel-edge:      0 0 0 transparent;                                        /* @kind shadow */
  --gel-bloom:     0 0 0 transparent;                                        /* @kind shadow */
  --gel-dark:      linear-gradient(var(--series-muted), var(--series-muted)); /* @kind color */
  --gel-dark-edge: inset 0 -2px 0 var(--series-muted-deep);                  /* @kind shadow */

  /* Filled value tracks are matte, one colour — the fill's LENGTH is the
     reading. --ramp-angle is kept for the components that pass it. */
  --value-ramp: linear-gradient(var(--ramp-angle, 90deg), var(--accent), var(--accent)); /* @kind color */

  /* ---------- Geometry · generous, contemporary ---------- */
  --radius-control: 10px;
  --radius-card:    16px;
  --radius-surface: 20px;
  --radius-media:   12px;

  /* ---------- Type · sentence case everywhere ----------
     Actions, tabs and chips are set like the rest of the UI: sentence case,
     no tracking. Uppercase tracked legends were the 2012 tell. Titles are
     set tight. Readouts carry the instrument feel through weight and
     tabular figures, not through glow. */
  --legend-transform: none;      /* @kind other */
  --legend-tracking:  0;         /* @kind other */
  --heading-transform: none;     /* @kind other */
  --heading-tracking: -0.018em;  /* @kind other */

  /* ---------- Motion · quick, physical ---------- */
  --spin-duration: 0.9s;         /* @kind other */
}


/* ============================================================
   Ten-foot / cinema · material off, indicators on
   ------------------------------------------------------------
   At distance and through display compression, side walls smear and
   soft edges band. Colour and the accent survive perfectly and are
   the load-bearing signals, so the MATERIAL flattens to a hairline
   and the indicators stay.
   ============================================================ */
[data-theme="industry"] [data-scale="cinema"],
[data-theme="industry"][data-scale="cinema"],
[data-theme="laboratory"] [data-scale="cinema"],
[data-theme="laboratory"][data-scale="cinema"] {
  --t-key-face: none;        /* @kind other */
  --t-body-face: none;       /* @kind other */
  --t-well-face: none;       /* @kind other */
  --t-well-face-soft: none;  /* @kind other */
  --t-edge: inset 0 0 0 1px var(--t-hi-soft);      /* @kind shadow */
  --t-edge-soft: inset 0 0 0 1px var(--t-hi-soft); /* @kind shadow */
  --t-key-shadow: inset 0 0 0 1px var(--t-hi-soft), 0 1px 0 var(--t-wall);      /* @kind shadow */
  --t-key-shadow-sm: inset 0 0 0 1px var(--t-hi-soft), 0 1px 0 var(--t-wall);   /* @kind shadow */
  --t-key-shadow-down: inset 0 0 0 1px var(--t-lo);                               /* @kind shadow */
  --t-well: inset 0 0 0 1px var(--t-lo);           /* @kind shadow */
  --t-well-deep: inset 0 0 0 1px var(--t-lo);      /* @kind shadow */
  --t-well-soft: inset 0 0 0 1px var(--t-lo);      /* @kind shadow */
  --t-body-shadow: 0 0 0 1px var(--t-seam);        /* @kind shadow */
  --shadow-contact: 0 1px 0 var(--t-wall);         /* @kind shadow */
}

/* ===== tokens/theme-laboratory.css ===== */
/* ============================================================
   Prism · LABORATORY theme — tokens (the light instrument face)
   ------------------------------------------------------------
   Laboratory is Industry's bright sibling for scientific and clinical
   UIs, lab instrumentation, metrology and QA tooling — equipment that
   lives under daylight. Set it with data-theme="laboratory".

   REFERENCE · the Rams System Icons. Matte soft-touch polymer in warm
   near-neutral greys, keys and knobs seated in seams, one saturated
   accent reserved for the part you touch, tiny LED dots. The bench is
   near-white; the device body is a shade below it; the keys read a
   shade LIGHTER than the body they sit in — that inversion is the
   whole Braun look and it is what separates this from generic light
   UI.

   Laboratory and Industry are ONE material system with two value
   sets. Everything structural lives in components/themes/industry.css,
   keyed to both faces, and reads the recipes in the shared instrument
   block at the bottom of tokens/theme-industry.css. This file supplies
   the light face's VALUES: surfaces, ink, accent, LED colours, shadows
   and the eleven tactile-kit values. components/themes/laboratory.css
   holds the very few rules that are structurally different on light.

   NEUTRALS: one warm hue family (~95) at very low chroma. Not blue-grey
   — the reference bodies are warm putty greys under warm light.
   ============================================================ */

[data-theme="laboratory"] {
  color-scheme: light;

  /* ---------- Surfaces · bench, body, key ---------- */
  --surface-page:      oklch(0.972 0.003 95);   /* the bench: near-white, warm */
  --surface-sunken:    oklch(0.905 0.006 95);   /* wells and trays */
  --surface-card:      oklch(0.946 0.005 95);   /* the device body, a shade below the bench */
  --surface-raised:    oklch(0.978 0.003 95);   /* keys read lighter than the body */
  --surface-overlay:   oklch(0.985 0.002 95);
  --surface-stripe:    oklch(0.958 0.004 95);
  --fill-subtle:       oklch(0.930 0.005 95);
  --fill-subtle-hover: oklch(0.912 0.006 95);
  --fill-muted:        oklch(0.885 0.007 95);

  /* ---------- Ink · warm near-black; seams in the same family ---------- */
  --text-primary:     oklch(0.255 0.010 80);
  --text-secondary:   oklch(0.455 0.010 85);
  --text-tertiary:    oklch(0.585 0.010 88);
  --text-placeholder: oklch(0.660 0.008 90);
  --border-subtle:    oklch(0.880 0.006 95);
  --border-default:   oklch(0.820 0.007 95);
  --border-strong:    oklch(0.720 0.008 95);

  /* ---------- Accent · a coloured polymer, not a lamp ----------
     Deep enough for white ink (AA on the fill). Overridden for Laboratory
     only, so Industry keeps its blue and its hue knob. Swap the hue here to
     re-skin the whole face — the Rams orange is oklch(0.64 0.19 42), but
     white ink does not clear AA on it; use dark ink or a deeper orange. */
  --accent:              oklch(0.550 0.140 228);
  --accent-hover:        oklch(0.515 0.140 228);
  --accent-active:       oklch(0.480 0.135 228);
  --accent-on:           oklch(1 0 0);
  --accent-text:         oklch(0.470 0.130 228);
  --accent-subtle:       oklch(0.550 0.140 228 / 0.10);
  --accent-subtle-hover: oklch(0.550 0.140 228 / 0.16);
  --accent-border:       oklch(0.550 0.140 228 / 0.35);
  --focus-ring: var(--accent);

  /* ---------- LED colours · what an indicator emits on the light face ---------- */
  --led:     oklch(0.700 0.150 222); /* @kind color */
  --led-dim: oklch(0.800 0.008 95);  /* @kind color */

  /* ---------- Shadows · warm-tinted, soft, low ---------- */
  --shadow-xs: 0 1px 2px oklch(0.35 0.01 80 / 0.06);
  --shadow-sm: 0 1px 2px oklch(0.35 0.01 80 / 0.06), 0 3px 8px oklch(0.35 0.01 80 / 0.06);
  --shadow-md: 0 2px 6px oklch(0.35 0.01 80 / 0.07), 0 10px 24px oklch(0.35 0.01 80 / 0.10);
  --shadow-lg: 0 4px 12px oklch(0.35 0.01 80 / 0.08), 0 20px 44px oklch(0.35 0.01 80 / 0.14);
  --shadow-xl: 0 8px 20px oklch(0.35 0.01 80 / 0.10), 0 36px 80px oklch(0.35 0.01 80 / 0.18);

  /* ---------- Tactile kit · the light face's values ---------- */
  --t-hi:      oklch(1 0 0 / 0.85);                 /* soft top edge light            @kind color */
  --t-hi-soft: oklch(1 0 0 / 0.55);                 /* the same, restrained           @kind color */
  --t-lo:      oklch(0.35 0.012 80 / 0.09);         /* soft lower inner shade         @kind color */
  --t-wall:    oklch(0.845 0.008 95);               /* side wall, first step          @kind color */
  --t-wall-2:  oklch(0.790 0.009 95);               /* side wall, second step         @kind color */
  --t-ao:      oklch(0.30 0.012 80 / 0.14);         /* contact / ambient occlusion    @kind color */
  --t-cast:    oklch(0.30 0.012 80 / 0.16);         /* soft cast                      @kind color */
  --t-seam:    oklch(0.30 0.012 80 / 0.07);         /* hairline seam around a body    @kind color */
  --t-key:     var(--surface-raised);               /* key face                       @kind color */
  --t-key-face:  linear-gradient(180deg, var(--t-hi-soft), transparent 48%, var(--t-lo));             /* @kind other */
  --t-body-face: linear-gradient(180deg, oklch(1 0 0 / 0.22), transparent 42%);                        /* @kind other */
  --t-well-fill: var(--surface-sunken);                                                                 /* @kind color */
  --t-well-face: linear-gradient(180deg, oklch(0.30 0.012 80 / 0.05), transparent 45%);                /* @kind other */
  --t-well-face-soft: linear-gradient(180deg, oklch(0.30 0.012 80 / 0.03), transparent 38%);           /* @kind other */
  --t-hover: 1.015; /* @kind other */

  /* ---------- Series · light matte tracks and muted marks ---------- */
  --series-track:      oklch(0.900 0.006 95); /* @kind color */
  --series-gap:        var(--surface-card);   /* @kind color */
  --series-muted:      oklch(0.875 0.006 95); /* @kind color */
  --series-muted-deep: oklch(0.845 0.007 95); /* @kind color */

  /* ---------- Glass · frosted white; the scrim is a light veil ---------- */
  --surface-glass: oklch(0.985 0.002 95 / 0.80); /* @kind color */
  --glass-blur: 28px;                            /* @kind other */
  --surface-scrim: oklch(0.45 0.01 85 / 0.28);   /* @kind color */
  --scrim-blur: 6px;                             /* @kind other */

  /* ---------- Technical line art (light face) ---------- */
  --lineart-stroke:       var(--text-secondary); /* @kind color */
  --lineart-stroke-quiet: var(--border-strong);  /* @kind color */
  --lineart-callout:      var(--accent);         /* @kind color */
  --lineart-width:          1.5px; /* @kind spacing */
  --lineart-width-hairline: 1px;   /* @kind spacing */
  --lineart-width-lg:       2px;   /* @kind spacing */
  --lineart-width-bold:     3px;   /* @kind spacing */
}

/* >>> GENERATED · print uses the light theme — do not edit; source is the light block. Run `cd prism-docs && npm run gen`. >>> */
@media print {
  [data-theme="industry"] {
    color-scheme: light;

    /* ---------- Surfaces · bench, body, key ---------- */
    --surface-page:      oklch(0.972 0.003 95);   /* the bench: near-white, warm */
    --surface-sunken:    oklch(0.905 0.006 95);   /* wells and trays */
    --surface-card:      oklch(0.946 0.005 95);   /* the device body, a shade below the bench */
    --surface-raised:    oklch(0.978 0.003 95);   /* keys read lighter than the body */
    --surface-overlay:   oklch(0.985 0.002 95);
    --surface-stripe:    oklch(0.958 0.004 95);
    --fill-subtle:       oklch(0.930 0.005 95);
    --fill-subtle-hover: oklch(0.912 0.006 95);
    --fill-muted:        oklch(0.885 0.007 95);

    /* ---------- Ink · warm near-black; seams in the same family ---------- */
    --text-primary:     oklch(0.255 0.010 80);
    --text-secondary:   oklch(0.455 0.010 85);
    --text-tertiary:    oklch(0.585 0.010 88);
    --text-placeholder: oklch(0.660 0.008 90);
    --border-subtle:    oklch(0.880 0.006 95);
    --border-default:   oklch(0.820 0.007 95);
    --border-strong:    oklch(0.720 0.008 95);

    /* ---------- Accent · a coloured polymer, not a lamp ----------
       Deep enough for white ink (AA on the fill). Overridden for Laboratory
       only, so Industry keeps its blue and its hue knob. Swap the hue here to
       re-skin the whole face — the Rams orange is oklch(0.64 0.19 42), but
       white ink does not clear AA on it; use dark ink or a deeper orange. */
    --accent:              oklch(0.550 0.140 228);
    --accent-hover:        oklch(0.515 0.140 228);
    --accent-active:       oklch(0.480 0.135 228);
    --accent-on:           oklch(1 0 0);
    --accent-text:         oklch(0.470 0.130 228);
    --accent-subtle:       oklch(0.550 0.140 228 / 0.10);
    --accent-subtle-hover: oklch(0.550 0.140 228 / 0.16);
    --accent-border:       oklch(0.550 0.140 228 / 0.35);
    --focus-ring: var(--accent);

    /* ---------- LED colours · what an indicator emits on the light face ---------- */
    --led:     oklch(0.700 0.150 222); /* @kind color */
    --led-dim: oklch(0.800 0.008 95);  /* @kind color */

    /* ---------- Shadows · warm-tinted, soft, low ---------- */
    --shadow-xs: 0 1px 2px oklch(0.35 0.01 80 / 0.06);
    --shadow-sm: 0 1px 2px oklch(0.35 0.01 80 / 0.06), 0 3px 8px oklch(0.35 0.01 80 / 0.06);
    --shadow-md: 0 2px 6px oklch(0.35 0.01 80 / 0.07), 0 10px 24px oklch(0.35 0.01 80 / 0.10);
    --shadow-lg: 0 4px 12px oklch(0.35 0.01 80 / 0.08), 0 20px 44px oklch(0.35 0.01 80 / 0.14);
    --shadow-xl: 0 8px 20px oklch(0.35 0.01 80 / 0.10), 0 36px 80px oklch(0.35 0.01 80 / 0.18);

    /* ---------- Tactile kit · the light face's values ---------- */
    --t-hi:      oklch(1 0 0 / 0.85);                 /* soft top edge light            @kind color */
    --t-hi-soft: oklch(1 0 0 / 0.55);                 /* the same, restrained           @kind color */
    --t-lo:      oklch(0.35 0.012 80 / 0.09);         /* soft lower inner shade         @kind color */
    --t-wall:    oklch(0.845 0.008 95);               /* side wall, first step          @kind color */
    --t-wall-2:  oklch(0.790 0.009 95);               /* side wall, second step         @kind color */
    --t-ao:      oklch(0.30 0.012 80 / 0.14);         /* contact / ambient occlusion    @kind color */
    --t-cast:    oklch(0.30 0.012 80 / 0.16);         /* soft cast                      @kind color */
    --t-seam:    oklch(0.30 0.012 80 / 0.07);         /* hairline seam around a body    @kind color */
    --t-key:     var(--surface-raised);               /* key face                       @kind color */
    --t-key-face:  linear-gradient(180deg, var(--t-hi-soft), transparent 48%, var(--t-lo));             /* @kind other */
    --t-body-face: linear-gradient(180deg, oklch(1 0 0 / 0.22), transparent 42%);                        /* @kind other */
    --t-well-fill: var(--surface-sunken);                                                                 /* @kind color */
    --t-well-face: linear-gradient(180deg, oklch(0.30 0.012 80 / 0.05), transparent 45%);                /* @kind other */
    --t-well-face-soft: linear-gradient(180deg, oklch(0.30 0.012 80 / 0.03), transparent 38%);           /* @kind other */
    --t-hover: 1.015; /* @kind other */

    /* ---------- Series · light matte tracks and muted marks ---------- */
    --series-track:      oklch(0.900 0.006 95); /* @kind color */
    --series-gap:        var(--surface-card);   /* @kind color */
    --series-muted:      oklch(0.875 0.006 95); /* @kind color */
    --series-muted-deep: oklch(0.845 0.007 95); /* @kind color */

    /* ---------- Glass · frosted white; the scrim is a light veil ---------- */
    --surface-glass: oklch(0.985 0.002 95 / 0.80); /* @kind color */
    --glass-blur: 28px;                            /* @kind other */
    --surface-scrim: oklch(0.45 0.01 85 / 0.28);   /* @kind color */
    --scrim-blur: 6px;                             /* @kind other */

    /* ---------- Technical line art (light face) ---------- */
    --lineart-stroke:       var(--text-secondary); /* @kind color */
    --lineart-stroke-quiet: var(--border-strong);  /* @kind color */
    --lineart-callout:      var(--accent);         /* @kind color */
    --lineart-width:          1.5px; /* @kind spacing */
    --lineart-width-hairline: 1px;   /* @kind spacing */
    --lineart-width-lg:       2px;   /* @kind spacing */
    --lineart-width-bold:     3px;   /* @kind spacing */
  }
}
/* <<< GENERATED · print <<< */

/* ===== tokens/base.css ===== */
/* ============================================================
   Prism · Base & primitives
   ------------------------------------------------------------
   A light reset plus the global defaults every Prism surface
   inherits: hyperlegible body type, a single highly-visible
   focus ring, logical properties for RTL, and a reduced-motion
   guard. Authored with logical properties (inline/block) so
   the whole system mirrors automatically under dir="rtl".
   ============================================================ */

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

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

body {
  margin: 0;
  font-family: var(--body-font);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  font-weight: var(--weight-regular);
  color: var(--text-primary);
  background-color: var(--surface-page);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Headings default to the display family; sizes set per-use */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--heading-font);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  margin: 0;
}

/* Contrast guard: on any colored / gradient / dark surface, mark the
   container with data-on-color so its headings inherit the surface's
   text colour instead of the global dark --text-primary (which would
   otherwise render dark headings on a dark/vibrant fill). */
[data-on-color] :is(h1, h2, h3, h4, h5, h6) { color: inherit; }

code, kbd, samp, pre {
  font-family: var(--code-font);
  font-size: 0.92em;
}

a {
  color: var(--text-link);
  text-underline-offset: 0.15em;
}
a:hover { color: var(--text-link-hover); }

/* ------------------------------------------------------------
   Focus — Prism shows a thick, offset ring on keyboard focus
   only. This is intentionally loud: visible focus is the most
   important accessibility affordance in the system.
   ------------------------------------------------------------ */
:where(a, button, input, select, textarea, [tabindex], [role="button"]):focus-visible {
  outline: var(--focus-ring-width) solid var(--focus-ring);
  outline-offset: var(--focus-ring-offset-width);
  border-radius: var(--radius-xs);
}

/* Skip-link helper for keyboard users */
.prism-skip-link {
  position: absolute;
  inset-inline-start: var(--space-4);
  inset-block-start: -100%;
  background: var(--surface-card);
  color: var(--text-link);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  z-index: var(--z-toast);
}
.prism-skip-link:focus { inset-block-start: var(--space-4); }

/* Visually hidden but available to screen readers */
.prism-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

::selection {
  background: var(--accent-subtle);
  color: var(--text-primary);
}

/* ------------------------------------------------------------
   Overflow & overlap guards — defensive defaults so content
   never spills out of or collides across its container.
   ------------------------------------------------------------ */
/* Media never exceeds its container. */
img, svg, video, canvas, picture, image-slot {
  max-inline-size: 100%;
}
img, video, canvas, picture { block-size: auto; }
/* UI icons (Lucide and the inline glyphs) take one stroke weight, set on the
   <svg> so it beats the presentation attribute. Charts and line art set their
   own strokes on paths and are unaffected. */
:is(.prism-btn, .prism-icon-btn, .prism-fab, .prism-tab, .prism-menu-item, .prism-alert-icon, .prism-sidenav-link,
    .prism-sidenav-item, .prism-navbtn, .prism-breadcrumbs, .prism-badge, .prism-tag, .prism-field-hint, .prism-field-error,
    .prism-empty, .prism-toast, .prism-appheader-action, .prism-tree-row, .prism-cmd-item, .prism-kanban-menu) > svg,
:is(.prism-btn, .prism-icon-btn, .prism-tab, .prism-menu-item, .prism-toast, .prism-empty, .prism-dg-tool) svg[stroke="currentColor"] {
  stroke-width: var(--icon-stroke);
}
/* Long words / URLs / unbroken strings wrap instead of overflowing. */
p, h1, h2, h3, h4, h5, h6, li, dd, dt, figcaption, blockquote, label, td, th {
  overflow-wrap: break-word;
}
/* Flex/grid children can shrink below content size (the #1 cause of
   overflowing rows); opt a subtree in with data-guard="layout". */
[data-guard="layout"] :where(*) { min-width: 0; min-height: 0; }
/* Single-line truncation helper. */
.prism-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Multi-line clamp helper (set --lines, default 2). */
.prism-clamp { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: var(--lines, 2); line-clamp: var(--lines, 2); overflow: hidden; }

/* ------------------------------------------------------------
   Honour the user's motion preference everywhere.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}

/* ------------------------------------------------------------
   Forced-colors (Windows High Contrast) — keep focus + borders.
   ------------------------------------------------------------ */
@media (forced-colors: active) {
  :where(button, input, select, textarea, [role="button"]):focus-visible {
    outline: 2px solid CanvasText;
  }
}

/* ------------------------------------------------------------
   Print visibility — works with or without the component CSS.
   data-print="hide"  on screen only (a toolbar, a "Print" button)
   data-print="only"  on paper only (a letterhead, a signature line)
   ------------------------------------------------------------ */
@media print {
  [data-print="hide"] { display: none !important; }
}
@media screen {
  [data-print="only"] { display: none !important; }
}

/* Prism globals — GENERATED by build-registry.mjs. Do not edit by hand.
   The full CSS-variable foundation (colour, type, spacing, scales, elevation)
   + every theme (data-theme="light"|"dark"|"system"|"industry"|"laboratory") + base
   resets & keyframes. Self-contained: no npm token package required.
   Fonts are a separate item (@prism/prism-fonts). */

/* Revision of this file — changes whenever any of it does, so `shadcn add --overwrite` always updates it. */
:root { --prism-globals-rev: "4ad5a5115659"; }
