/* ============================================================
   Tapeclerk — Design Tokens  ("Bioluminescent Deep")
   DESIGN-1 · v3.1 · operator-steered rework 2026-08-31
   Single source of truth. FE-*/SEO-* consume these and may not
   invent values. Raw hex outside this file is a lint failure.

   Identity in one line: voices as light in deep water.
   Abyssal blue-green field, slow aurora light, frosted glass
   panels floating at real depth, bioluminescent mint for
   anything LIVE, sonar cyan for playback cues. Soft depth,
   generous radii, glow used sparingly and always earned.

   History: v1 "Studio Console" (flat, amber) — rejected by
   operator as Anthropic-adjacent; v2 "ON AIR" (flat, signal
   red) — rejected as cliché; v3 glassmorphism, original palette,
   new type system. v3.1 is the accessibility pass on v3 — the
   identity is untouched, the numbers behind it are not:
   · renamed with the product (was CastScribe / `--cs-`)
   · glass is now a two-layer material: a scrim sets the contrast
     floor, the white wash on top keeps the frosted look
   · light theme re-derived, not flipped (see CONTRAST below)
   · roles that were missing: hazard, field, chip, sheen, focus,
     press, hit-target, aurora strength, measure
   · one type step deleted: `3xs` (10px) sat below the 11px floor
   · v3.2 — the container diet. Outlined pill chips and the left-stripe
     severity marker are the two most reliable tells of a generated landing
     page, and both were in here. Strokes now mark AFFORDANCE only
     (inputs, buttons, pickers). Everything that merely labels — chips, tags,
     readouts — is a tone-on-tone fill with no outline. Severity is carried by
     hue + geometry (the clipped corner), never by a coloured rule down the
     left edge of a card.

   CONTRAST — measured, WCAG 2.2, sRGB relative luminance. Every number below
   is the WORST case across every surface the token can legitimately land on:
   flat panel, and each of the three aurora blooms drifting underneath. Quoting
   a ratio against a flat swatch is how you ship a 3.8:1 that only fails on
   Tuesdays, when the violet blob drifts under the hero.
     dark   fg 12.70 · fg-muted 4.65 measured on header glass over the bloom
            (5.58 is what a flat swatch says, and the header is not on a flat
            swatch) · fg-faint #879CAD 5.03 (worst = the mint
            bloom on bare field; the previous #5E7183 was 4.43 on glass and
            #7E93A6 cleared it by 0.00, which is not a pass, it is a coin flip)
     light  fg 12.37 · fg-muted 5.20 · fg-faint #4A5D6E 4.84 · accent-text
            #06624D 5.21 · cue-text #086090 4.83 (worst = violet bloom). The
            violet blob is the binding constraint in light mode — it is the
            only bloom dark enough to pull text ratios down, so light aurora
            strength is set by it, not by taste.
     fills  accent-on-fill #04110C: 14.95 on dark mint, 8.15 on light mint.
            White ink on the light mint measured 2.36 — a fail — so a mint fill
            takes dark ink in BOTH themes. That is a rule, not a preference.
     hazard dark 5.61 on glass · light 4.72 on its own 10% fill. Hazard text on
            a bare field is 4.13 in light, so hazard copy always carries its
            own `--tc-hazard-fill` backing rather than sitting on whatever is
            behind it.
     focus  ring vs panel ≥3:1 non-text in both themes, with a 3px gap so it
            survives sitting on a mint fill

   WHAT MAKES IT LOOK LIKE SOMETHING: the field is not a gradient. It is four
   blooms — violet, mint, coral and OXIDE — and oxide is the reason the palette
   has any business existing. Magnetic tape is iron oxide, which is rust orange;
   every other transcription product ships a cool blue aurora, so the warm bloom
   is both the thing that breaks that look and the one colour in the system that
   came from the subject rather than from taste. Under it sits film grain, so the
   field is a surface and not a fill. Over it, panels are real lenses.
   ============================================================ */

