/* =========================================================================
   theme.css - tokens, the scene, and the baked Liquid Glass presets.

   Load order matters:  glass.css  ->  theme.css  ->  app.css
   glass.css defines the *material* (three optical layers driven by --lg-*).
   This file defines (a) the design system those layers live inside, and
   (b) named preset classes that pin the --lg-* knobs to the exact values
   exported by the reference generator.

   Why presets are plain CSS classes and not JS calls:
   LG.apply() writes the --lg-* set as inline styles on <html>, which every
   .lg then *inherits*. An element that carries its own declaration for the
   same custom property wins over an inherited one regardless of where the
   inherited value came from, so a `.glass-onyx` class cleanly overrides the
   document-level material without any specificity war. LG.apply() therefore
   sets the accent default for un-presetted glass and, more importantly,
   feeds LG's refraction engine (api.current) which CSS cannot reach.

   The numbers below are NOT hand-tuned here. They are the output of
   LG.vars(cfg) for each reference config, so what you see in the browser is
   byte-identical to what the generator produced:
     tintTop    = tintOpacity * 1.15
     tintBottom = tintOpacity * 0.55
     rim1 = rimOpacity,  rim2 = rimOpacity * 0.09,  rim3 = rimOpacity * 0.55
     innerSpread = -round(innerBlur * 0.3)
   Two knobs have no CSS equivalent: `refraction` and `edge` are consumed by
   LG.register()/LG.apply() in JS. They live in theme.js next to the accent
   configs; see the note there.
   ========================================================================= */

/* -------------------------------------------------------------------------
   1. Primitives: type, space, radii, depth, motion.
   These never change between appearances - only colour does.
   ------------------------------------------------------------------------- */
