/* ==========================================================================
   DULUS DESIGN SYSTEM — core.css  ·  "Liquid Glass" generation
   Single source of truth for tokens, reset, material, primitives, components.

   Canonical file: websites/shared/css/core.css
   Synced into each site by websites/sync.sh — never edit the copies.

   Zero dependencies. Zero build step. Works from file:// and from any CDN.

   ---------------------------------------------------------------------------
   THE MATERIAL

   Every raised surface on these sites is one material: `.glass`. It is not a
   blur rectangle. It models four physical properties, in this order:

     1. REFRACTION  the backdrop is bent, blurred and re-saturated as it passes
                    through the slab (`backdrop-filter`, optional SVG lens)
     2. THICKNESS   inset light on the top edge, inset shade on the bottom edge
     3. SPECULAR    a conic rim that catches a light source, plus a soft sheen
                    that tracks the pointer (`--lg-x` / `--lg-y`, set by core.js)
     4. ELEVATION   an ambient cast shadow that grows as the slab lifts

   Anything that needs to look raised gets `.glass`. Nothing re-implements it.

   ---------------------------------------------------------------------------
   PROGRESSIVE ENHANCEMENT CONTRACT

   The page is fully readable, fully navigable and fully styled with:
     · no JavaScript                 (`html` has no `.js` class → static reveal)
     · no backdrop-filter            (`@supports` → opaque surfaces)
     · no scroll-driven animation    (JS IntersectionObserver takes over)
     · no @property / color-mix      (fallback declarations precede every use)
     · reduced motion                (all animation collapses to 0.001ms)
     · reduced transparency          (all glass becomes solid, blur removed)
     · forced colors / high contrast (system colours win, decor is hidden)

   Nothing below is load-bearing for content. Glass is a finish, not a floor.
   ========================================================================== */

@layer reset, tokens, base, layout, type, material, components, patterns,
       motion, utilities, site;

/* ==========================================================================
   0 · REGISTERED CUSTOM PROPERTIES
   Typed properties are interpolatable. This is what lets a gradient angle, a
   specular position or a lift amount animate at all — untyped custom
   properties snap between values instead of tweening.
   ========================================================================== */

/* --lg-angle / --lg-x / --lg-y / --lg-sheen are read inside ::before and
   ::after. A pseudo-element inherits from its originating element, so a
   registered property declared `inherits: false` would resolve to its initial
   value there and the highlight would never move. They must inherit. Every
   component that uses them re-declares `--lg-sheen: 0` so the value cannot
   leak from a hovered card into the buttons nested inside it.

   --lg-lift and --flow are only ever read on the element itself, so those two
   stay non-inheriting and cost nothing to resolve. */

@property --lg-angle {
  syntax: "<angle>";
  inherits: true;
  initial-value: 135deg;
}
@property --lg-x {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}
@property --lg-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: -20%;
}
@property --lg-sheen {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}
@property --lg-lift {
  syntax: "<number>";
  inherits: false;
  initial-value: 0;
}
@property --flow {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 0%;
}