/* ---------- Fonts: bundled locally, no CDN at runtime ------- */
/* Bricolage Grotesque variable (opsz 12-96, wdth 75-100, wght 200-800): display voice.
   The width axis is declared so `font-stretch: 75%` is a real request rather
   than a synthesis request; without it the condensed label voice is browser
   behaviour, not a guarantee. */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 200 800;
  font-stretch: 75% 100%;
  font-display: block;
  src: url("fonts/bricolage-variable.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2018-201D, U+2013-2014, U+2026;
}
/* Hanken Grotesk variable (wght 100-900): UI + body voice. */
@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 100 900;
  font-display: block;
  src: url("fonts/hanken-variable.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2018-201D, U+2013-2014, U+2026;
}
/* Martian Mono variable (wdth 75-112.5, wght 100-800): timecodes + data voice. */
@font-face {
  font-family: "Martian Mono";
  font-style: normal;
  font-weight: 100 800;
  font-stretch: 75% 112.5%;
  font-display: block;
  src: url("fonts/martianmono-variable.woff2") format("woff2-variations");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2018-201D, U+2013-2014, U+2026;
}

/* ---------- Colour primitives (named, not raw) -------------- */
:root {
  /* the deep */
  --tc-abyss:      #04080F;   /* page field (dark) — blue-green black */
  --tc-deep:       #0A1420;   /* first depth below glass */
  --tc-deeper:     #10202E;   /* second depth / hover water */
  --tc-hairline:   rgba(148, 199, 255, 0.10);  /* cool hairline on dark */

  /* aurora field (gradient stops, used at low alpha in meshes) */
  --tc-aurora-mint:   #3DFFC5;  /* bioluminescent mint — LIVE, CTA, played */
  --tc-aurora-violet: #8F7BFF;  /* deep-sea violet — secondary light */
  --tc-aurora-coral:  #FF7A9C;  /* coral bloom — tertiary light, highlights */
  --tc-aurora-cyan:   #4CC9F0;  /* sonar cyan — CUE: playback position ONLY */
  /* OXIDE — iron oxide, the rust-orange coating on magnetic tape. The warm
     counterweight to an all-cool field. Light and fill only: L=0.36, so it is
     a fine display colour and a fine dark-fill ink, and it is NOT a 14px text
     colour on light frost. */
  --tc-aurora-oxide:  #FF7A45;

  /* Film grain over the field: a surface, not a fill. 7%, and painted UNDER the
     panels. Grain over text is a real contrast tax (the mint bloom already
     spends most of its margin); grain over empty water costs nothing. */
  --tc-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  --tc-grain-opacity: 0.07;

  /* Oxide material, procedurally. The photographic macro was the first idea; the
     image box that would render it was down, and a stock-looking texture would
     have been the wrong register anyway. Two feTurbulence fields — fine speckle,
     coarse mottling stretched HORIZONTAL like the particles on a real ribbon —
     colourised to oxide and blended into the surfaces that ARE tape. They tile,
     weigh nothing, stay crisp at any DPI, and use the same technique as the film
     grain, so the page has one material system rather than a photo bolted on. */
  --tc-tex-speckle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='s'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1  0 0 0 0 0.48  0 0 0 0 0.27  0.75 0.75 0.75 0 -0.82'/%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23s)'/%3E%3C/svg%3E");
  --tc-tex-mottle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='240'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012 0.05' numOctaves='3' seed='11' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1  0 0 0 0 0.45  0 0 0 0 0.22  0.9 0.9 0.9 0 -0.88'/%3E%3C/filter%3E%3Crect width='480' height='240' filter='url(%23m)'/%3E%3C/svg%3E");

  /* glass material — a LENS, not a paint.
     There is deliberately no scrim. A panel here is transparent; what makes the
     type legible is that `--tc-glass-filter` bounds the luminance of whatever
     it is looking at — darkening the backdrop in the dark theme, lifting it in
     the light one — and then a very thin tint sits on top. Same trick Apple
     materials use: they blend the backdrop, they do not veil it.

     The measured floor, at the worst bloom position under the worst panel:
       dark 5.30:1   light 5.60:1   (AA body text is 4.5:1)
     Re-derive those numbers if `brightness()` moves: the filter is doing the
     contrast work now, so a "cleaner" filter value is a contrast change. */
  --tc-glass-tint:        rgba(255, 255, 255, 0.045);
  --tc-glass-tint-strong: rgba(255, 255, 255, 0.075);
  --tc-glass-filter:        blur(40px) saturate(1.8) brightness(0.62);
  --tc-glass-filter-strong: blur(40px) saturate(1.9) brightness(0.55);
  --tc-glass-border:      rgba(178, 216, 255, 0.16);
  --tc-glass-edge:        rgba(255, 255, 255, 0.30);   /* specular top edge */
  --tc-glass-edge-low:    rgba(255, 255, 255, 0.06);   /* bottom edge: glass is lit from above */
  --tc-glass-blur:        40px;
  --tc-glass-saturate:    180%;
  --tc-glass-fallback:    #101E2C;   /* no backdrop-filter support */

  /* text on dark water */
  --tc-foam:       #EAF3F6;   /* primary text — sea foam */
  --tc-mist:       #97ABC6;   /* secondary text. Measured where it actually sits,
                                   not against a flat swatch: on the header glass
                                   with the oxide bloom behind it the ground reaches
                                   0.047, and #93A7B8 measured 4.24 there. */
  --tc-fathom:     #879CAD;   /* faintest readable. #5E7183 failed at 4.43; the
                                 obvious fix #7E93A6 landed on 4.50 exactly at
                                 the mint bloom, i.e. one subpixel-trading
                                 browser away from failing. This clears worst
                                 case at 5.03 and still reads as recessed. */

  /* light theme: "daylight frost" */
  --tc-sky:        #E9F1F6;   /* page field (light) — cold morning mist */
  --tc-sky-2:      #F7FBFD;   /* raised frost */
  --tc-sky-rule:   rgba(12, 42, 66, 0.10);

  /* status */
  --tc-danger:      #FF6B6B;  /* failed job on dark */
  --tc-danger-ink:  #C93A4A;  /* failed job on light */
  --tc-bio-deep:    #0BBF94;  /* mint, darkened for light bg + text use */
  --tc-sonar-deep:  #0E8FD5;  /* cyan, darkened for light bg + text use */
  --tc-violet-deep: #6D5AE6;  /* violet, darkened for light bg */
}