:root {
  /* --- type ------------------------------------------------------------ */
  --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Segoe UI",
               Inter, Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --font-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas,
               "Liberation Mono", "Courier New", monospace;

  /* Fluid scale. Each step interpolates between the 360px floor and the
     1440px ceiling so nothing needs a per-breakpoint font-size override. */
  --fs-display: clamp(2.25rem, 1.35rem + 4.0vw, 4.25rem);
  --fs-h1:      clamp(1.85rem, 1.25rem + 2.7vw, 3.25rem);
  --fs-h2:      clamp(1.45rem, 1.10rem + 1.6vw, 2.25rem);
  --fs-h3:      clamp(1.15rem, 1.00rem + 0.7vw, 1.5rem);
  --fs-lead:    clamp(1.02rem, 0.95rem + 0.5vw, 1.25rem);
  --fs-body:    clamp(0.95rem, 0.92rem + 0.2vw, 1.05rem);
  --fs-sm:      0.875rem;
  --fs-xs:      0.78rem;
  --fs-mono:    clamp(0.8rem, 0.75rem + 0.3vw, 0.92rem);

  --lh-tight: 1.08;
  --lh-snug: 1.28;
  --lh-body: 1.62;

  --tracking-tight: -0.022em;
  --tracking-wide: 0.08em;

  /* --- space: 4px base, doubling-ish so rhythm stays obvious ----------- */
  --sp-1: 4px;
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 20px;
  --sp-6: 24px;
  --sp-7: 32px;
  --sp-8: 40px;
  --sp-9: 56px;
  --sp-10: 72px;
  --sp-11: 96px;
  --sp-12: 128px;

  --container: 1180px;
  --container-narrow: 760px;
  --gutter: clamp(16px, 4vw, 40px);

  /* --- radii -----------------------------------------------------------
     These are for non-glass boxes. A .lg element takes its radius from
     --lg-radius so that the specular rim mask and the refraction lens map
     agree with the actual corner; never override border-radius on .lg. */
  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 28px;
  --r-pill: 999px;

  /* --- depth ------------------------------------------------------------
     The scene sits on negative layers so ordinary in-flow content (z-index
     auto) floats above it without any wrapper needing a z-index. Do not put
     `isolation`, `opacity` or `transform` on <body>: that would make body a
     stacking context and trap the scene behind it. */
  --z-scene-far: -3;
  --z-scene-near: -2;
  --z-scene-grain: -1;
  --z-base: 0;
  --z-raised: 10;
  --z-header: 100;
  --z-hud: 200;
  --z-tooltip: 300;
  --z-modal: 400;

  /* --- motion -----------------------------------------------------------
     --ease-glass is the same curve glass.css uses for lift/scale: a small
     overshoot that reads as a soft physical material rather than a fade. */
  --ease-glass: cubic-bezier(.32, 1.25, .5, 1);
  --ease-out: cubic-bezier(.22, .61, .36, 1);
  --ease-in-out: cubic-bezier(.65, 0, .35, 1);
  --ease-scene: cubic-bezier(.45, .05, .55, .95);

  --dur-1: .12s;   /* press feedback */
  --dur-2: .24s;   /* hover, colour */
  --dur-3: .42s;   /* glass lift, panel reveal */
  --dur-4: .8s;    /* progress, plan numbers */

  /* --- grain, baked once ------------------------------------------------
     Identical output to LG.noiseImage(0.04 | 0.05 | 0.06). Presets point
     --lg-noise at one of these instead of carrying their own copy. */
  --noise-04: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22160%22%20height%3D%22160%22%3E%3Cfilter%20id%3D%22n%22%20x%3D%220%22%20y%3D%220%22%20width%3D%22100%25%22%20height%3D%22100%25%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%220.85%22%20numOctaves%3D%223%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20type%3D%22saturate%22%20values%3D%220%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22160%22%20height%3D%22160%22%20filter%3D%22url(%23n)%22%20opacity%3D%220.040%22%2F%3E%3C%2Fsvg%3E");
  --noise-05: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22160%22%20height%3D%22160%22%3E%3Cfilter%20id%3D%22n%22%20x%3D%220%22%20y%3D%220%22%20width%3D%22100%25%22%20height%3D%22100%25%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%220.85%22%20numOctaves%3D%223%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20type%3D%22saturate%22%20values%3D%220%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22160%22%20height%3D%22160%22%20filter%3D%22url(%23n)%22%20opacity%3D%220.050%22%2F%3E%3C%2Fsvg%3E");
  --noise-06: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22160%22%20height%3D%22160%22%3E%3Cfilter%20id%3D%22n%22%20x%3D%220%22%20y%3D%220%22%20width%3D%22100%25%22%20height%3D%22100%25%22%3E%3CfeTurbulence%20type%3D%22fractalNoise%22%20baseFrequency%3D%220.85%22%20numOctaves%3D%223%22%20stitchTiles%3D%22stitch%22%2F%3E%3CfeColorMatrix%20type%3D%22saturate%22%20values%3D%220%22%2F%3E%3C%2Ffilter%3E%3Crect%20width%3D%22160%22%20height%3D%22160%22%20filter%3D%22url(%23n)%22%20opacity%3D%220.060%22%2F%3E%3C%2Fsvg%3E");

  /* --- status glyphs, baked once ----------------------------------------
     One glyph per warning tier, used as a mask so the shape takes the tier
     colour. They are three DIFFERENT shapes on purpose, not one shape in
     three colours: tone has to survive a monochrome display and the ~8 % of
     men with a red/green deficiency, for whom amber and red are the two
     hardest hues to tell apart. Triangle = check the output, circled i =
     just so you know, circled x = this cannot run as asked. */
  --glyph-warn: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20d%3D%22M12%201.8L.7%2021.4h22.6zm0%206.8l.9%207.4h-1.8zM12%2017.4a1.2%201.2%200%20110%202.4%201.2%201.2%200%20010-2.4z%22%2F%3E%3C%2Fsvg%3E");
  --glyph-info: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20d%3D%22M12%202a10%2010%200%20100%2020%2010%2010%200%20000-20zm0%204.3a1.45%201.45%200%20110%202.9%201.45%201.45%200%20010-2.9zm1.2%204.3V18h-2.4v-7.4z%22%2F%3E%3C%2Fsvg%3E");
  --glyph-danger: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20fill%3D%22%23000%22%20fill-rule%3D%22evenodd%22%20d%3D%22M12%202a10%2010%200%20100%2020%2010%2010%200%20000-20zm3.6%205.0L12%2010.6%208.4%207.0%207.0%208.4l3.6%203.6-3.6%203.6%201.4%201.4%203.6-3.6%203.6%203.6%201.4-1.4-3.6-3.6%203.6-3.6z%22%2F%3E%3C%2Fsvg%3E");

  /* --- flags, baked once (language pill) -------------------------------- */
  --flag-ru: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%209%206%22%3E%3Crect%20width%3D%229%22%20height%3D%226%22%20fill%3D%22%23ffffff%22%2F%3E%3Crect%20y%3D%222%22%20width%3D%229%22%20height%3D%224%22%20fill%3D%22%230039a6%22%2F%3E%3Crect%20y%3D%224%22%20width%3D%229%22%20height%3D%222%22%20fill%3D%22%23d52b1e%22%2F%3E%3C%2Fsvg%3E");
  --flag-en: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2060%2030%22%3E%3CclipPath%20id%3D%22c%22%3E%3Cpath%20d%3D%22M0%200h60v30H0z%22%2F%3E%3C%2FclipPath%3E%3Cg%20clip-path%3D%22url(%23c)%22%3E%3Cpath%20fill%3D%22%23012169%22%20d%3D%22M0%200h60v30H0z%22%2F%3E%3Cpath%20stroke%3D%22%23ffffff%22%20stroke-width%3D%226%22%20d%3D%22M0%200l60%2030m0-30L0%2030%22%2F%3E%3Cpath%20stroke%3D%22%23c8102e%22%20stroke-width%3D%224%22%20d%3D%22M0%200l60%2030m0-30L0%2030%22%2F%3E%3Cpath%20stroke%3D%22%23ffffff%22%20stroke-width%3D%2210%22%20d%3D%22M30%200v30M0%2015h60%22%2F%3E%3Cpath%20stroke%3D%22%23c8102e%22%20stroke-width%3D%226%22%20d%3D%22M30%200v30M0%2015h60%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
}

/* -------------------------------------------------------------------------
   2. Colour, dark first.
   The content layer is nearly black so the functional glass layer above it
   has something to be *lighter than*. Text colours are alpha-on-light so
   they stay legible whether they land on the scene or on a glass panel.
   ------------------------------------------------------------------------- */
:root {
  --bg-0: #05070c;              /* page floor, behind the scene */
  --bg-1: #0c1122;              /* nominal content plane */
  --bg-2: #111826;              /* raised, non-glass boxes */
  --bg-sunken: #03050a;         /* wells: code blocks, video letterbox */

  --text-1: #f3f7ff;
  --text-2: rgba(226, 234, 248, .74);
  --text-3: rgba(206, 217, 236, .52);
  --text-inverse: #05070c;

  --hairline: rgba(226, 234, 248, .11);
  --hairline-strong: rgba(226, 234, 248, .22);
  --scrim: rgba(3, 5, 10, .62);

  --ok: #46e0a8;
  --ok-bg: rgba(70, 224, 168, .13);
  --ok-rim: rgba(70, 224, 168, .34);
  --warn: #ffc75a;
  --warn-bg: rgba(255, 199, 90, .13);
  --warn-rim: rgba(255, 199, 90, .34);
  --danger: #ff7b8f;
  --danger-bg: rgba(255, 123, 143, .13);
  --danger-rim: rgba(255, 123, 143, .34);
  --info: #86d6ff;
  --info-bg: rgba(134, 214, 255, .12);
  --info-rim: rgba(134, 214, 255, .32);

  /* Selection + focus derive from the accent so every host feels tuned. */
  --focus-ring: rgba(var(--accent-rgb), .85);
  --focus-halo: rgba(var(--accent-rgb), .22);
  --selection-bg: rgba(var(--accent-rgb), .32);
}