@layer tokens {
  /* ========================================================================
     1 · TOKENS
     ======================================================================== */

  :root {
    /* -- Brand. docs/BRAND_GUIDE.md is authoritative; these hexes are it. --- */
    --dulus-orange: #ff6b1f;
    --dulus-amber: #ff9f43;
    --dulus-gold: #ffc233;
    --dulus-black: #0a0a0b;
    --dulus-green: #00ffa3;
    --dulus-white: #e6e6e6;
    --dulus-yellow: #ffcc00;
    --dulus-red: #ff6b6b;
    --dulus-blue: #4dabf7;
    --dulus-dr-blue: #002d62;

    /* -- Per-site signal. Each site overrides these in its site.css. ------- */
    --accent: var(--dulus-orange);
    --accent-soft: var(--dulus-amber);
    --signal: var(--dulus-green);

    /* -- Type ------------------------------------------------------------- */
    --font-sans: "InterVariable", "Inter", -apple-system, BlinkMacSystemFont,
      "Segoe UI Variable Text", "Segoe UI", Roboto, "Helvetica Neue", Arial,
      sans-serif;
    --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono",
      Menlo, Consolas, "Liberation Mono", monospace;
    --font-display: var(--font-sans);

    /* Fluid scale, 320px → 1440px viewport. */
    --t-xs: 0.6875rem;
    --t-sm: 0.8125rem;
    --t-base: clamp(0.9375rem, 0.9rem + 0.15vw, 1rem);
    --t-md: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
    --t-lg: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
    --t-xl: clamp(1.375rem, 1.15rem + 1vw, 1.875rem);
    --t-2xl: clamp(1.75rem, 1.3rem + 2vw, 2.75rem);
    --t-3xl: clamp(2.25rem, 1.4rem + 3.6vw, 4rem);
    --t-4xl: clamp(2.75rem, 1.2rem + 6.4vw, 5.75rem);

    /* -- Space ------------------------------------------------------------ */
    --s-1: 4px;
    --s-2: 8px;
    --s-3: 12px;
    --s-4: 16px;
    --s-5: 24px;
    --s-6: 32px;
    --s-7: 48px;
    --s-8: 64px;
    --s-9: 96px;
    --s-10: 128px;
    --section-y: clamp(68px, 8.5vw, 136px);
    --gutter: clamp(20px, 4vw, 40px);
    --maxw: 1200px;
    --maxw-narrow: 760px;

    /* -- Radii. Superellipse-adjacent: large, soft, consistent. ------------ */
    --r-sm: 10px;
    --r-md: 14px;
    --r-lg: 22px;
    --r-xl: 30px;
    --r-2xl: 40px;
    --r-pill: 999px;
    --bw: 1px;

    /* -- Motion. One easing family, four durations. ------------------------ */
    --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-spring: linear(
      0, 0.006, 0.025 2.8%, 0.101 6.1%, 0.539 18.9%, 0.721 25.3%, 0.849 31.5%,
      0.937 38.1%, 0.968 41.8%, 0.991 45.7%, 1.006 50.1%, 1.015 55%, 1.017 63.9%,
      1.001 100%
    );
    --dur-1: 0.16s;
    --dur-2: 0.28s;
    --dur-3: 0.5s;
    --dur-4: 0.8s;

    /* -- Depth ------------------------------------------------------------ */
    --z-grain: 1;
    --z-nav: 100;
    --z-drawer: 200;
    --z-toast: 300;

    /* -- Glass material knobs. Themed below; components tune per instance. - */
    --glass-blur: 22px;
    --glass-sat: 175%;
    --glass-radius: var(--r-lg);

    /* Capsule height + its breathing room. Sites reuse this to reserve the
       matching top padding on their first section. */
    --nav-h: 80px;
  }

  /* ------------------------------------------------------------------------
     2 · THEMES
     `color-scheme` is declared so `light-dark()`, form controls and the native
     scrollbar all follow the attribute, not just the OS preference.
     ---------------------------------------------------------------------- */

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

    --bg: #070709;
    --bg-1: #0d0d11;
    --bg-2: #131319;
    --bg-3: #1b1b23;
    --ink: #f4f0ea;
    --ink-2: #b7b2be;
    --ink-3: #7e7a88;
    --ink-4: #55525e;
    --line: rgba(255, 255, 255, 0.08);
    --line-2: rgba(255, 255, 255, 0.16);

    /* Glass */
    --glass: rgba(19, 19, 25, 0.55);
    --glass-tint: rgba(255, 255, 255, 0.055);
    --glass-tint-hi: rgba(255, 255, 255, 0.085);
    --glass-edge: rgba(255, 255, 255, 0.22);
    --glass-edge-lo: rgba(255, 255, 255, 0.05);
    --glass-under: rgba(0, 0, 0, 0.5);
    --glass-sheen: rgba(255, 255, 255, 0.14);
    --glass-solid: #14141a; /* reduced-transparency + no-backdrop fallback */

    /* Surfaces that must follow the theme instead of being pinned dark.
       --hero-wash  top colour of a hero's vertical gradient
       --sunken     a well recessed *into* the page (code sums, diagrams)
       --accent-ink accent used as text; the raw accent is only ~2.6:1 on the
                    light background, which fails for the small mono labels */
    --hero-wash: #050506;
    --sunken: rgba(0, 0, 0, 0.28);
    --accent-ink: var(--accent);
    --gold-ink: var(--dulus-gold);
    --signal-ink: var(--signal);
    --green-ink: var(--dulus-green);
    --warm-hi: #fff2bd;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.55);
    --shadow-2: 0 10px 30px -12px rgba(0, 0, 0, 0.75);
    --shadow-3: 0 30px 80px -24px rgba(0, 0, 0, 0.85);
    --glow: 0 0 0 1px rgba(255, 107, 31, 0.28),
      0 14px 44px -14px rgba(255, 107, 31, 0.45);

    /* Ambient field */
    --mesh-1: rgba(255, 107, 31, 0.2);
    --mesh-2: rgba(0, 255, 163, 0.09);
    --mesh-3: rgba(77, 171, 247, 0.08);
    --grain-opacity: 0.03;
    --spot-strength: 0.06;
  }

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

    --bg: #f7f6f3;
    --bg-1: #ffffff;
    --bg-2: #f1efeb;
    --bg-3: #e7e4dd;
    --ink: #111017;
    --ink-2: #474450;
    --ink-3: #6d6a77;
    --ink-4: #9a97a3;
    --line: rgba(12, 11, 16, 0.1);
    --line-2: rgba(12, 11, 16, 0.18);

    --glass: rgba(255, 255, 255, 0.6);
    --glass-tint: rgba(255, 255, 255, 0.5);
    --glass-tint-hi: rgba(255, 255, 255, 0.72);
    --glass-edge: rgba(255, 255, 255, 0.95);
    --glass-edge-lo: rgba(12, 11, 16, 0.08);
    --glass-under: rgba(12, 11, 16, 0.1);
    --glass-sheen: rgba(255, 255, 255, 0.75);
    --glass-solid: #ffffff;

    --hero-wash: #eceae4;
    --sunken: rgba(12, 11, 16, 0.05);
    --accent-ink: color-mix(in oklab, var(--accent) 74%, #2a0f00);
    --gold-ink: color-mix(in oklab, var(--dulus-gold) 62%, #33230a);
    --signal-ink: color-mix(in oklab, var(--signal) 58%, #04231a);
    --green-ink: color-mix(in oklab, var(--dulus-green) 52%, #032b1c);
    --warm-hi: color-mix(in oklab, var(--accent) 58%, #2a0f00);

    --shadow-1: 0 1px 2px rgba(17, 16, 23, 0.06);
    --shadow-2: 0 10px 30px -14px rgba(17, 16, 23, 0.18);
    --shadow-3: 0 30px 80px -30px rgba(17, 16, 23, 0.24);
    --glow: 0 0 0 1px rgba(255, 107, 31, 0.3),
      0 14px 44px -16px rgba(255, 107, 31, 0.35);

    --mesh-1: rgba(255, 107, 31, 0.16);
    --mesh-2: rgba(0, 150, 96, 0.08);
    --mesh-3: rgba(77, 171, 247, 0.1);
    --grain-opacity: 0.02;
    --spot-strength: 0.05;
  }

  /* Every glass surface in this file and in all three site.css files paints
     `linear-gradient(--glass-tint, …), var(--glass)`. Making --glass opaque
     here is therefore the single switch that turns the whole ecosystem solid
     when the engine cannot blur — a translucent surface with no blur behind it
     is unreadable, which is worse than no effect at all. */
  @supports not (
    (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))
  ) {
    :root,
    [data-theme="dark"],
    [data-theme="light"] {
      --glass: var(--glass-solid);
    }
    .drawer {
      background: var(--bg) !important;
    }
  }
}

@layer reset {
  /* ========================================================================
     3 · RESET
     ======================================================================== */

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

  html {
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: 108px;
    /* Lets height/width animate to and from `auto` in supporting engines. */
    interpolate-size: allow-keywords;
  }

  body {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-sans);
    font-size: var(--t-base);
    line-height: 1.65;
    font-optical-sizing: auto;
    font-synthesis-weight: none;
    font-feature-settings: "kern" 1, "liga" 1, "calt" 1, "ss03" 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: clip;
    min-height: 100svh;
  }

  img,
  svg,
  video,
  canvas {
    display: block;
    max-width: 100%;
    height: auto;
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  button,
  input,
  select,
  textarea {
    font: inherit;
    color: inherit;
    background: none;
    border: 0;
    field-sizing: content;
  }

  button {
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  ul,
  ol {
    list-style: none;
  }

  h1,
  h2,
  h3,
  h4 {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: -0.03em;
    line-height: 1.04;
    text-wrap: balance;
  }

  p {
    text-wrap: pretty;
  }

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

  ::selection {
    background: var(--accent);
    color: #12100e;
  }

  :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: var(--r-sm);
  }

  /* Standard first, WebKit shim second — Firefox and Safari both get a thumb. */
  * {
    scrollbar-width: thin;
    scrollbar-color: var(--bg-3) transparent;
  }
  ::-webkit-scrollbar {
    width: 10px;
    height: 10px;
  }
  ::-webkit-scrollbar-track {
    background: transparent;
  }
  ::-webkit-scrollbar-thumb {
    background: var(--bg-3);
    border-radius: var(--r-pill);
    border: 2px solid transparent;
    background-clip: padding-box;
  }
  ::-webkit-scrollbar-thumb:hover {
    background: var(--accent);
    background-clip: padding-box;
  }
}

@layer layout {
  /* ========================================================================
     4 · LAYOUT PRIMITIVES
     ======================================================================== */

  .container {
    width: 100%;
    max-width: var(--maxw);
    margin-inline: auto;
    padding-inline: var(--gutter);
  }
  .container--narrow {
    max-width: var(--maxw-narrow);
  }
  .container--wide {
    max-width: 1400px;
  }

  /* Deliberately no `content-visibility: auto` here. These pages are one
     screenful of markup each and are navigated almost entirely by in-page
     anchor (#router, #precios, #token …). Skipping offscreen layout makes the
     estimated scroll height wrong on first paint, so an anchor lands in the
     wrong place and then jumps once the real sections render. Correct anchors
     are worth more than the paint saving on a document this size. */
  .section {
    position: relative;
    padding-block: var(--section-y);
  }
  .section--tight {
    padding-block: clamp(40px, 5vw, 76px);
  }
  .section--hairline {
    border-top: var(--bw) solid var(--line);
  }
  .section--panel {
    background:
      radial-gradient(
        130% 100% at 50% 0%,
        color-mix(in oklab, var(--accent) 6%, transparent) 0%,
        transparent 62%
      ),
      var(--bg-1);
    border-block: var(--bw) solid var(--line);
  }

  .grid {
    display: grid;
    gap: var(--s-5);
  }
  .grid-2 {
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  }
  .grid-3 {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  }
  .grid-4 {
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  }

  .stack {
    display: grid;
    gap: var(--s-4);
  }
  .stack-sm {
    display: grid;
    gap: var(--s-2);
  }
  .stack-lg {
    display: grid;
    gap: var(--s-6);
  }

  .row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-3);
  }

  .split {
    display: grid;
    gap: clamp(32px, 5vw, 72px);
    align-items: center;
    grid-template-columns: 1fr;
  }
  @media (min-width: 900px) {
    .split {
      grid-template-columns: 1.05fr 1fr;
    }
    .split--reverse > :first-child {
      order: 2;
    }
  }

  .center {
    text-align: center;
  }
  .center-x {
    margin-inline: auto;
  }

  /* Grid and flex children default to min-width:auto, which lets code blocks,
     tables and long model names force a viewport wider than the screen. */
  .grid > *,
  .split > *,
  .terminal,
  .panel,
  .table-wrap {
    min-width: 0;
    max-width: 100%;
  }
}