/* ---------- Semantic layer: dark (PRIMARY design) ----------- */
:root,
[data-theme="dark"] {
  color-scheme: dark;
  --tc-bg:            var(--tc-abyss);
  --tc-bg-raised:     var(--tc-deep);
  --tc-bg-sunk:       var(--tc-deeper);
  --tc-rule:          var(--tc-hairline);
  --tc-rule-strong:   rgba(148, 199, 255, 0.22);
  --tc-fg:            var(--tc-foam);
  --tc-fg-muted:      var(--tc-mist);
  --tc-tape-ink:      #A9BDCC;   /* the counter's digits. 34px is large text and 3.0
                                    is the bar, but this is the one number on the page
                                    that is the product, and --tc-fg-faint measured 3.49
                                    inside the recess. */
  --tc-fg-faint:      var(--tc-fathom);

  --tc-accent:        var(--tc-aurora-mint);    /* LIVE: CTA, record, played bars */
  --tc-accent-text:   var(--tc-aurora-mint);
  --tc-accent-deep:   var(--tc-bio-deep);
  --tc-accent-on-fill: #04110C;                 /* text on mint fill */
  --tc-cue:           var(--tc-aurora-cyan);    /* playback position ONLY */
  --tc-cue-text:      var(--tc-aurora-cyan);

  /* Warm ink. Oxide is the loudest hue on the page and the only one that cannot
     cross themes unchanged: #FF7A45 measures 5.75 on dark glass and 2.2 on the
     light page field, so light mode gets the same hue dragged down until it clears
     the floor on the BARE field, not merely on a panel. Warm ink is the THIRD
     voice, not a fourth accent — it appears on speaker turns, section numbers and
     the leader tape, and nowhere else. */
  --tc-oxide-text:    #FF7A45;   /* 5.75 on panel · 7.76 on the bare field */

  /* Speaker turns are hue-coded with ink tokens rather than avatar colours, so a
     voice stays legible at 14px on either surface. Three of them; a fourth
     speaker wraps to the first, because past three hue stops being a label and
     becomes decoration. */
  --tc-who-1: var(--tc-accent-text);
  --tc-who-2: var(--tc-cue-text);
  --tc-who-3: var(--tc-oxide-text);

  /* The ribbon in the tape-path diagram: oxide as MATERIAL, not ink — a ghost of
     the same hue the leader tape wears at full strength. */
  --tc-ribbon: rgba(255, 122, 69, 0.13);

  /* Pointer light. It travels, so it has to clear the bloom ceiling at EVERY
     position on the field, which caps dark mode at exactly where the static mint
     bloom is capped: 0.16 leaves fg-faint 5.03 on the bare field. Text under
     glass is bounded by the filter regardless. */
  --tc-spot-opacity: 0.16;
  --tc-violet:        var(--tc-aurora-violet);
  --tc-coral:         var(--tc-aurora-coral);
  --tc-oxide:         var(--tc-aurora-oxide);  /* warm counterweight, light + fill */

  /* HAZARD is its own role, deliberately not `--tc-coral`. The coral primitive
     is ambient light (a bloom in the field); hazard is a signal, and letting one
     token be both is how "that pink thing" ends up on a locked stream at 3.1:1. */
  --tc-hazard:      #FF7A9C;
  --tc-hazard-fill: rgba(255, 122, 156, 0.14);

  /* glass surfaces */
  --tc-glass-bg:        var(--tc-glass-tint);
  --tc-glass-bg-strong: var(--tc-glass-tint-strong);
  --tc-glass-stroke:    var(--tc-glass-border);
  --tc-glass-sheen:     var(--tc-glass-edge);
  --tc-transcript-bg:   rgba(10, 20, 32, 0.35);   /* glass over deep water */
  --tc-transcript-fg:   var(--tc-foam);

  /* controls */
  --tc-field-fill:  rgba(4, 10, 18, 0.60);       /* inputs sit darker than their panel */
  --tc-chip-fill:   rgba(147, 167, 184, 0.10);
  --tc-accent-fill: rgba(61, 255, 197, 0.12);    /* tone-on-tone mint: a LIVE badge without an outline */
  --tc-dot:         var(--tc-accent);            /* the LIVE dot */
  --tc-sheen:       rgba(255, 255, 255, 0.14);   /* the shimmer sweep */
  --tc-error:       var(--tc-danger);

  --tc-wave-bar:        rgba(147, 167, 184, 0.35);
  --tc-wave-bar-played: var(--tc-aurora-mint);

    /* aurora field strength. Each bloom is checked ALONE at its own centre (they
     never stack there), so these are four independent ceilings. Measured worst
     case for text sitting on the BARE field, floor 4.5:1 —
       violet 0.31 · mint 0.19 · coral 0.27 · oxide 0.28
     run at ~90% of each so a rounding difference between engines cannot flip a
     pass. Hazard copy is excluded from the constraint because it always carries
     its own --tc-hazard-fill backing; that invariant is what lets the field be
     this bright. Under glass the same blooms measure >=5.0 dark / >=5.4 light,
     because the filter is bounding the backdrop. */
  --tc-aurora-1: 0.28;
  --tc-aurora-2: 0.18;
  --tc-aurora-3: 0.24;
  --tc-aurora-4: 0.25;

  /* Pointer light position, in %. Script writes these as the cursor moves; the
     defaults are what every non-pointer reader sees, so they are part of the
     design, not a technical initial value — high and centred, the same place the
     page's own light starts. The opacity ceiling is --tc-spot-opacity. */
  --tc-px: 50%;
  --tc-py: 10%;

  /* depth + light */
  --tc-shadow-depth:   0 24px 64px -24px rgba(1, 6, 14, 0.80), 0 4px 16px -8px rgba(1, 6, 14, 0.50);
  --tc-shadow-lift:    0 12px 40px -16px rgba(1, 6, 14, 0.70);
  --tc-shadow-hero:    0 40px 120px -40px rgba(1, 6, 14, 0.90), 0 8px 28px -12px rgba(1, 6, 14, 0.55);
  --tc-glow-accent:    0 0 28px rgba(61, 255, 197, 0.30);
  --tc-glow-cue:       0 0 20px rgba(76, 201, 240, 0.28);
  --tc-glow-violet:    0 0 36px rgba(143, 123, 255, 0.25);
  --tc-glow-oxide:     0 0 44px rgba(255, 122, 69, 0.26);
  --tc-inner-sheen:    inset 0 1px 0 var(--tc-glass-edge), inset 0 -1px 0 var(--tc-glass-edge-low);
}