/* -------------------------------------------------------------------------
   3. Accents.
   <html data-accent="..."> is emitted by tools/build.js, one per host.
   Each accent supplies:
     --accent        readable-on-dark hue for text, icons, rings
     --accent-deep   the saturated source hue, used for fills and glass tint
     --accent-rgb    channel triplet, for rgba(var(--accent-rgb), a)
     --accent-ink    text colour that sits on a solid --accent fill
     --scene-a/b/c   the three blobs of the background scene
   Indigo is also the fallback when the attribute is missing entirely.
   ------------------------------------------------------------------------- */
:root,
html[data-accent="indigo"] {
  --accent: #8a8aff;
  --accent-deep: #5b5bff;
  --accent-rgb: 138, 138, 255;
  --accent-ink: #070818;
  --scene-a: rgba(91, 91, 255, .62);
  --scene-b: rgba(168, 80, 255, .46);
  --scene-c: rgba(42, 160, 220, .40);
}
html[data-accent="teal"] {
  --accent: #43e3e3;
  --accent-deep: #2ad4d4;
  --accent-rgb: 67, 227, 227;
  --accent-ink: #04211f;
  --scene-a: rgba(42, 212, 212, .52);
  --scene-b: rgba(64, 118, 255, .44);
  --scene-c: rgba(150, 84, 240, .34);
}
html[data-accent="violet"] {
  --accent: #d489f7;
  --accent-deep: #bf5af2;
  --accent-rgb: 212, 137, 247;
  --accent-ink: #1c0827;
  --scene-a: rgba(191, 90, 242, .56);
  --scene-b: rgba(96, 112, 255, .44);
  --scene-c: rgba(255, 110, 165, .34);
}
html[data-accent="gunmetal"] {
  --accent: #b3c6dd;
  --accent-deep: #7f93ad;
  --accent-rgb: 179, 198, 221;
  --accent-ink: #0b1017;
  --scene-a: rgba(126, 156, 196, .46);
  --scene-b: rgba(66, 92, 134, .50);
  --scene-c: rgba(176, 190, 214, .30);
}
html[data-accent="midnight"] {
  --accent: #8fb4ff;
  --accent-deep: #4f7fd1;
  --accent-rgb: 143, 180, 255;
  --accent-ink: #04091a;
  --scene-a: rgba(72, 112, 205, .54);
  --scene-b: rgba(38, 58, 130, .54);
  --scene-c: rgba(124, 92, 214, .34);
}

/* -------------------------------------------------------------------------
   4. The scene.
   Glass is only visible because of what is behind it: with a flat backdrop
   the blur has nothing to smear and the refraction band has no gradient to
   bend. So the page ships its own light source - three large, very soft
   colour fields that drift on a minute-long cycle.

   Built from three pseudo-elements (two on <html>, one on <body>) so no
   markup is required. They are `position: fixed` and animate `transform`
   only, which stays on the compositor: no layout, no paint, no JS loop.

   The alphas below are not eyeballed. Compositing the exact layer stack on
   a canvas and sampling it gives, for indigo: blob centres at luminance
   62-70 with a chroma of ~109, and the middle of the page - where the text
   and the panels sit - still at luminance 18. That is the whole balance the
   scene has to strike: enough colour at the edges for a 34px blur to have
   something to smear, and a dark enough centre that body copy keeps its
   contrast.
   ------------------------------------------------------------------------- */
html {
  background-color: var(--bg-0);
  /* A static base wash under the moving blobs, so a repaint mid-animation
     never exposes bare black. */
  background-image:
    radial-gradient(120% 80% at 50% -10%, rgba(var(--accent-rgb), .16) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg-1) 0%, var(--bg-0) 55%, #04060c 100%);
  background-attachment: fixed;
}

/* far field: the two heavy blobs */
html::before,
html::after {
  content: "";
  position: fixed;
  inset: -30vmax;
  pointer-events: none;
  will-change: transform;
}

html::before {
  z-index: var(--z-scene-far);
  background-image:
    radial-gradient(38vmax 34vmax at 24% 26%, var(--scene-a) 0%, transparent 62%),
    radial-gradient(44vmax 40vmax at 78% 16%, var(--scene-b) 0%, transparent 60%);
  animation: scene-drift-a 54s var(--ease-scene) infinite alternate;
}

/* near field: the cooler third blob, screened so overlaps brighten rather
   than muddy, exactly like two coloured lights crossing. */
html::after {
  z-index: var(--z-scene-near);
  mix-blend-mode: screen;
  background-image:
    radial-gradient(46vmax 40vmax at 64% 88%, var(--scene-c) 0%, transparent 64%),
    radial-gradient(30vmax 30vmax at 10% 78%, rgba(var(--accent-rgb), .28) 0%, transparent 66%);
  animation: scene-drift-b 76s var(--ease-scene) infinite alternate;
}