@layer type {
  /* ========================================================================
     5 · TYPOGRAPHY
     ======================================================================== */

  .kicker {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent-ink);
  }
  .kicker::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 0 3px rgba(255, 107, 31, 0.18);
    box-shadow: 0 0 0 3px color-mix(in oklab, currentColor 22%, transparent);
  }
  .kicker--plain::before {
    display: none;
  }

  .h1 {
    font-size: var(--t-4xl);
  }
  .h2 {
    font-size: var(--t-3xl);
  }
  .h3 {
    font-size: var(--t-2xl);
  }
  .h4 {
    font-size: var(--t-xl);
  }

  .lede {
    font-size: var(--t-md);
    line-height: 1.62;
    color: var(--ink-2);
    max-width: 62ch;
  }

  .muted {
    color: var(--ink-2);
  }
  .dim {
    color: var(--ink-3);
  }
  .mono {
    font-family: var(--font-mono);
  }
  .nowrap {
    white-space: nowrap;
  }
  .tabular {
    font-variant-numeric: tabular-nums;
  }
  .accent {
    color: var(--accent-ink);
  }
  .signal {
    color: var(--signal-ink);
  }

  /* Two brand warms plus a highlight, interpolated in oklab.
     Deliberately not accent → signal: on dulus.online those are gold and blue,
     near-complementary, and a gradient between them passes straight through
     grey — the middle of the headline went colourless. Staying inside the warm
     pair also keeps the "at most two accent colours" rule in the brand guide.
     Animated only where --flow is registered; a static gradient elsewhere. */
  .gradient-text {
    background: linear-gradient(
      100deg in oklab,
      var(--accent) 0%,
      var(--accent-soft) 52%,
      color-mix(in oklab, var(--accent-soft) 45%, white) 100%
    );
    background-size: 220% 100%;
    background-position: var(--flow) 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    animation: dulus-flow 14s var(--ease) infinite alternate;
  }

  .underline-accent {
    position: relative;
    white-space: nowrap;
  }
  .underline-accent::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0.04em;
    height: 0.16em;
    border-radius: 2px;
    background: linear-gradient(
      90deg,
      var(--accent),
      color-mix(in oklab, var(--accent) 30%, transparent)
    );
    opacity: 0.42;
  }

  .section-head {
    display: grid;
    gap: var(--s-3);
    max-width: 68ch;
    margin-bottom: clamp(32px, 4vw, 56px);
  }
  .section-head--center {
    justify-items: center;
    text-align: center;
    margin-inline: auto;
  }
}

@layer material {
  /* ========================================================================
     6 · THE LIQUID GLASS MATERIAL
     One class. Everything raised uses it. Tune per instance with the knobs.
     ======================================================================== */

  .glass {
    --glass-blur: 22px;
    --glass-sat: 175%;
    --glass-fill: var(--glass-tint);
    --glass-rim: var(--glass-edge);
    --lg-sheen: 0;

    position: relative;
    isolation: isolate;
    border-radius: var(--glass-radius);
    /* Opaque first: any engine without backdrop-filter still gets a surface. */
    background: var(--glass-solid);
    background: linear-gradient(
        var(--glass-fill),
        color-mix(in oklab, var(--glass-fill) 45%, transparent)
      ),
      var(--glass);
    box-shadow:
      /* thickness: light hits the top edge, shade collects on the bottom */
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 -1px 0 0 var(--glass-edge-lo),
      inset 0 0 0 1px var(--glass-edge-lo),
      /* elevation */ 0 calc(6px + var(--lg-lift) * 10px)
        calc(24px + var(--lg-lift) * 26px) calc(-10px - var(--lg-lift) * 4px)
        var(--glass-under);
    transform: translate3d(0, calc(var(--lg-lift) * -3px), 0);
    transition:
      transform var(--dur-2) var(--ease),
      box-shadow var(--dur-2) var(--ease),
      background var(--dur-2) var(--ease),
      --lg-lift var(--dur-2) var(--ease);
  }

  /* Refraction + re-saturation of whatever is behind the slab. */
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .glass {
      background: linear-gradient(
          var(--glass-fill),
          color-mix(in oklab, var(--glass-fill) 45%, transparent)
        ),
        var(--glass);
      -webkit-backdrop-filter: blur(var(--glass-blur))
        saturate(var(--glass-sat));
      backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat));
    }
  }

  /* Specular rim. A conic sweep clipped to a 1px border ring — the edge
     brightens where the light source is and falls off around the curve. */
  .glass::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    padding: 1px;
    background: conic-gradient(
      from var(--lg-angle),
      transparent 0deg,
      var(--glass-rim) 42deg,
      transparent 122deg,
      transparent 216deg,
      color-mix(in oklab, var(--glass-rim) 55%, transparent) 268deg,
      transparent 350deg
    );
    -webkit-mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: 0.9;
    pointer-events: none;
    transition: opacity var(--dur-2) var(--ease);
  }

  /* Sheen. Follows the pointer via --lg-x / --lg-y, which core.js writes.
     plus-lighter keeps it additive so it reads as light, not as white paint. */
  .glass::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: radial-gradient(
      120% 90% at var(--lg-x) var(--lg-y),
      var(--glass-sheen) 0%,
      transparent 58%
    );
    opacity: var(--lg-sheen);
    mix-blend-mode: plus-lighter;
    pointer-events: none;
    transition: opacity var(--dur-3) var(--ease);
  }

  /* Interactive slabs lift and catch more light. */
  .glass--lift {
    cursor: default;
  }
  .glass--lift:hover,
  .glass--lift:focus-within {
    --lg-lift: 1;
    --lg-sheen: 1;
    --glass-fill: var(--glass-tint-hi);
  }
  .glass--lift:hover::before,
  .glass--lift:focus-within::before {
    opacity: 1;
  }

  /* Variants */
  .glass--thin {
    --glass-blur: 12px;
    --glass-sat: 150%;
  }
  .glass--thick {
    --glass-blur: 40px;
    --glass-sat: 200%;
  }
  .glass--flat {
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
  }
  .glass--accent {
    --glass-rim: color-mix(in oklab, var(--accent) 70%, var(--glass-edge));
    --glass-fill: color-mix(in oklab, var(--accent) 9%, var(--glass-tint));
  }
  .glass--signal {
    --glass-rim: color-mix(in oklab, var(--signal) 60%, var(--glass-edge));
    --glass-fill: color-mix(in oklab, var(--signal) 7%, var(--glass-tint));
  }

  /* True lensing. core.js injects the SVG filter and sets data-lens="on" only
     where `backdrop-filter: url()` is actually supported, so no engine ever
     renders an unresolved filter reference (which would blank the backdrop). */
  [data-lens="on"] .glass--lens {
    -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat))
      url("#dulus-lens");
    backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-sat))
      url("#dulus-lens");
  }

  /* ---- Accessibility overrides for the material ------------------------- */

  /* Users who ask for less transparency get solid, legible surfaces. This is
     deliberately universal: the three site.css files each add their own glass
     surfaces, and enumerating them here would silently miss the next one. */
  @media (prefers-reduced-transparency: reduce) {
    *,
    *::before,
    *::after {
      -webkit-backdrop-filter: none !important;
      backdrop-filter: none !important;
    }
    .glass,
    .card,
    .panel,
    .nav[data-stuck="true"] .nav__inner {
      background: var(--glass-solid) !important;
    }
    .drawer {
      background: var(--bg) !important;
    }
    .glass::after,
    .card::after,
    .spotlight {
      display: none;
    }
  }

  /* Windows High Contrast / forced-colors: drop decoration, keep structure. */
  @media (forced-colors: active) {
    .glass {
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
      background: Canvas;
      border: 1px solid CanvasText;
      box-shadow: none;
    }
    .glass::before,
    .glass::after,
    .mesh,
    .grain,
    .grid-lines,
    .spotlight {
      display: none;
    }
  }
}