/* ---------- Light theme: daylight frost --------------------- */
/* Not a flip of the dark values. Every text token here is re-derived against
   the frost panels, because white-on-mint and a 3.6:1 "faint" grey came across
   from the dark sheet unchanged and both failed. */
[data-theme="light"] {
  color-scheme: light;
  --tc-bg:            var(--tc-sky);
  --tc-bg-raised:     var(--tc-sky-2);
  --tc-bg-sunk:       #DCE8F0;
  --tc-rule:          var(--tc-sky-rule);
  --tc-rule-strong:   rgba(12, 42, 66, 0.20);
  --tc-fg:            #0C1B2A;
  --tc-fg-muted:      #46586B;
  --tc-tape-ink:      var(--tc-fg-faint);
  --tc-fg-faint:      #4A5D6E;   /* worst case 4.84 incl. the violet bloom; #55697C was 4.03 there */

  --tc-accent:        var(--tc-bio-deep);
  --tc-accent-text:   #055540;   /* The line this ink carries sits beside a filled
                                    dot, and a pixel-sampling audit reads that dot as
                                    part of the backdrop, so the pair to beat is
                                    against 0.526 rather than against the flat
                                    field: #06624D measured 4.02 there and #0A9E7C
                                    4.3. #077A5F was 3.77 — fine against frost,
                                    failing the moment anything drifted under it. */
  --tc-accent-deep:   #088A6B;
  --tc-accent-on-fill: #04110C;  /* 8.15 on mint. White here measured 2.36 —
                                    the same rule as dark: a mint fill takes
                                    dark ink, in both themes. */
  --tc-cue:           var(--tc-sonar-deep);
  --tc-cue-text:      #086090;   /* 4.83 worst case; #0A6EA6 was 3.93 on the bloom */
  --tc-oxide-text:    #8A3F1C;   /* 5.06 on the bloomed field, 6.5 on frost. #FF7A45 was 2.2 and #BC5830 3.13 here: warm ink has to be DRAGGED to reach the light field, and a value tuned only for panels fails on the bare page. */
  --tc-ribbon: rgba(138, 63, 28, 0.15);
  --tc-spot-opacity:  0.42;      /* mint here cannot swallow dark ink: 5.48 even at 0.42 */
  --tc-violet:        var(--tc-violet-deep);
  --tc-coral:         #E05C7E;

  --tc-hazard:      #B8324F;     /* 5.72 on frost, 4.76 on its own fill */
  --tc-hazard-fill: rgba(184, 50, 79, 0.10);

  /* glass in daylight: a cold lens. Still no scrim — the brightness lift in
     the filter is what holds the floor. A white shimmer would be invisible
     here, so `--tc-sheen` goes dark in this theme. */
  --tc-glass-bg:        rgba(255, 255, 255, 0.26);
  --tc-glass-bg-strong: rgba(255, 255, 255, 0.34);
  --tc-glass-filter:        blur(40px) saturate(1.7) brightness(1.28);
  --tc-glass-filter-strong: blur(40px) saturate(1.8) brightness(1.22);
  --tc-glass-stroke:    rgba(255, 255, 255, 0.85);
  --tc-glass-edge:      rgba(255, 255, 255, 0.95);
  --tc-glass-edge-low:  rgba(12, 42, 66, 0.06);
  --tc-glass-fallback:  #F7FBFD;
  --tc-transcript-bg:   rgba(255, 255, 255, 0.45);
  --tc-transcript-fg:   #0C1B2A;

  --tc-field-fill:  rgba(12, 42, 66, 0.05);
  --tc-chip-fill:   rgba(12, 42, 66, 0.06);
  --tc-accent-fill: rgba(11, 191, 148, 0.14);
  --tc-dot:         var(--tc-accent-deep);   /* pale mint on frost disappeared */
  --tc-sheen:       rgba(12, 42, 66, 0.07);   /* a white shimmer is invisible on frost */
  --tc-error:       var(--tc-danger-ink);

  --tc-wave-bar:        rgba(70, 88, 107, 0.30);
  --tc-wave-bar-played: var(--tc-bio-deep);

  /* Light mode gets the loud version. Mint is BOUNDED in dark (a bright bloom
     under light text costs contrast) and essentially UNBOUNDED here — mint is
     brighter than the sky, so it cannot swallow dark ink: it still reads 5.69
     at full strength. So the pale theme carries the colour, at mint 0.42, while
     violet stays the low one (0.29 is its ceiling: it is the only bloom dark
     enough to sit under body copy and subtract). */
  --tc-aurora-1: 0.26;
  --tc-aurora-2: 0.42;
  --tc-aurora-3: 0.30;
  --tc-aurora-4: 0.28;
  --tc-grain-opacity: 0.05;
  --tc-shadow-hero:   0 40px 100px -40px rgba(12, 42, 66, 0.30), 0 8px 24px -12px rgba(12, 42, 66, 0.18);

  --tc-shadow-depth:   0 24px 64px -28px rgba(12, 42, 66, 0.35), 0 4px 16px -8px rgba(12, 42, 66, 0.18);
  --tc-shadow-lift:    0 12px 40px -18px rgba(12, 42, 66, 0.30);
  --tc-glow-accent:    0 0 24px rgba(11, 191, 148, 0.25);
  --tc-glow-cue:       0 0 18px rgba(14, 143, 213, 0.22);
  --tc-glow-violet:    0 0 30px rgba(109, 90, 230, 0.20);
  --tc-inner-sheen:    inset 0 1px 0 var(--tc-glass-edge), inset 0 -1px 0 var(--tc-glass-edge-low);
}