/* grain + vignette: kills the banding that big soft gradients produce on
   8-bit displays and pushes the eye toward the centre of the page. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: var(--z-scene-grain);
  pointer-events: none;
  background-image:
    var(--noise-05),
    radial-gradient(135% 100% at 50% 0%, transparent 55%, rgba(0, 0, 0, .42) 100%);
  background-size: 160px 160px, auto;
}

@keyframes scene-drift-a {
  from { transform: translate3d(-2%, -1.5%, 0) scale(1.02) rotate(0deg); }
  to   { transform: translate3d(3.5%, 2.5%, 0) scale(1.14) rotate(7deg); }
}
@keyframes scene-drift-b {
  from { transform: translate3d(2.5%, 2%, 0) scale(1.10) rotate(0deg); }
  to   { transform: translate3d(-3%, -2.5%, 0) scale(1.00) rotate(-9deg); }
}

/* -------------------------------------------------------------------------
   5. Baked presets.
   Each block sets ONLY --lg-* custom properties, so it composes with .lg and
   with any layout class:  <div class="lg glass-onyx probe">.
   Nothing here touches border-radius directly; .lg reads --lg-radius.
   ------------------------------------------------------------------------- */

/* midnight - deepest structural panel; the widest blur of the set. */
.glass-midnight,
html[data-accent="midnight"] .glass-accent {
  --lg-blur: 36px;
  --lg-saturation: 128%;
  --lg-brightness: 88%;
  --lg-tint-top: rgba(20, 26, 36, 0.506);
  --lg-tint-bottom: rgba(20, 26, 36, 0.242);
  --lg-radius: 26px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(230, 237, 249, 0.580);
  --lg-rim-2: rgba(230, 237, 249, 0.052);
  --lg-rim-3: rgba(230, 237, 249, 0.319);
  --lg-inner-blur: 20px;
  --lg-inner-color: rgba(230, 237, 249, 0.200);
  --lg-inner-spread: -6px;
  --lg-shadow-y: 20px;
  --lg-shadow-blur: 50px;
  --lg-shadow-color: rgba(0, 0, 0, 0.42);
  --lg-spec: rgba(230, 237, 249, 0.140);
  --lg-noise: var(--noise-04);
}

/* onyx - the darkest, least saturated surface. Use where content must win:
   code blocks, the footer, dense read-only data. */
.glass-onyx,
.glass-code {
  --lg-blur: 24px;
  --lg-saturation: 104%;
  --lg-brightness: 76%;
  --lg-tint-top: rgba(11, 13, 16, 0.644);
  --lg-tint-bottom: rgba(11, 13, 16, 0.308);
  --lg-radius: 20px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(214, 220, 230, 0.440);
  --lg-rim-2: rgba(214, 220, 230, 0.040);
  --lg-rim-3: rgba(214, 220, 230, 0.242);
  --lg-inner-blur: 12px;
  --lg-inner-color: rgba(214, 220, 230, 0.140);
  --lg-inner-spread: -4px;
  --lg-shadow-y: 24px;
  --lg-shadow-blur: 58px;
  --lg-shadow-color: rgba(0, 0, 0, 0.50);
  --lg-spec: rgba(214, 220, 230, 0.140);
  --lg-noise: var(--noise-06);
}

/* spaceblack - neutral mid-dark; the default for form panels. */
.glass-spaceblack,
.glass-panel {
  --lg-blur: 30px;
  --lg-saturation: 110%;
  --lg-brightness: 82%;
  --lg-tint-top: rgba(18, 19, 22, 0.575);
  --lg-tint-bottom: rgba(18, 19, 22, 0.275);
  --lg-radius: 22px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(223, 229, 238, 0.500);
  --lg-rim-2: rgba(223, 229, 238, 0.045);
  --lg-rim-3: rgba(223, 229, 238, 0.275);
  --lg-inner-blur: 16px;
  --lg-inner-color: rgba(223, 229, 238, 0.160);
  --lg-inner-spread: -5px;
  --lg-shadow-y: 22px;
  --lg-shadow-blur: 54px;
  --lg-shadow-color: rgba(0, 0, 0, 0.46);
  --lg-spec: rgba(223, 229, 238, 0.140);
  --lg-noise: var(--noise-05);
}

/* charcoal - tighter corner, shallower shadow: reads as a *nested* card. */
.glass-charcoal {
  --lg-blur: 28px;
  --lg-saturation: 112%;
  --lg-brightness: 86%;
  --lg-tint-top: rgba(28, 31, 37, 0.529);
  --lg-tint-bottom: rgba(28, 31, 37, 0.253);
  --lg-radius: 18px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(232, 236, 242, 0.520);
  --lg-rim-2: rgba(232, 236, 242, 0.047);
  --lg-rim-3: rgba(232, 236, 242, 0.286);
  --lg-inner-blur: 14px;
  --lg-inner-color: rgba(232, 236, 242, 0.180);
  --lg-inner-spread: -4px;
  --lg-shadow-y: 16px;
  --lg-shadow-blur: 42px;
  --lg-shadow-color: rgba(0, 0, 0, 0.42);
  --lg-spec: rgba(232, 236, 242, 0.140);
  --lg-noise: var(--noise-06);
}

/* gunmetal - brightest rim of the neutrals (0.74) and an off-axis 130deg
   light. Use it when a neutral surface still has to feel "picked up". */
.glass-gunmetal,
html[data-accent="gunmetal"] .glass-accent {
  --lg-blur: 26px;
  --lg-saturation: 120%;
  --lg-brightness: 90%;
  --lg-tint-top: rgba(47, 53, 61, 0.460);
  --lg-tint-bottom: rgba(47, 53, 61, 0.220);
  --lg-radius: 20px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 130deg;
  --lg-rim-1: rgba(242, 245, 250, 0.740);
  --lg-rim-2: rgba(242, 245, 250, 0.067);
  --lg-rim-3: rgba(242, 245, 250, 0.407);
  --lg-inner-blur: 16px;
  --lg-inner-color: rgba(242, 245, 250, 0.240);
  --lg-inner-spread: -5px;
  --lg-shadow-y: 16px;
  --lg-shadow-blur: 40px;
  --lg-shadow-color: rgba(0, 0, 0, 0.40);
  --lg-spec: rgba(242, 245, 250, 0.140);
  --lg-noise: var(--noise-05);
}

