
  *, *::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);
    --glyph-lh: 1;
    --ui-lh: 1.4;
    --numeral-size: clamp(24px, 3vw, 36px);
    --numeral-weight: 200;
    --label-size: var(--_text-xs);
    --label-weight: var(--font-label-weight, 600);
    --label-spacing: 2px;
    --section-title-size: var(--label-size);
    --section-title-weight: var(--label-weight);
    --section-title-spacing: var(--label-spacing);
    --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);

    /* Decorative presets */
    --gradient-sunset: linear-gradient(135deg, #ff6b6b, #ffa500, #ff4757);
    --gradient-ocean: linear-gradient(135deg, #00d2ff, #3a7bd5, #6dd5fa);
    --orb-close: #ff5f57;
    --orb-minimize: #febc2e;
    --orb-maximize: #28c840;

    /* Lobes of light */
    --lobe-line: linear-gradient(var(--lobe-axis, 90deg), rgba(var(--lobe-rgb, var(--border-default-rgb)), 0), rgba(var(--lobe-rgb, var(--border-default-rgb)), var(--lobe-alpha, 1)), rgba(var(--lobe-rgb, var(--border-default-rgb)), 0));
    --lobe-start: linear-gradient(var(--lobe-axis, 90deg), rgba(var(--lobe-rgb, var(--border-default-rgb)), var(--lobe-alpha, 1)), rgba(var(--lobe-rgb, var(--border-default-rgb)), 0));
    --lobe-end: linear-gradient(var(--lobe-axis, 90deg), rgba(var(--lobe-rgb, var(--border-default-rgb)), 0), rgba(var(--lobe-rgb, var(--border-default-rgb)), var(--lobe-alpha, 1)));
    --lobe-ambient: radial-gradient(var(--lobe-shape, ellipse), rgba(var(--lobe-rgb, var(--border-default-rgb)), var(--lobe-alpha, 0.08)) 0%, rgba(var(--lobe-rgb, var(--border-default-rgb)), 0) var(--lobe-extent, 70%));

    /* 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;
        /* A page layout's height is the viewport, and the page is what scrolls.
           See :host([embedded]) below for the other half — the same layout
           sized by its container, scrolling inside itself. A CSS-only version
           of that was tried first (a --shell-height token) and reverted: the
           rail's own viewport height forced the shell past any smaller box
           whatever :host declared, so the token was honoured everywhere except
           the case it existed for. Which half you are in is a real difference
           in behaviour — what scrolls, and what sticky means — so it is a
           declared prop rather than a token that has to guess. */
        min-height: 100vh;
        background: var(--surface-base);
        color: var(--text-primary);
      }

      .shell {
        display: flex;
        flex-direction: column;
        min-height: 100vh;
      }

      /* ── Embedded: the container is the viewport ──────────────────────────
         Everything here is the same layout measured against the host box
         instead of the screen. The host takes its container's height, .shell
         fills the host, and the body becomes the scroll context that the page
         was — which is why min-height: 0 appears on the flex items: without
         it a flex item refuses to shrink below its content and the inner
         scrollers never engage.

         The consumer supplies the height, exactly as they would for any other
         element: <arc-app-shell embedded style="height:100%"> inside a box
         that has one. Nothing here invents a number. */
      :host([embedded]) {
        min-height: 0;
        height: 100%;
        display: grid;
        grid-template-rows: 1fr;
        overflow: hidden;
      }

      :host([embedded]) .shell {
        min-height: 0;
        height: 100%;
      }

      :host([embedded]) .shell__body {
        min-height: 0;
        /* The bar is in flow here rather than fixed to the viewport, so there
           is nothing to reserve room for. */
        padding-top: 0;
      }

      :host([embedded]) .shell__sidebar {
        /* Stretched by the body rather than sized from the screen, and static
           rather than sticky: the body is the scroll context now, so there is
           no page scroll for the rail to hold still against. */
        position: static;
        top: auto;
        height: auto;
        min-height: 0;
      }

      :host([embedded]) .shell__main {
        min-height: 0;
      }

      :host([embedded]) .shell__content {
        overflow-y: auto;
        min-height: 0;
      }

      :host([embedded]) .shell__toc {
        position: static;
        max-height: none;
      }

      /* Topbar sits above everything */
      .shell__topbar {
        position: relative;
        z-index: 200;
      }

      .shell__body {
        display: flex;
        flex: 1;
        padding-top: var(--nav-height);
      }

      /* ── Desktop sidebar ── */
      .shell__sidebar {
        /* grid, so the slotted rail fills the full height of this box rather
           than stopping at its own content. It matters to anything that draws
           an edge — arc-sidebar's divider, or a plain <nav> with a
           border-right, which is what the docs preview slots and what a
           consumer reaches for first. Finding #91 was the arc-sidebar case of
           this and was fixed with a ::slotted rule naming that one tag; the box
           is the right place for it, and covers content the shell has never
           heard of. */
        display: grid;
        flex-shrink: 0;
        /* The rail's width lives here rather than on the slotted arc-sidebar,
           which the ::slotted block below forces to 100% of it. --sidebar-width
           is the one handle that moves both: set it on the shell (or anywhere
           above it) and the wrapper and its contents follow. arc-sidebar's own
           width prop is for a standalone rail — see navigation/sidebar.js. */
        width: var(--sidebar-width, 280px);
        position: sticky;
        top: var(--nav-height);
        /* Two things were tried here and both failed, which is why this is a
           plain viewport figure: calc(100% - …) resolves against .shell__body,
           whose height comes from a min-height and is therefore not definite, so
           the rail collapsed to the height of one link; and stretching the rail
           to the body makes it as tall as the page, which leaves sticky nothing
           to do. */
        height: calc(100vh - var(--nav-height));
        overflow-y: auto;
        overflow-x: hidden;
        z-index: 1;
      }

      .shell__main {
        flex: 1;
        min-width: 0;
        display: flex;
      }

      .shell__content {
        flex: 3;
        min-width: 0;
        padding: var(--space-xl) var(--space-xl);
      }

      .shell__toc {
        flex: 1;
        min-width: 0;
        max-width: 280px;
        position: sticky;
        top: calc(var(--nav-height) + var(--space-xl));
        align-self: flex-start;
        max-height: calc(100vh - var(--nav-height) - 2 * var(--space-xl));
        overflow-y: auto;
        /* Zero, not --space-md on the bottom only. The border below is drawn
           down the padding box, so an unmatched bottom pad made the line
           overhang the last entry with nothing balancing it above. Evened up by
           removing the pad rather than by adding one on top, which would have
           pushed the panel out of line with the article beside it. */
        padding-block: 0;
        padding-inline: 0 var(--space-lg);
        margin-bottom: var(--space-xl);
        border-inline-start: 1px solid var(--border-subtle);
      }

      .shell__toc--empty { display: none; }

      @media (max-width: 1280px) { /* --breakpoint-xl */
        .shell__toc { display: none; }
      }

      :host([mobile]) .shell__toc {
        margin-bottom: var(--space-xl);
      }

      :host([mobile]) .shell__content {
        padding: var(--space-lg);
      }

      /* ── Mobile overlay ── */
      :host([mobile]) .shell__sidebar {
        position: fixed;
        top: 0;
        inset-inline-start: 0;
        bottom: 0;
        z-index: 99;
        height: auto;
        width: 300px;
        max-width: 85vw;
        transform: translateX(-100%);
        /* visibility, not transform alone. Translated off-screen the drawer is
           still visible to the browser, so its links stay in the tab order and
           in the accessibility tree — 176 of them on a docs page, all invisible,
           every one of them ahead of the content on a mobile keyboard.
           Transitioned rather than set flat so the discrete flip lands at the
           *end* of the slide out and at the start of the slide in, which is the
           same delay-hide the overlays use for their backdrops. */
        visibility: hidden;
        transition:
          transform 250ms var(--ease-out-expo),
          visibility 250ms var(--ease-out-expo);
        background: var(--surface-primary);
        padding-top: var(--nav-height);
        overflow-y: auto;
        overflow-x: hidden;
        scrollbar-width: thin;
        scrollbar-color: var(--border-default) transparent;
      }

      /* Override arc-sidebar's own sticky/height — the shell wrapper handles it */
      ::slotted(arc-sidebar) {
        position: static !important;
        height: auto !important;
        overflow: visible !important;
        width: 100% !important;
      }


      :host([mobile][sidebar-open]) .shell__sidebar {
        transform: translateX(0);
        visibility: visible;
      }

      /* Backdrop */
      .shell__backdrop {
        display: none;
      }

      :host([mobile]) .shell__backdrop {
        display: block;
        position: fixed;
        inset: 0;
        z-index: 97;
        background: var(--overlay-backdrop);
        opacity: 0;
        visibility: hidden;
        transition:
          opacity var(--transition-base),
          visibility var(--transition-base);
        -webkit-backdrop-filter: blur(2px);
        backdrop-filter: blur(2px);
      }

      :host([mobile][sidebar-open]) .shell__backdrop {
        opacity: 1;
        visibility: visible;
      }

      /* Body scroll lock when open */
      @media (prefers-reduced-motion: reduce) {
        :host([mobile]) .shell__sidebar {
          transition: none;
        }
        :host([mobile]) .shell__backdrop {
          transition: none;
        }
      }
    