changeset 258:60a876c4587a

[ui] Add semantic primitive ownership Build a layered Zenbu token and sizing system, make authored controls use native-underneath primitives, migrate mrjunejune without imposing visual surfaces, and document/enforce HTML ownership in the catalog and wiki. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Wed, 05 Aug 2026 05:25:40 -0700
parents 609d3c6aff4e
children 667156fcd3e3
files .claude/skills/zenbu-design-system/SKILL.md .claude/skills/zenbu-personal-site/SKILL.md design_system/BUILD design_system/COLORS.md design_system/COMPONENTS.md design_system/NOTIFICATIONS.md design_system/README.md design_system/SIZING.md design_system/THEMES.md design_system/TOKENS.md design_system/main.c design_system/src/catalog.css design_system/src/catalog.js design_system/src/component_catalog.js design_system/src/components/icon.js design_system/src/components/index.js design_system/src/components/link.js design_system/src/components/notifications.js design_system/src/components/primitives.js design_system/src/index.html design_system/src/storybook.css design_system/src/storybook.js design_system/src/styles/components.css design_system/src/styles/density.css design_system/src/styles/elements.css design_system/src/styles/reference.css design_system/src/styles/semantic.css design_system/src/styles/shadcn.css design_system/src/styles/themes.css design_system/src/styles/tokens.css design_system/test/BUILD design_system/test/catalog_test.js design_system/test/design_system_policy_test.js design_system/test/storybook_test.js design_system/wiki/HTML_AUTHORING.md design_system/wiki/PRIMITIVE_MAP.md design_system/wiki/README.md design_system/wiki/REVIEW_CHECKLIST.md design_system/wiki/TOKENS_AND_SIZING.md mrjunejune/src/base.css mrjunejune/src/index.html mrjunejune/src/index.js mrjunejune/src/notes/index.html mrjunejune/src/notes/login.html mrjunejune/src/offline.html mrjunejune/src/parts/header.html mrjunejune/src/public/pwa-register.js mrjunejune/src/resume/index.html mrjunejune/src/sw.js mrjunejune/src/talk/index.html mrjunejune/src/tools/file_converter/index.html mrjunejune/src/tools/hls_player/index.css mrjunejune/src/tools/hls_player/index.html mrjunejune/src/tools/latex_editor/index.css mrjunejune/src/tools/latex_editor/index.html mrjunejune/src/tools/markdown_to_html/index.css mrjunejune/src/tools/markdown_to_html/index.html mrjunejune/test/snapshots/blog.snapshot mrjunejune/test/snapshots/resume.snapshot mrjunejune/test/snapshots/root.snapshot mrjunejune/test/snapshots/talk.snapshot mrjunejune/test/snapshots/tools.snapshot mrjunejune/test/snapshots/tools_file_converter.snapshot mrjunejune/test/snapshots/tools_hls_player.snapshot mrjunejune/test/snapshots/tools_latex_editor.snapshot mrjunejune/test/snapshots/tools_markdown_to_html.snapshot mrjunejune/test/theme_and_webp_test.js
diffstat 67 files changed, 8112 insertions(+), 5712 deletions(-) [+]
line wrap: on
line diff
--- a/.claude/skills/zenbu-design-system/SKILL.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/.claude/skills/zenbu-design-system/SKILL.md	Wed Aug 05 05:25:40 2026 -0700
@@ -8,16 +8,27 @@
 ## Structure
 
 - `design_system/src/components/`: dependency-free ES module Web Components.
-- `design_system/src/styles/tokens.css`: shared `--zen-*` design tokens.
-- `design_system/src/styles/components.css`: component presentation.
+- `design_system/src/styles/reference.css`: context-free `--zenbu-ref-*` scales.
+- `design_system/src/styles/semantic.css`: theme-aware `--zenbu-sys-*` roles.
+- `design_system/src/styles/density.css`: comfortable/compact role mappings.
+- `design_system/src/styles/components.css` and `elements.css`: presentation.
+- `design_system/src/styles/tokens.css`: compatibility aliases only.
 - `design_system/src/index.html`: declarative component stories.
-- `design_system/src/storybook.js` and `storybook.css`: catalog shell.
+- `design_system/src/catalog.js`, `component_catalog.js`, and `catalog.css`:
+  catalog shell and story inventory.
 - `design_system/main.c`: Seobeo catalog server.
 
 ## Component conventions
 
 - Stay close to native HTML and use light DOM.
 - Wrap native interactive elements instead of recreating form/link semantics.
+- Keep behavior reusable without forcing presentation. Support
+  `appearance="plain"` for button/card/field integrations, and require visual
+  surfaces, borders, shadows, and backgrounds to be deliberate opt-ins at the
+  application boundary.
+- Do not wrap existing content in a visual component merely to demonstrate
+  design-system adoption; use components only where they add behavior,
+  semantics, or an explicitly requested visual recipe.
 - Do not add framework or runtime dependencies.
 - Keep application state outside components.
 - Keep notification action tokens opaque and out of DOM attributes; use scoped,
@@ -25,10 +36,21 @@
 - Keep `zen-notifications` behavior aligned with
   `design_system/NOTIFICATIONS.md`.
 - Notification presentation uses a measured collapsed depth stack that expands
-  on hover/focus; do not import Sonner or Radix.
+  on hover/focus and remains entirely first-party.
 - Preserve keyboard, form, validity, label, and ARIA behavior.
-- Prefix custom elements and tokens with `zen-` / `--zen-`.
+- Prefix custom elements and canonical tokens with `zen-` / `--zenbu-`.
 - Keep selectors low-specificity so applications can override tokens.
+- Use the canonical `xs` / `sm` / `md` / `lg` / `xl` scale for typography,
+  control heights, block/inline padding, gaps, icons, and containers. Do not
+  introduce one-off component dimensions when a scale token fits.
+- Plain controls inherit `--zenbu-control-*` variables from their size attribute
+  without receiving visual CSS; consuming applications should build their own
+  appearance from those variables.
+- Keep the token graph layered: `--zenbu-ref-*` defines context-free values,
+  `--zenbu-sys-*` defines theme/density-aware intent, and private
+  `--zenbu-<component>-*` aliases simplify variants. New component and
+  application CSS must consume semantic roles rather than reference colors or
+  deprecated `--zen-*` aliases.
 - Support light, dark, reduced-motion, desktop, and mobile behavior.
 - Disclosure, overlay, and collapsing surfaces require smooth tokenized motion
   plus a reduced-motion fallback. Native disclosure markers must be replaced by
@@ -43,10 +65,11 @@
 - Treat themes as semantic-token compositions. Preserve the built-in Paper,
   Ink, and Playful themes plus automatic system light/dark behavior; components
   must not branch on theme names.
-- Use semantic `--zen-color-*` aliases in component CSS. Use primitive ramps
-  or the ten data tokens only when a semantic role does not fit; never encode
-  meaning through color alone.
-- Raw color literals are forbidden outside `src/styles/tokens.css`. Run
+- Use semantic `--zenbu-sys-*` aliases in component CSS. Add a semantic role
+  instead of consuming reference colors directly; never encode meaning through
+  color alone.
+- Raw color literals are forbidden outside `src/styles/reference.css` and the
+  compatibility-only `src/styles/tokens.css`. Run
   `//design_system/test:design_system_policy_test` whenever styles, components,
   stories, or catalog markup changes.
 - Render every interface icon with the first-party `zen-icon` component. Emoji,
@@ -60,7 +83,7 @@
 
 ```bash
 bazel run //design_system:dev
-bazel test //design_system/test:storybook_test
+bazel test //design_system/test:catalog_test
 bazel test //design_system/test:design_system_policy_test
 bazel build //design_system:design_system_server_bundle
 ```
@@ -76,3 +99,9 @@
 Write stories declaratively with `zen-story` and a direct `template`. Every
 component state should have a rendered example and visible source. Browser tests
 must cover native semantics and interactions rather than only element presence.
+
+## Wiki requirement
+
+Read `design_system/wiki/README.md` before authoring application HTML. Follow
+its one-owner native-underneath rules and update the wiki whenever a public
+primitive or authoring contract changes.
--- a/.claude/skills/zenbu-personal-site/SKILL.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/.claude/skills/zenbu-personal-site/SKILL.md	Wed Aug 05 05:25:40 2026 -0700
@@ -16,6 +16,16 @@
 - Zenbu UI assets are copied from `//design_system:components` and
   `//design_system:styles` into `src/public/design-system/` by Bazel. Do not
   hand-copy or fork shared component files.
+- Preserve the site's established transparent content and plain header/icon
+  presentation. Use `appearance="plain"` when shared behavior is useful, and
+  do not introduce cards, shadows, borders, or surfaces without a concrete UX
+  reason.
+- Every site-owned `zen-button` declares an `xs` / `sm` / `md` / `lg` / `xl`
+  size. Site CSS must consume inherited `--zenbu-control-*` aliases plus
+  `--zenbu-sys-padding-*` and typography roles instead of hardcoding control
+  padding or height.
+- New site CSS uses `--zenbu-sys-*` semantic roles. Do not consume
+  `--zenbu-ref-color-*` or add new `--zen-*` compatibility-token usage.
 - `mrjunejune/test/`: integration tests and snapshots.
 - `mrjunejune/BUILD`: Bazel build, bundle, asset movement, and test-visible filegroups.
 - `mrjunejune/.config` and `.config.development`: server configuration. Do not commit secrets.
@@ -34,6 +44,11 @@
 
 The simple template renderer replaces `{{...}}` tokens with file contents loaded through `Seobeo_Web_LoadFile`.
 
+Before adding or changing HTML controls, read
+`design_system/wiki/HTML_AUTHORING.md` and `PRIMITIVE_MAP.md`. Every authored
+interactive control must have exactly one appropriate Zenbu owner while
+retaining its native element underneath.
+
 ## Routes and features
 
 Existing route areas include:
--- a/design_system/BUILD	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/BUILD	Wed Aug 05 05:25:40 2026 -0700
@@ -30,7 +30,11 @@
 
 filegroup(
   name = "policy_sources",
-  srcs = glob(["src/**"]),
+  srcs = glob([
+    "*.md",
+    "src/**",
+    "wiki/**/*.md",
+  ]) + ["main.c"],
   visibility = ["//design_system/test:__pkg__"],
 )
 
--- a/design_system/COLORS.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/COLORS.md	Wed Aug 05 05:25:40 2026 -0700
@@ -4,28 +4,23 @@
 most surfaces; restrained natural colors provide emphasis without making the
 interface feel synthetic or overly saturated.
 
-## Primitive ramps
+## Reference colors
 
-Each family has `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`,
-`900`, and `950` steps:
+`reference.css` exposes the steps required by current themes and components:
 
-- `--zen-color-neutral-*`: warm paper, linen, charcoal, and ink;
-- `--zen-color-red-*`: brick and iron oxide;
-- `--zen-color-orange-*`: persimmon;
-- `--zen-color-amber-*`: straw and ochre;
-- `--zen-color-green-*`: matcha and moss;
-- `--zen-color-teal-*`: aged copper and patina;
-- `--zen-color-blue-*`: faded workwear and indigo;
-- `--zen-color-violet-*`: muted plum;
-- `--zen-color-rose-*`: clay and dusty rose;
-- `--zen-color-brown-*`: kraft paper and wood.
+- `--zenbu-ref-color-neutral-*`: paper, linen, charcoal, and ink;
+- `--zenbu-ref-color-brand-*`: faded workwear and indigo;
+- `--zenbu-ref-color-danger-*`: brick and iron oxide;
+- `--zenbu-ref-color-success-*`: matcha and moss;
+- `--zenbu-ref-color-warning-*`: persimmon and ochre.
 
-Use a primitive when an application needs a precise ramp step. Primitive values
-do not change between light and dark themes.
+Reference values do not change between themes. They are consumed by semantic
+theme mappings, not directly by application components.
 
-## Material aliases
+## Legacy material aliases
 
-Material aliases make one-off composition readable:
+These compatibility aliases preserve existing visual names while migration is
+in progress:
 
 ```css
 var(--zen-color-paper)
@@ -43,21 +38,26 @@
 var(--zen-color-wood)
 ```
 
-## Semantic aliases
+Do not use them in new component CSS; map the intended role through a
+`--zenbu-sys-color-*` token instead.
+
+## Semantic roles
 
 Components should prefer semantic tokens because these adapt to the current
 theme:
 
-- surfaces: `canvas`, `surface`, `surface-raised`, `surface-muted`,
-  `surface-sunken`, and `surface-overlay`;
-- text: `text`, `text-muted`, `text-subtle`, and `text-inverse`;
-- borders: `border`, `border-muted`, and `border-strong`;
-- action: `accent`, `accent-hover`, `accent-muted`, `focus`, `disabled`, and
-  `selection`;
-- status: `info`, `success`, `warning`, `danger`, their `on-*` foregrounds,
-  and their `*-muted` surfaces.
+- surfaces: `--zenbu-sys-color-surface-*`;
+- text and icons: `--zenbu-sys-color-text-*` and
+  `--zenbu-sys-color-icon-*`;
+- borders: `--zenbu-sys-color-border-*`;
+- actions and states: `--zenbu-sys-color-action-*`;
+- status: `--zenbu-sys-color-info-*`, `success-*`, `warning-*`, and
+  `danger-*`;
+- selection and focus: `--zenbu-sys-color-selection-*` and
+  `--zenbu-sys-color-focus-*`.
 
-All names use the `--zen-color-` prefix.
+Legacy `--zen-color-*` values remain compatibility aliases. New code uses the
+`--zenbu-ref-*` / `--zenbu-sys-*` architecture.
 
 Component and catalog styles may not contain raw color literals. Add or reuse a
 token in `tokens.css`, then reference it with `var()`. The Bazel target
@@ -66,7 +66,8 @@
 
 ## Data colors
 
-`--zen-color-data-1` through `--zen-color-data-10` form a categorical palette.
+`--zen-color-data-1` through `--zen-color-data-10` remain the current
+categorical compatibility palette.
 They deliberately vary in both hue and lightness. Keep adjacent series in
 numerical order and provide labels or patterns; color alone must never carry
 meaning.
@@ -75,12 +76,13 @@
 
 ```css
 .repository-summary {
-  border: 1px solid var(--zen-color-border-muted);
-  background: var(--zen-color-surface-muted);
-  color: var(--zen-color-text);
+  border: var(--zenbu-sys-stroke-width) solid
+    var(--zenbu-sys-color-border-subtle);
+  background: var(--zenbu-sys-color-surface-subtle);
+  color: var(--zenbu-sys-color-text-primary);
 }
 
 .repository-summary strong {
-  color: var(--zen-color-indigo);
+  color: var(--zenbu-sys-color-text-link);
 }
 ```
--- a/design_system/COMPONENTS.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/COMPONENTS.md	Wed Aug 05 05:25:40 2026 -0700
@@ -1,12 +1,12 @@
 # Zenbu UI component contracts
 
-Zenbu UI covers the 65 concepts in the shadcn/ui component catalog without
-copying its React, Radix, or third-party runtime. Every Zenbu component uses
-light DOM and keeps the corresponding native HTML control visible.
+Zenbu UI provides first-party component concepts and composition patterns.
+Every component uses light DOM and keeps the corresponding native HTML control
+visible.
 
 ## Inventory
 
-| shadcn/ui concept | Zenbu UI element |
+| Component concept | Zenbu UI element |
 | --- | --- |
 | Accordion | `zen-accordion` |
 | Alert | `zen-alert` |
@@ -17,6 +17,7 @@
 | Badge | `zen-badge` |
 | Breadcrumb | `zen-breadcrumb` |
 | Bubble | `zen-bubble` |
+| Box | `zen-box` |
 | Button | `zen-button` |
 | Button Group | `zen-button-group` |
 | Calendar | `zen-calendar` |
@@ -38,12 +39,14 @@
 | Field | `zen-field` |
 | Form | `zen-form` |
 | Hover Card | `zen-hover-card` |
+| Heading | `zen-heading` |
 | Input | `zen-input` |
 | Input Group | `zen-input-group` |
 | Input OTP | `zen-input-otp` |
 | Item | `zen-item` |
 | Kbd | `zen-kbd` |
 | Label | `zen-label` |
+| Link | `zen-link` |
 | Marker | `zen-marker` |
 | Menubar | `zen-menubar` |
 | Message | `zen-message` |
@@ -62,12 +65,13 @@
 | Sidebar | `zen-sidebar` |
 | Skeleton | `zen-skeleton` |
 | Slider | `zen-slider` |
-| Sonner | `zen-notifications` |
+| Notifications | `zen-notifications` |
 | Spinner | `zen-spinner` |
 | Switch | `zen-switch` |
 | Table | `zen-table` |
 | Tabs | `zen-tabs` |
 | Textarea | `zen-textarea` |
+| Text | `zen-text` |
 | Toast (deprecated) | `zen-notifications` |
 | Toggle | `zen-toggle` |
 | Toggle Group | `zen-toggle-group` |
@@ -96,12 +100,14 @@
 
 | Elements | Required light-DOM hooks | Emitted event |
 | --- | --- | --- |
-| `zen-dialog`, `zen-alert-dialog`, `zen-sheet`, `zen-drawer` | `[data-zen-trigger]`, `dialog`, optional `[data-zen-close]` | native `close` |
-| `zen-popover`, `zen-hover-card`, `zen-tooltip` | `[data-zen-trigger]`, `[data-zen-content]` | native toggle/focus events |
+| `zen-dialog`, `zen-alert-dialog`, `zen-sheet`, `zen-drawer` | `zen-button > button[data-zen-trigger]`, `dialog`, optional `zen-button > button[data-zen-close]` | native `close` |
+| `zen-popover`, `zen-tooltip` | `zen-button > button[data-zen-trigger]`, `[data-zen-content]` | native toggle/focus events |
+| `zen-hover-card` | interactive `[data-zen-trigger]`, `[data-zen-content]` | native toggle/focus events |
 | Menu elements | `[data-zen-trigger]`, `[role="menu"]`, `[role="menuitem"]` | native click |
 | `zen-tabs` | `[role="tablist"]`, `[role="tab"]`, `[role="tabpanel"]` | `zen-change` with `{ value }` |
 | `zen-toggle` | direct `button` | `zen-change` with `{ pressed }` |
 | `zen-toggle-group` | direct buttons with `value` | `zen-change` with `{ values }` |
+| `zen-link` | direct native anchor; optional `effect="paw"` | native link events |
 | `zen-sidebar` | `[data-zen-sidebar-trigger]`, `[data-zen-sidebar-panel]` | `zen-change` with `{ open }` |
 | `zen-combobox` | `input`, `[role="listbox"]`, `[role="option"]` | native `input`/`change` and `zen-change` |
 | `zen-command` | `input`, `[role="menu"]`, `[role="menuitem"]` | `zen-command` with `{ value }` |
--- a/design_system/NOTIFICATIONS.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/NOTIFICATIONS.md	Wed Aug 05 05:25:40 2026 -0700
@@ -77,7 +77,7 @@
 - Twenty additional records may remain queued.
 - The idle stack layers older records behind the newest with depth and scale.
 - Hovering the stack or focusing an action expands all visible records using
-  their measured heights; no Sonner/Radix runtime or CSS is used.
+  their measured heights and first-party component code.
 - Overflow evicts the oldest finite record; all-persistent queues reject new
   records.
 - Queued records do not count down.
--- a/design_system/README.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/README.md	Wed Aug 05 05:25:40 2026 -0700
@@ -4,10 +4,11 @@
 It stays close to ordinary HTML: components wrap native controls and sectioning
 elements instead of replacing their semantics.
 
-The catalog includes native Zenbu implementations of all 65 concepts currently
-listed by shadcn/ui. These are original Web Components using Zenbu tokens, not
-ports of shadcn's React, Radix, or third-party runtime. See
+The catalog includes native Zenbu component concepts and composition patterns.
+They are original dependency-free Web Components using Zenbu tokens.
+See
 [`COMPONENTS.md`](COMPONENTS.md) for the complete mapping and HTML contracts.
+Future HTML work follows the [`Zenbu UI wiki`](wiki/README.md).
 
 ## Catalog
 
@@ -20,8 +21,7 @@
 Open `http://127.0.0.1:6980`. Override the port with
 `DESIGN_SYSTEM_PORT`.
 
-The catalog is intentionally Storybook-like without depending on Storybook. Its
-stories are declared as HTML templates:
+The first-party catalog renders stories declared as HTML templates:
 
 ```html
 <zen-story name="Primary button">
@@ -54,11 +54,15 @@
 <script type="module" src="/design-system/components/index.js"></script>
 ```
 
-Every visual token is a `--zen-*` custom property and can be overridden by the
-application. See [`COLORS.md`](COLORS.md) for the complete warm color ramps,
-material aliases, semantic roles, dark-theme behavior, and data palette.
+Canonical tokens use the layered
+[`--zenbu-ref-*` / `--zenbu-sys-*` architecture](TOKENS.md) and can be
+overridden at an application boundary; older `--zen-*` names remain
+compatibility aliases. See [`COLORS.md`](COLORS.md) for color roles and theme
+behavior.
 Named [`themes`](THEMES.md) compose those tokens as Paper, Ink, and Playful
 experiences in addition to automatic system light/dark behavior.
+The [`sizing scale`](SIZING.md) defines shared `xs` through `xl` typography,
+control, icon, gap, and padding primitives.
 
 Use [`zen-icon`](ICONS.md) for all interface iconography. Design-system source
 does not use emoji, ad hoc SVG, icon fonts, or third-party icon packages.
@@ -74,10 +78,11 @@
 
 | Component family | Native content | Attributes | Events |
 | --- | --- | --- | --- |
-| `zen-button` | direct `button` or `a` | `variant`, `loading`, `disabled` | native click/form events |
-| `zen-card` | direct `article` or `section` | `interactive` | native descendant events |
+| `zen-button` | direct `button` or `a` | `appearance`, `variant`, `loading`, `disabled` | native click/form events |
+| `zen-card` | direct `article` or `section` | `appearance`, `interactive` | native descendant events |
+| `zen-link` | direct `a` | `effect` | native navigation events |
 | `zen-alert` | message HTML | `tone`, `dismissible` | `zen-dismiss` |
-| `zen-field` | direct `label`, form control, help text | native control attributes | native input/change/invalid |
+| `zen-field` | direct `label`, form control, help text | `appearance`, native control attributes | native input/change/invalid |
 | `zen-notifications` | descendant event producers | `aria-label`, `dismiss-label` | `zen-notification-action`, `zen-notification-removed` |
 | `zen-stack` | any HTML | `direction`, `gap` | native descendant events |
 | Disclosure and tabs | `details`, `summary`, buttons, sections | `multiple`, `activation` | `zen-change` |
@@ -89,6 +94,14 @@
 presentation, small accessibility wiring, and interaction affordances while
 applications retain data and workflow ownership.
 
+Use `appearance="plain"` when an application needs component behavior without
+the Zenbu visual recipe. Plain buttons remove browser chrome, plain cards add
+no surface treatment, and plain fields keep label/validity wiring while leaving
+the application's control CSS untouched.
+
+`zen-link effect="paw"` adds the first-party paw decoration and hover motion
+while preserving the native anchor and all application-authored link styles.
+
 ### Notifications
 
 See [`NOTIFICATIONS.md`](NOTIFICATIONS.md) for the complete event contract,
@@ -128,6 +141,6 @@
 ## Tests
 
 ```bash
-bazel test //design_system/test:storybook_test
+bazel test //design_system/test:catalog_test
 bazel build //design_system:design_system_server_bundle
 ```
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/SIZING.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,65 @@
+# Zenbu UI sizing
+
+Zenbu UI uses one five-step scale everywhere:
+
+| Size | Intended use |
+| --- | --- |
+| `xs` | dense metadata and compact actions |
+| `sm` | secondary controls and toolbars |
+| `md` | default body text and controls |
+| `lg` | prominent actions and lead text |
+| `xl` | touch-forward actions and display text |
+
+## Tokens
+
+Each step defines:
+
+- `--zenbu-sys-font-size-*` and `--zenbu-sys-line-height-*`;
+- `--zenbu-sys-control-height-*`;
+- `--zenbu-sys-control-padding-block-*` and
+  `--zenbu-sys-control-padding-inline-*`;
+- `--zenbu-sys-control-gap-*`;
+- `--zenbu-sys-icon-size-*`;
+- `--zenbu-sys-padding-*` for containers.
+
+Component hosts expose the selected values through inherited variables:
+
+```css
+--zenbu-control-height
+--zenbu-control-padding-block
+--zenbu-control-padding-inline
+--zenbu-control-gap
+--zenbu-control-font-size
+--zenbu-control-line-height
+--zenbu-control-icon-size
+```
+
+Styled components consume these automatically:
+
+```html
+<zen-button size="lg"><button type="button">Publish</button></zen-button>
+<zen-input size="sm"><input aria-label="Filter" /></zen-input>
+```
+
+Plain components expose the same variables without styling the native control.
+Applications can preserve their visual identity while sharing the scale:
+
+```css
+zen-button[appearance="plain"] > button {
+  min-height: var(--zenbu-control-height);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  font-size: var(--zenbu-control-font-size);
+}
+```
+
+## Typography and containers
+
+Use native semantics inside the primitives:
+
+```html
+<zen-heading size="xl"><h2>Repository activity</h2></zen-heading>
+<zen-text size="sm"><p>Updated two minutes ago.</p></zen-text>
+<zen-box padding="lg">...</zen-box>
+```
--- a/design_system/THEMES.md	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/THEMES.md	Wed Aug 05 05:25:40 2026 -0700
@@ -18,8 +18,8 @@
 
 ```css
 :root {
-  --zen-font-editorial: "More Thin", sans-serif;
-  --zen-font-playful: "More", sans-serif;
+  --zenbu-font-editorial: "More Thin", sans-serif;
+  --zenbu-font-playful: "More", sans-serif;
 }
 ```
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/TOKENS.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,83 @@
+# Zenbu UI token architecture
+
+Zenbu UI uses three CSS custom-property layers:
+
+```text
+Reference values       Semantic system roles       Local component aliases
+--zenbu-ref-*          --zenbu-sys-*               --zenbu-<component>-*
+```
+
+## Reference values
+
+`reference.css` defines context-free values: color ramps, spacing, type sizes,
+weights, line heights, radii, strokes, shadows, durations, easing, opacity,
+icon sizes, control sizes, and z-index levels.
+
+Reference values answer what exists in the system. Application and component
+CSS must not consume reference colors directly.
+
+## Semantic roles
+
+`semantic.css` maps reference values to stable intent:
+
+```css
+var(--zenbu-sys-color-text-primary)
+var(--zenbu-sys-color-surface-raised)
+var(--zenbu-sys-color-action-primary-background)
+var(--zenbu-sys-type-body-size)
+var(--zenbu-sys-space-container)
+var(--zenbu-sys-radius-control)
+var(--zenbu-sys-motion-duration-state)
+```
+
+Themes and density change semantic assignments. Component selectors continue
+to consume the same roles.
+
+## Local aliases
+
+Components use private aliases where variants remap one internal role:
+
+```css
+zen-button:not([appearance="plain"]) > button {
+  --zenbu-button-background:
+    var(--zenbu-sys-color-action-primary-background);
+  background: var(--zenbu-button-background);
+}
+```
+
+Do not turn every internal declaration into public API. A local alias becomes a
+documented host override only when multiple applications need that stable
+customization point.
+
+## Themes and density
+
+Themes use `data-zen-theme`; density uses `data-zen-density`:
+
+```html
+<html data-zen-theme="paper" data-zen-density="compact">
+```
+
+Available densities:
+
+- no attribute or `comfortable`: canonical five-step control sizes;
+- `compact`: reduced visual heights, padding, and gaps.
+
+Explicit component `size="xs|sm|md|lg|xl"` maps through density-aware semantic
+tokens.
+
+## Compatibility
+
+Older `--zen-*` variables remain temporarily in `tokens.css` as aliases. New
+code must use `--zenbu-ref-*`, `--zenbu-sys-*`, or a documented local
+`--zenbu-<component>-*` alias.
+
+## Enforcement
+
+`//design_system/test:design_system_policy_test` checks:
+
+- raw colors appear only in token source files;
+- every referenced `--zenbu-*` property is declared;
+- component CSS does not consume reference colors directly;
+- source and documentation use first-party naming;
+- exported JavaScript APIs retain typed documentation;
+- icon and dependency policies remain intact.
--- a/design_system/main.c	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/main.c	Wed Aug 05 05:25:40 2026 -0700
@@ -13,6 +13,7 @@
     "/components/badge",
     "/components/breadcrumb",
     "/components/bubble",
+    "/components/box",
     "/components/button",
     "/components/button-group",
     "/components/calendar",
@@ -34,12 +35,14 @@
     "/components/field",
     "/components/form",
     "/components/hover-card",
+    "/components/heading",
     "/components/input",
     "/components/input-group",
     "/components/input-otp",
     "/components/item",
     "/components/kbd",
     "/components/label",
+    "/components/link",
     "/components/marker",
     "/components/menubar",
     "/components/message",
@@ -59,13 +62,13 @@
     "/components/sidebar",
     "/components/skeleton",
     "/components/slider",
-    "/components/sonner",
     "/components/spinner",
     "/components/stack",
     "/components/switch",
     "/components/table",
     "/components/tabs",
     "/components/textarea",
+    "/components/text",
     "/components/toast",
     "/components/toggle",
     "/components/toggle-group",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/catalog.css	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,401 @@
+* {
+  box-sizing: border-box;
+}
+
+html {
+  min-height: 100%;
+  background: var(--zenbu-sys-color-surface-canvas);
+  color: var(--zenbu-sys-color-text-primary);
+  font-family: var(--zenbu-sys-font-family-ui);
+}
+
+body {
+  min-height: 100vh;
+  margin: 0;
+}
+
+button,
+input,
+select,
+textarea {
+  font: inherit;
+}
+
+.catalog-shell {
+  display: grid;
+  grid-template-columns: 17rem minmax(0, 1fr);
+  min-height: 100vh;
+}
+
+.catalog-sidebar {
+  position: sticky;
+  top: 0;
+  height: 100vh;
+  overflow: auto;
+  padding: var(--zenbu-sys-space-container);
+  border-right: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+.catalog-brand {
+  display: inline-flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-control);
+  color: inherit;
+  font-size: var(--zenbu-sys-font-size-lg);
+  font-weight: 850;
+  text-decoration: none;
+}
+
+.catalog-search {
+  width: 100%;
+  margin-top: var(--zenbu-sys-space-container);
+}
+
+.catalog-search > zen-icon {
+  align-self: center;
+  margin-inline-start: var(--zenbu-sys-space-control);
+  color: var(--zenbu-sys-color-text-secondary);
+}
+
+.catalog-search > kbd {
+  align-self: center;
+  margin-inline-end: var(--zenbu-sys-space-related);
+  padding: 0 var(--zenbu-sys-space-icon-label);
+  border: 1px solid var(--zenbu-sys-color-border-subtle);
+  border-radius: var(--zenbu-sys-radius-control-small);
+  color: var(--zenbu-sys-color-text-secondary);
+  font: var(--zenbu-sys-font-size-xs)/1.5 var(--zenbu-sys-font-family-code);
+}
+
+.search-status {
+  min-height: 1.25rem;
+  margin: var(--zenbu-sys-space-icon-label) 0 0;
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-xs);
+}
+
+.catalog-mark {
+  display: grid;
+  width: 2.5rem;
+  height: 2.5rem;
+  place-items: center;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 50%;
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+.catalog-sidebar h2 {
+  margin: var(--zenbu-sys-space-content) 0 var(--zenbu-sys-space-related);
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-xs);
+  letter-spacing: 0.12em;
+  text-transform: uppercase;
+}
+
+.catalog-nav {
+  display: grid;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+.catalog-nav a {
+  padding: var(--zenbu-sys-space-related) var(--zenbu-sys-space-control);
+  border-radius: var(--zenbu-sys-radius-control-small);
+  color: inherit;
+  text-decoration: none;
+}
+
+.catalog-nav a[hidden],
+.component-grid > a[hidden] {
+  display: none;
+}
+
+.catalog-nav a:hover,
+.catalog-nav a[aria-current] {
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+.theme-toggle {
+  width: 100%;
+  margin-top: var(--zenbu-sys-space-content);
+  padding: var(--zenbu-sys-space-related);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: transparent;
+  color: inherit;
+  cursor: pointer;
+}
+
+.theme-toggle-wrap {
+  display: flex;
+  width: 100%;
+}
+
+.catalog-main {
+  width: min(100%, var(--zenbu-sys-width-page));
+  min-width: 0;
+  padding: var(--zenbu-sys-space-section) clamp(1rem, 5vw, 5rem);
+  outline: none;
+}
+
+.catalog-page {
+  min-width: 0;
+}
+
+.catalog-page[hidden] {
+  display: none;
+}
+
+.page-heading {
+  max-width: 52rem;
+  margin-bottom: var(--zenbu-sys-space-section);
+}
+
+.eyebrow {
+  margin: 0 0 var(--zenbu-sys-space-related);
+  color: var(--zenbu-sys-color-info-foreground);
+  font-size: var(--zenbu-sys-font-size-sm);
+  font-weight: 800;
+  letter-spacing: 0.1em;
+  text-transform: uppercase;
+}
+
+.page-heading h1 {
+  margin: 0 0 var(--zenbu-sys-space-control);
+  font-size: var(--zenbu-sys-type-page-title-size);
+  line-height: 1.05;
+}
+
+.page-heading p {
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-lg);
+}
+
+.principles,
+.component-grid,
+.token-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
+  gap: var(--zenbu-sys-space-container);
+}
+
+.principle,
+.token-group {
+  padding: var(--zenbu-sys-space-container);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+.principle h2,
+.token-group h2 {
+  margin-top: 0;
+}
+
+.component-grid a {
+  color: inherit;
+  text-decoration: none;
+}
+
+.component-grid zen-card {
+  height: 100%;
+}
+
+.component-grid code {
+  color: var(--zenbu-sys-color-info-foreground);
+  font-size: var(--zenbu-sys-font-size-xs);
+}
+
+.component-grid p {
+  color: var(--zenbu-sys-color-text-secondary);
+}
+
+.swatch-list {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+  margin: 0;
+}
+
+.swatch-list div {
+  display: grid;
+  grid-template-columns: 2rem 1fr;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+}
+
+.swatch-list dt,
+.swatch-list dd {
+  margin: 0;
+  font-family: var(--zenbu-sys-font-family-code);
+  font-size: var(--zenbu-sys-font-size-xs);
+}
+
+.swatch {
+  --zenbu-color-swatch: transparent;
+  width: 2rem;
+  height: 2rem;
+  border: 1px solid var(--zenbu-sys-color-border-default);
+  border-radius: 50%;
+  background: var(--zenbu-color-swatch);
+}
+
+.token-group-wide {
+  grid-column: span 2;
+}
+
+.token-group > p {
+  color: var(--zenbu-sys-color-text-secondary);
+}
+
+.palette-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
+  gap: var(--zenbu-sys-space-control);
+}
+
+.palette-grid > div {
+  display: grid;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+.palette-grid span {
+  --zenbu-color-swatch: transparent;
+  min-height: 3.5rem;
+  border: 1px solid var(--zenbu-sys-color-border-subtle);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-color-swatch);
+}
+
+.palette-grid code {
+  font-size: var(--zenbu-sys-font-size-xs);
+}
+
+.data-palette {
+  display: grid;
+  grid-template-columns: repeat(10, minmax(1.75rem, 1fr));
+  min-height: 4rem;
+  overflow: hidden;
+  border: 1px solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+}
+
+.data-palette span {
+  --zenbu-color-swatch: transparent;
+  background: var(--zenbu-color-swatch);
+}
+
+.icon-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
+  gap: var(--zenbu-sys-space-control);
+}
+
+.icon-grid figure {
+  display: grid;
+  min-height: 7rem;
+  margin: 0;
+  padding: var(--zenbu-sys-space-control);
+  place-items: center;
+  gap: var(--zenbu-sys-space-related);
+  border: 1px solid var(--zenbu-sys-color-border-subtle);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+.icon-grid figcaption {
+  max-width: 100%;
+  overflow: hidden;
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-xs);
+  text-overflow: ellipsis;
+}
+
+zen-story {
+  display: block;
+  max-width: 100%;
+  margin-bottom: var(--zenbu-sys-space-content);
+  overflow: hidden;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-story > header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: var(--zenbu-sys-space-control);
+  padding: var(--zenbu-sys-space-control) var(--zenbu-sys-space-group);
+  border-bottom: 1px solid var(--zenbu-sys-color-border-default);
+}
+
+zen-story > header h3 {
+  margin: 0;
+}
+
+zen-story > header button {
+  padding: var(--zenbu-sys-space-icon-label) var(--zenbu-sys-space-related);
+  border: 0;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: transparent;
+  color: var(--zenbu-sys-color-info-foreground);
+  cursor: pointer;
+}
+
+.story-canvas {
+  min-height: 8rem;
+  padding: clamp(1rem, 4vw, 3rem);
+  background:
+    linear-gradient(90deg, var(--zenbu-sys-color-gridline) 1px, transparent 1px),
+    linear-gradient(var(--zenbu-sys-color-gridline) 1px, transparent 1px);
+  background-size: 1rem 1rem;
+}
+
+zen-story > pre {
+  max-height: 24rem;
+  overflow: auto;
+  margin: 0;
+  padding: var(--zenbu-sys-space-group);
+  border-top: 1px solid var(--zenbu-sys-color-border-default);
+  background: var(--zenbu-sys-color-code-surface);
+  color: var(--zenbu-sys-color-code-text);
+  font: var(--zenbu-sys-font-size-sm)/1.55 var(--zenbu-sys-font-family-code);
+}
+
+.demo-card-grid {
+  display: grid;
+  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
+  gap: var(--zenbu-sys-space-container);
+}
+
+@media (max-width: 760px) {
+  .catalog-shell {
+    grid-template-columns: 1fr;
+  }
+
+  .catalog-sidebar {
+    position: static;
+    width: 100%;
+    height: auto;
+    border-right: 0;
+    border-bottom: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  }
+
+  .catalog-nav {
+    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
+  }
+
+  .catalog-main {
+    padding: var(--zenbu-sys-space-content) var(--zenbu-sys-space-group);
+  }
+
+  .token-group-wide {
+    grid-column: auto;
+  }
+
+  .data-palette {
+    grid-template-columns: repeat(5, 1fr);
+  }
+}
--- a/design_system/src/catalog.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/catalog.js	Wed Aug 05 05:25:40 2026 -0700
@@ -1,732 +1,304 @@
-/** @const {!ReadonlyArray<!Object>} shadcn concepts shown by the catalog. */
-export const componentCatalog = [
-  {
-    name: "Accordion",
-    slug: "accordion",
-    element: "zen-accordion",
-    group: "Disclosure",
-    description: "A group of native details elements with optional single-open behavior.",
-    markup: `<zen-accordion>
-  <details open><summary>Is it accessible?</summary><p>It keeps native details and summary semantics.</p></details>
-  <details><summary>Can several open?</summary><p>Add the multiple attribute to allow it.</p></details>
-</zen-accordion>`,
-  },
-  {
-    name: "Alert",
-    slug: "alert",
-    element: "zen-alert",
-    group: "Feedback",
-    description: "Status messaging with semantic tones and optional dismissal.",
-    existing: true,
-  },
-  {
-    name: "Alert Dialog",
-    slug: "alert-dialog",
-    element: "zen-alert-dialog",
-    group: "Overlays",
-    description: "A native modal dialog for decisions that require confirmation.",
-    markup: `<zen-alert-dialog>
-  <button type="button" data-zen-trigger>Delete deployment</button>
-  <dialog>
-    <h3>Delete deployment?</h3>
-    <p>This action cannot be undone.</p>
-    <button type="button" data-zen-close>Cancel</button>
-    <button type="button" value="confirm" data-zen-close>Delete</button>
-  </dialog>
-</zen-alert-dialog>`,
-  },
-  {
-    name: "Aspect Ratio",
-    slug: "aspect-ratio",
-    element: "zen-aspect-ratio",
-    group: "Layout",
-    description: "A media frame driven by a readable ratio attribute.",
-    markup: `<zen-aspect-ratio ratio="16/9">
-  <div class="demo-media">16 / 9</div>
-</zen-aspect-ratio>`,
-  },
-  {
-    name: "Attachment",
-    slug: "attachment",
-    element: "zen-attachment",
-    group: "Chat",
-    description: "File and upload state presentation using ordinary links and buttons.",
-    markup: `<zen-attachment state="complete">
-  <span aria-hidden="true">PDF</span>
-  <div><strong>release-notes.pdf</strong><small>248 KB · Ready</small></div>
-  <button type="button" aria-label="Remove attachment"><zen-icon name="close"></zen-icon></button>
-</zen-attachment>`,
-  },
-  {
-    name: "Avatar",
-    slug: "avatar",
-    element: "zen-avatar",
-    group: "Display",
-    description: "A compact identity image with a visible text fallback.",
-    markup: `<zen-avatar aria-label="June Park"><span>JP</span></zen-avatar>`,
-  },
-  {
-    name: "Badge",
-    slug: "badge",
-    element: "zen-badge",
-    group: "Display",
-    description: "A small label for metadata, state, or counts.",
-    markup: `<zen-stack direction="row">
-  <zen-badge>Default</zen-badge>
-  <zen-badge tone="success">Healthy</zen-badge>
-  <zen-badge tone="danger">Failed</zen-badge>
-</zen-stack>`,
-  },
-  {
-    name: "Breadcrumb",
-    slug: "breadcrumb",
-    element: "zen-breadcrumb",
-    group: "Navigation",
-    description: "A native navigation landmark for hierarchical location.",
-    markup: `<zen-breadcrumb>
-  <nav><ol>
-    <li><a href="/">Home</a></li>
-    <li><a href="/components">Components</a></li>
-    <li aria-current="page">Breadcrumb</li>
-  </ol></nav>
-</zen-breadcrumb>`,
-  },
-  {
-    name: "Bubble",
-    slug: "bubble",
-    element: "zen-bubble",
-    group: "Chat",
-    description: "A message bubble with incoming and outgoing alignment.",
-    markup: `<zen-stack>
-  <zen-bubble><p>The deployment is ready.</p></zen-bubble>
-  <zen-bubble align="end"><p>Ship it.</p></zen-bubble>
-</zen-stack>`,
-  },
-  {
-    name: "Button",
-    slug: "button",
-    element: "zen-button",
-    group: "Actions",
-    description: "Native buttons and links with shared variants and states.",
-    existing: true,
-  },
-  {
-    name: "Button Group",
-    slug: "button-group",
-    element: "zen-button-group",
-    group: "Actions",
-    description: "Related native buttons joined into one visual control.",
-    markup: `<zen-button-group aria-label="Text alignment">
-  <button type="button">Left</button>
-  <button type="button">Center</button>
-  <button type="button">Right</button>
-</zen-button-group>`,
-  },
-  {
-    name: "Calendar",
-    slug: "calendar",
-    element: "zen-calendar",
-    group: "Forms",
-    description: "A first-party date month grid backed by a native form value.",
-    markup: `<zen-calendar>
-  <label for="calendar-demo">Release date</label>
-  <input id="calendar-demo" type="date" value="2026-08-04" />
-</zen-calendar>`,
-  },
-  {
-    name: "Card",
-    slug: "card",
-    element: "zen-card",
-    group: "Display",
-    description: "A visual container around native article or section content.",
-    existing: true,
-  },
-  {
-    name: "Carousel",
-    slug: "carousel",
-    element: "zen-carousel",
-    group: "Collections",
-    description: "A scroll-snap collection with native buttons and keyboard controls.",
-    markup: `<zen-carousel aria-label="Recent projects">
-  <div data-zen-viewport>
-    <article>Mercurial forge</article>
-    <article>HLS player</article>
-    <article>LaTeX editor</article>
-  </div>
-  <button type="button" data-zen-prev aria-label="Previous slide"><zen-icon name="arrow-left"></zen-icon></button>
-  <button type="button" data-zen-next aria-label="Next slide"><zen-icon name="arrow-right"></zen-icon></button>
-</zen-carousel>`,
-  },
-  {
-    name: "Chart",
-    slug: "chart",
-    element: "zen-chart",
-    group: "Data",
-    description: "A dependency-free chart frame for semantic labels and custom marks.",
-    markup: `<zen-chart aria-label="Build minutes by day">
-  <div data-zen-chart-plot>
-    <span style="--zen-chart-value: 42%" data-label="Mon"></span>
-    <span style="--zen-chart-value: 76%" data-label="Tue"></span>
-    <span style="--zen-chart-value: 58%" data-label="Wed"></span>
-    <span style="--zen-chart-value: 88%" data-label="Thu"></span>
-  </div>
-</zen-chart>`,
-  },
-  {
-    name: "Checkbox",
-    slug: "checkbox",
-    element: "zen-checkbox",
-    group: "Forms",
-    description: "A styled native checkbox that remains form-associated.",
-    markup: `<zen-checkbox>
-  <label><input type="checkbox" checked /> Include deployment artifacts</label>
-</zen-checkbox>`,
-  },
-  {
-    name: "Collapsible",
-    slug: "collapsible",
-    element: "zen-collapsible",
-    group: "Disclosure",
-    description: "A single native details disclosure.",
-    markup: `<zen-collapsible>
-  <details><summary>Three changed files</summary><p>server.c, styles.css, README.md</p></details>
-</zen-collapsible>`,
-  },
-  {
-    name: "Combobox",
-    slug: "combobox",
-    element: "zen-combobox",
-    group: "Forms",
-    description: "A filterable text input backed by an accessible option list.",
-    markup: `<zen-combobox>
-  <label for="repo-combobox">Repository</label>
-  <input id="repo-combobox" autocomplete="off" placeholder="Find repository" />
-  <div role="listbox">
-    <button type="button" role="option" data-value="zenbu">zenbu</button>
-    <button type="button" role="option" data-value="hg-web">hg-web</button>
-    <button type="button" role="option" data-value="seobeo">seobeo</button>
-  </div>
-</zen-combobox>`,
-  },
-  {
-    name: "Command",
-    slug: "command",
-    element: "zen-command",
-    group: "Navigation",
-    description: "A keyboard-first filterable command list.",
-    markup: `<zen-command>
-  <input type="search" aria-label="Commands" placeholder="Type a command" />
-  <div role="menu">
-    <button type="button" role="menuitem" data-value="new">New repository</button>
-    <button type="button" role="menuitem" data-value="deploy">Deploy release</button>
-    <button type="button" role="menuitem" data-value="theme">Toggle theme</button>
-  </div>
-</zen-command>`,
-  },
-  {
-    name: "Context Menu",
-    slug: "context-menu",
-    element: "zen-context-menu",
-    group: "Menus",
-    description: "A right-click menu with keyboard navigation and native buttons.",
-    markup: `<zen-context-menu>
-  <div data-zen-trigger tabindex="0">Right-click this repository</div>
-  <div role="menu" hidden>
-    <button type="button" role="menuitem">Open</button>
-    <button type="button" role="menuitem">Clone</button>
-    <button type="button" role="menuitem">Archive</button>
-  </div>
-</zen-context-menu>`,
-  },
-  {
-    name: "Data Table",
-    slug: "data-table",
-    element: "zen-data-table",
-    group: "Data",
-    description: "A native table enhanced with optional client-side sorting.",
-    markup: `<zen-data-table>
-  <table>
-    <thead><tr>
-      <th><button type="button" data-zen-sort="name">Repository</button></th>
-      <th><button type="button" data-zen-sort="commits">Commits</button></th>
-    </tr></thead>
-    <tbody>
-      <tr><td data-key="name">seobeo</td><td data-key="commits">87</td></tr>
-      <tr><td data-key="name">hg-web</td><td data-key="commits">142</td></tr>
-      <tr><td data-key="name">design-system</td><td data-key="commits">12</td></tr>
-    </tbody>
-  </table>
-</zen-data-table>`,
-  },
-  {
-    name: "Date Picker",
-    slug: "date-picker",
-    element: "zen-date-picker",
-    group: "Forms",
-    description: "A tokenized date trigger and first-party keyboard calendar.",
-    markup: `<zen-date-picker>
-  <label for="date-picker-demo">Deploy on</label>
-  <input id="date-picker-demo" type="date" />
-</zen-date-picker>`,
-  },
-  {
-    name: "Dialog",
-    slug: "dialog",
-    element: "zen-dialog",
-    group: "Overlays",
-    description: "A native modal dialog with trigger and close wiring.",
-    markup: `<zen-dialog>
-  <button type="button" data-zen-trigger>Edit profile</button>
-  <dialog>
-    <h3>Edit profile</h3>
-    <label>Display name <input value="June" /></label>
-    <button type="button" data-zen-close>Done</button>
-  </dialog>
-</zen-dialog>`,
-  },
-  {
-    name: "Direction",
-    slug: "direction",
-    element: "zen-direction",
-    group: "Utilities",
-    description: "A light-DOM boundary for left-to-right or right-to-left content.",
-    markup: `<zen-direction dir="rtl"><p>مرحبا بالعالم</p></zen-direction>`,
-  },
-  {
-    name: "Drawer",
-    slug: "drawer",
-    element: "zen-drawer",
-    group: "Overlays",
-    description: "A native dialog presented as an edge drawer.",
-    markup: `<zen-drawer placement="bottom">
-  <button type="button" data-zen-trigger>Open drawer</button>
-  <dialog><h3>Build queue</h3><p>Two jobs are running.</p><button type="button" data-zen-close>Close</button></dialog>
-</zen-drawer>`,
-  },
-  {
-    name: "Dropdown Menu",
-    slug: "dropdown-menu",
-    element: "zen-dropdown-menu",
-    group: "Menus",
-    description: "A button-owned action menu with arrow-key navigation.",
-    markup: `<zen-dropdown-menu>
-  <button type="button" data-zen-trigger>Repository actions</button>
-  <div role="menu" hidden>
-    <button type="button" role="menuitem">Clone</button>
-    <button type="button" role="menuitem">Bookmark</button>
-    <button type="button" role="menuitem">Archive</button>
-  </div>
-</zen-dropdown-menu>`,
-  },
-  {
-    name: "Empty",
-    slug: "empty",
-    element: "zen-empty",
-    group: "Feedback",
-    description: "A structured empty state with an optional native action.",
-    markup: `<zen-empty>
-  <strong>No deployments yet</strong>
-  <p>Create the first release from the current default branch.</p>
-  <button type="button">Create deployment</button>
-</zen-empty>`,
-  },
-  {
-    name: "Field",
-    slug: "field",
-    element: "zen-field",
-    group: "Forms",
-    description: "Label, help text, validity, and a native form control.",
-    existing: true,
-  },
-  {
-    name: "Form",
-    slug: "form",
-    element: "zen-form",
-    group: "Forms",
-    description: "A native form boundary with visible browser validity state.",
-    markup: `<zen-form>
-  <form>
-    <zen-field><label>Repository name</label><input required /><small>Required</small></zen-field>
-    <button type="submit">Create</button>
-  </form>
-</zen-form>`,
-  },
-  {
-    name: "Hover Card",
-    slug: "hover-card",
-    element: "zen-hover-card",
-    group: "Overlays",
-    description: "Supplemental content shown on hover or keyboard focus.",
-    markup: `<zen-hover-card>
-  <a href="#" data-zen-trigger>@mrjunejune</a>
-  <div data-zen-content hidden><strong>June Park</strong><p>Building Zenbu in C and native HTML.</p></div>
-</zen-hover-card>`,
-  },
-  {
-    name: "Input",
-    slug: "input",
-    element: "zen-input",
-    group: "Forms",
-    description: "A styled native input with no replacement semantics.",
-    markup: `<zen-input><input type="email" placeholder="[email protected]" aria-label="Email" /></zen-input>`,
-  },
-  {
-    name: "Input Group",
-    slug: "input-group",
-    element: "zen-input-group",
-    group: "Forms",
-    description: "A native input with prefix, suffix, or inline actions.",
-    markup: `<zen-input-group>
-  <span aria-hidden="true">https://</span>
-  <input aria-label="Host" value="zenbu.babocoder.com" />
-  <button type="button">Copy</button>
-</zen-input-group>`,
-  },
-  {
-    name: "Input OTP",
-    slug: "input-otp",
-    element: "zen-input-otp",
-    group: "Forms",
-    description: "A single native one-time-code input with visual slots.",
-    markup: `<zen-input-otp>
-  <label for="otp-demo">Verification code</label>
-  <input id="otp-demo" inputmode="numeric" autocomplete="one-time-code" maxlength="6" />
-  <div data-zen-otp-slots aria-hidden="true"></div>
-</zen-input-otp>`,
-  },
-  {
-    name: "Item",
-    slug: "item",
-    element: "zen-item",
-    group: "Display",
-    description: "A flexible list row for an icon, content, and actions.",
-    markup: `<zen-item>
-  <zen-icon name="repository"></zen-icon>
-  <div><strong>hg-web</strong><small>Updated two minutes ago</small></div>
-  <button type="button">Open</button>
-</zen-item>`,
-  },
-  {
-    name: "Kbd",
-    slug: "kbd",
-    element: "zen-kbd",
-    group: "Display",
-    description: "Keyboard shortcut presentation using native kbd elements.",
-    markup: `<p>Open commands with <zen-kbd><kbd>Ctrl</kbd><span>+</span><kbd>K</kbd></zen-kbd>.</p>`,
-  },
-  {
-    name: "Label",
-    slug: "label",
-    element: "zen-label",
-    group: "Forms",
-    description: "A styled native label that keeps browser association.",
-    markup: `<zen-label><label for="label-demo">Branch name</label></zen-label>
-<zen-input><input id="label-demo" value="default" /></zen-input>`,
-  },
-  {
-    name: "Marker",
-    slug: "marker",
-    element: "zen-marker",
-    group: "Chat",
-    description: "An inline system marker for chat and activity streams.",
-    markup: `<zen-marker><span>Today</span></zen-marker>`,
-  },
-  {
-    name: "Menubar",
-    slug: "menubar",
-    element: "zen-menubar",
-    group: "Menus",
-    description: "A horizontal application menu using native buttons and menu roles.",
-    markup: `<zen-menubar>
-  <button type="button" data-zen-trigger>File</button>
-  <div role="menu" hidden><button role="menuitem">New</button><button role="menuitem">Open</button></div>
-  <button type="button" data-zen-trigger>View</button>
-  <div role="menu" hidden><button role="menuitem">Graph</button><button role="menuitem">History</button></div>
-</zen-menubar>`,
-  },
-  {
-    name: "Message",
-    slug: "message",
-    element: "zen-message",
-    group: "Chat",
-    description: "An avatar, author, and content row for conversations.",
-    markup: `<zen-message>
-  <zen-avatar aria-label="June"><span>JP</span></zen-avatar>
-  <div><strong>June</strong><zen-bubble><p>Can we deploy this release?</p></zen-bubble></div>
-</zen-message>`,
-  },
-  {
-    name: "Message Scroller",
-    slug: "message-scroller",
-    element: "zen-message-scroller",
-    group: "Chat",
-    description: "A chat viewport that follows new content until the reader scrolls away.",
-    markup: `<zen-message-scroller>
-  <div data-zen-viewport>
-    <p>Worker connected.</p><p>Build started.</p><p>Bundle created.</p><p>Deployment complete.</p>
-  </div>
-  <button type="button" data-zen-scroll-end hidden>Jump to latest</button>
-</zen-message-scroller>`,
-  },
-  {
-    name: "Native Select",
-    slug: "native-select",
-    element: "zen-native-select",
-    group: "Forms",
-    description: "A styled native select with full platform behavior.",
-    markup: `<zen-native-select><select aria-label="Environment"><option>Development</option><option>Production</option></select></zen-native-select>`,
-  },
-  {
-    name: "Navigation Menu",
-    slug: "navigation-menu",
-    element: "zen-navigation-menu",
-    group: "Navigation",
-    description: "Top-level navigation with optional keyboard-accessible flyouts.",
-    markup: `<zen-navigation-menu>
-  <nav aria-label="Products">
-    <button type="button" data-zen-trigger>Projects</button>
-    <div role="menu" hidden><a role="menuitem" href="/components">Zenbu UI</a><a role="menuitem" href="/">hg-web</a></div>
-    <a href="/tokens">Tokens</a>
-  </nav>
-</zen-navigation-menu>`,
-  },
-  {
-    name: "Pagination",
-    slug: "pagination",
-    element: "zen-pagination",
-    group: "Navigation",
-    description: "Page navigation built from native links.",
-    markup: `<zen-pagination>
-  <nav><a href="#">Previous</a><a href="#">1</a><a href="#" aria-current="page">2</a><a href="#">3</a><a href="#">Next</a></nav>
-</zen-pagination>`,
-  },
-  {
-    name: "Popover",
-    slug: "popover",
-    element: "zen-popover",
-    group: "Overlays",
-    description: "A lightweight panel using the native Popover API when available.",
-    markup: `<zen-popover>
-  <button type="button" data-zen-trigger>Open settings</button>
-  <div data-zen-content><strong>Dimensions</strong><label>Width <input value="100%" /></label></div>
-</zen-popover>`,
-  },
-  {
-    name: "Progress",
-    slug: "progress",
-    element: "zen-progress",
-    group: "Feedback",
-    description: "A styled native progress element.",
-    markup: `<zen-progress><label for="progress-demo">Uploading</label><progress id="progress-demo" value="68" max="100">68%</progress></zen-progress>`,
-  },
-  {
-    name: "Radio Group",
-    slug: "radio-group",
-    element: "zen-radio-group",
-    group: "Forms",
-    description: "A fieldset of native radio inputs.",
-    markup: `<zen-radio-group>
-  <fieldset><legend>Visibility</legend>
-    <label><input type="radio" name="visibility" checked /> Public</label>
-    <label><input type="radio" name="visibility" /> Private</label>
-  </fieldset>
-</zen-radio-group>`,
-  },
-  {
-    name: "Resizable",
-    slug: "resizable",
-    element: "zen-resizable",
-    group: "Layout",
-    description: "Two native panels separated by a pointer and keyboard handle.",
-    markup: `<zen-resizable>
-  <section data-zen-panel>Repository tree</section>
-  <div data-zen-handle tabindex="0"></div>
-  <section data-zen-panel>File preview</section>
-</zen-resizable>`,
-  },
-  {
-    name: "Scroll Area",
-    slug: "scroll-area",
-    element: "zen-scroll-area",
-    group: "Layout",
-    description: "A bounded native scroll container with theme-aware scrollbars.",
-    markup: `<zen-scroll-area tabindex="0">
-  <p>default</p><p>feature/design-system</p><p>release/2026-08</p><p>experiment/trading</p>
-</zen-scroll-area>`,
-  },
-  {
-    name: "Select",
-    slug: "select",
-    element: "zen-select",
-    group: "Forms",
-    description: "A native select styled as the default accessible implementation.",
-    markup: `<zen-select><label>Branch <select><option>default</option><option>stable</option></select></label></zen-select>`,
-  },
-  {
-    name: "Separator",
-    slug: "separator",
-    element: "zen-separator",
-    group: "Layout",
-    description: "A native horizontal rule or ARIA separator.",
-    markup: `<div>Repository</div><zen-separator><hr /></zen-separator><div>Changesets</div>`,
-  },
-  {
-    name: "Sheet",
-    slug: "sheet",
-    element: "zen-sheet",
-    group: "Overlays",
-    description: "A native dialog presented from a selected screen edge.",
-    markup: `<zen-sheet placement="right">
-  <button type="button" data-zen-trigger>Open filters</button>
-  <dialog><h3>Filters</h3><label>Author <input /></label><button type="button" data-zen-close>Apply</button></dialog>
-</zen-sheet>`,
-  },
-  {
-    name: "Sidebar",
-    slug: "sidebar",
-    element: "zen-sidebar",
-    group: "Navigation",
-    description: "A collapsible navigation region with an explicit native trigger.",
-    markup: `<zen-sidebar open>
-  <button type="button" data-zen-sidebar-trigger>Toggle sidebar</button>
-  <aside data-zen-sidebar-panel><nav><a href="/">Overview</a><a href="/components">Components</a><a href="/tokens">Tokens</a></nav></aside>
-</zen-sidebar>`,
-  },
-  {
-    name: "Skeleton",
-    slug: "skeleton",
-    element: "zen-skeleton",
-    group: "Feedback",
-    description: "A reduced-motion-safe placeholder for pending content.",
-    markup: `<zen-stack>
-  <zen-skeleton shape="circle"></zen-skeleton>
-  <zen-skeleton></zen-skeleton>
-  <zen-skeleton width="60%"></zen-skeleton>
-</zen-stack>`,
-  },
-  {
-    name: "Slider",
-    slug: "slider",
-    element: "zen-slider",
-    group: "Forms",
-    description: "A native range input with browser keyboard and pointer behavior.",
-    markup: `<zen-slider><label for="slider-demo">Volume</label><input id="slider-demo" type="range" value="65" /></zen-slider>`,
-  },
-  {
-    name: "Sonner",
-    slug: "sonner",
-    element: "zen-notifications",
-    group: "Feedback",
-    description: "Zenbu's bounded, scoped, Sonner-like notification stack.",
-    markup: `<zen-notifications aria-label="Sonner demo">
-  <button type="button" data-notification-demo data-notification-id="sonner-demo" data-tone="success" data-message="Deployment complete">Show notification</button>
-</zen-notifications>`,
-  },
-  {
-    name: "Spinner",
-    slug: "spinner",
-    element: "zen-spinner",
-    group: "Feedback",
-    description: "A small CSS loading indicator with status semantics.",
-    markup: `<zen-spinner aria-label="Loading repositories"></zen-spinner>`,
-  },
-  {
-    name: "Switch",
-    slug: "switch",
-    element: "zen-switch",
-    group: "Forms",
-    description: "A native checkbox presented with switch semantics.",
-    markup: `<zen-switch><label><input type="checkbox" checked /> Automatic deployment</label></zen-switch>`,
-  },
-  {
-    name: "Table",
-    slug: "table",
-    element: "zen-table",
-    group: "Data",
-    description: "Responsive styling around a native HTML table.",
-    markup: `<zen-table><table>
-  <caption>Recent changesets</caption>
-  <thead><tr><th>Revision</th><th>Author</th></tr></thead>
-  <tbody><tr><td>253:fdf3816959cb</td><td>June</td></tr><tr><td>252:7a7581f040e8</td><td>June</td></tr></tbody>
-</table></zen-table>`,
-  },
-  {
-    name: "Tabs",
-    slug: "tabs",
-    element: "zen-tabs",
-    group: "Disclosure",
-    description: "ARIA tabs with automatic or manual keyboard activation.",
-    markup: `<zen-tabs>
-  <div role="tablist" aria-label="Repository views">
-    <button type="button" role="tab" data-value="files">Files</button>
-    <button type="button" role="tab" data-value="history">History</button>
-    <button type="button" role="tab" data-value="graph">Graph</button>
-  </div>
-  <section role="tabpanel">Browse repository files.</section>
-  <section role="tabpanel">Inspect changesets.</section>
-  <section role="tabpanel">View branch topology.</section>
-</zen-tabs>`,
-  },
-  {
-    name: "Textarea",
-    slug: "textarea",
-    element: "zen-textarea",
-    group: "Forms",
-    description: "A styled native multiline text control.",
-    markup: `<zen-textarea><textarea aria-label="Commit message" placeholder="Describe this change"></textarea></zen-textarea>`,
-  },
-  {
-    name: "Toast",
-    slug: "toast",
-    element: "zen-notifications",
-    group: "Feedback",
-    description: "The deprecated toast concept maps to zen-notifications.",
-    markup: `<zen-alert tone="warning"><p><strong>Toast is deprecated.</strong> Use <code>zen-notifications</code> for scoped transient messages.</p></zen-alert>`,
-  },
-  {
-    name: "Toggle",
-    slug: "toggle",
-    element: "zen-toggle",
-    group: "Actions",
-    description: "A native button with managed pressed state.",
-    markup: `<zen-toggle><button type="button">Bold</button></zen-toggle>`,
-  },
-  {
-    name: "Toggle Group",
-    slug: "toggle-group",
-    element: "zen-toggle-group",
-    group: "Actions",
-    description: "Single or multiple pressed-state buttons with roving keyboard focus.",
-    markup: `<zen-toggle-group type="single" value="center" aria-label="Alignment">
-  <button type="button" value="left">Left</button>
-  <button type="button" value="center">Center</button>
-  <button type="button" value="right">Right</button>
-</zen-toggle-group>`,
-  },
-  {
-    name: "Tooltip",
-    slug: "tooltip",
-    element: "zen-tooltip",
-    group: "Overlays",
-    description: "A delayed, non-interactive description for hover and focus.",
-    markup: `<zen-tooltip>
-  <button type="button" data-zen-trigger aria-label="Add repository"><zen-icon name="add"></zen-icon></button>
-  <span data-zen-content hidden>Add repository</span>
-</zen-tooltip>`,
-  },
-  {
-    name: "Typography",
-    slug: "typography",
-    element: "zen-typography",
-    group: "Foundations",
-    description: "Readable defaults for native headings, paragraphs, lists, and code.",
-    markup: `<zen-typography>
-  <h2>The Mercurial forge</h2>
-  <p>Typography stays semantic and inherits Zenbu tokens.</p>
-  <blockquote>Own the stack, understand the stack.</blockquote>
-</zen-typography>`,
-  },
-];
+import "./components/index.js";
+import { componentCatalog } from "./component_catalog.js";
+import { ICON_NAMES } from "./components/icon.js";
+
+const stackComponent = {
+  name: "Stack",
+  slug: "stack",
+  element: "zen-stack",
+  group: "Layout",
+  description: "A Zenbu-specific flex layout primitive with tokenized gaps.",
+  existing: true,
+};
+const displayedComponents = [...componentCatalog, stackComponent];
+
+const pages = new Map([
+  ["/", "overview"],
+  ["/components", "overview"],
+  ["/tokens", "tokens"],
+  ["/icons", "icons"],
+  ["/components/button", "button"],
+  ["/components/card", "card"],
+  ["/components/alert", "alert"],
+  ["/components/field", "field"],
+  ["/components/notifications", "notifications"],
+  ["/components/stack", "stack"],
+]);
+
+for (const component of componentCatalog) {
+  pages.set(`/components/${component.slug}`, component.slug);
+}
+
+function createCatalogLink(component) {
+  const link = document.createElement("a");
+  link.href = `/components/${component.slug}`;
+  link.dataset.catalogLink = "";
+  link.dataset.zenElement = component.element;
+  link.textContent = component.name;
+  return link;
+}
+
+function createComponentCard(component) {
+  const link = createCatalogLink(component);
+  const card = document.createElement("zen-card");
+  card.setAttribute("interactive", "");
+  const article = document.createElement("article");
+  const heading = document.createElement("h3");
+  heading.textContent = component.name;
+  const description = document.createElement("p");
+  description.textContent = component.description;
+  const element = document.createElement("code");
+  element.textContent = component.element;
+  article.append(heading, description, element);
+  card.append(article);
+  link.replaceChildren(card);
+  return link;
+}
+
+function createCatalogPage(component) {
+  const section = document.createElement("section");
+  section.className = "catalog-page";
+  section.dataset.catalogPage = component.slug;
+  section.hidden = true;
+
+  const header = document.createElement("header");
+  header.className = "page-heading";
+  const eyebrow = document.createElement("p");
+  eyebrow.className = "eyebrow";
+  eyebrow.textContent = component.group;
+  const heading = document.createElement("h1");
+  heading.textContent = component.name;
+  const description = document.createElement("p");
+  description.textContent = component.description;
+  header.append(eyebrow, heading, description);
+
+  const story = document.createElement("zen-story");
+  story.setAttribute("name", `${component.name} example`);
+  const template = document.createElement("template");
+  template.innerHTML = component.markup;
+  story.append(template);
+  section.append(header, story);
+  return section;
+}
+
+function installComponentCatalog() {
+  const navigation = document.querySelector(
+    '.catalog-nav[aria-label="Components"]',
+  );
+  const componentGrid = document.querySelector(".component-grid");
+  const main = document.querySelector("#catalogMain");
+  if (!navigation || !componentGrid || !main) return;
+
+  navigation.replaceChildren(
+    ...displayedComponents.map(createCatalogLink),
+  );
+  componentGrid.replaceChildren(
+    ...displayedComponents.map(createComponentCard),
+  );
+
+  for (const component of componentCatalog) {
+    if (component.existing) continue;
+    main.append(createCatalogPage(component));
+  }
+}
+
+function installIconCatalog() {
+  const grid = document.querySelector("#iconGrid");
+  if (!grid) return;
+  const items = ICON_NAMES.map(name => {
+    const figure = document.createElement("figure");
+    const icon = document.createElement("zen-icon");
+    icon.setAttribute("name", name);
+    icon.setAttribute("size", "2rem");
+    const caption = document.createElement("figcaption");
+    const code = document.createElement("code");
+    code.textContent = name;
+    caption.append(code);
+    figure.append(icon, caption);
+    return figure;
+  });
+  grid.replaceChildren(...items);
+}
 
-/** @const {number} Number of mapped shadcn component concepts. */
-export const shadcnComponentCount = componentCatalog.length;
+function installComponentSearch() {
+  const input = document.querySelector("#componentSearch");
+  const status = document.querySelector("#componentSearchStatus");
+  if (!input || !status) return;
+  const links = [
+    ...document.querySelectorAll(
+      '.catalog-nav[aria-label="Components"] a',
+    ),
+  ];
+  const cards = [...document.querySelectorAll(".component-grid > a")];
+  const descriptions = new Map(
+    displayedComponents.map(component => [
+      component.slug,
+      [
+        component.name,
+        component.element,
+        component.group,
+        component.description,
+      ].join(" ").toLocaleLowerCase(),
+    ]),
+  );
+  const filter = () => {
+    const query = input.value.trim().toLocaleLowerCase();
+    let matches = 0;
+    for (const link of links) {
+      const slug = new URL(link.href).pathname.split("/").pop();
+      const visible = !query || descriptions.get(slug)?.includes(query);
+      link.hidden = !visible;
+      if (visible) matches++;
+    }
+    for (const card of cards) {
+      const slug = new URL(card.href).pathname.split("/").pop();
+      card.hidden = Boolean(query) &&
+        !descriptions.get(slug)?.includes(query);
+    }
+    status.textContent = query
+      ? `${matches} component${matches === 1 ? "" : "s"} found`
+      : `${links.length} components`;
+  };
+
+  input.addEventListener("input", filter);
+  input.addEventListener("keydown", event => {
+    if (event.key !== "Escape" || !input.value) return;
+    input.value = "";
+    filter();
+  });
+  document.addEventListener("keydown", event => {
+    const target = event.target;
+    const typing = target instanceof HTMLElement &&
+      target.matches("input, textarea, select, [contenteditable]");
+    if (event.key !== "/" || typing || event.metaKey || event.ctrlKey ||
+        event.altKey) return;
+    event.preventDefault();
+    input.focus();
+    input.select();
+  });
+  filter();
+}
+
+function showPage(pathname) {
+  const pageName = pages.get(pathname) || "overview";
+  for (const page of document.querySelectorAll("[data-catalog-page]")) {
+    page.hidden = page.dataset.catalogPage !== pageName;
+  }
+  for (const link of document.querySelectorAll(
+    ".catalog-sidebar [data-catalog-link]",
+  )) {
+    const active = new URL(link.href).pathname === pathname;
+    if (active) link.setAttribute("aria-current", "page");
+    else link.removeAttribute("aria-current");
+  }
+  const heading = document.querySelector(
+    `[data-catalog-page="${pageName}"] h1`,
+  );
+  if (heading) document.title = `${heading.textContent} · Zenbu UI`;
+}
+
+window.addEventListener("DOMContentLoaded", () => {
+  installComponentCatalog();
+  installIconCatalog();
+  installComponentSearch();
+  const root = document.documentElement;
+  const systemTheme = matchMedia("(prefers-color-scheme: dark)");
+  const storedTheme = localStorage.getItem("zen-theme");
+  if (storedTheme) root.dataset.zenTheme = storedTheme;
+
+  const themeToggle = document.querySelector("#themeToggle");
+  const isDark = () => {
+    if (root.dataset.zenTheme) {
+      return root.dataset.zenTheme === "dark";
+    }
+    return systemTheme.matches;
+  };
+  const updateThemeButton = () => {
+    const dark = isDark();
+    themeToggle?.setAttribute("aria-pressed", String(dark));
+    if (themeToggle) {
+      themeToggle.textContent = dark
+        ? "Use light theme"
+        : "Use dark theme";
+    }
+  };
+  updateThemeButton();
+  themeToggle?.addEventListener("click", () => {
+    const next = isDark() ? "light" : "dark";
+    root.dataset.zenTheme = next;
+    localStorage.setItem("zen-theme", next);
+    updateThemeButton();
+  });
+  systemTheme.addEventListener("change", () => {
+    if (!root.dataset.zenTheme) updateThemeButton();
+  });
+
+  document.addEventListener("click", event => {
+    const notificationDemo = event.target.closest(
+      "[data-notification-demo]",
+    );
+    if (notificationDemo) {
+      const scope = notificationDemo.closest("zen-notifications");
+      if (!scope) return;
+      const tone = notificationDemo.dataset.tone || "info";
+      const baseId = notificationDemo.dataset.notificationId || tone;
+      const count = notificationDemo.dataset.burst === "true" ? 5 : 1;
+      for (let index = 0; index < count; index++) {
+        notificationDemo.dispatchEvent(new CustomEvent("zen-notify", {
+          bubbles: true,
+          composed: false,
+          detail: {
+            version: 1,
+            id: count > 1 ? `${baseId}-${Date.now()}-${index}` : baseId,
+            tone,
+            message: notificationDemo.dataset.message || "Notification",
+            description: notificationDemo.dataset.description,
+            announcement: tone === "error" ? "assertive" : "polite",
+            durationMs: 5000,
+            persistent: notificationDemo.dataset.persistent === "true",
+            action: notificationDemo.dataset.action === "true"
+              ? { token: `catalog-action-${Date.now()}`, label: "Retry" }
+              : undefined,
+          },
+        }));
+      }
+      return;
+    }
+
+    const dismissDemo = event.target.closest(
+      "[data-notification-dismiss-demo]",
+    );
+    if (dismissDemo) {
+      dismissDemo.dispatchEvent(new CustomEvent(
+        "zen-dismiss-notification",
+        {
+          bubbles: true,
+          composed: false,
+          detail: {
+            version: 1,
+            id: dismissDemo.dataset.notificationDismissDemo,
+          },
+        },
+      ));
+      return;
+    }
+
+    const link = event.target.closest("a[data-catalog-link]");
+    if (!link ||
+        link.origin !== location.origin ||
+        event.defaultPrevented ||
+        event.button !== 0 ||
+        event.metaKey ||
+        event.ctrlKey ||
+        event.shiftKey ||
+        event.altKey ||
+        link.hasAttribute("download") ||
+        link.target) return;
+    event.preventDefault();
+    history.pushState({}, "", link.href);
+    showPage(location.pathname);
+    document.querySelector("#catalogMain")?.focus();
+  });
+  window.addEventListener("popstate", () => showPage(location.pathname));
+  showPage(location.pathname);
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/component_catalog.js	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,818 @@
+/** @const {!ReadonlyArray<!Object>} Component concepts shown by the catalog. */
+export const componentCatalog = [
+  {
+    name: "Accordion",
+    slug: "accordion",
+    element: "zen-accordion",
+    group: "Disclosure",
+    description: "A group of native details elements with optional single-open behavior.",
+    markup: `<zen-accordion>
+  <details open><summary>Is it accessible?</summary><p>It keeps native details and summary semantics.</p></details>
+  <details><summary>Can several open?</summary><p>Add the multiple attribute to allow it.</p></details>
+</zen-accordion>`,
+  },
+  {
+    name: "Alert",
+    slug: "alert",
+    element: "zen-alert",
+    group: "Feedback",
+    description: "Status messaging with semantic tones and optional dismissal.",
+    existing: true,
+  },
+  {
+    name: "Alert Dialog",
+    slug: "alert-dialog",
+    element: "zen-alert-dialog",
+    group: "Overlays",
+    description: "A native modal dialog for decisions that require confirmation.",
+    markup: `<zen-alert-dialog>
+  <zen-button size="md" variant="danger">
+    <button type="button" data-zen-trigger>Delete deployment</button>
+  </zen-button>
+  <dialog>
+    <h3>Delete deployment?</h3>
+    <p>This action cannot be undone.</p>
+    <zen-button size="md" variant="quiet">
+      <button type="button" data-zen-close>Cancel</button>
+    </zen-button>
+    <zen-button size="md" variant="danger">
+      <button type="button" value="confirm" data-zen-close>Delete</button>
+    </zen-button>
+  </dialog>
+</zen-alert-dialog>`,
+  },
+  {
+    name: "Aspect Ratio",
+    slug: "aspect-ratio",
+    element: "zen-aspect-ratio",
+    group: "Layout",
+    description: "A media frame driven by a readable ratio attribute.",
+    markup: `<zen-aspect-ratio ratio="16/9">
+  <div class="demo-media">16 / 9</div>
+</zen-aspect-ratio>`,
+  },
+  {
+    name: "Attachment",
+    slug: "attachment",
+    element: "zen-attachment",
+    group: "Chat",
+    description: "File and upload state presentation using ordinary links and buttons.",
+    markup: `<zen-attachment state="complete">
+  <span aria-hidden="true">PDF</span>
+  <div><strong>release-notes.pdf</strong><small>248 KB · Ready</small></div>
+  <button type="button" aria-label="Remove attachment"><zen-icon name="close"></zen-icon></button>
+</zen-attachment>`,
+  },
+  {
+    name: "Avatar",
+    slug: "avatar",
+    element: "zen-avatar",
+    group: "Display",
+    description: "A compact identity image with a visible text fallback.",
+    markup: `<zen-avatar aria-label="June Park"><span>JP</span></zen-avatar>`,
+  },
+  {
+    name: "Badge",
+    slug: "badge",
+    element: "zen-badge",
+    group: "Display",
+    description: "A small label for metadata, state, or counts.",
+    markup: `<zen-stack direction="row">
+  <zen-badge>Default</zen-badge>
+  <zen-badge tone="success">Healthy</zen-badge>
+  <zen-badge tone="danger">Failed</zen-badge>
+</zen-stack>`,
+  },
+  {
+    name: "Breadcrumb",
+    slug: "breadcrumb",
+    element: "zen-breadcrumb",
+    group: "Navigation",
+    description: "A native navigation landmark for hierarchical location.",
+    markup: `<zen-breadcrumb>
+  <nav><ol>
+    <li><a href="/">Home</a></li>
+    <li><a href="/components">Components</a></li>
+    <li aria-current="page">Breadcrumb</li>
+  </ol></nav>
+</zen-breadcrumb>`,
+  },
+  {
+    name: "Bubble",
+    slug: "bubble",
+    element: "zen-bubble",
+    group: "Chat",
+    description: "A message bubble with incoming and outgoing alignment.",
+    markup: `<zen-stack>
+  <zen-bubble><p>The deployment is ready.</p></zen-bubble>
+  <zen-bubble align="end"><p>Ship it.</p></zen-bubble>
+</zen-stack>`,
+  },
+  {
+    name: "Box",
+    slug: "box",
+    element: "zen-box",
+    group: "Layout",
+    description: "A container with canonical xs through xl padding.",
+    markup: `<zen-stack direction="row">
+  <zen-box padding="xs">XS padding</zen-box>
+  <zen-box padding="sm">SM padding</zen-box>
+  <zen-box padding="md">MD padding</zen-box>
+  <zen-box padding="lg">LG padding</zen-box>
+  <zen-box padding="xl">XL padding</zen-box>
+</zen-stack>`,
+  },
+  {
+    name: "Button",
+    slug: "button",
+    element: "zen-button",
+    group: "Actions",
+    description: "Native buttons and links with shared variants and states.",
+    existing: true,
+  },
+  {
+    name: "Button Group",
+    slug: "button-group",
+    element: "zen-button-group",
+    group: "Actions",
+    description: "Related native buttons joined into one visual control.",
+    markup: `<zen-button-group aria-label="Text alignment">
+  <button type="button">Left</button>
+  <button type="button">Center</button>
+  <button type="button">Right</button>
+</zen-button-group>`,
+  },
+  {
+    name: "Calendar",
+    slug: "calendar",
+    element: "zen-calendar",
+    group: "Forms",
+    description: "A first-party date month grid backed by a native form value.",
+    markup: `<zen-calendar>
+  <label for="calendar-demo">Release date</label>
+  <input id="calendar-demo" type="date" value="2026-08-04" />
+</zen-calendar>`,
+  },
+  {
+    name: "Card",
+    slug: "card",
+    element: "zen-card",
+    group: "Display",
+    description: "A visual container around native article or section content.",
+    existing: true,
+  },
+  {
+    name: "Carousel",
+    slug: "carousel",
+    element: "zen-carousel",
+    group: "Collections",
+    description: "A scroll-snap collection with native buttons and keyboard controls.",
+    markup: `<zen-carousel aria-label="Recent projects">
+  <div data-zen-viewport>
+    <article>Mercurial forge</article>
+    <article>HLS player</article>
+    <article>LaTeX editor</article>
+  </div>
+  <button type="button" data-zen-prev aria-label="Previous slide"><zen-icon name="arrow-left"></zen-icon></button>
+  <button type="button" data-zen-next aria-label="Next slide"><zen-icon name="arrow-right"></zen-icon></button>
+</zen-carousel>`,
+  },
+  {
+    name: "Chart",
+    slug: "chart",
+    element: "zen-chart",
+    group: "Data",
+    description: "A dependency-free chart frame for semantic labels and custom marks.",
+    markup: `<zen-chart aria-label="Build minutes by day">
+  <div data-zen-chart-plot>
+    <span style="--zen-chart-value: 42%" data-label="Mon"></span>
+    <span style="--zen-chart-value: 76%" data-label="Tue"></span>
+    <span style="--zen-chart-value: 58%" data-label="Wed"></span>
+    <span style="--zen-chart-value: 88%" data-label="Thu"></span>
+  </div>
+</zen-chart>`,
+  },
+  {
+    name: "Checkbox",
+    slug: "checkbox",
+    element: "zen-checkbox",
+    group: "Forms",
+    description: "A styled native checkbox that remains form-associated.",
+    markup: `<zen-checkbox>
+  <label><input type="checkbox" checked /> Include deployment artifacts</label>
+</zen-checkbox>`,
+  },
+  {
+    name: "Collapsible",
+    slug: "collapsible",
+    element: "zen-collapsible",
+    group: "Disclosure",
+    description: "A single native details disclosure.",
+    markup: `<zen-collapsible>
+  <details><summary>Three changed files</summary><p>server.c, styles.css, README.md</p></details>
+</zen-collapsible>`,
+  },
+  {
+    name: "Combobox",
+    slug: "combobox",
+    element: "zen-combobox",
+    group: "Forms",
+    description: "A filterable text input backed by an accessible option list.",
+    markup: `<zen-combobox>
+  <label for="repo-combobox">Repository</label>
+  <input id="repo-combobox" autocomplete="off" placeholder="Find repository" />
+  <div role="listbox">
+    <button type="button" role="option" data-value="zenbu">zenbu</button>
+    <button type="button" role="option" data-value="hg-web">hg-web</button>
+    <button type="button" role="option" data-value="seobeo">seobeo</button>
+  </div>
+</zen-combobox>`,
+  },
+  {
+    name: "Command",
+    slug: "command",
+    element: "zen-command",
+    group: "Navigation",
+    description: "A keyboard-first filterable command list.",
+    markup: `<zen-command>
+  <input type="search" aria-label="Commands" placeholder="Type a command" />
+  <div role="menu">
+    <button type="button" role="menuitem" data-value="new">New repository</button>
+    <button type="button" role="menuitem" data-value="deploy">Deploy release</button>
+    <button type="button" role="menuitem" data-value="theme">Toggle theme</button>
+  </div>
+</zen-command>`,
+  },
+  {
+    name: "Context Menu",
+    slug: "context-menu",
+    element: "zen-context-menu",
+    group: "Menus",
+    description: "A right-click menu with keyboard navigation and native buttons.",
+    markup: `<zen-context-menu>
+  <div data-zen-trigger tabindex="0">Right-click this repository</div>
+  <div role="menu" hidden>
+    <button type="button" role="menuitem">Open</button>
+    <button type="button" role="menuitem">Clone</button>
+    <button type="button" role="menuitem">Archive</button>
+  </div>
+</zen-context-menu>`,
+  },
+  {
+    name: "Data Table",
+    slug: "data-table",
+    element: "zen-data-table",
+    group: "Data",
+    description: "A native table enhanced with optional client-side sorting.",
+    markup: `<zen-data-table>
+  <table>
+    <thead><tr>
+      <th><button type="button" data-zen-sort="name">Repository</button></th>
+      <th><button type="button" data-zen-sort="commits">Commits</button></th>
+    </tr></thead>
+    <tbody>
+      <tr><td data-key="name">seobeo</td><td data-key="commits">87</td></tr>
+      <tr><td data-key="name">hg-web</td><td data-key="commits">142</td></tr>
+      <tr><td data-key="name">design-system</td><td data-key="commits">12</td></tr>
+    </tbody>
+  </table>
+</zen-data-table>`,
+  },
+  {
+    name: "Date Picker",
+    slug: "date-picker",
+    element: "zen-date-picker",
+    group: "Forms",
+    description: "A tokenized date trigger and first-party keyboard calendar.",
+    markup: `<zen-date-picker>
+  <label for="date-picker-demo">Deploy on</label>
+  <input id="date-picker-demo" type="date" />
+</zen-date-picker>`,
+  },
+  {
+    name: "Dialog",
+    slug: "dialog",
+    element: "zen-dialog",
+    group: "Overlays",
+    description: "A native modal dialog with trigger and close wiring.",
+    markup: `<zen-dialog>
+  <zen-button size="md">
+    <button type="button" data-zen-trigger>Edit profile</button>
+  </zen-button>
+  <dialog>
+    <h3>Edit profile</h3>
+    <zen-field>
+      <label>Display name</label>
+      <input value="June" />
+    </zen-field>
+    <zen-button size="md">
+      <button type="button" data-zen-close>Done</button>
+    </zen-button>
+  </dialog>
+</zen-dialog>`,
+  },
+  {
+    name: "Direction",
+    slug: "direction",
+    element: "zen-direction",
+    group: "Utilities",
+    description: "A light-DOM boundary for left-to-right or right-to-left content.",
+    markup: `<zen-direction dir="rtl"><p>مرحبا بالعالم</p></zen-direction>`,
+  },
+  {
+    name: "Drawer",
+    slug: "drawer",
+    element: "zen-drawer",
+    group: "Overlays",
+    description: "A native dialog presented as an edge drawer.",
+    markup: `<zen-drawer placement="bottom">
+  <zen-button size="md">
+    <button type="button" data-zen-trigger>Open drawer</button>
+  </zen-button>
+  <dialog>
+    <h3>Build queue</h3>
+    <p>Two jobs are running.</p>
+    <zen-button size="md">
+      <button type="button" data-zen-close>Close</button>
+    </zen-button>
+  </dialog>
+</zen-drawer>`,
+  },
+  {
+    name: "Dropdown Menu",
+    slug: "dropdown-menu",
+    element: "zen-dropdown-menu",
+    group: "Menus",
+    description: "A button-owned action menu with arrow-key navigation.",
+    markup: `<zen-dropdown-menu>
+  <button type="button" data-zen-trigger>Repository actions</button>
+  <div role="menu" hidden>
+    <button type="button" role="menuitem">Clone</button>
+    <button type="button" role="menuitem">Bookmark</button>
+    <button type="button" role="menuitem">Archive</button>
+  </div>
+</zen-dropdown-menu>`,
+  },
+  {
+    name: "Empty",
+    slug: "empty",
+    element: "zen-empty",
+    group: "Feedback",
+    description: "A structured empty state with an optional native action.",
+    markup: `<zen-empty>
+  <strong>No deployments yet</strong>
+  <p>Create the first release from the current default branch.</p>
+  <zen-button size="md"><button type="button">Create deployment</button></zen-button>
+</zen-empty>`,
+  },
+  {
+    name: "Field",
+    slug: "field",
+    element: "zen-field",
+    group: "Forms",
+    description: "Label, help text, validity, and a native form control.",
+    existing: true,
+  },
+  {
+    name: "Form",
+    slug: "form",
+    element: "zen-form",
+    group: "Forms",
+    description: "A native form boundary with visible browser validity state.",
+    markup: `<zen-form>
+  <form>
+    <zen-field><label>Repository name</label><input required /><small>Required</small></zen-field>
+    <zen-button size="md"><button type="submit">Create</button></zen-button>
+  </form>
+</zen-form>`,
+  },
+  {
+    name: "Hover Card",
+    slug: "hover-card",
+    element: "zen-hover-card",
+    group: "Overlays",
+    description: "Supplemental content shown on hover or keyboard focus.",
+    markup: `<zen-hover-card>
+  <a href="#" data-zen-trigger>@mrjunejune</a>
+  <div data-zen-content hidden><strong>June Park</strong><p>Building Zenbu in C and native HTML.</p></div>
+</zen-hover-card>`,
+  },
+  {
+    name: "Heading",
+    slug: "heading",
+    element: "zen-heading",
+    group: "Typography",
+    description: "Strong native headings on the canonical type scale.",
+    markup: `<zen-stack>
+  <zen-heading size="xs"><h3>Extra small heading</h3></zen-heading>
+  <zen-heading size="sm"><h3>Small heading</h3></zen-heading>
+  <zen-heading size="md"><h3>Medium heading</h3></zen-heading>
+  <zen-heading size="lg"><h3>Large heading</h3></zen-heading>
+  <zen-heading size="xl"><h3>Extra large heading</h3></zen-heading>
+</zen-stack>`,
+  },
+  {
+    name: "Input",
+    slug: "input",
+    element: "zen-input",
+    group: "Forms",
+    description: "A styled native input with no replacement semantics.",
+    markup: `<zen-input><input type="email" placeholder="[email protected]" aria-label="Email" /></zen-input>`,
+  },
+  {
+    name: "Input Group",
+    slug: "input-group",
+    element: "zen-input-group",
+    group: "Forms",
+    description: "A native input with prefix, suffix, or inline actions.",
+    markup: `<zen-input-group>
+  <span aria-hidden="true">https://</span>
+  <input aria-label="Host" value="zenbu.babocoder.com" />
+  <button type="button">Copy</button>
+</zen-input-group>`,
+  },
+  {
+    name: "Input OTP",
+    slug: "input-otp",
+    element: "zen-input-otp",
+    group: "Forms",
+    description: "A single native one-time-code input with visual slots.",
+    markup: `<zen-input-otp>
+  <label for="otp-demo">Verification code</label>
+  <input id="otp-demo" inputmode="numeric" autocomplete="one-time-code" maxlength="6" />
+  <div data-zen-otp-slots aria-hidden="true"></div>
+</zen-input-otp>`,
+  },
+  {
+    name: "Item",
+    slug: "item",
+    element: "zen-item",
+    group: "Display",
+    description: "A flexible list row for an icon, content, and actions.",
+    markup: `<zen-item>
+  <zen-icon name="repository"></zen-icon>
+  <div><strong>hg-web</strong><small>Updated two minutes ago</small></div>
+  <zen-button size="sm" variant="quiet"><button type="button">Open</button></zen-button>
+</zen-item>`,
+  },
+  {
+    name: "Kbd",
+    slug: "kbd",
+    element: "zen-kbd",
+    group: "Display",
+    description: "Keyboard shortcut presentation using native kbd elements.",
+    markup: `<p>Open commands with <zen-kbd><kbd>Ctrl</kbd><span>+</span><kbd>K</kbd></zen-kbd>.</p>`,
+  },
+  {
+    name: "Label",
+    slug: "label",
+    element: "zen-label",
+    group: "Forms",
+    description: "A styled native label that keeps browser association.",
+    markup: `<zen-label><label for="label-demo">Branch name</label></zen-label>
+<zen-input><input id="label-demo" value="default" /></zen-input>`,
+  },
+  {
+    name: "Link",
+    slug: "link",
+    element: "zen-link",
+    group: "Navigation",
+    description: "A native link with optional reusable first-party effects.",
+    markup: `<zen-link effect="paw">
+  <a href="/components/link">A link with the paw effect</a>
+</zen-link>`,
+  },
+  {
+    name: "Marker",
+    slug: "marker",
+    element: "zen-marker",
+    group: "Chat",
+    description: "An inline system marker for chat and activity streams.",
+    markup: `<zen-marker><span>Today</span></zen-marker>`,
+  },
+  {
+    name: "Menubar",
+    slug: "menubar",
+    element: "zen-menubar",
+    group: "Menus",
+    description: "A horizontal application menu using native buttons and menu roles.",
+    markup: `<zen-menubar>
+  <button type="button" data-zen-trigger>File</button>
+  <div role="menu" hidden><button role="menuitem">New</button><button role="menuitem">Open</button></div>
+  <button type="button" data-zen-trigger>View</button>
+  <div role="menu" hidden><button role="menuitem">Graph</button><button role="menuitem">History</button></div>
+</zen-menubar>`,
+  },
+  {
+    name: "Message",
+    slug: "message",
+    element: "zen-message",
+    group: "Chat",
+    description: "An avatar, author, and content row for conversations.",
+    markup: `<zen-message>
+  <zen-avatar aria-label="June"><span>JP</span></zen-avatar>
+  <div><strong>June</strong><zen-bubble><p>Can we deploy this release?</p></zen-bubble></div>
+</zen-message>`,
+  },
+  {
+    name: "Message Scroller",
+    slug: "message-scroller",
+    element: "zen-message-scroller",
+    group: "Chat",
+    description: "A chat viewport that follows new content until the reader scrolls away.",
+    markup: `<zen-message-scroller>
+  <div data-zen-viewport>
+    <p>Worker connected.</p><p>Build started.</p><p>Bundle created.</p><p>Deployment complete.</p>
+  </div>
+  <button type="button" data-zen-scroll-end hidden>Jump to latest</button>
+</zen-message-scroller>`,
+  },
+  {
+    name: "Native Select",
+    slug: "native-select",
+    element: "zen-native-select",
+    group: "Forms",
+    description: "A styled native select with full platform behavior.",
+    markup: `<zen-native-select><select aria-label="Environment"><option>Development</option><option>Production</option></select></zen-native-select>`,
+  },
+  {
+    name: "Navigation Menu",
+    slug: "navigation-menu",
+    element: "zen-navigation-menu",
+    group: "Navigation",
+    description: "Top-level navigation with optional keyboard-accessible flyouts.",
+    markup: `<zen-navigation-menu>
+  <nav aria-label="Products">
+    <button type="button" data-zen-trigger>Projects</button>
+    <div role="menu" hidden><a role="menuitem" href="/components">Zenbu UI</a><a role="menuitem" href="/">hg-web</a></div>
+    <a href="/tokens">Tokens</a>
+  </nav>
+</zen-navigation-menu>`,
+  },
+  {
+    name: "Pagination",
+    slug: "pagination",
+    element: "zen-pagination",
+    group: "Navigation",
+    description: "Page navigation built from native links.",
+    markup: `<zen-pagination>
+  <nav><a href="#">Previous</a><a href="#">1</a><a href="#" aria-current="page">2</a><a href="#">3</a><a href="#">Next</a></nav>
+</zen-pagination>`,
+  },
+  {
+    name: "Popover",
+    slug: "popover",
+    element: "zen-popover",
+    group: "Overlays",
+    description: "A lightweight panel using the native Popover API when available.",
+    markup: `<zen-popover>
+  <zen-button size="md">
+    <button type="button" data-zen-trigger>Open settings</button>
+  </zen-button>
+  <div data-zen-content>
+    <strong>Dimensions</strong>
+    <zen-field><label>Width</label><input value="100%" /></zen-field>
+  </div>
+</zen-popover>`,
+  },
+  {
+    name: "Progress",
+    slug: "progress",
+    element: "zen-progress",
+    group: "Feedback",
+    description: "A styled native progress element.",
+    markup: `<zen-progress><label for="progress-demo">Uploading</label><progress id="progress-demo" value="68" max="100">68%</progress></zen-progress>`,
+  },
+  {
+    name: "Radio Group",
+    slug: "radio-group",
+    element: "zen-radio-group",
+    group: "Forms",
+    description: "A fieldset of native radio inputs.",
+    markup: `<zen-radio-group>
+  <fieldset><legend>Visibility</legend>
+    <label><input type="radio" name="visibility" checked /> Public</label>
+    <label><input type="radio" name="visibility" /> Private</label>
+  </fieldset>
+</zen-radio-group>`,
+  },
+  {
+    name: "Resizable",
+    slug: "resizable",
+    element: "zen-resizable",
+    group: "Layout",
+    description: "Two native panels separated by a pointer and keyboard handle.",
+    markup: `<zen-resizable>
+  <section data-zen-panel>Repository tree</section>
+  <div data-zen-handle tabindex="0"></div>
+  <section data-zen-panel>File preview</section>
+</zen-resizable>`,
+  },
+  {
+    name: "Scroll Area",
+    slug: "scroll-area",
+    element: "zen-scroll-area",
+    group: "Layout",
+    description: "A bounded native scroll container with theme-aware scrollbars.",
+    markup: `<zen-scroll-area tabindex="0">
+  <p>default</p><p>feature/design-system</p><p>release/2026-08</p><p>experiment/trading</p>
+</zen-scroll-area>`,
+  },
+  {
+    name: "Select",
+    slug: "select",
+    element: "zen-select",
+    group: "Forms",
+    description: "A native select styled as the default accessible implementation.",
+    markup: `<zen-select><label>Branch <select><option>default</option><option>stable</option></select></label></zen-select>`,
+  },
+  {
+    name: "Separator",
+    slug: "separator",
+    element: "zen-separator",
+    group: "Layout",
+    description: "A native horizontal rule or ARIA separator.",
+    markup: `<div>Repository</div><zen-separator><hr /></zen-separator><div>Changesets</div>`,
+  },
+  {
+    name: "Sheet",
+    slug: "sheet",
+    element: "zen-sheet",
+    group: "Overlays",
+    description: "A native dialog presented from a selected screen edge.",
+    markup: `<zen-sheet placement="right">
+  <zen-button size="md">
+    <button type="button" data-zen-trigger>Open filters</button>
+  </zen-button>
+  <dialog>
+    <h3>Filters</h3>
+    <zen-field><label>Author</label><input /></zen-field>
+    <zen-button size="md">
+      <button type="button" data-zen-close>Apply</button>
+    </zen-button>
+  </dialog>
+</zen-sheet>`,
+  },
+  {
+    name: "Sidebar",
+    slug: "sidebar",
+    element: "zen-sidebar",
+    group: "Navigation",
+    description: "A collapsible navigation region with an explicit native trigger.",
+    markup: `<zen-sidebar open>
+  <button type="button" data-zen-sidebar-trigger>Toggle sidebar</button>
+  <aside data-zen-sidebar-panel><nav><a href="/">Overview</a><a href="/components">Components</a><a href="/tokens">Tokens</a></nav></aside>
+</zen-sidebar>`,
+  },
+  {
+    name: "Skeleton",
+    slug: "skeleton",
+    element: "zen-skeleton",
+    group: "Feedback",
+    description: "A reduced-motion-safe placeholder for pending content.",
+    markup: `<zen-stack>
+  <zen-skeleton shape="circle"></zen-skeleton>
+  <zen-skeleton></zen-skeleton>
+  <zen-skeleton width="60%"></zen-skeleton>
+</zen-stack>`,
+  },
+  {
+    name: "Slider",
+    slug: "slider",
+    element: "zen-slider",
+    group: "Forms",
+    description: "A native range input with browser keyboard and pointer behavior.",
+    markup: `<zen-slider><label for="slider-demo">Volume</label><input id="slider-demo" type="range" value="65" /></zen-slider>`,
+  },
+  {
+    name: "Notifications",
+    slug: "notifications",
+    element: "zen-notifications",
+    group: "Feedback",
+    description: "A bounded, scoped notification stack.",
+    existing: true,
+  },
+  {
+    name: "Spinner",
+    slug: "spinner",
+    element: "zen-spinner",
+    group: "Feedback",
+    description: "A small CSS loading indicator with status semantics.",
+    markup: `<zen-spinner aria-label="Loading repositories"></zen-spinner>`,
+  },
+  {
+    name: "Switch",
+    slug: "switch",
+    element: "zen-switch",
+    group: "Forms",
+    description: "A native checkbox presented with switch semantics.",
+    markup: `<zen-switch><label><input type="checkbox" checked /> Automatic deployment</label></zen-switch>`,
+  },
+  {
+    name: "Table",
+    slug: "table",
+    element: "zen-table",
+    group: "Data",
+    description: "Responsive styling around a native HTML table.",
+    markup: `<zen-table><table>
+  <caption>Recent changesets</caption>
+  <thead><tr><th>Revision</th><th>Author</th></tr></thead>
+  <tbody><tr><td>253:fdf3816959cb</td><td>June</td></tr><tr><td>252:7a7581f040e8</td><td>June</td></tr></tbody>
+</table></zen-table>`,
+  },
+  {
+    name: "Tabs",
+    slug: "tabs",
+    element: "zen-tabs",
+    group: "Disclosure",
+    description: "ARIA tabs with automatic or manual keyboard activation.",
+    markup: `<zen-tabs>
+  <div role="tablist" aria-label="Repository views">
+    <button type="button" role="tab" data-value="files">Files</button>
+    <button type="button" role="tab" data-value="history">History</button>
+    <button type="button" role="tab" data-value="graph">Graph</button>
+  </div>
+  <section role="tabpanel">Browse repository files.</section>
+  <section role="tabpanel">Inspect changesets.</section>
+  <section role="tabpanel">View branch topology.</section>
+</zen-tabs>`,
+  },
+  {
+    name: "Textarea",
+    slug: "textarea",
+    element: "zen-textarea",
+    group: "Forms",
+    description: "A styled native multiline text control.",
+    markup: `<zen-textarea><textarea aria-label="Commit message" placeholder="Describe this change"></textarea></zen-textarea>`,
+  },
+  {
+    name: "Text",
+    slug: "text",
+    element: "zen-text",
+    group: "Typography",
+    description: "Native text on the canonical xs through xl type scale.",
+    markup: `<zen-stack>
+  <zen-text size="xs"><p>Extra small text</p></zen-text>
+  <zen-text size="sm"><p>Small text</p></zen-text>
+  <zen-text size="md"><p>Medium text</p></zen-text>
+  <zen-text size="lg"><p>Large text</p></zen-text>
+  <zen-text size="xl"><p>Extra large text</p></zen-text>
+</zen-stack>`,
+  },
+  {
+    name: "Toast",
+    slug: "toast",
+    element: "zen-notifications",
+    group: "Feedback",
+    description: "The deprecated toast concept maps to zen-notifications.",
+    markup: `<zen-alert tone="warning"><p><strong>Toast is deprecated.</strong> Use <code>zen-notifications</code> for scoped transient messages.</p></zen-alert>`,
+  },
+  {
+    name: "Toggle",
+    slug: "toggle",
+    element: "zen-toggle",
+    group: "Actions",
+    description: "A native button with managed pressed state.",
+    markup: `<zen-toggle><button type="button">Bold</button></zen-toggle>`,
+  },
+  {
+    name: "Toggle Group",
+    slug: "toggle-group",
+    element: "zen-toggle-group",
+    group: "Actions",
+    description: "Single or multiple pressed-state buttons with roving keyboard focus.",
+    markup: `<zen-toggle-group type="single" value="center" aria-label="Alignment">
+  <button type="button" value="left">Left</button>
+  <button type="button" value="center">Center</button>
+  <button type="button" value="right">Right</button>
+</zen-toggle-group>`,
+  },
+  {
+    name: "Tooltip",
+    slug: "tooltip",
+    element: "zen-tooltip",
+    group: "Overlays",
+    description: "A delayed, non-interactive description for hover and focus.",
+    markup: `<zen-tooltip>
+  <zen-button size="sm" variant="quiet">
+    <button type="button" data-zen-trigger aria-label="Add repository"><zen-icon name="add"></zen-icon></button>
+  </zen-button>
+  <span data-zen-content hidden>Add repository</span>
+</zen-tooltip>`,
+  },
+  {
+    name: "Typography",
+    slug: "typography",
+    element: "zen-typography",
+    group: "Foundations",
+    description: "Readable defaults for native headings, paragraphs, lists, and code.",
+    markup: `<zen-typography>
+  <h2>The Mercurial forge</h2>
+  <p>Typography stays semantic and inherits Zenbu tokens.</p>
+  <blockquote>Own the stack, understand the stack.</blockquote>
+</zen-typography>`,
+  },
+];
+
+/** @const {number} Number of component concepts in the catalog. */
+export const componentConceptCount = componentCatalog.length;
--- a/design_system/src/components/icon.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/components/icon.js	Wed Aug 05 05:25:40 2026 -0700
@@ -28,7 +28,21 @@
   menu: ["M4 6h16", "M4 12h16", "M4 18h16"],
   moon: ["M20 15a8 8 0 0 1-11-11 9 9 0 1 0 11 11Z"],
   more: ["M5 12h.01", "M12 12h.01", "M19 12h.01"],
+  offline: [
+    "M5 12a7 7 0 0 1 10.5-6",
+    "M19 12a7 7 0 0 0-.7-3",
+    "M8.5 15.5a5 5 0 0 1 7 0",
+    "M11.5 19h1",
+    "M3 3l18 18",
+  ],
   pause: ["M8 5v14", "M16 5v14"],
+  paw: [
+    "M8 11c-1.7 0-3-1.5-3-3.3S6 4.5 7.7 4.5s2.5 1.5 2.5 3.3S9.7 11 8 11Z",
+    "M16 11c-1.7 0-2.2-1.5-2.2-3.2s.8-3.3 2.5-3.3S19 6 19 7.7 17.7 11 16 11Z",
+    "M5.3 15c-1.5 0-2.8-1.2-2.8-2.7s1.2-2.8 2.7-2.8S8 10.7 8 12.2 6.8 15 5.3 15Z",
+    "M18.7 15c-1.5 0-2.7-1.2-2.7-2.8s1.2-2.7 2.8-2.7 2.7 1.2 2.7 2.8-1.3 2.7-2.8 2.7Z",
+    "M7 18.5c0-3 2.2-5.5 5-5.5s5 2.5 5 5.5c0 1.5-1.2 2.5-2.7 2.5-.8 0-1.5-.4-2.3-.4s-1.5.4-2.3.4C8.2 21 7 20 7 18.5Z",
+  ],
   play: ["m8 5 11 7-11 7Z"],
   repository: ["M4 4h13a3 3 0 0 1 3 3v13H7a3 3 0 0 1-3-3Z", "M8 4v16"],
   retry: ["M4 4v6h6", "M5 9a8 8 0 1 1 2 8"],
@@ -99,7 +113,10 @@
       this.setAttribute("aria-hidden", "true");
     }
     this.dataset.zenIcon = known ? requested : "alert";
-    this.style.setProperty("--zen-icon-size", safeSize(this.getAttribute("size")));
+    this.style.setProperty(
+      "--zenbu-icon-size",
+      safeSize(this.getAttribute("size")),
+    );
     this.replaceChildren(svg);
   }
 }
--- a/design_system/src/components/index.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/components/index.js	Wed Aug 05 05:25:40 2026 -0700
@@ -30,6 +30,7 @@
   ZenSwitch,
 } from "./forms.js";
 export { ICON_NAMES, ZenIcon } from "./icon.js";
+export { ZenLink } from "./link.js";
 export {
   ZenNotifications,
   validateNotification,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/link.js	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,53 @@
+/**
+ * Adds an optional reusable effect to one direct native link.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenLink extends HTMLElement {
+  static get observedAttributes() {
+    return ["effect"];
+  }
+
+  connectedCallback() {
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeGeneratedDecoration();
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected) this.sync();
+  }
+
+  removeGeneratedDecoration() {
+    this.querySelector(
+      ':scope > a > zen-icon[data-zen-link-decoration][data-zen-generated="true"]',
+    )?.remove();
+  }
+
+  sync() {
+    const link = this.querySelector(":scope > a");
+    if (!link || this.getAttribute("effect") !== "paw") {
+      this.removeGeneratedDecoration();
+      return;
+    }
+    let decoration = link.querySelector(
+      ":scope > zen-icon[data-zen-link-decoration]",
+    );
+    if (!decoration) {
+      decoration = document.createElement("zen-icon");
+      decoration.dataset.zenLinkDecoration = "";
+      decoration.dataset.zenGenerated = "true";
+      decoration.setAttribute("name", "paw");
+      link.prepend(decoration);
+    }
+  }
+}
+
+if (!customElements.get("zen-link")) {
+  customElements.define("zen-link", ZenLink);
+}
--- a/design_system/src/components/notifications.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/components/notifications.js	Wed Aug 05 05:25:40 2026 -0700
@@ -13,6 +13,17 @@
     (allowEmpty || value.trim().length > 0);
 }
 
+function resolveCssLength(element, property, fallback) {
+  const probe = document.createElement("span");
+  probe.style.position = "absolute";
+  probe.style.inlineSize = `var(${property})`;
+  probe.style.visibility = "hidden";
+  element.append(probe);
+  const value = Number.parseFloat(getComputedStyle(probe).inlineSize);
+  probe.remove();
+  return Number.isFinite(value) ? value : fallback;
+}
+
 /**
  * Validates and normalizes a notification event record.
  *
@@ -85,7 +96,7 @@
 }
 
 /**
- * Renders a bounded, scoped, Sonner-like notification queue.
+ * Renders a bounded, scoped notification queue.
  *
  * @extends {HTMLElement}
  */
@@ -496,13 +507,11 @@
     const visible = [...this.#records.values()]
       .slice(-MAX_VISIBLE)
       .filter(record => record.view?.article.isConnected);
-    const styles = getComputedStyle(this.stack);
-    const configuredGap = Number.parseFloat(
-      styles.getPropertyValue("--zen-notification-gap"),
+    const gap = resolveCssLength(
+      this.stack,
+      "--zenbu-notification-gap",
+      12,
     );
-    const gap = Number.isFinite(configuredGap)
-      ? configuredGap
-      : 12;
     let expandedHeight = 0;
     let newestHeight = 0;
 
@@ -513,24 +522,24 @@
       const height = article.offsetHeight;
       if (depth === 0) newestHeight = height;
       article.style.setProperty(
-        "--zen-notification-depth",
+        "--zenbu-notification-depth",
         String(depth),
       );
       article.style.setProperty(
-        "--zen-notification-collapsed-offset",
+        "--zenbu-notification-collapsed-offset",
         `${-depth * 10}px`,
       );
       article.style.setProperty(
-        "--zen-notification-collapsed-opacity",
+        "--zenbu-notification-collapsed-opacity",
         String(Math.max(0.55, 1 - depth * 0.18)),
       );
       article.dataset.depth = String(depth);
       article.style.setProperty(
-        "--zen-notification-offset",
+        "--zenbu-notification-offset",
         `${-expandedHeight}px`,
       );
       article.style.setProperty(
-        "--zen-notification-scale",
+        "--zenbu-notification-scale",
         String(Math.max(0.88, 1 - depth * 0.055)),
       );
       article.style.zIndex = String(visible.length - depth);
@@ -539,11 +548,11 @@
 
     this.stack.dataset.count = String(visible.length);
     this.stack.style.setProperty(
-      "--zen-notification-collapsed-height",
+      "--zenbu-notification-collapsed-height",
       `${newestHeight + Math.max(0, visible.length - 1) * 10}px`,
     );
     this.stack.style.setProperty(
-      "--zen-notification-expanded-height",
+      "--zenbu-notification-expanded-height",
       `${Math.max(0, expandedHeight - gap)}px`,
     );
   }
--- a/design_system/src/components/primitives.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/components/primitives.js	Wed Aug 05 05:25:40 2026 -0700
@@ -6,6 +6,7 @@
   "zen-badge",
   "zen-breadcrumb",
   "zen-bubble",
+  "zen-box",
   "zen-button-group",
   "zen-chart",
   "zen-direction",
@@ -15,6 +16,7 @@
   "zen-item",
   "zen-kbd",
   "zen-label",
+  "zen-heading",
   "zen-marker",
   "zen-message",
   "zen-native-select",
@@ -25,6 +27,7 @@
   "zen-skeleton",
   "zen-spinner",
   "zen-table",
+  "zen-text",
   "zen-textarea",
   "zen-typography",
 ];
@@ -60,7 +63,7 @@
     switch (this.localName) {
       case "zen-aspect-ratio":
         this.style.setProperty(
-          "--zen-aspect-ratio",
+          "--zenbu-aspect-ratio",
           parseRatio(this.getAttribute("ratio")),
         );
         break;
@@ -118,11 +121,11 @@
       case "zen-skeleton":
         if (this.hasAttribute("width")) {
           this.style.setProperty(
-            "--zen-skeleton-width",
+            "--zenbu-skeleton-width",
             this.getAttribute("width"),
           );
         } else {
-          this.style.removeProperty("--zen-skeleton-width");
+          this.style.removeProperty("--zenbu-skeleton-width");
         }
         if (!this.hasAttribute("role")) this.setAttribute("aria-hidden", "true");
         break;
--- a/design_system/src/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -8,8 +8,8 @@
     <link rel="stylesheet" href="/styles/tokens.css" />
     <link rel="stylesheet" href="/styles/themes.css" />
     <link rel="stylesheet" href="/styles/components.css" />
-    <link rel="stylesheet" href="/storybook.css" />
-    <script type="module" src="/storybook.js"></script>
+    <link rel="stylesheet" href="/catalog.css" />
+    <script type="module" src="/catalog.js"></script>
   </head>
   <body>
     <div class="catalog-shell">
@@ -50,9 +50,11 @@
           <a href="/components/stack" data-catalog-link>Stack</a>
         </nav>
 
-        <button id="themeToggle" class="theme-toggle" type="button">
-          Toggle theme
-        </button>
+        <zen-button class="theme-toggle-wrap" appearance="plain" size="sm">
+          <button id="themeToggle" class="theme-toggle" type="button">
+            Toggle theme
+          </button>
+        </zen-button>
       </aside>
 
       <main id="catalogMain" class="catalog-main" tabindex="-1">
@@ -175,6 +177,25 @@
               </zen-stack>
             </section>
             <section class="token-group">
+              <h2>Size scale</h2>
+              <zen-stack gap="tight">
+                <code>xs · sm · md · lg · xl</code>
+                <code>--zenbu-sys-control-height-*</code>
+                <code>--zenbu-sys-control-padding-*</code>
+                <code>--zenbu-sys-font-size-* / --zenbu-sys-line-height-*</code>
+                <code>--zenbu-sys-padding-* / --zenbu-sys-icon-size-*</code>
+              </zen-stack>
+            </section>
+            <section class="token-group token-group-wide">
+              <h2>Token layers</h2>
+              <zen-stack direction="row">
+                <code>--zenbu-ref-* · available values</code>
+                <code>--zenbu-sys-* · semantic intent</code>
+                <code>--zenbu-&lt;component&gt;-* · local aliases</code>
+              </zen-stack>
+              <p>Components consume semantic intent. Themes and density remap the system layer.</p>
+            </section>
+            <section class="token-group">
               <h2>Shape</h2>
               <zen-stack gap="tight">
                 <code>--zen-radius-sm</code>
@@ -210,6 +231,17 @@
               </zen-stack>
             </template>
           </zen-story>
+          <zen-story name="Sizes">
+            <template>
+              <zen-stack direction="row">
+                <zen-button size="xs"><button type="button">Extra small</button></zen-button>
+                <zen-button size="sm"><button type="button">Small</button></zen-button>
+                <zen-button size="md"><button type="button">Medium</button></zen-button>
+                <zen-button size="lg"><button type="button">Large</button></zen-button>
+                <zen-button size="xl"><button type="button">Extra large</button></zen-button>
+              </zen-stack>
+            </template>
+          </zen-story>
           <zen-story name="States">
             <template>
               <zen-stack direction="row">
--- a/design_system/src/storybook.css	Tue Aug 04 16:49:11 2026 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-* {
-  box-sizing: border-box;
-}
-
-html {
-  min-height: 100%;
-  background: var(--zen-color-canvas);
-  color: var(--zen-color-text);
-  font-family: var(--zen-font-sans);
-}
-
-body {
-  min-height: 100vh;
-  margin: 0;
-}
-
-button,
-input,
-select,
-textarea {
-  font: inherit;
-}
-
-.catalog-shell {
-  display: grid;
-  grid-template-columns: 17rem minmax(0, 1fr);
-  min-height: 100vh;
-}
-
-.catalog-sidebar {
-  position: sticky;
-  top: 0;
-  height: 100vh;
-  overflow: auto;
-  padding: var(--zen-space-5);
-  border-right: var(--zen-border-width) solid var(--zen-color-border);
-  background: var(--zen-color-surface);
-}
-
-.catalog-brand {
-  display: inline-flex;
-  align-items: center;
-  gap: var(--zen-space-3);
-  color: inherit;
-  font-size: var(--zen-font-size-lg);
-  font-weight: 850;
-  text-decoration: none;
-}
-
-.catalog-search {
-  width: 100%;
-  margin-top: var(--zen-space-5);
-}
-
-.catalog-search > zen-icon {
-  align-self: center;
-  margin-inline-start: var(--zen-space-3);
-  color: var(--zen-color-text-muted);
-}
-
-.catalog-search > kbd {
-  align-self: center;
-  margin-inline-end: var(--zen-space-2);
-  padding: 0 var(--zen-space-1);
-  border: 1px solid var(--zen-color-border-muted);
-  border-radius: var(--zen-radius-sm);
-  color: var(--zen-color-text-muted);
-  font: var(--zen-font-size-xs)/1.5 var(--zen-font-mono);
-}
-
-.search-status {
-  min-height: 1.25rem;
-  margin: var(--zen-space-1) 0 0;
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-xs);
-}
-
-.catalog-mark {
-  display: grid;
-  width: 2.5rem;
-  height: 2.5rem;
-  place-items: center;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 50%;
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-.catalog-sidebar h2 {
-  margin: var(--zen-space-6) 0 var(--zen-space-2);
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-xs);
-  letter-spacing: 0.12em;
-  text-transform: uppercase;
-}
-
-.catalog-nav {
-  display: grid;
-  gap: var(--zen-space-1);
-}
-
-.catalog-nav a {
-  padding: var(--zen-space-2) var(--zen-space-3);
-  border-radius: var(--zen-radius-sm);
-  color: inherit;
-  text-decoration: none;
-}
-
-.catalog-nav a[hidden],
-.component-grid > a[hidden] {
-  display: none;
-}
-
-.catalog-nav a:hover,
-.catalog-nav a[aria-current] {
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-.theme-toggle {
-  width: 100%;
-  margin-top: var(--zen-space-6);
-  padding: var(--zen-space-2);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: transparent;
-  color: inherit;
-  cursor: pointer;
-}
-
-.catalog-main {
-  width: min(100%, var(--zen-content-width));
-  min-width: 0;
-  padding: var(--zen-space-7) clamp(1rem, 5vw, 5rem);
-  outline: none;
-}
-
-.catalog-page {
-  min-width: 0;
-}
-
-.catalog-page[hidden] {
-  display: none;
-}
-
-.page-heading {
-  max-width: 52rem;
-  margin-bottom: var(--zen-space-7);
-}
-
-.eyebrow {
-  margin: 0 0 var(--zen-space-2);
-  color: var(--zen-color-info);
-  font-size: var(--zen-font-size-sm);
-  font-weight: 800;
-  letter-spacing: 0.1em;
-  text-transform: uppercase;
-}
-
-.page-heading h1 {
-  margin: 0 0 var(--zen-space-3);
-  font-size: var(--zen-font-size-xl);
-  line-height: 1.05;
-}
-
-.page-heading p {
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-lg);
-}
-
-.principles,
-.component-grid,
-.token-grid {
-  display: grid;
-  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
-  gap: var(--zen-space-5);
-}
-
-.principle,
-.token-group {
-  padding: var(--zen-space-5);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-.principle h2,
-.token-group h2 {
-  margin-top: 0;
-}
-
-.component-grid a {
-  color: inherit;
-  text-decoration: none;
-}
-
-.component-grid zen-card {
-  height: 100%;
-}
-
-.component-grid code {
-  color: var(--zen-color-info);
-  font-size: var(--zen-font-size-xs);
-}
-
-.component-grid p {
-  color: var(--zen-color-text-muted);
-}
-
-.swatch-list {
-  display: grid;
-  gap: var(--zen-space-2);
-  margin: 0;
-}
-
-.swatch-list div {
-  display: grid;
-  grid-template-columns: 2rem 1fr;
-  align-items: center;
-  gap: var(--zen-space-2);
-}
-
-.swatch-list dt,
-.swatch-list dd {
-  margin: 0;
-  font-family: var(--zen-font-mono);
-  font-size: var(--zen-font-size-xs);
-}
-
-.swatch {
-  width: 2rem;
-  height: 2rem;
-  border: 1px solid var(--zen-color-border);
-  border-radius: 50%;
-  background: var(--zen-color-swatch);
-}
-
-.token-group-wide {
-  grid-column: span 2;
-}
-
-.token-group > p {
-  color: var(--zen-color-text-muted);
-}
-
-.palette-grid {
-  display: grid;
-  grid-template-columns: repeat(auto-fit, minmax(6rem, 1fr));
-  gap: var(--zen-space-3);
-}
-
-.palette-grid > div {
-  display: grid;
-  gap: var(--zen-space-1);
-}
-
-.palette-grid span {
-  min-height: 3.5rem;
-  border: 1px solid var(--zen-color-border-muted);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-swatch);
-}
-
-.palette-grid code {
-  font-size: var(--zen-font-size-xs);
-}
-
-.data-palette {
-  display: grid;
-  grid-template-columns: repeat(10, minmax(1.75rem, 1fr));
-  min-height: 4rem;
-  overflow: hidden;
-  border: 1px solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-}
-
-.data-palette span {
-  background: var(--zen-color-swatch);
-}
-
-.icon-grid {
-  display: grid;
-  grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
-  gap: var(--zen-space-3);
-}
-
-.icon-grid figure {
-  display: grid;
-  min-height: 7rem;
-  margin: 0;
-  padding: var(--zen-space-3);
-  place-items: center;
-  gap: var(--zen-space-2);
-  border: 1px solid var(--zen-color-border-muted);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-}
-
-.icon-grid figcaption {
-  max-width: 100%;
-  overflow: hidden;
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-xs);
-  text-overflow: ellipsis;
-}
-
-zen-story {
-  display: block;
-  max-width: 100%;
-  margin-bottom: var(--zen-space-6);
-  overflow: hidden;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-zen-story > header {
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  gap: var(--zen-space-3);
-  padding: var(--zen-space-3) var(--zen-space-4);
-  border-bottom: 1px solid var(--zen-color-border);
-}
-
-zen-story > header h3 {
-  margin: 0;
-}
-
-zen-story > header button {
-  padding: var(--zen-space-1) var(--zen-space-2);
-  border: 0;
-  border-radius: var(--zen-radius-sm);
-  background: transparent;
-  color: var(--zen-color-info);
-  cursor: pointer;
-}
-
-.story-canvas {
-  min-height: 8rem;
-  padding: clamp(1rem, 4vw, 3rem);
-  background:
-    linear-gradient(90deg, var(--zen-color-gridline) 1px, transparent 1px),
-    linear-gradient(var(--zen-color-gridline) 1px, transparent 1px);
-  background-size: 1rem 1rem;
-}
-
-zen-story > pre {
-  max-height: 24rem;
-  overflow: auto;
-  margin: 0;
-  padding: var(--zen-space-4);
-  border-top: 1px solid var(--zen-color-border);
-  background: var(--zen-color-code-surface);
-  color: var(--zen-color-code-text);
-  font: var(--zen-font-size-sm)/1.55 var(--zen-font-mono);
-}
-
-.demo-card-grid {
-  display: grid;
-  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
-  gap: var(--zen-space-5);
-}
-
-@media (max-width: 760px) {
-  .catalog-shell {
-    grid-template-columns: 1fr;
-  }
-
-  .catalog-sidebar {
-    position: static;
-    width: 100%;
-    height: auto;
-    border-right: 0;
-    border-bottom: var(--zen-border-width) solid var(--zen-color-border);
-  }
-
-  .catalog-nav {
-    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
-  }
-
-  .catalog-main {
-    padding: var(--zen-space-6) var(--zen-space-4);
-  }
-
-  .token-group-wide {
-    grid-column: auto;
-  }
-
-  .data-palette {
-    grid-template-columns: repeat(5, 1fr);
-  }
-}
--- a/design_system/src/storybook.js	Tue Aug 04 16:49:11 2026 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-import "./components/index.js";
-import { componentCatalog } from "./catalog.js";
-import { ICON_NAMES } from "./components/icon.js";
-
-const stackComponent = {
-  name: "Stack",
-  slug: "stack",
-  element: "zen-stack",
-  group: "Layout",
-  description: "A Zenbu-specific flex layout primitive with tokenized gaps.",
-  existing: true,
-};
-const displayedComponents = [...componentCatalog, stackComponent];
-
-const pages = new Map([
-  ["/", "overview"],
-  ["/components", "overview"],
-  ["/tokens", "tokens"],
-  ["/icons", "icons"],
-  ["/components/button", "button"],
-  ["/components/card", "card"],
-  ["/components/alert", "alert"],
-  ["/components/field", "field"],
-  ["/components/notifications", "notifications"],
-  ["/components/stack", "stack"],
-]);
-
-for (const component of componentCatalog) {
-  pages.set(`/components/${component.slug}`, component.slug);
-}
-
-function createCatalogLink(component) {
-  const link = document.createElement("a");
-  link.href = `/components/${component.slug}`;
-  link.dataset.catalogLink = "";
-  link.dataset.zenElement = component.element;
-  link.textContent = component.name;
-  return link;
-}
-
-function createComponentCard(component) {
-  const link = createCatalogLink(component);
-  const card = document.createElement("zen-card");
-  card.setAttribute("interactive", "");
-  const article = document.createElement("article");
-  const heading = document.createElement("h3");
-  heading.textContent = component.name;
-  const description = document.createElement("p");
-  description.textContent = component.description;
-  const element = document.createElement("code");
-  element.textContent = component.element;
-  article.append(heading, description, element);
-  card.append(article);
-  link.replaceChildren(card);
-  return link;
-}
-
-function createCatalogPage(component) {
-  const section = document.createElement("section");
-  section.className = "catalog-page";
-  section.dataset.catalogPage = component.slug;
-  section.hidden = true;
-
-  const header = document.createElement("header");
-  header.className = "page-heading";
-  const eyebrow = document.createElement("p");
-  eyebrow.className = "eyebrow";
-  eyebrow.textContent = component.group;
-  const heading = document.createElement("h1");
-  heading.textContent = component.name;
-  const description = document.createElement("p");
-  description.textContent = component.description;
-  header.append(eyebrow, heading, description);
-
-  const story = document.createElement("zen-story");
-  story.setAttribute("name", `${component.name} example`);
-  const template = document.createElement("template");
-  template.innerHTML = component.markup;
-  story.append(template);
-  section.append(header, story);
-  return section;
-}
-
-function installComponentCatalog() {
-  const navigation = document.querySelector(
-    '.catalog-nav[aria-label="Components"]',
-  );
-  const componentGrid = document.querySelector(".component-grid");
-  const main = document.querySelector("#catalogMain");
-  if (!navigation || !componentGrid || !main) return;
-
-  navigation.replaceChildren(
-    ...displayedComponents.map(createCatalogLink),
-  );
-  componentGrid.replaceChildren(
-    ...displayedComponents.map(createComponentCard),
-  );
-
-  for (const component of componentCatalog) {
-    if (component.existing) continue;
-    main.append(createCatalogPage(component));
-  }
-}
-
-function installIconCatalog() {
-  const grid = document.querySelector("#iconGrid");
-  if (!grid) return;
-  const items = ICON_NAMES.map(name => {
-    const figure = document.createElement("figure");
-    const icon = document.createElement("zen-icon");
-    icon.setAttribute("name", name);
-    icon.setAttribute("size", "2rem");
-    const caption = document.createElement("figcaption");
-    const code = document.createElement("code");
-    code.textContent = name;
-    caption.append(code);
-    figure.append(icon, caption);
-    return figure;
-  });
-  grid.replaceChildren(...items);
-}
-
-function installComponentSearch() {
-  const input = document.querySelector("#componentSearch");
-  const status = document.querySelector("#componentSearchStatus");
-  if (!input || !status) return;
-  const links = [
-    ...document.querySelectorAll(
-      '.catalog-nav[aria-label="Components"] a',
-    ),
-  ];
-  const cards = [...document.querySelectorAll(".component-grid > a")];
-  const descriptions = new Map(
-    displayedComponents.map(component => [
-      component.slug,
-      [
-        component.name,
-        component.element,
-        component.group,
-        component.description,
-      ].join(" ").toLocaleLowerCase(),
-    ]),
-  );
-  const filter = () => {
-    const query = input.value.trim().toLocaleLowerCase();
-    let matches = 0;
-    for (const link of links) {
-      const slug = new URL(link.href).pathname.split("/").pop();
-      const visible = !query || descriptions.get(slug)?.includes(query);
-      link.hidden = !visible;
-      if (visible) matches++;
-    }
-    for (const card of cards) {
-      const slug = new URL(card.href).pathname.split("/").pop();
-      card.hidden = Boolean(query) &&
-        !descriptions.get(slug)?.includes(query);
-    }
-    status.textContent = query
-      ? `${matches} component${matches === 1 ? "" : "s"} found`
-      : `${links.length} components`;
-  };
-
-  input.addEventListener("input", filter);
-  input.addEventListener("keydown", event => {
-    if (event.key !== "Escape" || !input.value) return;
-    input.value = "";
-    filter();
-  });
-  document.addEventListener("keydown", event => {
-    const target = event.target;
-    const typing = target instanceof HTMLElement &&
-      target.matches("input, textarea, select, [contenteditable]");
-    if (event.key !== "/" || typing || event.metaKey || event.ctrlKey ||
-        event.altKey) return;
-    event.preventDefault();
-    input.focus();
-    input.select();
-  });
-  filter();
-}
-
-function showPage(pathname) {
-  const pageName = pages.get(pathname) || "overview";
-  for (const page of document.querySelectorAll("[data-catalog-page]")) {
-    page.hidden = page.dataset.catalogPage !== pageName;
-  }
-  for (const link of document.querySelectorAll(
-    ".catalog-sidebar [data-catalog-link]",
-  )) {
-    const active = new URL(link.href).pathname === pathname;
-    if (active) link.setAttribute("aria-current", "page");
-    else link.removeAttribute("aria-current");
-  }
-  const heading = document.querySelector(
-    `[data-catalog-page="${pageName}"] h1`,
-  );
-  if (heading) document.title = `${heading.textContent} · Zenbu UI`;
-}
-
-window.addEventListener("DOMContentLoaded", () => {
-  installComponentCatalog();
-  installIconCatalog();
-  installComponentSearch();
-  const root = document.documentElement;
-  const systemTheme = matchMedia("(prefers-color-scheme: dark)");
-  const storedTheme = localStorage.getItem("zen-theme");
-  if (storedTheme) root.dataset.zenTheme = storedTheme;
-
-  const themeToggle = document.querySelector("#themeToggle");
-  const isDark = () => {
-    if (root.dataset.zenTheme) {
-      return root.dataset.zenTheme === "dark";
-    }
-    return systemTheme.matches;
-  };
-  const updateThemeButton = () => {
-    const dark = isDark();
-    themeToggle?.setAttribute("aria-pressed", String(dark));
-    if (themeToggle) {
-      themeToggle.textContent = dark
-        ? "Use light theme"
-        : "Use dark theme";
-    }
-  };
-  updateThemeButton();
-  themeToggle?.addEventListener("click", () => {
-    const next = isDark() ? "light" : "dark";
-    root.dataset.zenTheme = next;
-    localStorage.setItem("zen-theme", next);
-    updateThemeButton();
-  });
-  systemTheme.addEventListener("change", () => {
-    if (!root.dataset.zenTheme) updateThemeButton();
-  });
-
-  document.addEventListener("click", event => {
-    const notificationDemo = event.target.closest(
-      "[data-notification-demo]",
-    );
-    if (notificationDemo) {
-      const scope = notificationDemo.closest("zen-notifications");
-      if (!scope) return;
-      const tone = notificationDemo.dataset.tone || "info";
-      const baseId = notificationDemo.dataset.notificationId || tone;
-      const count = notificationDemo.dataset.burst === "true" ? 5 : 1;
-      for (let index = 0; index < count; index++) {
-        notificationDemo.dispatchEvent(new CustomEvent("zen-notify", {
-          bubbles: true,
-          composed: false,
-          detail: {
-            version: 1,
-            id: count > 1 ? `${baseId}-${Date.now()}-${index}` : baseId,
-            tone,
-            message: notificationDemo.dataset.message || "Notification",
-            description: notificationDemo.dataset.description,
-            announcement: tone === "error" ? "assertive" : "polite",
-            durationMs: 5000,
-            persistent: notificationDemo.dataset.persistent === "true",
-            action: notificationDemo.dataset.action === "true"
-              ? { token: `catalog-action-${Date.now()}`, label: "Retry" }
-              : undefined,
-          },
-        }));
-      }
-      return;
-    }
-
-    const dismissDemo = event.target.closest(
-      "[data-notification-dismiss-demo]",
-    );
-    if (dismissDemo) {
-      dismissDemo.dispatchEvent(new CustomEvent(
-        "zen-dismiss-notification",
-        {
-          bubbles: true,
-          composed: false,
-          detail: {
-            version: 1,
-            id: dismissDemo.dataset.notificationDismissDemo,
-          },
-        },
-      ));
-      return;
-    }
-
-    const link = event.target.closest("a[data-catalog-link]");
-    if (!link ||
-        link.origin !== location.origin ||
-        event.defaultPrevented ||
-        event.button !== 0 ||
-        event.metaKey ||
-        event.ctrlKey ||
-        event.shiftKey ||
-        event.altKey ||
-        link.hasAttribute("download") ||
-        link.target) return;
-    event.preventDefault();
-    history.pushState({}, "", link.href);
-    showPage(location.pathname);
-    document.querySelector("#catalogMain")?.focus();
-  });
-  window.addEventListener("popstate", () => showPage(location.pathname));
-  showPage(location.pathname);
-});
--- a/design_system/src/styles/components.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/styles/components.css	Wed Aug 05 05:25:40 2026 -0700
@@ -1,4 +1,4 @@
-@import url("./shadcn.css");
+@import url("./elements.css");
 
 :where(
   zen-button,
@@ -9,78 +9,128 @@
   zen-notifications
 ) {
   box-sizing: border-box;
-  font-family: var(--zen-font-sans);
-  color: var(--zen-color-text);
+  font-family: var(--zenbu-sys-font-family-ui);
+  color: var(--zenbu-sys-color-text-primary);
 }
 
 zen-button {
   display: inline-flex;
 }
 
-zen-button > :where(button, a) {
+zen-button:not([appearance="plain"]) > :where(button, a) {
+  --zenbu-button-background:
+    var(--zenbu-sys-color-action-primary-background);
+  --zenbu-button-background-hover:
+    var(--zenbu-sys-color-action-primary-background-hover);
+  --zenbu-button-background-pressed:
+    var(--zenbu-sys-color-action-primary-background-pressed);
+  --zenbu-button-border:
+    var(--zenbu-sys-color-action-primary-border);
+  --zenbu-button-foreground:
+    var(--zenbu-sys-color-action-primary-foreground);
   appearance: none;
+  box-sizing: border-box;
   display: inline-flex;
   align-items: center;
   justify-content: center;
-  gap: var(--zen-space-2);
-  min-height: 2.75rem;
-  padding: var(--zen-space-2) var(--zen-space-4);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  box-shadow: var(--zen-shadow-sm);
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-  font: 700 var(--zen-font-size-md)/1 var(--zen-font-sans);
+  gap: var(--zenbu-control-gap);
+  min-height: var(--zenbu-control-height);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width) solid var(--zenbu-button-border);
+  border-radius: var(--zenbu-sys-radius-control);
+  box-shadow: var(--zenbu-sys-shadow-subtle);
+  background: var(--zenbu-button-background);
+  color: var(--zenbu-button-foreground);
+  font:
+    var(--zenbu-sys-font-weight-strong)
+    var(--zenbu-control-font-size) /
+    var(--zenbu-control-line-height)
+    var(--zenbu-sys-font-family-ui);
   text-decoration: none;
   cursor: pointer;
   transition:
-    background var(--zen-motion-fast) ease,
-    box-shadow var(--zen-motion-fast) ease,
-    transform var(--zen-motion-fast) ease;
+    background var(--zenbu-sys-motion-duration-state)
+      var(--zenbu-sys-motion-ease-state),
+    border-color var(--zenbu-sys-motion-duration-state)
+      var(--zenbu-sys-motion-ease-state),
+    box-shadow var(--zenbu-sys-motion-duration-feedback)
+      var(--zenbu-sys-motion-ease-state),
+    transform var(--zenbu-sys-motion-duration-feedback)
+      var(--zenbu-sys-motion-ease-state);
 }
 
-zen-button > :where(button, a):hover {
-  background: var(--zen-color-accent-hover);
+zen-button:not([appearance="plain"]) > :where(button, a):hover:not(
+  :disabled,
+  [aria-disabled="true"]
+) {
+  background: var(--zenbu-button-background-hover);
   transform: translate(-1px, -1px);
-  box-shadow: var(--zen-shadow-hover);
+  box-shadow: var(--zenbu-sys-shadow-raised);
 }
 
-zen-button > :where(button, a):active {
+zen-button:not([appearance="plain"]) > :where(button, a):active:not(
+  :disabled,
+  [aria-disabled="true"]
+) {
+  background: var(--zenbu-button-background-pressed);
   transform: translate(2px, 2px);
   box-shadow: none;
 }
 
-zen-button > :where(button, a):focus-visible,
+zen-button:not([appearance="plain"]) > :where(button, a):focus-visible,
 zen-alert [data-zen-dismiss]:focus-visible {
-  outline: 3px solid var(--zen-color-focus);
-  outline-offset: 3px;
+  outline: var(--zenbu-sys-focus-width) solid
+    var(--zenbu-sys-color-focus-outer);
+  outline-offset: var(--zenbu-sys-focus-offset);
 }
 
-zen-field :where(input, select, textarea):focus-visible {
+zen-field:not([appearance="plain"]) :where(
+  input,
+  select,
+  textarea
+):focus-visible {
   outline: none;
 }
 
-zen-button[variant="quiet"] > :where(button, a) {
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
+zen-button:not([appearance="plain"])[variant="quiet"] > :where(button, a) {
+  --zenbu-button-background:
+    var(--zenbu-sys-color-action-neutral-background);
+  --zenbu-button-background-hover:
+    var(--zenbu-sys-color-action-neutral-background-hover);
+  --zenbu-button-background-pressed:
+    var(--zenbu-sys-color-action-neutral-background-pressed);
+  --zenbu-button-border:
+    var(--zenbu-sys-color-action-neutral-border);
+  --zenbu-button-foreground:
+    var(--zenbu-sys-color-action-neutral-foreground);
 }
 
-zen-button[variant="danger"] > :where(button, a) {
-  background: var(--zen-color-danger);
-  color: var(--zen-color-on-danger);
+zen-button:not([appearance="plain"])[variant="danger"] > :where(button, a) {
+  --zenbu-button-background:
+    var(--zenbu-sys-color-action-danger-background);
+  --zenbu-button-background-hover:
+    var(--zenbu-sys-color-action-danger-background-hover);
+  --zenbu-button-background-pressed:
+    var(--zenbu-sys-color-action-danger-background-pressed);
+  --zenbu-button-border:
+    var(--zenbu-sys-color-action-danger-border);
+  --zenbu-button-foreground:
+    var(--zenbu-sys-color-action-danger-foreground);
 }
 
-zen-button[disabled] > :where(button, a),
-zen-button[loading] > :where(button, a) {
-  opacity: 0.55;
+zen-button:not([appearance="plain"])[disabled] > :where(button, a),
+zen-button:not([appearance="plain"])[loading] > :where(button, a) {
+  opacity: var(--zenbu-sys-opacity-disabled);
   box-shadow: none;
   cursor: not-allowed;
   transform: none;
 }
 
-zen-button[loading] > :where(button, a)::before {
-  width: 0.85rem;
-  height: 0.85rem;
+zen-button:not([appearance="plain"])[loading] > :where(button, a)::before {
+  width: var(--zenbu-control-icon-size);
+  height: var(--zenbu-control-icon-size);
   border: 2px solid currentColor;
   border-right-color: transparent;
   border-radius: 50%;
@@ -96,24 +146,30 @@
   display: block;
 }
 
-zen-card > :where(article, section) {
+zen-card:not([appearance="plain"]) > :where(article, section) {
+  --zenbu-card-background: var(--zenbu-sys-color-surface-raised);
+  --zenbu-card-border: var(--zenbu-sys-color-border-subtle);
+  --zenbu-card-foreground: var(--zenbu-sys-color-text-primary);
   height: 100%;
-  padding: var(--zen-space-5);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  box-shadow: var(--zen-shadow-md);
-  background: var(--zen-color-surface-raised);
+  padding: var(--zenbu-sys-padding-lg);
+  border: var(--zenbu-sys-stroke-width) solid var(--zenbu-card-border);
+  border-radius: var(--zenbu-sys-radius-container);
+  box-shadow: var(--zenbu-sys-shadow-raised);
+  background: var(--zenbu-card-background);
+  color: var(--zenbu-card-foreground);
 }
 
-zen-card[interactive] > :where(article, section) {
+zen-card:not([appearance="plain"])[interactive] > :where(article, section) {
   transition:
-    box-shadow var(--zen-motion-fast) ease,
-    transform var(--zen-motion-fast) ease;
+    box-shadow var(--zenbu-sys-motion-duration-state)
+      var(--zenbu-sys-motion-ease-state),
+    transform var(--zenbu-sys-motion-duration-state)
+      var(--zenbu-sys-motion-ease-state);
 }
 
-zen-card[interactive] > :where(article, section):hover {
+zen-card:not([appearance="plain"])[interactive] > :where(article, section):hover {
   transform: translate(-2px, -2px);
-  box-shadow: var(--zen-shadow-lifted);
+  box-shadow: var(--zenbu-sys-shadow-overlay);
 }
 
 zen-card :where(h2, h3, p) {
@@ -121,85 +177,123 @@
 }
 
 zen-alert {
+  --zenbu-alert-background: var(--zenbu-sys-color-info-background);
+  --zenbu-alert-border: var(--zenbu-sys-color-info-border);
+  --zenbu-alert-foreground: var(--zenbu-sys-color-info-foreground);
   display: grid;
-  grid-template-columns: 0.35rem minmax(0, 1fr) auto;
+  --zenbu-alert-indicator-width: var(--zenbu-ref-space-1-5);
+  grid-template-columns:
+    var(--zenbu-alert-indicator-width)
+    minmax(0, 1fr)
+    auto;
   align-items: start;
-  gap: var(--zen-space-3);
-  padding: var(--zen-space-4);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface-raised);
+  gap: var(--zenbu-sys-space-control);
+  padding: var(--zenbu-sys-padding-md);
+  border: var(--zenbu-sys-stroke-width) solid var(--zenbu-alert-border);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-alert-background);
+  color: var(--zenbu-alert-foreground);
 }
 
 zen-alert::before {
   align-self: stretch;
-  border-radius: 999px;
-  background: var(--zen-color-info);
+  border-radius: var(--zenbu-sys-radius-pill);
+  background: var(--zenbu-alert-border);
   content: "";
 }
 
-zen-alert[tone="success"]::before { background: var(--zen-color-success); }
-zen-alert[tone="warning"]::before { background: var(--zen-color-warning); }
-zen-alert[tone="danger"]::before { background: var(--zen-color-danger); }
+zen-alert[tone="success"] {
+  --zenbu-alert-background: var(--zenbu-sys-color-success-background);
+  --zenbu-alert-border: var(--zenbu-sys-color-success-border);
+  --zenbu-alert-foreground: var(--zenbu-sys-color-success-foreground);
+}
+zen-alert[tone="warning"] {
+  --zenbu-alert-background: var(--zenbu-sys-color-warning-background);
+  --zenbu-alert-border: var(--zenbu-sys-color-warning-border);
+  --zenbu-alert-foreground: var(--zenbu-sys-color-warning-foreground);
+}
+zen-alert[tone="danger"] {
+  --zenbu-alert-background: var(--zenbu-sys-color-danger-background);
+  --zenbu-alert-border: var(--zenbu-sys-color-danger-border);
+  --zenbu-alert-foreground: var(--zenbu-sys-color-danger-foreground);
+}
 
 zen-alert > :where(p, div) {
   margin: 0;
 }
 
 zen-alert [data-zen-dismiss] {
-  min-width: 2rem;
-  min-height: 2rem;
+  min-width: var(--zenbu-sys-control-height-xs);
+  min-height: var(--zenbu-sys-control-height-xs);
   padding: 0;
   border: 0;
-  border-radius: 50%;
+  border-radius: var(--zenbu-sys-radius-pill);
   background: transparent;
   color: inherit;
-  font: 700 1.2rem/1 var(--zen-font-sans);
+  font:
+    var(--zenbu-sys-font-weight-bold)
+    var(--zenbu-sys-font-size-lg) / 1
+    var(--zenbu-sys-font-family-ui);
   cursor: pointer;
 }
 
 zen-field {
+  --zenbu-field-textarea-min-height:
+    calc(var(--zenbu-ref-space-24) + var(--zenbu-ref-space-4));
   display: grid;
-  gap: var(--zen-space-2);
+  gap: var(--zenbu-sys-space-icon-label);
 }
 
-zen-field > label {
-  font-weight: 750;
+zen-field[appearance="plain"] {
+  display: contents;
+}
+
+zen-field:not([appearance="plain"]) > label {
+  font-family: var(--zenbu-sys-type-label-family);
+  font-size: var(--zenbu-sys-type-label-size);
+  font-weight: var(--zenbu-sys-type-label-weight);
+  line-height: var(--zenbu-sys-type-label-line-height);
 }
 
-zen-field > :where(input, select, textarea) {
+zen-field:not([appearance="plain"]) > :where(input, select, textarea) {
   width: 100%;
-  min-height: 2.75rem;
+  min-height: var(--zenbu-control-height);
   box-sizing: border-box;
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-  font: inherit;
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width) solid
+    var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+  font-family: inherit;
+  font-size: var(--zenbu-control-font-size);
+  line-height: var(--zenbu-control-line-height);
 }
 
-zen-field > textarea {
-  min-height: 7rem;
+zen-field:not([appearance="plain"]) > textarea {
+  min-height: var(--zenbu-field-textarea-min-height);
   resize: vertical;
 }
 
-zen-field > :where(small, [data-help]) {
-  color: var(--zen-color-text-muted);
+zen-field:not([appearance="plain"]) > :where(small, [data-help]) {
+  color: var(--zenbu-sys-color-text-secondary);
 }
 
-zen-field[data-invalid] > :where(input, select, textarea) {
-  border-color: var(--zen-color-danger);
+zen-field:not([appearance="plain"])[data-invalid] > :where(input, select, textarea) {
+  border-color: var(--zenbu-sys-color-danger-border);
 }
 
-zen-field[data-invalid] > :where(small, [data-help]) {
-  color: var(--zen-color-danger);
+zen-field:not([appearance="plain"])[data-invalid] > :where(small, [data-help]) {
+  color: var(--zenbu-sys-color-danger-foreground);
 }
 
 zen-stack {
+  --zenbu-stack-gap: var(--zenbu-sys-space-group);
   display: flex;
   flex-direction: column;
-  gap: var(--zen-stack-gap, var(--zen-space-4));
+  gap: var(--zenbu-stack-gap);
 }
 
 zen-stack[direction="row"] {
@@ -207,59 +301,89 @@
   align-items: center;
 }
 
-zen-stack[gap="tight"] { --zen-stack-gap: var(--zen-space-2); }
-zen-stack[gap="loose"] { --zen-stack-gap: var(--zen-space-6); }
+zen-stack[gap="tight"] {
+  --zenbu-stack-gap: var(--zenbu-sys-space-related);
+}
+zen-stack[gap="loose"] {
+  --zenbu-stack-gap: var(--zenbu-sys-space-container);
+}
 
 zen-notifications > [data-zen-notification-stack] {
+  --zenbu-notification-z-index: var(--zenbu-sys-z-notification);
+  --zenbu-notification-inset: var(--zenbu-sys-padding-md);
+  --zenbu-notification-bottom-inset: var(--zenbu-sys-padding-md);
+  --zenbu-notification-collapsed-height: 0;
+  --zenbu-notification-expanded-height: 0;
   position: fixed;
-  z-index: var(--zen-notification-z-index, 1000);
-  inset-inline-end: var(--zen-notification-inset, var(--zen-space-4));
+  z-index: var(
+    --zenbu-notification-z-index,
+    var(--zenbu-sys-z-notification)
+  );
+  inset-inline-end: var(
+    --zenbu-notification-inset,
+    var(--zenbu-sys-padding-md)
+  );
   inset-block-end: var(
-    --zen-notification-bottom-inset,
-    var(--zen-space-4)
+    --zenbu-notification-bottom-inset,
+    var(--zenbu-sys-padding-md)
   );
   inline-size: min(24rem, calc(100vi - 2rem));
-  height: var(--zen-notification-collapsed-height, 0);
-  --zen-notification-gap: 12px;
+  height: var(--zenbu-notification-collapsed-height, 0);
+  --zenbu-notification-gap: var(--zenbu-sys-space-control);
   pointer-events: auto;
   isolation: isolate;
-  transition: height 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
+  transition:
+    height var(--zenbu-sys-motion-duration-layout)
+      var(--zenbu-sys-motion-ease-layout);
 }
 
 zen-notifications > [data-zen-notification-stack]:is(
   :hover,
   :focus-within
 ) {
-  height: var(--zen-notification-expanded-height, 0);
+  height: var(--zenbu-notification-expanded-height, 0);
 }
 
 zen-notifications > [data-zen-notification-stack] > article {
+  --zenbu-notification-collapsed-opacity: 1;
+  --zenbu-notification-collapsed-offset: 0;
+  --zenbu-notification-offset: 0;
+  --zenbu-notification-scale: 1;
+  --zenbu-notification-background:
+    var(--zenbu-sys-color-surface-raised);
+  --zenbu-notification-border:
+    var(--zenbu-sys-color-border-subtle);
+  --zenbu-notification-foreground:
+    var(--zenbu-sys-color-text-primary);
   position: absolute;
   inset-inline: 0;
   inset-block-end: 0;
   display: grid;
   grid-template-columns: 1.75rem minmax(0, 1fr) 2rem;
   align-items: start;
-  gap: var(--zen-space-3);
-  padding: var(--zen-space-4);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  box-shadow: var(--zen-shadow-md);
-  background: var(--zen-color-surface-raised);
-  color: var(--zen-color-text);
-  opacity: var(--zen-notification-collapsed-opacity, 1);
+  gap: var(--zenbu-sys-space-control);
+  padding: var(--zenbu-sys-padding-md);
+  border: var(--zenbu-sys-stroke-width) solid
+    var(--zenbu-notification-border);
+  border-radius: var(--zenbu-sys-radius-container);
+  box-shadow: var(--zenbu-sys-shadow-overlay);
+  background: var(--zenbu-notification-background);
+  color: var(--zenbu-notification-foreground);
+  opacity: var(--zenbu-notification-collapsed-opacity, 1);
   pointer-events: none;
   transform:
     translate3d(
       0,
-      var(--zen-notification-collapsed-offset, 0),
+      var(--zenbu-notification-collapsed-offset, 0),
       0
     )
-    scale(var(--zen-notification-scale, 1));
+    scale(var(--zenbu-notification-scale, 1));
   transform-origin: center bottom;
   transition:
-    opacity 180ms ease,
-    transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
+    opacity var(--zenbu-sys-motion-duration-exit)
+      var(--zenbu-sys-motion-ease-exit),
+    transform var(--zenbu-sys-motion-duration-layout)
+      var(--zenbu-sys-motion-ease-layout);
   will-change: transform;
   animation: zen-notification-enter 160ms ease-out;
 }
@@ -277,7 +401,7 @@
   transform:
     translate3d(
       0,
-      var(--zen-notification-offset, 0px),
+      var(--zenbu-notification-offset, 0px),
       0
     )
     scale(1);
@@ -290,34 +414,38 @@
 }
 
 .zen-notification-tone {
+  --zenbu-notification-tone-background:
+    var(--zenbu-sys-color-info-foreground);
+  --zenbu-notification-tone-foreground:
+    var(--zenbu-sys-color-text-inverse);
   display: grid;
   width: 1.75rem;
   height: 1.75rem;
   place-items: center;
-  border-radius: 50%;
-  background: var(--zen-color-info);
-  color: var(--zen-color-on-info);
-  font-weight: 900;
+  border-radius: var(--zenbu-sys-radius-pill);
+  background: var(--zenbu-notification-tone-background);
+  color: var(--zenbu-notification-tone-foreground);
+  font-weight: var(--zenbu-sys-font-weight-bold);
 }
 
 [data-tone="success"] > .zen-notification-tone {
-  background: var(--zen-color-success);
-  color: var(--zen-color-on-success);
+  --zenbu-notification-tone-background:
+    var(--zenbu-sys-color-success-foreground);
 }
 
 [data-tone="warning"] > .zen-notification-tone {
-  background: var(--zen-color-warning);
-  color: var(--zen-color-on-warning);
+  --zenbu-notification-tone-background:
+    var(--zenbu-sys-color-warning-foreground);
 }
 
 [data-tone="error"] > .zen-notification-tone {
-  background: var(--zen-color-danger);
-  color: var(--zen-color-on-danger);
+  --zenbu-notification-tone-background:
+    var(--zenbu-sys-color-danger-foreground);
 }
 
 .zen-notification-content {
   display: grid;
-  gap: var(--zen-space-1);
+  gap: var(--zenbu-sys-space-icon-label);
 }
 
 .zen-notification-message,
@@ -326,12 +454,12 @@
 }
 
 .zen-notification-message {
-  font-weight: 800;
+  font-weight: var(--zenbu-sys-font-weight-bold);
 }
 
 .zen-notification-description {
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-sm);
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-sm);
 }
 
 .zen-notification-action,
@@ -344,10 +472,10 @@
 
 .zen-notification-action {
   justify-self: start;
-  margin-top: var(--zen-space-2);
+  margin-top: var(--zenbu-sys-space-related);
   padding: 0;
-  color: var(--zen-color-info);
-  font-weight: 800;
+  color: var(--zenbu-sys-color-text-link);
+  font-weight: var(--zenbu-sys-font-weight-bold);
   text-decoration: underline;
   text-underline-offset: 0.2em;
 }
@@ -356,14 +484,15 @@
   width: 2rem;
   height: 2rem;
   padding: 0;
-  border-radius: 50%;
-  font-size: 1.25rem;
+  border-radius: var(--zenbu-sys-radius-pill);
+  font-size: var(--zenbu-sys-font-size-xl);
 }
 
 .zen-notification-action:focus-visible,
 .zen-notification-dismiss:focus-visible {
-  outline: 3px solid var(--zen-color-focus);
-  outline-offset: 2px;
+  outline: var(--zenbu-sys-focus-width) solid
+    var(--zenbu-sys-color-focus-outer);
+  outline-offset: var(--zenbu-sys-focus-offset);
 }
 
 .zen-visually-hidden {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/styles/density.css	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,31 @@
+:root,
+:root[data-zen-density="comfortable"] {
+  --zenbu-sys-control-height-xs: var(--zenbu-ref-size-control-xs);
+  --zenbu-sys-control-height-sm: var(--zenbu-ref-size-control-sm);
+  --zenbu-sys-control-height-md: var(--zenbu-ref-size-control-md);
+  --zenbu-sys-control-height-lg: var(--zenbu-ref-size-control-lg);
+  --zenbu-sys-control-height-xl: var(--zenbu-ref-size-control-xl);
+}
+
+:root[data-zen-density="compact"] {
+  --zenbu-sys-control-height-xs: 1.75rem;
+  --zenbu-sys-control-height-sm: 2rem;
+  --zenbu-sys-control-height-md: 2.25rem;
+  --zenbu-sys-control-height-lg: 2.75rem;
+  --zenbu-sys-control-height-xl: 3.25rem;
+  --zenbu-sys-control-padding-block-xs: var(--zenbu-ref-space-0-5);
+  --zenbu-sys-control-padding-block-sm: var(--zenbu-ref-space-1);
+  --zenbu-sys-control-padding-block-md: var(--zenbu-ref-space-1-5);
+  --zenbu-sys-control-padding-block-lg: var(--zenbu-ref-space-2);
+  --zenbu-sys-control-padding-block-xl: var(--zenbu-ref-space-3);
+  --zenbu-sys-control-padding-inline-xs: var(--zenbu-ref-space-2);
+  --zenbu-sys-control-padding-inline-sm: var(--zenbu-ref-space-2-5);
+  --zenbu-sys-control-padding-inline-md: var(--zenbu-ref-space-3);
+  --zenbu-sys-control-padding-inline-lg: var(--zenbu-ref-space-4);
+  --zenbu-sys-control-padding-inline-xl: var(--zenbu-ref-space-5);
+  --zenbu-sys-control-gap-xs: var(--zenbu-ref-space-0-5);
+  --zenbu-sys-control-gap-sm: var(--zenbu-ref-space-1);
+  --zenbu-sys-control-gap-md: var(--zenbu-ref-space-1-5);
+  --zenbu-sys-control-gap-lg: var(--zenbu-ref-space-2);
+  --zenbu-sys-control-gap-xl: var(--zenbu-ref-space-3);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/styles/elements.css	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,2030 @@
+:where(
+  zen-accordion,
+  zen-alert-dialog,
+  zen-aspect-ratio,
+  zen-attachment,
+  zen-avatar,
+  zen-badge,
+  zen-breadcrumb,
+  zen-bubble,
+  zen-box,
+  zen-button-group,
+  zen-calendar,
+  zen-carousel,
+  zen-chart,
+  zen-checkbox,
+  zen-collapsible,
+  zen-combobox,
+  zen-command,
+  zen-context-menu,
+  zen-data-table,
+  zen-date-picker,
+  zen-dialog,
+  zen-direction,
+  zen-drawer,
+  zen-dropdown-menu,
+  zen-empty,
+  zen-form,
+  zen-hover-card,
+  zen-heading,
+  zen-icon,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-item,
+  zen-kbd,
+  zen-label,
+  zen-marker,
+  zen-menubar,
+  zen-message,
+  zen-message-scroller,
+  zen-native-select,
+  zen-navigation-menu,
+  zen-pagination,
+  zen-popover,
+  zen-progress,
+  zen-radio-group,
+  zen-resizable,
+  zen-scroll-area,
+  zen-select,
+  zen-separator,
+  zen-sheet,
+  zen-sidebar,
+  zen-skeleton,
+  zen-slider,
+  zen-spinner,
+  zen-switch,
+  zen-table,
+  zen-text,
+  zen-tabs,
+  zen-textarea,
+  zen-toggle,
+  zen-toggle-group,
+  zen-tooltip,
+  zen-typography
+) {
+  box-sizing: border-box;
+  color: var(--zenbu-sys-color-text-primary);
+  font-family: var(--zenbu-sys-font-family-ui);
+}
+
+:where(
+  zen-button,
+  zen-calendar,
+  zen-checkbox,
+  zen-combobox,
+  zen-command,
+  zen-date-picker,
+  zen-field,
+  zen-form,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-radio-group,
+  zen-select,
+  zen-slider,
+  zen-switch,
+  zen-textarea
+) {
+  --zenbu-control-height: var(--zenbu-sys-control-height-md);
+  --zenbu-control-padding-block: var(--zenbu-sys-control-padding-block-md);
+  --zenbu-control-padding-inline: var(--zenbu-sys-control-padding-inline-md);
+  --zenbu-control-gap: var(--zenbu-sys-control-gap-md);
+  --zenbu-control-font-size: var(--zenbu-sys-font-size-md);
+  --zenbu-control-line-height: var(--zenbu-sys-control-line-height-md);
+  --zenbu-control-icon-size: var(--zenbu-sys-icon-size-md);
+}
+
+:where(
+  zen-button,
+  zen-calendar,
+  zen-checkbox,
+  zen-combobox,
+  zen-command,
+  zen-date-picker,
+  zen-field,
+  zen-form,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-radio-group,
+  zen-select,
+  zen-slider,
+  zen-switch,
+  zen-textarea
+)[size="xs"] {
+  --zenbu-control-height: var(--zenbu-sys-control-height-xs);
+  --zenbu-control-padding-block: var(--zenbu-sys-control-padding-block-xs);
+  --zenbu-control-padding-inline: var(--zenbu-sys-control-padding-inline-xs);
+  --zenbu-control-gap: var(--zenbu-sys-control-gap-xs);
+  --zenbu-control-font-size: var(--zenbu-sys-font-size-xs);
+  --zenbu-control-line-height: var(--zenbu-sys-control-line-height-xs);
+  --zenbu-control-icon-size: var(--zenbu-sys-icon-size-xs);
+}
+
+:where(
+  zen-button,
+  zen-calendar,
+  zen-checkbox,
+  zen-combobox,
+  zen-command,
+  zen-date-picker,
+  zen-field,
+  zen-form,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-radio-group,
+  zen-select,
+  zen-slider,
+  zen-switch,
+  zen-textarea
+)[size="sm"] {
+  --zenbu-control-height: var(--zenbu-sys-control-height-sm);
+  --zenbu-control-padding-block: var(--zenbu-sys-control-padding-block-sm);
+  --zenbu-control-padding-inline: var(--zenbu-sys-control-padding-inline-sm);
+  --zenbu-control-gap: var(--zenbu-sys-control-gap-sm);
+  --zenbu-control-font-size: var(--zenbu-sys-font-size-sm);
+  --zenbu-control-line-height: var(--zenbu-sys-control-line-height-sm);
+  --zenbu-control-icon-size: var(--zenbu-sys-icon-size-sm);
+}
+
+:where(
+  zen-button,
+  zen-calendar,
+  zen-checkbox,
+  zen-combobox,
+  zen-command,
+  zen-date-picker,
+  zen-field,
+  zen-form,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-radio-group,
+  zen-select,
+  zen-slider,
+  zen-switch,
+  zen-textarea
+)[size="lg"] {
+  --zenbu-control-height: var(--zenbu-sys-control-height-lg);
+  --zenbu-control-padding-block: var(--zenbu-sys-control-padding-block-lg);
+  --zenbu-control-padding-inline: var(--zenbu-sys-control-padding-inline-lg);
+  --zenbu-control-gap: var(--zenbu-sys-control-gap-lg);
+  --zenbu-control-font-size: var(--zenbu-sys-font-size-lg);
+  --zenbu-control-line-height: var(--zenbu-sys-control-line-height-lg);
+  --zenbu-control-icon-size: var(--zenbu-sys-icon-size-lg);
+}
+
+:where(
+  zen-button,
+  zen-calendar,
+  zen-checkbox,
+  zen-combobox,
+  zen-command,
+  zen-date-picker,
+  zen-field,
+  zen-form,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-radio-group,
+  zen-select,
+  zen-slider,
+  zen-switch,
+  zen-textarea
+)[size="xl"] {
+  --zenbu-control-height: var(--zenbu-sys-control-height-xl);
+  --zenbu-control-padding-block: var(--zenbu-sys-control-padding-block-xl);
+  --zenbu-control-padding-inline: var(--zenbu-sys-control-padding-inline-xl);
+  --zenbu-control-gap: var(--zenbu-sys-control-gap-xl);
+  --zenbu-control-font-size: var(--zenbu-sys-font-size-xl);
+  --zenbu-control-line-height: var(--zenbu-sys-control-line-height-xl);
+  --zenbu-control-icon-size: var(--zenbu-sys-icon-size-xl);
+}
+
+zen-box {
+  display: block;
+  padding: var(--zenbu-box-padding, 0);
+}
+
+zen-box[padding="xs"] { --zenbu-box-padding: var(--zenbu-sys-padding-xs); }
+zen-box[padding="sm"] { --zenbu-box-padding: var(--zenbu-sys-padding-sm); }
+zen-box[padding="md"] { --zenbu-box-padding: var(--zenbu-sys-padding-md); }
+zen-box[padding="lg"] { --zenbu-box-padding: var(--zenbu-sys-padding-lg); }
+zen-box[padding="xl"] { --zenbu-box-padding: var(--zenbu-sys-padding-xl); }
+
+:where(zen-text, zen-heading) {
+  display: contents;
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-md);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-md);
+}
+
+:where(zen-text, zen-heading)[size="xs"] {
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-xs);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-xs);
+}
+
+:where(zen-text, zen-heading)[size="sm"] {
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-sm);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-sm);
+}
+
+:where(zen-text, zen-heading)[size="md"] {
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-md);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-md);
+}
+
+:where(zen-text, zen-heading)[size="lg"] {
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-lg);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-lg);
+}
+
+:where(zen-text, zen-heading)[size="xl"] {
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-xl);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-xl);
+}
+
+zen-text > :where(span, p, small, strong) {
+  font-size: var(--zenbu-type-font-size);
+  line-height: var(--zenbu-type-line-height);
+}
+
+zen-heading {
+  --zenbu-type-font-size: var(--zenbu-sys-font-size-2xl);
+  --zenbu-type-line-height: var(--zenbu-sys-line-height-xl);
+}
+
+zen-heading > :where(h1, h2, h3, h4, h5, h6) {
+  font-size: var(--zenbu-type-font-size);
+  font-weight: var(--zenbu-sys-font-weight-display);
+  line-height: var(--zenbu-type-line-height);
+}
+
+zen-icon {
+  --zenbu-icon-size: 1em;
+  display: inline-grid;
+  width: var(--zenbu-icon-size, 1em);
+  height: var(--zenbu-icon-size, 1em);
+  flex: 0 0 auto;
+  place-items: center;
+  color: inherit;
+  vertical-align: -0.125em;
+}
+
+zen-icon > svg {
+  display: block;
+  width: 100%;
+  height: 100%;
+}
+
+zen-link {
+  display: contents;
+}
+
+zen-link[effect="paw"] > a > [data-zen-link-decoration] {
+  width: 1em;
+  height: 1em;
+  margin-inline-end: var(--zenbu-sys-space-related);
+  color: var(--zenbu-sys-color-link-decoration);
+  animation: zen-paw-step 600ms ease-out both;
+}
+
+zen-link[effect="paw"] > a:hover > [data-zen-link-decoration] {
+  animation: zen-paw-wiggle 400ms ease-in-out infinite;
+}
+
+:where(
+  zen-alert-dialog,
+  zen-calendar,
+  zen-combobox,
+  zen-command,
+  zen-date-picker,
+  zen-dialog,
+  zen-drawer,
+  zen-form,
+  zen-input-otp,
+  zen-popover,
+  zen-progress,
+  zen-radio-group,
+  zen-resizable,
+  zen-select,
+  zen-sheet,
+  zen-sidebar,
+  zen-slider,
+  zen-tabs
+) {
+  display: block;
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) {
+  display: block;
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) details {
+  interpolate-size: allow-keywords;
+  border-block-end: 1px solid color-mix(
+    in srgb,
+    var(--zenbu-sys-color-border-default) 28%,
+    transparent
+  );
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) summary {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-control);
+  padding: var(--zenbu-sys-space-control) 0;
+  font-weight: 800;
+  list-style: none;
+  cursor: pointer;
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) summary::marker,
+:where(
+  zen-accordion,
+  zen-collapsible
+) summary::-webkit-details-marker {
+  display: none;
+  content: "";
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) summary > [data-zen-disclosure-icon] {
+  margin-inline-start: auto;
+  transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) details[open] > summary > [data-zen-disclosure-icon] {
+  transform: rotate(180deg);
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) details::details-content {
+  block-size: 0;
+  overflow: clip;
+  opacity: 0;
+  transition:
+    block-size 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
+    content-visibility 220ms allow-discrete,
+    opacity 180ms ease;
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) details[open]::details-content {
+  block-size: auto;
+  opacity: 1;
+}
+
+:where(
+  zen-accordion,
+  zen-collapsible
+) details > :not(summary) {
+  margin-block-start: 0;
+  padding-block-end: var(--zenbu-sys-space-control);
+  color: var(--zenbu-sys-color-text-secondary);
+}
+
+:where(
+  zen-alert-dialog,
+  zen-dialog,
+  zen-drawer,
+  zen-sheet
+) > [data-zen-trigger],
+:where(
+  zen-dropdown-menu,
+  zen-menubar,
+  zen-navigation-menu,
+  zen-popover
+) [data-zen-trigger],
+zen-empty > button,
+zen-form button,
+zen-input-group button {
+  min-height: var(--zenbu-control-height);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  box-shadow: var(--zenbu-sys-shadow-subtle);
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+  font-weight: 800;
+  cursor: pointer;
+}
+
+:where(
+  zen-alert-dialog,
+  zen-dialog,
+  zen-drawer,
+  zen-sheet
+) dialog {
+  width: min(32rem, calc(100vi - 2rem));
+  padding: var(--zenbu-sys-space-container);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  box-shadow: var(--zenbu-sys-shadow-raised);
+  background: var(--zenbu-sys-color-surface-raised);
+  color: var(--zenbu-sys-color-text-primary);
+}
+
+:where(
+  zen-alert-dialog,
+  zen-dialog,
+  zen-drawer,
+  zen-sheet
+) dialog[open],
+:where(
+  zen-combobox,
+  zen-command,
+  zen-context-menu,
+  zen-dropdown-menu,
+  zen-hover-card,
+  zen-menubar,
+  zen-navigation-menu,
+  zen-popover,
+  zen-tooltip
+) :where(
+  [data-zen-content],
+  [role="listbox"],
+  [role="menu"]
+):not([hidden]) {
+  animation: zen-surface-open 160ms ease-out;
+}
+
+:where(
+  zen-alert-dialog,
+  zen-dialog,
+  zen-drawer,
+  zen-sheet
+) dialog::backdrop {
+  background: var(--zenbu-sys-color-scrim);
+  backdrop-filter: blur(3px);
+}
+
+:where(
+  zen-alert-dialog,
+  zen-dialog,
+  zen-drawer,
+  zen-sheet
+) dialog > h3 {
+  margin-block-start: 0;
+}
+
+:where(
+  zen-alert-dialog,
+  zen-dialog,
+  zen-drawer,
+  zen-sheet
+) dialog button {
+  min-height: 2.35rem;
+  margin-inline-end: var(--zenbu-sys-space-related);
+  padding-inline: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+  font-weight: 700;
+  cursor: pointer;
+}
+
+zen-alert-dialog dialog button[value="confirm"] {
+  background: var(--zenbu-sys-color-danger-foreground);
+  color: var(--zenbu-sys-color-text-inverse);
+}
+
+:where(zen-sheet, zen-drawer) dialog {
+  position: fixed;
+  max-width: none;
+  max-height: none;
+  margin: 0;
+}
+
+:where(zen-sheet, zen-drawer)[placement="right"] dialog {
+  inset: 0 0 0 auto;
+  width: min(28rem, 92vi);
+  height: 100vb;
+  border-radius: var(--zenbu-sys-radius-container) 0 0 var(--zenbu-sys-radius-container);
+}
+
+:where(zen-sheet, zen-drawer)[placement="left"] dialog {
+  inset: 0 auto 0 0;
+  width: min(28rem, 92vi);
+  height: 100vb;
+  border-radius: 0 var(--zenbu-sys-radius-container) var(--zenbu-sys-radius-container) 0;
+}
+
+:where(zen-sheet, zen-drawer)[placement="bottom"] dialog,
+zen-drawer:not([placement]) dialog {
+  inset: auto 0 0;
+  width: 100vi;
+  border-radius: var(--zenbu-sys-radius-container) var(--zenbu-sys-radius-container) 0 0;
+}
+
+zen-aspect-ratio {
+  --zenbu-aspect-ratio: 16 / 9;
+  display: block;
+  aspect-ratio: var(--zenbu-aspect-ratio, 16 / 9);
+  overflow: hidden;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-aspect-ratio > * {
+  width: 100%;
+  height: 100%;
+}
+
+.demo-media {
+  display: grid;
+  place-items: center;
+  background: var(--zenbu-sys-color-surface-subtle);
+  color: var(--zenbu-sys-color-text-primary);
+  font-size: var(--zenbu-sys-font-size-lg);
+  font-weight: 900;
+}
+
+zen-attachment {
+  display: grid;
+  grid-template-columns: 3rem minmax(0, 1fr) auto;
+  align-items: center;
+  gap: var(--zenbu-sys-space-control);
+  padding: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-attachment > span {
+  display: grid;
+  width: 3rem;
+  height: 3rem;
+  place-items: center;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: var(--zenbu-sys-color-info-foreground);
+  color: var(--zenbu-sys-color-text-inverse);
+  font-size: var(--zenbu-sys-font-size-xs);
+  font-weight: 900;
+}
+
+zen-attachment > div,
+zen-item > div {
+  display: grid;
+}
+
+:where(zen-attachment, zen-item) small {
+  color: var(--zenbu-sys-color-text-secondary);
+}
+
+:where(zen-attachment, zen-item) > button {
+  border: 0;
+  background: transparent;
+  color: inherit;
+  cursor: pointer;
+}
+
+zen-avatar {
+  --zenbu-avatar-size: var(--zenbu-sys-control-height-md);
+  display: inline-grid;
+  width: var(--zenbu-avatar-size, 2.75rem);
+  height: var(--zenbu-avatar-size, 2.75rem);
+  overflow: hidden;
+  place-items: center;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 50%;
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+  font-weight: 900;
+}
+
+zen-avatar > img {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
+}
+
+zen-badge {
+  display: inline-flex;
+  align-items: center;
+  min-height: 1.75rem;
+  padding: 0 var(--zenbu-sys-space-related);
+  border: 1px solid var(--zenbu-sys-color-border-default);
+  border-radius: 999px;
+  background: var(--zenbu-sys-color-surface-default);
+  font-size: var(--zenbu-sys-font-size-xs);
+  font-weight: 850;
+}
+
+zen-badge[tone="success"] {
+  background: var(--zenbu-sys-color-success-foreground);
+  color: var(--zenbu-sys-color-text-inverse);
+}
+
+zen-badge[tone="danger"] {
+  background: var(--zenbu-sys-color-danger-foreground);
+  color: var(--zenbu-sys-color-text-inverse);
+}
+
+:where(zen-breadcrumb, zen-pagination) nav {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+}
+
+zen-breadcrumb ol {
+  display: flex;
+  flex-wrap: wrap;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+  margin: 0;
+  padding: 0;
+  list-style: none;
+}
+
+zen-breadcrumb li:not(:last-child)::after {
+  margin-inline-start: var(--zenbu-sys-space-related);
+  color: var(--zenbu-sys-color-text-secondary);
+  content: "/";
+}
+
+:where(zen-breadcrumb, zen-pagination) a {
+  color: var(--zenbu-sys-color-info-foreground);
+  text-underline-offset: 0.2em;
+}
+
+zen-bubble {
+  display: block;
+  width: fit-content;
+  max-width: min(42rem, 88%);
+  padding: var(--zenbu-sys-space-control) var(--zenbu-sys-space-group);
+  border-radius: var(--zenbu-sys-radius-container) var(--zenbu-sys-radius-container)
+    var(--zenbu-sys-radius-container) var(--zenbu-sys-radius-control-small);
+  background: var(--zenbu-sys-color-surface-raised);
+  box-shadow: var(--zenbu-sys-shadow-subtle);
+}
+
+zen-bubble[align="end"] {
+  margin-inline-start: auto;
+  border-radius: var(--zenbu-sys-radius-container) var(--zenbu-sys-radius-container)
+    var(--zenbu-sys-radius-control-small) var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+zen-bubble > :first-child {
+  margin-block-start: 0;
+}
+
+zen-bubble > :last-child {
+  margin-block-end: 0;
+}
+
+zen-button-group {
+  display: inline-flex;
+}
+
+zen-button-group > :where(button, a) {
+  min-height: 2.5rem;
+  padding-inline: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 0;
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+  font-weight: 750;
+  cursor: pointer;
+}
+
+zen-button-group > :first-child {
+  border-radius: var(--zenbu-sys-radius-control) 0 0 var(--zenbu-sys-radius-control);
+}
+
+zen-button-group > :last-child {
+  border-radius: 0 var(--zenbu-sys-radius-control) var(--zenbu-sys-radius-control) 0;
+}
+
+zen-button-group > :not(:first-child) {
+  margin-inline-start: calc(-1 * var(--zenbu-sys-stroke-width-emphasis));
+}
+
+:where(
+  zen-calendar,
+  zen-date-picker,
+  zen-slider
+) {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+  max-width: 22rem;
+}
+
+:where(
+  zen-calendar,
+  zen-date-picker,
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-select,
+  zen-slider,
+  zen-textarea
+):not([appearance="plain"]) :where(input, select, textarea) {
+  appearance: none;
+  min-height: var(--zenbu-control-height);
+  box-sizing: border-box;
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+  font-family: inherit;
+  font-size: var(--zenbu-control-font-size);
+  line-height: var(--zenbu-control-line-height);
+}
+
+:where(
+  zen-input,
+  zen-input-group,
+  zen-input-otp,
+  zen-native-select,
+  zen-select,
+  zen-textarea,
+  zen-calendar,
+  zen-date-picker
+):not([appearance="plain"]) :where(input, select, textarea),
+zen-field:not([appearance="plain"]) > :where(input, select, textarea) {
+  appearance: none;
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+}
+
+:where(zen-native-select, zen-select) {
+  position: relative;
+}
+
+:where(zen-native-select, zen-select) select {
+  width: 100%;
+  padding-inline-end: 2.75rem;
+  cursor: pointer;
+}
+
+:where(zen-native-select, zen-select) > [data-zen-select-icon] {
+  position: absolute;
+  inset-inline-end: var(--zenbu-sys-space-control);
+  inset-block-end: 0.9rem;
+  pointer-events: none;
+}
+
+:where(
+  zen-calendar,
+  zen-date-picker,
+  zen-input,
+  zen-native-select,
+  zen-select,
+  zen-textarea
+):not([appearance="plain"]) {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+}
+
+zen-textarea:not([appearance="plain"]) textarea {
+  width: 100%;
+  min-height: 8rem;
+  resize: vertical;
+}
+
+:where(
+  zen-checkbox,
+  zen-input,
+  zen-native-select,
+  zen-radio-group,
+  zen-select,
+  zen-slider,
+  zen-switch,
+  zen-textarea
+)[appearance="plain"] {
+  display: contents;
+  color: inherit;
+  font-family: inherit;
+}
+
+:where(zen-calendar, zen-date-picker) > input[data-zen-calendar-input] {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  overflow: hidden;
+  clip-path: inset(50%);
+  pointer-events: none;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-generated="calendar"] {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+}
+
+zen-date-picker [data-zen-generated="calendar"] {
+  position: relative;
+}
+
+:where(zen-calendar, zen-date-picker) :where(
+  [data-zen-date-trigger],
+  [data-zen-calendar-previous],
+  [data-zen-calendar-next],
+  [data-zen-calendar-day]
+) {
+  appearance: none;
+  border: 0;
+  background: transparent;
+  color: var(--zenbu-sys-color-text-primary);
+  font: inherit;
+  cursor: pointer;
+}
+
+zen-date-picker [data-zen-date-trigger] {
+  display: inline-flex;
+  min-height: var(--zenbu-control-height);
+  align-items: center;
+  gap: var(--zenbu-control-gap);
+  justify-content: flex-start;
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  box-shadow: var(--zenbu-sys-shadow-subtle);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-date-picker[data-invalid] [data-zen-date-trigger],
+zen-calendar[data-invalid] [data-zen-calendar-view] {
+  border-color: var(--zenbu-sys-color-danger-foreground);
+}
+
+zen-date-picker [data-zen-calendar-panel] {
+  position: absolute;
+  z-index: 40;
+  inset-block-start: calc(100% + var(--zenbu-sys-space-related));
+  inset-inline-start: 0;
+  width: min(21rem, calc(100vi - 2rem));
+  padding: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  box-shadow: var(--zenbu-sys-shadow-raised);
+  background: var(--zenbu-sys-color-surface-raised);
+  transform-origin: top left;
+  animation: zen-calendar-open 160ms ease-out;
+}
+
+zen-date-picker [data-zen-calendar-panel][hidden] {
+  display: none;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-view] {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+  padding: var(--zenbu-sys-space-control);
+  border: 1px solid var(--zenbu-sys-color-border-subtle);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-date-picker [data-zen-calendar-view] {
+  padding: 0;
+  border: 0;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-view] > header {
+  display: grid;
+  grid-template-columns: 2.5rem minmax(0, 1fr) 2.5rem;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+  text-align: center;
+}
+
+:where(zen-calendar, zen-date-picker) :where(
+  [data-zen-calendar-previous],
+  [data-zen-calendar-next]
+) {
+  display: grid;
+  width: 2.5rem;
+  height: 2.5rem;
+  place-items: center;
+  border: 1px solid var(--zenbu-sys-color-border-subtle);
+  border-radius: 50%;
+}
+
+:where(zen-calendar, zen-date-picker) :where(
+  [data-zen-calendar-previous],
+  [data-zen-calendar-next]
+):hover {
+  background: var(--zenbu-sys-color-action-neutral-background-hover);
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-weekdays],
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-grid] > [role="row"] {
+  display: grid;
+  grid-template-columns: repeat(7, minmax(2rem, 1fr));
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-weekdays] > span {
+  padding-block: var(--zenbu-sys-space-icon-label);
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-xs);
+  font-weight: 800;
+  text-align: center;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-grid] {
+  display: grid;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-day] {
+  aspect-ratio: 1;
+  min-width: 2rem;
+  border-radius: 50%;
+  font-size: var(--zenbu-sys-font-size-sm);
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-day]:hover {
+  background: var(--zenbu-sys-color-action-neutral-background-hover);
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-day][data-outside] {
+  color: var(--zenbu-sys-color-text-tertiary);
+  opacity: 0.55;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-day][data-today] {
+  outline: 1px solid var(--zenbu-sys-color-info-foreground);
+  outline-offset: -2px;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-day][aria-selected="true"] {
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+  font-weight: 900;
+}
+
+:where(zen-calendar, zen-date-picker) [data-zen-calendar-day]:disabled {
+  color: var(--zenbu-sys-color-text-disabled);
+  cursor: not-allowed;
+}
+
+@keyframes zen-calendar-open {
+  from {
+    opacity: 0;
+    transform: translateY(calc(-1 * var(--zenbu-sys-space-icon-label))) scale(0.98);
+  }
+}
+
+@keyframes zen-paw-step {
+  from {
+    opacity: 0;
+    transform: scale(0);
+  }
+  to {
+    opacity: 1;
+    transform: scale(1);
+  }
+}
+
+@keyframes zen-paw-wiggle {
+  0%,
+  100% {
+    transform: rotate(-15deg);
+  }
+  50% {
+    transform: rotate(15deg);
+  }
+}
+
+@keyframes zen-surface-open {
+  from {
+    opacity: 0;
+    transform: translateY(calc(-1 * var(--zenbu-sys-space-icon-label))) scale(0.98);
+  }
+}
+
+@media print {
+  zen-link[effect="paw"] > a > [data-zen-link-decoration] {
+    display: none;
+  }
+}
+
+zen-input-group {
+  display: flex;
+  align-items: stretch;
+  width: min(100%, 36rem);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-input-group > :where(span, button) {
+  display: inline-flex;
+  align-items: center;
+  padding-inline: var(--zenbu-sys-space-control);
+}
+
+zen-input-group input {
+  min-width: 0;
+  flex: 1;
+  border: 0;
+  border-radius: 0;
+}
+
+zen-input-group button {
+  min-height: auto;
+  border-width: 0 0 0 var(--zenbu-sys-stroke-width-emphasis);
+  border-radius: 0 var(--zenbu-sys-radius-control-small) var(--zenbu-sys-radius-control-small) 0;
+  box-shadow: none;
+}
+
+zen-carousel {
+  position: relative;
+  display: grid;
+  grid-template-columns: auto minmax(0, 1fr) auto;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+}
+
+zen-carousel [data-zen-viewport] {
+  display: flex;
+  grid-column: 1 / -1;
+  gap: var(--zenbu-sys-space-control);
+  overflow: auto;
+  scroll-snap-type: inline mandatory;
+  scrollbar-width: none;
+}
+
+zen-carousel [data-zen-viewport] > * {
+  min-width: min(22rem, 82vi);
+  min-height: 9rem;
+  padding: var(--zenbu-sys-space-container);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-raised);
+  scroll-snap-align: start;
+}
+
+zen-carousel :where([data-zen-prev], [data-zen-next]) {
+  width: 2.5rem;
+  height: 2.5rem;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 50%;
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+  cursor: pointer;
+}
+
+zen-carousel [data-zen-prev] {
+  grid-column: 1;
+}
+
+zen-carousel [data-zen-next] {
+  grid-column: 3;
+}
+
+zen-chart {
+  display: block;
+  min-height: 15rem;
+  padding: var(--zenbu-sys-space-group);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-chart [data-zen-chart-plot] {
+  display: flex;
+  height: 12rem;
+  align-items: end;
+  justify-content: space-around;
+  gap: var(--zenbu-sys-space-control);
+  border-block-end: 1px solid var(--zenbu-sys-color-border-default);
+}
+
+zen-chart [data-zen-chart-plot] > span {
+  --zenbu-chart-value: 0%;
+  position: relative;
+  width: min(3rem, 15%);
+  height: var(--zenbu-chart-value);
+  min-height: 1rem;
+  border-radius: var(--zenbu-sys-radius-control-small) var(--zenbu-sys-radius-control-small) 0 0;
+  background: var(--zenbu-sys-color-data-1);
+}
+
+zen-chart [data-zen-chart-plot] > span:nth-child(2) {
+  background: var(--zenbu-sys-color-data-2);
+}
+
+zen-chart [data-zen-chart-plot] > span:nth-child(3) {
+  background: var(--zenbu-sys-color-data-3);
+}
+
+zen-chart [data-zen-chart-plot] > span:nth-child(4) {
+  background: var(--zenbu-sys-color-data-4);
+}
+
+zen-chart [data-zen-chart-plot] > span:nth-child(5) {
+  background: var(--zenbu-sys-color-data-5);
+}
+
+zen-chart [data-zen-chart-plot] > span::after {
+  position: absolute;
+  inset-block-start: 100%;
+  inset-inline-start: 50%;
+  padding-block-start: var(--zenbu-sys-space-icon-label);
+  color: var(--zenbu-sys-color-text-secondary);
+  content: attr(data-label);
+  font-size: var(--zenbu-sys-font-size-xs);
+  transform: translateX(-50%);
+}
+
+:where(
+  zen-checkbox:not([appearance="plain"]),
+  zen-switch:not([appearance="plain"])
+) label,
+zen-radio-group:not([appearance="plain"]) label {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+  width: fit-content;
+  cursor: pointer;
+}
+
+:where(
+  zen-checkbox:not([appearance="plain"]),
+  zen-radio-group:not([appearance="plain"])
+) input {
+  appearance: none;
+  display: inline-grid;
+  width: 1.2rem;
+  height: 1.2rem;
+  flex: 0 0 auto;
+  place-content: center;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  background: var(--zenbu-sys-color-surface-default);
+  cursor: pointer;
+}
+
+zen-checkbox:not([appearance="plain"]) input {
+  border-radius: var(--zenbu-sys-radius-control-small);
+}
+
+zen-checkbox:not([appearance="plain"]) input::before {
+  width: 0.55rem;
+  height: 0.3rem;
+  border-block-end: 2px solid var(--zenbu-sys-color-action-primary-foreground);
+  border-inline-start: 2px solid var(--zenbu-sys-color-action-primary-foreground);
+  content: "";
+  opacity: 0;
+  transform: translateY(-0.08rem) rotate(-45deg);
+}
+
+zen-checkbox:not([appearance="plain"]) input:checked {
+  background: var(--zenbu-sys-color-action-primary-background);
+}
+
+zen-checkbox:not([appearance="plain"]) input:checked::before {
+  opacity: 1;
+}
+
+zen-radio-group:not([appearance="plain"]) input {
+  border-radius: 50%;
+}
+
+zen-radio-group:not([appearance="plain"]) input::before {
+  width: 0.55rem;
+  height: 0.55rem;
+  border-radius: 50%;
+  background: var(--zenbu-sys-color-info-foreground);
+  content: "";
+  opacity: 0;
+}
+
+zen-radio-group:not([appearance="plain"]) input:checked::before {
+  opacity: 1;
+}
+
+zen-radio-group:not([appearance="plain"]) fieldset {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+  padding: var(--zenbu-sys-space-group);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+}
+
+zen-switch:not([appearance="plain"]) input {
+  appearance: none;
+  width: 2.75rem;
+  height: 1.5rem;
+  margin: 0;
+  padding: 2px;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 999px;
+  background: var(--zenbu-sys-color-surface-default);
+  cursor: pointer;
+  transition: background var(--zenbu-sys-motion-duration-feedback) ease;
+}
+
+zen-switch:not([appearance="plain"]) input::before {
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  border-radius: 50%;
+  background: var(--zenbu-sys-color-border-default);
+  content: "";
+  transition: transform var(--zenbu-sys-motion-duration-feedback) ease;
+}
+
+zen-switch:not([appearance="plain"]) input:checked {
+  background: var(--zenbu-sys-color-success-foreground);
+}
+
+zen-switch:not([appearance="plain"]) input:checked::before {
+  background: var(--zenbu-sys-color-text-inverse);
+  transform: translateX(1.2rem);
+}
+
+:where(zen-combobox, zen-command) {
+  position: relative;
+  display: grid;
+  width: min(100%, 28rem);
+  gap: var(--zenbu-sys-space-related);
+}
+
+:where(zen-combobox, zen-command) > input {
+  min-height: var(--zenbu-control-height);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+  color: var(--zenbu-sys-color-text-primary);
+}
+
+:where(
+  zen-combobox,
+  zen-command,
+  zen-context-menu,
+  zen-dropdown-menu,
+  zen-menubar,
+  zen-navigation-menu
+) :where([role="listbox"], [role="menu"]) {
+  z-index: 20;
+  display: grid;
+  min-width: 12rem;
+  padding: var(--zenbu-sys-space-icon-label);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  box-shadow: var(--zenbu-sys-shadow-raised);
+  background: var(--zenbu-sys-color-surface-raised);
+}
+
+:where(
+  zen-combobox,
+  zen-command,
+  zen-context-menu,
+  zen-dropdown-menu,
+  zen-menubar,
+  zen-navigation-menu
+) :where([role="listbox"], [role="menu"])[hidden] {
+  display: none;
+}
+
+:where(
+  zen-combobox,
+  zen-command,
+  zen-context-menu,
+  zen-dropdown-menu,
+  zen-menubar,
+  zen-navigation-menu
+) :where([role="option"], [role="menuitem"]) {
+  display: block;
+  width: 100%;
+  padding: var(--zenbu-sys-space-related) var(--zenbu-sys-space-control);
+  border: 0;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: transparent;
+  color: var(--zenbu-sys-color-text-primary);
+  text-align: start;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+:where(
+  zen-combobox,
+  zen-command,
+  zen-context-menu,
+  zen-dropdown-menu,
+  zen-menubar,
+  zen-navigation-menu
+) :where([role="option"], [role="menuitem"]):is(
+  :hover,
+  :focus,
+  [aria-selected="true"]
+) {
+  outline: none;
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+:where(
+  zen-context-menu,
+  zen-dropdown-menu,
+  zen-navigation-menu
+) {
+  position: relative;
+  display: inline-block;
+}
+
+zen-context-menu > [data-zen-trigger] {
+  min-height: 8rem;
+  padding: var(--zenbu-sys-space-container);
+  border: 2px dashed var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+:where(
+  zen-dropdown-menu,
+  zen-navigation-menu
+) > [role="menu"],
+zen-navigation-menu nav > [role="menu"] {
+  position: absolute;
+  inset-block-start: calc(100% + var(--zenbu-sys-space-related));
+  inset-inline-start: 0;
+}
+
+zen-context-menu > [role="menu"] {
+  position: fixed;
+}
+
+zen-menubar {
+  position: relative;
+  display: flex;
+  width: fit-content;
+  padding: var(--zenbu-sys-space-icon-label);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-menubar > [data-zen-trigger] {
+  border: 0;
+  box-shadow: none;
+  background: transparent;
+  color: var(--zenbu-sys-color-text-primary);
+}
+
+zen-menubar > [role="menu"] {
+  position: absolute;
+  inset-block-start: calc(100% + var(--zenbu-sys-space-icon-label));
+}
+
+zen-data-table,
+zen-table {
+  display: block;
+  max-width: 100%;
+  overflow: auto;
+}
+
+:where(zen-data-table, zen-table) table {
+  width: 100%;
+  border-collapse: collapse;
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+:where(zen-data-table, zen-table) :where(th, td) {
+  padding: var(--zenbu-sys-space-control);
+  border-block-end: 1px solid color-mix(
+    in srgb,
+    var(--zenbu-sys-color-border-default) 30%,
+    transparent
+  );
+  text-align: start;
+}
+
+:where(zen-data-table, zen-table) th {
+  font-size: var(--zenbu-sys-font-size-sm);
+}
+
+zen-data-table [data-zen-sort] {
+  padding: 0;
+  border: 0;
+  background: transparent;
+  color: inherit;
+  font-weight: 850;
+  cursor: pointer;
+}
+
+zen-direction {
+  display: contents;
+}
+
+zen-empty {
+  display: grid;
+  justify-items: center;
+  gap: var(--zenbu-sys-space-related);
+  padding: var(--zenbu-sys-space-section) var(--zenbu-sys-space-container);
+  border: var(--zenbu-sys-stroke-width-emphasis) dashed var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+  text-align: center;
+}
+
+zen-empty > p {
+  max-width: 34rem;
+  margin: 0;
+  color: var(--zenbu-sys-color-text-secondary);
+}
+
+zen-form form {
+  display: grid;
+  max-width: 34rem;
+  gap: var(--zenbu-sys-space-group);
+}
+
+zen-form[data-invalid] form {
+  padding-inline-start: var(--zenbu-sys-space-control);
+  border-inline-start: 0.35rem solid var(--zenbu-sys-color-danger-foreground);
+}
+
+:where(zen-hover-card, zen-tooltip, zen-popover) {
+  position: relative;
+  display: inline-block;
+}
+
+:where(zen-hover-card, zen-tooltip, zen-popover) [data-zen-content] {
+  position: absolute;
+  z-index: 30;
+  inset-block-start: calc(100% + var(--zenbu-sys-space-related));
+  inset-inline-start: 0;
+  width: max-content;
+  max-width: min(22rem, calc(100vi - 2rem));
+  padding: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  box-shadow: var(--zenbu-sys-shadow-raised);
+  background: var(--zenbu-sys-color-surface-raised);
+  color: var(--zenbu-sys-color-text-primary);
+}
+
+:where(zen-hover-card, zen-tooltip, zen-popover) [data-zen-content][hidden] {
+  display: none;
+}
+
+zen-tooltip [data-zen-content] {
+  padding: var(--zenbu-sys-space-icon-label) var(--zenbu-sys-space-related);
+  background: var(--zenbu-sys-color-border-default);
+  color: var(--zenbu-sys-color-surface-default);
+  font-size: var(--zenbu-sys-font-size-xs);
+}
+
+zen-input-otp [data-zen-otp-slots] {
+  display: flex;
+  gap: var(--zenbu-control-gap);
+}
+
+zen-input-otp [data-zen-otp-slots] > span {
+  display: grid;
+  width: var(--zenbu-control-height);
+  height: var(--zenbu-control-height);
+  place-items: center;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: var(--zenbu-sys-color-surface-default);
+  font-size: var(--zenbu-control-font-size);
+  font-weight: var(--zenbu-sys-font-weight-strong);
+}
+
+zen-item {
+  display: grid;
+  grid-template-columns: auto minmax(0, 1fr) auto;
+  align-items: center;
+  gap: var(--zenbu-sys-space-control);
+  padding: var(--zenbu-sys-space-control);
+  border-block-end: 1px solid color-mix(
+    in srgb,
+    var(--zenbu-sys-color-border-default) 28%,
+    transparent
+  );
+}
+
+zen-kbd {
+  display: inline-flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+zen-kbd kbd {
+  min-width: 1.75rem;
+  padding: 0.1rem var(--zenbu-sys-space-icon-label);
+  border: 1px solid var(--zenbu-sys-color-border-default);
+  border-block-end-width: 3px;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: var(--zenbu-sys-color-surface-default);
+  font: 700 var(--zenbu-sys-font-size-xs)/1.5 var(--zenbu-sys-font-family-code);
+  text-align: center;
+}
+
+zen-label {
+  display: block;
+  margin-block-end: var(--zenbu-sys-space-related);
+  font-weight: 800;
+}
+
+zen-marker {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-related);
+  color: var(--zenbu-sys-color-text-secondary);
+  font-size: var(--zenbu-sys-font-size-xs);
+  text-transform: uppercase;
+}
+
+zen-marker::before,
+zen-marker::after {
+  height: 1px;
+  flex: 1;
+  background: color-mix(
+    in srgb,
+    var(--zenbu-sys-color-border-default) 32%,
+    transparent
+  );
+  content: "";
+}
+
+zen-message {
+  display: grid;
+  grid-template-columns: auto minmax(0, 1fr);
+  align-items: start;
+  gap: var(--zenbu-sys-space-control);
+}
+
+zen-message > div {
+  display: grid;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+zen-message-scroller {
+  position: relative;
+  display: block;
+}
+
+zen-message-scroller [data-zen-viewport] {
+  max-height: 12rem;
+  overflow: auto;
+  padding: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-message-scroller [data-zen-scroll-end] {
+  position: absolute;
+  inset-inline-end: var(--zenbu-sys-space-control);
+  inset-block-end: var(--zenbu-sys-space-control);
+}
+
+zen-navigation-menu nav {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-control);
+}
+
+zen-pagination nav {
+  flex-wrap: wrap;
+}
+
+zen-pagination a {
+  display: inline-grid;
+  min-width: 2.35rem;
+  min-height: 2.35rem;
+  place-items: center;
+  padding-inline: var(--zenbu-sys-space-related);
+  border: 1px solid transparent;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  text-decoration: none;
+}
+
+zen-pagination a[aria-current] {
+  border-color: var(--zenbu-sys-color-border-default);
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+zen-progress {
+  display: grid;
+  gap: var(--zenbu-sys-space-related);
+}
+
+zen-progress progress {
+  appearance: none;
+  width: 100%;
+  height: 0.75rem;
+  overflow: hidden;
+  border: 0;
+  border-radius: 999px;
+  accent-color: var(--zenbu-sys-color-success-foreground);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-progress progress::-webkit-progress-bar {
+  background: var(--zenbu-sys-color-surface-subtle);
+}
+
+zen-progress progress::-webkit-progress-value {
+  background: var(--zenbu-sys-color-success-foreground);
+}
+
+zen-progress progress::-moz-progress-bar {
+  background: var(--zenbu-sys-color-success-foreground);
+}
+
+zen-resizable {
+  display: flex;
+  min-height: 12rem;
+  overflow: hidden;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+}
+
+zen-resizable [data-zen-panel] {
+  min-width: 0;
+  flex: 1 1 50%;
+  padding: var(--zenbu-sys-space-group);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-resizable [data-zen-handle] {
+  width: 0.65rem;
+  flex: 0 0 0.65rem;
+  border-inline: 1px solid var(--zenbu-sys-color-border-default);
+  background: var(--zenbu-sys-color-action-primary-background);
+  cursor: col-resize;
+}
+
+zen-scroll-area {
+  display: block;
+  max-height: 10rem;
+  overflow: auto;
+  padding: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+  scrollbar-color: var(--zenbu-sys-color-action-primary-background) transparent;
+}
+
+zen-separator {
+  display: block;
+}
+
+zen-separator hr {
+  margin-block: var(--zenbu-sys-space-group);
+  border: 0;
+  border-block-start: 1px solid var(--zenbu-sys-color-border-default);
+}
+
+zen-separator[orientation="vertical"] {
+  display: inline-block;
+  width: 1px;
+  min-height: 1.5rem;
+  background: var(--zenbu-sys-color-border-default);
+}
+
+zen-sidebar {
+  display: grid;
+  grid-template-columns: minmax(12rem, 17rem) minmax(0, 1fr);
+  gap: var(--zenbu-sys-space-control);
+}
+
+zen-sidebar > [data-zen-sidebar-trigger] {
+  grid-column: 1 / -1;
+  justify-self: start;
+}
+
+zen-sidebar [data-zen-sidebar-panel] {
+  padding: var(--zenbu-sys-space-control);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-container);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-sidebar [data-zen-sidebar-panel] nav {
+  display: grid;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+zen-sidebar [data-zen-sidebar-panel] a {
+  padding: var(--zenbu-sys-space-related);
+  border-radius: var(--zenbu-sys-radius-control-small);
+  color: inherit;
+  text-decoration: none;
+}
+
+zen-sidebar [data-zen-sidebar-panel] a:hover {
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+zen-skeleton {
+  --zenbu-skeleton-width: 100%;
+  display: block;
+  width: var(--zenbu-skeleton-width, 100%);
+  height: 1rem;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background:
+    linear-gradient(
+      100deg,
+      color-mix(in srgb, var(--zenbu-sys-color-text-secondary) 18%, transparent) 20%,
+      color-mix(in srgb, var(--zenbu-sys-color-text-secondary) 8%, transparent) 38%,
+      color-mix(in srgb, var(--zenbu-sys-color-text-secondary) 18%, transparent) 56%
+    );
+  background-size: 200% 100%;
+  animation: zen-skeleton-shimmer 1.4s linear infinite;
+}
+
+zen-skeleton[shape="circle"] {
+  width: 3rem;
+  height: 3rem;
+  border-radius: 50%;
+}
+
+zen-slider:not([appearance="plain"]) input {
+  appearance: none;
+  width: 100%;
+  height: 0.5rem;
+  padding-inline: 0;
+  border: 0;
+  border-radius: 999px;
+  background: var(--zenbu-sys-color-surface-sunken);
+  cursor: pointer;
+}
+
+zen-slider:not([appearance="plain"]) input::-webkit-slider-thumb {
+  appearance: none;
+  width: 1.35rem;
+  height: 1.35rem;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 50%;
+  box-shadow: var(--zenbu-sys-shadow-subtle);
+  background: var(--zenbu-sys-color-action-primary-background);
+}
+
+zen-slider:not([appearance="plain"]) input::-moz-range-thumb {
+  width: 1.35rem;
+  height: 1.35rem;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--zenbu-sys-color-border-default);
+  border-radius: 50%;
+  box-shadow: var(--zenbu-sys-shadow-subtle);
+  background: var(--zenbu-sys-color-action-primary-background);
+}
+
+zen-spinner {
+  display: inline-block;
+  width: 1.35rem;
+  height: 1.35rem;
+  border: 3px solid color-mix(
+    in srgb,
+    var(--zenbu-sys-color-text-secondary) 28%,
+    transparent
+  );
+  border-inline-end-color: var(--zenbu-sys-color-info-foreground);
+  border-radius: 50%;
+  animation: zen-element-spin 650ms linear infinite;
+}
+
+zen-tabs [role="tablist"] {
+  display: flex;
+  width: fit-content;
+  gap: var(--zenbu-sys-space-icon-label);
+  padding: var(--zenbu-sys-space-icon-label);
+  border: 1px solid var(--zenbu-sys-color-border-default);
+  border-radius: var(--zenbu-sys-radius-control);
+  background: var(--zenbu-sys-color-surface-default);
+}
+
+zen-tabs [role="tab"] {
+  min-height: 2.25rem;
+  padding-inline: var(--zenbu-sys-space-control);
+  border: 0;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: transparent;
+  color: var(--zenbu-sys-color-text-primary);
+  font-weight: 750;
+  cursor: pointer;
+}
+
+zen-tabs [role="tab"][aria-selected="true"] {
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+zen-tabs [role="tabpanel"] {
+  padding-block: var(--zenbu-sys-space-group);
+}
+
+zen-tabs [role="tabpanel"][hidden] {
+  display: none;
+}
+
+:where(zen-toggle, zen-toggle-group) {
+  display: inline-flex;
+}
+
+:where(zen-toggle, zen-toggle-group) > button {
+  min-height: 2.5rem;
+  padding-inline: var(--zenbu-sys-space-control);
+  border: 1px solid transparent;
+  border-radius: var(--zenbu-sys-radius-control-small);
+  background: transparent;
+  color: var(--zenbu-sys-color-text-primary);
+  font-weight: 750;
+  cursor: pointer;
+}
+
+:where(zen-toggle, zen-toggle-group) > button[aria-pressed="true"] {
+  border-color: var(--zenbu-sys-color-border-default);
+  background: var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-action-primary-foreground);
+}
+
+zen-typography {
+  display: block;
+  max-width: 65ch;
+  line-height: var(--zenbu-sys-type-body-line-height);
+}
+
+zen-typography > :where(h1, h2, h3) {
+  line-height: 1.15;
+  text-wrap: balance;
+}
+
+zen-typography blockquote {
+  margin-inline: 0;
+  padding-inline-start: var(--zenbu-sys-space-group);
+  border-inline-start: 0.35rem solid var(--zenbu-sys-color-action-primary-background);
+  color: var(--zenbu-sys-color-text-secondary);
+  font-style: italic;
+}
+
+:where(
+  button,
+  summary,
+  [tabindex]
+):focus-visible {
+  outline: 3px solid var(--zenbu-sys-color-focus-outer);
+  outline-offset: 3px;
+}
+
+:where(
+  zen-calendar:not([appearance="plain"]),
+  zen-checkbox:not([appearance="plain"]),
+  zen-combobox:not([appearance="plain"]),
+  zen-command:not([appearance="plain"]),
+  zen-date-picker:not([appearance="plain"]),
+  zen-field:not([appearance="plain"]),
+  zen-form:not([appearance="plain"]),
+  zen-input:not([appearance="plain"]),
+  zen-input-group:not([appearance="plain"]),
+  zen-input-otp:not([appearance="plain"]),
+  zen-native-select:not([appearance="plain"]),
+  zen-radio-group:not([appearance="plain"]),
+  zen-select:not([appearance="plain"]),
+  zen-slider:not([appearance="plain"]),
+  zen-switch:not([appearance="plain"]),
+  zen-textarea:not([appearance="plain"])
+) :where(input, select, textarea):focus-visible {
+  outline: none;
+}
+
+@keyframes zen-element-spin {
+  to { transform: rotate(1turn); }
+}
+
+@keyframes zen-skeleton-shimmer {
+  to { background-position-x: -200%; }
+}
+
+@media (max-width: 640px) {
+  zen-sidebar {
+    display: block;
+  }
+
+  zen-sidebar > [data-zen-sidebar-trigger] {
+    margin-block-end: var(--zenbu-sys-space-related);
+  }
+
+  :where(zen-calendar, zen-date-picker) {
+    width: 100%;
+    max-width: 100%;
+  }
+
+  zen-date-picker [data-zen-calendar-panel] {
+    position: fixed;
+    inset: auto var(--zenbu-sys-space-control) var(--zenbu-sys-space-control);
+    width: auto;
+    max-height: calc(100vb - 2 * var(--zenbu-sys-space-control));
+    overflow: auto;
+    transform-origin: bottom center;
+  }
+}
+
+@media (forced-colors: active) {
+  :where(
+    zen-aspect-ratio,
+    zen-attachment,
+    zen-avatar,
+    zen-badge,
+    zen-empty,
+    zen-resizable,
+    zen-scroll-area
+  ) {
+    border: 1px solid CanvasText;
+  }
+}
+
+@media (prefers-reduced-motion: reduce) {
+  zen-link[effect="paw"] > a > [data-zen-link-decoration],
+  zen-link[effect="paw"] > a:hover > [data-zen-link-decoration] {
+    animation: none;
+  }
+
+  zen-skeleton,
+  zen-spinner {
+    animation: none;
+  }
+
+  zen-switch input,
+  zen-switch input::before,
+  :where(
+    zen-accordion,
+    zen-collapsible
+  ) details::details-content,
+  :where(
+    zen-accordion,
+    zen-collapsible
+  ) summary > [data-zen-disclosure-icon] {
+    transition: none;
+  }
+
+  zen-date-picker [data-zen-calendar-panel] {
+    animation: none;
+  }
+
+  :where(
+    zen-alert-dialog,
+    zen-dialog,
+    zen-drawer,
+    zen-sheet
+  ) dialog[open],
+  :where(
+    zen-combobox,
+    zen-command,
+    zen-context-menu,
+    zen-dropdown-menu,
+    zen-hover-card,
+    zen-menubar,
+    zen-navigation-menu,
+    zen-popover,
+    zen-tooltip
+  ) :where(
+    [data-zen-content],
+    [role="listbox"],
+    [role="menu"]
+  ):not([hidden]) {
+    animation: none;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/styles/reference.css	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,167 @@
+:root {
+  --zenbu-ref-color-black: #000000;
+  --zenbu-ref-color-white: #ffffff;
+  --zenbu-ref-color-transparent: transparent;
+
+  --zenbu-ref-color-neutral-50: #fffdf7;
+  --zenbu-ref-color-neutral-100: #f7f3e8;
+  --zenbu-ref-color-neutral-200: #ece5d5;
+  --zenbu-ref-color-neutral-300: #ddd2bd;
+  --zenbu-ref-color-neutral-400: #b9aa90;
+  --zenbu-ref-color-neutral-500: #8e8069;
+  --zenbu-ref-color-neutral-600: #6f6351;
+  --zenbu-ref-color-neutral-700: #564c3e;
+  --zenbu-ref-color-neutral-800: #3b352d;
+  --zenbu-ref-color-neutral-900: #27241f;
+  --zenbu-ref-color-neutral-950: #171613;
+
+  --zenbu-ref-color-brand-100: #e4eaf2;
+  --zenbu-ref-color-brand-200: #cbd7e6;
+  --zenbu-ref-color-brand-300: #a6bad2;
+  --zenbu-ref-color-brand-400: #7b99b8;
+  --zenbu-ref-color-brand-500: #5c7d9d;
+  --zenbu-ref-color-brand-600: #48647f;
+  --zenbu-ref-color-brand-700: #3c5167;
+  --zenbu-ref-color-brand-800: #354655;
+  --zenbu-ref-color-brand-900: #303c49;
+
+  --zenbu-ref-color-danger-100: #f9e9e2;
+  --zenbu-ref-color-danger-300: #dda995;
+  --zenbu-ref-color-danger-500: #a9553f;
+  --zenbu-ref-color-danger-600: #8f4132;
+  --zenbu-ref-color-danger-700: #71342a;
+  --zenbu-ref-color-danger-900: #4b2924;
+  --zenbu-ref-color-success-100: #e9edd5;
+  --zenbu-ref-color-success-300: #afbf79;
+  --zenbu-ref-color-success-500: #6d8139;
+  --zenbu-ref-color-success-600: #55672d;
+  --zenbu-ref-color-success-700: #424f27;
+  --zenbu-ref-color-success-900: #303923;
+  --zenbu-ref-color-warning-100: #fcebd1;
+  --zenbu-ref-color-warning-300: #efb670;
+  --zenbu-ref-color-warning-500: #c76a26;
+  --zenbu-ref-color-warning-600: #a94f1c;
+  --zenbu-ref-color-warning-700: #873d1b;
+  --zenbu-ref-color-warning-900: #5b2d1d;
+  --zenbu-ref-color-amber-50: #fffbea;
+  --zenbu-ref-color-amber-100: #f6efc6;
+  --zenbu-ref-color-amber-300: #d9c455;
+  --zenbu-ref-color-amber-600: #80651e;
+  --zenbu-ref-color-orange-100: #fcebd1;
+  --zenbu-ref-color-orange-300: #efb670;
+  --zenbu-ref-color-rose-100: #f8e7e7;
+  --zenbu-ref-color-rose-300: #dfa9ad;
+  --zenbu-ref-color-rose-600: #924550;
+  --zenbu-ref-color-violet-100: #eee7ee;
+  --zenbu-ref-color-violet-500: #916f91;
+  --zenbu-ref-color-violet-700: #5e465d;
+  --zenbu-ref-color-blue-600: #48647f;
+  --zenbu-ref-color-blue-900: #303c49;
+  --zenbu-ref-color-blue-950: #1c252e;
+  --zenbu-ref-color-accent: #ffb000;
+  --zenbu-ref-color-accent-hover: #ffca4a;
+  --zenbu-ref-color-accent-pressed: #9e8124;
+  --zenbu-ref-color-info: #2764d7;
+  --zenbu-ref-color-success: #18794e;
+  --zenbu-ref-color-warning: #9a5b00;
+  --zenbu-ref-color-danger: #c62f3e;
+  --zenbu-ref-color-focus: #7c3aed;
+  --zenbu-ref-color-link-decoration: #ae5b65;
+  --zenbu-ref-color-black-alpha-8: rgba(0, 0, 0, 0.08);
+  --zenbu-ref-color-black-alpha-60: rgba(0, 0, 0, 0.6);
+
+  --zenbu-ref-space-0: 0;
+  --zenbu-ref-space-0-5: 0.125rem;
+  --zenbu-ref-space-1: 0.25rem;
+  --zenbu-ref-space-1-5: 0.375rem;
+  --zenbu-ref-space-2: 0.5rem;
+  --zenbu-ref-space-2-5: 0.625rem;
+  --zenbu-ref-space-3: 0.75rem;
+  --zenbu-ref-space-4: 1rem;
+  --zenbu-ref-space-5: 1.25rem;
+  --zenbu-ref-space-6: 1.5rem;
+  --zenbu-ref-space-8: 2rem;
+  --zenbu-ref-space-10: 2.5rem;
+  --zenbu-ref-space-12: 3rem;
+  --zenbu-ref-space-16: 4rem;
+  --zenbu-ref-space-20: 5rem;
+  --zenbu-ref-space-24: 6rem;
+
+  --zenbu-ref-font-family-sans:
+    Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
+    "Segoe UI", sans-serif;
+  --zenbu-ref-font-family-mono:
+    "SFMono-Regular", Consolas, "Liberation Mono", monospace;
+  --zenbu-ref-font-size-xs: 0.75rem;
+  --zenbu-ref-font-size-sm: 0.875rem;
+  --zenbu-ref-font-size-md: 1rem;
+  --zenbu-ref-font-size-lg: 1.125rem;
+  --zenbu-ref-font-size-xl: 1.25rem;
+  --zenbu-ref-font-size-2xl: 1.5rem;
+  --zenbu-ref-font-size-3xl: 2rem;
+  --zenbu-ref-font-size-display: 2.5rem;
+  --zenbu-ref-font-weight-regular: 400;
+  --zenbu-ref-font-weight-medium: 500;
+  --zenbu-ref-font-weight-strong: 600;
+  --zenbu-ref-font-weight-bold: 700;
+  --zenbu-ref-line-height-tight: 1.15;
+  --zenbu-ref-line-height-heading: 1.25;
+  --zenbu-ref-line-height-ui: 1.4;
+  --zenbu-ref-line-height-body: 1.55;
+  --zenbu-ref-line-height-reading: 1.7;
+  --zenbu-ref-letter-spacing-tight: -0.02em;
+  --zenbu-ref-letter-spacing-normal: 0;
+  --zenbu-ref-letter-spacing-wide: 0.02em;
+  --zenbu-ref-letter-spacing-caps: 0.06em;
+
+  --zenbu-ref-radius-0: 0;
+  --zenbu-ref-radius-1: 0.25rem;
+  --zenbu-ref-radius-2: 0.5rem;
+  --zenbu-ref-radius-3: 0.75rem;
+  --zenbu-ref-radius-4: 1rem;
+  --zenbu-ref-radius-5: 1.5rem;
+  --zenbu-ref-radius-6: 2rem;
+  --zenbu-ref-radius-round: 9999px;
+  --zenbu-ref-stroke-0: 0;
+  --zenbu-ref-stroke-1: 1px;
+  --zenbu-ref-stroke-2: 2px;
+  --zenbu-ref-stroke-3: 3px;
+
+  --zenbu-ref-shadow-1: 3px 3px 0 rgba(23, 26, 33, 0.12);
+  --zenbu-ref-shadow-2: 5px 5px 0 rgba(23, 26, 33, 0.16);
+  --zenbu-ref-shadow-3: 7px 7px 0 rgba(23, 26, 33, 0.18);
+  --zenbu-ref-shadow-4: 10px 10px 0 rgba(23, 26, 33, 0.2);
+
+  --zenbu-ref-duration-instant: 50ms;
+  --zenbu-ref-duration-fast: 120ms;
+  --zenbu-ref-duration-normal: 200ms;
+  --zenbu-ref-duration-slow: 300ms;
+  --zenbu-ref-duration-deliberate: 500ms;
+  --zenbu-ref-ease-linear: linear;
+  --zenbu-ref-ease-standard: cubic-bezier(0.2, 0, 0, 1);
+  --zenbu-ref-ease-enter: cubic-bezier(0, 0, 0, 1);
+  --zenbu-ref-ease-exit: cubic-bezier(0.3, 0, 1, 1);
+  --zenbu-ref-ease-emphasized: cubic-bezier(0.2, 0.8, 0.2, 1);
+
+  --zenbu-ref-opacity-disabled: 0.45;
+  --zenbu-ref-opacity-muted: 0.7;
+  --zenbu-ref-opacity-backdrop: 0.6;
+  --zenbu-ref-size-icon-xs: 0.75rem;
+  --zenbu-ref-size-icon-sm: 0.875rem;
+  --zenbu-ref-size-icon-md: 1rem;
+  --zenbu-ref-size-icon-lg: 1.25rem;
+  --zenbu-ref-size-icon-xl: 1.5rem;
+  --zenbu-ref-size-control-xs: 2rem;
+  --zenbu-ref-size-control-sm: 2.25rem;
+  --zenbu-ref-size-control-md: 2.75rem;
+  --zenbu-ref-size-control-lg: 3.25rem;
+  --zenbu-ref-size-control-xl: 3.75rem;
+  --zenbu-ref-size-target-min: 2.75rem;
+  --zenbu-ref-z-base: 0;
+  --zenbu-ref-z-sticky: 100;
+  --zenbu-ref-z-dropdown: 300;
+  --zenbu-ref-z-popover: 400;
+  --zenbu-ref-z-notification: 600;
+  --zenbu-ref-z-modal: 800;
+  --zenbu-ref-z-critical: 1000;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/styles/semantic.css	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,245 @@
+:root {
+  --zenbu-font-editorial: var(--zenbu-ref-font-family-sans);
+  --zenbu-font-playful: var(--zenbu-ref-font-family-sans);
+  --zenbu-sys-font-family-ui: var(--zenbu-ref-font-family-sans);
+  --zenbu-sys-font-family-content: var(--zenbu-ref-font-family-sans);
+  --zenbu-sys-font-family-code: var(--zenbu-ref-font-family-mono);
+  --zenbu-sys-font-weight-regular: var(--zenbu-ref-font-weight-regular);
+  --zenbu-sys-font-weight-medium: var(--zenbu-ref-font-weight-medium);
+  --zenbu-sys-font-weight-strong: var(--zenbu-ref-font-weight-strong);
+  --zenbu-sys-font-weight-bold: var(--zenbu-ref-font-weight-bold);
+  --zenbu-sys-font-weight-display: var(--zenbu-ref-font-weight-bold);
+  --zenbu-sys-font-size-xs: var(--zenbu-ref-font-size-xs);
+  --zenbu-sys-font-size-sm: var(--zenbu-ref-font-size-sm);
+  --zenbu-sys-font-size-md: var(--zenbu-ref-font-size-md);
+  --zenbu-sys-font-size-lg: var(--zenbu-ref-font-size-lg);
+  --zenbu-sys-font-size-xl: var(--zenbu-ref-font-size-xl);
+  --zenbu-sys-font-size-2xl: var(--zenbu-ref-font-size-2xl);
+  --zenbu-sys-font-size-3xl: var(--zenbu-ref-font-size-3xl);
+  --zenbu-sys-line-height-xs: 1.25;
+  --zenbu-sys-line-height-sm: var(--zenbu-ref-line-height-ui);
+  --zenbu-sys-line-height-md: var(--zenbu-ref-line-height-body);
+  --zenbu-sys-line-height-lg: 1.5;
+  --zenbu-sys-line-height-xl: var(--zenbu-ref-line-height-ui);
+
+  --zenbu-sys-type-caption-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-caption-size: var(--zenbu-ref-font-size-xs);
+  --zenbu-sys-type-caption-weight: var(--zenbu-sys-font-weight-regular);
+  --zenbu-sys-type-caption-line-height: var(--zenbu-ref-line-height-ui);
+  --zenbu-sys-type-label-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-label-size: var(--zenbu-ref-font-size-sm);
+  --zenbu-sys-type-label-weight: var(--zenbu-sys-font-weight-medium);
+  --zenbu-sys-type-label-line-height: var(--zenbu-ref-line-height-ui);
+  --zenbu-sys-type-body-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-body-size: var(--zenbu-ref-font-size-md);
+  --zenbu-sys-type-body-weight: var(--zenbu-sys-font-weight-regular);
+  --zenbu-sys-type-body-line-height: var(--zenbu-ref-line-height-body);
+  --zenbu-sys-type-body-large-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-body-large-size: var(--zenbu-ref-font-size-lg);
+  --zenbu-sys-type-body-large-weight: var(--zenbu-sys-font-weight-regular);
+  --zenbu-sys-type-body-large-line-height: var(--zenbu-ref-line-height-body);
+  --zenbu-sys-type-subtitle-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-subtitle-size: var(--zenbu-ref-font-size-xl);
+  --zenbu-sys-type-subtitle-weight: var(--zenbu-sys-font-weight-strong);
+  --zenbu-sys-type-subtitle-line-height: var(--zenbu-ref-line-height-heading);
+  --zenbu-sys-type-title-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-title-size: var(--zenbu-ref-font-size-2xl);
+  --zenbu-sys-type-title-weight: var(--zenbu-sys-font-weight-strong);
+  --zenbu-sys-type-title-line-height: var(--zenbu-ref-line-height-heading);
+  --zenbu-sys-type-page-title-family: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-type-page-title-size:
+    clamp(var(--zenbu-ref-font-size-3xl), 1.5rem + 2cqi, var(--zenbu-ref-font-size-display));
+  --zenbu-sys-type-page-title-weight: var(--zenbu-sys-font-weight-strong);
+  --zenbu-sys-type-page-title-line-height: var(--zenbu-ref-line-height-tight);
+  --zenbu-sys-type-reading-family: var(--zenbu-sys-font-family-content);
+  --zenbu-sys-type-reading-size: var(--zenbu-ref-font-size-md);
+  --zenbu-sys-type-reading-weight: var(--zenbu-sys-font-weight-regular);
+  --zenbu-sys-type-reading-line-height: var(--zenbu-ref-line-height-reading);
+  --zenbu-sys-type-code-family: var(--zenbu-sys-font-family-code);
+  --zenbu-sys-type-code-size: var(--zenbu-ref-font-size-sm);
+  --zenbu-sys-type-code-weight: var(--zenbu-sys-font-weight-regular);
+  --zenbu-sys-type-code-line-height: var(--zenbu-ref-line-height-body);
+
+  --zenbu-sys-space-icon-label: var(--zenbu-ref-space-1);
+  --zenbu-sys-space-related: var(--zenbu-ref-space-2);
+  --zenbu-sys-space-control: var(--zenbu-ref-space-3);
+  --zenbu-sys-space-group: var(--zenbu-ref-space-4);
+  --zenbu-sys-space-container: var(--zenbu-ref-space-6);
+  --zenbu-sys-space-content: var(--zenbu-ref-space-8);
+  --zenbu-sys-space-section: var(--zenbu-ref-space-12);
+  --zenbu-sys-space-page: var(--zenbu-ref-space-16);
+  --zenbu-sys-padding-xs: var(--zenbu-ref-space-2);
+  --zenbu-sys-padding-sm: var(--zenbu-ref-space-3);
+  --zenbu-sys-padding-md: var(--zenbu-ref-space-4);
+  --zenbu-sys-padding-lg: var(--zenbu-ref-space-6);
+  --zenbu-sys-padding-xl: var(--zenbu-ref-space-8);
+
+  --zenbu-sys-radius-control-small: var(--zenbu-ref-radius-1);
+  --zenbu-sys-radius-control: var(--zenbu-ref-radius-2);
+  --zenbu-sys-radius-control-large: var(--zenbu-ref-radius-3);
+  --zenbu-sys-radius-container: var(--zenbu-ref-radius-3);
+  --zenbu-sys-radius-panel: var(--zenbu-ref-radius-4);
+  --zenbu-sys-radius-dialog: var(--zenbu-ref-radius-5);
+  --zenbu-sys-radius-pill: var(--zenbu-ref-radius-round);
+  --zenbu-sys-stroke-width: var(--zenbu-ref-stroke-1);
+  --zenbu-sys-stroke-width-emphasis: var(--zenbu-ref-stroke-2);
+  --zenbu-sys-focus-width: var(--zenbu-ref-stroke-3);
+  --zenbu-sys-focus-offset: var(--zenbu-ref-space-0-5);
+  --zenbu-sys-shadow-rest: none;
+  --zenbu-sys-shadow-subtle: var(--zenbu-ref-shadow-1);
+  --zenbu-sys-shadow-raised: var(--zenbu-ref-shadow-2);
+  --zenbu-sys-shadow-overlay: var(--zenbu-ref-shadow-3);
+  --zenbu-sys-shadow-dialog: var(--zenbu-ref-shadow-4);
+
+  --zenbu-sys-motion-duration-feedback: var(--zenbu-ref-duration-fast);
+  --zenbu-sys-motion-duration-state: var(--zenbu-ref-duration-normal);
+  --zenbu-sys-motion-duration-enter: var(--zenbu-ref-duration-normal);
+  --zenbu-sys-motion-duration-exit: var(--zenbu-ref-duration-fast);
+  --zenbu-sys-motion-duration-layout: var(--zenbu-ref-duration-slow);
+  --zenbu-sys-motion-ease-state: var(--zenbu-ref-ease-standard);
+  --zenbu-sys-motion-ease-enter: var(--zenbu-ref-ease-enter);
+  --zenbu-sys-motion-ease-exit: var(--zenbu-ref-ease-exit);
+  --zenbu-sys-motion-ease-layout: var(--zenbu-ref-ease-emphasized);
+  --zenbu-sys-opacity-disabled: var(--zenbu-ref-opacity-disabled);
+
+  --zenbu-sys-control-height-xs: var(--zenbu-ref-size-control-xs);
+  --zenbu-sys-control-height-sm: var(--zenbu-ref-size-control-sm);
+  --zenbu-sys-control-height-md: var(--zenbu-ref-size-control-md);
+  --zenbu-sys-control-height-lg: var(--zenbu-ref-size-control-lg);
+  --zenbu-sys-control-height-xl: var(--zenbu-ref-size-control-xl);
+  --zenbu-sys-control-padding-block-xs: var(--zenbu-ref-space-1);
+  --zenbu-sys-control-padding-block-sm: var(--zenbu-ref-space-1-5);
+  --zenbu-sys-control-padding-block-md: var(--zenbu-ref-space-2);
+  --zenbu-sys-control-padding-block-lg: var(--zenbu-ref-space-3);
+  --zenbu-sys-control-padding-block-xl: var(--zenbu-ref-space-4);
+  --zenbu-sys-control-padding-inline-xs: var(--zenbu-ref-space-2-5);
+  --zenbu-sys-control-padding-inline-sm: var(--zenbu-ref-space-3);
+  --zenbu-sys-control-padding-inline-md: var(--zenbu-ref-space-4);
+  --zenbu-sys-control-padding-inline-lg: var(--zenbu-ref-space-5);
+  --zenbu-sys-control-padding-inline-xl: var(--zenbu-ref-space-6);
+  --zenbu-sys-control-gap-xs: var(--zenbu-ref-space-1);
+  --zenbu-sys-control-gap-sm: var(--zenbu-ref-space-1-5);
+  --zenbu-sys-control-gap-md: var(--zenbu-ref-space-2);
+  --zenbu-sys-control-gap-lg: var(--zenbu-ref-space-3);
+  --zenbu-sys-control-gap-xl: var(--zenbu-ref-space-4);
+  --zenbu-sys-control-font-size-xs: var(--zenbu-ref-font-size-xs);
+  --zenbu-sys-control-font-size-sm: var(--zenbu-ref-font-size-sm);
+  --zenbu-sys-control-font-size-md: var(--zenbu-ref-font-size-md);
+  --zenbu-sys-control-font-size-lg: var(--zenbu-ref-font-size-lg);
+  --zenbu-sys-control-font-size-xl: var(--zenbu-ref-font-size-xl);
+  --zenbu-sys-control-line-height-xs: 1;
+  --zenbu-sys-control-line-height-sm: 1;
+  --zenbu-sys-control-line-height-md: 1;
+  --zenbu-sys-control-line-height-lg: 1;
+  --zenbu-sys-control-line-height-xl: 1;
+  --zenbu-sys-icon-size-xs: var(--zenbu-ref-size-icon-xs);
+  --zenbu-sys-icon-size-sm: var(--zenbu-ref-size-icon-sm);
+  --zenbu-sys-icon-size-md: var(--zenbu-ref-size-icon-md);
+  --zenbu-sys-icon-size-lg: var(--zenbu-ref-size-icon-lg);
+  --zenbu-sys-icon-size-xl: var(--zenbu-ref-size-icon-xl);
+  --zenbu-sys-size-target-min: var(--zenbu-ref-size-target-min);
+  --zenbu-sys-width-reading: 45rem;
+  --zenbu-sys-width-content: 64rem;
+  --zenbu-sys-width-page: 90rem;
+  --zenbu-sys-z-sticky: var(--zenbu-ref-z-sticky);
+  --zenbu-sys-z-dropdown: var(--zenbu-ref-z-dropdown);
+  --zenbu-sys-z-popover: var(--zenbu-ref-z-popover);
+  --zenbu-sys-z-notification: var(--zenbu-ref-z-notification);
+  --zenbu-sys-z-modal: var(--zenbu-ref-z-modal);
+
+  --zenbu-sys-color-surface-page: var(--zenbu-ref-color-neutral-100);
+  --zenbu-sys-color-surface-canvas: var(--zenbu-ref-color-neutral-100);
+  --zenbu-sys-color-surface-default: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-surface-subtle: var(--zenbu-ref-color-neutral-200);
+  --zenbu-sys-color-surface-raised: var(--zenbu-ref-color-white);
+  --zenbu-sys-color-surface-overlay: var(--zenbu-ref-color-white);
+  --zenbu-sys-color-surface-sunken: var(--zenbu-ref-color-neutral-200);
+  --zenbu-sys-color-scrim: var(--zenbu-ref-color-black-alpha-60);
+  --zenbu-sys-color-text-primary: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-text-secondary: var(--zenbu-ref-color-neutral-700);
+  --zenbu-sys-color-text-tertiary: var(--zenbu-ref-color-neutral-600);
+  --zenbu-sys-color-text-placeholder: var(--zenbu-ref-color-neutral-500);
+  --zenbu-sys-color-text-disabled: var(--zenbu-ref-color-neutral-400);
+  --zenbu-sys-color-text-inverse: var(--zenbu-ref-color-white);
+  --zenbu-sys-color-text-link: var(--zenbu-ref-color-brand-600);
+  --zenbu-sys-color-link-decoration: var(--zenbu-ref-color-link-decoration);
+  --zenbu-sys-color-icon-primary: var(--zenbu-ref-color-neutral-900);
+  --zenbu-sys-color-icon-secondary: var(--zenbu-ref-color-neutral-600);
+  --zenbu-sys-color-border-subtle: var(--zenbu-ref-color-neutral-300);
+  --zenbu-sys-color-border-default: var(--zenbu-ref-color-neutral-500);
+  --zenbu-sys-color-border-strong: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-action-primary-background: var(--zenbu-ref-color-accent);
+  --zenbu-sys-color-action-primary-background-hover: var(--zenbu-ref-color-accent-hover);
+  --zenbu-sys-color-action-primary-background-pressed: var(--zenbu-ref-color-accent-pressed);
+  --zenbu-sys-color-action-primary-foreground: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-action-primary-border: var(--zenbu-sys-color-border-strong);
+  --zenbu-sys-color-action-neutral-background: var(--zenbu-sys-color-surface-default);
+  --zenbu-sys-color-action-neutral-background-hover: var(--zenbu-sys-color-surface-subtle);
+  --zenbu-sys-color-action-neutral-background-pressed: var(--zenbu-sys-color-surface-sunken);
+  --zenbu-sys-color-action-neutral-foreground: var(--zenbu-sys-color-text-primary);
+  --zenbu-sys-color-action-neutral-border: var(--zenbu-sys-color-border-default);
+  --zenbu-sys-color-action-danger-background: var(--zenbu-ref-color-danger);
+  --zenbu-sys-color-action-danger-background-hover: var(--zenbu-ref-color-danger-700);
+  --zenbu-sys-color-action-danger-background-pressed: var(--zenbu-ref-color-danger-900);
+  --zenbu-sys-color-action-danger-foreground: var(--zenbu-ref-color-white);
+  --zenbu-sys-color-action-danger-border: var(--zenbu-ref-color-danger);
+  --zenbu-sys-color-focus-inner: var(--zenbu-sys-color-surface-default);
+  --zenbu-sys-color-focus-outer: var(--zenbu-ref-color-focus);
+  --zenbu-sys-color-selection-background: var(--zenbu-ref-color-warning-300);
+  --zenbu-sys-color-selection-foreground: var(--zenbu-sys-color-text-primary);
+  --zenbu-sys-color-info-background: var(--zenbu-ref-color-brand-100);
+  --zenbu-sys-color-info-foreground: var(--zenbu-ref-color-brand-700);
+  --zenbu-sys-color-info-border: var(--zenbu-ref-color-brand-400);
+  --zenbu-sys-color-success-background: var(--zenbu-ref-color-success-100);
+  --zenbu-sys-color-success-foreground: var(--zenbu-ref-color-success);
+  --zenbu-sys-color-success-border: var(--zenbu-ref-color-success-500);
+  --zenbu-sys-color-warning-background: var(--zenbu-ref-color-warning-100);
+  --zenbu-sys-color-warning-foreground: var(--zenbu-ref-color-warning);
+  --zenbu-sys-color-warning-border: var(--zenbu-ref-color-warning-500);
+  --zenbu-sys-color-danger-background: var(--zenbu-ref-color-danger-100);
+  --zenbu-sys-color-danger-foreground: var(--zenbu-ref-color-danger);
+  --zenbu-sys-color-danger-border: var(--zenbu-ref-color-danger-500);
+  --zenbu-sys-color-code-surface: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-code-text: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-gridline: var(--zenbu-ref-color-black-alpha-8);
+  --zenbu-sys-color-data-1: var(--zenbu-ref-color-brand-600);
+  --zenbu-sys-color-data-2: var(--zenbu-ref-color-warning-500);
+  --zenbu-sys-color-data-3: var(--zenbu-ref-color-success-600);
+  --zenbu-sys-color-data-4: var(--zenbu-ref-color-violet-500);
+  --zenbu-sys-color-data-5: var(--zenbu-ref-color-amber-600);
+}
+
+@media (forced-colors: active) {
+  :root {
+    --zenbu-sys-color-surface-page: Canvas;
+    --zenbu-sys-color-surface-canvas: Canvas;
+    --zenbu-sys-color-surface-default: Canvas;
+    --zenbu-sys-color-surface-subtle: Canvas;
+    --zenbu-sys-color-surface-raised: Canvas;
+    --zenbu-sys-color-surface-overlay: Canvas;
+    --zenbu-sys-color-text-primary: CanvasText;
+    --zenbu-sys-color-text-secondary: CanvasText;
+    --zenbu-sys-color-text-tertiary: GrayText;
+    --zenbu-sys-color-text-disabled: GrayText;
+    --zenbu-sys-color-text-link: LinkText;
+    --zenbu-sys-color-border-subtle: CanvasText;
+    --zenbu-sys-color-border-default: CanvasText;
+    --zenbu-sys-color-border-strong: CanvasText;
+    --zenbu-sys-color-focus-inner: Canvas;
+    --zenbu-sys-color-focus-outer: CanvasText;
+    --zenbu-sys-shadow-subtle: none;
+    --zenbu-sys-shadow-raised: none;
+    --zenbu-sys-shadow-overlay: none;
+    --zenbu-sys-shadow-dialog: none;
+  }
+}
+
+@media (prefers-reduced-motion: reduce) {
+  :root {
+    --zenbu-sys-motion-duration-feedback: 1ms;
+    --zenbu-sys-motion-duration-state: 1ms;
+    --zenbu-sys-motion-duration-enter: 1ms;
+    --zenbu-sys-motion-duration-exit: 1ms;
+    --zenbu-sys-motion-duration-layout: 1ms;
+  }
+}
--- a/design_system/src/styles/shadcn.css	Tue Aug 04 16:49:11 2026 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1744 +0,0 @@
-:where(
-  zen-accordion,
-  zen-alert-dialog,
-  zen-aspect-ratio,
-  zen-attachment,
-  zen-avatar,
-  zen-badge,
-  zen-breadcrumb,
-  zen-bubble,
-  zen-button-group,
-  zen-calendar,
-  zen-carousel,
-  zen-chart,
-  zen-checkbox,
-  zen-collapsible,
-  zen-combobox,
-  zen-command,
-  zen-context-menu,
-  zen-data-table,
-  zen-date-picker,
-  zen-dialog,
-  zen-direction,
-  zen-drawer,
-  zen-dropdown-menu,
-  zen-empty,
-  zen-form,
-  zen-hover-card,
-  zen-icon,
-  zen-input,
-  zen-input-group,
-  zen-input-otp,
-  zen-item,
-  zen-kbd,
-  zen-label,
-  zen-marker,
-  zen-menubar,
-  zen-message,
-  zen-message-scroller,
-  zen-native-select,
-  zen-navigation-menu,
-  zen-pagination,
-  zen-popover,
-  zen-progress,
-  zen-radio-group,
-  zen-resizable,
-  zen-scroll-area,
-  zen-select,
-  zen-separator,
-  zen-sheet,
-  zen-sidebar,
-  zen-skeleton,
-  zen-slider,
-  zen-spinner,
-  zen-switch,
-  zen-table,
-  zen-tabs,
-  zen-textarea,
-  zen-toggle,
-  zen-toggle-group,
-  zen-tooltip,
-  zen-typography
-) {
-  box-sizing: border-box;
-  color: var(--zen-color-text);
-  font-family: var(--zen-font-sans);
-}
-
-zen-icon {
-  display: inline-grid;
-  width: var(--zen-icon-size, 1em);
-  height: var(--zen-icon-size, 1em);
-  flex: 0 0 auto;
-  place-items: center;
-  color: inherit;
-  vertical-align: -0.125em;
-}
-
-zen-icon > svg {
-  display: block;
-  width: 100%;
-  height: 100%;
-}
-
-:where(
-  zen-alert-dialog,
-  zen-calendar,
-  zen-combobox,
-  zen-command,
-  zen-date-picker,
-  zen-dialog,
-  zen-drawer,
-  zen-form,
-  zen-input-otp,
-  zen-popover,
-  zen-progress,
-  zen-radio-group,
-  zen-resizable,
-  zen-select,
-  zen-sheet,
-  zen-sidebar,
-  zen-slider,
-  zen-tabs
-) {
-  display: block;
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) {
-  display: block;
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) details {
-  interpolate-size: allow-keywords;
-  border-block-end: 1px solid color-mix(
-    in srgb,
-    var(--zen-color-border) 28%,
-    transparent
-  );
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) summary {
-  display: flex;
-  align-items: center;
-  gap: var(--zen-space-3);
-  padding: var(--zen-space-3) 0;
-  font-weight: 800;
-  list-style: none;
-  cursor: pointer;
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) summary::marker,
-:where(
-  zen-accordion,
-  zen-collapsible
-) summary::-webkit-details-marker {
-  display: none;
-  content: "";
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) summary > [data-zen-disclosure-icon] {
-  margin-inline-start: auto;
-  transition: transform 220ms cubic-bezier(0.2, 0.8, 0.2, 1);
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) details[open] > summary > [data-zen-disclosure-icon] {
-  transform: rotate(180deg);
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) details::details-content {
-  block-size: 0;
-  overflow: clip;
-  opacity: 0;
-  transition:
-    block-size 220ms cubic-bezier(0.2, 0.8, 0.2, 1),
-    content-visibility 220ms allow-discrete,
-    opacity 180ms ease;
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) details[open]::details-content {
-  block-size: auto;
-  opacity: 1;
-}
-
-:where(
-  zen-accordion,
-  zen-collapsible
-) details > :not(summary) {
-  margin-block-start: 0;
-  padding-block-end: var(--zen-space-3);
-  color: var(--zen-color-text-muted);
-}
-
-:where(
-  zen-alert-dialog,
-  zen-dialog,
-  zen-drawer,
-  zen-sheet
-) > [data-zen-trigger],
-:where(
-  zen-dropdown-menu,
-  zen-menubar,
-  zen-navigation-menu,
-  zen-popover
-) [data-zen-trigger],
-zen-empty > button,
-zen-form button,
-zen-input-group button {
-  min-height: 2.5rem;
-  padding: var(--zen-space-2) var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  box-shadow: var(--zen-shadow-sm);
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-  font-weight: 800;
-  cursor: pointer;
-}
-
-:where(
-  zen-alert-dialog,
-  zen-dialog,
-  zen-drawer,
-  zen-sheet
-) dialog {
-  width: min(32rem, calc(100vi - 2rem));
-  padding: var(--zen-space-5);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  box-shadow: var(--zen-shadow-md);
-  background: var(--zen-color-surface-raised);
-  color: var(--zen-color-text);
-}
-
-:where(
-  zen-alert-dialog,
-  zen-dialog,
-  zen-drawer,
-  zen-sheet
-) dialog[open],
-:where(
-  zen-combobox,
-  zen-command,
-  zen-context-menu,
-  zen-dropdown-menu,
-  zen-hover-card,
-  zen-menubar,
-  zen-navigation-menu,
-  zen-popover,
-  zen-tooltip
-) :where(
-  [data-zen-content],
-  [role="listbox"],
-  [role="menu"]
-):not([hidden]) {
-  animation: zen-surface-open 160ms ease-out;
-}
-
-:where(
-  zen-alert-dialog,
-  zen-dialog,
-  zen-drawer,
-  zen-sheet
-) dialog::backdrop {
-  background: var(--zen-color-surface-overlay);
-  backdrop-filter: blur(3px);
-}
-
-:where(
-  zen-alert-dialog,
-  zen-dialog,
-  zen-drawer,
-  zen-sheet
-) dialog > h3 {
-  margin-block-start: 0;
-}
-
-:where(
-  zen-alert-dialog,
-  zen-dialog,
-  zen-drawer,
-  zen-sheet
-) dialog button {
-  min-height: 2.35rem;
-  margin-inline-end: var(--zen-space-2);
-  padding-inline: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-sm);
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-  font-weight: 700;
-  cursor: pointer;
-}
-
-zen-alert-dialog dialog button[value="confirm"] {
-  background: var(--zen-color-danger);
-  color: var(--zen-color-on-danger);
-}
-
-:where(zen-sheet, zen-drawer) dialog {
-  position: fixed;
-  max-width: none;
-  max-height: none;
-  margin: 0;
-}
-
-:where(zen-sheet, zen-drawer)[placement="right"] dialog {
-  inset: 0 0 0 auto;
-  width: min(28rem, 92vi);
-  height: 100vb;
-  border-radius: var(--zen-radius-lg) 0 0 var(--zen-radius-lg);
-}
-
-:where(zen-sheet, zen-drawer)[placement="left"] dialog {
-  inset: 0 auto 0 0;
-  width: min(28rem, 92vi);
-  height: 100vb;
-  border-radius: 0 var(--zen-radius-lg) var(--zen-radius-lg) 0;
-}
-
-:where(zen-sheet, zen-drawer)[placement="bottom"] dialog,
-zen-drawer:not([placement]) dialog {
-  inset: auto 0 0;
-  width: 100vi;
-  border-radius: var(--zen-radius-lg) var(--zen-radius-lg) 0 0;
-}
-
-zen-aspect-ratio {
-  display: block;
-  aspect-ratio: var(--zen-aspect-ratio, 16 / 9);
-  overflow: hidden;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-zen-aspect-ratio > * {
-  width: 100%;
-  height: 100%;
-}
-
-.demo-media {
-  display: grid;
-  place-items: center;
-  background: var(--zen-color-surface-muted);
-  color: var(--zen-color-text);
-  font-size: var(--zen-font-size-lg);
-  font-weight: 900;
-}
-
-zen-attachment {
-  display: grid;
-  grid-template-columns: 3rem minmax(0, 1fr) auto;
-  align-items: center;
-  gap: var(--zen-space-3);
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-}
-
-zen-attachment > span {
-  display: grid;
-  width: 3rem;
-  height: 3rem;
-  place-items: center;
-  border-radius: var(--zen-radius-sm);
-  background: var(--zen-color-info);
-  color: var(--zen-color-on-info);
-  font-size: var(--zen-font-size-xs);
-  font-weight: 900;
-}
-
-zen-attachment > div,
-zen-item > div {
-  display: grid;
-}
-
-:where(zen-attachment, zen-item) small {
-  color: var(--zen-color-text-muted);
-}
-
-:where(zen-attachment, zen-item) > button {
-  border: 0;
-  background: transparent;
-  color: inherit;
-  cursor: pointer;
-}
-
-zen-avatar {
-  display: inline-grid;
-  width: var(--zen-avatar-size, 2.75rem);
-  height: var(--zen-avatar-size, 2.75rem);
-  overflow: hidden;
-  place-items: center;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 50%;
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-  font-weight: 900;
-}
-
-zen-avatar > img {
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-}
-
-zen-badge {
-  display: inline-flex;
-  align-items: center;
-  min-height: 1.75rem;
-  padding: 0 var(--zen-space-2);
-  border: 1px solid var(--zen-color-border);
-  border-radius: 999px;
-  background: var(--zen-color-surface);
-  font-size: var(--zen-font-size-xs);
-  font-weight: 850;
-}
-
-zen-badge[tone="success"] {
-  background: var(--zen-color-success);
-  color: var(--zen-color-on-success);
-}
-
-zen-badge[tone="danger"] {
-  background: var(--zen-color-danger);
-  color: var(--zen-color-on-danger);
-}
-
-:where(zen-breadcrumb, zen-pagination) nav {
-  display: flex;
-  align-items: center;
-  gap: var(--zen-space-2);
-}
-
-zen-breadcrumb ol {
-  display: flex;
-  flex-wrap: wrap;
-  align-items: center;
-  gap: var(--zen-space-2);
-  margin: 0;
-  padding: 0;
-  list-style: none;
-}
-
-zen-breadcrumb li:not(:last-child)::after {
-  margin-inline-start: var(--zen-space-2);
-  color: var(--zen-color-text-muted);
-  content: "/";
-}
-
-:where(zen-breadcrumb, zen-pagination) a {
-  color: var(--zen-color-info);
-  text-underline-offset: 0.2em;
-}
-
-zen-bubble {
-  display: block;
-  width: fit-content;
-  max-width: min(42rem, 88%);
-  padding: var(--zen-space-3) var(--zen-space-4);
-  border-radius: var(--zen-radius-lg) var(--zen-radius-lg)
-    var(--zen-radius-lg) var(--zen-radius-sm);
-  background: var(--zen-color-surface-raised);
-  box-shadow: var(--zen-shadow-sm);
-}
-
-zen-bubble[align="end"] {
-  margin-inline-start: auto;
-  border-radius: var(--zen-radius-lg) var(--zen-radius-lg)
-    var(--zen-radius-sm) var(--zen-radius-lg);
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-zen-bubble > :first-child {
-  margin-block-start: 0;
-}
-
-zen-bubble > :last-child {
-  margin-block-end: 0;
-}
-
-zen-button-group {
-  display: inline-flex;
-}
-
-zen-button-group > :where(button, a) {
-  min-height: 2.5rem;
-  padding-inline: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 0;
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-  font-weight: 750;
-  cursor: pointer;
-}
-
-zen-button-group > :first-child {
-  border-radius: var(--zen-radius-md) 0 0 var(--zen-radius-md);
-}
-
-zen-button-group > :last-child {
-  border-radius: 0 var(--zen-radius-md) var(--zen-radius-md) 0;
-}
-
-zen-button-group > :not(:first-child) {
-  margin-inline-start: calc(-1 * var(--zen-border-width));
-}
-
-:where(
-  zen-calendar,
-  zen-date-picker,
-  zen-slider
-) {
-  display: grid;
-  gap: var(--zen-space-2);
-  max-width: 22rem;
-}
-
-:where(
-  zen-calendar,
-  zen-date-picker,
-  zen-input,
-  zen-input-group,
-  zen-input-otp,
-  zen-native-select,
-  zen-select,
-  zen-slider,
-  zen-textarea
-) :where(input, select, textarea) {
-  appearance: none;
-  min-height: 2.75rem;
-  box-sizing: border-box;
-  padding: var(--zen-space-2) var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-  font: inherit;
-}
-
-:where(
-  zen-input,
-  zen-input-group,
-  zen-input-otp,
-  zen-native-select,
-  zen-select,
-  zen-textarea,
-  zen-calendar,
-  zen-date-picker
-) :where(input, select, textarea),
-zen-field > :where(input, select, textarea) {
-  appearance: none;
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-}
-
-:where(zen-native-select, zen-select) {
-  position: relative;
-}
-
-:where(zen-native-select, zen-select) select {
-  width: 100%;
-  padding-inline-end: 2.75rem;
-  cursor: pointer;
-}
-
-:where(zen-native-select, zen-select) > [data-zen-select-icon] {
-  position: absolute;
-  inset-inline-end: var(--zen-space-3);
-  inset-block-end: 0.9rem;
-  pointer-events: none;
-}
-
-:where(
-  zen-calendar,
-  zen-date-picker,
-  zen-input,
-  zen-native-select,
-  zen-select,
-  zen-textarea
-) {
-  display: grid;
-  gap: var(--zen-space-2);
-}
-
-zen-textarea textarea {
-  width: 100%;
-  min-height: 8rem;
-  resize: vertical;
-}
-
-:where(zen-calendar, zen-date-picker) > input[data-zen-calendar-input] {
-  position: absolute;
-  width: 1px;
-  height: 1px;
-  overflow: hidden;
-  clip-path: inset(50%);
-  pointer-events: none;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-generated="calendar"] {
-  display: grid;
-  gap: var(--zen-space-2);
-}
-
-zen-date-picker [data-zen-generated="calendar"] {
-  position: relative;
-}
-
-:where(zen-calendar, zen-date-picker) :where(
-  [data-zen-date-trigger],
-  [data-zen-calendar-previous],
-  [data-zen-calendar-next],
-  [data-zen-calendar-day]
-) {
-  appearance: none;
-  border: 0;
-  background: transparent;
-  color: var(--zen-color-text);
-  font: inherit;
-  cursor: pointer;
-}
-
-zen-date-picker [data-zen-date-trigger] {
-  display: inline-flex;
-  min-height: 2.75rem;
-  align-items: center;
-  gap: var(--zen-space-2);
-  justify-content: flex-start;
-  padding: var(--zen-space-2) var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  box-shadow: var(--zen-shadow-sm);
-  background: var(--zen-color-surface);
-}
-
-zen-date-picker[data-invalid] [data-zen-date-trigger],
-zen-calendar[data-invalid] [data-zen-calendar-view] {
-  border-color: var(--zen-color-danger);
-}
-
-zen-date-picker [data-zen-calendar-panel] {
-  position: absolute;
-  z-index: 40;
-  inset-block-start: calc(100% + var(--zen-space-2));
-  inset-inline-start: 0;
-  width: min(21rem, calc(100vi - 2rem));
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  box-shadow: var(--zen-shadow-md);
-  background: var(--zen-color-surface-raised);
-  transform-origin: top left;
-  animation: zen-calendar-open 160ms ease-out;
-}
-
-zen-date-picker [data-zen-calendar-panel][hidden] {
-  display: none;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-view] {
-  display: grid;
-  gap: var(--zen-space-2);
-  padding: var(--zen-space-3);
-  border: 1px solid var(--zen-color-border-muted);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-zen-date-picker [data-zen-calendar-view] {
-  padding: 0;
-  border: 0;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-view] > header {
-  display: grid;
-  grid-template-columns: 2.5rem minmax(0, 1fr) 2.5rem;
-  align-items: center;
-  gap: var(--zen-space-2);
-  text-align: center;
-}
-
-:where(zen-calendar, zen-date-picker) :where(
-  [data-zen-calendar-previous],
-  [data-zen-calendar-next]
-) {
-  display: grid;
-  width: 2.5rem;
-  height: 2.5rem;
-  place-items: center;
-  border: 1px solid var(--zen-color-border-muted);
-  border-radius: 50%;
-}
-
-:where(zen-calendar, zen-date-picker) :where(
-  [data-zen-calendar-previous],
-  [data-zen-calendar-next]
-):hover {
-  background: var(--zen-color-accent-muted);
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-weekdays],
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-grid] > [role="row"] {
-  display: grid;
-  grid-template-columns: repeat(7, minmax(2rem, 1fr));
-  gap: var(--zen-space-1);
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-weekdays] > span {
-  padding-block: var(--zen-space-1);
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-xs);
-  font-weight: 800;
-  text-align: center;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-grid] {
-  display: grid;
-  gap: var(--zen-space-1);
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-day] {
-  aspect-ratio: 1;
-  min-width: 2rem;
-  border-radius: 50%;
-  font-size: var(--zen-font-size-sm);
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-day]:hover {
-  background: var(--zen-color-accent-muted);
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-day][data-outside] {
-  color: var(--zen-color-text-subtle);
-  opacity: 0.55;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-day][data-today] {
-  outline: 1px solid var(--zen-color-info);
-  outline-offset: -2px;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-day][aria-selected="true"] {
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-  font-weight: 900;
-}
-
-:where(zen-calendar, zen-date-picker) [data-zen-calendar-day]:disabled {
-  color: var(--zen-color-disabled);
-  cursor: not-allowed;
-}
-
-@keyframes zen-calendar-open {
-  from {
-    opacity: 0;
-    transform: translateY(calc(-1 * var(--zen-space-1))) scale(0.98);
-  }
-
-  @keyframes zen-surface-open {
-    from {
-      opacity: 0;
-      transform: translateY(calc(-1 * var(--zen-space-1))) scale(0.98);
-    }
-  }
-}
-
-zen-input-group {
-  display: flex;
-  align-items: stretch;
-  width: min(100%, 36rem);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-}
-
-zen-input-group > :where(span, button) {
-  display: inline-flex;
-  align-items: center;
-  padding-inline: var(--zen-space-3);
-}
-
-zen-input-group input {
-  min-width: 0;
-  flex: 1;
-  border: 0;
-  border-radius: 0;
-}
-
-zen-input-group button {
-  min-height: auto;
-  border-width: 0 0 0 var(--zen-border-width);
-  border-radius: 0 var(--zen-radius-sm) var(--zen-radius-sm) 0;
-  box-shadow: none;
-}
-
-zen-carousel {
-  position: relative;
-  display: grid;
-  grid-template-columns: auto minmax(0, 1fr) auto;
-  align-items: center;
-  gap: var(--zen-space-2);
-}
-
-zen-carousel [data-zen-viewport] {
-  display: flex;
-  grid-column: 1 / -1;
-  gap: var(--zen-space-3);
-  overflow: auto;
-  scroll-snap-type: inline mandatory;
-  scrollbar-width: none;
-}
-
-zen-carousel [data-zen-viewport] > * {
-  min-width: min(22rem, 82vi);
-  min-height: 9rem;
-  padding: var(--zen-space-5);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface-raised);
-  scroll-snap-align: start;
-}
-
-zen-carousel :where([data-zen-prev], [data-zen-next]) {
-  width: 2.5rem;
-  height: 2.5rem;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 50%;
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-  cursor: pointer;
-}
-
-zen-carousel [data-zen-prev] {
-  grid-column: 1;
-}
-
-zen-carousel [data-zen-next] {
-  grid-column: 3;
-}
-
-zen-chart {
-  display: block;
-  min-height: 15rem;
-  padding: var(--zen-space-4);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-zen-chart [data-zen-chart-plot] {
-  display: flex;
-  height: 12rem;
-  align-items: end;
-  justify-content: space-around;
-  gap: var(--zen-space-3);
-  border-block-end: 1px solid var(--zen-color-border);
-}
-
-zen-chart [data-zen-chart-plot] > span {
-  position: relative;
-  width: min(3rem, 15%);
-  height: var(--zen-chart-value);
-  min-height: 1rem;
-  border-radius: var(--zen-radius-sm) var(--zen-radius-sm) 0 0;
-  background: var(--zen-color-data-1);
-}
-
-zen-chart [data-zen-chart-plot] > span:nth-child(2) {
-  background: var(--zen-color-data-2);
-}
-
-zen-chart [data-zen-chart-plot] > span:nth-child(3) {
-  background: var(--zen-color-data-3);
-}
-
-zen-chart [data-zen-chart-plot] > span:nth-child(4) {
-  background: var(--zen-color-data-4);
-}
-
-zen-chart [data-zen-chart-plot] > span:nth-child(5) {
-  background: var(--zen-color-data-5);
-}
-
-zen-chart [data-zen-chart-plot] > span::after {
-  position: absolute;
-  inset-block-start: 100%;
-  inset-inline-start: 50%;
-  padding-block-start: var(--zen-space-1);
-  color: var(--zen-color-text-muted);
-  content: attr(data-label);
-  font-size: var(--zen-font-size-xs);
-  transform: translateX(-50%);
-}
-
-:where(zen-checkbox, zen-switch) label,
-zen-radio-group label {
-  display: flex;
-  align-items: center;
-  gap: var(--zen-space-2);
-  width: fit-content;
-  cursor: pointer;
-}
-
-:where(zen-checkbox, zen-radio-group) input {
-  appearance: none;
-  display: inline-grid;
-  width: 1.2rem;
-  height: 1.2rem;
-  flex: 0 0 auto;
-  place-content: center;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  background: var(--zen-color-surface);
-  cursor: pointer;
-}
-
-zen-checkbox input {
-  border-radius: var(--zen-radius-sm);
-}
-
-zen-checkbox input::before {
-  width: 0.55rem;
-  height: 0.3rem;
-  border-block-end: 2px solid var(--zen-color-on-accent);
-  border-inline-start: 2px solid var(--zen-color-on-accent);
-  content: "";
-  opacity: 0;
-  transform: translateY(-0.08rem) rotate(-45deg);
-}
-
-zen-checkbox input:checked {
-  background: var(--zen-color-accent);
-}
-
-zen-checkbox input:checked::before {
-  opacity: 1;
-}
-
-zen-radio-group input {
-  border-radius: 50%;
-}
-
-zen-radio-group input::before {
-  width: 0.55rem;
-  height: 0.55rem;
-  border-radius: 50%;
-  background: var(--zen-color-info);
-  content: "";
-  opacity: 0;
-}
-
-zen-radio-group input:checked::before {
-  opacity: 1;
-}
-
-zen-radio-group fieldset {
-  display: grid;
-  gap: var(--zen-space-2);
-  padding: var(--zen-space-4);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-}
-
-zen-switch input {
-  appearance: none;
-  width: 2.75rem;
-  height: 1.5rem;
-  margin: 0;
-  padding: 2px;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 999px;
-  background: var(--zen-color-surface);
-  cursor: pointer;
-  transition: background var(--zen-motion-fast) ease;
-}
-
-zen-switch input::before {
-  display: block;
-  width: 1rem;
-  height: 1rem;
-  border-radius: 50%;
-  background: var(--zen-color-border);
-  content: "";
-  transition: transform var(--zen-motion-fast) ease;
-}
-
-zen-switch input:checked {
-  background: var(--zen-color-success);
-}
-
-zen-switch input:checked::before {
-  background: var(--zen-color-on-success);
-  transform: translateX(1.2rem);
-}
-
-:where(zen-combobox, zen-command) {
-  position: relative;
-  display: grid;
-  width: min(100%, 28rem);
-  gap: var(--zen-space-2);
-}
-
-:where(zen-combobox, zen-command) > input {
-  min-height: 2.75rem;
-  padding: var(--zen-space-2) var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-  color: var(--zen-color-text);
-}
-
-:where(
-  zen-combobox,
-  zen-command,
-  zen-context-menu,
-  zen-dropdown-menu,
-  zen-menubar,
-  zen-navigation-menu
-) :where([role="listbox"], [role="menu"]) {
-  z-index: 20;
-  display: grid;
-  min-width: 12rem;
-  padding: var(--zen-space-1);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  box-shadow: var(--zen-shadow-md);
-  background: var(--zen-color-surface-raised);
-}
-
-:where(
-  zen-combobox,
-  zen-command,
-  zen-context-menu,
-  zen-dropdown-menu,
-  zen-menubar,
-  zen-navigation-menu
-) :where([role="listbox"], [role="menu"])[hidden] {
-  display: none;
-}
-
-:where(
-  zen-combobox,
-  zen-command,
-  zen-context-menu,
-  zen-dropdown-menu,
-  zen-menubar,
-  zen-navigation-menu
-) :where([role="option"], [role="menuitem"]) {
-  display: block;
-  width: 100%;
-  padding: var(--zen-space-2) var(--zen-space-3);
-  border: 0;
-  border-radius: var(--zen-radius-sm);
-  background: transparent;
-  color: var(--zen-color-text);
-  text-align: start;
-  text-decoration: none;
-  cursor: pointer;
-}
-
-:where(
-  zen-combobox,
-  zen-command,
-  zen-context-menu,
-  zen-dropdown-menu,
-  zen-menubar,
-  zen-navigation-menu
-) :where([role="option"], [role="menuitem"]):is(
-  :hover,
-  :focus,
-  [aria-selected="true"]
-) {
-  outline: none;
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-:where(
-  zen-context-menu,
-  zen-dropdown-menu,
-  zen-navigation-menu
-) {
-  position: relative;
-  display: inline-block;
-}
-
-zen-context-menu > [data-zen-trigger] {
-  min-height: 8rem;
-  padding: var(--zen-space-5);
-  border: 2px dashed var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-:where(
-  zen-dropdown-menu,
-  zen-navigation-menu
-) > [role="menu"],
-zen-navigation-menu nav > [role="menu"] {
-  position: absolute;
-  inset-block-start: calc(100% + var(--zen-space-2));
-  inset-inline-start: 0;
-}
-
-zen-context-menu > [role="menu"] {
-  position: fixed;
-}
-
-zen-menubar {
-  position: relative;
-  display: flex;
-  width: fit-content;
-  padding: var(--zen-space-1);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-}
-
-zen-menubar > [data-zen-trigger] {
-  border: 0;
-  box-shadow: none;
-  background: transparent;
-  color: var(--zen-color-text);
-}
-
-zen-menubar > [role="menu"] {
-  position: absolute;
-  inset-block-start: calc(100% + var(--zen-space-1));
-}
-
-zen-data-table,
-zen-table {
-  display: block;
-  max-width: 100%;
-  overflow: auto;
-}
-
-:where(zen-data-table, zen-table) table {
-  width: 100%;
-  border-collapse: collapse;
-  background: var(--zen-color-surface);
-}
-
-:where(zen-data-table, zen-table) :where(th, td) {
-  padding: var(--zen-space-3);
-  border-block-end: 1px solid color-mix(
-    in srgb,
-    var(--zen-color-border) 30%,
-    transparent
-  );
-  text-align: start;
-}
-
-:where(zen-data-table, zen-table) th {
-  font-size: var(--zen-font-size-sm);
-}
-
-zen-data-table [data-zen-sort] {
-  padding: 0;
-  border: 0;
-  background: transparent;
-  color: inherit;
-  font-weight: 850;
-  cursor: pointer;
-}
-
-zen-direction {
-  display: contents;
-}
-
-zen-empty {
-  display: grid;
-  justify-items: center;
-  gap: var(--zen-space-2);
-  padding: var(--zen-space-7) var(--zen-space-5);
-  border: var(--zen-border-width) dashed var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-  text-align: center;
-}
-
-zen-empty > p {
-  max-width: 34rem;
-  margin: 0;
-  color: var(--zen-color-text-muted);
-}
-
-zen-form form {
-  display: grid;
-  max-width: 34rem;
-  gap: var(--zen-space-4);
-}
-
-zen-form[data-invalid] form {
-  padding-inline-start: var(--zen-space-3);
-  border-inline-start: 0.35rem solid var(--zen-color-danger);
-}
-
-:where(zen-hover-card, zen-tooltip, zen-popover) {
-  position: relative;
-  display: inline-block;
-}
-
-:where(zen-hover-card, zen-tooltip, zen-popover) [data-zen-content] {
-  position: absolute;
-  z-index: 30;
-  inset-block-start: calc(100% + var(--zen-space-2));
-  inset-inline-start: 0;
-  width: max-content;
-  max-width: min(22rem, calc(100vi - 2rem));
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  box-shadow: var(--zen-shadow-md);
-  background: var(--zen-color-surface-raised);
-  color: var(--zen-color-text);
-}
-
-:where(zen-hover-card, zen-tooltip, zen-popover) [data-zen-content][hidden] {
-  display: none;
-}
-
-zen-tooltip [data-zen-content] {
-  padding: var(--zen-space-1) var(--zen-space-2);
-  background: var(--zen-color-border);
-  color: var(--zen-color-surface);
-  font-size: var(--zen-font-size-xs);
-}
-
-zen-input-otp [data-zen-otp-slots] {
-  display: flex;
-  gap: var(--zen-space-1);
-}
-
-zen-input-otp [data-zen-otp-slots] > span {
-  display: grid;
-  width: 2.5rem;
-  height: 2.75rem;
-  place-items: center;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-sm);
-  background: var(--zen-color-surface);
-  font-weight: 850;
-}
-
-zen-item {
-  display: grid;
-  grid-template-columns: auto minmax(0, 1fr) auto;
-  align-items: center;
-  gap: var(--zen-space-3);
-  padding: var(--zen-space-3);
-  border-block-end: 1px solid color-mix(
-    in srgb,
-    var(--zen-color-border) 28%,
-    transparent
-  );
-}
-
-zen-kbd {
-  display: inline-flex;
-  align-items: center;
-  gap: var(--zen-space-1);
-}
-
-zen-kbd kbd {
-  min-width: 1.75rem;
-  padding: 0.1rem var(--zen-space-1);
-  border: 1px solid var(--zen-color-border);
-  border-block-end-width: 3px;
-  border-radius: var(--zen-radius-sm);
-  background: var(--zen-color-surface);
-  font: 700 var(--zen-font-size-xs)/1.5 var(--zen-font-mono);
-  text-align: center;
-}
-
-zen-label {
-  display: block;
-  margin-block-end: var(--zen-space-2);
-  font-weight: 800;
-}
-
-zen-marker {
-  display: flex;
-  align-items: center;
-  gap: var(--zen-space-2);
-  color: var(--zen-color-text-muted);
-  font-size: var(--zen-font-size-xs);
-  text-transform: uppercase;
-}
-
-zen-marker::before,
-zen-marker::after {
-  height: 1px;
-  flex: 1;
-  background: color-mix(
-    in srgb,
-    var(--zen-color-border) 32%,
-    transparent
-  );
-  content: "";
-}
-
-zen-message {
-  display: grid;
-  grid-template-columns: auto minmax(0, 1fr);
-  align-items: start;
-  gap: var(--zen-space-3);
-}
-
-zen-message > div {
-  display: grid;
-  gap: var(--zen-space-1);
-}
-
-zen-message-scroller {
-  position: relative;
-  display: block;
-}
-
-zen-message-scroller [data-zen-viewport] {
-  max-height: 12rem;
-  overflow: auto;
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-}
-
-zen-message-scroller [data-zen-scroll-end] {
-  position: absolute;
-  inset-inline-end: var(--zen-space-3);
-  inset-block-end: var(--zen-space-3);
-}
-
-zen-navigation-menu nav {
-  display: flex;
-  align-items: center;
-  gap: var(--zen-space-3);
-}
-
-zen-pagination nav {
-  flex-wrap: wrap;
-}
-
-zen-pagination a {
-  display: inline-grid;
-  min-width: 2.35rem;
-  min-height: 2.35rem;
-  place-items: center;
-  padding-inline: var(--zen-space-2);
-  border: 1px solid transparent;
-  border-radius: var(--zen-radius-sm);
-  text-decoration: none;
-}
-
-zen-pagination a[aria-current] {
-  border-color: var(--zen-color-border);
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-zen-progress {
-  display: grid;
-  gap: var(--zen-space-2);
-}
-
-zen-progress progress {
-  appearance: none;
-  width: 100%;
-  height: 0.75rem;
-  overflow: hidden;
-  border: 0;
-  border-radius: 999px;
-  accent-color: var(--zen-color-success);
-  background: var(--zen-color-surface);
-}
-
-zen-progress progress::-webkit-progress-bar {
-  background: var(--zen-color-surface-muted);
-}
-
-zen-progress progress::-webkit-progress-value {
-  background: var(--zen-color-success);
-}
-
-zen-progress progress::-moz-progress-bar {
-  background: var(--zen-color-success);
-}
-
-zen-resizable {
-  display: flex;
-  min-height: 12rem;
-  overflow: hidden;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-}
-
-zen-resizable [data-zen-panel] {
-  min-width: 0;
-  flex: 1 1 50%;
-  padding: var(--zen-space-4);
-  background: var(--zen-color-surface);
-}
-
-zen-resizable [data-zen-handle] {
-  width: 0.65rem;
-  flex: 0 0 0.65rem;
-  border-inline: 1px solid var(--zen-color-border);
-  background: var(--zen-color-accent);
-  cursor: col-resize;
-}
-
-zen-scroll-area {
-  display: block;
-  max-height: 10rem;
-  overflow: auto;
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-  scrollbar-color: var(--zen-color-accent) transparent;
-}
-
-zen-separator {
-  display: block;
-}
-
-zen-separator hr {
-  margin-block: var(--zen-space-4);
-  border: 0;
-  border-block-start: 1px solid var(--zen-color-border);
-}
-
-zen-separator[orientation="vertical"] {
-  display: inline-block;
-  width: 1px;
-  min-height: 1.5rem;
-  background: var(--zen-color-border);
-}
-
-zen-sidebar {
-  display: grid;
-  grid-template-columns: minmax(12rem, 17rem) minmax(0, 1fr);
-  gap: var(--zen-space-3);
-}
-
-zen-sidebar > [data-zen-sidebar-trigger] {
-  grid-column: 1 / -1;
-  justify-self: start;
-}
-
-zen-sidebar [data-zen-sidebar-panel] {
-  padding: var(--zen-space-3);
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: var(--zen-radius-lg);
-  background: var(--zen-color-surface);
-}
-
-zen-sidebar [data-zen-sidebar-panel] nav {
-  display: grid;
-  gap: var(--zen-space-1);
-}
-
-zen-sidebar [data-zen-sidebar-panel] a {
-  padding: var(--zen-space-2);
-  border-radius: var(--zen-radius-sm);
-  color: inherit;
-  text-decoration: none;
-}
-
-zen-sidebar [data-zen-sidebar-panel] a:hover {
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-zen-skeleton {
-  display: block;
-  width: var(--zen-skeleton-width, 100%);
-  height: 1rem;
-  border-radius: var(--zen-radius-sm);
-  background:
-    linear-gradient(
-      100deg,
-      color-mix(in srgb, var(--zen-color-text-muted) 18%, transparent) 20%,
-      color-mix(in srgb, var(--zen-color-text-muted) 8%, transparent) 38%,
-      color-mix(in srgb, var(--zen-color-text-muted) 18%, transparent) 56%
-    );
-  background-size: 200% 100%;
-  animation: zen-skeleton-shimmer 1.4s linear infinite;
-}
-
-zen-skeleton[shape="circle"] {
-  width: 3rem;
-  height: 3rem;
-  border-radius: 50%;
-}
-
-zen-slider input {
-  appearance: none;
-  width: 100%;
-  height: 0.5rem;
-  padding-inline: 0;
-  border: 0;
-  border-radius: 999px;
-  background: var(--zen-color-surface-sunken);
-  cursor: pointer;
-}
-
-zen-slider input::-webkit-slider-thumb {
-  appearance: none;
-  width: 1.35rem;
-  height: 1.35rem;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 50%;
-  box-shadow: var(--zen-shadow-sm);
-  background: var(--zen-color-accent);
-}
-
-zen-slider input::-moz-range-thumb {
-  width: 1.35rem;
-  height: 1.35rem;
-  border: var(--zen-border-width) solid var(--zen-color-border);
-  border-radius: 50%;
-  box-shadow: var(--zen-shadow-sm);
-  background: var(--zen-color-accent);
-}
-
-zen-spinner {
-  display: inline-block;
-  width: 1.35rem;
-  height: 1.35rem;
-  border: 3px solid color-mix(
-    in srgb,
-    var(--zen-color-text-muted) 28%,
-    transparent
-  );
-  border-inline-end-color: var(--zen-color-info);
-  border-radius: 50%;
-  animation: zen-shadcn-spin 650ms linear infinite;
-}
-
-zen-tabs [role="tablist"] {
-  display: flex;
-  width: fit-content;
-  gap: var(--zen-space-1);
-  padding: var(--zen-space-1);
-  border: 1px solid var(--zen-color-border);
-  border-radius: var(--zen-radius-md);
-  background: var(--zen-color-surface);
-}
-
-zen-tabs [role="tab"] {
-  min-height: 2.25rem;
-  padding-inline: var(--zen-space-3);
-  border: 0;
-  border-radius: var(--zen-radius-sm);
-  background: transparent;
-  color: var(--zen-color-text);
-  font-weight: 750;
-  cursor: pointer;
-}
-
-zen-tabs [role="tab"][aria-selected="true"] {
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-zen-tabs [role="tabpanel"] {
-  padding-block: var(--zen-space-4);
-}
-
-zen-tabs [role="tabpanel"][hidden] {
-  display: none;
-}
-
-:where(zen-toggle, zen-toggle-group) {
-  display: inline-flex;
-}
-
-:where(zen-toggle, zen-toggle-group) > button {
-  min-height: 2.5rem;
-  padding-inline: var(--zen-space-3);
-  border: 1px solid transparent;
-  border-radius: var(--zen-radius-sm);
-  background: transparent;
-  color: var(--zen-color-text);
-  font-weight: 750;
-  cursor: pointer;
-}
-
-:where(zen-toggle, zen-toggle-group) > button[aria-pressed="true"] {
-  border-color: var(--zen-color-border);
-  background: var(--zen-color-accent);
-  color: var(--zen-color-on-accent);
-}
-
-zen-typography {
-  display: block;
-  max-width: 65ch;
-  line-height: var(--zen-line-height);
-}
-
-zen-typography > :where(h1, h2, h3) {
-  line-height: 1.15;
-  text-wrap: balance;
-}
-
-zen-typography blockquote {
-  margin-inline: 0;
-  padding-inline-start: var(--zen-space-4);
-  border-inline-start: 0.35rem solid var(--zen-color-accent);
-  color: var(--zen-color-text-muted);
-  font-style: italic;
-}
-
-:where(
-  button,
-  summary,
-  [tabindex]
-):focus-visible {
-  outline: 3px solid var(--zen-color-focus);
-  outline-offset: 3px;
-}
-
-:where(
-  zen-calendar,
-  zen-checkbox,
-  zen-combobox,
-  zen-command,
-  zen-date-picker,
-  zen-field,
-  zen-form,
-  zen-input,
-  zen-input-group,
-  zen-input-otp,
-  zen-native-select,
-  zen-radio-group,
-  zen-select,
-  zen-slider,
-  zen-switch,
-  zen-textarea
-) :where(input, select, textarea):focus-visible {
-  outline: none;
-}
-
-@keyframes zen-shadcn-spin {
-  to { transform: rotate(1turn); }
-}
-
-@keyframes zen-skeleton-shimmer {
-  to { background-position-x: -200%; }
-}
-
-@media (max-width: 640px) {
-  zen-sidebar {
-    display: block;
-  }
-
-  zen-sidebar > [data-zen-sidebar-trigger] {
-    margin-block-end: var(--zen-space-2);
-  }
-
-  :where(zen-calendar, zen-date-picker) {
-    width: 100%;
-    max-width: 100%;
-  }
-
-  zen-date-picker [data-zen-calendar-panel] {
-    position: fixed;
-    inset: auto var(--zen-space-3) var(--zen-space-3);
-    width: auto;
-    max-height: calc(100vb - 2 * var(--zen-space-3));
-    overflow: auto;
-    transform-origin: bottom center;
-  }
-}
-
-@media (forced-colors: active) {
-  :where(
-    zen-aspect-ratio,
-    zen-attachment,
-    zen-avatar,
-    zen-badge,
-    zen-empty,
-    zen-resizable,
-    zen-scroll-area
-  ) {
-    border: 1px solid CanvasText;
-  }
-}
-
-@media (prefers-reduced-motion: reduce) {
-  zen-skeleton,
-  zen-spinner {
-    animation: none;
-  }
-
-  zen-switch input,
-  zen-switch input::before,
-  :where(
-    zen-accordion,
-    zen-collapsible
-  ) details::details-content,
-  :where(
-    zen-accordion,
-    zen-collapsible
-  ) summary > [data-zen-disclosure-icon] {
-    transition: none;
-  }
-
-  zen-date-picker [data-zen-calendar-panel] {
-    animation: none;
-  }
-
-  :where(
-    zen-alert-dialog,
-    zen-dialog,
-    zen-drawer,
-    zen-sheet
-  ) dialog[open],
-  :where(
-    zen-combobox,
-    zen-command,
-    zen-context-menu,
-    zen-dropdown-menu,
-    zen-hover-card,
-    zen-menubar,
-    zen-navigation-menu,
-    zen-popover,
-    zen-tooltip
-  ) :where(
-    [data-zen-content],
-    [role="listbox"],
-    [role="menu"]
-  ):not([hidden]) {
-    animation: none;
-  }
-}
--- a/design_system/src/styles/themes.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/styles/themes.css	Wed Aug 05 05:25:40 2026 -0700
@@ -18,12 +18,6 @@
   --zen-color-warning: var(--zen-color-orange-600);
   --zen-color-danger: var(--zen-color-red-600);
   --zen-color-focus: var(--zen-color-violet-600);
-  --zen-font-sans: var(
-    --zen-font-editorial,
-    ui-rounded,
-    system-ui,
-    sans-serif
-  );
 }
 
 :root[data-zen-theme="ink"] {
@@ -52,12 +46,6 @@
   --zen-color-focus: var(--zen-color-violet-300);
   --zen-color-on-accent: var(--zen-color-neutral-950);
   --zen-color-text-inverse: var(--zen-color-neutral-950);
-  --zen-font-sans: var(
-    --zen-font-editorial,
-    ui-rounded,
-    system-ui,
-    sans-serif
-  );
 }
 
 :root[data-zen-theme="playful"] {
@@ -83,13 +71,156 @@
   --zen-color-on-warning: var(--zen-color-neutral-50);
   --zen-color-focus: var(--zen-color-violet-500);
   --zen-color-on-accent: var(--zen-color-blue-950);
-  --zen-font-sans: var(
-    --zen-font-playful,
-    ui-rounded,
-    system-ui,
-    sans-serif
-  );
   --zen-radius-sm: 0.65rem;
   --zen-radius-md: 1rem;
   --zen-radius-lg: 1.5rem;
 }
+
+:root[data-zen-theme="paper"] {
+  --zenbu-sys-font-family-ui: var(
+    --zenbu-font-editorial,
+    var(--zenbu-ref-font-family-sans)
+  );
+  --zenbu-sys-font-family-content: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-color-surface-page: var(--zenbu-ref-color-neutral-100);
+  --zenbu-sys-color-surface-canvas: var(--zenbu-ref-color-neutral-100);
+  --zenbu-sys-color-surface-default: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-surface-subtle: var(--zenbu-ref-color-neutral-200);
+  --zenbu-sys-color-surface-raised: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-surface-sunken: var(--zenbu-ref-color-neutral-200);
+  --zenbu-sys-color-text-primary: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-text-secondary: var(--zenbu-ref-color-neutral-700);
+  --zenbu-sys-color-text-tertiary: var(--zenbu-ref-color-neutral-500);
+  --zenbu-sys-color-border-subtle: var(--zenbu-ref-color-neutral-300);
+  --zenbu-sys-color-border-default: var(--zenbu-ref-color-neutral-500);
+  --zenbu-sys-color-border-strong: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-action-primary-background: var(--zenbu-ref-color-amber-300);
+  --zenbu-sys-color-action-primary-background-hover: var(--zenbu-ref-color-amber-100);
+  --zenbu-sys-color-action-primary-background-pressed: var(--zenbu-ref-color-warning-600);
+  --zenbu-sys-color-action-primary-foreground: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-text-link: var(--zenbu-ref-color-brand-600);
+  --zenbu-sys-color-focus-outer: var(--zenbu-ref-color-focus);
+}
+
+:root[data-zen-theme="ink"],
+:root[data-zen-theme="dark"] {
+  --zenbu-sys-font-family-ui: var(
+    --zenbu-font-editorial,
+    var(--zenbu-ref-font-family-sans)
+  );
+  --zenbu-sys-font-family-content: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-color-surface-page: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-surface-canvas: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-surface-default: var(--zenbu-ref-color-neutral-900);
+  --zenbu-sys-color-surface-subtle: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-surface-raised: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-surface-sunken: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-text-primary: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-text-secondary: var(--zenbu-ref-color-neutral-300);
+  --zenbu-sys-color-text-tertiary: var(--zenbu-ref-color-neutral-400);
+  --zenbu-sys-color-text-inverse: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-text-link: var(--zenbu-ref-color-brand-300);
+  --zenbu-sys-color-border-subtle: var(--zenbu-ref-color-neutral-700);
+  --zenbu-sys-color-border-default: var(--zenbu-ref-color-neutral-600);
+  --zenbu-sys-color-border-strong: var(--zenbu-ref-color-neutral-200);
+  --zenbu-sys-color-action-primary-background: var(--zenbu-ref-color-amber-300);
+  --zenbu-sys-color-action-primary-background-hover: var(--zenbu-ref-color-amber-100);
+  --zenbu-sys-color-action-primary-background-pressed: var(--zenbu-ref-color-warning-600);
+  --zenbu-sys-color-action-primary-foreground: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-action-danger-background: var(--zenbu-ref-color-danger-300);
+  --zenbu-sys-color-action-danger-background-hover: var(--zenbu-ref-color-danger-500);
+  --zenbu-sys-color-action-danger-background-pressed: var(--zenbu-ref-color-danger-600);
+  --zenbu-sys-color-action-danger-foreground: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-focus-inner: var(--zenbu-ref-color-neutral-950);
+  --zenbu-sys-color-focus-outer: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-info-background: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-info-foreground: var(--zenbu-ref-color-brand-300);
+  --zenbu-sys-color-success-background: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-success-foreground: var(--zenbu-ref-color-success-300);
+  --zenbu-sys-color-warning-background: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-warning-foreground: var(--zenbu-ref-color-warning-300);
+  --zenbu-sys-color-danger-background: var(--zenbu-ref-color-neutral-800);
+  --zenbu-sys-color-danger-foreground: var(--zenbu-ref-color-danger-300);
+}
+
+:root[data-zen-theme="playful"] {
+  --zenbu-sys-font-family-ui: var(
+    --zenbu-font-playful,
+    var(--zenbu-ref-font-family-sans)
+  );
+  --zenbu-sys-font-family-content: var(--zenbu-sys-font-family-ui);
+  --zenbu-sys-color-surface-page: var(--zenbu-ref-color-rose-100);
+  --zenbu-sys-color-surface-canvas: var(--zenbu-ref-color-rose-100);
+  --zenbu-sys-color-surface-default: var(--zenbu-ref-color-amber-50);
+  --zenbu-sys-color-surface-subtle: var(--zenbu-ref-color-orange-100);
+  --zenbu-sys-color-surface-raised: var(--zenbu-ref-color-neutral-50);
+  --zenbu-sys-color-surface-sunken: var(--zenbu-ref-color-violet-100);
+  --zenbu-sys-color-text-primary: var(--zenbu-ref-color-blue-900);
+  --zenbu-sys-color-text-secondary: var(--zenbu-ref-color-violet-700);
+  --zenbu-sys-color-text-tertiary: var(--zenbu-ref-color-blue-600);
+  --zenbu-sys-color-border-subtle: var(--zenbu-ref-color-rose-300);
+  --zenbu-sys-color-border-default: var(--zenbu-ref-color-violet-500);
+  --zenbu-sys-color-border-strong: var(--zenbu-ref-color-violet-700);
+  --zenbu-sys-color-action-primary-background: var(--zenbu-ref-color-orange-300);
+  --zenbu-sys-color-action-primary-background-hover: var(--zenbu-ref-color-amber-300);
+  --zenbu-sys-color-action-primary-background-pressed: var(--zenbu-ref-color-warning-600);
+  --zenbu-sys-color-action-primary-foreground: var(--zenbu-ref-color-blue-950);
+  --zenbu-sys-color-text-link: var(--zenbu-ref-color-blue-600);
+  --zenbu-sys-color-focus-outer: var(--zenbu-ref-color-violet-500);
+  --zenbu-sys-radius-control-small: var(--zenbu-ref-radius-2);
+  --zenbu-sys-radius-control: var(--zenbu-ref-radius-4);
+  --zenbu-sys-radius-container: var(--zenbu-ref-radius-5);
+}
+
+@media (prefers-color-scheme: dark) {
+  :root:not([data-zen-theme]) {
+    --zenbu-sys-color-surface-page: var(--zenbu-ref-color-neutral-950);
+    --zenbu-sys-color-surface-canvas: var(--zenbu-ref-color-neutral-950);
+    --zenbu-sys-color-surface-default: var(--zenbu-ref-color-neutral-900);
+    --zenbu-sys-color-surface-subtle: var(--zenbu-ref-color-neutral-800);
+    --zenbu-sys-color-surface-raised: var(--zenbu-ref-color-neutral-800);
+    --zenbu-sys-color-surface-sunken: var(--zenbu-ref-color-neutral-950);
+    --zenbu-sys-color-text-primary: var(--zenbu-ref-color-neutral-50);
+    --zenbu-sys-color-text-secondary: var(--zenbu-ref-color-neutral-300);
+    --zenbu-sys-color-text-tertiary: var(--zenbu-ref-color-neutral-400);
+    --zenbu-sys-color-border-subtle: var(--zenbu-ref-color-neutral-700);
+    --zenbu-sys-color-border-default: var(--zenbu-ref-color-neutral-600);
+    --zenbu-sys-color-border-strong: var(--zenbu-ref-color-neutral-200);
+    --zenbu-sys-color-text-link: var(--zenbu-ref-color-brand-300);
+    --zenbu-sys-color-focus-inner: var(--zenbu-ref-color-neutral-950);
+    --zenbu-sys-color-focus-outer: var(--zenbu-ref-color-neutral-50);
+  }
+}
+
+@media (forced-colors: active) {
+  :root,
+  :root[data-zen-theme],
+  :root:not([data-zen-theme]) {
+    --zenbu-sys-color-surface-page: Canvas;
+    --zenbu-sys-color-surface-canvas: Canvas;
+    --zenbu-sys-color-surface-default: Canvas;
+    --zenbu-sys-color-surface-subtle: Canvas;
+    --zenbu-sys-color-surface-raised: Canvas;
+    --zenbu-sys-color-surface-overlay: Canvas;
+    --zenbu-sys-color-surface-sunken: Canvas;
+    --zenbu-sys-color-text-primary: CanvasText;
+    --zenbu-sys-color-text-secondary: CanvasText;
+    --zenbu-sys-color-text-tertiary: GrayText;
+    --zenbu-sys-color-text-disabled: GrayText;
+    --zenbu-sys-color-text-link: LinkText;
+    --zenbu-sys-color-border-subtle: CanvasText;
+    --zenbu-sys-color-border-default: CanvasText;
+    --zenbu-sys-color-border-strong: CanvasText;
+    --zenbu-sys-color-action-primary-background: Highlight;
+    --zenbu-sys-color-action-primary-background-hover: Highlight;
+    --zenbu-sys-color-action-primary-background-pressed: Highlight;
+    --zenbu-sys-color-action-primary-foreground: HighlightText;
+    --zenbu-sys-color-action-primary-border: Highlight;
+    --zenbu-sys-color-focus-inner: Canvas;
+    --zenbu-sys-color-focus-outer: CanvasText;
+    --zenbu-sys-shadow-subtle: none;
+    --zenbu-sys-shadow-raised: none;
+    --zenbu-sys-shadow-overlay: none;
+    --zenbu-sys-shadow-dialog: none;
+  }
+}
--- a/design_system/src/styles/tokens.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/src/styles/tokens.css	Wed Aug 05 05:25:40 2026 -0700
@@ -1,3 +1,7 @@
+@import url("./reference.css");
+@import url("./semantic.css");
+@import url("./density.css");
+
 :root {
   color-scheme: light;
 
@@ -170,6 +174,7 @@
   --zen-color-danger-muted: var(--zen-color-red-100);
   --zen-color-disabled: var(--zen-color-neutral-300);
   --zen-color-selection: var(--zen-color-amber-200);
+  --zen-color-link-decoration: var(--zen-color-clay);
   --zen-color-code-surface: #111318;
   --zen-color-code-text: #f4f4f5;
   --zen-color-gridline: rgba(127, 127, 127, 0.08);
@@ -185,22 +190,71 @@
   --zen-color-data-9: var(--zen-color-clay);
   --zen-color-data-10: var(--zen-color-blue-400);
 
-  --zen-font-sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
-  --zen-font-mono: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
-  --zen-font-size-xs: 0.75rem;
-  --zen-font-size-sm: 0.875rem;
-  --zen-font-size-md: 1rem;
-  --zen-font-size-lg: 1.25rem;
-  --zen-font-size-xl: clamp(1.75rem, 4vw, 3rem);
-  --zen-line-height: 1.55;
+  /* Compatibility aliases. New code consumes --zenbu-sys-* tokens. */
+  --zen-font-sans: var(--zenbu-sys-font-family-ui);
+  --zen-font-mono: var(--zenbu-sys-font-family-code);
+  --zen-font-size-xs: var(--zenbu-sys-font-size-xs);
+  --zen-font-size-sm: var(--zenbu-sys-font-size-sm);
+  --zen-font-size-md: var(--zenbu-sys-font-size-md);
+  --zen-font-size-lg: var(--zenbu-sys-font-size-lg);
+  --zen-font-size-xl: var(--zenbu-sys-font-size-xl);
+  --zen-font-size-2xl: var(--zenbu-sys-font-size-2xl);
+  --zen-font-size-3xl: var(--zenbu-sys-type-page-title-size);
+  --zen-line-height-xs: var(--zenbu-sys-line-height-xs);
+  --zen-line-height-sm: var(--zenbu-sys-line-height-sm);
+  --zen-line-height-md: var(--zenbu-sys-line-height-md);
+  --zen-line-height-lg: var(--zenbu-sys-line-height-lg);
+  --zen-line-height-xl: var(--zenbu-sys-line-height-xl);
+  --zen-line-height: var(--zenbu-sys-type-body-line-height);
+  --zen-font-weight-regular: var(--zenbu-sys-font-weight-regular);
+  --zen-font-weight-medium: var(--zenbu-sys-font-weight-medium);
+  --zen-font-weight-strong: var(--zenbu-sys-font-weight-strong);
+  --zen-font-weight-display: var(--zenbu-sys-font-weight-display);
+
+  --zen-space-1: var(--zenbu-ref-space-1);
+  --zen-space-2: var(--zenbu-ref-space-2);
+  --zen-space-3: var(--zenbu-ref-space-3);
+  --zen-space-4: var(--zenbu-ref-space-4);
+  --zen-space-5: var(--zenbu-ref-space-6);
+  --zen-space-6: var(--zenbu-ref-space-8);
+  --zen-space-7: var(--zenbu-ref-space-12);
 
-  --zen-space-1: 0.25rem;
-  --zen-space-2: 0.5rem;
-  --zen-space-3: 0.75rem;
-  --zen-space-4: 1rem;
-  --zen-space-5: 1.5rem;
-  --zen-space-6: 2rem;
-  --zen-space-7: 3rem;
+  --zen-padding-xs: var(--zenbu-sys-padding-xs);
+  --zen-padding-sm: var(--zenbu-sys-padding-sm);
+  --zen-padding-md: var(--zenbu-sys-padding-md);
+  --zen-padding-lg: var(--zenbu-sys-padding-lg);
+  --zen-padding-xl: var(--zenbu-sys-padding-xl);
+
+  --zen-control-height-xs: var(--zenbu-sys-control-height-xs);
+  --zen-control-height-sm: var(--zenbu-sys-control-height-sm);
+  --zen-control-height-md: var(--zenbu-sys-control-height-md);
+  --zen-control-height-lg: var(--zenbu-sys-control-height-lg);
+  --zen-control-height-xl: var(--zenbu-sys-control-height-xl);
+  --zen-control-padding-block-xs: var(--zenbu-sys-control-padding-block-xs);
+  --zen-control-padding-block-sm: var(--zenbu-sys-control-padding-block-sm);
+  --zen-control-padding-block-md: var(--zenbu-sys-control-padding-block-md);
+  --zen-control-padding-block-lg: var(--zenbu-sys-control-padding-block-lg);
+  --zen-control-padding-block-xl: var(--zenbu-sys-control-padding-block-xl);
+  --zen-control-padding-inline-xs: var(--zenbu-sys-control-padding-inline-xs);
+  --zen-control-padding-inline-sm: var(--zenbu-sys-control-padding-inline-sm);
+  --zen-control-padding-inline-md: var(--zenbu-sys-control-padding-inline-md);
+  --zen-control-padding-inline-lg: var(--zenbu-sys-control-padding-inline-lg);
+  --zen-control-padding-inline-xl: var(--zenbu-sys-control-padding-inline-xl);
+  --zen-control-gap-xs: var(--zenbu-sys-control-gap-xs);
+  --zen-control-gap-sm: var(--zenbu-sys-control-gap-sm);
+  --zen-control-gap-md: var(--zenbu-sys-control-gap-md);
+  --zen-control-gap-lg: var(--zenbu-sys-control-gap-lg);
+  --zen-control-gap-xl: var(--zenbu-sys-control-gap-xl);
+  --zen-control-line-height-xs: var(--zenbu-sys-control-line-height-xs);
+  --zen-control-line-height-sm: var(--zenbu-sys-control-line-height-sm);
+  --zen-control-line-height-md: var(--zenbu-sys-control-line-height-md);
+  --zen-control-line-height-lg: var(--zenbu-sys-control-line-height-lg);
+  --zen-control-line-height-xl: var(--zenbu-sys-control-line-height-xl);
+  --zen-icon-size-xs: var(--zenbu-sys-icon-size-xs);
+  --zen-icon-size-sm: var(--zenbu-sys-icon-size-sm);
+  --zen-icon-size-md: var(--zenbu-sys-icon-size-md);
+  --zen-icon-size-lg: var(--zenbu-sys-icon-size-lg);
+  --zen-icon-size-xl: var(--zenbu-sys-icon-size-xl);
 
   --zen-radius-sm: 0.35rem;
   --zen-radius-md: 0.7rem;
--- a/design_system/test/BUILD	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/test/BUILD	Wed Aug 05 05:25:40 2026 -0700
@@ -8,8 +8,8 @@
 )
 
 js_test(
-  name = "storybook_test",
-  entry_point = "storybook_test.js",
+  name = "catalog_test",
+  entry_point = "catalog_test.js",
   data = [
     "//design_system:design_system_server",
     "//hg-web/e2e:node_modules/playwright-core",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/test/catalog_test.js	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,2100 @@
+const assert = require('node:assert/strict');
+const http = require('node:http');
+const net = require('node:net');
+const path = require('node:path');
+const { spawn } = require('node:child_process');
+
+const RUNFILES = process.env.JS_BINARY__RUNFILES;
+const WORKSPACE = process.env.JS_BINARY__WORKSPACE;
+const runfilesWorkspace = path.join(RUNFILES, WORKSPACE);
+const playwrightPath = path.join(
+  runfilesWorkspace,
+  'hg-web/e2e/node_modules/playwright-core',
+);
+const { chromium } = require(playwrightPath);
+
+function findFreePort() {
+  return new Promise((resolve, reject) => {
+    const server = net.createServer();
+    server.once('error', reject);
+    server.listen(0, '127.0.0.1', () => {
+      const address = server.address();
+      server.close(error => {
+        if (error) reject(error);
+        else resolve(String(address.port));
+      });
+    });
+  });
+}
+
+async function stopProcess(child) {
+  if (!child || child.exitCode !== null) return;
+  child.kill('SIGTERM');
+  await new Promise(resolve => {
+    const timer = setTimeout(() => {
+      if (child.exitCode === null) child.kill('SIGKILL');
+    }, 3000);
+    child.once('exit', () => {
+      clearTimeout(timer);
+      resolve();
+    });
+  });
+}
+
+async function waitForServer(server, baseUrl, logs) {
+  const deadline = Date.now() + 15000;
+  while (Date.now() < deadline) {
+    if (server.exitCode !== null) {
+      throw new Error(`Server exited with ${server.exitCode}\n${logs.join('')}`);
+    }
+    try {
+      const response = await fetch(baseUrl);
+      if (response.ok) return;
+    } catch {
+      // Keep waiting.
+    }
+    await new Promise(resolve => setTimeout(resolve, 100));
+  }
+  throw new Error(`Server startup timed out\n${logs.join('')}`);
+}
+
+function requestRawPath(port, requestPath) {
+  return new Promise((resolve, reject) => {
+    const request = http.request({
+      host: '127.0.0.1',
+      port,
+      method: 'GET',
+      path: requestPath,
+      agent: false,
+    }, response => {
+      response.resume();
+      response.on('end', () => resolve(response.statusCode));
+    });
+    request.on('error', reject);
+    request.end();
+  });
+}
+
+(async () => {
+  assert.ok(RUNFILES);
+  assert.ok(WORKSPACE);
+  const serverBinary = path.join(
+    runfilesWorkspace,
+    'design_system/design_system_server',
+  );
+  const chromiumPath = path.resolve(process.env.CHROMIUM_PATH);
+  const port = await findFreePort();
+  const baseUrl = `http://127.0.0.1:${port}`;
+  const logs = [];
+  let server;
+  let browser;
+
+  try {
+    const invalidServer = spawn(serverBinary, [], {
+      cwd: runfilesWorkspace,
+      env: {
+        ...process.env,
+        DESIGN_SYSTEM_PORT: 'not-a-port',
+      },
+      stdio: ['ignore', 'pipe', 'pipe'],
+    });
+    const invalidExit = await new Promise(resolve => {
+      invalidServer.once('exit', (code, signal) => resolve({ code, signal }));
+    });
+    assert.equal(invalidExit.code, 1);
+    assert.equal(invalidExit.signal, null);
+
+    server = spawn(serverBinary, [], {
+      cwd: runfilesWorkspace,
+      env: {
+        ...process.env,
+        DESIGN_SYSTEM_PORT: port,
+      },
+      stdio: ['ignore', 'pipe', 'pipe'],
+    });
+    server.stdout.on('data', chunk => logs.push(chunk.toString()));
+    server.stderr.on('data', chunk => logs.push(chunk.toString()));
+    await waitForServer(server, baseUrl, logs);
+    assert.equal(await requestRawPath(port, '/../../MODULE.bazel'), 400);
+
+    for (const route of [
+      '/',
+      '/tokens',
+      '/icons',
+      '/components',
+      '/components/button',
+      '/components/card',
+      '/components/alert',
+      '/components/field',
+      '/components/notifications',
+      '/components/stack',
+    ]) {
+      const response = await fetch(`${baseUrl}${route}`);
+      assert.equal(response.status, 200, route);
+      assert.match(
+        response.headers.get('content-type') || '',
+        /^text\/html/,
+      );
+    }
+    for (const asset of [
+      '/styles/tokens.css',
+      '/styles/reference.css',
+      '/styles/semantic.css',
+      '/styles/density.css',
+      '/styles/themes.css',
+      '/styles/components.css',
+      '/styles/elements.css',
+      '/components/index.js',
+      '/components/icon.js',
+      '/catalog.js',
+      '/catalog.js',
+    ]) {
+      const response = await fetch(`${baseUrl}${asset}`);
+      assert.equal(response.status, 200, asset);
+      assert.ok((await response.text()).length > 100, asset);
+    }
+
+    browser = await chromium.launch({
+      executablePath: chromiumPath,
+      headless: true,
+      args: ['--no-sandbox'],
+    });
+    const context = await browser.newContext({ colorScheme: 'light' });
+    const page = await context.newPage();
+    const errors = [];
+    const devtools = await context.newCDPSession(page);
+    await devtools.send('Runtime.enable');
+    devtools.on('Runtime.exceptionThrown', event => {
+      const exception = event.exceptionDetails;
+      errors.push(
+        `${exception.text}: ${exception.exception?.description || ''} ` +
+        `${exception.url || ''}:${exception.lineNumber + 1}`,
+      );
+    });
+    page.on('pageerror', error => errors.push(error.stack || error.message));
+    page.on('console', message => {
+      if (message.type() === 'error') {
+        const location = message.location();
+        errors.push(
+          `${message.text()} ${location.url || ''}:${location.lineNumber + 1}`,
+        );
+      }
+    });
+    page.on('response', response => {
+      if (response.status() >= 400) {
+        errors.push(`${response.status()} ${response.url()}`);
+      }
+    });
+
+    await page.goto(`${baseUrl}/components/button`, {
+      waitUntil: 'networkidle',
+    });
+    try {
+      await page.waitForFunction(
+        () => customElements.get('zen-button') &&
+          customElements.get('zen-story'),
+        undefined,
+        { timeout: 5000 },
+      );
+    } catch (error) {
+      throw new Error(`${error.message}\n${errors.join('\n')}`);
+    }
+    const catalogState = await page.evaluate(async () => {
+      const links = [
+        ...document.querySelectorAll(
+          '.catalog-nav[aria-label="Components"] a',
+        ),
+      ];
+      const elements = [...new Set(
+        links.map(link => link.dataset.zenElement).filter(Boolean),
+      )];
+      const statuses = await Promise.all(
+        links.map(async link => (await fetch(link.href)).status),
+      );
+      return {
+        cards: document.querySelectorAll('.component-grid > a').length,
+        elements,
+        links: links.length,
+        missing: elements.filter(name => !customElements.get(name)),
+        routes: links.map(link => new URL(link.href).pathname),
+        statuses,
+      };
+    });
+    assert.equal(catalogState.cards, 70);
+    assert.equal(catalogState.links, 70);
+    assert.equal(catalogState.elements.length, 69);
+    assert.deepEqual(catalogState.missing, []);
+    assert.deepEqual(
+      [...new Set(catalogState.statuses)],
+      [200],
+    );
+    const primitiveOwnership = await page.evaluate(() => {
+      const buttonOwners = [
+        'zen-alert',
+        'zen-attachment',
+        'zen-button',
+        'zen-button-group',
+        'zen-calendar',
+        'zen-carousel',
+        'zen-combobox',
+        'zen-command',
+        'zen-context-menu',
+        'zen-data-table',
+        'zen-date-picker',
+        'zen-dropdown-menu',
+        'zen-input-group',
+        'zen-menubar',
+        'zen-message-scroller',
+        'zen-navigation-menu',
+        'zen-notifications',
+        'zen-sidebar',
+        'zen-tabs',
+        'zen-toggle',
+        'zen-toggle-group',
+      ].join(',');
+      const controlOwners = [
+        'zen-calendar',
+        'zen-checkbox',
+        'zen-combobox',
+        'zen-command',
+        'zen-date-picker',
+        'zen-field',
+        'zen-form',
+        'zen-input',
+        'zen-input-group',
+        'zen-input-otp',
+        'zen-native-select',
+        'zen-radio-group',
+        'zen-select',
+        'zen-slider',
+        'zen-switch',
+        'zen-textarea',
+      ].join(',');
+      return {
+        buttons: [...document.querySelectorAll('button')].filter(button =>
+          !button.closest(buttonOwners) &&
+          !button.matches('zen-story > header > button')
+        ).map(button => button.outerHTML),
+        controls: [
+          ...document.querySelectorAll('input, select, textarea'),
+        ].filter(control => !control.closest(controlOwners))
+          .map(control => control.outerHTML),
+      };
+    });
+    assert.deepEqual(primitiveOwnership, {
+      buttons: [],
+      controls: [],
+    });
+    const brokenCatalogPages = await page.evaluate(routes => {
+      const failures = [];
+      const buttonOwners = [
+        'zen-alert',
+        'zen-attachment',
+        'zen-button',
+        'zen-button-group',
+        'zen-calendar',
+        'zen-carousel',
+        'zen-combobox',
+        'zen-command',
+        'zen-context-menu',
+        'zen-data-table',
+        'zen-date-picker',
+        'zen-dropdown-menu',
+        'zen-input-group',
+        'zen-menubar',
+        'zen-message-scroller',
+        'zen-navigation-menu',
+        'zen-notifications',
+        'zen-sidebar',
+        'zen-tabs',
+        'zen-toggle',
+        'zen-toggle-group',
+      ].join(',');
+      for (const route of ['/', '/tokens', '/icons', '/components', ...routes]) {
+        history.replaceState({}, '', route);
+        window.dispatchEvent(new PopStateEvent('popstate'));
+        const visible = [
+          ...document.querySelectorAll('[data-catalog-page]:not([hidden])'),
+        ];
+        const expected = route === '/' || route === '/components'
+          ? 'overview'
+          : route.slice(route.lastIndexOf('/') + 1);
+        if (visible.length !== 1 ||
+            visible[0].dataset.catalogPage !== expected ||
+            !visible[0].querySelector('h1')?.textContent.trim()) {
+          failures.push(route);
+          continue;
+        }
+        if (route.startsWith('/components/')) {
+          const story = visible[0].querySelector('zen-story');
+          const canvas = story?.querySelector('.story-canvas');
+          const source = story?.querySelector('pre code');
+          if (!story || !canvas?.children.length ||
+              !source?.textContent.trim()) {
+            failures.push(`${route}:empty-story`);
+          }
+          const unownedButtons = [...canvas?.querySelectorAll('button') || []]
+            .filter(button => !button.closest(buttonOwners));
+          if (unownedButtons.length) {
+            failures.push(`${route}:unowned-button`);
+          }
+        }
+      }
+      history.replaceState({}, '', '/components/button');
+      window.dispatchEvent(new PopStateEvent('popstate'));
+      return failures;
+    }, catalogState.routes);
+    assert.deepEqual(brokenCatalogPages, []);
+    await page.keyboard.press('/');
+    assert.equal(
+      await page.locator('#componentSearch').evaluate(
+        input => document.activeElement === input,
+      ),
+      true,
+    );
+    await page.locator('#componentSearch').fill('date');
+    assert.equal(
+      await page.locator(
+        '.catalog-nav[aria-label="Components"] a:not([hidden])',
+      ).count(),
+      2,
+    );
+    assert.equal(
+      await page.locator('.component-grid > a:not([hidden])').count(),
+      2,
+    );
+    assert.match(
+      await page.locator('#componentSearchStatus').textContent(),
+      /^2 components found$/,
+    );
+    await page.locator('#componentSearch').press('Escape');
+    assert.equal(await page.locator('#componentSearch').inputValue(), '');
+    assert.equal(
+      await page.locator(
+        '.catalog-nav[aria-label="Components"] a:not([hidden])',
+      ).count(),
+      70,
+    );
+    await page.locator('#componentSearch').fill('stack');
+    assert.equal(
+      await page.locator(
+        '.catalog-nav[aria-label="Components"] a[href="/components/stack"]',
+      ).getAttribute('hidden'),
+      null,
+    );
+    assert.equal(
+      await page.locator(
+        '.component-grid > a[href="/components/stack"]',
+      ).getAttribute('hidden'),
+      null,
+    );
+    await page.locator('#componentSearch').press('Escape');
+    assert.equal(
+      await page.locator('[data-catalog-page="button"]').isVisible(),
+      true,
+    );
+    assert.equal(
+      await page.locator('.catalog-sidebar a[href="/components/button"]').getAttribute('aria-current'),
+      'page',
+    );
+    assert.match(
+      await page.locator('zen-story pre').first().textContent(),
+      /<zen-button>/,
+    );
+    const plainPresentation = await page.evaluate(() => {
+      const style = document.createElement('style');
+      style.textContent = `
+        .application-button {
+          padding: 7px;
+          border: 3px solid currentColor;
+          box-shadow: none;
+          background: transparent;
+        }
+        .application-input {
+          appearance: auto;
+          padding: 9px;
+          border: 4px solid currentColor;
+          background: transparent;
+        }
+      `;
+      document.head.append(style);
+      const buttonHost = document.createElement('zen-button');
+      buttonHost.setAttribute('appearance', 'plain');
+      buttonHost.setAttribute('loading', '');
+      const button = document.createElement('button');
+      button.className = 'application-button';
+      button.textContent = 'Plain';
+      buttonHost.append(button);
+
+      const card = document.createElement('zen-card');
+      card.setAttribute('appearance', 'plain');
+      const article = document.createElement('article');
+      card.append(article);
+
+      const field = document.createElement('zen-field');
+      field.setAttribute('appearance', 'plain');
+      const label = document.createElement('label');
+      label.textContent = 'Plain field';
+      const input = document.createElement('input');
+      field.append(label, input);
+      const inputHost = document.createElement('zen-input');
+      inputHost.setAttribute('appearance', 'plain');
+      inputHost.setAttribute('size', 'lg');
+      const applicationInput = document.createElement('input');
+      applicationInput.className = 'application-input';
+      inputHost.append(applicationInput);
+      document.body.append(buttonHost, card, field, inputHost);
+
+      const buttonStyle = getComputedStyle(button);
+      const cardStyle = getComputedStyle(article);
+      return {
+        buttonBackground: buttonStyle.backgroundColor,
+        buttonBorder: buttonStyle.borderTopWidth,
+        buttonPadding: buttonStyle.paddingTop,
+        buttonShadow: buttonStyle.boxShadow,
+        buttonOpacity: buttonStyle.opacity,
+        buttonSpinner: getComputedStyle(button, '::before').content,
+        cardBackground: cardStyle.backgroundColor,
+        cardBorder: cardStyle.borderTopWidth,
+        cardShadow: cardStyle.boxShadow,
+        fieldDisplay: getComputedStyle(field).display,
+        inputAppearance: getComputedStyle(input).appearance,
+        plainInputAppearance: getComputedStyle(applicationInput).appearance,
+        plainInputBorder: getComputedStyle(applicationInput).borderTopWidth,
+        plainInputPadding: getComputedStyle(applicationInput).paddingTop,
+        labelFor: label.htmlFor,
+        inputId: input.id,
+      };
+    });
+    assert.deepEqual(plainPresentation, {
+      buttonBackground: 'rgba(0, 0, 0, 0)',
+      buttonBorder: '3px',
+      buttonPadding: '7px',
+      buttonShadow: 'none',
+      buttonOpacity: '1',
+      buttonSpinner: 'none',
+      cardBackground: 'rgba(0, 0, 0, 0)',
+      cardBorder: '0px',
+      cardShadow: 'none',
+      fieldDisplay: 'contents',
+      inputAppearance: 'auto',
+      plainInputAppearance: 'auto',
+      plainInputBorder: '4px',
+      plainInputPadding: '9px',
+      labelFor: plainPresentation.inputId,
+      inputId: plainPresentation.inputId,
+    });
+    const buttonScale = await page.locator(
+      '[data-catalog-page="button"] zen-button[size] > button',
+    ).evaluateAll(buttons => buttons.map(button => {
+      const host = button.parentElement;
+      const style = getComputedStyle(button);
+      const hostStyle = getComputedStyle(host);
+      return {
+        fontSize: Number.parseFloat(style.fontSize),
+        height: button.getBoundingClientRect().height,
+        paddingInline: Number.parseFloat(style.paddingInlineStart),
+        size: host.getAttribute('size'),
+        variableHeight: Number.parseFloat(
+          hostStyle.getPropertyValue('--zenbu-control-height'),
+        ) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
+      };
+    }));
+    assert.deepEqual(
+      buttonScale.map(item => item.size),
+      ['xs', 'sm', 'md', 'lg', 'xl'],
+    );
+    for (let index = 1; index < buttonScale.length; index++) {
+      assert.ok(buttonScale[index].height > buttonScale[index - 1].height);
+      assert.ok(
+        buttonScale[index].paddingInline >
+          buttonScale[index - 1].paddingInline,
+      );
+      assert.ok(
+        buttonScale[index].fontSize > buttonScale[index - 1].fontSize,
+      );
+    }
+    for (const item of buttonScale) {
+      assert.ok(
+        Math.abs(item.height - item.variableHeight) < 1,
+        JSON.stringify(buttonScale),
+      );
+    }
+    const compactScale = await page.evaluate(() => {
+      document.documentElement.dataset.zenDensity = 'compact';
+      return [...document.querySelectorAll(
+        '[data-catalog-page="button"] zen-button[size] > button',
+      )]
+        .map(button => button.getBoundingClientRect().height);
+    });
+    assert.equal(compactScale.length, buttonScale.length);
+    for (let index = 0; index < compactScale.length; index++) {
+      assert.ok(compactScale[index] < buttonScale[index].height);
+    }
+    await page.evaluate(() => {
+      delete document.documentElement.dataset.zenDensity;
+    });
+
+    await page.emulateMedia({ reducedMotion: 'reduce' });
+    assert.equal(
+      await page.evaluate(() =>
+        getComputedStyle(document.documentElement)
+          .getPropertyValue('--zenbu-sys-motion-duration-state')
+          .trim()
+      ),
+      '1ms',
+    );
+    await page.emulateMedia({ reducedMotion: 'no-preference' });
+
+    assert.equal(
+      await page.locator('zen-button[loading]:not([appearance="plain"])').getAttribute('inert'),
+      null,
+    );
+    assert.equal(
+      await page.locator('zen-button[loading]:not([appearance="plain"]) button').getAttribute('aria-disabled'),
+      'true',
+    );
+    assert.equal(
+      await page.locator('zen-button[loading]:not([appearance="plain"]) button').getAttribute('aria-busy'),
+      'true',
+    );
+    await page.evaluate(() => {
+      window.__loadingClicks = 0;
+      document.querySelector('zen-button[loading]:not([appearance="plain"]) button')
+        .addEventListener('click', () => window.__loadingClicks++);
+    });
+    await page.locator('zen-button[loading]:not([appearance="plain"]) button').evaluate(
+      button => button.click(),
+    );
+    assert.equal(await page.evaluate(() => window.__loadingClicks), 0);
+    await page.locator('zen-button[loading]:not([appearance="plain"]) button').focus();
+    assert.equal(
+      await page.locator('zen-button[loading]:not([appearance="plain"]) button').evaluate(
+        button => document.activeElement === button,
+      ),
+      true,
+    );
+    await page.keyboard.press('Tab');
+    assert.equal(
+      await page.locator('zen-button[loading]:not([appearance="plain"]) button').evaluate(
+        button => document.activeElement === button,
+      ),
+      false,
+    );
+    const nativeDisabledPreserved = await page.evaluate(async () => {
+      const wrapper = document.createElement('zen-button');
+      const button = document.createElement('button');
+      button.disabled = true;
+      button.textContent = 'Native disabled';
+      wrapper.append(button);
+      document.body.append(wrapper);
+      await customElements.whenDefined('zen-button');
+      wrapper.setAttribute('disabled', '');
+      wrapper.removeAttribute('disabled');
+      return button.disabled;
+    });
+    assert.equal(nativeDisabledPreserved, true);
+    const replacementButtonState = await page.evaluate(async () => {
+      const wrapper = document.createElement('zen-button');
+      wrapper.setAttribute('disabled', '');
+      const first = document.createElement('button');
+      first.textContent = 'First';
+      wrapper.append(first);
+      document.body.append(wrapper);
+      await new Promise(resolve => setTimeout(resolve));
+      const second = document.createElement('button');
+      second.textContent = 'Second';
+      wrapper.replaceChildren(second);
+      await new Promise(resolve => setTimeout(resolve));
+      return {
+        firstDisabled: first.disabled,
+        secondAriaDisabled: second.getAttribute('aria-disabled'),
+        wrapperInert: wrapper.hasAttribute('inert'),
+      };
+    });
+    assert.equal(replacementButtonState.firstDisabled, false);
+    assert.equal(replacementButtonState.secondAriaDisabled, 'true');
+    assert.equal(replacementButtonState.wrapperInert, false);
+    const modifiedClickAllowed = await page.evaluate(() => {
+      const link = document.querySelector(
+        '.catalog-sidebar a[href="/components/card"]',
+      );
+      return link.dispatchEvent(new MouseEvent('click', {
+        bubbles: true,
+        cancelable: true,
+        button: 0,
+        ctrlKey: true,
+      }));
+    });
+    assert.equal(modifiedClickAllowed, true);
+
+    await page.goto(`${baseUrl}/icons`, { waitUntil: 'networkidle' });
+    const iconCount = await page.locator('#iconGrid figure').count();
+    assert.ok(iconCount >= 30);
+    assert.equal(
+      await page.locator('#iconGrid figure zen-icon > svg').count(),
+      iconCount,
+    );
+    const iconFallback = await page.evaluate(() => {
+      const icon = document.createElement('zen-icon');
+      icon.setAttribute('name', 'not-a-real-icon');
+      icon.setAttribute('label', 'Missing icon fallback');
+      document.body.append(icon);
+      return {
+        fallback: icon.dataset.zenIcon,
+        hidden: icon.getAttribute('aria-hidden'),
+        label: icon.getAttribute('aria-label'),
+        role: icon.getAttribute('role'),
+      };
+    });
+    assert.deepEqual(iconFallback, {
+      fallback: 'alert',
+      hidden: null,
+      label: 'Missing icon fallback',
+      role: 'img',
+    });
+
+    await page.goto(`${baseUrl}/components/link`, {
+      waitUntil: 'networkidle',
+    });
+    const linkPrimitive = page.locator('zen-link[effect="paw"]').first();
+    assert.equal(
+      await linkPrimitive.locator(
+        ':scope > a > zen-icon[name="paw"][data-zen-link-decoration]',
+      ).count(),
+      1,
+    );
+    const pawMotion = await linkPrimitive.locator('zen-icon').evaluate(icon => {
+      const style = getComputedStyle(icon);
+      const keyframes = icon.getAnimations().some(animation =>
+        animation.animationName === 'zen-paw-step'
+      );
+      return {
+        animationDuration: style.animationDuration,
+        color: style.color,
+        keyframes,
+      };
+    });
+    assert.notEqual(pawMotion.animationDuration, '0s');
+    assert.notEqual(pawMotion.color, 'rgba(0, 0, 0, 0)');
+    assert.equal(pawMotion.keyframes, true);
+    await page.emulateMedia({ reducedMotion: 'reduce' });
+    assert.equal(
+      await linkPrimitive.locator('zen-icon').evaluate(
+        icon => getComputedStyle(icon).animationName,
+      ),
+      'none',
+    );
+    await page.emulateMedia({ reducedMotion: 'no-preference' });
+
+    await page.goto(`${baseUrl}/components/text`, {
+      waitUntil: 'networkidle',
+    });
+    const textScale = await page.locator('zen-text[size] > p').evaluateAll(
+      texts => texts.map(text => Number.parseFloat(
+        getComputedStyle(text).fontSize,
+      )),
+    );
+    assert.equal(textScale.length, 5);
+    for (let index = 1; index < textScale.length; index++) {
+      assert.ok(textScale[index] > textScale[index - 1]);
+    }
+
+    await page.goto(`${baseUrl}/components/heading`, {
+      waitUntil: 'networkidle',
+    });
+    const headingScale = await page.locator(
+      'zen-heading[size] > h3',
+    ).evaluateAll(headings => headings.map(heading => ({
+      fontSize: Number.parseFloat(getComputedStyle(heading).fontSize),
+      weight: Number(getComputedStyle(heading).fontWeight),
+    })));
+    assert.equal(headingScale.length, 5);
+    assert.ok(headingScale.every(heading => heading.weight >= 700));
+    for (let index = 1; index < headingScale.length; index++) {
+      assert.ok(
+        headingScale[index].fontSize > headingScale[index - 1].fontSize,
+      );
+    }
+
+    await page.goto(`${baseUrl}/components/box`, {
+      waitUntil: 'networkidle',
+    });
+    const boxScale = await page.locator('zen-box[padding]').evaluateAll(
+      boxes => boxes.map(box => Number.parseFloat(
+        getComputedStyle(box).paddingTop,
+      )),
+    );
+    assert.equal(boxScale.length, 5);
+    for (let index = 1; index < boxScale.length; index++) {
+      assert.ok(boxScale[index] > boxScale[index - 1]);
+    }
+
+    await page.goto(`${baseUrl}/components/skeleton`, {
+      waitUntil: 'networkidle',
+    });
+    assert.equal(
+      await page.locator('zen-skeleton[width="60%"]').evaluate(
+        skeleton => skeleton.style.getPropertyValue(
+          '--zenbu-skeleton-width',
+        ),
+      ),
+      '60%',
+    );
+
+    await page.goto(`${baseUrl}/tokens`, { waitUntil: 'networkidle' });
+    const colorTokenState = await page.evaluate(() => {
+      const root = document.documentElement;
+      const value = name => getComputedStyle(root)
+        .getPropertyValue(`--zen-color-${name}`)
+        .trim();
+      const systemValue = name => getComputedStyle(root)
+        .getPropertyValue(`--zenbu-sys-${name}`)
+        .trim();
+      const families = [
+        'neutral',
+        'red',
+        'orange',
+        'amber',
+        'green',
+        'teal',
+        'blue',
+        'violet',
+        'rose',
+        'brown',
+      ];
+      const steps = [
+        '50',
+        '100',
+        '200',
+        '300',
+        '400',
+        '500',
+        '600',
+        '700',
+        '800',
+        '900',
+        '950',
+      ];
+      const rampsComplete = families.every(family =>
+        steps.every(step => value(`${family}-${step}`))
+      );
+      const data = Array.from(
+        { length: 10 },
+        (_, index) => value(`data-${index + 1}`),
+      );
+      const materials = [
+        'paper',
+        'washi',
+        'linen',
+        'sumi',
+        'brick',
+        'persimmon',
+        'ochre',
+        'moss',
+        'patina',
+        'indigo',
+        'plum',
+        'clay',
+        'wood',
+      ].map(value);
+      const lightMuted = systemValue('color-surface-subtle');
+      root.dataset.zenTheme = 'dark';
+      const darkMuted = systemValue('color-surface-subtle');
+      const darkData = Array.from(
+        { length: 10 },
+        (_, index) => value(`data-${index + 1}`),
+      );
+      const themes = ['paper', 'ink', 'playful'].map(theme => {
+        root.dataset.zenTheme = theme;
+        const channels = value => value.match(/\d+(?:\.\d+)?/g)
+          .slice(0, 3)
+          .map(Number);
+        const luminance = value => {
+          const converted = channels(value).map(channel => {
+            const normalized = channel / 255;
+            return normalized <= 0.04045
+              ? normalized / 12.92
+              : ((normalized + 0.055) / 1.055) ** 2.4;
+          });
+          return converted[0] * 0.2126 +
+            converted[1] * 0.7152 +
+            converted[2] * 0.0722;
+        };
+        const contrasts = [
+          'info',
+          'success',
+          'warning',
+          'danger',
+        ].map(tone => {
+          const probe = document.createElement('span');
+          probe.style.background =
+            `var(--zenbu-sys-color-${tone}-background)`;
+          probe.style.color =
+            `var(--zenbu-sys-color-${tone}-foreground)`;
+          document.body.append(probe);
+          const probeStyle = getComputedStyle(probe);
+          const foreground = luminance(probeStyle.color);
+          const background = luminance(probeStyle.backgroundColor);
+          const contrast = (Math.max(foreground, background) + 0.05) /
+            (Math.min(foreground, background) + 0.05);
+          probe.remove();
+          return contrast;
+        });
+        return {
+          canvas: systemValue('color-surface-page'),
+          contrast: Math.min(...contrasts),
+          font: getComputedStyle(root)
+            .getPropertyValue('--zenbu-sys-font-family-ui')
+            .trim(),
+          name: theme,
+          radius: getComputedStyle(root)
+            .getPropertyValue('--zenbu-sys-radius-container')
+            .trim(),
+        };
+      });
+      delete root.dataset.zenTheme;
+      return {
+        darkData,
+        darkMuted,
+        data,
+        lightMuted,
+        materials,
+        rampsComplete,
+        themes,
+      };
+    });
+    assert.equal(colorTokenState.rampsComplete, true);
+    assert.equal(new Set(colorTokenState.materials).size, 13);
+    assert.equal(new Set(colorTokenState.data).size, 10);
+    assert.equal(new Set(colorTokenState.darkData).size, 10);
+    assert.notDeepEqual(colorTokenState.data, colorTokenState.darkData);
+    assert.equal(
+      new Set(colorTokenState.themes.map(theme => theme.canvas)).size,
+      3,
+    );
+    assert.notEqual(
+      colorTokenState.themes.find(theme => theme.name === 'paper').radius,
+      colorTokenState.themes.find(theme => theme.name === 'playful').radius,
+    );
+    assert.ok(
+      colorTokenState.themes.every(theme => theme.contrast >= 4.5),
+      JSON.stringify(colorTokenState.themes),
+    );
+    assert.notEqual(
+      colorTokenState.lightMuted,
+      colorTokenState.darkMuted,
+    );
+    assert.equal(await page.locator('.palette-grid > div').count(), 13);
+    assert.equal(await page.locator('.data-palette > span').count(), 10);
+    await page.evaluate(() => {
+      document.documentElement.dataset.zenTheme = 'playful';
+    });
+    await page.emulateMedia({ forcedColors: 'active' });
+    assert.equal(
+      await page.evaluate(() =>
+        getComputedStyle(document.documentElement)
+          .getPropertyValue('--zenbu-sys-color-surface-page')
+          .trim()
+          .toLowerCase()
+      ),
+      'canvas',
+    );
+    await page.emulateMedia({ forcedColors: 'none' });
+    await page.evaluate(() => {
+      delete document.documentElement.dataset.zenTheme;
+    });
+
+    await page.goto(`${baseUrl}/components/field`, {
+      waitUntil: 'networkidle',
+    });
+    const fieldWiring = await page.locator('zen-field').first().evaluate(field => {
+      const label = field.querySelector('label');
+      const input = field.querySelector('input');
+      const help = field.querySelector('small');
+      input.checkValidity();
+      return {
+        describedBy: input.getAttribute('aria-describedby'),
+        helpId: help.id,
+        inputId: input.id,
+        invalid: field.hasAttribute('data-invalid'),
+        labelFor: label.htmlFor,
+      };
+    });
+    assert.ok(fieldWiring.inputId);
+    assert.equal(fieldWiring.labelFor, fieldWiring.inputId);
+    assert.equal(fieldWiring.describedBy, fieldWiring.helpId);
+    assert.equal(fieldWiring.invalid, true);
+    await page.locator('zen-field input').first().focus();
+    assert.equal(
+      await page.locator('zen-field input').first().evaluate(
+        input => getComputedStyle(input).outlineStyle,
+      ),
+      'none',
+    );
+    const replacementField = await page.locator('zen-field').first().evaluate(
+      async field => {
+        const label = field.querySelector('label');
+        const oldInput = field.querySelector('input');
+        const blocker = document.createElement('div');
+        blocker.id = 'zen-field-3';
+        document.body.append(blocker);
+        const nextInput = document.createElement('input');
+        nextInput.required = true;
+        oldInput.replaceWith(nextInput);
+        await new Promise(resolve => setTimeout(resolve));
+        oldInput.dispatchEvent(new Event('invalid'));
+        const help = field.querySelector('small');
+        nextInput.id = 'replacement-email';
+        help.id = 'replacement-help';
+        await new Promise(resolve => setTimeout(resolve));
+        return {
+          describedBy: nextInput.getAttribute('aria-describedby'),
+          helpId: help.id,
+          labelFor: label.htmlFor,
+          nextId: nextInput.id,
+          blockerId: blocker.id,
+        };
+      },
+    );
+    assert.ok(replacementField.nextId);
+    assert.notEqual(replacementField.nextId, replacementField.blockerId);
+    assert.equal(replacementField.labelFor, replacementField.nextId);
+    assert.equal(replacementField.describedBy, replacementField.helpId);
+
+    await page.goto(`${baseUrl}/components/alert`, {
+      waitUntil: 'networkidle',
+    });
+    await page.evaluate(() => {
+      window.__dismissed = 0;
+      document.addEventListener('zen-dismiss', () => {
+        window.__dismissed++;
+      });
+    });
+    const dismissible = page.locator('zen-alert[dismissible]');
+    assert.equal(await dismissible.getAttribute('role'), 'alert');
+    await dismissible.locator('[data-zen-dismiss]').click();
+    assert.equal(await dismissible.count(), 0);
+    assert.equal(await page.evaluate(() => window.__dismissed), 1);
+    const authoredDismissState = await page.evaluate(async () => {
+      const alert = document.createElement('zen-alert');
+      alert.setAttribute('dismissible', '');
+      const message = document.createElement('p');
+      message.textContent = 'Authored dismiss control';
+      const dismiss = document.createElement('button');
+      dismiss.dataset.zenDismiss = '';
+      alert.append(message, dismiss);
+      document.body.append(alert);
+      await new Promise(resolve => setTimeout(resolve));
+      let events = 0;
+      alert.addEventListener('zen-dismiss', () => events++);
+      alert.removeAttribute('dismissible');
+      dismiss.click();
+      return {
+        connected: alert.isConnected,
+        events,
+      };
+    });
+    assert.equal(authoredDismissState.connected, true);
+    assert.equal(authoredDismissState.events, 0);
+
+    await page.goto(`${baseUrl}/components/accordion`, {
+      waitUntil: 'networkidle',
+    });
+    const accordion = page.locator('zen-accordion').first();
+    const disclosureIcon = accordion.locator(
+      'summary > zen-icon[data-zen-disclosure-icon]',
+    ).nth(1);
+    const collapsedDisclosure = await disclosureIcon.evaluate(icon => {
+      const style = getComputedStyle(icon);
+      return {
+        duration: style.transitionDuration,
+        transform: style.transform,
+      };
+    });
+    assert.notEqual(collapsedDisclosure.duration, '0s');
+    await accordion.locator('summary').nth(1).click();
+    await page.waitForTimeout(250);
+    assert.notEqual(
+      await disclosureIcon.evaluate(icon => getComputedStyle(icon).transform),
+      collapsedDisclosure.transform,
+    );
+    assert.equal(
+      await accordion.locator('details').first().getAttribute('open'),
+      null,
+    );
+    assert.equal(
+      await accordion.locator('details').nth(1).getAttribute('open'),
+      '',
+    );
+    await accordion.locator('summary').nth(1).press('ArrowUp');
+    assert.equal(
+      await accordion.locator('summary').first().evaluate(
+        summary => document.activeElement === summary,
+      ),
+      true,
+    );
+
+    await page.goto(`${baseUrl}/components/aspect-ratio`, {
+      waitUntil: 'networkidle',
+    });
+    const aspectColors = await page.locator('.demo-media').evaluate(media => {
+      const style = getComputedStyle(media);
+      const probe = document.createElement('span');
+      probe.style.background = 'var(--zenbu-sys-color-surface-subtle)';
+      document.body.append(probe);
+      const token = getComputedStyle(probe).backgroundColor;
+      probe.remove();
+      return {
+        background: style.backgroundColor,
+        image: style.backgroundImage,
+        token,
+      };
+    });
+    assert.equal(aspectColors.image, 'none');
+    assert.equal(aspectColors.background, aspectColors.token);
+
+    await page.goto(`${baseUrl}/components/tabs`, {
+      waitUntil: 'networkidle',
+    });
+    await page.evaluate(() => {
+      window.__tabValue = null;
+      document.querySelector('zen-tabs').addEventListener(
+        'zen-change',
+        event => {
+          window.__tabValue = event.detail.value;
+        },
+      );
+    });
+    await page.locator('zen-tabs [role="tab"]').nth(1).click();
+    assert.equal(
+      await page.locator('zen-tabs [role="tab"]').nth(1)
+        .getAttribute('aria-selected'),
+      'true',
+    );
+    assert.equal(
+      await page.locator('zen-tabs [role="tabpanel"]').nth(1)
+        .getAttribute('hidden'),
+      null,
+    );
+    assert.equal(await page.evaluate(() => window.__tabValue), 'history');
+
+    await page.goto(`${baseUrl}/components/dialog`, {
+      waitUntil: 'networkidle',
+    });
+    await page.locator('zen-dialog [data-zen-trigger]').click();
+    assert.equal(await page.locator('zen-dialog dialog').getAttribute('open'), '');
+    await page.locator('zen-dialog [data-zen-close]').click();
+    assert.equal(await page.locator('zen-dialog dialog').getAttribute('open'), null);
+    const dynamicOverlays = await page.evaluate(async () => {
+      const ownAction = button => {
+        const owner = document.createElement('zen-button');
+        owner.setAttribute('size', 'md');
+        owner.append(button);
+        return owner;
+      };
+      const dialogHost = document.createElement('zen-dialog');
+      const popoverHost = document.createElement('zen-popover');
+      const tooltipHost = document.createElement('zen-tooltip');
+      const menuHost = document.createElement('zen-dropdown-menu');
+      document.body.append(dialogHost, popoverHost, tooltipHost, menuHost);
+
+      const dialogTrigger = document.createElement('button');
+      dialogTrigger.type = 'button';
+      dialogTrigger.dataset.zenTrigger = '';
+      const dialog = document.createElement('dialog');
+      dialogHost.append(ownAction(dialogTrigger), dialog);
+
+      const popoverTrigger = document.createElement('button');
+      popoverTrigger.type = 'button';
+      popoverTrigger.dataset.zenTrigger = '';
+      const popover = document.createElement('div');
+      popover.dataset.zenContent = '';
+      popoverHost.append(ownAction(popoverTrigger), popover);
+
+      const tooltipTrigger = document.createElement('button');
+      tooltipTrigger.type = 'button';
+      tooltipTrigger.dataset.zenTrigger = '';
+      const tooltip = document.createElement('span');
+      tooltip.dataset.zenContent = '';
+      tooltipHost.append(ownAction(tooltipTrigger), tooltip);
+
+      const menuTrigger = document.createElement('button');
+      menuTrigger.type = 'button';
+      menuTrigger.dataset.zenTrigger = '';
+      const menu = document.createElement('div');
+      menu.setAttribute('role', 'menu');
+      const item = document.createElement('button');
+      item.type = 'button';
+      item.setAttribute('role', 'menuitem');
+      menu.append(item);
+      menuHost.append(menuTrigger, menu);
+
+      await new Promise(resolve => setTimeout(resolve));
+      dialogTrigger.click();
+      const dialogOpen = dialog.open;
+      dialog.close();
+      popoverTrigger.click();
+      menuTrigger.click();
+      tooltipTrigger.focus();
+      await new Promise(resolve => setTimeout(resolve, 375));
+      return {
+        dialogControlled: Boolean(dialogTrigger.getAttribute('aria-controls')),
+        dialogOpen,
+        menuOpen: !menu.hidden,
+        popoverExpanded: popoverTrigger.getAttribute('aria-expanded'),
+        tooltipOpen: !tooltip.hidden,
+      };
+    });
+    assert.deepEqual(dynamicOverlays, {
+      dialogControlled: true,
+      dialogOpen: true,
+      menuOpen: true,
+      popoverExpanded: 'true',
+      tooltipOpen: true,
+    });
+
+    await page.goto(`${baseUrl}/components/dropdown-menu`, {
+      waitUntil: 'networkidle',
+    });
+    const dropdownTrigger = page.locator(
+      'zen-dropdown-menu [data-zen-trigger]',
+    );
+    await dropdownTrigger.click();
+    assert.equal(
+      await page.locator('zen-dropdown-menu [role="menu"]')
+        .getAttribute('hidden'),
+      null,
+    );
+    await page.keyboard.press('Escape');
+    assert.equal(
+      await page.locator('zen-dropdown-menu [role="menu"]')
+        .getAttribute('hidden'),
+      '',
+    );
+    assert.equal(
+      await dropdownTrigger.evaluate(
+        trigger => document.activeElement === trigger,
+      ),
+      true,
+    );
+    await dropdownTrigger.click();
+    await page.locator('zen-dropdown-menu [role="menuitem"]').first().click();
+    assert.equal(
+      await dropdownTrigger.evaluate(
+        trigger => document.activeElement === trigger,
+      ),
+      true,
+    );
+
+    await page.goto(`${baseUrl}/components/combobox`, {
+      waitUntil: 'networkidle',
+    });
+    const comboboxInput = page.locator('zen-combobox input');
+    await comboboxInput.fill('seo');
+    assert.equal(
+      await page.locator('zen-combobox [role="option"]:not([hidden])').count(),
+      1,
+    );
+    await comboboxInput.press('ArrowDown');
+    await comboboxInput.press('Enter');
+    assert.equal(await comboboxInput.inputValue(), 'seobeo');
+    assert.equal(
+      await page.locator('zen-combobox [role="listbox"]')
+        .getAttribute('hidden'),
+      '',
+    );
+
+    await page.goto(`${baseUrl}/components/date-picker`, {
+      waitUntil: 'networkidle',
+    });
+    const dateInput = page.locator('zen-date-picker input[type="date"]');
+    assert.equal(await dateInput.getAttribute('aria-hidden'), 'true');
+    assert.equal(
+      await dateInput.evaluate(input => getComputedStyle(input).position),
+      'absolute',
+    );
+    await page.evaluate(() => {
+      window.__dateValue = null;
+      document.querySelector('zen-date-picker').addEventListener(
+        'zen-change',
+        event => {
+          window.__dateValue = event.detail.value;
+        },
+      );
+    });
+    const dateTrigger = page.locator(
+      'zen-date-picker [data-zen-date-trigger]',
+    );
+    await dateTrigger.click();
+    assert.equal(
+      await page.locator('zen-date-picker [data-zen-calendar-panel]')
+        .getAttribute('hidden'),
+      null,
+    );
+    assert.equal(
+      await page.locator(
+        'zen-date-picker [data-zen-calendar-day]',
+      ).count(),
+      42,
+    );
+    const chosenDate = await page.locator(
+      'zen-date-picker [data-zen-calendar-day]:not([data-outside]):not(:disabled)',
+    ).nth(14).getAttribute('data-zen-calendar-day');
+    await page.locator(
+      `zen-date-picker [data-zen-calendar-day="${chosenDate}"]`,
+    ).click();
+    assert.equal(await dateInput.inputValue(), chosenDate);
+    assert.equal(await page.evaluate(() => window.__dateValue), chosenDate);
+    assert.equal(await dateTrigger.getAttribute('aria-expanded'), 'false');
+    const triggerName = await dateTrigger.evaluate(trigger =>
+      (trigger.getAttribute('aria-labelledby') || '')
+        .split(/\s+/)
+        .map(id => document.getElementById(id)?.textContent || '')
+        .join(' ')
+    );
+    assert.match(triggerName, /Deploy on/);
+    assert.equal(
+      await page.locator('zen-date-picker > label').getAttribute('for'),
+      await dateTrigger.getAttribute('id'),
+    );
+    const minimumDate = `${chosenDate.slice(0, 8)}10`;
+    await dateInput.evaluate((input, minimum) => {
+      input.min = minimum;
+    }, minimumDate);
+    await page.waitForTimeout(0);
+    await dateTrigger.click();
+    const focusedBoundary = page.locator(
+      `zen-date-picker [data-zen-calendar-day="${chosenDate}"]`,
+    );
+    await focusedBoundary.press('PageUp');
+    assert.equal(
+      await page.evaluate(() =>
+        document.activeElement?.dataset.zenCalendarDay
+      ),
+      minimumDate,
+    );
+    assert.equal(
+      await page.locator(
+        'zen-date-picker [data-zen-calendar-day][tabindex="0"]:not(:disabled)',
+      ).count(),
+      1,
+    );
+    await page.keyboard.press('Escape');
+    await dateInput.evaluate(input => {
+      input.disabled = true;
+    });
+    await page.waitForTimeout(0);
+    assert.equal(await dateTrigger.isDisabled(), true);
+    await dateInput.evaluate(input => {
+      input.disabled = false;
+      input.readOnly = true;
+    });
+    await page.waitForTimeout(0);
+    assert.equal(await dateTrigger.isDisabled(), true);
+    await dateInput.evaluate(input => {
+      input.readOnly = false;
+      input.required = true;
+      input.value = '';
+      input.dispatchEvent(new Event('input', { bubbles: true }));
+      input.reportValidity();
+    });
+    await page.waitForTimeout(0);
+    assert.equal(await dateTrigger.getAttribute('aria-invalid'), 'true');
+    assert.equal(
+      await dateTrigger.evaluate(
+        trigger => document.activeElement === trigger,
+      ),
+      true,
+    );
+    assert.equal(
+      await page.locator('zen-date-picker').getAttribute('data-invalid'),
+      '',
+    );
+    await dateInput.evaluate((input, value) => {
+      input.value = value;
+      input.dispatchEvent(new Event('input', { bubbles: true }));
+    }, chosenDate);
+    assert.equal(await dateTrigger.getAttribute('aria-invalid'), 'false');
+    const earlyYear = await page.evaluate(async () => {
+      const calendar = document.createElement('zen-calendar');
+      const input = document.createElement('input');
+      input.type = 'date';
+      input.value = '0001-01-01';
+      input.setAttribute('aria-label', 'Early date');
+      calendar.append(input);
+      document.body.append(calendar);
+      await new Promise(resolve => setTimeout(resolve));
+      return {
+        selected: calendar.querySelector(
+          '[data-zen-calendar-day][aria-selected="true"]',
+        )?.dataset.zenCalendarDay,
+        value: input.value,
+      };
+    });
+    assert.deepEqual(earlyYear, {
+      selected: '0001-01-01',
+      value: '0001-01-01',
+    });
+    const resetDateState = await page.evaluate(async () => {
+      const label = document.createElement('span');
+      label.id = 'reset-date-label';
+      label.textContent = 'Reset date';
+      const form = document.createElement('form');
+      const picker = document.createElement('zen-date-picker');
+      const input = document.createElement('input');
+      input.type = 'date';
+      input.defaultValue = '2026-08-04';
+      input.setAttribute('aria-labelledby', label.id);
+      picker.append(input);
+      form.append(picker);
+      document.body.append(label, form);
+      await new Promise(resolve => setTimeout(resolve));
+      input.value = '2026-08-12';
+      input.dispatchEvent(new Event('input', { bubbles: true }));
+      form.reset();
+      await new Promise(resolve => setTimeout(resolve));
+      const trigger = picker.querySelector('[data-zen-date-trigger]');
+      return {
+        labelledBy: trigger.getAttribute('aria-labelledby'),
+        selected: picker.querySelector(
+          '[data-zen-calendar-day][aria-selected="true"]',
+        )?.dataset.zenCalendarDay,
+        value: input.value,
+      };
+    });
+    assert.match(resetDateState.labelledBy, /^reset-date-label /);
+    assert.deepEqual(
+      {
+        selected: resetDateState.selected,
+        value: resetDateState.value,
+      },
+      {
+        selected: '2026-08-04',
+        value: '2026-08-04',
+      },
+    );
+
+    await page.goto(`${baseUrl}/components/input-otp`, {
+      waitUntil: 'networkidle',
+    });
+    await page.evaluate(() => {
+      window.__otpValue = null;
+      document.querySelector('zen-input-otp').addEventListener(
+        'zen-complete',
+        event => {
+          window.__otpValue = event.detail.value;
+        },
+      );
+    });
+    await page.locator('zen-input-otp input').evaluate(input => {
+      input.value = '12a3456';
+      input.dispatchEvent(new Event('input', { bubbles: true }));
+    });
+    assert.equal(await page.locator('zen-input-otp input').inputValue(), '123456');
+    assert.equal(
+      await page.locator('zen-input-otp [data-zen-otp-slots] > span').count(),
+      6,
+    );
+    const otp = page.locator('zen-input-otp');
+    await otp.evaluate(host => host.setAttribute('size', 'xs'));
+    const compactOtpSize = await otp.locator(
+      '[data-zen-otp-slots] > span',
+    ).first().evaluate(slot => slot.getBoundingClientRect().width);
+    await otp.evaluate(host => host.setAttribute('size', 'xl'));
+    const largeOtpSize = await otp.locator(
+      '[data-zen-otp-slots] > span',
+    ).first().evaluate(slot => slot.getBoundingClientRect().width);
+    assert.ok(largeOtpSize > compactOtpSize);
+    assert.equal(await page.evaluate(() => window.__otpValue), '123456');
+
+    await page.goto(`${baseUrl}/components/data-table`, {
+      waitUntil: 'networkidle',
+    });
+    await page.locator('zen-data-table [data-zen-sort="commits"]').click();
+    assert.equal(
+      await page.locator('zen-data-table th').nth(1).getAttribute('aria-sort'),
+      'ascending',
+    );
+    assert.equal(
+      await page.locator('zen-data-table tbody tr').first().locator(
+        '[data-key="commits"]',
+      ).textContent(),
+      '12',
+    );
+
+    await page.goto(`${baseUrl}/components/carousel`, {
+      waitUntil: 'networkidle',
+    });
+    await page.evaluate(() => {
+      window.__carouselIndex = null;
+      document.querySelector('zen-carousel').addEventListener(
+        'zen-change',
+        event => {
+          window.__carouselIndex = event.detail.index;
+        },
+      );
+    });
+    await page.locator('zen-carousel [data-zen-next]').click();
+    assert.equal(await page.evaluate(() => window.__carouselIndex), 1);
+    assert.equal(
+      await page.locator('zen-carousel [data-zen-prev]').isDisabled(),
+      false,
+    );
+
+    await page.goto(`${baseUrl}/components/resizable`, {
+      waitUntil: 'networkidle',
+    });
+    const resizeHandle = page.locator('zen-resizable [data-zen-handle]');
+    const initialPercent = Number(
+      await resizeHandle.getAttribute('aria-valuenow'),
+    );
+    await resizeHandle.focus();
+    await resizeHandle.press('ArrowRight');
+    assert.ok(
+      Number(await resizeHandle.getAttribute('aria-valuenow')) > initialPercent,
+    );
+
+    await page.goto(`${baseUrl}/components/switch`, {
+      waitUntil: 'networkidle',
+    });
+    const switchInput = page.locator('zen-switch input');
+    assert.equal(await switchInput.getAttribute('role'), 'switch');
+    assert.equal(await switchInput.getAttribute('aria-checked'), 'true');
+    await switchInput.uncheck();
+    assert.equal(await switchInput.getAttribute('aria-checked'), 'false');
+
+    await page.goto(`${baseUrl}/components/checkbox`, {
+      waitUntil: 'networkidle',
+    });
+    assert.equal(
+      await page.locator('zen-checkbox input').evaluate(
+        input => getComputedStyle(input).appearance,
+      ),
+      'none',
+    );
+    await page.goto(`${baseUrl}/components/native-select`, {
+      waitUntil: 'networkidle',
+    });
+    assert.equal(
+      await page.locator('zen-native-select select').evaluate(
+        select => getComputedStyle(select).appearance,
+      ),
+      'none',
+    );
+    assert.equal(
+      await page.locator(
+        'zen-native-select > zen-icon[data-zen-select-icon]',
+      ).count(),
+      1,
+    );
+    await page.goto(`${baseUrl}/components/slider`, {
+      waitUntil: 'networkidle',
+    });
+    assert.equal(
+      await page.locator('zen-slider input').evaluate(
+        input => getComputedStyle(input).appearance,
+      ),
+      'none',
+    );
+
+    await page.goto(`${baseUrl}/components/toggle-group`, {
+      waitUntil: 'networkidle',
+    });
+    await page.locator('zen-toggle-group button[value="right"]').click();
+    assert.equal(
+      await page.locator('zen-toggle-group button[value="right"]')
+        .getAttribute('aria-pressed'),
+      'true',
+    );
+    assert.equal(
+      await page.locator('zen-toggle-group').getAttribute('value'),
+      'right',
+    );
+
+    await page.goto(`${baseUrl}/components/sidebar`, {
+      waitUntil: 'networkidle',
+    });
+    const sidebarTrigger = page.locator(
+      'zen-sidebar [data-zen-sidebar-trigger]',
+    );
+    const sidebarPanel = page.locator(
+      'zen-sidebar [data-zen-sidebar-panel]',
+    );
+    assert.equal(await sidebarTrigger.getAttribute('aria-expanded'), 'true');
+    assert.equal(await sidebarPanel.getAttribute('hidden'), null);
+    await sidebarTrigger.click();
+    assert.equal(await sidebarTrigger.getAttribute('aria-expanded'), 'false');
+    assert.equal(await sidebarPanel.getAttribute('hidden'), '');
+
+    await page.goto(`${baseUrl}/components/notifications`, {
+      waitUntil: 'networkidle',
+    });
+    const notificationScope = page.locator('zen-notifications').first();
+    const notificationPosition = await notificationScope.locator(
+      '[data-zen-notification-stack]',
+    ).evaluate(stack => {
+      const style = getComputedStyle(stack);
+      return {
+        bottom: style.bottom,
+        position: style.position,
+        right: style.right,
+      };
+    });
+    assert.equal(notificationPosition.position, 'fixed');
+    assert.notEqual(notificationPosition.bottom, 'auto');
+    assert.notEqual(notificationPosition.right, 'auto');
+
+    const dedupe = await notificationScope.evaluate(scope => {
+      const source = scope.querySelector('[data-notification-demo]');
+      const send = detail => source.dispatchEvent(
+        new CustomEvent('zen-notify', {
+          bubbles: true,
+          composed: false,
+          detail,
+        }),
+      );
+      send({
+        version: 1,
+        id: 'dedupe',
+        tone: 'info',
+        message: 'First announcement',
+        announcement: 'polite',
+        persistent: true,
+      });
+      send({
+        version: 1,
+        id: 'dedupe',
+        tone: 'success',
+        message: 'Updated without duplication',
+        announcement: 'polite',
+        persistent: true,
+      });
+      send({ version: 99, id: 'invalid' });
+      return {
+        size: scope.size,
+        visible: scope.visibleCount,
+      };
+    });
+    assert.deepEqual(dedupe, { size: 1, visible: 1 });
+    assert.equal(
+      await notificationScope.locator('article').count(),
+      1,
+    );
+    assert.match(
+      await notificationScope.locator('article').textContent(),
+      /Updated without duplication/,
+    );
+    await page.waitForFunction(() =>
+      document.querySelector(
+        'zen-notifications [data-zen-live="polite"]',
+      )?.textContent === 'First announcement'
+    );
+
+    const bounded = await notificationScope.evaluate(scope => {
+      let accepted = 0;
+      for (let index = 0; index < 25; index++) {
+        if (scope.notify({
+          version: 1,
+          id: `bounded-${index}`,
+          tone: 'info',
+          message: `Bounded ${index}`,
+          announcement: 'none',
+          durationMs: 120000,
+        })) accepted++;
+      }
+      return {
+        accepted,
+        size: scope.size,
+        visible: scope.visibleCount,
+      };
+    });
+    assert.deepEqual(bounded, { accepted: 25, size: 23, visible: 3 });
+    assert.equal(
+      await notificationScope.locator('article').count(),
+      3,
+    );
+    await page.waitForFunction(() =>
+      [...document.querySelectorAll(
+        'zen-notifications article',
+      )].some(article => article.dataset.depth === '2')
+    );
+    const collapsedStack = await notificationScope.locator(
+      '[data-zen-notification-stack]',
+    ).evaluate(stack => {
+      const articles = [...stack.querySelectorAll('article')];
+      return {
+        depths: articles.map(article => article.dataset.depth),
+        height: stack.getBoundingClientRect().height,
+        positions: articles.map(article =>
+          getComputedStyle(article).position
+        ),
+        transforms: articles.map(article =>
+          getComputedStyle(article).transform
+        ),
+      };
+    });
+    assert.deepEqual(collapsedStack.depths, ['2', '1', '0']);
+    assert.deepEqual(
+      collapsedStack.positions,
+      ['absolute', 'absolute', 'absolute'],
+    );
+    await notificationScope.locator('article').last().hover();
+    await page.waitForTimeout(300);
+    const expandedStack = await notificationScope.locator(
+      '[data-zen-notification-stack]',
+    ).evaluate(stack => ({
+      height: stack.getBoundingClientRect().height,
+      rects: [...stack.querySelectorAll('article')].map(article => {
+        const bounds = article.getBoundingClientRect();
+        return {
+          bottom: bounds.bottom,
+          left: bounds.left,
+          right: bounds.right,
+          top: bounds.top,
+        };
+      }),
+      tops: [...stack.querySelectorAll('article')].map(
+        article => Math.round(article.getBoundingClientRect().top),
+      ),
+      transforms: [...stack.querySelectorAll('article')].map(
+        article => getComputedStyle(article).transform,
+      ),
+    }));
+    assert.ok(expandedStack.height > collapsedStack.height);
+    assert.equal(new Set(expandedStack.tops).size, 3);
+    const expandedGaps = [
+      expandedStack.rects[1].top - expandedStack.rects[0].bottom,
+      expandedStack.rects[2].top - expandedStack.rects[1].bottom,
+    ];
+    for (const gap of expandedGaps) {
+      assert.ok(gap >= 10 && gap <= 14, JSON.stringify(expandedGaps));
+    }
+    assert.notDeepEqual(
+      expandedStack.transforms,
+      collapsedStack.transforms,
+    );
+    const gapX =
+      (expandedStack.rects[0].left + expandedStack.rects[0].right) / 2;
+    const gapY =
+      (expandedStack.rects[0].bottom + expandedStack.rects[1].top) / 2;
+    await page.mouse.move(gapX, gapY);
+    await page.waitForTimeout(100);
+    const gapState = await notificationScope.locator(
+      '[data-zen-notification-stack]',
+    ).evaluate(stack => ({
+      height: stack.getBoundingClientRect().height,
+      hovered: stack.matches(':hover'),
+    }));
+    assert.equal(gapState.hovered, true);
+    assert.ok(gapState.height >= expandedStack.height - 1);
+    await page.mouse.move(0, 0);
+
+    const actionScope = await page.evaluate(() => {
+      const scope = document.createElement('zen-notifications');
+      scope.id = 'action-scope';
+      const source = document.createElement('button');
+      scope.append(source);
+      document.body.append(scope);
+      window.__notificationAction = null;
+      scope.addEventListener('zen-notification-action', event => {
+        window.__notificationAction = event.detail;
+      });
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'action',
+          tone: 'error',
+          message: 'Action required',
+          announcement: 'assertive',
+          persistent: true,
+          action: {
+            token: 'opaque-secret-token',
+            label: 'Retry',
+          },
+        },
+      }));
+      return scope.id;
+    });
+    assert.equal(
+      await page.locator(`#${actionScope}`).evaluate(
+        scope => scope.records,
+      ),
+      undefined,
+    );
+    const actionArticle = page.locator(
+      `#${actionScope} [data-zen-notification-id="action"]`,
+    );
+    assert.doesNotMatch(
+      await actionArticle.evaluate(article => article.outerHTML),
+      /opaque-secret-token/,
+    );
+    await actionArticle.locator('.zen-notification-action').focus();
+    await page.locator(`#${actionScope}`).evaluate(scope => {
+      const source = scope.querySelector('button');
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'action-neighbor',
+          tone: 'info',
+          message: 'Neighbor',
+          announcement: 'none',
+          persistent: true,
+        },
+      }));
+    });
+    assert.equal(
+      await actionArticle.locator('.zen-notification-action').evaluate(
+        action => document.activeElement === action,
+      ),
+      true,
+    );
+    await actionArticle.locator('.zen-notification-action').click();
+    assert.deepEqual(
+      await page.evaluate(() => window.__notificationAction),
+      {
+        version: 1,
+        id: 'action',
+        token: 'opaque-secret-token',
+      },
+    );
+    await page.locator(`#${actionScope}`).evaluate(scope => {
+      const source = scope.querySelector('button');
+      source.dispatchEvent(new CustomEvent(
+        'zen-dismiss-notification',
+        {
+          bubbles: true,
+          composed: false,
+          detail: { version: 1, id: 'action' },
+        },
+      ));
+    });
+    await actionArticle.waitFor({ state: 'detached' });
+
+    await page.evaluate(() => {
+      const scope = document.createElement('zen-notifications');
+      scope.id = 'announcement-scope';
+      const source = document.createElement('button');
+      scope.append(source);
+      document.body.append(scope);
+      window.__announcements = [];
+      const region = scope.querySelector('[data-zen-live="polite"]');
+      new MutationObserver(() => {
+        if (region.textContent) {
+          window.__announcements.push(region.textContent);
+        }
+      }).observe(region, { childList: true });
+      for (let index = 0; index < 3; index++) {
+        source.dispatchEvent(new CustomEvent('zen-notify', {
+          bubbles: true,
+          composed: false,
+          detail: {
+            version: 1,
+            id: `announcement-${index}`,
+            tone: 'info',
+            message: `Announcement ${index}`,
+            announcement: 'polite',
+            persistent: true,
+          },
+        }));
+      }
+    });
+    await page.waitForFunction(() =>
+      window.__announcements?.length === 3
+    );
+    assert.deepEqual(
+      await page.evaluate(() => window.__announcements),
+      ['Announcement 0', 'Announcement 1', 'Announcement 2'],
+    );
+
+    const composedRejected = await page.evaluate(() => {
+      const scope = document.createElement('zen-notifications');
+      const source = document.createElement('button');
+      scope.append(source);
+      document.body.append(scope);
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: true,
+        detail: {
+          version: 1,
+          id: 'composed',
+          tone: 'info',
+          message: 'Must be rejected',
+          announcement: 'none',
+          persistent: true,
+        },
+      }));
+      return scope.size;
+    });
+    assert.equal(composedRejected, 0);
+
+    await page.evaluate(() => {
+      const scope = document.createElement('zen-notifications');
+      scope.id = 'focus-timer-scope';
+      const source = document.createElement('button');
+      scope.append(source);
+      document.body.append(scope);
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'focus-timer',
+          tone: 'warning',
+          message: 'Focus timer',
+          announcement: 'none',
+          durationMs: 300,
+          action: { token: 'focus-token', label: 'Keep focused' },
+        },
+      }));
+    });
+    const focusTimer = page.locator(
+      '#focus-timer-scope [data-zen-notification-id="focus-timer"]',
+    );
+    await focusTimer.locator('.zen-notification-action').focus();
+    await page.locator('#focus-timer-scope').evaluate(scope => {
+      const source = scope.querySelector(':scope > button');
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'focus-neighbor',
+          tone: 'info',
+          message: 'Focus neighbor',
+          announcement: 'none',
+          persistent: true,
+        },
+      }));
+    });
+    await page.waitForTimeout(500);
+    assert.equal(await focusTimer.count(), 1);
+    assert.equal(
+      await focusTimer.locator('.zen-notification-action').evaluate(
+        action => document.activeElement === action,
+      ),
+      true,
+    );
+    await page.mouse.move(0, 0);
+    await page.locator('#catalogMain').focus();
+    await page.waitForFunction(() =>
+      !document.querySelector(
+        '#focus-timer-scope [data-zen-notification-id="focus-timer"]',
+      )
+    );
+
+    await page.evaluate(() => {
+      const scope = document.createElement('zen-notifications');
+      scope.id = 'timer-scope';
+      const source = document.createElement('button');
+      scope.append(source);
+      document.body.append(scope);
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'timer',
+          tone: 'info',
+          message: 'Paused timer',
+          announcement: 'none',
+          durationMs: 300,
+        },
+      }));
+    });
+    const timerArticle = page.locator('#timer-scope article');
+    await timerArticle.hover();
+    await page.waitForTimeout(500);
+    assert.equal(await timerArticle.count(), 1);
+    await page.mouse.move(0, 0);
+    await page.waitForFunction(() =>
+      !document.querySelector('#timer-scope article')
+    );
+
+    await page.evaluate(() => {
+      const scope = document.createElement('zen-notifications');
+      scope.id = 'hidden-timer-scope';
+      const source = document.createElement('button');
+      scope.append(source);
+      document.body.append(scope);
+      source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'hidden-timer',
+          tone: 'info',
+          message: 'Hidden timer',
+          announcement: 'none',
+          durationMs: 300,
+        },
+      }));
+      Object.defineProperty(document, 'hidden', {
+        configurable: true,
+        value: true,
+      });
+      document.dispatchEvent(new Event('visibilitychange'));
+    });
+    await page.waitForTimeout(500);
+    assert.equal(
+      await page.locator('#hidden-timer-scope article').count(),
+      1,
+    );
+    await page.evaluate(() => {
+      Object.defineProperty(document, 'hidden', {
+        configurable: true,
+        value: false,
+      });
+      document.dispatchEvent(new Event('visibilitychange'));
+    });
+    await page.waitForFunction(() =>
+      !document.querySelector('#hidden-timer-scope article')
+    );
+
+    const isolated = await page.evaluate(() => {
+      const makeScope = id => {
+        const scope = document.createElement('zen-notifications');
+        scope.id = id;
+        const source = document.createElement('button');
+        scope.append(source);
+        document.body.append(scope);
+        return { scope, source };
+      };
+      const first = makeScope('scope-one');
+      const second = makeScope('scope-two');
+      first.source.dispatchEvent(new CustomEvent('zen-notify', {
+        bubbles: true,
+        composed: false,
+        detail: {
+          version: 1,
+          id: 'isolated',
+          tone: 'success',
+          message: 'Only first scope',
+          announcement: 'none',
+          persistent: true,
+        },
+      }));
+      return [first.scope.size, second.scope.size];
+    });
+    assert.deepEqual(isolated, [1, 0]);
+
+    const lightCanvas = await page.evaluate(() =>
+      getComputedStyle(document.documentElement)
+        .getPropertyValue('--zenbu-sys-color-surface-page')
+        .trim()
+    );
+    await page.locator('#themeToggle').click();
+    const darkCanvas = await page.evaluate(() =>
+      getComputedStyle(document.documentElement)
+        .getPropertyValue('--zenbu-sys-color-surface-page')
+        .trim()
+    );
+    assert.notEqual(lightCanvas, darkCanvas);
+    assert.equal(
+      await page.evaluate(() => localStorage.getItem('zen-theme')),
+      'dark',
+    );
+
+    assert.deepEqual(errors, []);
+    await context.close();
+
+    const darkContext = await browser.newContext({ colorScheme: 'dark' });
+    const darkPage = await darkContext.newPage();
+    await darkPage.goto(baseUrl, { waitUntil: 'networkidle' });
+    assert.equal(
+      await darkPage.locator('#themeToggle').getAttribute('aria-pressed'),
+      'true',
+    );
+    const systemDarkCanvas = await darkPage.evaluate(() =>
+      getComputedStyle(document.documentElement)
+        .getPropertyValue('--zenbu-sys-color-surface-page')
+        .trim()
+    );
+    await darkPage.locator('#themeToggle').click();
+    const explicitLightCanvas = await darkPage.evaluate(() =>
+      getComputedStyle(document.documentElement)
+        .getPropertyValue('--zenbu-sys-color-surface-page')
+        .trim()
+    );
+    assert.notEqual(systemDarkCanvas, explicitLightCanvas);
+    await darkContext.close();
+
+    const mobileContext = await browser.newContext({
+      colorScheme: 'light',
+      viewport: { width: 390, height: 844 },
+    });
+    const mobilePage = await mobileContext.newPage();
+    const mobileErrors = [];
+    mobilePage.on('pageerror', error => {
+      mobileErrors.push(error.stack || error.message);
+    });
+    mobilePage.on('console', message => {
+      if (message.type() === 'error') mobileErrors.push(message.text());
+    });
+    await mobilePage.goto(baseUrl, { waitUntil: 'networkidle' });
+    await mobilePage.waitForFunction(() =>
+      customElements.get('zen-date-picker') &&
+      document.querySelectorAll(
+        '.catalog-nav[aria-label="Components"] a',
+      ).length === 70
+    );
+    const mobileFailures = await mobilePage.evaluate(() => {
+      const routes = [
+        '/',
+        '/tokens',
+        '/icons',
+        ...[...document.querySelectorAll(
+          '.catalog-nav[aria-label="Components"] a',
+        )].map(link => new URL(link.href).pathname),
+      ];
+      const failures = [];
+      for (const route of routes) {
+        history.replaceState({}, '', route);
+        window.dispatchEvent(new PopStateEvent('popstate'));
+        const page = document.querySelector(
+          '[data-catalog-page]:not([hidden])',
+        );
+        if (!page ||
+            document.documentElement.scrollWidth > innerWidth + 1 ||
+            page.getBoundingClientRect().right > innerWidth + 1) {
+          failures.push(route);
+        }
+      }
+      return failures;
+    });
+    assert.deepEqual(mobileFailures, []);
+    await mobilePage.goto(`${baseUrl}/components/date-picker`, {
+      waitUntil: 'networkidle',
+    });
+    await mobilePage.locator(
+      'zen-date-picker [data-zen-date-trigger]',
+    ).click();
+    const mobileCalendarBounds = await mobilePage.locator(
+      'zen-date-picker [data-zen-calendar-panel]',
+    ).evaluate(panel => {
+      const bounds = panel.getBoundingClientRect();
+      return {
+        bottom: bounds.bottom,
+        left: bounds.left,
+        right: bounds.right,
+        top: bounds.top,
+      };
+    });
+    assert.ok(mobileCalendarBounds.left >= 0);
+    assert.ok(mobileCalendarBounds.right <= 390);
+    assert.ok(mobileCalendarBounds.top >= 0);
+    assert.ok(mobileCalendarBounds.bottom <= 844);
+    assert.deepEqual(mobileErrors, []);
+    await mobileContext.close();
+  } finally {
+    if (browser) await browser.close();
+    await stopProcess(server);
+  }
+})().catch(error => {
+  console.error(error.stack || error);
+  process.exitCode = 1;
+});
--- a/design_system/test/design_system_policy_test.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/design_system/test/design_system_policy_test.js	Wed Aug 05 05:25:40 2026 -0700
@@ -7,7 +7,8 @@
 assert.ok(RUNFILES);
 assert.ok(WORKSPACE);
 
-const sourceRoot = path.join(RUNFILES, WORKSPACE, 'design_system/src');
+const designRoot = path.join(RUNFILES, WORKSPACE, 'design_system');
+const sourceRoot = path.join(designRoot, 'src');
 const files = [];
 
 function walk(directory) {
@@ -19,6 +20,26 @@
 }
 
 walk(sourceRoot);
+function listMarkdown(directory) {
+  const markdown = [];
+  for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
+    const entryPath = path.join(directory, entry.name);
+    if (entry.isDirectory()) markdown.push(...listMarkdown(entryPath));
+    else if (entry.name.endsWith('.md')) markdown.push(entryPath);
+  }
+  return markdown;
+}
+const documentationFiles = [
+  ...fs.readdirSync(designRoot)
+    .filter(name => name.endsWith('.md'))
+    .map(name => path.join(designRoot, name)),
+  ...listMarkdown(path.join(designRoot, 'wiki')),
+];
+const namingFiles = [
+  ...files,
+  ...documentationFiles,
+  path.join(designRoot, 'main.c'),
+];
 
 function validateCallableDocumentation(
   relative,
@@ -58,13 +79,18 @@
 ].join('|'), 'gi');
 const forbiddenGlyph = /[×←→↑↓+◆◇✓✔✕✖★☆⚠]/gu;
 const pictographic = /\p{Extended_Pictographic}/gu;
+const borrowedProductName =
+  /(?:shadcn|storybook|sonner|radix|tailwind|react)/gi;
 const failures = [];
 
 for (const file of files) {
   const relative = path.relative(sourceRoot, file);
   const source = fs.readFileSync(file, 'utf8');
 
-  if (relative !== 'styles/tokens.css') {
+  if (![
+    'styles/reference.css',
+    'styles/tokens.css',
+  ].includes(relative)) {
     for (const match of source.matchAll(rawColor)) {
       failures.push(
         `${relative}:${source.slice(0, match.index).split('\n').length} ` +
@@ -157,7 +183,7 @@
            !/(?:collapse|image|radius|spacing|style|width)/.test(property));
         if (!colorProperty) continue;
         const withoutTokens = value.replace(
-          /var\(\s*--zen-[\w-]+\s*\)/g,
+          /var\(\s*--(?:zenbu|zen)-[\w-]+\s*\)/g,
           '',
         );
         const words = withoutTokens.toLowerCase()
@@ -168,7 +194,7 @@
             )) {
           failures.push(
             `${relative}:${css.slice(0, declaration.index).split('\n').length} ` +
-            `${property} must use a --zen-* token`,
+            `${property} must use a --zenbu-sys-* token`,
           );
         }
       }
@@ -223,6 +249,54 @@
   }
 }
 
+const cssFiles = files.filter(file => file.endsWith('.css'));
+const zenbuDeclarations = new Set();
+for (const file of cssFiles) {
+  const source = fs.readFileSync(file, 'utf8');
+  for (const match of source.matchAll(/(--zenbu-[\w-]+)\s*:/g)) {
+    zenbuDeclarations.add(match[1]);
+  }
+}
+for (const file of cssFiles) {
+  const relative = path.relative(sourceRoot, file);
+  const source = fs.readFileSync(file, 'utf8');
+  for (const match of source.matchAll(/var\(\s*(--zenbu-[\w-]+)/g)) {
+    if (!zenbuDeclarations.has(match[1])) {
+      failures.push(`${relative} references unknown token ${match[1]}`);
+    }
+  }
+  if (![
+    'styles/reference.css',
+    'styles/semantic.css',
+    'styles/themes.css',
+    'styles/tokens.css',
+  ].includes(relative)) {
+    for (const match of source.matchAll(
+      /var\(\s*(--zenbu-ref-color-[\w-]+)/g,
+    )) {
+      failures.push(
+        `${relative} consumes reference color ${match[1]} directly`,
+      );
+    }
+  }
+  if (![
+    'styles/themes.css',
+    'styles/tokens.css',
+  ].includes(relative) && /var\(\s*--zen-/.test(source)) {
+    failures.push(`${relative} consumes deprecated --zen-* tokens`);
+  }
+}
+
+for (const file of namingFiles) {
+  const source = fs.readFileSync(file, 'utf8');
+  for (const match of source.matchAll(borrowedProductName)) {
+    failures.push(
+      `${path.relative(designRoot, file)} uses borrowed product name ` +
+      JSON.stringify(match[0]),
+    );
+  }
+}
+
 for (const file of files.filter(file =>
   file.endsWith('.js')
 )) {
--- a/design_system/test/storybook_test.js	Tue Aug 04 16:49:11 2026 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1741 +0,0 @@
-const assert = require('node:assert/strict');
-const http = require('node:http');
-const net = require('node:net');
-const path = require('node:path');
-const { spawn } = require('node:child_process');
-
-const RUNFILES = process.env.JS_BINARY__RUNFILES;
-const WORKSPACE = process.env.JS_BINARY__WORKSPACE;
-const runfilesWorkspace = path.join(RUNFILES, WORKSPACE);
-const playwrightPath = path.join(
-  runfilesWorkspace,
-  'hg-web/e2e/node_modules/playwright-core',
-);
-const { chromium } = require(playwrightPath);
-
-function findFreePort() {
-  return new Promise((resolve, reject) => {
-    const server = net.createServer();
-    server.once('error', reject);
-    server.listen(0, '127.0.0.1', () => {
-      const address = server.address();
-      server.close(error => {
-        if (error) reject(error);
-        else resolve(String(address.port));
-      });
-    });
-  });
-}
-
-async function stopProcess(child) {
-  if (!child || child.exitCode !== null) return;
-  child.kill('SIGTERM');
-  await new Promise(resolve => {
-    const timer = setTimeout(() => {
-      if (child.exitCode === null) child.kill('SIGKILL');
-    }, 3000);
-    child.once('exit', () => {
-      clearTimeout(timer);
-      resolve();
-    });
-  });
-}
-
-async function waitForServer(server, baseUrl, logs) {
-  const deadline = Date.now() + 15000;
-  while (Date.now() < deadline) {
-    if (server.exitCode !== null) {
-      throw new Error(`Server exited with ${server.exitCode}\n${logs.join('')}`);
-    }
-    try {
-      const response = await fetch(baseUrl);
-      if (response.ok) return;
-    } catch {
-      // Keep waiting.
-    }
-    await new Promise(resolve => setTimeout(resolve, 100));
-  }
-  throw new Error(`Server startup timed out\n${logs.join('')}`);
-}
-
-function requestRawPath(port, requestPath) {
-  return new Promise((resolve, reject) => {
-    const request = http.request({
-      host: '127.0.0.1',
-      port,
-      method: 'GET',
-      path: requestPath,
-      agent: false,
-    }, response => {
-      response.resume();
-      response.on('end', () => resolve(response.statusCode));
-    });
-    request.on('error', reject);
-    request.end();
-  });
-}
-
-(async () => {
-  assert.ok(RUNFILES);
-  assert.ok(WORKSPACE);
-  const serverBinary = path.join(
-    runfilesWorkspace,
-    'design_system/design_system_server',
-  );
-  const chromiumPath = path.resolve(process.env.CHROMIUM_PATH);
-  const port = await findFreePort();
-  const baseUrl = `http://127.0.0.1:${port}`;
-  const logs = [];
-  let server;
-  let browser;
-
-  try {
-    const invalidServer = spawn(serverBinary, [], {
-      cwd: runfilesWorkspace,
-      env: {
-        ...process.env,
-        DESIGN_SYSTEM_PORT: 'not-a-port',
-      },
-      stdio: ['ignore', 'pipe', 'pipe'],
-    });
-    const invalidExit = await new Promise(resolve => {
-      invalidServer.once('exit', (code, signal) => resolve({ code, signal }));
-    });
-    assert.equal(invalidExit.code, 1);
-    assert.equal(invalidExit.signal, null);
-
-    server = spawn(serverBinary, [], {
-      cwd: runfilesWorkspace,
-      env: {
-        ...process.env,
-        DESIGN_SYSTEM_PORT: port,
-      },
-      stdio: ['ignore', 'pipe', 'pipe'],
-    });
-    server.stdout.on('data', chunk => logs.push(chunk.toString()));
-    server.stderr.on('data', chunk => logs.push(chunk.toString()));
-    await waitForServer(server, baseUrl, logs);
-    assert.equal(await requestRawPath(port, '/../../MODULE.bazel'), 400);
-
-    for (const route of [
-      '/',
-      '/tokens',
-      '/icons',
-      '/components',
-      '/components/button',
-      '/components/card',
-      '/components/alert',
-      '/components/field',
-      '/components/notifications',
-      '/components/stack',
-    ]) {
-      const response = await fetch(`${baseUrl}${route}`);
-      assert.equal(response.status, 200, route);
-      assert.match(
-        response.headers.get('content-type') || '',
-        /^text\/html/,
-      );
-    }
-    for (const asset of [
-      '/styles/tokens.css',
-      '/styles/themes.css',
-      '/styles/components.css',
-      '/styles/shadcn.css',
-      '/components/index.js',
-      '/components/icon.js',
-      '/catalog.js',
-      '/storybook.js',
-    ]) {
-      const response = await fetch(`${baseUrl}${asset}`);
-      assert.equal(response.status, 200, asset);
-      assert.ok((await response.text()).length > 100, asset);
-    }
-
-    browser = await chromium.launch({
-      executablePath: chromiumPath,
-      headless: true,
-      args: ['--no-sandbox'],
-    });
-    const context = await browser.newContext({ colorScheme: 'light' });
-    const page = await context.newPage();
-    const errors = [];
-    const devtools = await context.newCDPSession(page);
-    await devtools.send('Runtime.enable');
-    devtools.on('Runtime.exceptionThrown', event => {
-      const exception = event.exceptionDetails;
-      errors.push(
-        `${exception.text}: ${exception.exception?.description || ''} ` +
-        `${exception.url || ''}:${exception.lineNumber + 1}`,
-      );
-    });
-    page.on('pageerror', error => errors.push(error.stack || error.message));
-    page.on('console', message => {
-      if (message.type() === 'error') {
-        const location = message.location();
-        errors.push(
-          `${message.text()} ${location.url || ''}:${location.lineNumber + 1}`,
-        );
-      }
-    });
-    page.on('response', response => {
-      if (response.status() >= 400) {
-        errors.push(`${response.status()} ${response.url()}`);
-      }
-    });
-
-    await page.goto(`${baseUrl}/components/button`, {
-      waitUntil: 'networkidle',
-    });
-    try {
-      await page.waitForFunction(
-        () => customElements.get('zen-button') &&
-          customElements.get('zen-story'),
-        undefined,
-        { timeout: 5000 },
-      );
-    } catch (error) {
-      throw new Error(`${error.message}\n${errors.join('\n')}`);
-    }
-    const catalogState = await page.evaluate(async () => {
-      const links = [
-        ...document.querySelectorAll(
-          '.catalog-nav[aria-label="Components"] a',
-        ),
-      ];
-      const elements = [...new Set(
-        links.map(link => link.dataset.zenElement).filter(Boolean),
-      )];
-      const statuses = await Promise.all(
-        links.map(async link => (await fetch(link.href)).status),
-      );
-      return {
-        cards: document.querySelectorAll('.component-grid > a').length,
-        elements,
-        links: links.length,
-        missing: elements.filter(name => !customElements.get(name)),
-        routes: links.map(link => new URL(link.href).pathname),
-        statuses,
-      };
-    });
-    assert.equal(catalogState.cards, 66);
-    assert.equal(catalogState.links, 66);
-    assert.equal(catalogState.elements.length, 65);
-    assert.deepEqual(catalogState.missing, []);
-    assert.deepEqual(
-      [...new Set(catalogState.statuses)],
-      [200],
-    );
-    const brokenCatalogPages = await page.evaluate(routes => {
-      const failures = [];
-      for (const route of ['/', '/tokens', '/icons', '/components', ...routes]) {
-        history.replaceState({}, '', route);
-        window.dispatchEvent(new PopStateEvent('popstate'));
-        const visible = [
-          ...document.querySelectorAll('[data-catalog-page]:not([hidden])'),
-        ];
-        const expected = route === '/' || route === '/components'
-          ? 'overview'
-          : route.slice(route.lastIndexOf('/') + 1);
-        if (visible.length !== 1 ||
-            visible[0].dataset.catalogPage !== expected ||
-            !visible[0].querySelector('h1')?.textContent.trim()) {
-          failures.push(route);
-          continue;
-        }
-        if (route.startsWith('/components/')) {
-          const story = visible[0].querySelector('zen-story');
-          const canvas = story?.querySelector('.story-canvas');
-          const source = story?.querySelector('pre code');
-          if (!story || !canvas?.children.length ||
-              !source?.textContent.trim()) {
-            failures.push(`${route}:empty-story`);
-          }
-        }
-      }
-      history.replaceState({}, '', '/components/button');
-      window.dispatchEvent(new PopStateEvent('popstate'));
-      return failures;
-    }, catalogState.routes);
-    assert.deepEqual(brokenCatalogPages, []);
-    await page.keyboard.press('/');
-    assert.equal(
-      await page.locator('#componentSearch').evaluate(
-        input => document.activeElement === input,
-      ),
-      true,
-    );
-    await page.locator('#componentSearch').fill('date');
-    assert.equal(
-      await page.locator(
-        '.catalog-nav[aria-label="Components"] a:not([hidden])',
-      ).count(),
-      2,
-    );
-    assert.equal(
-      await page.locator('.component-grid > a:not([hidden])').count(),
-      2,
-    );
-    assert.match(
-      await page.locator('#componentSearchStatus').textContent(),
-      /^2 components found$/,
-    );
-    await page.locator('#componentSearch').press('Escape');
-    assert.equal(await page.locator('#componentSearch').inputValue(), '');
-    assert.equal(
-      await page.locator(
-        '.catalog-nav[aria-label="Components"] a:not([hidden])',
-      ).count(),
-      66,
-    );
-    await page.locator('#componentSearch').fill('stack');
-    assert.equal(
-      await page.locator(
-        '.catalog-nav[aria-label="Components"] a[href="/components/stack"]',
-      ).getAttribute('hidden'),
-      null,
-    );
-    assert.equal(
-      await page.locator(
-        '.component-grid > a[href="/components/stack"]',
-      ).getAttribute('hidden'),
-      null,
-    );
-    await page.locator('#componentSearch').press('Escape');
-    assert.equal(
-      await page.locator('[data-catalog-page="button"]').isVisible(),
-      true,
-    );
-    assert.equal(
-      await page.locator('.catalog-sidebar a[href="/components/button"]').getAttribute('aria-current'),
-      'page',
-    );
-    assert.match(
-      await page.locator('zen-story pre').first().textContent(),
-      /<zen-button>/,
-    );
-    assert.equal(
-      await page.locator('zen-button[loading]').getAttribute('inert'),
-      null,
-    );
-    assert.equal(
-      await page.locator('zen-button[loading] button').getAttribute('aria-disabled'),
-      'true',
-    );
-    assert.equal(
-      await page.locator('zen-button[loading] button').getAttribute('aria-busy'),
-      'true',
-    );
-    await page.evaluate(() => {
-      window.__loadingClicks = 0;
-      document.querySelector('zen-button[loading] button')
-        .addEventListener('click', () => window.__loadingClicks++);
-    });
-    await page.locator('zen-button[loading] button').evaluate(
-      button => button.click(),
-    );
-    assert.equal(await page.evaluate(() => window.__loadingClicks), 0);
-    await page.locator('zen-button[loading] button').focus();
-    assert.equal(
-      await page.locator('zen-button[loading] button').evaluate(
-        button => document.activeElement === button,
-      ),
-      true,
-    );
-    await page.keyboard.press('Tab');
-    assert.equal(
-      await page.locator('zen-button[loading] button').evaluate(
-        button => document.activeElement === button,
-      ),
-      false,
-    );
-    const nativeDisabledPreserved = await page.evaluate(async () => {
-      const wrapper = document.createElement('zen-button');
-      const button = document.createElement('button');
-      button.disabled = true;
-      button.textContent = 'Native disabled';
-      wrapper.append(button);
-      document.body.append(wrapper);
-      await customElements.whenDefined('zen-button');
-      wrapper.setAttribute('disabled', '');
-      wrapper.removeAttribute('disabled');
-      return button.disabled;
-    });
-    assert.equal(nativeDisabledPreserved, true);
-    const replacementButtonState = await page.evaluate(async () => {
-      const wrapper = document.createElement('zen-button');
-      wrapper.setAttribute('disabled', '');
-      const first = document.createElement('button');
-      first.textContent = 'First';
-      wrapper.append(first);
-      document.body.append(wrapper);
-      await new Promise(resolve => setTimeout(resolve));
-      const second = document.createElement('button');
-      second.textContent = 'Second';
-      wrapper.replaceChildren(second);
-      await new Promise(resolve => setTimeout(resolve));
-      return {
-        firstDisabled: first.disabled,
-        secondAriaDisabled: second.getAttribute('aria-disabled'),
-        wrapperInert: wrapper.hasAttribute('inert'),
-      };
-    });
-    assert.equal(replacementButtonState.firstDisabled, false);
-    assert.equal(replacementButtonState.secondAriaDisabled, 'true');
-    assert.equal(replacementButtonState.wrapperInert, false);
-    const modifiedClickAllowed = await page.evaluate(() => {
-      const link = document.querySelector(
-        '.catalog-sidebar a[href="/components/card"]',
-      );
-      return link.dispatchEvent(new MouseEvent('click', {
-        bubbles: true,
-        cancelable: true,
-        button: 0,
-        ctrlKey: true,
-      }));
-    });
-    assert.equal(modifiedClickAllowed, true);
-
-    await page.goto(`${baseUrl}/icons`, { waitUntil: 'networkidle' });
-    const iconCount = await page.locator('#iconGrid figure').count();
-    assert.ok(iconCount >= 30);
-    assert.equal(
-      await page.locator('#iconGrid figure zen-icon > svg').count(),
-      iconCount,
-    );
-    const iconFallback = await page.evaluate(() => {
-      const icon = document.createElement('zen-icon');
-      icon.setAttribute('name', 'not-a-real-icon');
-      icon.setAttribute('label', 'Missing icon fallback');
-      document.body.append(icon);
-      return {
-        fallback: icon.dataset.zenIcon,
-        hidden: icon.getAttribute('aria-hidden'),
-        label: icon.getAttribute('aria-label'),
-        role: icon.getAttribute('role'),
-      };
-    });
-    assert.deepEqual(iconFallback, {
-      fallback: 'alert',
-      hidden: null,
-      label: 'Missing icon fallback',
-      role: 'img',
-    });
-
-    await page.goto(`${baseUrl}/tokens`, { waitUntil: 'networkidle' });
-    const colorTokenState = await page.evaluate(() => {
-      const root = document.documentElement;
-      const value = name => getComputedStyle(root)
-        .getPropertyValue(`--zen-color-${name}`)
-        .trim();
-      const families = [
-        'neutral',
-        'red',
-        'orange',
-        'amber',
-        'green',
-        'teal',
-        'blue',
-        'violet',
-        'rose',
-        'brown',
-      ];
-      const steps = [
-        '50',
-        '100',
-        '200',
-        '300',
-        '400',
-        '500',
-        '600',
-        '700',
-        '800',
-        '900',
-        '950',
-      ];
-      const rampsComplete = families.every(family =>
-        steps.every(step => value(`${family}-${step}`))
-      );
-      const data = Array.from(
-        { length: 10 },
-        (_, index) => value(`data-${index + 1}`),
-      );
-      const materials = [
-        'paper',
-        'washi',
-        'linen',
-        'sumi',
-        'brick',
-        'persimmon',
-        'ochre',
-        'moss',
-        'patina',
-        'indigo',
-        'plum',
-        'clay',
-        'wood',
-      ].map(value);
-      const lightMuted = value('surface-muted');
-      root.dataset.zenTheme = 'dark';
-      const darkMuted = value('surface-muted');
-      const darkData = Array.from(
-        { length: 10 },
-        (_, index) => value(`data-${index + 1}`),
-      );
-      const themes = ['paper', 'ink', 'playful'].map(theme => {
-        root.dataset.zenTheme = theme;
-        const channels = value => value.match(/\d+(?:\.\d+)?/g)
-          .slice(0, 3)
-          .map(Number);
-        const luminance = value => {
-          const converted = channels(value).map(channel => {
-            const normalized = channel / 255;
-            return normalized <= 0.04045
-              ? normalized / 12.92
-              : ((normalized + 0.055) / 1.055) ** 2.4;
-          });
-          return converted[0] * 0.2126 +
-            converted[1] * 0.7152 +
-            converted[2] * 0.0722;
-        };
-        const contrasts = [
-          'info',
-          'success',
-          'warning',
-          'danger',
-        ].map(tone => {
-          const probe = document.createElement('span');
-          probe.style.background = `var(--zen-color-${tone})`;
-          probe.style.color = `var(--zen-color-on-${tone})`;
-          document.body.append(probe);
-          const probeStyle = getComputedStyle(probe);
-          const foreground = luminance(probeStyle.color);
-          const background = luminance(probeStyle.backgroundColor);
-          const contrast = (Math.max(foreground, background) + 0.05) /
-            (Math.min(foreground, background) + 0.05);
-          probe.remove();
-          return contrast;
-        });
-        return {
-          canvas: value('canvas'),
-          contrast: Math.min(...contrasts),
-          font: getComputedStyle(root)
-            .getPropertyValue('--zen-font-sans')
-            .trim(),
-          name: theme,
-          radius: getComputedStyle(root)
-            .getPropertyValue('--zen-radius-lg')
-            .trim(),
-        };
-      });
-      delete root.dataset.zenTheme;
-      return {
-        darkData,
-        darkMuted,
-        data,
-        lightMuted,
-        materials,
-        rampsComplete,
-        themes,
-      };
-    });
-    assert.equal(colorTokenState.rampsComplete, true);
-    assert.equal(new Set(colorTokenState.materials).size, 13);
-    assert.equal(new Set(colorTokenState.data).size, 10);
-    assert.equal(new Set(colorTokenState.darkData).size, 10);
-    assert.notDeepEqual(colorTokenState.data, colorTokenState.darkData);
-    assert.equal(
-      new Set(colorTokenState.themes.map(theme => theme.canvas)).size,
-      3,
-    );
-    assert.notEqual(
-      colorTokenState.themes.find(theme => theme.name === 'paper').radius,
-      colorTokenState.themes.find(theme => theme.name === 'playful').radius,
-    );
-    assert.ok(
-      colorTokenState.themes.every(theme => theme.contrast >= 4.5),
-      JSON.stringify(colorTokenState.themes),
-    );
-    assert.notEqual(
-      colorTokenState.lightMuted,
-      colorTokenState.darkMuted,
-    );
-    assert.equal(await page.locator('.palette-grid > div').count(), 13);
-    assert.equal(await page.locator('.data-palette > span').count(), 10);
-
-    await page.goto(`${baseUrl}/components/field`, {
-      waitUntil: 'networkidle',
-    });
-    const fieldWiring = await page.locator('zen-field').first().evaluate(field => {
-      const label = field.querySelector('label');
-      const input = field.querySelector('input');
-      const help = field.querySelector('small');
-      input.checkValidity();
-      return {
-        describedBy: input.getAttribute('aria-describedby'),
-        helpId: help.id,
-        inputId: input.id,
-        invalid: field.hasAttribute('data-invalid'),
-        labelFor: label.htmlFor,
-      };
-    });
-    assert.ok(fieldWiring.inputId);
-    assert.equal(fieldWiring.labelFor, fieldWiring.inputId);
-    assert.equal(fieldWiring.describedBy, fieldWiring.helpId);
-    assert.equal(fieldWiring.invalid, true);
-    await page.locator('zen-field input').first().focus();
-    assert.equal(
-      await page.locator('zen-field input').first().evaluate(
-        input => getComputedStyle(input).outlineStyle,
-      ),
-      'none',
-    );
-    const replacementField = await page.locator('zen-field').first().evaluate(
-      async field => {
-        const label = field.querySelector('label');
-        const oldInput = field.querySelector('input');
-        const blocker = document.createElement('div');
-        blocker.id = 'zen-field-3';
-        document.body.append(blocker);
-        const nextInput = document.createElement('input');
-        nextInput.required = true;
-        oldInput.replaceWith(nextInput);
-        await new Promise(resolve => setTimeout(resolve));
-        oldInput.dispatchEvent(new Event('invalid'));
-        const help = field.querySelector('small');
-        nextInput.id = 'replacement-email';
-        help.id = 'replacement-help';
-        await new Promise(resolve => setTimeout(resolve));
-        return {
-          describedBy: nextInput.getAttribute('aria-describedby'),
-          helpId: help.id,
-          labelFor: label.htmlFor,
-          nextId: nextInput.id,
-          blockerId: blocker.id,
-        };
-      },
-    );
-    assert.ok(replacementField.nextId);
-    assert.notEqual(replacementField.nextId, replacementField.blockerId);
-    assert.equal(replacementField.labelFor, replacementField.nextId);
-    assert.equal(replacementField.describedBy, replacementField.helpId);
-
-    await page.goto(`${baseUrl}/components/alert`, {
-      waitUntil: 'networkidle',
-    });
-    await page.evaluate(() => {
-      window.__dismissed = 0;
-      document.addEventListener('zen-dismiss', () => {
-        window.__dismissed++;
-      });
-    });
-    const dismissible = page.locator('zen-alert[dismissible]');
-    assert.equal(await dismissible.getAttribute('role'), 'alert');
-    await dismissible.locator('[data-zen-dismiss]').click();
-    assert.equal(await dismissible.count(), 0);
-    assert.equal(await page.evaluate(() => window.__dismissed), 1);
-    const authoredDismissState = await page.evaluate(async () => {
-      const alert = document.createElement('zen-alert');
-      alert.setAttribute('dismissible', '');
-      const message = document.createElement('p');
-      message.textContent = 'Authored dismiss control';
-      const dismiss = document.createElement('button');
-      dismiss.dataset.zenDismiss = '';
-      alert.append(message, dismiss);
-      document.body.append(alert);
-      await new Promise(resolve => setTimeout(resolve));
-      let events = 0;
-      alert.addEventListener('zen-dismiss', () => events++);
-      alert.removeAttribute('dismissible');
-      dismiss.click();
-      return {
-        connected: alert.isConnected,
-        events,
-      };
-    });
-    assert.equal(authoredDismissState.connected, true);
-    assert.equal(authoredDismissState.events, 0);
-
-    await page.goto(`${baseUrl}/components/accordion`, {
-      waitUntil: 'networkidle',
-    });
-    const accordion = page.locator('zen-accordion').first();
-    const disclosureIcon = accordion.locator(
-      'summary > zen-icon[data-zen-disclosure-icon]',
-    ).nth(1);
-    const collapsedDisclosure = await disclosureIcon.evaluate(icon => {
-      const style = getComputedStyle(icon);
-      return {
-        duration: style.transitionDuration,
-        transform: style.transform,
-      };
-    });
-    assert.notEqual(collapsedDisclosure.duration, '0s');
-    await accordion.locator('summary').nth(1).click();
-    await page.waitForTimeout(250);
-    assert.notEqual(
-      await disclosureIcon.evaluate(icon => getComputedStyle(icon).transform),
-      collapsedDisclosure.transform,
-    );
-    assert.equal(
-      await accordion.locator('details').first().getAttribute('open'),
-      null,
-    );
-    assert.equal(
-      await accordion.locator('details').nth(1).getAttribute('open'),
-      '',
-    );
-    await accordion.locator('summary').nth(1).press('ArrowUp');
-    assert.equal(
-      await accordion.locator('summary').first().evaluate(
-        summary => document.activeElement === summary,
-      ),
-      true,
-    );
-
-    await page.goto(`${baseUrl}/components/aspect-ratio`, {
-      waitUntil: 'networkidle',
-    });
-    const aspectColors = await page.locator('.demo-media').evaluate(media => {
-      const style = getComputedStyle(media);
-      const probe = document.createElement('span');
-      probe.style.background = 'var(--zen-color-surface-muted)';
-      document.body.append(probe);
-      const token = getComputedStyle(probe).backgroundColor;
-      probe.remove();
-      return {
-        background: style.backgroundColor,
-        image: style.backgroundImage,
-        token,
-      };
-    });
-    assert.equal(aspectColors.image, 'none');
-    assert.equal(aspectColors.background, aspectColors.token);
-
-    await page.goto(`${baseUrl}/components/tabs`, {
-      waitUntil: 'networkidle',
-    });
-    await page.evaluate(() => {
-      window.__tabValue = null;
-      document.querySelector('zen-tabs').addEventListener(
-        'zen-change',
-        event => {
-          window.__tabValue = event.detail.value;
-        },
-      );
-    });
-    await page.locator('zen-tabs [role="tab"]').nth(1).click();
-    assert.equal(
-      await page.locator('zen-tabs [role="tab"]').nth(1)
-        .getAttribute('aria-selected'),
-      'true',
-    );
-    assert.equal(
-      await page.locator('zen-tabs [role="tabpanel"]').nth(1)
-        .getAttribute('hidden'),
-      null,
-    );
-    assert.equal(await page.evaluate(() => window.__tabValue), 'history');
-
-    await page.goto(`${baseUrl}/components/dialog`, {
-      waitUntil: 'networkidle',
-    });
-    await page.locator('zen-dialog [data-zen-trigger]').click();
-    assert.equal(await page.locator('zen-dialog dialog').getAttribute('open'), '');
-    await page.locator('zen-dialog [data-zen-close]').click();
-    assert.equal(await page.locator('zen-dialog dialog').getAttribute('open'), null);
-    const dynamicOverlays = await page.evaluate(async () => {
-      const dialogHost = document.createElement('zen-dialog');
-      const popoverHost = document.createElement('zen-popover');
-      const tooltipHost = document.createElement('zen-tooltip');
-      const menuHost = document.createElement('zen-dropdown-menu');
-      document.body.append(dialogHost, popoverHost, tooltipHost, menuHost);
-
-      const dialogTrigger = document.createElement('button');
-      dialogTrigger.type = 'button';
-      dialogTrigger.dataset.zenTrigger = '';
-      const dialog = document.createElement('dialog');
-      dialogHost.append(dialogTrigger, dialog);
-
-      const popoverTrigger = document.createElement('button');
-      popoverTrigger.type = 'button';
-      popoverTrigger.dataset.zenTrigger = '';
-      const popover = document.createElement('div');
-      popover.dataset.zenContent = '';
-      popoverHost.append(popoverTrigger, popover);
-
-      const tooltipTrigger = document.createElement('button');
-      tooltipTrigger.type = 'button';
-      tooltipTrigger.dataset.zenTrigger = '';
-      const tooltip = document.createElement('span');
-      tooltip.dataset.zenContent = '';
-      tooltipHost.append(tooltipTrigger, tooltip);
-
-      const menuTrigger = document.createElement('button');
-      menuTrigger.type = 'button';
-      menuTrigger.dataset.zenTrigger = '';
-      const menu = document.createElement('div');
-      menu.setAttribute('role', 'menu');
-      const item = document.createElement('button');
-      item.type = 'button';
-      item.setAttribute('role', 'menuitem');
-      menu.append(item);
-      menuHost.append(menuTrigger, menu);
-
-      await new Promise(resolve => setTimeout(resolve));
-      dialogTrigger.click();
-      const dialogOpen = dialog.open;
-      dialog.close();
-      popoverTrigger.click();
-      menuTrigger.click();
-      tooltipTrigger.focus();
-      await new Promise(resolve => setTimeout(resolve, 375));
-      return {
-        dialogControlled: Boolean(dialogTrigger.getAttribute('aria-controls')),
-        dialogOpen,
-        menuOpen: !menu.hidden,
-        popoverExpanded: popoverTrigger.getAttribute('aria-expanded'),
-        tooltipOpen: !tooltip.hidden,
-      };
-    });
-    assert.deepEqual(dynamicOverlays, {
-      dialogControlled: true,
-      dialogOpen: true,
-      menuOpen: true,
-      popoverExpanded: 'true',
-      tooltipOpen: true,
-    });
-
-    await page.goto(`${baseUrl}/components/dropdown-menu`, {
-      waitUntil: 'networkidle',
-    });
-    const dropdownTrigger = page.locator(
-      'zen-dropdown-menu [data-zen-trigger]',
-    );
-    await dropdownTrigger.click();
-    assert.equal(
-      await page.locator('zen-dropdown-menu [role="menu"]')
-        .getAttribute('hidden'),
-      null,
-    );
-    await page.keyboard.press('Escape');
-    assert.equal(
-      await page.locator('zen-dropdown-menu [role="menu"]')
-        .getAttribute('hidden'),
-      '',
-    );
-    assert.equal(
-      await dropdownTrigger.evaluate(
-        trigger => document.activeElement === trigger,
-      ),
-      true,
-    );
-    await dropdownTrigger.click();
-    await page.locator('zen-dropdown-menu [role="menuitem"]').first().click();
-    assert.equal(
-      await dropdownTrigger.evaluate(
-        trigger => document.activeElement === trigger,
-      ),
-      true,
-    );
-
-    await page.goto(`${baseUrl}/components/combobox`, {
-      waitUntil: 'networkidle',
-    });
-    const comboboxInput = page.locator('zen-combobox input');
-    await comboboxInput.fill('seo');
-    assert.equal(
-      await page.locator('zen-combobox [role="option"]:not([hidden])').count(),
-      1,
-    );
-    await comboboxInput.press('ArrowDown');
-    await comboboxInput.press('Enter');
-    assert.equal(await comboboxInput.inputValue(), 'seobeo');
-    assert.equal(
-      await page.locator('zen-combobox [role="listbox"]')
-        .getAttribute('hidden'),
-      '',
-    );
-
-    await page.goto(`${baseUrl}/components/date-picker`, {
-      waitUntil: 'networkidle',
-    });
-    const dateInput = page.locator('zen-date-picker input[type="date"]');
-    assert.equal(await dateInput.getAttribute('aria-hidden'), 'true');
-    assert.equal(
-      await dateInput.evaluate(input => getComputedStyle(input).position),
-      'absolute',
-    );
-    await page.evaluate(() => {
-      window.__dateValue = null;
-      document.querySelector('zen-date-picker').addEventListener(
-        'zen-change',
-        event => {
-          window.__dateValue = event.detail.value;
-        },
-      );
-    });
-    const dateTrigger = page.locator(
-      'zen-date-picker [data-zen-date-trigger]',
-    );
-    await dateTrigger.click();
-    assert.equal(
-      await page.locator('zen-date-picker [data-zen-calendar-panel]')
-        .getAttribute('hidden'),
-      null,
-    );
-    assert.equal(
-      await page.locator(
-        'zen-date-picker [data-zen-calendar-day]',
-      ).count(),
-      42,
-    );
-    const chosenDate = await page.locator(
-      'zen-date-picker [data-zen-calendar-day]:not([data-outside]):not(:disabled)',
-    ).nth(14).getAttribute('data-zen-calendar-day');
-    await page.locator(
-      `zen-date-picker [data-zen-calendar-day="${chosenDate}"]`,
-    ).click();
-    assert.equal(await dateInput.inputValue(), chosenDate);
-    assert.equal(await page.evaluate(() => window.__dateValue), chosenDate);
-    assert.equal(await dateTrigger.getAttribute('aria-expanded'), 'false');
-    const triggerName = await dateTrigger.evaluate(trigger =>
-      (trigger.getAttribute('aria-labelledby') || '')
-        .split(/\s+/)
-        .map(id => document.getElementById(id)?.textContent || '')
-        .join(' ')
-    );
-    assert.match(triggerName, /Deploy on/);
-    assert.equal(
-      await page.locator('zen-date-picker > label').getAttribute('for'),
-      await dateTrigger.getAttribute('id'),
-    );
-    const minimumDate = `${chosenDate.slice(0, 8)}10`;
-    await dateInput.evaluate((input, minimum) => {
-      input.min = minimum;
-    }, minimumDate);
-    await page.waitForTimeout(0);
-    await dateTrigger.click();
-    const focusedBoundary = page.locator(
-      `zen-date-picker [data-zen-calendar-day="${chosenDate}"]`,
-    );
-    await focusedBoundary.press('PageUp');
-    assert.equal(
-      await page.evaluate(() =>
-        document.activeElement?.dataset.zenCalendarDay
-      ),
-      minimumDate,
-    );
-    assert.equal(
-      await page.locator(
-        'zen-date-picker [data-zen-calendar-day][tabindex="0"]:not(:disabled)',
-      ).count(),
-      1,
-    );
-    await page.keyboard.press('Escape');
-    await dateInput.evaluate(input => {
-      input.disabled = true;
-    });
-    await page.waitForTimeout(0);
-    assert.equal(await dateTrigger.isDisabled(), true);
-    await dateInput.evaluate(input => {
-      input.disabled = false;
-      input.readOnly = true;
-    });
-    await page.waitForTimeout(0);
-    assert.equal(await dateTrigger.isDisabled(), true);
-    await dateInput.evaluate(input => {
-      input.readOnly = false;
-      input.required = true;
-      input.value = '';
-      input.dispatchEvent(new Event('input', { bubbles: true }));
-      input.reportValidity();
-    });
-    await page.waitForTimeout(0);
-    assert.equal(await dateTrigger.getAttribute('aria-invalid'), 'true');
-    assert.equal(
-      await dateTrigger.evaluate(
-        trigger => document.activeElement === trigger,
-      ),
-      true,
-    );
-    assert.equal(
-      await page.locator('zen-date-picker').getAttribute('data-invalid'),
-      '',
-    );
-    await dateInput.evaluate((input, value) => {
-      input.value = value;
-      input.dispatchEvent(new Event('input', { bubbles: true }));
-    }, chosenDate);
-    assert.equal(await dateTrigger.getAttribute('aria-invalid'), 'false');
-    const earlyYear = await page.evaluate(async () => {
-      const calendar = document.createElement('zen-calendar');
-      const input = document.createElement('input');
-      input.type = 'date';
-      input.value = '0001-01-01';
-      input.setAttribute('aria-label', 'Early date');
-      calendar.append(input);
-      document.body.append(calendar);
-      await new Promise(resolve => setTimeout(resolve));
-      return {
-        selected: calendar.querySelector(
-          '[data-zen-calendar-day][aria-selected="true"]',
-        )?.dataset.zenCalendarDay,
-        value: input.value,
-      };
-    });
-    assert.deepEqual(earlyYear, {
-      selected: '0001-01-01',
-      value: '0001-01-01',
-    });
-    const resetDateState = await page.evaluate(async () => {
-      const label = document.createElement('span');
-      label.id = 'reset-date-label';
-      label.textContent = 'Reset date';
-      const form = document.createElement('form');
-      const picker = document.createElement('zen-date-picker');
-      const input = document.createElement('input');
-      input.type = 'date';
-      input.defaultValue = '2026-08-04';
-      input.setAttribute('aria-labelledby', label.id);
-      picker.append(input);
-      form.append(picker);
-      document.body.append(label, form);
-      await new Promise(resolve => setTimeout(resolve));
-      input.value = '2026-08-12';
-      input.dispatchEvent(new Event('input', { bubbles: true }));
-      form.reset();
-      await new Promise(resolve => setTimeout(resolve));
-      const trigger = picker.querySelector('[data-zen-date-trigger]');
-      return {
-        labelledBy: trigger.getAttribute('aria-labelledby'),
-        selected: picker.querySelector(
-          '[data-zen-calendar-day][aria-selected="true"]',
-        )?.dataset.zenCalendarDay,
-        value: input.value,
-      };
-    });
-    assert.match(resetDateState.labelledBy, /^reset-date-label /);
-    assert.deepEqual(
-      {
-        selected: resetDateState.selected,
-        value: resetDateState.value,
-      },
-      {
-        selected: '2026-08-04',
-        value: '2026-08-04',
-      },
-    );
-
-    await page.goto(`${baseUrl}/components/input-otp`, {
-      waitUntil: 'networkidle',
-    });
-    await page.evaluate(() => {
-      window.__otpValue = null;
-      document.querySelector('zen-input-otp').addEventListener(
-        'zen-complete',
-        event => {
-          window.__otpValue = event.detail.value;
-        },
-      );
-    });
-    await page.locator('zen-input-otp input').evaluate(input => {
-      input.value = '12a3456';
-      input.dispatchEvent(new Event('input', { bubbles: true }));
-    });
-    assert.equal(await page.locator('zen-input-otp input').inputValue(), '123456');
-    assert.equal(
-      await page.locator('zen-input-otp [data-zen-otp-slots] > span').count(),
-      6,
-    );
-    assert.equal(await page.evaluate(() => window.__otpValue), '123456');
-
-    await page.goto(`${baseUrl}/components/data-table`, {
-      waitUntil: 'networkidle',
-    });
-    await page.locator('zen-data-table [data-zen-sort="commits"]').click();
-    assert.equal(
-      await page.locator('zen-data-table th').nth(1).getAttribute('aria-sort'),
-      'ascending',
-    );
-    assert.equal(
-      await page.locator('zen-data-table tbody tr').first().locator(
-        '[data-key="commits"]',
-      ).textContent(),
-      '12',
-    );
-
-    await page.goto(`${baseUrl}/components/carousel`, {
-      waitUntil: 'networkidle',
-    });
-    await page.evaluate(() => {
-      window.__carouselIndex = null;
-      document.querySelector('zen-carousel').addEventListener(
-        'zen-change',
-        event => {
-          window.__carouselIndex = event.detail.index;
-        },
-      );
-    });
-    await page.locator('zen-carousel [data-zen-next]').click();
-    assert.equal(await page.evaluate(() => window.__carouselIndex), 1);
-    assert.equal(
-      await page.locator('zen-carousel [data-zen-prev]').isDisabled(),
-      false,
-    );
-
-    await page.goto(`${baseUrl}/components/resizable`, {
-      waitUntil: 'networkidle',
-    });
-    const resizeHandle = page.locator('zen-resizable [data-zen-handle]');
-    const initialPercent = Number(
-      await resizeHandle.getAttribute('aria-valuenow'),
-    );
-    await resizeHandle.focus();
-    await resizeHandle.press('ArrowRight');
-    assert.ok(
-      Number(await resizeHandle.getAttribute('aria-valuenow')) > initialPercent,
-    );
-
-    await page.goto(`${baseUrl}/components/switch`, {
-      waitUntil: 'networkidle',
-    });
-    const switchInput = page.locator('zen-switch input');
-    assert.equal(await switchInput.getAttribute('role'), 'switch');
-    assert.equal(await switchInput.getAttribute('aria-checked'), 'true');
-    await switchInput.uncheck();
-    assert.equal(await switchInput.getAttribute('aria-checked'), 'false');
-
-    await page.goto(`${baseUrl}/components/checkbox`, {
-      waitUntil: 'networkidle',
-    });
-    assert.equal(
-      await page.locator('zen-checkbox input').evaluate(
-        input => getComputedStyle(input).appearance,
-      ),
-      'none',
-    );
-    await page.goto(`${baseUrl}/components/native-select`, {
-      waitUntil: 'networkidle',
-    });
-    assert.equal(
-      await page.locator('zen-native-select select').evaluate(
-        select => getComputedStyle(select).appearance,
-      ),
-      'none',
-    );
-    assert.equal(
-      await page.locator(
-        'zen-native-select > zen-icon[data-zen-select-icon]',
-      ).count(),
-      1,
-    );
-    await page.goto(`${baseUrl}/components/slider`, {
-      waitUntil: 'networkidle',
-    });
-    assert.equal(
-      await page.locator('zen-slider input').evaluate(
-        input => getComputedStyle(input).appearance,
-      ),
-      'none',
-    );
-
-    await page.goto(`${baseUrl}/components/toggle-group`, {
-      waitUntil: 'networkidle',
-    });
-    await page.locator('zen-toggle-group button[value="right"]').click();
-    assert.equal(
-      await page.locator('zen-toggle-group button[value="right"]')
-        .getAttribute('aria-pressed'),
-      'true',
-    );
-    assert.equal(
-      await page.locator('zen-toggle-group').getAttribute('value'),
-      'right',
-    );
-
-    await page.goto(`${baseUrl}/components/sidebar`, {
-      waitUntil: 'networkidle',
-    });
-    const sidebarTrigger = page.locator(
-      'zen-sidebar [data-zen-sidebar-trigger]',
-    );
-    const sidebarPanel = page.locator(
-      'zen-sidebar [data-zen-sidebar-panel]',
-    );
-    assert.equal(await sidebarTrigger.getAttribute('aria-expanded'), 'true');
-    assert.equal(await sidebarPanel.getAttribute('hidden'), null);
-    await sidebarTrigger.click();
-    assert.equal(await sidebarTrigger.getAttribute('aria-expanded'), 'false');
-    assert.equal(await sidebarPanel.getAttribute('hidden'), '');
-
-    await page.goto(`${baseUrl}/components/notifications`, {
-      waitUntil: 'networkidle',
-    });
-    const notificationScope = page.locator('zen-notifications').first();
-    const notificationPosition = await notificationScope.locator(
-      '[data-zen-notification-stack]',
-    ).evaluate(stack => {
-      const style = getComputedStyle(stack);
-      return {
-        bottom: style.bottom,
-        position: style.position,
-        right: style.right,
-      };
-    });
-    assert.equal(notificationPosition.position, 'fixed');
-    assert.notEqual(notificationPosition.bottom, 'auto');
-    assert.notEqual(notificationPosition.right, 'auto');
-
-    const dedupe = await notificationScope.evaluate(scope => {
-      const source = scope.querySelector('[data-notification-demo]');
-      const send = detail => source.dispatchEvent(
-        new CustomEvent('zen-notify', {
-          bubbles: true,
-          composed: false,
-          detail,
-        }),
-      );
-      send({
-        version: 1,
-        id: 'dedupe',
-        tone: 'info',
-        message: 'First announcement',
-        announcement: 'polite',
-        persistent: true,
-      });
-      send({
-        version: 1,
-        id: 'dedupe',
-        tone: 'success',
-        message: 'Updated without duplication',
-        announcement: 'polite',
-        persistent: true,
-      });
-      send({ version: 99, id: 'invalid' });
-      return {
-        size: scope.size,
-        visible: scope.visibleCount,
-      };
-    });
-    assert.deepEqual(dedupe, { size: 1, visible: 1 });
-    assert.equal(
-      await notificationScope.locator('article').count(),
-      1,
-    );
-    assert.match(
-      await notificationScope.locator('article').textContent(),
-      /Updated without duplication/,
-    );
-    await page.waitForFunction(() =>
-      document.querySelector(
-        'zen-notifications [data-zen-live="polite"]',
-      )?.textContent === 'First announcement'
-    );
-
-    const bounded = await notificationScope.evaluate(scope => {
-      let accepted = 0;
-      for (let index = 0; index < 25; index++) {
-        if (scope.notify({
-          version: 1,
-          id: `bounded-${index}`,
-          tone: 'info',
-          message: `Bounded ${index}`,
-          announcement: 'none',
-          durationMs: 120000,
-        })) accepted++;
-      }
-      return {
-        accepted,
-        size: scope.size,
-        visible: scope.visibleCount,
-      };
-    });
-    assert.deepEqual(bounded, { accepted: 25, size: 23, visible: 3 });
-    assert.equal(
-      await notificationScope.locator('article').count(),
-      3,
-    );
-    await page.waitForFunction(() =>
-      [...document.querySelectorAll(
-        'zen-notifications article',
-      )].some(article => article.dataset.depth === '2')
-    );
-    const collapsedStack = await notificationScope.locator(
-      '[data-zen-notification-stack]',
-    ).evaluate(stack => {
-      const articles = [...stack.querySelectorAll('article')];
-      return {
-        depths: articles.map(article => article.dataset.depth),
-        height: stack.getBoundingClientRect().height,
-        positions: articles.map(article =>
-          getComputedStyle(article).position
-        ),
-        transforms: articles.map(article =>
-          getComputedStyle(article).transform
-        ),
-      };
-    });
-    assert.deepEqual(collapsedStack.depths, ['2', '1', '0']);
-    assert.deepEqual(
-      collapsedStack.positions,
-      ['absolute', 'absolute', 'absolute'],
-    );
-    await notificationScope.locator('article').last().hover();
-    await page.waitForTimeout(300);
-    const expandedStack = await notificationScope.locator(
-      '[data-zen-notification-stack]',
-    ).evaluate(stack => ({
-      height: stack.getBoundingClientRect().height,
-      rects: [...stack.querySelectorAll('article')].map(article => {
-        const bounds = article.getBoundingClientRect();
-        return {
-          bottom: bounds.bottom,
-          left: bounds.left,
-          right: bounds.right,
-          top: bounds.top,
-        };
-      }),
-      tops: [...stack.querySelectorAll('article')].map(
-        article => Math.round(article.getBoundingClientRect().top),
-      ),
-      transforms: [...stack.querySelectorAll('article')].map(
-        article => getComputedStyle(article).transform,
-      ),
-    }));
-    assert.ok(expandedStack.height > collapsedStack.height);
-    assert.equal(new Set(expandedStack.tops).size, 3);
-    const expandedGaps = [
-      expandedStack.rects[1].top - expandedStack.rects[0].bottom,
-      expandedStack.rects[2].top - expandedStack.rects[1].bottom,
-    ];
-    for (const gap of expandedGaps) {
-      assert.ok(gap >= 10 && gap <= 14, JSON.stringify(expandedGaps));
-    }
-    assert.notDeepEqual(
-      expandedStack.transforms,
-      collapsedStack.transforms,
-    );
-    const gapX =
-      (expandedStack.rects[0].left + expandedStack.rects[0].right) / 2;
-    const gapY =
-      (expandedStack.rects[0].bottom + expandedStack.rects[1].top) / 2;
-    await page.mouse.move(gapX, gapY);
-    await page.waitForTimeout(100);
-    const gapState = await notificationScope.locator(
-      '[data-zen-notification-stack]',
-    ).evaluate(stack => ({
-      height: stack.getBoundingClientRect().height,
-      hovered: stack.matches(':hover'),
-    }));
-    assert.equal(gapState.hovered, true);
-    assert.ok(gapState.height >= expandedStack.height - 1);
-    await page.mouse.move(0, 0);
-
-    const actionScope = await page.evaluate(() => {
-      const scope = document.createElement('zen-notifications');
-      scope.id = 'action-scope';
-      const source = document.createElement('button');
-      scope.append(source);
-      document.body.append(scope);
-      window.__notificationAction = null;
-      scope.addEventListener('zen-notification-action', event => {
-        window.__notificationAction = event.detail;
-      });
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'action',
-          tone: 'error',
-          message: 'Action required',
-          announcement: 'assertive',
-          persistent: true,
-          action: {
-            token: 'opaque-secret-token',
-            label: 'Retry',
-          },
-        },
-      }));
-      return scope.id;
-    });
-    assert.equal(
-      await page.locator(`#${actionScope}`).evaluate(
-        scope => scope.records,
-      ),
-      undefined,
-    );
-    const actionArticle = page.locator(
-      `#${actionScope} [data-zen-notification-id="action"]`,
-    );
-    assert.doesNotMatch(
-      await actionArticle.evaluate(article => article.outerHTML),
-      /opaque-secret-token/,
-    );
-    await actionArticle.locator('.zen-notification-action').focus();
-    await page.locator(`#${actionScope}`).evaluate(scope => {
-      const source = scope.querySelector('button');
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'action-neighbor',
-          tone: 'info',
-          message: 'Neighbor',
-          announcement: 'none',
-          persistent: true,
-        },
-      }));
-    });
-    assert.equal(
-      await actionArticle.locator('.zen-notification-action').evaluate(
-        action => document.activeElement === action,
-      ),
-      true,
-    );
-    await actionArticle.locator('.zen-notification-action').click();
-    assert.deepEqual(
-      await page.evaluate(() => window.__notificationAction),
-      {
-        version: 1,
-        id: 'action',
-        token: 'opaque-secret-token',
-      },
-    );
-    await page.locator(`#${actionScope}`).evaluate(scope => {
-      const source = scope.querySelector('button');
-      source.dispatchEvent(new CustomEvent(
-        'zen-dismiss-notification',
-        {
-          bubbles: true,
-          composed: false,
-          detail: { version: 1, id: 'action' },
-        },
-      ));
-    });
-    await actionArticle.waitFor({ state: 'detached' });
-
-    await page.evaluate(() => {
-      const scope = document.createElement('zen-notifications');
-      scope.id = 'announcement-scope';
-      const source = document.createElement('button');
-      scope.append(source);
-      document.body.append(scope);
-      window.__announcements = [];
-      const region = scope.querySelector('[data-zen-live="polite"]');
-      new MutationObserver(() => {
-        if (region.textContent) {
-          window.__announcements.push(region.textContent);
-        }
-      }).observe(region, { childList: true });
-      for (let index = 0; index < 3; index++) {
-        source.dispatchEvent(new CustomEvent('zen-notify', {
-          bubbles: true,
-          composed: false,
-          detail: {
-            version: 1,
-            id: `announcement-${index}`,
-            tone: 'info',
-            message: `Announcement ${index}`,
-            announcement: 'polite',
-            persistent: true,
-          },
-        }));
-      }
-    });
-    await page.waitForFunction(() =>
-      window.__announcements?.length === 3
-    );
-    assert.deepEqual(
-      await page.evaluate(() => window.__announcements),
-      ['Announcement 0', 'Announcement 1', 'Announcement 2'],
-    );
-
-    const composedRejected = await page.evaluate(() => {
-      const scope = document.createElement('zen-notifications');
-      const source = document.createElement('button');
-      scope.append(source);
-      document.body.append(scope);
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: true,
-        detail: {
-          version: 1,
-          id: 'composed',
-          tone: 'info',
-          message: 'Must be rejected',
-          announcement: 'none',
-          persistent: true,
-        },
-      }));
-      return scope.size;
-    });
-    assert.equal(composedRejected, 0);
-
-    await page.evaluate(() => {
-      const scope = document.createElement('zen-notifications');
-      scope.id = 'focus-timer-scope';
-      const source = document.createElement('button');
-      scope.append(source);
-      document.body.append(scope);
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'focus-timer',
-          tone: 'warning',
-          message: 'Focus timer',
-          announcement: 'none',
-          durationMs: 300,
-          action: { token: 'focus-token', label: 'Keep focused' },
-        },
-      }));
-    });
-    const focusTimer = page.locator(
-      '#focus-timer-scope [data-zen-notification-id="focus-timer"]',
-    );
-    await focusTimer.locator('.zen-notification-action').focus();
-    await page.locator('#focus-timer-scope').evaluate(scope => {
-      const source = scope.querySelector(':scope > button');
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'focus-neighbor',
-          tone: 'info',
-          message: 'Focus neighbor',
-          announcement: 'none',
-          persistent: true,
-        },
-      }));
-    });
-    await page.waitForTimeout(500);
-    assert.equal(await focusTimer.count(), 1);
-    assert.equal(
-      await focusTimer.locator('.zen-notification-action').evaluate(
-        action => document.activeElement === action,
-      ),
-      true,
-    );
-    await page.mouse.move(0, 0);
-    await page.locator('#catalogMain').focus();
-    await page.waitForFunction(() =>
-      !document.querySelector(
-        '#focus-timer-scope [data-zen-notification-id="focus-timer"]',
-      )
-    );
-
-    await page.evaluate(() => {
-      const scope = document.createElement('zen-notifications');
-      scope.id = 'timer-scope';
-      const source = document.createElement('button');
-      scope.append(source);
-      document.body.append(scope);
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'timer',
-          tone: 'info',
-          message: 'Paused timer',
-          announcement: 'none',
-          durationMs: 300,
-        },
-      }));
-    });
-    const timerArticle = page.locator('#timer-scope article');
-    await timerArticle.hover();
-    await page.waitForTimeout(500);
-    assert.equal(await timerArticle.count(), 1);
-    await page.mouse.move(0, 0);
-    await page.waitForFunction(() =>
-      !document.querySelector('#timer-scope article')
-    );
-
-    await page.evaluate(() => {
-      const scope = document.createElement('zen-notifications');
-      scope.id = 'hidden-timer-scope';
-      const source = document.createElement('button');
-      scope.append(source);
-      document.body.append(scope);
-      source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'hidden-timer',
-          tone: 'info',
-          message: 'Hidden timer',
-          announcement: 'none',
-          durationMs: 300,
-        },
-      }));
-      Object.defineProperty(document, 'hidden', {
-        configurable: true,
-        value: true,
-      });
-      document.dispatchEvent(new Event('visibilitychange'));
-    });
-    await page.waitForTimeout(500);
-    assert.equal(
-      await page.locator('#hidden-timer-scope article').count(),
-      1,
-    );
-    await page.evaluate(() => {
-      Object.defineProperty(document, 'hidden', {
-        configurable: true,
-        value: false,
-      });
-      document.dispatchEvent(new Event('visibilitychange'));
-    });
-    await page.waitForFunction(() =>
-      !document.querySelector('#hidden-timer-scope article')
-    );
-
-    const isolated = await page.evaluate(() => {
-      const makeScope = id => {
-        const scope = document.createElement('zen-notifications');
-        scope.id = id;
-        const source = document.createElement('button');
-        scope.append(source);
-        document.body.append(scope);
-        return { scope, source };
-      };
-      const first = makeScope('scope-one');
-      const second = makeScope('scope-two');
-      first.source.dispatchEvent(new CustomEvent('zen-notify', {
-        bubbles: true,
-        composed: false,
-        detail: {
-          version: 1,
-          id: 'isolated',
-          tone: 'success',
-          message: 'Only first scope',
-          announcement: 'none',
-          persistent: true,
-        },
-      }));
-      return [first.scope.size, second.scope.size];
-    });
-    assert.deepEqual(isolated, [1, 0]);
-
-    const lightCanvas = await page.evaluate(() =>
-      getComputedStyle(document.documentElement)
-        .getPropertyValue('--zen-color-canvas')
-        .trim()
-    );
-    await page.locator('#themeToggle').click();
-    const darkCanvas = await page.evaluate(() =>
-      getComputedStyle(document.documentElement)
-        .getPropertyValue('--zen-color-canvas')
-        .trim()
-    );
-    assert.notEqual(lightCanvas, darkCanvas);
-    assert.equal(
-      await page.evaluate(() => localStorage.getItem('zen-theme')),
-      'dark',
-    );
-
-    assert.deepEqual(errors, []);
-    await context.close();
-
-    const darkContext = await browser.newContext({ colorScheme: 'dark' });
-    const darkPage = await darkContext.newPage();
-    await darkPage.goto(baseUrl, { waitUntil: 'networkidle' });
-    assert.equal(
-      await darkPage.locator('#themeToggle').getAttribute('aria-pressed'),
-      'true',
-    );
-    const systemDarkCanvas = await darkPage.evaluate(() =>
-      getComputedStyle(document.documentElement)
-        .getPropertyValue('--zen-color-canvas')
-        .trim()
-    );
-    await darkPage.locator('#themeToggle').click();
-    const explicitLightCanvas = await darkPage.evaluate(() =>
-      getComputedStyle(document.documentElement)
-        .getPropertyValue('--zen-color-canvas')
-        .trim()
-    );
-    assert.notEqual(systemDarkCanvas, explicitLightCanvas);
-    await darkContext.close();
-
-    const mobileContext = await browser.newContext({
-      colorScheme: 'light',
-      viewport: { width: 390, height: 844 },
-    });
-    const mobilePage = await mobileContext.newPage();
-    const mobileErrors = [];
-    mobilePage.on('pageerror', error => {
-      mobileErrors.push(error.stack || error.message);
-    });
-    mobilePage.on('console', message => {
-      if (message.type() === 'error') mobileErrors.push(message.text());
-    });
-    await mobilePage.goto(baseUrl, { waitUntil: 'networkidle' });
-    await mobilePage.waitForFunction(() =>
-      customElements.get('zen-date-picker') &&
-      document.querySelectorAll(
-        '.catalog-nav[aria-label="Components"] a',
-      ).length === 66
-    );
-    const mobileFailures = await mobilePage.evaluate(() => {
-      const routes = [
-        '/',
-        '/tokens',
-        '/icons',
-        ...[...document.querySelectorAll(
-          '.catalog-nav[aria-label="Components"] a',
-        )].map(link => new URL(link.href).pathname),
-      ];
-      const failures = [];
-      for (const route of routes) {
-        history.replaceState({}, '', route);
-        window.dispatchEvent(new PopStateEvent('popstate'));
-        const page = document.querySelector(
-          '[data-catalog-page]:not([hidden])',
-        );
-        if (!page ||
-            document.documentElement.scrollWidth > innerWidth + 1 ||
-            page.getBoundingClientRect().right > innerWidth + 1) {
-          failures.push(route);
-        }
-      }
-      return failures;
-    });
-    assert.deepEqual(mobileFailures, []);
-    await mobilePage.goto(`${baseUrl}/components/date-picker`, {
-      waitUntil: 'networkidle',
-    });
-    await mobilePage.locator(
-      'zen-date-picker [data-zen-date-trigger]',
-    ).click();
-    const mobileCalendarBounds = await mobilePage.locator(
-      'zen-date-picker [data-zen-calendar-panel]',
-    ).evaluate(panel => {
-      const bounds = panel.getBoundingClientRect();
-      return {
-        bottom: bounds.bottom,
-        left: bounds.left,
-        right: bounds.right,
-        top: bounds.top,
-      };
-    });
-    assert.ok(mobileCalendarBounds.left >= 0);
-    assert.ok(mobileCalendarBounds.right <= 390);
-    assert.ok(mobileCalendarBounds.top >= 0);
-    assert.ok(mobileCalendarBounds.bottom <= 844);
-    assert.deepEqual(mobileErrors, []);
-    await mobileContext.close();
-  } finally {
-    if (browser) await browser.close();
-    await stopProcess(server);
-  }
-})().catch(error => {
-  console.error(error.stack || error);
-  process.exitCode = 1;
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/wiki/HTML_AUTHORING.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,95 @@
+# HTML authoring
+
+## Native underneath
+
+Seeing a native `button`, `input`, `textarea`, `select`, or `a` inside a Zenbu
+element is intentional:
+
+```html
+<zen-button size="md">
+  <button type="submit">Save</button>
+</zen-button>
+```
+
+The native element retains form submission, keyboard activation, focus,
+validation, autofill, link navigation, and browser APIs. The Zenbu host owns
+shared behavior, sizing, tokens, and optional presentation.
+
+Do not replace the inner button with text-only custom-element content.
+
+## One owner per control
+
+An authored control must have one nearest owner:
+
+```html
+<zen-field appearance="plain" size="lg">
+  <label for="token">Access token</label>
+  <input id="token" required>
+</zen-field>
+```
+
+Do not nest a control inside unrelated visual primitives merely to increase
+component usage. A toggle button is already owned by `zen-toggle`. Overlay and
+layout components only coordinate behavior, so their authored actions still
+use the control primitive:
+
+```html
+<zen-drawer>
+  <zen-button size="md">
+    <button type="button" data-zen-trigger>Open drawer</button>
+  </zen-button>
+  <dialog>
+    <zen-button size="md">
+      <button type="button" data-zen-close>Close</button>
+    </zen-button>
+  </dialog>
+</zen-drawer>
+```
+
+## Plain integration
+
+Use plain appearance to preserve an application's visual language:
+
+```html
+<zen-button appearance="plain" size="sm">
+  <button class="existing-toolbar-button">Close</button>
+</zen-button>
+```
+
+Plain mode:
+
+- retains component behavior and ARIA wiring;
+- exposes inherited `--zenbu-control-*` aliases;
+- does not add borders, shadows, colors, padding, or hover effects;
+- leaves application selectors on the native element effective.
+
+## Structural HTML
+
+Keep semantic structure native unless a primitive adds a concrete contract:
+
+```html
+<main>
+  <section aria-labelledby="activity-heading">
+    <zen-heading size="xl">
+      <h2 id="activity-heading">Activity</h2>
+    </zen-heading>
+    <zen-text size="md"><p>Latest repository events.</p></zen-text>
+  </section>
+</main>
+```
+
+`main`, `section`, `nav`, lists, tables, paragraphs, and heading levels still
+carry document meaning. Zenbu must not obscure that meaning.
+
+## Links
+
+Use `zen-link` when a reusable effect is requested:
+
+```html
+<zen-link effect="paw">
+  <a href="/blog">Blog</a>
+</zen-link>
+```
+
+Use a native link without a Zenbu wrapper when no link behavior or effect is
+being added. Button-like links belong in `zen-button`.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/wiki/PRIMITIVE_MAP.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,43 @@
+# Primitive map
+
+| Native authored element | Owning Zenbu primitive |
+| --- | --- |
+| `button`, button-like `a` | `zen-button` |
+| text/email/file/etc. `input` | `zen-input` or `zen-field` |
+| `textarea` | `zen-textarea` or `zen-field` |
+| native `select` | `zen-native-select`, `zen-select`, or `zen-field` |
+| checkbox input | `zen-checkbox` |
+| radio inputs/fieldset | `zen-radio-group` |
+| switch checkbox | `zen-switch` |
+| range input | `zen-slider` |
+| date value | `zen-calendar` or `zen-date-picker` |
+| one-time-code input | `zen-input-otp` |
+| filter input and options | `zen-combobox` |
+| command input and items | `zen-command` |
+| anchor with reusable effect | `zen-link` |
+| heading with canonical type role | `zen-heading` |
+| text with canonical type role | `zen-text` |
+| padded container | `zen-box` |
+
+## Control-owning composites
+
+These behavior primitives already own their native buttons. Do not add a second
+`zen-button`:
+
+- menus, context menus, menubars, and navigation menus;
+- tabs, toggles, toggle groups, and sidebars;
+- calendars, carousels, commands, and data tables;
+- notifications and dismissible alerts.
+
+## Coordinating containers
+
+Dialogs, alert dialogs, sheets, drawers, popovers, tooltips, forms, empty
+states, and items coordinate or arrange content. They do not own application
+actions. Wrap authored action buttons in `zen-button`, then put the native
+`button` inside it.
+
+## Generated controls
+
+Component implementation code may create native buttons for accessibility.
+Generated controls are owned by that component. Application-authored controls
+are checked separately.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/wiki/README.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,23 @@
+# Zenbu UI wiki
+
+This wiki is the source of truth for future HTML and component work.
+
+## Pages
+
+- [HTML authoring](HTML_AUTHORING.md): native-underneath markup and ownership.
+- [Primitive map](PRIMITIVE_MAP.md): which primitive owns each native control.
+- [Tokens and sizing](TOKENS_AND_SIZING.md): reference, semantic, local, theme,
+  density, and xs-xl contracts.
+- [Review checklist](REVIEW_CHECKLIST.md): required searches, tests, and
+  accessibility checks.
+
+## Core rules
+
+1. Keep browser semantics. A Zenbu control contains the appropriate native
+   element rather than replacing it.
+2. Give every authored interactive control one owning primitive.
+3. Use `appearance="plain"` when only behavior and scale are shared.
+4. Consume `--zenbu-sys-*` intent in application/component CSS.
+5. Use reference values only while defining semantic mappings.
+6. Keep business state and workflows outside the design system.
+7. Add catalog and browser evidence for every public primitive.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/wiki/REVIEW_CHECKLIST.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,40 @@
+# Review checklist
+
+## Discovery
+
+- Read relevant Bazel `BUILD` dependencies before broad searches.
+- Identify shared assets and downstream consumers.
+- Search for existing primitives and semantic tokens before adding new ones.
+
+## HTML
+
+- Every authored action button belongs to `zen-button`.
+- A behavior primitive owns a raw native button only when that button is the
+  primitive's semantic control, such as a tab, toggle, menu item, or carousel
+  control.
+- Every authored form control belongs to a form-control primitive.
+- Native semantics remain visible in source.
+- There is only one owning primitive per control.
+- Plain appearance preserves application CSS.
+
+## CSS
+
+- New variables use the `--zenbu-*` namespace.
+- Components and applications consume `--zenbu-sys-*` roles.
+- Reference colors are not used directly in component/application CSS.
+- Repeated dimensions use the xs-xl or semantic spacing scale.
+- Focus, disabled, hover, pressed, invalid, and selected states are covered.
+- Reduced motion and forced colors remain usable.
+
+## Verification
+
+```bash
+bazel test //design_system/test:design_system_policy_test
+bazel test //design_system/test:catalog_test
+bazel test //mrjunejune/test:theme_and_webp_test
+bazel build //design_system:design_system_server_bundle
+bazel build //mrjunejune:mrjunejune_server_bundle
+```
+
+Do not mark an integration complete when controls are merely present. Exercise
+native forms, keyboard behavior, sizing, theme, density, and mobile layout.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/wiki/TOKENS_AND_SIZING.md	Wed Aug 05 05:25:40 2026 -0700
@@ -0,0 +1,53 @@
+# Tokens and sizing
+
+## Three layers
+
+```text
+--zenbu-ref-*          available context-free values
+--zenbu-sys-*          theme/density-aware semantic intent
+--zenbu-<component>-*  local component aliases
+```
+
+Application CSS consumes semantic roles. Component CSS may define local aliases
+that fall back to semantic roles. Reference colors are restricted to token and
+theme definitions.
+
+## Five-step scale
+
+Controls, text, icons, gaps, and padding use:
+
+```text
+xs  sm  md  lg  xl
+```
+
+Every sized control host exposes:
+
+```css
+--zenbu-control-height
+--zenbu-control-padding-block
+--zenbu-control-padding-inline
+--zenbu-control-gap
+--zenbu-control-font-size
+--zenbu-control-line-height
+--zenbu-control-icon-size
+```
+
+Styled components consume these automatically. Plain components expose them to
+application CSS.
+
+## Density
+
+Set density once at the application root:
+
+```html
+<html data-zen-density="compact">
+```
+
+Density remaps semantic control sizes and padding. It does not require
+component-specific selectors.
+
+## Typography roles
+
+Prefer semantic type roles for page CSS and use `zen-text` / `zen-heading`
+where a reusable type contract is useful. Font sizes remain in `rem`; line
+heights remain unitless.
--- a/mrjunejune/src/base.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/base.css	Wed Aug 05 05:25:40 2026 -0700
@@ -99,36 +99,37 @@
 }
 
 :root {
-  --zen-font-editorial: "More Thin", "Roboto", sans-serif;
-  --zen-font-playful: "More", "More Thin", sans-serif;
-  --zen-font-sans: var(--zen-font-editorial);
+  --zenbu-font-editorial: "More Thin", "Roboto", sans-serif;
+  --zenbu-font-playful: "More", "More Thin", sans-serif;
+  --zenbu-sys-font-family-ui: var(--zenbu-font-editorial);
+  --zenbu-sys-font-family-content: var(--zenbu-font-editorial);
 }
 
 :root:not([data-zen-theme]),
 :root[data-zen-theme] {
-  --white: var(--zen-color-surface);
-  --black: var(--zen-color-text);
-  --darkgray: var(--zen-color-border-strong);
-  --lightgray: var(--zen-color-border-muted);
-  --gray-light: var(--zen-color-border-muted);
-  --green: var(--zen-color-success);
-  --orange: var(--zen-color-warning);
-  --purple: var(--zen-color-violet-400);
-  --red: var(--zen-color-danger);
-  --blue: var(--zen-color-info);
-  --darktext: var(--zen-color-text-muted);
-  --text: var(--zen-color-text);
-  --graytext: var(--zen-color-text-muted);
-  --lighttext: var(--zen-color-text-subtle);
-  --awesome: var(--zen-color-persimmon);
-  --accent: var(--zen-color-info);
-  --accent-dark: var(--zen-color-indigo);
-  --gray-dark: var(--zen-color-text);
+  --white: var(--zenbu-sys-color-surface-default);
+  --black: var(--zenbu-sys-color-text-primary);
+  --darkgray: var(--zenbu-sys-color-border-strong);
+  --lightgray: var(--zenbu-sys-color-border-subtle);
+  --gray-light: var(--zenbu-sys-color-border-subtle);
+  --green: var(--zenbu-sys-color-success-foreground);
+  --orange: var(--zenbu-sys-color-action-primary-background-hover);
+  --purple: var(--zenbu-sys-color-action-primary-background);
+  --red: var(--zenbu-sys-color-danger-foreground);
+  --blue: var(--zenbu-sys-color-info-foreground);
+  --darktext: var(--zenbu-sys-color-text-secondary);
+  --text: var(--zenbu-sys-color-text-primary);
+  --graytext: var(--zenbu-sys-color-text-secondary);
+  --lighttext: var(--zenbu-sys-color-text-tertiary);
+  --awesome: var(--zenbu-sys-color-action-danger-background);
+  --accent: var(--zenbu-sys-color-text-link);
+  --accent-dark: var(--zenbu-sys-color-action-primary-background-pressed);
+  --gray-dark: var(--zenbu-sys-color-text-primary);
   --gray-gradient: linear-gradient(
-    var(--zen-color-canvas),
-    var(--zen-color-surface)
+    var(--zenbu-sys-color-surface-page),
+    var(--zenbu-sys-color-surface-default)
   );
-  --box-shadow: var(--zen-shadow-md);
+  --box-shadow: var(--zenbu-sys-shadow-raised);
 }
 
 /* --- fonts --- */
@@ -165,6 +166,7 @@
 
 /* -- HTML Tags only --*/
 html {
+  min-height: 100%;
   background: var(--white);
 }
 
@@ -174,23 +176,26 @@
 }
 
 body {
-  font-family: var(--zen-font-sans, "More Thin", sans-serif);
+  min-height: 100vh;
+  font-family: var(--zenbu-sys-font-family-content);
   margin: 0;
   padding: 0;
   text-align: left;
   background: var(--gray-gradient);
-  background-size: 100% 600px;
+  background-attachment: fixed;
+  background-repeat: no-repeat;
+  background-size: cover;
   word-wrap: break-word;
   overflow-wrap: break-word;
   color: var(--gray-dark);
-  font-size: 20px;
-  line-height: 1.7;
+  font-size: var(--zenbu-sys-font-size-xl);
+  line-height: var(--zenbu-sys-line-height-lg);
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
 }
 
 main {
-  background: var(--white);
+  background: transparent;
   width: var(--main-width);
   max-width: calc(100% - 2em);
   margin: auto;
@@ -208,23 +213,23 @@
 }
 
 h1 {
-  font-size: 2.5em;
+  font-size: var(--zenbu-sys-font-size-3xl);
 }
 
 h2 {
-  font-size: 2em;
+  font-size: var(--zenbu-sys-font-size-2xl);
 }
 
 h3 {
-  font-size: 1.75em;
+  font-size: var(--zenbu-sys-font-size-xl);
 }
 
 h4 {
-  font-size: 1.5em;
+  font-size: var(--zenbu-sys-font-size-lg);
 }
 
 h5 {
-  font-size: 1.25em;
+  font-size: var(--zenbu-sys-font-size-md);
 }
 
 strong,
@@ -245,6 +250,19 @@
   font-size: 16px;
 }
 
+zen-button[appearance="plain"][size] > :where(button, a) {
+  display: inline-flex;
+  min-height: var(--zenbu-control-height);
+  align-items: center;
+  justify-content: center;
+  gap: var(--zenbu-control-gap);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  font-size: var(--zenbu-control-font-size);
+  line-height: var(--zenbu-control-line-height);
+}
+
 input {
   font-size: 16px;
 }
@@ -274,7 +292,8 @@
   border-left: 4px solid var(--accent);
   padding: 0 0 0 20px;
   margin-bottom: 1.25em;
-  font-size: 1.333em;
+  font-size: var(--zenbu-sys-font-size-lg);
+  line-height: var(--zenbu-sys-line-height-lg);
 }
 
 ul {
@@ -295,63 +314,35 @@
   text-decoration: underline;
 }
 
-a::before {
-  content: "";
-  display: inline-block;
-  width: 1em;
-  height: 1em;
-  margin-right: 8px;
-  vertical-align: middle;
-  background-color: #FF69B4;
-  -webkit-mask: url('/public/paw.svg') no-repeat center;
-  mask: url('/public/paw.svg') no-repeat center;
-  animation: pawStep 0.6s ease-out forwards;
-}
-
-@keyframes pawStep {
-  0% { transform: scale(0); opacity: 0; }
-  100% { transform: scale(1); opacity: 1; }
-}
-
-a:hover::before {
-  animation: wiggle 0.4s ease-in-out infinite;
-}
-
-@keyframes wiggle {
-  0%, 100% { transform: rotate(-15deg); }
-  50% { transform: rotate(15deg); }
-}
-
-
 /* -- mobile -- */
 @media (max-width: 720px) {
   body {
-    font-size: 18px;
-    line-height: 1.8;
+    font-size: var(--zenbu-sys-font-size-lg);
+    line-height: var(--zenbu-sys-line-height-md);
   }
 
   main {
-    padding: 1.5em 1em;
+    padding: var(--zenbu-sys-padding-lg) var(--zenbu-sys-padding-md);
   }
 
   h1 {
-    font-size: 2em;
+    font-size: var(--zenbu-sys-font-size-2xl);
   }
 
   h2 {
-    font-size: 1.75em;
+    font-size: var(--zenbu-sys-font-size-xl);
   }
 
   h3 {
-    font-size: 1.5em;
+    font-size: var(--zenbu-sys-font-size-lg);
   }
 
   h4 {
-    font-size: 1.25em;
+    font-size: var(--zenbu-sys-font-size-md);
   }
 
   h5 {
-    font-size: 1.1em;
+    font-size: var(--zenbu-sys-font-size-sm);
   }
 
   p {
@@ -364,25 +355,19 @@
     display: inline-block;
   }
 
-  button, input[type="submit"], input[type="button"] {
-    min-height: 44px;
-    padding: 0.75em 1.5em;
-    font-size: 1em;
-  }
-
   input, textarea, select {
     font-size: 16px; /* Prevents zoom on iOS */
   }
 
   /* Improve blockquote readability */
   blockquote {
-    font-size: 1.1em;
+    font-size: var(--zenbu-sys-font-size-md);
     padding: 0.5em 0 0.5em 1em;
   }
 
   /* Better code block sizing */
   code {
-    font-size: 0.9em;
+    font-size: var(--zenbu-sys-font-size-sm);
   }
 
   pre {
@@ -397,34 +382,24 @@
   position: fixed;
   bottom: 20px;
   right: 20px;
-  padding: 12px 24px 12px 36px;
+  min-height: var(--zenbu-control-height);
+  gap: var(--zenbu-control-gap);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
   background: #000000;
   color: #eeffee;
   border: none;
   border-radius: 8px;
   cursor: pointer;
-  font-size: 14px;
+  font-size: var(--zenbu-control-font-size);
   font-weight: bold;
   box-shadow: 0 4px 12px rgba(0,0,0,0.2);
   z-index: 1000;
   font-family: inherit;
 }
 
-#pwa-install-btn.with-icon::before {
-  content: "";
-  position: absolute;
-  left: 14px;
-  top: 50%;
-  transform: translateY(-50%);
-  width: 18px;
-  height: 18px;
-
-  /* Masked icon */
-  -webkit-mask: url('/public/paw.svg') no-repeat center;
-  mask: url('/public/paw.svg') no-repeat center;
-  mask-size: contain;
-  mask-repeat: no-repeat;
-
-  /* Icon color = button text color */
-  background-color: currentColor;
+#pwa-install-btn zen-icon {
+  width: var(--zenbu-control-icon-size);
+  height: var(--zenbu-control-icon-size);
 }
--- a/mrjunejune/src/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -65,27 +65,6 @@
         cursor: pointer;
       }
 
-      .site-link-grid {
-        display: grid;
-        grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
-        gap: var(--zen-space-4);
-      }
-
-      .site-link-grid > a {
-        color: inherit;
-        text-decoration: none;
-      }
-
-      .site-link-grid zen-card,
-      .site-link-grid article {
-        height: 100%;
-      }
-
-      .site-link-grid p {
-        margin: 0;
-        color: var(--zen-color-text-muted);
-        font-size: 0.9rem;
-      }
     </style>
   </head>
   <body>
@@ -102,28 +81,12 @@
        </div>
 
        <h2>Links</h2>
-       <div class="site-link-grid">
-         <a href="https://zenbu.babocoder.com/file/tip">
-           <zen-card interactive>
-             <article><h3>Repository</h3><p>Browse the code behind these experiments.</p></article>
-           </zen-card>
-         </a>
-         <a href="/blog">
-           <zen-card interactive>
-             <article><h3>Blogs</h3><p>Thoughts, experiments, and technical notes.</p></article>
-           </zen-card>
-         </a>
-         <a href="/resume">
-           <zen-card interactive>
-             <article><h3>Resume</h3><p>Professional experience and selected work.</p></article>
-           </zen-card>
-         </a>
-         <a href="/tools">
-           <zen-card interactive>
-             <article><h3>Tools</h3><p>Small things I built for myself.</p></article>
-           </zen-card>
-         </a>
-       </div>
+       <ul>
+         <li><a href="https://zenbu.babocoder.com/file/tip">Repository</a> - Check out my code</li>
+         <li><a href="/blog">Blogs</a> - My thoughts / Experiments </li>
+         <li><a href="/resume">Resume</a> - My professional experiences </li>
+         <li><a href="/tools">Tools</a> - Things I made for myself </li>
+       </ul>
        <canvas id="background"></canvas>
        <canvas id="game"></canvas>
        <canvas id="gameUI"></canvas>
--- a/mrjunejune/src/index.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/index.js	Wed Aug 05 05:25:40 2026 -0700
@@ -19,7 +19,7 @@
 
 function updateThemeColor() {
   const probe = document.createElement('span');
-  probe.style.background = 'var(--zen-color-canvas)';
+  probe.style.background = 'var(--zenbu-sys-color-surface-page)';
   document.body.append(probe);
   const color = getComputedStyle(probe).backgroundColor;
   probe.remove();
@@ -57,6 +57,34 @@
   localStorage.setItem(THEME_STORAGE_KEY, currentPreference);
 }
 
+function enhanceLinks(root = document) {
+  const links = root instanceof HTMLAnchorElement
+    ? [root]
+    : [...root.querySelectorAll?.('a') || []];
+  for (const link of links) {
+    if (link.closest('zen-link, zen-button') ||
+        link.dataset.zenLinkEffect === 'none') {
+      continue;
+    }
+    const wrapper = document.createElement('zen-link');
+    wrapper.setAttribute('effect', 'paw');
+    link.before(wrapper);
+    wrapper.append(link);
+  }
+}
+
+window.addEventListener('DOMContentLoaded', () => {
+  enhanceLinks();
+  const observer = new MutationObserver(records => {
+    for (const record of records) {
+      for (const node of record.addedNodes) {
+        if (node instanceof Element) enhanceLinks(node);
+      }
+    }
+  });
+  observer.observe(document.body, { childList: true, subtree: true });
+});
+
 document.querySelector('#themeToggle')?.addEventListener('click', () => {
   const current = getThemePreference();
   const next = THEMES[(THEMES.indexOf(current) + 1) % THEMES.length];
--- a/mrjunejune/src/notes/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/notes/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -7,7 +7,7 @@
     .notes-page {
       min-width: 70%;
       margin: 0 auto;
-      padding: 20px;
+      padding: var(--zenbu-sys-padding-lg);
     }
     .notes-header {
       display: flex;
@@ -15,36 +15,36 @@
       align-items: center;
       margin-bottom: 20px;
       flex-wrap: wrap;
-      gap: 12px;
+      gap: var(--zenbu-sys-space-control);
     }
     .notes-header h1 {
       margin: 0;
       display: flex;
       align-items: center;
-      gap: 12px;
+      gap: var(--zenbu-sys-space-control);
     }
     .note-id-display {
-      font-size: 14px;
+      font-size: var(--zenbu-sys-font-size-sm);
       color: #666;
       background: #f0f0f0;
-      padding: 4px 12px;
-      border-radius: 4px;
+      padding:
+        var(--zenbu-sys-control-padding-block-xs)
+        var(--zenbu-sys-control-padding-inline-sm);
+      border-radius: var(--zenbu-sys-radius-control-small);
       font-weight: normal;
     }
     .notes-actions {
       display: flex;
-      gap: 8px;
+      gap: var(--zenbu-sys-space-related);
       align-items: center;
     }
     .notes-actions button, .notes-actions a {
-      padding: 8px 16px;
       border: 1px solid #ccc;
-      border-radius: 4px;
+      border-radius: var(--zenbu-sys-radius-control-small);
       background: #fff;
       cursor: pointer;
       text-decoration: none;
       color: #333;
-      font-size: 14px;
     }
     .notes-actions button:hover, .notes-actions a:hover {
       background: #f5f5f5;
@@ -78,8 +78,8 @@
     }
     .new-note-form {
       background: white;
-      padding: 24px;
-      border-radius: 8px;
+      padding: var(--zenbu-sys-padding-lg);
+      border-radius: var(--zenbu-sys-radius-control);
       width: 400px;
       max-width: 90%;
     }
@@ -88,23 +88,21 @@
     }
     .new-note-form input {
       width: 100%;
-      padding: 10px;
+      padding: var(--zenbu-sys-padding-sm);
       border: 1px solid #ccc;
-      border-radius: 4px;
-      font-size: 16px;
+      border-radius: var(--zenbu-sys-radius-control-small);
+      font-size: var(--zenbu-sys-font-size-md);
       box-sizing: border-box;
       margin-bottom: 16px;
     }
     .new-note-form .form-actions {
       display: flex;
-      gap: 8px;
+      gap: var(--zenbu-sys-space-related);
       justify-content: flex-end;
     }
     .new-note-form button {
-      padding: 8px 16px;
-      border-radius: 4px;
+      border-radius: var(--zenbu-sys-radius-control-small);
       cursor: pointer;
-      font-size: 14px;
     }
     .new-note-form .btn-cancel {
       background: #f5f5f5;
@@ -116,7 +114,7 @@
       border: none;
     }
     .note-hint {
-      font-size: 12px;
+      font-size: var(--zenbu-sys-font-size-xs);
       color: #666;
       margin-top: -12px;
       margin-bottom: 16px;
@@ -133,8 +131,12 @@
         <span class="note-id-display" id="note-id-display">index</span>
       </h1>
       <div class="notes-actions">
-        <button onclick="goHome()"> Home </button>
-        <button onclick="logout()" class="btn-danger">Logout</button>
+        <zen-button appearance="plain" size="sm">
+          <button onclick="goHome()"> Home </button>
+        </zen-button>
+        <zen-button appearance="plain" size="sm">
+          <button onclick="logout()" class="btn-danger">Logout</button>
+        </zen-button>
       </div>
     </div>
 
@@ -145,11 +147,17 @@
   <div class="new-note-dialog" id="new-note-dialog">
     <div class="new-note-form">
       <h2>Create New Note</h2>
-      <input type="text" id="new-note-id" placeholder="note-id (e.g., my-ideas)">
+      <zen-input appearance="plain" size="md">
+        <input type="text" id="new-note-id" placeholder="note-id (e.g., my-ideas)">
+      </zen-input>
       <p class="note-hint">Use lowercase letters, numbers, and hyphens only</p>
       <div class="form-actions">
-        <button class="btn-cancel" onclick="hideNewNoteDialog()">Cancel</button>
-        <button class="btn-create" onclick="createNewNote()">Create & Open</button>
+        <zen-button appearance="plain" size="sm">
+          <button class="btn-cancel" onclick="hideNewNoteDialog()">Cancel</button>
+        </zen-button>
+        <zen-button appearance="plain" size="sm">
+          <button class="btn-create" onclick="createNewNote()">Create & Open</button>
+        </zen-button>
       </div>
     </div>
   </div>
--- a/mrjunejune/src/notes/login.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/notes/login.html	Wed Aug 05 05:25:40 2026 -0700
@@ -7,18 +7,18 @@
     .login-page {
       max-width: 400px;
       margin: 100px auto;
-      padding: 20px;
+      padding: var(--zenbu-sys-padding-lg);
     }
     .login-box {
       background: #fff;
       border: 1px solid #ddd;
-      border-radius: 8px;
-      padding: 32px;
+      border-radius: var(--zenbu-sys-radius-control);
+      padding: var(--zenbu-sys-padding-xl);
       box-shadow: 0 2px 8px rgba(0,0,0,0.1);
     }
     .login-box h1 {
       margin: 0 0 24px 0;
-      font-size: 24px;
+      font-size: var(--zenbu-sys-font-size-2xl);
       text-align: center;
     }
     .login-box label {
@@ -28,10 +28,14 @@
     }
     .login-box input {
       width: 100%;
-      padding: 12px;
+      min-height: var(--zenbu-control-height);
+      padding:
+        var(--zenbu-control-padding-block)
+        var(--zenbu-control-padding-inline);
       border: 1px solid #ccc;
-      border-radius: 4px;
-      font-size: 16px;
+      border-radius: var(--zenbu-sys-radius-control-small);
+      font-size: var(--zenbu-control-font-size);
+      line-height: var(--zenbu-control-line-height);
       box-sizing: border-box;
     }
     .login-box input:focus {
@@ -40,15 +44,16 @@
     }
     .login-box button {
       width: 100%;
-      padding: 12px;
       margin-top: 16px;
       background: #0078ff;
       color: white;
       border: none;
-      border-radius: 4px;
-      font-size: 16px;
+      border-radius: var(--zenbu-sys-radius-control-small);
       cursor: pointer;
     }
+    .login-box zen-button {
+      width: 100%;
+    }
     .login-box button:hover {
       background: #0066dd;
     }
@@ -67,9 +72,13 @@
     <div class="login-box">
       <h1>Notes Login</h1>
       <form id="login-form">
-        <label for="token">Access Token</label>
-        <input type="password" id="token" placeholder="Enter your access token" required>
-        <button type="submit">Login</button>
+        <zen-field appearance="plain" size="lg">
+          <label for="token">Access Token</label>
+          <input type="password" id="token" placeholder="Enter your access token" required>
+        </zen-field>
+        <zen-button appearance="plain" size="lg">
+          <button type="submit">Login</button>
+        </zen-button>
         <p class="error-msg" id="error-msg">Invalid token</p>
       </form>
     </div>
--- a/mrjunejune/src/offline.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/offline.html	Wed Aug 05 05:25:40 2026 -0700
@@ -3,6 +3,13 @@
   <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="/public/design-system/styles/tokens.css">
+    <link rel="stylesheet" href="/public/design-system/styles/themes.css">
+    <link rel="stylesheet" href="/public/design-system/styles/components.css">
+    <script
+      type="module"
+      src="/public/design-system/components/index.js"
+    ></script>
     <title>Offline - MrJuneJune</title>
     <style>
       body {
@@ -13,30 +20,34 @@
         justify-content: center;
         min-height: 100vh;
         margin: 0;
-        padding: 20px;
+        padding: var(--zenbu-sys-padding-lg);
         background: linear-gradient(135deg, #544e43 0%, #3a3630 100%);
         color: white;
         text-align: center;
       }
 
       h1 {
-        font-size: 3em;
+        font-size: var(--zenbu-sys-font-size-3xl);
         margin: 0 0 0.5em 0;
       }
 
       p {
-        font-size: 1.2em;
+        font-size: var(--zenbu-sys-font-size-lg);
+        line-height: var(--zenbu-sys-line-height-lg);
         margin: 0 0 2em 0;
         opacity: 0.9;
       }
 
       button {
-        padding: 12px 32px;
-        font-size: 1em;
+        min-height: var(--zenbu-control-height);
+        padding:
+          var(--zenbu-control-padding-block)
+          var(--zenbu-control-padding-inline);
+        font-size: var(--zenbu-control-font-size);
         background: white;
         color: #544e43;
         border: none;
-        border-radius: 8px;
+        border-radius: var(--zenbu-sys-radius-control);
         cursor: pointer;
         font-weight: bold;
         transition: transform 0.2s;
@@ -53,9 +64,13 @@
     </style>
   </head>
   <body>
-    <div class="icon">📡</div>
+    <div class="icon">
+      <zen-icon name="offline" label="Offline"></zen-icon>
+    </div>
     <h1>You're Offline</h1>
     <p>It looks like you've lost your internet connection.<br>Don't worry, some cached pages might still work!</p>
-    <button onclick="window.location.reload()">Try Again</button>
+    <zen-button appearance="plain" size="lg">
+      <button onclick="window.location.reload()">Try Again</button>
+    </zen-button>
   </body>
 </html>
--- a/mrjunejune/src/parts/header.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/parts/header.html	Wed Aug 05 05:25:40 2026 -0700
@@ -18,16 +18,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -35,7 +30,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -137,7 +131,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -151,11 +145,11 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
--- a/mrjunejune/src/public/pwa-register.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/public/pwa-register.js	Wed Aug 05 05:25:40 2026 -0700
@@ -57,7 +57,11 @@
   const installBtn = document.createElement('button');
   installBtn.classList.add('with-icon');
   installBtn.id = 'pwa-install-btn';
-  installBtn.textContent = 'Install as App';
+  const installIcon = document.createElement('zen-icon');
+  installIcon.setAttribute('name', 'download');
+  const installLabel = document.createElement('span');
+  installLabel.textContent = 'Install as App';
+  installBtn.append(installIcon, installLabel);
 
   installBtn.addEventListener('click', async () => {
     if (!deferredPrompt) return;
@@ -70,12 +74,16 @@
     installBtn.remove();
   });
 
-  document.body.appendChild(installBtn);
+  const wrapper = document.createElement('zen-button');
+  wrapper.setAttribute('appearance', 'plain');
+  wrapper.setAttribute('size', 'md');
+  wrapper.append(installBtn);
+  document.body.appendChild(wrapper);
 
   setTimeout(() => {
     installBtn.style.opacity = '0';
     installBtn.style.transition = 'opacity 0.3s';
-    setTimeout(() => installBtn.remove(), 300);
+    setTimeout(() => wrapper.remove(), 300);
   }, 5000);
 }
 
@@ -84,5 +92,5 @@
   deferredPrompt = null;
 
   const installBtn = document.getElementById('pwa-install-btn');
-  if (installBtn) installBtn.remove();
+  if (installBtn) installBtn.closest('zen-button')?.remove();
 });
--- a/mrjunejune/src/resume/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/resume/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -10,7 +10,7 @@
     {{/parts/header.html}}
     <main>
       <div class="info">
-        <a href="/public/resume.pdf">Download PDF</a>
+        <a href="/public/resume.pdf" data-zen-link-effect="none">Download PDF</a>
         <hr>
         <p><span class="header-firstname-style"> JUNTAE </span><span class="header-lastname-style">PARK</span><p>
         <p class="header-position-style"> MEMBER OF TECHNICAL STAFF &middot; SOFTWARE ENGINEER </p>
--- a/mrjunejune/src/sw.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/sw.js	Wed Aug 05 05:25:40 2026 -0700
@@ -1,16 +1,20 @@
 // Root-scoped Service Worker for MrJuneJune PWA
-const CACHE_VERSION = 'v5-zenbu-themes';
+const CACHE_VERSION = 'v6-zenbu-headless';
 const CACHE_NAME = `mrjunejune-${CACHE_VERSION}`;
 
 // Files to cache immediately on install
 const STATIC_CACHE = [
   '/',
+  '/offline.html',
   '/index.js',
   '/base.css',
   '/public/design-system/styles/tokens.css',
+  '/public/design-system/styles/reference.css',
+  '/public/design-system/styles/semantic.css',
+  '/public/design-system/styles/density.css',
   '/public/design-system/styles/themes.css',
   '/public/design-system/styles/components.css',
-  '/public/design-system/styles/shadcn.css',
+  '/public/design-system/styles/elements.css',
   '/public/design-system/components/index.js',
   '/public/design-system/components/alert.js',
   '/public/design-system/components/button.js',
@@ -20,6 +24,7 @@
   '/public/design-system/components/field.js',
   '/public/design-system/components/forms.js',
   '/public/design-system/components/icon.js',
+  '/public/design-system/components/link.js',
   '/public/design-system/components/notifications.js',
   '/public/design-system/components/overlays.js',
   '/public/design-system/components/primitives.js',
--- a/mrjunejune/src/talk/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/talk/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -5,8 +5,8 @@
   <title>Talk!</title>
   {{/parts/base_head.html}}
   <style>
-    body { font-family: sans-serif; padding: 20px; }
-    #messages { height: 200px; border: 1px solid #ccc; overflow-y: scroll; margin-bottom: 10px; padding: 10px; }
+    body { font-family: sans-serif; padding: var(--zenbu-sys-padding-lg); }
+    #messages { height: 200px; border: 1px solid #ccc; overflow-y: scroll; margin-bottom: var(--zenbu-sys-space-control); padding: var(--zenbu-sys-padding-md); }
     #chat { display: flex; gap: 10px; }
     input { flex-grow: 1; }
   </style>
@@ -19,8 +19,12 @@
     <div id="messages"></div>
 
     <div id="chat">
-      <input type="text" id="messageInput" placeholder="Type a message...">
-      <button id="sendBtn">Send</button>
+      <zen-input appearance="plain" size="md">
+        <input type="text" id="messageInput" placeholder="Type a message...">
+      </zen-input>
+      <zen-button appearance="plain" size="md">
+        <button id="sendBtn">Send</button>
+      </zen-button>
     </div>
   </main>
   {{/parts/footer.html}}
--- a/mrjunejune/src/tools/file_converter/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/file_converter/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -9,13 +9,13 @@
         .container {
             max-width: 800px;
             margin: 2rem auto;
-            padding: 2rem;
+            padding: var(--zenbu-sys-padding-xl);
         }
 
         .converter-section {
-            border-radius: 8px;
+            border-radius: var(--zenbu-sys-radius-control);
             border: 2px solid var(--lightgray);
-            padding: 2rem;
+            padding: var(--zenbu-sys-padding-xl);
             margin-bottom: 2rem;
         }
 
@@ -35,11 +35,11 @@
         }
 
         input[type="file"] {
-            padding: 0.75rem;
+            padding: var(--zenbu-sys-padding-sm);
             border: 2px dashed #ccc;
-            border-radius: 4px;
+            border-radius: var(--zenbu-sys-radius-control-small);
             background: white;
-            font-size: 16px;
+            font-size: var(--zenbu-sys-font-size-md);
         }
 
         button {
@@ -47,12 +47,9 @@
             font-family: "More Thin", sans-serif;
             color: var(--gray-gradient);
             border: none;
-            padding: 0.75rem 1.5rem;
-            border-radius: 4px;
+            border-radius: var(--zenbu-sys-radius-control-small);
             cursor: pointer;
-            font-size: 1rem;
             margin-top: 1rem;
-            min-height: 44px;
         }
 
         button:hover {
@@ -66,9 +63,9 @@
 
         .result {
             margin-top: 1rem;
-            padding: 1rem;
+            padding: var(--zenbu-sys-padding-md);
             background: white;
-            border-radius: 4px;
+            border-radius: var(--zenbu-sys-radius-control-small);
             display: none;
         }
 
@@ -107,30 +104,28 @@
         /* Mobile responsive */
         @media (max-width: 720px) {
             .container {
-                padding: 1rem;
+                padding: var(--zenbu-sys-padding-md);
                 margin: 1rem auto;
             }
 
             .converter-section {
-                padding: 1.5rem 1rem;
+                padding:
+                  var(--zenbu-sys-padding-lg)
+                  var(--zenbu-sys-padding-md);
             }
 
             .converter-section h2 {
-                font-size: 1.5rem;
+                font-size: var(--zenbu-sys-font-size-2xl);
             }
 
             .file-input-wrapper label {
-                font-size: 1rem;
+                font-size: var(--zenbu-sys-font-size-md);
             }
 
-            button {
-                font-size: 1.1rem;
-                padding: 1rem 1.5rem;
-            }
 
             .result {
-                padding: 1rem;
-                font-size: 1rem;
+                padding: var(--zenbu-sys-padding-md);
+                font-size: var(--zenbu-sys-font-size-md);
             }
         }
     </style>
@@ -148,10 +143,14 @@
 
             <div class="file-input-wrapper">
                 <label for="imageInput">Choose an image file:</label>
-                <input type="file" id="imageInput" accept="image/*">
+                <zen-input appearance="plain" size="md">
+                  <input type="file" id="imageInput" accept="image/*">
+                </zen-input>
             </div>
 
-            <button id="convertImageBtn" onclick="convertImageToWebP()">Convert to WebP</button>
+            <zen-button appearance="plain" size="md">
+              <button id="convertImageBtn" onclick="convertImageToWebP()">Convert to WebP</button>
+            </zen-button>
 
             <div class="loading" id="imageLoading">Converting... Please wait.</div>
 
@@ -167,10 +166,14 @@
 
             <div class="file-input-wrapper">
                 <label for="videoInput">Choose a video file:</label>
-                <input type="file" id="videoInput" accept="video/*">
+                <zen-input appearance="plain" size="md">
+                  <input type="file" id="videoInput" accept="video/*">
+                </zen-input>
             </div>
 
-            <button id="convertVideoBtn" onclick="convertVideoToMP4()">Convert to MP4</button>
+            <zen-button appearance="plain" size="md">
+              <button id="convertVideoBtn" onclick="convertVideoToMP4()">Convert to MP4</button>
+            </zen-button>
 
             <div class="loading" id="videoLoading">Converting... Please wait.</div>
 
--- a/mrjunejune/src/tools/hls_player/index.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/hls_player/index.css	Wed Aug 05 05:25:40 2026 -0700
@@ -14,27 +14,28 @@
   gap: 0.6rem;
 }
 
-.hls-url-row input,
-.hls-url-row button {
-  min-height: 44px;
-  font: inherit;
+.hls-url-row input {
+  min-height: var(--zenbu-sys-control-height-md);
+  font-size: var(--zenbu-sys-font-size-md);
+  line-height: var(--zenbu-sys-line-height-md);
 }
 
 .hls-url-row input {
   width: 100%;
-  padding: 0.65rem 0.8rem;
+  padding:
+    var(--zenbu-sys-control-padding-block-md)
+    var(--zenbu-sys-control-padding-inline-md);
   color: var(--gray-dark);
   background: var(--white);
   border: 1px solid var(--darkgray);
-  border-radius: 6px;
+  border-radius: var(--zenbu-sys-radius-control-small);
 }
 
 .hls-url-row button {
-  padding: 0.65rem 1rem;
   color: var(--white);
   background: var(--darkgray);
   border: 1px solid var(--darkgray);
-  border-radius: 6px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   cursor: pointer;
 }
 
@@ -48,7 +49,7 @@
 .hls-player-shell {
   overflow: hidden;
   border: 1px solid var(--darkgray);
-  border-radius: 8px;
+  border-radius: var(--zenbu-sys-radius-control);
   background: #10131a;
 }
 
@@ -56,7 +57,7 @@
   margin: 1rem 0 1.5rem;
   padding: 0.9rem;
   border: 1px solid var(--gray-light);
-  border-radius: 8px;
+  border-radius: var(--zenbu-sys-radius-control);
 }
 
 .hls-local-picker legend {
@@ -77,11 +78,15 @@
 .hls-file-button {
   display: inline-flex;
   align-items: center;
-  min-height: 44px;
-  padding: 0.65rem 1rem;
+  min-height: var(--zenbu-sys-control-height-md);
+  padding:
+    var(--zenbu-sys-control-padding-block-md)
+    var(--zenbu-sys-control-padding-inline-md);
+  font-size: var(--zenbu-sys-font-size-md);
+  line-height: var(--zenbu-sys-line-height-md);
   color: var(--white);
   background: var(--darkgray);
-  border-radius: 6px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   cursor: pointer;
 }
 
@@ -107,9 +112,9 @@
 }
 
 .hls-status {
-  min-height: 2.75rem;
+  min-height: var(--zenbu-sys-control-height-md);
   margin: 0;
-  padding: 0.65rem 0.9rem;
+  padding: var(--zenbu-sys-padding-sm);
   color: #f3f5f8;
   background: #171b24;
 }
@@ -138,7 +143,7 @@
 .hls-details div {
   padding: 0.7rem;
   border: 1px solid var(--gray-light);
-  border-radius: 6px;
+  border-radius: var(--zenbu-sys-radius-control-small);
 }
 
 .hls-details dt {
--- a/mrjunejune/src/tools/hls_player/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/hls_player/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -16,17 +16,23 @@
       <form id="hlsForm" class="hls-form">
         <label for="hlsUrl">Playlist URL</label>
         <div class="hls-url-row">
-          <input
-            id="hlsUrl"
-            name="url"
-            type="text"
-            inputmode="url"
-            value="/public/hls-sample/h264-ts-stream.m3u8"
-            placeholder="https://example.com/stream.m3u8"
-            required
-          />
-          <button type="submit">Load</button>
-          <button id="sampleButton" type="button">Sample</button>
+          <zen-input appearance="plain" size="md">
+            <input
+              id="hlsUrl"
+              name="url"
+              type="text"
+              inputmode="url"
+              value="/public/hls-sample/h264-ts-stream.m3u8"
+              placeholder="https://example.com/stream.m3u8"
+              required
+            />
+          </zen-input>
+          <zen-button appearance="plain" size="md">
+            <button type="submit">Load</button>
+          </zen-button>
+          <zen-button appearance="plain" size="md">
+            <button id="sampleButton" type="button">Sample</button>
+          </zen-button>
         </div>
       </form>
 
@@ -36,21 +42,25 @@
         <div class="hls-local-actions">
           <label class="hls-file-button">
             Choose HLS files
-            <input
-              id="hlsFiles"
-              type="file"
-              accept=".m3u8,.m4s,.mp4,.ts,.aac,.vtt,.key,application/vnd.apple.mpegurl"
-              multiple
-            />
+            <zen-input appearance="plain" size="md">
+              <input
+                id="hlsFiles"
+                type="file"
+                accept=".m3u8,.m4s,.mp4,.ts,.aac,.vtt,.key,application/vnd.apple.mpegurl"
+                multiple
+              />
+            </zen-input>
           </label>
           <label class="hls-file-button">
             Choose HLS folder
-            <input
-              id="hlsFolder"
-              type="file"
-              webkitdirectory
-              multiple
-            />
+            <zen-input appearance="plain" size="md">
+              <input
+                id="hlsFolder"
+                type="file"
+                webkitdirectory
+                multiple
+              />
+            </zen-input>
           </label>
         </div>
       </fieldset>
--- a/mrjunejune/src/tools/latex_editor/index.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/latex_editor/index.css	Wed Aug 05 05:25:40 2026 -0700
@@ -25,12 +25,14 @@
   gap: 0.65rem;
 }
 
+.latex-actions zen-button {
+  display: inline-flex;
+}
+
 .latex-actions button,
 .button-link {
-  min-height: 42px;
-  padding: 0.65rem 1rem;
   border: 2px solid var(--black);
-  border-radius: 8px;
+  border-radius: var(--zenbu-sys-radius-control);
   background: var(--awesome);
   color: var(--black);
   font: inherit;
@@ -86,7 +88,7 @@
   min-width: 0;
   overflow: hidden;
   border: 2px solid var(--black);
-  border-radius: 12px;
+  border-radius: var(--zenbu-sys-radius-panel);
   background: var(--white);
   box-shadow: 6px 6px 0 rgba(0, 0, 0, 0.12);
 }
@@ -100,9 +102,11 @@
   display: flex;
   align-items: center;
   justify-content: space-between;
-  gap: 1rem;
-  min-height: 48px;
-  padding: 0.55rem 0.8rem;
+  gap: var(--zenbu-sys-control-gap-md);
+  min-height: var(--zenbu-sys-control-height-lg);
+  padding:
+    var(--zenbu-sys-control-padding-block-sm)
+    var(--zenbu-sys-control-padding-inline-md);
   border-bottom: 2px solid var(--black);
   background: var(--gray-gradient);
 }
@@ -110,7 +114,7 @@
 .panel-heading h2,
 .panel-heading span {
   margin: 0;
-  font-size: 0.95rem;
+  font-size: var(--zenbu-sys-font-size-sm);
 }
 
 #latexSource {
@@ -120,13 +124,15 @@
   min-height: 540px;
   resize: vertical;
   box-sizing: border-box;
-  padding: 1rem;
+  padding: var(--zenbu-sys-padding-md);
   border: 0;
   outline: 0;
   background: #111318;
   color: #f4f4f5;
   caret-color: #f4f4f5;
-  font: 15px/1.55 ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
+  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
+  font-size: var(--zenbu-sys-font-size-sm);
+  line-height: var(--zenbu-sys-line-height-md);
   tab-size: 2;
 }
 
@@ -198,4 +204,12 @@
     flex: 1 1 45%;
     text-align: center;
   }
+
+  .latex-actions zen-button {
+    flex: 1 1 45%;
+  }
+
+  .latex-actions zen-button > :where(button, a) {
+    width: 100%;
+  }
 }
--- a/mrjunejune/src/tools/latex_editor/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/latex_editor/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -15,13 +15,21 @@
           <p>Write LaTeX here. My server compiles it inside a locked-down sandbox and sends the PDF back to this preview.</p>
         </div>
         <div class="latex-actions">
-          <label class="auto-compile">
-            <input id="autoCompile" type="checkbox" checked />
-            Auto compile
-          </label>
-          <button id="resetButton" type="button" class="secondary">Reset</button>
-          <button id="compileButton" type="button">Compile PDF</button>
-          <a id="downloadButton" class="button-link disabled" aria-disabled="true">Download</a>
+          <zen-checkbox appearance="plain" size="sm">
+            <label class="auto-compile">
+              <input id="autoCompile" type="checkbox" checked />
+              Auto compile
+            </label>
+          </zen-checkbox>
+          <zen-button appearance="plain" size="md">
+            <button id="resetButton" type="button" class="secondary">Reset</button>
+          </zen-button>
+          <zen-button appearance="plain" size="md">
+            <button id="compileButton" type="button">Compile PDF</button>
+          </zen-button>
+          <zen-button appearance="plain" size="md">
+            <a id="downloadButton" class="button-link disabled" aria-disabled="true">Download</a>
+          </zen-button>
         </div>
       </div>
 
@@ -35,7 +43,8 @@
             <h2 id="sourceHeading">document.tex</h2>
             <span id="sourceSize">0 / 65,536 bytes</span>
           </div>
-          <textarea id="latexSource" spellcheck="false" autocomplete="off" aria-label="LaTeX source" placeholder="Type your LaTeX document here...">\documentclass[11pt]{article}
+          <zen-textarea appearance="plain" size="md">
+            <textarea id="latexSource" spellcheck="false" autocomplete="off" aria-label="LaTeX source" placeholder="Type your LaTeX document here...">\documentclass[11pt]{article}
 \usepackage[margin=1in]{geometry}
 \usepackage{amsmath}
 \usepackage{xcolor}
@@ -57,6 +66,7 @@
 
 \end{document}
 </textarea>
+          </zen-textarea>
         </section>
 
         <section class="latex-panel preview-panel" aria-labelledby="previewHeading">
--- a/mrjunejune/src/tools/markdown_to_html/index.css	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/markdown_to_html/index.css	Wed Aug 05 05:25:40 2026 -0700
@@ -6,7 +6,7 @@
 
 body {
   line-height: 1.6;
-  padding: 20px;
+  padding: var(--zenbu-sys-padding-lg);
   max-width: 1400px;
   margin: 0 auto;
 }
@@ -24,7 +24,7 @@
 .container {
   display: grid;
   grid-template-columns: 1fr 1fr;
-  gap: 20px;
+  gap: var(--zenbu-sys-space-container);
   height: calc(100vh - 200px);
   min-height: 500px;
 }
@@ -33,9 +33,9 @@
   display: flex;
   flex-direction: column;
   background: var(--white);
-  border-radius: 8px;
+  border-radius: var(--zenbu-sys-radius-control);
   border: 1px solid rgba(var(--gray), 0.3);
-  padding: 15px;
+  padding: var(--zenbu-sys-padding-md);
   overflow: hidden;
 }
 
@@ -50,7 +50,7 @@
 .label {
   font-weight: 600;
   color: var(--gray-dark);
-  font-size: 14px;
+  font-size: var(--zenbu-sys-font-size-sm);
   text-transform: uppercase;
   letter-spacing: 0.5px;
 }
@@ -59,10 +59,8 @@
   background: var(--accent);
   color: var(--white);
   border: none;
-  padding: 8px 16px;
-  border-radius: 4px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   cursor: pointer;
-  font-size: 14px;
   transition: background 0.2s;
 }
 
@@ -74,13 +72,14 @@
 textarea {
   flex: 1;
   width: 100%;
-  padding: 15px;
+  padding: var(--zenbu-sys-padding-md);
   background: var(--gray-light);
   color: var(--gray-dark);
   border: 1px solid rgba(var(--gray), 0.3);
-  border-radius: 4px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
-  font-size: 14px;
+  font-size: var(--zenbu-sys-font-size-sm);
+  line-height: var(--zenbu-sys-line-height-sm);
   line-height: 1.5;
   resize: none;
 }
@@ -93,13 +92,14 @@
 /* Output panel */
 #output {
   flex: 1;
-  padding: 15px;
+  padding: var(--zenbu-sys-padding-md);
   border: 1px solid rgba(var(--gray), 0.3);
-  border-radius: 4px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   background: var(--white);
   color: var(--gray-dark);
   overflow-y: auto;
-  font-size: 15px;
+  font-size: var(--zenbu-sys-font-size-sm);
+  line-height: var(--zenbu-sys-line-height-sm);
 }
 
 /* Markdown output styles */
@@ -134,7 +134,7 @@
 #output code {
   background: var(--gray-light);
   padding: 2px 6px;
-  border-radius: 3px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   font-family: 'SF Mono', 'Monaco', 'Consolas', monospace;
   font-size: 0.9em;
   color: var(--accent);
@@ -144,7 +144,7 @@
   background: var(--black);
   color: var(--white);
   padding: 15px;
-  border-radius: 6px;
+  border-radius: var(--zenbu-sys-radius-control-small);
   overflow-x: auto;
   margin: 1em 0;
   line-height: 1.4;
@@ -183,7 +183,7 @@
 #output img {
   max-width: 100%;
   height: auto;
-  border-radius: 4px;
+  border-radius: var(--zenbu-sys-radius-control-small);
 }
 
 #output strong {
--- a/mrjunejune/src/tools/markdown_to_html/index.html	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/src/tools/markdown_to_html/index.html	Wed Aug 05 05:25:40 2026 -0700
@@ -15,7 +15,8 @@
     
     <div class="container">
         <div class="panel">
-            <div class="label">Markdown Input</div>
+          <zen-field appearance="plain" size="md">
+            <label class="label" for="input">Markdown Input</label>
             <textarea id="input" placeholder="Type your markdown here..."># Welcome to Markdown Converter
 
 ## Features
@@ -57,12 +58,15 @@
 ![Alt text](https://mrjunejune.com/public/epi_favicon.svg)
 
 **Try editing this text!**</textarea>
+          </zen-field>
         </div>
         
         <div class="panel">
             <div class="title">
               <div class="label">HTML Output</div>
-              <button id="copy"> Copy </button>
+              <zen-button appearance="plain" size="sm">
+                <button id="copy"> Copy </button>
+              </zen-button>
             </div>
             <div id="output"></div>
         </div>
--- a/mrjunejune/test/snapshots/blog.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/blog.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -53,16 +53,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -70,7 +65,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -172,7 +166,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -186,12 +180,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
--- a/mrjunejune/test/snapshots/resume.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/resume.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -56,16 +56,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -73,7 +68,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -175,7 +169,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -189,18 +183,18 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
     <main>
       <div class="info">
-        <a href="/public/resume.pdf">Download PDF</a>
+        <a href="/public/resume.pdf" data-zen-link-effect="none">Download PDF</a>
         <hr>
         <p><span class="header-firstname-style"> JUNTAE </span><span class="header-lastname-style">PARK</span><p>
         <p class="header-position-style"> MEMBER OF TECHNICAL STAFF &middot; SOFTWARE ENGINEER </p>
--- a/mrjunejune/test/snapshots/root.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/root.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -94,27 +94,6 @@
         cursor: pointer;
       }
 
-      .site-link-grid {
-        display: grid;
-        grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
-        gap: var(--zen-space-4);
-      }
-
-      .site-link-grid > a {
-        color: inherit;
-        text-decoration: none;
-      }
-
-      .site-link-grid zen-card,
-      .site-link-grid article {
-        height: 100%;
-      }
-
-      .site-link-grid p {
-        margin: 0;
-        color: var(--zen-color-text-muted);
-        font-size: 0.9rem;
-      }
     </style>
   </head>
   <body>
@@ -138,16 +117,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -155,7 +129,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -257,7 +230,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -271,12 +244,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
@@ -292,28 +265,12 @@
        </div>
 
        <h2>Links</h2>
-       <div class="site-link-grid">
-         <a href="https://zenbu.babocoder.com/file/tip">
-           <zen-card interactive>
-             <article><h3>Repository</h3><p>Browse the code behind these experiments.</p></article>
-           </zen-card>
-         </a>
-         <a href="/blog">
-           <zen-card interactive>
-             <article><h3>Blogs</h3><p>Thoughts, experiments, and technical notes.</p></article>
-           </zen-card>
-         </a>
-         <a href="/resume">
-           <zen-card interactive>
-             <article><h3>Resume</h3><p>Professional experience and selected work.</p></article>
-           </zen-card>
-         </a>
-         <a href="/tools">
-           <zen-card interactive>
-             <article><h3>Tools</h3><p>Small things I built for myself.</p></article>
-           </zen-card>
-         </a>
-       </div>
+       <ul>
+         <li><a href="https://zenbu.babocoder.com/file/tip">Repository</a> - Check out my code</li>
+         <li><a href="/blog">Blogs</a> - My thoughts / Experiments </li>
+         <li><a href="/resume">Resume</a> - My professional experiences </li>
+         <li><a href="/tools">Tools</a> - Things I made for myself </li>
+       </ul>
        <canvas id="background"></canvas>
        <canvas id="game"></canvas>
        <canvas id="gameUI"></canvas>
--- a/mrjunejune/test/snapshots/talk.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/talk.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -34,8 +34,8 @@
 <script src="/public/pwa-register.js" defer></script>
 
   <style>
-    body { font-family: sans-serif; padding: 20px; }
-    #messages { height: 200px; border: 1px solid #ccc; overflow-y: scroll; margin-bottom: 10px; padding: 10px; }
+    body { font-family: sans-serif; padding: var(--zenbu-sys-padding-lg); }
+    #messages { height: 200px; border: 1px solid #ccc; overflow-y: scroll; margin-bottom: var(--zenbu-sys-space-control); padding: var(--zenbu-sys-padding-md); }
     #chat { display: flex; gap: 10px; }
     input { flex-grow: 1; }
   </style>
@@ -61,16 +61,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -78,7 +73,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -180,7 +174,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -194,12 +188,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
@@ -209,8 +203,12 @@
     <div id="messages"></div>
 
     <div id="chat">
-      <input type="text" id="messageInput" placeholder="Type a message...">
-      <button id="sendBtn">Send</button>
+      <zen-input appearance="plain" size="md">
+        <input type="text" id="messageInput" placeholder="Type a message...">
+      </zen-input>
+      <zen-button appearance="plain" size="md">
+        <button id="sendBtn">Send</button>
+      </zen-button>
     </div>
   </main>
   <div style="display: flex; align-items: center; justify-content: center; margin: 30px 0px;">
--- a/mrjunejune/test/snapshots/tools.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/tools.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -54,16 +54,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -71,7 +66,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -173,7 +167,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -187,12 +181,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
--- a/mrjunejune/test/snapshots/tools_file_converter.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/tools_file_converter.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -38,13 +38,13 @@
         .container {
             max-width: 800px;
             margin: 2rem auto;
-            padding: 2rem;
+            padding: var(--zenbu-sys-padding-xl);
         }
 
         .converter-section {
-            border-radius: 8px;
+            border-radius: var(--zenbu-sys-radius-control);
             border: 2px solid var(--lightgray);
-            padding: 2rem;
+            padding: var(--zenbu-sys-padding-xl);
             margin-bottom: 2rem;
         }
 
@@ -64,11 +64,11 @@
         }
 
         input[type="file"] {
-            padding: 0.75rem;
+            padding: var(--zenbu-sys-padding-sm);
             border: 2px dashed #ccc;
-            border-radius: 4px;
+            border-radius: var(--zenbu-sys-radius-control-small);
             background: white;
-            font-size: 16px;
+            font-size: var(--zenbu-sys-font-size-md);
         }
 
         button {
@@ -76,12 +76,9 @@
             font-family: "More Thin", sans-serif;
             color: var(--gray-gradient);
             border: none;
-            padding: 0.75rem 1.5rem;
-            border-radius: 4px;
+            border-radius: var(--zenbu-sys-radius-control-small);
             cursor: pointer;
-            font-size: 1rem;
             margin-top: 1rem;
-            min-height: 44px;
         }
 
         button:hover {
@@ -95,9 +92,9 @@
 
         .result {
             margin-top: 1rem;
-            padding: 1rem;
+            padding: var(--zenbu-sys-padding-md);
             background: white;
-            border-radius: 4px;
+            border-radius: var(--zenbu-sys-radius-control-small);
             display: none;
         }
 
@@ -136,30 +133,28 @@
         /* Mobile responsive */
         @media (max-width: 720px) {
             .container {
-                padding: 1rem;
+                padding: var(--zenbu-sys-padding-md);
                 margin: 1rem auto;
             }
 
             .converter-section {
-                padding: 1.5rem 1rem;
+                padding:
+                  var(--zenbu-sys-padding-lg)
+                  var(--zenbu-sys-padding-md);
             }
 
             .converter-section h2 {
-                font-size: 1.5rem;
+                font-size: var(--zenbu-sys-font-size-2xl);
             }
 
             .file-input-wrapper label {
-                font-size: 1rem;
+                font-size: var(--zenbu-sys-font-size-md);
             }
 
-            button {
-                font-size: 1.1rem;
-                padding: 1rem 1.5rem;
-            }
 
             .result {
-                padding: 1rem;
-                font-size: 1rem;
+                padding: var(--zenbu-sys-padding-md);
+                font-size: var(--zenbu-sys-font-size-md);
             }
         }
     </style>
@@ -185,16 +180,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -202,7 +192,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -304,7 +293,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -318,12 +307,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
@@ -338,10 +327,14 @@
 
             <div class="file-input-wrapper">
                 <label for="imageInput">Choose an image file:</label>
-                <input type="file" id="imageInput" accept="image/*">
+                <zen-input appearance="plain" size="md">
+                  <input type="file" id="imageInput" accept="image/*">
+                </zen-input>
             </div>
 
-            <button id="convertImageBtn" onclick="convertImageToWebP()">Convert to WebP</button>
+            <zen-button appearance="plain" size="md">
+              <button id="convertImageBtn" onclick="convertImageToWebP()">Convert to WebP</button>
+            </zen-button>
 
             <div class="loading" id="imageLoading">Converting... Please wait.</div>
 
@@ -357,10 +350,14 @@
 
             <div class="file-input-wrapper">
                 <label for="videoInput">Choose a video file:</label>
-                <input type="file" id="videoInput" accept="video/*">
+                <zen-input appearance="plain" size="md">
+                  <input type="file" id="videoInput" accept="video/*">
+                </zen-input>
             </div>
 
-            <button id="convertVideoBtn" onclick="convertVideoToMP4()">Convert to MP4</button>
+            <zen-button appearance="plain" size="md">
+              <button id="convertVideoBtn" onclick="convertVideoToMP4()">Convert to MP4</button>
+            </zen-button>
 
             <div class="loading" id="videoLoading">Converting... Please wait.</div>
 
--- a/mrjunejune/test/snapshots/tools_hls_player.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/tools_hls_player.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -57,16 +57,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -74,7 +69,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -176,7 +170,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -190,12 +184,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
@@ -206,17 +200,23 @@
       <form id="hlsForm" class="hls-form">
         <label for="hlsUrl">Playlist URL</label>
         <div class="hls-url-row">
-          <input
-            id="hlsUrl"
-            name="url"
-            type="text"
-            inputmode="url"
-            value="/public/hls-sample/h264-ts-stream.m3u8"
-            placeholder="https://example.com/stream.m3u8"
-            required
-          />
-          <button type="submit">Load</button>
-          <button id="sampleButton" type="button">Sample</button>
+          <zen-input appearance="plain" size="md">
+            <input
+              id="hlsUrl"
+              name="url"
+              type="text"
+              inputmode="url"
+              value="/public/hls-sample/h264-ts-stream.m3u8"
+              placeholder="https://example.com/stream.m3u8"
+              required
+            />
+          </zen-input>
+          <zen-button appearance="plain" size="md">
+            <button type="submit">Load</button>
+          </zen-button>
+          <zen-button appearance="plain" size="md">
+            <button id="sampleButton" type="button">Sample</button>
+          </zen-button>
         </div>
       </form>
 
@@ -226,21 +226,25 @@
         <div class="hls-local-actions">
           <label class="hls-file-button">
             Choose HLS files
-            <input
-              id="hlsFiles"
-              type="file"
-              accept=".m3u8,.m4s,.mp4,.ts,.aac,.vtt,.key,application/vnd.apple.mpegurl"
-              multiple
-            />
+            <zen-input appearance="plain" size="md">
+              <input
+                id="hlsFiles"
+                type="file"
+                accept=".m3u8,.m4s,.mp4,.ts,.aac,.vtt,.key,application/vnd.apple.mpegurl"
+                multiple
+              />
+            </zen-input>
           </label>
           <label class="hls-file-button">
             Choose HLS folder
-            <input
-              id="hlsFolder"
-              type="file"
-              webkitdirectory
-              multiple
-            />
+            <zen-input appearance="plain" size="md">
+              <input
+                id="hlsFolder"
+                type="file"
+                webkitdirectory
+                multiple
+              />
+            </zen-input>
           </label>
         </div>
       </fieldset>
--- a/mrjunejune/test/snapshots/tools_latex_editor.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/tools_latex_editor.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -56,16 +56,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -73,7 +68,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -175,7 +169,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -189,12 +183,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
@@ -205,13 +199,21 @@
           <p>Write LaTeX here. My server compiles it inside a locked-down sandbox and sends the PDF back to this preview.</p>
         </div>
         <div class="latex-actions">
-          <label class="auto-compile">
-            <input id="autoCompile" type="checkbox" checked />
-            Auto compile
-          </label>
-          <button id="resetButton" type="button" class="secondary">Reset</button>
-          <button id="compileButton" type="button">Compile PDF</button>
-          <a id="downloadButton" class="button-link disabled" aria-disabled="true">Download</a>
+          <zen-checkbox appearance="plain" size="sm">
+            <label class="auto-compile">
+              <input id="autoCompile" type="checkbox" checked />
+              Auto compile
+            </label>
+          </zen-checkbox>
+          <zen-button appearance="plain" size="md">
+            <button id="resetButton" type="button" class="secondary">Reset</button>
+          </zen-button>
+          <zen-button appearance="plain" size="md">
+            <button id="compileButton" type="button">Compile PDF</button>
+          </zen-button>
+          <zen-button appearance="plain" size="md">
+            <a id="downloadButton" class="button-link disabled" aria-disabled="true">Download</a>
+          </zen-button>
         </div>
       </div>
 
@@ -225,7 +227,8 @@
             <h2 id="sourceHeading">document.tex</h2>
             <span id="sourceSize">0 / 65,536 bytes</span>
           </div>
-          <textarea id="latexSource" spellcheck="false" autocomplete="off" aria-label="LaTeX source" placeholder="Type your LaTeX document here...">\documentclass[11pt]{article}
+          <zen-textarea appearance="plain" size="md">
+            <textarea id="latexSource" spellcheck="false" autocomplete="off" aria-label="LaTeX source" placeholder="Type your LaTeX document here...">\documentclass[11pt]{article}
 \usepackage[margin=1in]{geometry}
 \usepackage{amsmath}
 \usepackage{xcolor}
@@ -247,6 +250,7 @@
 
 \end{document}
 </textarea>
+          </zen-textarea>
         </section>
 
         <section class="latex-panel preview-panel" aria-labelledby="previewHeading">
--- a/mrjunejune/test/snapshots/tools_markdown_to_html.snapshot	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/snapshots/tools_markdown_to_html.snapshot	Wed Aug 05 05:25:40 2026 -0700
@@ -57,16 +57,11 @@
   }
 
   #themeToggle {
+    display: flex;
     flex-direction: column;
-    min-width: 4.5rem;
-    padding: 0.35rem;
-    border-radius: 1.5rem;
-  }
-
-  #themeName {
-    font-family: "More", sans-serif;
-    font-size: 0.65rem;
-    line-height: 1;
+    padding: 0;
+    border: 0;
+    background: transparent;
   }
 
   /* Professional header */
@@ -74,7 +69,6 @@
     margin: auto;
     padding: 1.5em 1em;
     font-family: "More", sans-serif;
-    box-shadow: var(--zen-shadow-sm);
     width: 720px;
     max-width: calc(100% - 2em);
     text-align: center;
@@ -176,7 +170,7 @@
   }
 </style>
 
-<zen-button id="themeControl" variant="quiet">
+<zen-button id="themeControl" appearance="plain" size="xl">
   <button
     id="themeToggle"
     type="button"
@@ -190,12 +184,12 @@
       height="50"
       width="50"
     >
-    <span id="themeName" aria-live="polite">Auto</span>
+    <span id="themeName" class="zen-visually-hidden" aria-live="polite">Auto</span>
   </button>
 </zen-button>
 
 <header>
-  <h1><a href="/">MrJuneJune</a></h1>
+  <h1><a href="/" data-zen-link-effect="none">MrJuneJune</a></h1>
 </header>
 <script src="/index.js"></script>
 
@@ -205,7 +199,8 @@
     
     <div class="container">
         <div class="panel">
-            <div class="label">Markdown Input</div>
+          <zen-field appearance="plain" size="md">
+            <label class="label" for="input">Markdown Input</label>
             <textarea id="input" placeholder="Type your markdown here..."># Welcome to Markdown Converter
 
 ## Features
@@ -247,12 +242,15 @@
 ![Alt text](https://mrjunejune.com/public/epi_favicon.svg)
 
 **Try editing this text!**</textarea>
+          </zen-field>
         </div>
         
         <div class="panel">
             <div class="title">
               <div class="label">HTML Output</div>
-              <button id="copy"> Copy </button>
+              <zen-button appearance="plain" size="sm">
+                <button id="copy"> Copy </button>
+              </zen-button>
             </div>
             <div id="output"></div>
         </div>
--- a/mrjunejune/test/theme_and_webp_test.js	Tue Aug 04 16:49:11 2026 -0700
+++ b/mrjunejune/test/theme_and_webp_test.js	Wed Aug 05 05:25:40 2026 -0700
@@ -56,6 +56,72 @@
   return files;
 }
 
+function primitiveOwnershipViolations(source) {
+  const violations = [];
+  const stack = [];
+  const voidElements = new Set([
+    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link',
+    'meta', 'param', 'source', 'track', 'wbr',
+  ]);
+  const ownerMap = {
+    button: new Set(['zen-button']),
+    select: new Set(['zen-field', 'zen-native-select', 'zen-select']),
+    textarea: new Set(['zen-field', 'zen-textarea']),
+  };
+
+  for (const token of source.matchAll(
+    /<!--[\s\S]*?-->|<\/?([a-zA-Z][\w-]*)\b([^>]*)>/g,
+  )) {
+    if (!token[1]) continue;
+    const name = token[1].toLowerCase();
+    if (token[0].startsWith('</')) {
+      while (stack.length) {
+        if (stack.pop() === name) break;
+      }
+      continue;
+    }
+
+    let owners = ownerMap[name];
+    if (name === 'input') {
+      const type = /\btype\s*=\s*["']?([^"'\s>]+)/i.exec(token[2])?.[1]
+        ?.toLowerCase() || 'text';
+      if (type === 'checkbox') {
+        owners = new Set(['zen-checkbox', 'zen-field', 'zen-switch']);
+      } else if (type === 'radio') {
+        owners = new Set(['zen-field', 'zen-radio-group']);
+      } else if (type === 'range') {
+        owners = new Set(['zen-field', 'zen-slider']);
+      } else if (type === 'date') {
+        owners = new Set(['zen-calendar', 'zen-date-picker', 'zen-field']);
+      } else {
+        owners = new Set([
+          'zen-combobox',
+          'zen-command',
+          'zen-field',
+          'zen-input',
+          'zen-input-group',
+          'zen-input-otp',
+        ]);
+      }
+    }
+    if (owners) {
+      const matchingOwners = stack.filter(ancestor => owners.has(ancestor));
+      if (matchingOwners.length !== 1) {
+        violations.push({
+          control: name,
+          owners: matchingOwners,
+          source: token[0],
+        });
+      }
+    }
+
+    if (!voidElements.has(name) && !token[0].endsWith('/>')) {
+      stack.push(name);
+    }
+  }
+  return violations;
+}
+
 async function sampleTheme(browser, theme) {
   const context = await browser.newContext({ colorScheme: 'dark' });
   await context.addInitScript(value => {
@@ -125,19 +191,46 @@
         converted[2] * 0.0722;
     };
     const bodyStyle = getComputedStyle(document.body);
-    const foreground = colorLuminance(bodyStyle.color);
-    const background = colorLuminance(
-      getComputedStyle(document.querySelector('main')).backgroundColor,
+    const themeButtonStyle = getComputedStyle(
+      document.querySelector('#themeToggle'),
     );
+    const foreground = colorLuminance(bodyStyle.color);
+    const contrastProbe = document.createElement('span');
+    contrastProbe.style.background = 'var(--zen-color-surface)';
+    document.body.append(contrastProbe);
+    const background = colorLuminance(
+      getComputedStyle(contrastProbe).backgroundColor,
+    );
+    contrastProbe.remove();
     return {
-      cardCount: document.querySelectorAll('.site-link-grid zen-card').length,
-      componentReady: Boolean(customElements.get('zen-card')),
+      backgroundRepeat: bodyStyle.backgroundRepeat,
+      backgroundSize: bodyStyle.backgroundSize,
+      bodyCoversViewport: document.body.getBoundingClientRect().height >=
+        innerHeight,
+      componentReady: Boolean(customElements.get('zen-button')),
       count,
       fontFamily: getComputedStyle(document.body).fontFamily,
+      headerPaws: document.querySelectorAll(
+        'header [data-zen-link-decoration]',
+      ).length,
       luminance: count ? luminance / count : 0,
       textContrast: (Math.max(foreground, background) + 0.05) /
         (Math.min(foreground, background) + 0.05),
       rootTheme: document.documentElement.dataset.zenTheme || 'auto',
+      enhancedLinks: document.querySelectorAll(
+        'zen-link[effect="paw"] > a > zen-icon[name="paw"]',
+      ).length,
+      links: document.querySelectorAll('a').length,
+      pawLinks: [...document.querySelectorAll('a')].filter(link =>
+        !link.closest('zen-button') &&
+        link.dataset.zenLinkEffect !== 'none'
+      ).length,
+      mainBackground: getComputedStyle(
+        document.querySelector('main'),
+      ).backgroundColor,
+      themeButtonBackground: themeButtonStyle.backgroundColor,
+      themeButtonBorder: themeButtonStyle.borderTopWidth,
+      themeButtonShadow: themeButtonStyle.boxShadow,
       themeLabel: document.querySelector('#themeName')?.textContent,
     };
   });
@@ -168,6 +261,118 @@
   await context.close();
 }
 
+async function testPlainField(browser) {
+  const page = await browser.newPage();
+  await page.goto(`${baseUrl}/tools/markdown_to_html`, {
+    waitUntil: 'networkidle',
+  });
+  await page.waitForFunction(() => customElements.get('zen-field'));
+  const state = await page.locator('zen-field[appearance="plain"]').evaluate(
+    field => {
+      const label = field.querySelector('label');
+      const textarea = field.querySelector('textarea');
+      const probe = document.createElement('span');
+      probe.style.border = '1px solid var(--accent)';
+      document.body.append(probe);
+      const accent = getComputedStyle(probe).borderColor;
+      probe.remove();
+      textarea.focus();
+      return {
+        borderColor: getComputedStyle(textarea).borderColor,
+        display: getComputedStyle(field).display,
+        labelFor: label.htmlFor,
+        accent,
+        textareaId: textarea.id,
+      };
+    },
+  );
+  assert.deepEqual(state, {
+    accent: state.borderColor,
+    borderColor: state.borderColor,
+    display: 'contents',
+    labelFor: 'input',
+    textareaId: 'input',
+  });
+  await page.close();
+}
+
+async function testButtonScale(browser) {
+  const page = await browser.newPage();
+  for (const route of [
+    '/talk',
+    '/notes/login',
+    '/tools/hls_player',
+    '/tools/latex_editor',
+    '/tools/markdown_to_html',
+    '/tools/file_converter',
+    '/offline.html',
+  ]) {
+    await page.goto(`${baseUrl}${route}`, { waitUntil: 'networkidle' });
+    await page.waitForFunction(() => customElements.get('zen-button'));
+    const controls = await page.locator(
+      'zen-button[size] > :is(button, a):not(#themeToggle)',
+    ).evaluateAll(elements => elements.map(control => {
+      const host = control.parentElement;
+      const style = getComputedStyle(control);
+      const hostStyle = getComputedStyle(host);
+      return {
+        height: control.getBoundingClientRect().height,
+        minimum: Number.parseFloat(
+          hostStyle.getPropertyValue('--zenbu-control-height'),
+        ) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
+        paddingBlock: style.paddingBlockStart,
+        paddingVariable: Number.parseFloat(
+          hostStyle.getPropertyValue('--zenbu-control-padding-block'),
+        ) * Number.parseFloat(getComputedStyle(document.documentElement).fontSize),
+        size: host.getAttribute('size'),
+      };
+    }));
+    assert.ok(controls.length > 0, route);
+    for (const control of controls) {
+      assert.match(control.size, /^(?:xs|sm|md|lg|xl)$/);
+      assert.ok(control.height >= control.minimum - 1, JSON.stringify(control));
+      assert.ok(
+        Math.abs(Number.parseFloat(control.paddingBlock) -
+          control.paddingVariable) < 1,
+        JSON.stringify(control),
+      );
+    }
+  }
+  await page.close();
+}
+
+async function testDynamicButtonOwnership(browser) {
+  const page = await browser.newPage();
+  await page.goto(baseUrl, { waitUntil: 'networkidle' });
+  await page.evaluate(() => {
+    window.dispatchEvent(new Event('beforeinstallprompt', {
+      cancelable: true,
+    }));
+  });
+  const state = await page.locator('#pwa-install-btn').evaluate(button => ({
+    ownerCount: button.closest('zen-button') ? 1 : 0,
+    appearance: button.closest('zen-button')?.getAttribute('appearance'),
+    size: button.closest('zen-button')?.getAttribute('size'),
+  }));
+  assert.deepEqual(state, {
+    appearance: 'plain',
+    ownerCount: 1,
+    size: 'md',
+  });
+  await page.close();
+}
+
+async function testResumePrint(browser) {
+  const page = await browser.newPage();
+  await page.emulateMedia({ media: 'print' });
+  await page.goto(`${baseUrl}/resume`, { waitUntil: 'networkidle' });
+  assert.equal(
+    await page.locator('.info > a[href="/public/resume.pdf"]').isVisible(),
+    false,
+  );
+  await page.close();
+}
+
 async function testHlsPlayer(browser, siteRoot) {
   const page = await browser.newPage();
   const errors = [];
@@ -423,6 +628,34 @@
     baseUrl = `http://127.0.0.1:${port}`;
     const pngFiles = listFiles(siteRoot).filter(file => file.endsWith('.png'));
     assert.deepEqual(pngFiles, [], `PNG files leaked into runfiles: ${pngFiles}`);
+    for (const file of listFiles(siteRoot).filter(file =>
+      file.endsWith('.html')
+    )) {
+      const source = fs.readFileSync(file, 'utf8');
+      for (const primitive of source.matchAll(/<zen-button\b([^>]*)>/g)) {
+        assert.match(
+          primitive[1],
+          /\bsize=["'](?:xs|sm|md|lg|xl)["']/,
+          `${path.relative(siteRoot, file)} has an unsized zen-button`,
+        );
+      }
+      assert.deepEqual(
+        primitiveOwnershipViolations(source),
+        [],
+        `${path.relative(siteRoot, file)} violates primitive ownership`,
+      );
+    }
+    for (const file of listFiles(siteRoot).filter(file =>
+      /\.(?:css|html|js)$/.test(file) &&
+      !file.includes(`${path.sep}public${path.sep}design-system${path.sep}`)
+    )) {
+      const source = fs.readFileSync(file, 'utf8');
+      assert.doesNotMatch(
+        source,
+        /var\(\s*--zen-/,
+        `${path.relative(siteRoot, file)} consumes a deprecated token`,
+      );
+    }
 
     server = spawn(serverBinary, [], {
       cwd: runfilesWorkspace,
@@ -446,7 +679,7 @@
     for (const source of [home, dogGame, manifest]) {
       assert.doesNotMatch(source, /\.png(?:["')]|$)/i);
     }
-    assert.match(serviceWorker, /v5-zenbu-themes/);
+    assert.match(serviceWorker, /v6-zenbu-headless/);
     assert.match(
       await (
         await fetch(`${baseUrl}/public/pwa-register.js`)
@@ -486,15 +719,28 @@
     assert.equal(automatic.themeLabel, 'Auto');
     for (const sample of [paper, ink, playful, automatic]) {
       assert.ok(sample.count > 0);
+      assert.equal(sample.backgroundRepeat, 'no-repeat');
+      assert.equal(sample.backgroundSize, 'cover');
+      assert.equal(sample.bodyCoversViewport, true);
       assert.equal(sample.componentReady, true);
-      assert.equal(sample.cardCount, 4);
+      assert.ok(sample.links > 0);
+      assert.equal(sample.enhancedLinks, sample.pawLinks);
       assert.match(sample.fontFamily, /More/);
+      assert.equal(sample.headerPaws, 0);
       assert.ok(sample.textContrast >= 4.5, JSON.stringify(sample));
+      assert.equal(sample.mainBackground, 'rgba(0, 0, 0, 0)');
+      assert.equal(sample.themeButtonBackground, 'rgba(0, 0, 0, 0)');
+      assert.equal(sample.themeButtonBorder, '0px');
+      assert.equal(sample.themeButtonShadow, 'none');
     }
     assert.ok(paper.luminance < 175, JSON.stringify(paper));
     assert.ok(playful.luminance < 175, JSON.stringify(playful));
     assert.ok(ink.luminance > 200, JSON.stringify(ink));
     await testThemeCycle(browser);
+    await testPlainField(browser);
+    await testButtonScale(browser);
+    await testDynamicButtonOwnership(browser);
+    await testResumePrint(browser);
     await testHlsPlayer(browser, siteRoot);
   } finally {
     if (browser) await browser.close();