/* slate - the lightest, most transparent neutral: big hero surfaces where
   the scene should still read clearly through the panel. */
.glass-slate,
.glass-card {
  --lg-blur: 34px;
  --lg-saturation: 124%;
  --lg-brightness: 92%;
  --lg-tint-top: rgba(43, 50, 61, 0.437);
  --lg-tint-bottom: rgba(43, 50, 61, 0.209);
  --lg-radius: 24px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(233, 238, 247, 0.600);
  --lg-rim-2: rgba(233, 238, 247, 0.054);
  --lg-rim-3: rgba(233, 238, 247, 0.330);
  --lg-inner-blur: 20px;
  --lg-inner-color: rgba(233, 238, 247, 0.220);
  --lg-inner-spread: -6px;
  --lg-shadow-y: 18px;
  --lg-shadow-blur: 46px;
  --lg-shadow-color: rgba(0, 0, 0, 0.38);
  --lg-spec: rgba(233, 238, 247, 0.140);
  --lg-noise: var(--noise-04);
}

/* --- the three chromatic presets ------------------------------------------
   Very high saturation (190-200%) with a thin tint: the colour comes mostly
   from over-saturating whatever is *behind* the glass, not from painting on
   top of it. That is what keeps them from looking like coloured plastic. */
.glass-indigo,
html[data-accent="indigo"] .glass-accent,
:root:not([data-accent]) .glass-accent {
  --lg-blur: 24px;
  --lg-saturation: 190%;
  --lg-brightness: 106%;
  --lg-tint-top: rgba(91, 91, 255, 0.299);
  --lg-tint-bottom: rgba(91, 91, 255, 0.143);
  --lg-radius: 28px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(255, 255, 255, 0.750);
  --lg-rim-2: rgba(255, 255, 255, 0.068);
  --lg-rim-3: rgba(255, 255, 255, 0.413);
  --lg-inner-blur: 20px;
  --lg-inner-color: rgba(255, 255, 255, 0.280);
  --lg-inner-spread: -6px;
  --lg-shadow-y: 18px;
  --lg-shadow-blur: 40px;
  --lg-shadow-color: rgba(0, 0, 0, 0.28);
  --lg-spec: rgba(255, 255, 255, 0.140);
  --lg-noise: var(--noise-04);
}

.glass-violet,
html[data-accent="violet"] .glass-accent {
  --lg-blur: 24px;
  --lg-saturation: 200%;
  --lg-brightness: 108%;
  --lg-tint-top: rgba(191, 90, 242, 0.299);
  --lg-tint-bottom: rgba(191, 90, 242, 0.143);
  --lg-radius: 28px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 125deg;
  --lg-rim-1: rgba(255, 255, 255, 0.750);
  --lg-rim-2: rgba(255, 255, 255, 0.068);
  --lg-rim-3: rgba(255, 255, 255, 0.413);
  --lg-inner-blur: 20px;
  --lg-inner-color: rgba(255, 255, 255, 0.280);
  --lg-inner-spread: -6px;
  --lg-shadow-y: 18px;
  --lg-shadow-blur: 40px;
  --lg-shadow-color: rgba(0, 0, 0, 0.28);
  --lg-spec: rgba(255, 255, 255, 0.140);
  --lg-noise: var(--noise-04);
}

.glass-teal,
html[data-accent="teal"] .glass-accent {
  --lg-blur: 24px;
  --lg-saturation: 198%;
  --lg-brightness: 108%;
  --lg-tint-top: rgba(42, 212, 212, 0.265);
  --lg-tint-bottom: rgba(42, 212, 212, 0.127);
  --lg-radius: 28px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(255, 255, 255, 0.750);
  --lg-rim-2: rgba(255, 255, 255, 0.068);
  --lg-rim-3: rgba(255, 255, 255, 0.413);
  --lg-inner-blur: 20px;
  --lg-inner-color: rgba(255, 255, 255, 0.280);
  --lg-inner-spread: -6px;
  --lg-shadow-y: 18px;
  --lg-shadow-blur: 40px;
  --lg-shadow-color: rgba(0, 0, 0, 0.28);
  --lg-spec: rgba(255, 255, 255, 0.140);
  --lg-noise: var(--noise-04);
}

/* button - a capsule of nearly clear glass. Small elements get a small
   blur (14px) because a wide blur on a 44px pill just samples itself. The
   rim runs at 0.90 so the capsule outline survives on any backdrop. */
.glass-button,
.glass-pill,
.glass-cta {
  --lg-blur: 14px;
  --lg-saturation: 180%;
  --lg-brightness: 110%;
  --lg-tint-top: rgba(255, 255, 255, 0.207);
  --lg-tint-bottom: rgba(255, 255, 255, 0.099);
  --lg-radius: 999px;
  --lg-rim-w: 1.2px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(255, 255, 255, 0.900);
  --lg-rim-2: rgba(255, 255, 255, 0.081);
  --lg-rim-3: rgba(255, 255, 255, 0.495);
  --lg-inner-blur: 8px;
  --lg-inner-color: rgba(255, 255, 255, 0.300);
  --lg-inner-spread: -2px;
  --lg-shadow-y: 6px;
  --lg-shadow-blur: 16px;
  --lg-shadow-color: rgba(0, 0, 0, 0.26);
  --lg-spec: rgba(255, 255, 255, 0.220);
  --lg-noise: var(--noise-04);
}

/* toolbar - the header. Thin rim (1px) and a modest shadow so a sticky bar
   floats without cutting a hard line across the page. */