@layer components {
  /* ========================================================================
     7 · BUTTONS
     ======================================================================== */

  .btn {
    --btn-ink: var(--ink);
    --btn-rim: var(--glass-edge);
    --btn-fill: var(--glass-tint);
    --lg-sheen: 0;

    position: relative;
    isolation: isolate;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: 13px 22px;
    border-radius: var(--r-pill);
    color: var(--btn-ink);
    font-size: var(--t-sm);
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
    overflow: hidden;
    background: var(--bg-2);
    background: linear-gradient(
        var(--btn-fill),
        color-mix(in oklab, var(--btn-fill) 40%, transparent)
      ),
      var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--btn-rim),
      inset 0 0 0 1px var(--glass-edge-lo),
      0 6px 18px -10px var(--glass-under);
    transition:
      transform var(--dur-1) var(--ease),
      box-shadow var(--dur-2) var(--ease),
      background var(--dur-2) var(--ease),
      color var(--dur-2) var(--ease);
  }

  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .btn {
      -webkit-backdrop-filter: blur(14px) saturate(165%);
      backdrop-filter: blur(14px) saturate(165%);
    }
  }

  /* Liquid fill: a light wipe that runs across the face on hover. */
  .btn::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: radial-gradient(
      90% 140% at var(--lg-x) 120%,
      var(--glass-sheen) 0%,
      transparent 62%
    );
    opacity: 0;
    mix-blend-mode: plus-lighter;
    transition: opacity var(--dur-2) var(--ease);
  }

  .btn:hover {
    transform: translateY(-1px);
  }
  .btn:hover::after {
    opacity: 1;
  }
  .btn:active {
    transform: translateY(0) scale(0.985);
  }

  .btn--primary {
    --btn-ink: #12100e;
    --btn-rim: rgba(255, 255, 255, 0.45);
    font-weight: 700;
    background: linear-gradient(
      168deg,
      color-mix(in oklab, var(--accent-soft) 62%, white 6%) 0%,
      var(--accent) 52%,
      color-mix(in oklab, var(--accent) 82%, black) 100%
    );
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.45),
      inset 0 -1px 0 0 rgba(0, 0, 0, 0.22),
      0 12px 32px -14px rgba(255, 107, 31, 0.85);
  }
  .btn--primary:hover {
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.55),
      inset 0 -1px 0 0 rgba(0, 0, 0, 0.22),
      0 18px 44px -16px rgba(255, 107, 31, 0.95);
  }

  .btn--ghost {
    --btn-fill: transparent;
  }
  .btn--ghost:hover {
    --btn-fill: var(--glass-tint);
    --btn-rim: color-mix(in oklab, var(--accent) 55%, var(--glass-edge));
  }

  .btn--quiet {
    --btn-ink: var(--ink-2);
    --btn-fill: transparent;
    padding-inline: 12px;
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
  }
  .btn--quiet:hover {
    --btn-ink: var(--ink);
    background: var(--glass-tint);
  }

  .btn--lg {
    padding: 16px 30px;
    font-size: var(--t-base);
  }
  .btn--sm {
    padding: 9px 16px;
    font-size: var(--t-xs);
  }
  .btn--block {
    width: 100%;
  }

  .btn__arrow {
    transition: transform var(--dur-2) var(--ease-spring);
  }
  .btn:hover .btn__arrow {
    transform: translateX(4px);
  }

  /* ========================================================================
     8 · PILLS, CHIPS
     ======================================================================== */

  .pill {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: 5px 12px;
    border-radius: var(--r-pill);
    background: var(--bg-2);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-2);
    white-space: nowrap;
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .pill {
      -webkit-backdrop-filter: blur(12px) saturate(160%);
      backdrop-filter: blur(12px) saturate(160%);
    }
  }

  .pill--accent {
    color: var(--accent-ink);
    background: color-mix(in oklab, var(--accent) 12%, transparent);
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.16),
      inset 0 0 0 1px color-mix(in oklab, var(--accent) 38%, transparent);
  }
  .pill--signal {
    color: var(--signal-ink);
    background: color-mix(in oklab, var(--signal) 10%, transparent);
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.14),
      inset 0 0 0 1px color-mix(in oklab, var(--signal) 36%, transparent);
  }
  .pill--live {
    color: var(--signal-ink);
  }
  .pill--live::before {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: currentColor;
    animation: dulus-pulse 2s var(--ease) infinite;
  }

  .chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 13px;
    border-radius: var(--r-sm);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    color: var(--ink-2);
    transition:
      color var(--dur-2) var(--ease),
      transform var(--dur-1) var(--ease),
      box-shadow var(--dur-2) var(--ease);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .chip {
      -webkit-backdrop-filter: blur(12px) saturate(160%);
      backdrop-filter: blur(12px) saturate(160%);
    }
  }
  .chip:hover {
    color: var(--ink);
    transform: translateY(-2px);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px color-mix(in oklab, var(--accent) 45%, transparent),
      0 10px 24px -14px var(--glass-under);
  }

  /* ========================================================================
     9 · CARDS + PANELS
     ======================================================================== */

  .card {
    /* Cards respond to the space they are given, not to the viewport. */
    container-type: inline-size;
    container-name: card;
    --lg-sheen: 0;

    position: relative;
    isolation: isolate;
    display: flex;
    flex-direction: column;
    gap: var(--s-3);
    padding: clamp(20px, 2.4vw, 30px);
    border-radius: var(--r-lg);
    background: var(--bg-1);
    background: linear-gradient(
        var(--glass-tint),
        color-mix(in oklab, var(--glass-tint) 40%, transparent)
      ),
      var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 -1px 0 0 var(--glass-edge-lo),
      inset 0 0 0 1px var(--glass-edge-lo),
      0 calc(6px + var(--lg-lift) * 12px) calc(24px + var(--lg-lift) * 30px)
        -12px var(--glass-under);
    transform: translate3d(0, calc(var(--lg-lift) * -4px), 0);
    transition:
      transform var(--dur-2) var(--ease),
      box-shadow var(--dur-2) var(--ease),
      background var(--dur-2) var(--ease),
      --lg-lift var(--dur-2) var(--ease);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .card {
      -webkit-backdrop-filter: blur(20px) saturate(170%);
      backdrop-filter: blur(20px) saturate(170%);
    }
  }

  .card::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: radial-gradient(
      110% 80% at var(--lg-x) var(--lg-y),
      var(--glass-sheen) 0%,
      transparent 56%
    );
    opacity: var(--lg-sheen);
    mix-blend-mode: plus-lighter;
    pointer-events: none;
    transition: opacity var(--dur-3) var(--ease);
  }

  .card--hover:hover,
  .card--hover:focus-within {
    --lg-lift: 1;
    --lg-sheen: 1;
  }

  .card--feature {
    background: radial-gradient(
        130% 100% at 0% 0%,
        color-mix(in oklab, var(--accent) 12%, transparent) 0%,
        transparent 58%
      ),
      linear-gradient(var(--glass-tint), transparent), var(--glass);
  }

  .card--flush {
    padding: 0;
    overflow: hidden;
  }

  .card__icon {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    border-radius: var(--r-md);
    background: linear-gradient(
        160deg,
        color-mix(in oklab, var(--accent) 24%, transparent),
        transparent 70%
      ),
      var(--bg-2);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
    color: var(--accent-ink);
    font-family: var(--font-mono);
    font-size: var(--t-sm);
    font-weight: 700;
    flex: 0 0 auto;
  }

  .card__title {
    font-size: var(--t-lg);
    font-weight: 700;
    letter-spacing: -0.02em;
  }

  .card__body {
    font-size: var(--t-sm);
    line-height: 1.62;
    color: var(--ink-2);
    margin: 0;
  }

  .card__foot {
    margin-top: auto;
    padding-top: var(--s-3);
    border-top: var(--bw) solid var(--line);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    color: var(--ink-3);
  }

  /* Container query: a card that gets real width earns a wider title. */
  @container card (min-width: 420px) {
    .card__title {
      font-size: var(--t-xl);
    }
  }

  .panel {
    position: relative;
    isolation: isolate;
    border-radius: var(--r-xl);
    background: var(--bg-1);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo),
      var(--shadow-3);
    overflow: hidden;
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .panel {
      -webkit-backdrop-filter: blur(26px) saturate(180%);
      backdrop-filter: blur(26px) saturate(180%);
    }
  }

  .panel__bar {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: 13px 18px;
    border-bottom: var(--bw) solid var(--line);
    background: var(--glass-tint);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    color: var(--ink-3);
  }

  .panel__dots {
    display: flex;
    gap: 6px;
    flex: 0 0 auto;
  }
  .panel__dots i {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--bg-3);
    display: block;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
  }
  .panel__dots i:first-child {
    background: #ff5f57;
  }
  .panel__dots i:nth-child(2) {
    background: #febc2e;
  }
  .panel__dots i:nth-child(3) {
    background: #28c840;
  }

  .panel__body {
    padding: clamp(16px, 2vw, 26px);
  }

  /* ========================================================================
     10 · STATS
     ======================================================================== */

  .stats {
    display: grid;
    gap: 1px;
    border-radius: var(--r-lg);
    overflow: hidden;
    background: var(--line);
    box-shadow: inset 0 0 0 1px var(--glass-edge-lo);
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  }

  .stat {
    padding: clamp(16px, 2vw, 26px);
    background: var(--bg-1);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    display: grid;
    gap: 4px;
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .stat {
      -webkit-backdrop-filter: blur(18px) saturate(165%);
      backdrop-filter: blur(18px) saturate(165%);
    }
  }

  .stat__num {
    font-family: var(--font-display);
    font-size: var(--t-2xl);
    font-weight: 700;
    letter-spacing: -0.035em;
    line-height: 1;
    font-variant-numeric: tabular-nums;
  }
  .stat__label {
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-3);
  }
  .stat__note {
    font-size: var(--t-xs);
    color: var(--ink-4);
  }

  /* ========================================================================
     11 · NAV — a floating glass capsule, not a bar
     ======================================================================== */

  .nav {
    position: sticky;
    top: 0;
    z-index: var(--z-nav);
    padding-block: 10px;
    view-transition-name: dulus-nav;
  }

  /* The capsule floats over the first section rather than sitting on a band of
     its own. Without this pull-up the hero's light field — mesh, grid lines,
     gradient — is clipped at the nav's lower edge and draws a hard seam across
     the top of the page. Each site adds `var(--nav-h)` back as top padding on
     its first section, so the layout is unchanged and only the backdrop moves. */
  .nav + main,
  .nav + [data-drawer] + main {
    margin-top: calc(-1 * var(--nav-h));
  }

  .nav__inner {
    display: flex;
    align-items: center;
    gap: var(--s-4);
    height: 60px;
    min-width: 0;
    padding-inline: var(--s-3);
    border-radius: var(--r-pill);
    background: transparent;
    box-shadow: none;
    transition:
      background var(--dur-3) var(--ease),
      box-shadow var(--dur-3) var(--ease),
      padding var(--dur-3) var(--ease);
  }

  .nav[data-stuck="true"] .nav__inner {
    background: var(--glass-solid);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo),
      0 18px 48px -22px var(--glass-under);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .nav[data-stuck="true"] .nav__inner {
      -webkit-backdrop-filter: blur(26px) saturate(185%);
      backdrop-filter: blur(26px) saturate(185%);
    }
  }

  .brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    flex: 0 0 auto;
    font-weight: 700;
    letter-spacing: -0.025em;
    font-size: var(--t-md);
  }
  /* A view-transition-name must be unique in the document. `.brand` is also
     used in the drawer header and in the footer, so only the one in the nav
     capsule may claim the name — duplicates make the browser skip the
     transition entirely. */
  .nav__inner > .brand {
    view-transition-name: dulus-brand;
  }
  .brand img {
    width: 30px;
    height: 30px;
    object-fit: contain;
    filter: drop-shadow(0 0 14px rgba(255, 107, 31, 0.45));
  }
  .brand__sub {
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-3);
    padding-left: 10px;
    margin-left: 2px;
    border-left: var(--bw) solid var(--line);
  }

  .nav__links {
    display: none;
    align-items: center;
    gap: 2px;
    margin-inline: auto;
  }

  .nav__link {
    position: relative;
    padding: 8px 13px;
    border-radius: var(--r-pill);
    font-size: var(--t-sm);
    font-weight: 500;
    color: var(--ink-2);
    transition:
      color var(--dur-1) var(--ease),
      background var(--dur-2) var(--ease);
  }
  .nav__link:hover {
    color: var(--ink);
    background: var(--glass-tint);
  }
  .nav__link[aria-current="true"] {
    color: var(--ink);
  }
  /* The active pill is one shared element that slides between links. */
  .nav__link[aria-current="true"]::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: color-mix(in oklab, var(--accent) 16%, transparent);
    box-shadow: inset 0 0 0 1px
      color-mix(in oklab, var(--accent) 34%, transparent);
    view-transition-name: dulus-navpill;
  }

  .nav__actions {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    margin-left: auto;
    min-width: 0;
  }

  @media (max-width: 719px) {
    .nav__actions > .btn {
      display: none;
    }
  }
  @media (min-width: 1040px) {
    .nav__links {
      display: flex;
    }
    .nav__actions {
      margin-left: 0;
    }
  }

  .icon-btn {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: var(--r-pill);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
    color: var(--ink-2);
    transition:
      color var(--dur-1) var(--ease),
      transform var(--dur-1) var(--ease-spring),
      box-shadow var(--dur-2) var(--ease);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .icon-btn {
      -webkit-backdrop-filter: blur(14px) saturate(160%);
      backdrop-filter: blur(14px) saturate(160%);
    }
  }
  .icon-btn:hover {
    color: var(--ink);
    transform: scale(1.06);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--line-2),
      0 8px 20px -12px var(--glass-under);
  }
  .icon-btn:active {
    transform: scale(0.96);
  }
  /* The theme toggle rotates its icon rather than swapping it. */
  [data-theme-toggle] svg {
    transition: transform var(--dur-3) var(--ease-spring);
  }
  [data-theme-toggle][aria-pressed="true"] svg {
    transform: rotate(-140deg);
  }

  .lang-switch {
    position: relative;
    display: inline-flex;
    padding: 3px;
    border-radius: var(--r-pill);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .lang-switch {
      -webkit-backdrop-filter: blur(14px) saturate(160%);
      backdrop-filter: blur(14px) saturate(160%);
    }
  }
  .lang-switch button {
    position: relative;
    padding: 5px 12px;
    border-radius: var(--r-pill);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    font-weight: 600;
    letter-spacing: 0.08em;
    color: var(--ink-3);
    transition: color var(--dur-2) var(--ease);
  }
  .lang-switch button[aria-pressed="true"] {
    color: #12100e;
  }
  /* One travelling knob, shared between the two buttons. */
  .lang-switch button[aria-pressed="true"]::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit;
    background: linear-gradient(
      165deg,
      color-mix(in oklab, var(--accent-soft) 55%, white 5%),
      var(--accent)
    );
    box-shadow: 0 4px 12px -6px rgba(255, 107, 31, 0.9);
    view-transition-name: dulus-langknob;
  }

  .nav__burger {
    display: grid;
  }
  @media (min-width: 1040px) {
    .nav__burger {
      display: none;
    }
  }

  /* ---- Mobile drawer ---------------------------------------------------- */

  .drawer {
    position: fixed;
    inset: 0;
    z-index: var(--z-drawer);
    display: grid;
    grid-template-rows: auto 1fr;
    background: color-mix(in oklab, var(--bg) 72%, transparent);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity var(--dur-3) var(--ease-out),
      visibility var(--dur-3);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .drawer {
      -webkit-backdrop-filter: blur(30px) saturate(180%);
      backdrop-filter: blur(30px) saturate(180%);
    }
  }
  .drawer[data-open="true"] {
    opacity: 1;
    visibility: visible;
  }
  .drawer__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 80px;
    padding-inline: var(--gutter);
    border-bottom: var(--bw) solid var(--line);
  }
  .drawer__body {
    padding: var(--s-6) var(--gutter) var(--s-8);
    display: grid;
    gap: var(--s-1);
    align-content: start;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .drawer__body a {
    padding: 15px 4px;
    border-bottom: var(--bw) solid var(--line);
    font-size: var(--t-lg);
    font-weight: 600;
    transform: translateY(12px);
    opacity: 0;
    transition:
      transform var(--dur-3) var(--ease-out),
      opacity var(--dur-3) var(--ease-out),
      color var(--dur-1) var(--ease);
  }
  .drawer__body a:hover {
    color: var(--accent-ink);
  }
  .drawer[data-open="true"] .drawer__body a {
    transform: none;
    opacity: 1;
  }
  /* CSS-only stagger. sibling-index() removes the need for nth-child rules or
     a JS delay loop; engines without it just animate everything together. */
  @supports (transition-delay: calc(sibling-index() * 1ms)) {
    .drawer[data-open="true"] .drawer__body a {
      transition-delay: calc(sibling-index() * 45ms);
    }
  }
  .drawer__cta {
    display: grid;
    gap: var(--s-3);
    margin-top: var(--s-5);
  }

  /* ========================================================================
     12 · TERMINAL / CODE
     ======================================================================== */

  .terminal {
    position: relative;
    border-radius: var(--r-lg);
    background: #060608;
    overflow: hidden;
    font-family: var(--font-mono);
    font-size: var(--t-sm);
    box-shadow:
      inset 0 1px 0 0 rgba(255, 255, 255, 0.09),
      inset 0 0 0 1px rgba(255, 255, 255, 0.06),
      var(--shadow-3);
  }
  [data-theme="light"] .terminal {
    background: #0a0a0d;
    color: #e9e5df;
  }

  .terminal__bar {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: 11px 15px;
    border-bottom: var(--bw) solid rgba(255, 255, 255, 0.07);
    background: rgba(255, 255, 255, 0.035);
    color: rgba(255, 255, 255, 0.42);
    font-size: var(--t-xs);
  }

  .terminal__body {
    padding: 17px;
    display: grid;
    gap: 6px;
    color: #dcd7d0;
    line-height: 1.7;
    min-height: 0;
    overflow-x: auto;
  }

  .terminal__line {
    white-space: pre-wrap;
    word-break: break-word;
  }
  .terminal__prompt {
    color: var(--accent);
  }
  .terminal__ok {
    color: var(--dulus-green);
  }
  .terminal__warn {
    color: var(--dulus-yellow);
  }
  .terminal__err {
    color: var(--dulus-red);
  }
  .terminal__dim {
    color: rgba(255, 255, 255, 0.4);
  }

  .caret {
    display: inline-block;
    width: 8px;
    height: 1.05em;
    vertical-align: text-bottom;
    background: var(--accent);
    box-shadow: 0 0 10px rgba(255, 107, 31, 0.8);
    animation: dulus-blink 1.05s steps(2, start) infinite;
  }

  .copy-row {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: 9px 9px 9px 18px;
    border-radius: var(--r-pill);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
    font-family: var(--font-mono);
    font-size: var(--t-sm);
    max-width: max-content;
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .copy-row {
      -webkit-backdrop-filter: blur(16px) saturate(165%);
      backdrop-filter: blur(16px) saturate(165%);
    }
  }
  .copy-row code {
    color: var(--ink);
  }
  .copy-row .accent {
    color: var(--accent-ink);
  }

  .copy-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 13px;
    border-radius: var(--r-pill);
    background: var(--glass-tint);
    box-shadow: inset 0 0 0 1px var(--glass-edge-lo);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-2);
    transition:
      color var(--dur-1) var(--ease),
      box-shadow var(--dur-2) var(--ease);
  }
  .copy-btn:hover {
    color: var(--accent-ink);
    box-shadow: inset 0 0 0 1px
      color-mix(in oklab, var(--accent) 55%, transparent);
  }
  .copy-btn[data-copied="true"] {
    color: var(--signal-ink);
    box-shadow: inset 0 0 0 1px
      color-mix(in oklab, var(--signal) 55%, transparent);
  }

  /* ========================================================================
     13 · TABLES + LISTS
     ======================================================================== */

  .table-wrap {
    overflow-x: auto;
    border-radius: var(--r-lg);
    background: linear-gradient(var(--glass-tint), transparent), var(--glass);
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo);
  }
  @supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
    .table-wrap {
      -webkit-backdrop-filter: blur(20px) saturate(170%);
      backdrop-filter: blur(20px) saturate(170%);
    }
  }

  table.dulus {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--t-sm);
    min-width: 560px;
  }
  table.dulus th,
  table.dulus td {
    padding: 15px 19px;
    text-align: left;
    border-bottom: var(--bw) solid var(--line);
    vertical-align: top;
  }
  table.dulus thead th {
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ink-3);
    font-weight: 500;
    background: var(--glass-tint);
    white-space: nowrap;
    position: sticky;
    top: 0;
  }
  table.dulus tbody tr:last-child td {
    border-bottom: 0;
  }
  table.dulus tbody tr:hover {
    background: var(--glass-tint);
  }
  table.dulus td.is-yes {
    color: var(--signal-ink);
    font-weight: 600;
  }
  table.dulus td.is-no {
    color: var(--ink-4);
  }

  .ticks {
    display: grid;
    gap: 11px;
  }

  /* Hanging indent, deliberately NOT `display: grid` on the <li>.
     Every tick in these pages is written as mixed inline content —
     `<li><strong>Lead.</strong> body copy with <code>a token</code> in it.</li>`
     — and a grid container turns each element *and each run of bare text*
     into its own grid item. Against `18px 1fr` that stacks the sentence into
     a ~60px column, one word per line. Absolute positioning keeps the marker
     out of flow and leaves the sentence as a single inline run. */
  .ticks li {
    position: relative;
    padding-left: 28px;
    font-size: var(--t-sm);
    color: var(--ink-2);
    line-height: 1.6;
  }
  .ticks li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.3em;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    box-shadow: inset 0 0 0 1px
      color-mix(in oklab, var(--signal) 55%, transparent);
    background:
      linear-gradient(var(--signal), var(--signal)) center / 6px 2px no-repeat,
      color-mix(in oklab, var(--signal) 14%, transparent);
  }
  .ticks li strong {
    color: var(--ink);
    font-weight: 600;
  }
  .ticks--dash li::before {
    box-shadow: inset 0 0 0 1px var(--line-2);
    background: linear-gradient(var(--ink-4), var(--ink-4)) center / 7px 1px
      no-repeat, transparent;
  }

  /* ========================================================================
     14 · FAQ / DETAILS
     ======================================================================== */

  .faq {
    display: grid;
    gap: 0;
    border-top: var(--bw) solid var(--line);
  }
  .faq details {
    border-bottom: var(--bw) solid var(--line);
  }
  .faq summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    padding: 21px 4px;
    cursor: pointer;
    font-size: var(--t-md);
    font-weight: 600;
    list-style: none;
    transition: color var(--dur-1) var(--ease);
  }
  .faq summary::-webkit-details-marker {
    display: none;
  }
  .faq summary:hover {
    color: var(--accent-ink);
  }
  .faq summary::after {
    content: "+";
    font-family: var(--font-mono);
    font-size: var(--t-lg);
    color: var(--accent-ink);
    flex: 0 0 auto;
    transition: transform var(--dur-3) var(--ease-spring);
  }
  .faq details[open] summary::after {
    transform: rotate(135deg);
  }
  .faq details > div {
    padding: 0 4px 24px;
    max-width: 78ch;
    font-size: var(--t-sm);
    line-height: 1.7;
    color: var(--ink-2);
  }
  .faq details > div p + p {
    margin-top: 12px;
  }

  /* Native open/close animation. ::details-content plus interpolate-size is
     what makes a <details> element expand smoothly with no JS at all. */
  @supports selector(::details-content) {
    .faq details::details-content {
      block-size: 0;
      overflow: clip;
      opacity: 0;
      transition:
        block-size var(--dur-3) var(--ease-out),
        content-visibility var(--dur-3) allow-discrete,
        opacity var(--dur-2) var(--ease);
    }
    .faq details[open]::details-content {
      block-size: auto;
      opacity: 1;
    }
  }

  /* ========================================================================
     15 · LOGO STRIP / MARQUEE
     ======================================================================== */

  .logo-strip {
    display: flex;
    align-items: center;
    gap: clamp(28px, 5vw, 64px);
    flex-wrap: wrap;
    justify-content: center;
  }
  .logo-strip span {
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-3);
    transition: color var(--dur-2) var(--ease);
  }
  .logo-strip span:hover {
    color: var(--ink);
  }

  .marquee {
    overflow: hidden;
    mask-image: linear-gradient(
      90deg,
      transparent,
      #000 8%,
      #000 92%,
      transparent
    );
    -webkit-mask-image: linear-gradient(
      90deg,
      transparent,
      #000 8%,
      #000 92%,
      transparent
    );
  }
  .marquee__track {
    display: flex;
    gap: var(--s-4);
    width: max-content;
    animation: dulus-marquee 42s linear infinite;
  }
  .marquee:hover .marquee__track {
    animation-play-state: paused;
  }

  /* ========================================================================
     16 · FOOTER
     ======================================================================== */

  .footer {
    position: relative;
    border-top: var(--bw) solid var(--line);
    background: linear-gradient(
      to bottom,
      transparent,
      color-mix(in oklab, var(--bg-1) 70%, transparent)
    );
    padding-block: clamp(48px, 6vw, 88px) var(--s-6);
  }

  .footer__grid {
    display: grid;
    gap: clamp(32px, 4vw, 56px);
    grid-template-columns: 1fr;
  }
  @media (min-width: 720px) {
    .footer__grid {
      grid-template-columns: 1.4fr repeat(3, 1fr);
    }
  }

  .footer__col h4 {
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    font-weight: 500;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ink-3);
    margin-bottom: var(--s-4);
  }
  .footer__col ul {
    display: grid;
    gap: 10px;
  }
  .footer__col a {
    font-size: var(--t-sm);
    color: var(--ink-2);
    transition:
      color var(--dur-1) var(--ease),
      padding-left var(--dur-2) var(--ease);
  }
  .footer__col a:hover {
    color: var(--accent-ink);
    padding-left: 4px;
  }

  .footer__bottom {
    margin-top: clamp(40px, 5vw, 64px);
    padding-top: var(--s-5);
    border-top: var(--bw) solid var(--line);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    color: var(--ink-4);
  }
  .footer__legal {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-4);
  }
}