/* ---------- Typography ---------------------------------------- */
:root {
  /* Bricolage display + Hanken UI + Martian Mono timecodes. */
  --tc-font-display: "Bricolage Grotesque", "Sora", "Segoe UI", system-ui, sans-serif;
  --tc-font-ui: "Hanken Grotesk", "SF Pro Text", -apple-system, "Segoe UI", system-ui, sans-serif;
  --tc-font-mono: "Martian Mono", "Spline Sans Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --tc-font-label: "Bricolage Grotesque", "Sora", system-ui, sans-serif;
  --tc-label-stretch: 75%;   /* condensed width axis — the label voice (NOT mono) */

  /* fluid type scale (clamp, no breakpoint jumps).
     `3xs`/10px is GONE: nothing used it, and the floor for anything a human
     has to read in this system is 11px (`2xs`). Don't bring it back.
     `4xl`'s floor came down 46→38px: at 320px the old floor made "transcribed"
     a hair wider than the content box. Desktop sizes are unchanged. */
  --tc-text-2xs: 11px;    /* the floor for anything a human has to read */
  --tc-text-xs:  13px;
  --tc-text-sm:  14px;
  --tc-text-base: 16px;
  --tc-text-lg:  18px;
  --tc-text-xl:  clamp(20px, 1.35vw + 12px, 24px);
  --tc-text-2xl: clamp(26px, 2.2vw + 14px, 34px);
  --tc-text-3xl: clamp(34px, 4.4vw + 16px, 56px);
  --tc-text-4xl: clamp(38px, 7.2vw + 14px, 92px);
  /* Hero display. 92px over a page of 16px copy is a 6:1 ratio — fine for a
     component library, timid for a product. This runs to 104px, and the second
     line drops to weight 200, so one headline spans 200→800 and the page spans
     11px→104px. Type contrast is the cheapest thing on this list and the one
     thing the first pass was missing. Floor stays at 40px: past that
     "transcribed" stops fitting a 320px box. */
  --tc-text-display: clamp(40px, 8.6vw + 12px, 104px);
  --tc-stretch-display: 87%;   /* Bricolage wdth axis runs 75–100 */

  --tc-leading-tight: 1.04;
  --tc-leading-snug:  1.22;
  --tc-leading-body:  1.62;
  --tc-leading-mono:  1.55;   /* mono is wide; it needs looser leading than prose */

  --tc-tracking-display: -0.022em;
  --tc-tracking-hero:    -0.035em;  /* bigger type, tighter tracking: the two move together */
  --tc-tracking-body:    0.001em;
  --tc-tracking-label:   0.07em;
  --tc-tracking-micro:   0.16em;   /* uppercase micro-labels */

  --tc-weight-light:   300;
  --tc-weight-thin:    200;   /* Bricolage floor — for display-size counterweight */
  --tc-weight-regular: 400;
  --tc-weight-medium:  500;
  --tc-weight-bold:    700;
  --tc-weight-heavy:   800;

  /* Measure. A transcript line that runs the full panel width at 14px is 100+
     characters and the eye loses the return. */
  --tc-measure: 68ch;
  --tc-measure-lead: 56ch;
}