.glass-toolbar,
.glass-bar {
  --lg-blur: 30px;
  --lg-saturation: 185%;
  --lg-brightness: 110%;
  --lg-tint-top: rgba(255, 255, 255, 0.207);
  --lg-tint-bottom: rgba(255, 255, 255, 0.099);
  --lg-radius: 20px;
  --lg-rim-w: 1px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(255, 255, 255, 0.600);
  --lg-rim-2: rgba(255, 255, 255, 0.054);
  --lg-rim-3: rgba(255, 255, 255, 0.330);
  --lg-inner-blur: 14px;
  --lg-inner-color: rgba(255, 255, 255, 0.280);
  --lg-inner-spread: -4px;
  --lg-shadow-y: 10px;
  --lg-shadow-blur: 26px;
  --lg-shadow-color: rgba(0, 0, 0, 0.24);
  --lg-spec: rgba(255, 255, 255, 0.140);
  --lg-noise: var(--noise-04);
}

/* hud - progress and overlays. A cold near-black tint (#0b0f1a) at high
   saturation: it darkens whatever is under it so white numerals stay
   readable while the panel is on top of a preview or a busy scene. */
.glass-hud {
  --lg-blur: 30px;
  --lg-saturation: 160%;
  --lg-brightness: 96%;
  --lg-tint-top: rgba(11, 15, 26, 0.437);
  --lg-tint-bottom: rgba(11, 15, 26, 0.209);
  --lg-radius: 26px;
  --lg-rim-w: 1.5px;
  --lg-rim-angle: 145deg;
  --lg-rim-1: rgba(255, 255, 255, 0.500);
  --lg-rim-2: rgba(255, 255, 255, 0.045);
  --lg-rim-3: rgba(255, 255, 255, 0.275);
  --lg-inner-blur: 20px;
  --lg-inner-color: rgba(255, 255, 255, 0.200);
  --lg-inner-spread: -6px;
  --lg-shadow-y: 18px;
  --lg-shadow-blur: 44px;
  --lg-shadow-color: rgba(0, 0, 0, 0.44);
  --lg-spec: rgba(255, 255, 255, 0.140);
  --lg-noise: var(--noise-05);
}

/* -------------------------------------------------------------------------
   6. Light appearance.
   Same material logic, inverted light source. In a bright room the glass is
   *lighter* than the content behind it and the rim has to go darker to be
   visible at all, so tints move to near-white and rim colours to slate.
   Brightness drops below 100% for the neutral presets: a light backdrop
   would otherwise blow out and the panel would vanish.
   ------------------------------------------------------------------------- */
[data-appearance="light"] {
  --bg-0: #eef1f8;
  --bg-1: #f6f8fc;
  --bg-2: #ffffff;
  --bg-sunken: #e7ebf4;

  --text-1: #0d1220;
  --text-2: rgba(20, 28, 45, .72);
  --text-3: rgba(28, 38, 58, .52);
  --text-inverse: #ffffff;

  --hairline: rgba(16, 24, 40, .12);
  --hairline-strong: rgba(16, 24, 40, .24);
  --scrim: rgba(238, 241, 248, .7);

  --ok: #0f8f62;
  --ok-bg: rgba(15, 143, 98, .12);
  --ok-rim: rgba(15, 143, 98, .34);
  --warn: #9a6a00;
  --warn-bg: rgba(154, 106, 0, .12);
  --warn-rim: rgba(154, 106, 0, .34);
  --danger: #c0304a;
  --danger-bg: rgba(192, 48, 74, .12);
  --danger-rim: rgba(192, 48, 74, .34);
  --info: #10618f;
  --info-bg: rgba(16, 97, 143, .12);
  --info-rim: rgba(16, 97, 143, .32);
}

/* Accent hues need to darken in light mode or they fail contrast on white.
   --accent-deep stays the same source hue for glass tints; only the text
   token and the ink flip. */