@layer patterns {
  /* ========================================================================
     17 · AMBIENT FIELD
     The page sits inside a slow-moving light field. Everything glass refracts
     it, which is what makes the material read as glass instead of as a blur.
     ======================================================================== */

  .mesh {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 0;
    contain: strict;
  }
  .mesh::before,
  .mesh::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    filter: blur(90px);
    will-change: transform;
  }
  .mesh::before {
    width: 62vw;
    height: 62vw;
    max-width: 820px;
    max-height: 820px;
    top: -24%;
    right: -12%;
    background: var(--mesh-1);
    animation: dulus-drift-a 34s var(--ease) infinite alternate;
  }
  .mesh::after {
    width: 46vw;
    height: 46vw;
    max-width: 600px;
    max-height: 600px;
    bottom: -28%;
    left: -10%;
    background: var(--mesh-2);
    animation: dulus-drift-b 28s var(--ease) infinite alternate;
  }
  /* A third, cooler light source gives the glass something to disagree with. */
  .mesh--aurora::before {
    background:
      radial-gradient(circle at 30% 30%, var(--mesh-1), transparent 60%),
      radial-gradient(circle at 70% 60%, var(--mesh-3), transparent 62%);
  }

  .grid-lines {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background-image: linear-gradient(
        to right,
        var(--line) 1px,
        transparent 1px
      ),
      linear-gradient(to bottom, var(--line) 1px, transparent 1px);
    background-size: 76px 76px;
    mask-image: radial-gradient(120% 90% at 50% 0%, #000 0%, transparent 72%);
    -webkit-mask-image: radial-gradient(
      120% 90% at 50% 0%,
      #000 0%,
      transparent 72%
    );
    opacity: 0.6;
  }

  .grain {
    position: fixed;
    inset: 0;
    z-index: var(--z-grain);
    pointer-events: none;
    opacity: var(--grain-opacity);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
  }

  /* Page-wide pointer light. core.js writes --spot-x / --spot-y in px. */
  .spotlight {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background: radial-gradient(
      560px circle at var(--spot-x, 50vw) var(--spot-y, 30vh),
      var(--accent),
      transparent 70%
    );
    opacity: var(--spot-strength);
    transition: opacity var(--dur-4) var(--ease);
  }
  @media (hover: none) {
    .spotlight {
      display: none;
    }
  }

  /* Reading-progress line. Pure CSS where scroll timelines exist. */
  .progress {
    position: fixed;
    inset: 0 0 auto 0;
    height: 2px;
    z-index: calc(var(--z-nav) + 1);
    transform-origin: 0 50%;
    transform: scaleX(0);
    background: linear-gradient(90deg, var(--accent), var(--signal));
    pointer-events: none;
  }
  @supports (animation-timeline: scroll()) {
    .progress {
      animation: dulus-progress linear both;
      animation-timeline: scroll(root block);
    }
  }

  .hairline {
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--line-2), transparent);
    border: 0;
  }

  /* Legacy hook, kept so existing markup keeps its accent edge. */
  .glow-wrap {
    position: relative;
  }
  .glow-wrap::before {
    content: "";
    position: absolute;
    inset: -1px;
    border-radius: inherit;
    padding: 1px;
    background: linear-gradient(
      140deg,
      color-mix(in oklab, var(--accent) 60%, transparent),
      transparent 46%
    );
    -webkit-mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    mask:
      linear-gradient(#000 0 0) content-box,
      linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
  }

  /* ========================================================================
     18 · POPOVER TOOLTIP
     Native top-layer popover, positioned by CSS anchor positioning. No JS,
     no z-index fights, no clipping by an overflow ancestor.
     ======================================================================== */

  [popovertarget] {
    anchor-name: --dulus-anchor;
  }

  .tip {
    position: absolute;
    margin: 0;
    padding: 9px 13px;
    max-width: 30ch;
    border: 0;
    border-radius: var(--r-sm);
    background: var(--glass-solid);
    color: var(--ink);
    font-family: var(--font-mono);
    font-size: var(--t-xs);
    line-height: 1.5;
    box-shadow:
      inset 0 1px 0 0 var(--glass-edge),
      inset 0 0 0 1px var(--glass-edge-lo),
      var(--shadow-2);
    opacity: 0;
    transition:
      opacity var(--dur-2) var(--ease),
      translate var(--dur-2) var(--ease-out),
      overlay var(--dur-2) allow-discrete,
      display var(--dur-2) allow-discrete;
    translate: 0 6px;
  }
  .tip:popover-open {
    opacity: 1;
    translate: 0 0;
  }
  @starting-style {
    .tip:popover-open {
      opacity: 0;
      translate: 0 6px;
    }
  }
  @supports (anchor-name: --a) {
    .tip {
      position-anchor: --dulus-anchor;
      inset: auto;
      top: anchor(bottom);
      justify-self: anchor-center;
      margin-top: 8px;
      position-try-fallbacks: flip-block;
    }
  }
}