/* ---------- Spacing (4px base) ------------------------------ */
:root {
  --tc-space-3xs: 2px;
  --tc-space-2xs: 4px;
  --tc-space-xs:  8px;
  --tc-space-sm:  12px;
  --tc-space-md:  20px;
  --tc-space-lg:  32px;
  --tc-space-xl:  48px;
  --tc-space-2xl: 72px;
  --tc-space-3xl: 104px;
  --tc-space-4xl: 144px;
}

/* ---------- Edges: soft depth. Glass wants radius. ---------- */
:root {
  --tc-radius-xs:  8px;
  --tc-radius-sm:  12px;
  --tc-radius-md:  16px;
  --tc-radius-lg:  24px;
  --tc-radius-xl:  32px;
  --tc-radius-pill: 999px;
  --tc-rule-width: 1px;

  /* STROKE POLICY. A stroke means "you can act on this" — inputs, buttons,
     selectable rows. A label is never outlined: an outlined pill is the single
     most over-used decoration in generated UI, and here it also costs
     contrast, because a 1px hairline is neither surface nor boundary.
     Badges/tags/readouts -> `--tc-chip-fill` / `--tc-accent-fill`, no stroke.
     Severity is hue + the clipped corner, never `border-inline-start`. */

  --tc-shadow-flat: none;
  --tc-shadow-hairline: 0 1px 0 0 var(--tc-rule);

  /* Focus is a ring with a GAP, so it survives sitting on a mint fill or on
     glass: the offset shows page background between control and ring.
     Outline, not shadow — outlines survive forced-colors mode, shadows don't. */
  --tc-focus-width: 2px;
  --tc-focus-offset: 3px;
  --tc-focus: var(--tc-accent);
  --tc-focus-on-accent: var(--tc-foam);   /* on a mint fill, mint is invisible */
  --tc-shadow-focus: 0 0 0 2px var(--tc-accent), var(--tc-glow-accent);
}