[data-appearance="light"] { --accent-ink: #ffffff; }
html[data-appearance="light"],
html[data-appearance="light"][data-accent="indigo"] { --accent: #4040e0; --accent-rgb: 64, 64, 224; }
html[data-appearance="light"][data-accent="teal"]      { --accent: #0e8f8f; --accent-rgb: 14, 143, 143; }
html[data-appearance="light"][data-accent="violet"]    { --accent: #8b2fc0; --accent-rgb: 139, 47, 192; }
html[data-appearance="light"][data-accent="gunmetal"]  { --accent: #3f556f; --accent-rgb: 63, 85, 111; }
html[data-appearance="light"][data-accent="midnight"]  { --accent: #2a4f9e; --accent-rgb: 42, 79, 158; }

/* The scene loses its heavy blobs and becomes a pale wash: the same three
   lights, one third the strength, over a near-white floor. */
html[data-appearance="light"] {
  background-image:
    radial-gradient(120% 80% at 50% -10%, rgba(var(--accent-rgb), .12) 0%, transparent 60%),
    linear-gradient(180deg, #ffffff 0%, var(--bg-0) 60%, #e4e9f4 100%);
}
/* The blob alphas are tuned for a near-black floor. On a near-white one the
   same lights would be poster paint, so they are scaled back hard and the
   near field switches to multiply: on light, colour has to be *subtracted*
   from white rather than added to black. */
html[data-appearance="light"]::before { opacity: .22; }
html[data-appearance="light"]::after  { opacity: .18; mix-blend-mode: multiply; }
[data-appearance="light"] body::before {
  background-image:
    var(--noise-04),
    radial-gradient(130% 95% at 50% 0%, transparent 45%, rgba(40, 55, 85, .14) 100%);
}

/* --- light preset overrides ---------------------------------------------
   Only the knobs that must move are re-declared; blur, radius, refraction
   and shadow geometry are appearance-independent. */
[data-appearance="light"] .glass-midnight,
html[data-appearance="light"][data-accent="midnight"] .glass-accent {
  --lg-brightness: 104%;
  --lg-tint-top: rgba(233, 238, 250, 0.660);
  --lg-tint-bottom: rgba(214, 224, 244, 0.380);
  --lg-rim-1: rgba(34, 48, 76, 0.300);
  --lg-rim-2: rgba(34, 48, 76, 0.030);
  --lg-rim-3: rgba(255, 255, 255, 0.800);
  --lg-inner-color: rgba(255, 255, 255, 0.700);
  --lg-shadow-color: rgba(24, 36, 62, 0.16);
  --lg-spec: rgba(255, 255, 255, 0.500);
}
[data-appearance="light"] .glass-onyx,
[data-appearance="light"] .glass-code {
  --lg-brightness: 102%;
  --lg-saturation: 130%;
  --lg-tint-top: rgba(226, 232, 244, 0.740);
  --lg-tint-bottom: rgba(208, 218, 236, 0.440);
  --lg-rim-1: rgba(28, 40, 64, 0.260);
  --lg-rim-2: rgba(28, 40, 64, 0.026);
  --lg-rim-3: rgba(255, 255, 255, 0.760);
  --lg-inner-color: rgba(255, 255, 255, 0.640);
  --lg-shadow-color: rgba(24, 36, 62, 0.18);
  --lg-spec: rgba(255, 255, 255, 0.460);
}
[data-appearance="light"] .glass-spaceblack,
[data-appearance="light"] .glass-panel {
  --lg-brightness: 104%;
  --lg-saturation: 140%;
  --lg-tint-top: rgba(240, 244, 252, 0.680);
  --lg-tint-bottom: rgba(222, 230, 245, 0.400);
  --lg-rim-1: rgba(30, 42, 68, 0.280);
  --lg-rim-2: rgba(30, 42, 68, 0.028);
  --lg-rim-3: rgba(255, 255, 255, 0.780);
  --lg-inner-color: rgba(255, 255, 255, 0.680);
  --lg-shadow-color: rgba(24, 36, 62, 0.15);
  --lg-spec: rgba(255, 255, 255, 0.500);
}
[data-appearance="light"] .glass-charcoal {
  --lg-brightness: 104%;
  --lg-saturation: 140%;
  --lg-tint-top: rgba(244, 247, 253, 0.640);
  --lg-tint-bottom: rgba(228, 235, 248, 0.360);
  --lg-rim-1: rgba(30, 42, 68, 0.240);
  --lg-rim-2: rgba(30, 42, 68, 0.024);
  --lg-rim-3: rgba(255, 255, 255, 0.760);
  --lg-inner-color: rgba(255, 255, 255, 0.660);
  --lg-shadow-color: rgba(24, 36, 62, 0.13);
  --lg-spec: rgba(255, 255, 255, 0.480);
}
[data-appearance="light"] .glass-gunmetal,
html[data-appearance="light"][data-accent="gunmetal"] .glass-accent {
  --lg-brightness: 106%;
  --lg-saturation: 150%;
  --lg-tint-top: rgba(226, 234, 246, 0.600);
  --lg-tint-bottom: rgba(206, 218, 236, 0.340);
  --lg-rim-1: rgba(36, 52, 78, 0.340);
  --lg-rim-2: rgba(36, 52, 78, 0.032);
  --lg-rim-3: rgba(255, 255, 255, 0.860);
  --lg-inner-color: rgba(255, 255, 255, 0.720);
  --lg-shadow-color: rgba(24, 36, 62, 0.14);
  --lg-spec: rgba(255, 255, 255, 0.520);
}
[data-appearance="light"] .glass-slate,
[data-appearance="light"] .glass-card {
  --lg-brightness: 106%;
  --lg-saturation: 150%;
  --lg-tint-top: rgba(248, 250, 255, 0.600);
  --lg-tint-bottom: rgba(230, 238, 250, 0.320);
  --lg-rim-1: rgba(32, 46, 72, 0.260);
  --lg-rim-2: rgba(32, 46, 72, 0.026);
  --lg-rim-3: rgba(255, 255, 255, 0.820);
  --lg-inner-color: rgba(255, 255, 255, 0.700);
  --lg-shadow-color: rgba(24, 36, 62, 0.12);
  --lg-spec: rgba(255, 255, 255, 0.520);
}
/* Chromatic presets keep their hue in light mode but drop saturation and
   lift the tint, otherwise they read as neon on a white page. */
[data-appearance="light"] .glass-indigo,
html[data-appearance="light"][data-accent="indigo"] .glass-accent,
html[data-appearance="light"]:not([data-accent]) .glass-accent {
  --lg-saturation: 150%;
  --lg-brightness: 102%;
  --lg-tint-top: rgba(91, 91, 255, 0.180);
  --lg-tint-bottom: rgba(91, 91, 255, 0.080);
  --lg-rim-1: rgba(48, 48, 150, 0.360);
  --lg-rim-2: rgba(48, 48, 150, 0.034);
  --lg-rim-3: rgba(255, 255, 255, 0.860);
  --lg-inner-color: rgba(255, 255, 255, 0.640);
  --lg-shadow-color: rgba(48, 48, 150, 0.18);
  --lg-spec: rgba(255, 255, 255, 0.520);
}
[data-appearance="light"] .glass-violet,
html[data-appearance="light"][data-accent="violet"] .glass-accent {
  --lg-saturation: 155%;
  --lg-brightness: 102%;
  --lg-tint-top: rgba(191, 90, 242, 0.180);
  --lg-tint-bottom: rgba(191, 90, 242, 0.080);
  --lg-rim-1: rgba(112, 34, 150, 0.360);
  --lg-rim-2: rgba(112, 34, 150, 0.034);
  --lg-rim-3: rgba(255, 255, 255, 0.860);
  --lg-inner-color: rgba(255, 255, 255, 0.640);
  --lg-shadow-color: rgba(112, 34, 150, 0.18);
  --lg-spec: rgba(255, 255, 255, 0.520);
}
[data-appearance="light"] .glass-teal,
html[data-appearance="light"][data-accent="teal"] .glass-accent {
  --lg-saturation: 155%;
  --lg-brightness: 102%;
  --lg-tint-top: rgba(42, 212, 212, 0.200);
  --lg-tint-bottom: rgba(42, 212, 212, 0.090);
  --lg-rim-1: rgba(10, 96, 96, 0.360);
  --lg-rim-2: rgba(10, 96, 96, 0.034);
  --lg-rim-3: rgba(255, 255, 255, 0.860);
  --lg-inner-color: rgba(255, 255, 255, 0.640);
  --lg-shadow-color: rgba(10, 96, 96, 0.18);
  --lg-spec: rgba(255, 255, 255, 0.520);
}
[data-appearance="light"] .glass-button,
[data-appearance="light"] .glass-pill,
[data-appearance="light"] .glass-cta {
  --lg-tint-top: rgba(255, 255, 255, 0.520);
  --lg-tint-bottom: rgba(255, 255, 255, 0.300);
  --lg-rim-1: rgba(28, 40, 64, 0.420);
  --lg-rim-2: rgba(28, 40, 64, 0.038);
  --lg-rim-3: rgba(255, 255, 255, 0.950);
  --lg-inner-color: rgba(255, 255, 255, 0.900);
  --lg-shadow-color: rgba(24, 36, 62, 0.16);
  --lg-spec: rgba(255, 255, 255, 0.700);
}
[data-appearance="light"] .glass-toolbar,
[data-appearance="light"] .glass-bar {
  --lg-tint-top: rgba(255, 255, 255, 0.560);
  --lg-tint-bottom: rgba(255, 255, 255, 0.320);
  --lg-rim-1: rgba(28, 40, 64, 0.300);
  --lg-rim-2: rgba(28, 40, 64, 0.028);
  --lg-rim-3: rgba(255, 255, 255, 0.940);
  --lg-inner-color: rgba(255, 255, 255, 0.880);
  --lg-shadow-color: rgba(24, 36, 62, 0.14);
  --lg-spec: rgba(255, 255, 255, 0.600);
}
[data-appearance="light"] .glass-hud {
  --lg-brightness: 104%;
  --lg-tint-top: rgba(236, 241, 251, 0.720);
  --lg-tint-bottom: rgba(218, 227, 244, 0.420);
  --lg-rim-1: rgba(28, 40, 64, 0.300);
  --lg-rim-2: rgba(28, 40, 64, 0.028);
  --lg-rim-3: rgba(255, 255, 255, 0.860);
  --lg-inner-color: rgba(255, 255, 255, 0.720);
  --lg-shadow-color: rgba(24, 36, 62, 0.20);
  --lg-spec: rgba(255, 255, 255, 0.520);
}

/* glass.css focuses .lg--live with a fixed blue outline. Re-point it at the
   host accent so the ring matches the rest of the page. */
.lg--live:focus-visible { outline-color: var(--focus-ring); }

/* -------------------------------------------------------------------------
   8. Semantic aliases.
   The template layer names surfaces by role rather than by material, so each
   role maps onto exactly one preset above and is declared in the same rule
   (CSS has no @extend, and a second block would drift the moment one of the
   two is retuned):
     .glass-bar   = .glass-toolbar     sticky header
     .glass-pill  = .glass-button      header toggles, radio chips
     .glass-cta   = .glass-button      primary action capsule
     .glass-panel = .glass-spaceblack  dropzone / options / progress / result
     .glass-card  = .glass-slate       feature, step and FAQ cards
     .glass-code  = .glass-onyx        command blocks on /local
   `.glass-accent` has no alias: it is resolved per host from <html data-accent>
   and must be used by name.
   ------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------
   9. Accessibility parity.
   theme.js mirrors these into body[data-*] so glass.js and glass.css agree
   with the media query; the media queries below are the no-JS fallback.
   ------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  /* The scene freezes on its first frame rather than disappearing: the
     glass still needs something to refract. */
  html::before,
  html::after {
    animation: none;
    transform: translate3d(0, 0, 0) scale(1.06);
  }
  *,
  *::before,
  *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

@media (prefers-reduced-transparency: reduce) {
  /* Reduced transparency is about not seeing THROUGH surfaces, not about
     removing colour from the page. glass.css already swaps every .lg::before
     for an opaque tint, so the panels stop being see-through on their own.
     The scene therefore stays: it is behind the content, never under text,
     and deleting it is what leaves the page looking broken rather than
     accessible. It only stops moving and drops to half strength, so nothing
     drifts under an opaque panel edge. */
  html::before,
  html::after {
    animation: none;
    transform: translate3d(0, 0, 0) scale(1.06);
    opacity: .5;
  }
}

@media (prefers-contrast: more) {
  :root {
    --text-2: rgba(236, 242, 253, .92);
    --text-3: rgba(226, 234, 248, .78);
    --hairline: rgba(236, 242, 253, .28);
    --hairline-strong: rgba(236, 242, 253, .45);
  }
  [data-appearance="light"] {
    --text-2: rgba(10, 16, 28, .95);
    --text-3: rgba(10, 16, 28, .8);
    --hairline: rgba(10, 16, 28, .3);
    --hairline-strong: rgba(10, 16, 28, .5);
  }
}