@layer motion {
  /* ========================================================================
     19 · SCROLL REVEAL

     This is deliberately NOT a scroll-driven CSS animation, even though the
     engines these pages target all support `animation-timeline: view()`.

     A view timeline holds its before-phase state whenever its current time is
     unresolved or still negative, and `.reveal` starts at opacity 0 — so any
     moment the timeline has not resolved against the scroller, the content is
     simply gone. Loading straight into a deep link (dulus.ai/#precios) is one
     such moment: measured here, every `.reveal` card rendered at opacity 0.

     An IntersectionObserver cannot fail that way. It only ever *adds* `.is-in`
     and then unobserves, so a revealed element can never be un-revealed, and
     with no JS at all the base rule leaves everything visible. Reveal is
     decoration; decoration must not be able to delete the page.

     Scroll-driven CSS is still used below for `.progress`, where the worst
     case is a bar that does not move.
     ======================================================================== */

  .reveal {
    opacity: 1;
    transform: none;
  }

  html.js .reveal {
    opacity: 0;
    transform: translateY(20px) scale(0.985);
    transition:
      opacity var(--dur-4) var(--ease-out),
      transform var(--dur-4) var(--ease-out);
    transition-delay: var(--reveal-delay, 0ms);
  }
  html.js .reveal.is-in {
    opacity: 1;
    transform: none;
  }

  /* ========================================================================
     20 · VIEW TRANSITIONS
     ======================================================================== */

  @view-transition {
    navigation: auto;
  }

  ::view-transition-old(root) {
    animation: dulus-vt-out 0.22s var(--ease) both;
  }
  ::view-transition-new(root) {
    animation: dulus-vt-in 0.34s var(--ease-out) both;
  }
  ::view-transition-group(dulus-nav),
  ::view-transition-group(dulus-brand),
  ::view-transition-group(dulus-navpill),
  ::view-transition-group(dulus-langknob) {
    animation-duration: 0.34s;
    animation-timing-function: var(--ease-spring);
  }

  /* ========================================================================
     21 · KEYFRAMES
     ======================================================================== */

  @keyframes dulus-blink {
    0%,
    100% {
      opacity: 1;
    }
    50% {
      opacity: 0;
    }
  }

  @keyframes dulus-pulse {
    0% {
      box-shadow: 0 0 0 0 currentColor;
      opacity: 1;
    }
    70% {
      box-shadow: 0 0 0 7px transparent;
      opacity: 0.75;
    }
    100% {
      box-shadow: 0 0 0 0 transparent;
      opacity: 1;
    }
  }

  @keyframes dulus-marquee {
    from {
      transform: translateX(0);
    }
    to {
      transform: translateX(-50%);
    }
  }

  @keyframes dulus-float {
    0%,
    100% {
      transform: translateY(0) rotate(0deg);
    }
    50% {
      transform: translateY(-14px) rotate(-1.2deg);
    }
  }

  @keyframes dulus-sweep {
    0% {
      transform: translateX(-120%);
    }
    100% {
      transform: translateX(320%);
    }
  }

  @keyframes dulus-flow {
    from {
      --flow: 0%;
    }
    to {
      --flow: 100%;
    }
  }

  @keyframes dulus-progress {
    from {
      transform: scaleX(0);
    }
    to {
      transform: scaleX(1);
    }
  }

  @keyframes dulus-drift-a {
    from {
      transform: translate3d(0, 0, 0) scale(1);
    }
    to {
      transform: translate3d(-6%, 5%, 0) scale(1.12);
    }
  }

  @keyframes dulus-drift-b {
    from {
      transform: translate3d(0, 0, 0) scale(1.08);
    }
    to {
      transform: translate3d(7%, -6%, 0) scale(1);
    }
  }

  @keyframes dulus-vt-out {
    to {
      opacity: 0;
    }
  }

  @keyframes dulus-vt-in {
    from {
      opacity: 0;
      transform: translateY(8px);
    }
  }
}