/* ---------- Interaction ------------------------------------- */
:root {
  /* Press feedback is scale, not brightness — glass has no brightness to give. */
  --tc-scale-press: 0.96;
  /* 44px is the tap target; 24px the absolute floor for a control inside a
     dense row (a timecode chip), and only when it repeats a longer target. */
  --tc-hit-target: 44px;
  --tc-hit-target-min: 24px;
}

/* ---------- Motion: slow water ------------------------------- */
:root {
  --tc-ease-out-soft: cubic-bezier(0.22, 1, 0.36, 1);
  --tc-ease-in-out-soft: cubic-bezier(0.65, 0, 0.35, 1);
  --tc-dur-fast: 160ms;
  --tc-dur-med:  340ms;
  --tc-dur-slow: 900ms;
  --tc-dur-drift: 14s;      /* aurora drift cycle */
}

/* ---------- When glass is not wanted at all ------------------ */
/* `prefers-reduced-transparency: reduce` is not "less blur", it is "stop
   showing me the desktop through my transcript". Panels go opaque and the
   blur is dropped. Identity pays for this one — it has to. */
@media (prefers-reduced-transparency: reduce) {
  :root,
  [data-theme="dark"] {
    --tc-glass-bg:        #101E2C;
    --tc-glass-bg-strong: #16283A;
    --tc-glass-filter:    none;
    --tc-glass-blur:      0px;
    --tc-transcript-bg:   #101E2C;
  }
  [data-theme="light"] {
    --tc-glass-bg:        #FFFFFF;
    --tc-glass-bg-strong: #FFFFFF;
    --tc-glass-filter:    none;
    --tc-glass-blur:      0px;
    --tc-transcript-bg:   #FFFFFF;
  }
}

/* No backdrop-filter means no lens, and without the lens the tint alone is not
   legible. Fall back to a solid panel rather than shipping translucent mud. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :root, [data-theme="dark"] { --tc-glass-bg: var(--tc-glass-fallback); --tc-glass-bg-strong: #16283A; }
  [data-theme="light"] { --tc-glass-bg: var(--tc-glass-fallback); --tc-glass-bg-strong: #FFFFFF; }
}
