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

  /* Neutralise the UA stylesheet for [popover]. PositionController promotes
     floating panels to the top layer, and the UA rules for a popover include
     a solid border, padding, a canvas background and inset:0/margin:auto —
     enough to inflate a measured panel by 14px and to paint a border no
     component asked for. :where() keeps this at zero specificity so it beats
     the UA origin but loses to every rule a component writes for itself. */
  :where([popover]) {
    border: 0;
    padding: 0;
    margin: 0;
    inset: auto;
    width: auto;
    height: auto;
    background: none;
    color: inherit;
    overflow: visible;
  }

  :host {
    transition: opacity var(--transition-fast);

    
    /* Generated from shared/tokens.js by scripts/generate/host-tokens.js. */
    /* Do not edit by hand — edit the token tree instead. */

    --font-body: var(--font-body-family, 'Host Grotesk'), var(--font-body-fallback, system-ui, sans-serif);
    --font-label: var(--font-label-family, 'Tomorrow'), var(--font-label-fallback, system-ui, -apple-system, Segoe UI, sans-serif);
    --font-mono: var(--font-mono-family, 'JetBrains Mono'), var(--font-mono-fallback, ui-monospace, monospace);
    --font-quote: var(--font-quote-family, Georgia), var(--font-quote-fallback, serif);
    --font-display: var(--font-display-family, var(--font-body-family, 'Host Grotesk')), var(--font-display-fallback, var(--font-body-fallback, system-ui, sans-serif));
    --font-accent: var(--font-label);

    /* Private mirrors: components read these, consumers override --text-*. */
    --_text-xs: var(--text-xs, 12px);
    --_text-sm: var(--text-sm, 16px);
    --_text-md: var(--text-md, 17px);
    --_text-lg: var(--text-lg, clamp(18px, 1.5vw, 20px));
    --_text-xl: var(--text-xl, clamp(22px, 2.5vw, 26px));
    --_text-2xl: var(--text-2xl, clamp(28px, 3vw, 36px));
    --_text-3xl: var(--text-3xl, clamp(36px, 5vw, 52px));

    --display-xl-size: var(--_text-3xl);
    --display-xl-weight: var(--font-display-weight, 500);
    --display-xl-spacing: -1px;
    --heading-size: var(--_text-xl);
    --heading-weight: var(--font-display-weight, 500);
    --heading-lh: 1.2;
    --body-size: var(--_text-md);
    --body-weight: var(--font-body-weight, 500);
    --body-lh: 1.7;
    --wordmark-size: clamp(20px, 2.5vw, 28px);
    --wordmark-weight: var(--font-display-weight, 500);
    --wordmark-spacing: clamp(8px, 1.2vw, 14px);
    --section-title-size: var(--_text-xs);
    --section-title-weight: var(--font-label-weight, 600);
    --section-title-spacing: 2px;
    --ui-accent-size: 16px;
    --ui-accent-weight: var(--font-label-weight, 600);
    --ui-accent-spacing: 0.5px;
    --code-size: 14px;
    --code-lh: 1.8;
    --label-inline-size: 10px;
    --label-inline-spacing: 0.75px;

    /* Spacing */
    --space-xs: 4px;
    --space-sm: 8px;
    --space-md: 16px;
    --space-lg: 24px;
    --space-xl: 40px;
    --space-2xl: 64px;
    --space-3xl: 96px;
    --space-4xl: 128px;

    /* Radii */
    --radius-xs: 2px;
    --radius-sm: 4px;
    --radius-md: 10px;
    --radius-lg: 14px;
    --radius-xl: 20px;
    --radius-full: 9999px;

    /* Transitions and motion */
    --transition-fast: var(--duration-fast) var(--ease-standard);
    --transition-base: var(--duration-base) var(--ease-standard);
    --transition-slow: var(--duration-slow) var(--ease-standard);
    --transition-enter: var(--duration-enter) var(--ease-out);
    --transition-exit: var(--duration-exit) var(--ease-in);
    --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
    --duration-fast: 120ms;
    --duration-base: 200ms;
    --duration-slow: 400ms;
    --duration-enter: 500ms;
    --duration-exit: 300ms;
    --ease-out-expo: var(--ease-out);
    --ease-in-out: var(--ease-standard);

    /* Z-index */
    --z-base: 0;
    --z-dropdown: 1000;
    --z-tooltip: 1100;
    --z-overlay: 1200;
    --z-modal: 1300;
    --z-toast: 1400;
    --z-max: 9999;

    /* Glow and focus */
    --glow-xs: 0 0 6px rgba(var(--accent-primary-rgb), 0.3);
    --glow-sm: 0 0 8px rgba(var(--accent-primary-rgb), 0.3);
    --glow-md: 0 0 12px rgba(var(--accent-primary-rgb), 0.25);
    --glow-status: 0 0 12px rgba(var(--_status-rgb), var(--glow-status-alpha, 0.15));
    --glow-status-alpha: 0.15;
    --glow-hover: 0 0 12px rgba(var(--accent-primary-rgb), 0.15);
    --focus-ring: 0 0 0 1px rgba(var(--accent-primary-rgb),0.25);
    --focus-glow: 0 0 0 1px rgba(var(--accent-primary-rgb),0.2), 0 0 6px rgba(var(--accent-primary-rgb),0.35), 0 0 16px rgba(var(--accent-primary-rgb),0.2), 0 0 40px rgba(var(--accent-secondary-rgb),0.12);
    --focus-error: 0 0 0 2px var(--surface-base), 0 0 0 4px var(--color-error), 0 0 16px rgba(var(--color-error-rgb), 0.2);
    --focus-inset: inset 0 0 0 2px var(--interactive);
    --focus-thumb: 0 0 8px rgba(var(--interactive-rgb), 0.5), 0 0 20px rgba(var(--interactive-rgb), 0.25);

    /* Semantic aliases */
    --interactive: var(--accent-primary);
    --interactive-rgb: var(--accent-primary-rgb);
    --interactive-hover: var(--glow-hover);
    --interactive-active: var(--glow-primary);
    --interactive-focus: var(--focus-glow);
    --interactive-focus-ring: var(--focus-ring);
    --interactive-focus-error: var(--focus-error);
    --interactive-focus-inset: var(--focus-inset);
    --interactive-focus-thumb: var(--focus-thumb);
    --interactive-muted: var(--text-ghost);
    --surface-base: var(--bg-deep);
    --surface-primary: var(--bg-surface);
    --surface-raised: var(--bg-card);
    --surface-overlay: var(--bg-elevated);
    --surface-hover: var(--bg-hover);
    --divider: var(--border-subtle);
    --on-accent: var(--surface-base);

    /* Interactive and layout */
    --touch-min: 24px;
    --touch-pad: 4px;
    --max-width: 1120px;
    --max-width-sm: 720px;
    --nav-height: 64px;
    --nav-row-inset: var(--space-sm);

  }

  
  @media (pointer: coarse) {
    :host {
      --touch-min: 36px;
      --touch-pad: 8px;
    }
  }


  /* Reduced motion, once, for every component that adopts these styles.

     This was copy-pasted verbatim into sixty-nine component files while fifteen
     animating components had no guard at all — which is the usual outcome when
     a cross-cutting rule is a convention rather than a place. Components keep
     their own blocks only for what this cannot express: scroll-behavior,
     animation-play-state, a transform that must be neutralised rather than
     shortened.

     0.01ms rather than "animation: none" on purpose. A component that removes
     itself on animationend — the exiting toast and snackbar both do — would
     wait forever for an event that a canceled animation never fires. A
     duration this short is imperceptible and still completes. */
  @media (prefers-reduced-motion: reduce) {
    :host *,
    :host *::before,
    :host *::after {
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
      transition-duration: 0.01ms !important;
    }
  }

      :host {
        display: block;
      }

      .scroll-spy {
        padding: 0 var(--space-md);
      }

      .scroll-spy__heading {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        width: 100%;
        box-sizing: border-box;
        text-align: start;
        cursor: pointer;
        position: sticky;
        top: 0;
        z-index: 1;
        background: var(--surface-primary);
        padding: var(--space-sm) var(--space-md);
        border-radius: var(--radius-md);
        border: 1px solid var(--border-subtle);
        margin-bottom: var(--space-sm);
        transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
      }

      .scroll-spy__heading:hover {
        border-color: var(--border-default);
        box-shadow: var(--glow-card-hover);
      }

      .scroll-spy__heading-text {
        font-family: var(--font-label);
        font-weight: var(--font-label-weight, 600);
        font-size: var(--_text-xs);
        letter-spacing: 3px;
        text-transform: uppercase;
        background: var(--gradient-accent-text);
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        background-clip: text;
      }

      /* ── Reading progress ── */
      /* An arc rather than a bar. A full-width bar under the heading reads as a
         second piece of chrome stacked on the panel; a 14px ring sits on the
         heading's own baseline as one more thing in that row, and says the same
         quantity in a shape the library is named after. */
      .scroll-spy__ring {
        margin-inline-start: auto;
        flex-shrink: 0;
        display: block;
        transform: rotate(-90deg);  /* Start the sweep at twelve o'clock. */
      }

      .scroll-spy__ring-track {
        stroke: var(--border-subtle);
      }

      .scroll-spy__ring-fill {
        stroke: var(--interactive);
        stroke-linecap: round;
        /* Deliberately untransitioned: the offset is rewritten on every scroll
           frame, so easing between frames only makes the ring trail the page. */
      }

      .scroll-spy__list {
        list-style: none;
        margin: 0;
        padding: 0;
        display: flex;
        flex-direction: column;
        gap: 2px; /* cosmetic micro-spacing */
      }

      .scroll-spy__item {
        display: block;
      }

      .scroll-spy__link {
        display: flex;
        align-items: center;
        font-family: var(--font-body);
        font-size: var(--_text-sm);
        line-height: 1.4;
        /* The unread baseline. --text-primary, and not one of the greys, for a
           reason worth writing down: secondary, muted and ghost are rgb 150,
           142 and 133 — seventeen points end to end. A read/unread split built
           from any two of them is invisible, which is exactly how it looked.
           The only real interval in the ramp is up to primary, so the hierarchy
           is built by lifting what is ahead rather than by sinking what is
           behind. Nothing ends up dimmer than the flat ghost every entry shared
           before, so the panel gains a state without spending contrast. */
        color: var(--text-primary);
        font-weight: 400;
        text-decoration: none;
        padding-block: var(--space-xs);
        padding-inline: var(--nav-row-inset) var(--space-sm);
        border-radius: var(--radius-sm);
        cursor: pointer;
        transition:
          color var(--transition-fast),
          background var(--transition-fast),
          box-shadow var(--transition-fast);
        background: none;
        border: none;
        width: 100%;
        /* An anchor is content-box by default where the <button> this replaced
           was border-box, so without this the indent on nested entries pushes
           the link wider than its container. */
        box-sizing: border-box;
        text-align: start;
        min-height: var(--touch-min);
      }

      .scroll-spy__link:hover {
        color: var(--text-primary);
        /* --surface-hover, not a white wash: --white-rgb is 255,255,255 in both
           themes, so 3% of it over a light background was invisible and the
           link had no hover affordance at all there. The token is the same
           thing done per-theme — white at 4% on dark, accent at 4% on light. */
        background: var(--surface-hover);
      }

      /* Ahead of the active rule, not after it. Both selectors are one class on
         one class, so the later one won: a nested heading that was the current
         section stayed ghost-grey, and on any page whose h3s outnumber its h2s
         the highlight was invisible most of the way down. */
      .scroll-spy__link--nested {
        font-size: var(--_text-xs);
      }

      /* Sections already scrolled past. Reading the list top to bottom, the
         point where it brightens is where you are — the same fact the ring
         gives as a quantity, in the place you are already looking.
         Hover puts it back: going *back* to a section you have read is the
         second thing a table of contents is for, and a receded row must not be
         a harder target than an unread one. */
      .scroll-spy__link--read {
        color: var(--text-ghost);
      }

      .scroll-spy__link--read:hover {
        color: var(--text-primary);
      }

      /* The accent, not a brighter grey. Unread entries already sit at
         --text-primary — the ramp has nothing above it — so lightness cannot
         say "here" as well as "ahead" at the same time. Hue can, and this is
         the treatment arc-sidebar gives its current page, which makes the two
         navigation panels agree about what current looks like. */
      /* The accent, carried to AA by the theme's own text-mix rather than by a
         number chosen here. Raw, it is 4.17:1 on its own tint in the light
         theme — the tint costs 0.73 against the 4.90 the same blue manages on
         plain white, and this is the one state that marks where the reader is.
         --accent-text-mix is solved per theme against every accent the library
         sets as text, so this rule states the intent and the palette states
         the amount. */
      .scroll-spy__link[aria-current="location"] {
        color: color-mix(in srgb, var(--interactive), var(--text-primary) var(--accent-text-mix, 0%));
        font-weight: 500;
        background: var(--accent-primary-subtle);
        box-shadow: 0 0 12px rgba(var(--interactive-rgb), 0.08);
      }

      .scroll-spy__link[aria-current="location"]:hover {
        color: color-mix(in srgb, var(--interactive), var(--text-primary) var(--accent-text-mix, 0%));
      }

      .scroll-spy__link:focus-visible {
        outline: none;
        box-shadow: var(--interactive-focus);
      }

      .scroll-spy__slot-host { display: none; }
    