@layer utilities {
  /* ========================================================================
     22 · UTILITIES + A11Y
     ======================================================================== */

  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  .skip-link {
    position: absolute;
    left: 50%;
    top: -100px;
    transform: translateX(-50%);
    z-index: var(--z-toast);
    padding: 12px 22px;
    border-radius: 0 0 var(--r-md) var(--r-md);
    background: var(--accent);
    color: #12100e;
    font-weight: 700;
    font-size: var(--t-sm);
    transition: top var(--dur-2) var(--ease);
  }
  .skip-link:focus {
    top: 0;
  }

  .relative {
    position: relative;
    z-index: 1;
  }
  .hide-sm {
    display: none;
  }
  @media (min-width: 720px) {
    .hide-sm {
      display: revert;
    }
    .only-sm {
      display: none;
    }
  }

  .table-wrap {
    overflow-x: auto;
  }

  /* ========================================================================
     23 · MOTION + PRINT
     ======================================================================== */

  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto;
    }
    *,
    *::before,
    *::after {
      animation-duration: 0.001ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.001ms !important;
      scroll-behavior: auto !important;
    }
    html.js .reveal {
      opacity: 1;
      transform: none;
      animation: none;
    }
    .mesh::before,
    .mesh::after {
      animation: none;
    }
    ::view-transition-old(root),
    ::view-transition-new(root) {
      animation: none;
    }
    /* A scroll-driven animation ignores animation-duration, so the blanket
       0.001ms above cannot neutralise the progress bar. Remove it instead. */
    .progress {
      display: none;
    }
  }

  @media print {
    .nav,
    .drawer,
    .grain,
    .mesh,
    .grid-lines,
    .spotlight,
    .progress {
      display: none !important;
    }
    body {
      background: #fff;
      color: #000;
    }
    .glass,
    .card,
    .panel {
      -webkit-backdrop-filter: none;
      backdrop-filter: none;
      background: #fff;
      box-shadow: none;
      border: 1px solid #ddd;
    }
    .section {
      content-visibility: visible;
    }
  }
}
