changeset 254:2b6e732087ff

[ui] Add complete native component catalog Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 15:12:09 -0700
parents fdf3816959cb
children 5ec271d612ae
files .claude/skills/zenbu-design-system/SKILL.md design_system/BUILD design_system/COLORS.md design_system/COMPONENTS.md design_system/ICONS.md design_system/README.md design_system/main.c design_system/src/catalog.js design_system/src/components/alert.js design_system/src/components/button.js design_system/src/components/card.js design_system/src/components/collections.js design_system/src/components/disclosure.js design_system/src/components/field.js design_system/src/components/forms.js design_system/src/components/icon.js design_system/src/components/index.js design_system/src/components/notifications.js design_system/src/components/overlays.js design_system/src/components/primitives.js design_system/src/components/stack.js design_system/src/components/story.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/shadcn.css design_system/src/styles/tokens.css design_system/test/BUILD design_system/test/design_system_policy_test.js design_system/test/storybook_test.js
diffstat 31 files changed, 8464 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/.claude/skills/zenbu-design-system/SKILL.md	Tue Aug 04 12:21:19 2026 -0700
+++ b/.claude/skills/zenbu-design-system/SKILL.md	Tue Aug 04 15:12:09 2026 -0700
@@ -30,12 +30,35 @@
 - Prefix custom elements and tokens with `zen-` / `--zen-`.
 - Keep selectors low-specificity so applications can override tokens.
 - 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
+  first-party `zen-icon` geometry.
+- Reset browser chrome for design-system form controls and restyle every state
+  with Zenbu tokens. Calendar and date-picker UI must use the first-party
+  keyboard calendar rather than exposing the browser's default date picker.
+- Browser acceptance must exercise every catalog route at desktop and mobile
+  widths and reject horizontal page overflow.
+- Preserve the warm, restrained MUJI-like visual character: paper neutrals,
+  natural material colors, strong typography, and deliberate color accents.
+- 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
+  `//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,
+  text-glyph icons, ad hoc SVG, icon fonts, and external icon packages are
+  forbidden.
+- Every exported JavaScript class, function, or constant requires Google-style
+  JSDoc with its public type tags. The policy test must fail when documentation
+  is missing.
 
 ## Bazel targets
 
 ```bash
 bazel run //design_system:dev
 bazel test //design_system/test:storybook_test
+bazel test //design_system/test:design_system_policy_test
 bazel build //design_system:design_system_server_bundle
 ```
 
--- a/design_system/BUILD	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/BUILD	Tue Aug 04 15:12:09 2026 -0700
@@ -28,6 +28,12 @@
   srcs = glob(["src/**"]),
 )
 
+filegroup(
+  name = "policy_sources",
+  srcs = glob(["src/**"]),
+  visibility = ["//design_system/test:__pkg__"],
+)
+
 cc_binary(
   name = "design_system_server",
   srcs = ["main.c"],
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/COLORS.md	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,86 @@
+# Zenbu UI color
+
+The Zenbu palette is warm, quiet, and material-oriented. Paper neutrals carry
+most surfaces; restrained natural colors provide emphasis without making the
+interface feel synthetic or overly saturated.
+
+## Primitive ramps
+
+Each family has `50`, `100`, `200`, `300`, `400`, `500`, `600`, `700`, `800`,
+`900`, and `950` steps:
+
+- `--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.
+
+Use a primitive when an application needs a precise ramp step. Primitive values
+do not change between light and dark themes.
+
+## Material aliases
+
+Material aliases make one-off composition readable:
+
+```css
+var(--zen-color-paper)
+var(--zen-color-washi)
+var(--zen-color-linen)
+var(--zen-color-sumi)
+var(--zen-color-brick)
+var(--zen-color-persimmon)
+var(--zen-color-ochre)
+var(--zen-color-moss)
+var(--zen-color-patina)
+var(--zen-color-indigo)
+var(--zen-color-plum)
+var(--zen-color-clay)
+var(--zen-color-wood)
+```
+
+## Semantic aliases
+
+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.
+
+All names use the `--zen-color-` prefix.
+
+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
+`//design_system/test:design_system_policy_test` rejects hex, functional, or
+named colors anywhere else in the design-system source.
+
+## Data colors
+
+`--zen-color-data-1` through `--zen-color-data-10` form a categorical 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.
+
+## Usage
+
+```css
+.repository-summary {
+  border: 1px solid var(--zen-color-border-muted);
+  background: var(--zen-color-surface-muted);
+  color: var(--zen-color-text);
+}
+
+.repository-summary strong {
+  color: var(--zen-color-indigo);
+}
+```
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/COMPONENTS.md	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,125 @@
+# 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.
+
+## Inventory
+
+| shadcn/ui concept | Zenbu UI element |
+| --- | --- |
+| Accordion | `zen-accordion` |
+| Alert | `zen-alert` |
+| Alert Dialog | `zen-alert-dialog` |
+| Aspect Ratio | `zen-aspect-ratio` |
+| Attachment | `zen-attachment` |
+| Avatar | `zen-avatar` |
+| Badge | `zen-badge` |
+| Breadcrumb | `zen-breadcrumb` |
+| Bubble | `zen-bubble` |
+| Button | `zen-button` |
+| Button Group | `zen-button-group` |
+| Calendar | `zen-calendar` |
+| Card | `zen-card` |
+| Carousel | `zen-carousel` |
+| Chart | `zen-chart` |
+| Checkbox | `zen-checkbox` |
+| Collapsible | `zen-collapsible` |
+| Combobox | `zen-combobox` |
+| Command | `zen-command` |
+| Context Menu | `zen-context-menu` |
+| Data Table | `zen-data-table` |
+| Date Picker | `zen-date-picker` |
+| Dialog | `zen-dialog` |
+| Direction | `zen-direction` |
+| Drawer | `zen-drawer` |
+| Dropdown Menu | `zen-dropdown-menu` |
+| Empty | `zen-empty` |
+| Field | `zen-field` |
+| Form | `zen-form` |
+| Hover Card | `zen-hover-card` |
+| Input | `zen-input` |
+| Input Group | `zen-input-group` |
+| Input OTP | `zen-input-otp` |
+| Item | `zen-item` |
+| Kbd | `zen-kbd` |
+| Label | `zen-label` |
+| Marker | `zen-marker` |
+| Menubar | `zen-menubar` |
+| Message | `zen-message` |
+| Message Scroller | `zen-message-scroller` |
+| Native Select | `zen-native-select` |
+| Navigation Menu | `zen-navigation-menu` |
+| Pagination | `zen-pagination` |
+| Popover | `zen-popover` |
+| Progress | `zen-progress` |
+| Radio Group | `zen-radio-group` |
+| Resizable | `zen-resizable` |
+| Scroll Area | `zen-scroll-area` |
+| Select | `zen-select` |
+| Separator | `zen-separator` |
+| Sheet | `zen-sheet` |
+| Sidebar | `zen-sidebar` |
+| Skeleton | `zen-skeleton` |
+| Slider | `zen-slider` |
+| Sonner | `zen-notifications` |
+| Spinner | `zen-spinner` |
+| Switch | `zen-switch` |
+| Table | `zen-table` |
+| Tabs | `zen-tabs` |
+| Textarea | `zen-textarea` |
+| Toast (deprecated) | `zen-notifications` |
+| Toggle | `zen-toggle` |
+| Toggle Group | `zen-toggle-group` |
+| Tooltip | `zen-tooltip` |
+| Typography | `zen-typography` |
+
+`zen-stack` remains a Zenbu-specific layout primitive in addition to this
+catalog.
+
+## Native HTML rules
+
+- Dialog, alert dialog, sheet, and drawer contain a real `dialog`.
+- Accordion and collapsible contain `details` and `summary`.
+- Input, textarea, select, checkbox, radio, switch, and slider contain their
+  corresponding native form controls.
+- Calendar and date picker keep a native date value for form submission while
+  rendering the first-party keyboard month grid. The browser date-picker chrome
+  is not exposed.
+- Table and data table contain a real `table`; pagination and breadcrumbs use
+  native links in a `nav`.
+- Button-like components contain native `button` or `a` elements.
+- Components do not own application data, network requests, routing, or
+  persistence.
+
+## Interactive hooks
+
+| 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 |
+| 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-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 }` |
+| `zen-input-otp` | one native input, optional `[data-zen-otp-slots]` | `zen-complete` with `{ value }` |
+| `zen-calendar`, `zen-date-picker` | native date input plus generated month grid | native `input`/`change` and `zen-change` |
+| `zen-carousel` | `[data-zen-viewport]`, `[data-zen-prev]`, `[data-zen-next]` | `zen-change` with `{ index }` |
+| `zen-resizable` | two `[data-zen-panel]` elements and `[data-zen-handle]` | `zen-resize` with `{ percent }` |
+| `zen-data-table` | `button[data-zen-sort]` and matching cell `data-key` values | `zen-sort` |
+
+All custom events bubble but remain inside their current DOM tree unless a
+component-specific document says otherwise. Application code should listen at
+the nearest owning feature boundary.
+
+## Catalog
+
+Every inventory row has a route at `/components/<name>`, a rendered example,
+and copyable HTML source in the Seobeo-backed catalog:
+
+```bash
+bazel run //design_system:dev
+```
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/ICONS.md	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,40 @@
+# Zenbu UI icons
+
+`zen-icon` is the only icon renderer used by Zenbu UI. It renders first-party
+SVG geometry in light DOM, inherits the current text color, and has no font,
+emoji, package, or network dependency.
+
+```html
+<zen-icon name="search"></zen-icon>
+<zen-icon name="archive" label="Archive repository" size="1.25rem"></zen-icon>
+```
+
+Icons without `label` are decorative and receive `aria-hidden="true"`. An icon
+with a label receives `role="img"` and the matching accessible name. Buttons
+that already have an accessible name should use an unlabeled icon.
+
+## Names
+
+The initial set contains:
+
+```text
+add alert archive arrow-down arrow-left arrow-right arrow-up
+branch calendar check chevron-down chevron-left chevron-right chevron-up
+close code copy download error external file folder history info
+menu moon more pause play repository retry search settings sun
+trash upload user
+```
+
+Unknown names render the `alert` fallback rather than inserting authored HTML.
+The catalog at `/icons` renders the authoritative runtime list.
+
+## Hard requirements
+
+- Do not use emoji or text glyphs as interface icons.
+- Do not add inline SVG outside `components/icon.js`.
+- Do not import an external icon package or icon font.
+- Use `currentColor` through `zen-icon`; the owning component must obtain that
+  color from a `--zen-color-*` token.
+- Add new geometry to the first-party icon registry and include a catalog test.
+
+`//design_system/test:design_system_policy_test` enforces these requirements.
--- a/design_system/README.md	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/README.md	Tue Aug 04 15:12:09 2026 -0700
@@ -4,6 +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
+[`COMPONENTS.md`](COMPONENTS.md) for the complete mapping and HTML contracts.
+
 ## Catalog
 
 Run the Seobeo-backed component catalog:
@@ -50,11 +55,22 @@
 ```
 
 Every visual token is a `--zen-*` custom property and can be overridden by the
-application.
+application. See [`COLORS.md`](COLORS.md) for the complete warm color ramps,
+material aliases, semantic roles, dark-theme behavior, and data palette.
+
+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.
+
+All exported JavaScript APIs use Google-style JSDoc. The policy target checks
+the documentation contract along with token-only colors and first-party icons.
+
+The catalog navigation is searchable with `/`, and every route is exercised at
+desktop and mobile widths. Form controls reset browser chrome; date selection
+uses Zenbu's first-party keyboard calendar.
 
 ## Native HTML contract
 
-| Component | Native content | Attributes | Events |
+| 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 |
@@ -62,6 +78,10 @@
 | `zen-field` | direct `label`, form control, help text | 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` |
+| Dialogs and menus | native `dialog`, buttons, links | `placement`, native attributes | native click/close |
+| Form controls | native input, select, textarea, fieldset | native control attributes | native form events |
+| Collections | table, article, section, scroll containers | component-specific data hooks | `zen-change`, `zen-sort`, `zen-resize` |
 
 Do not put business state into the design-system components. They provide
 presentation, small accessibility wiring, and interaction affordances while
--- a/design_system/main.c	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/main.c	Tue Aug 04 15:12:09 2026 -0700
@@ -3,6 +3,76 @@
 #include <stdlib.h>
 #include <string.h>
 
+static const char *const COMPONENT_PATHS[] = {
+    "/components/accordion",
+    "/components/alert",
+    "/components/alert-dialog",
+    "/components/aspect-ratio",
+    "/components/attachment",
+    "/components/avatar",
+    "/components/badge",
+    "/components/breadcrumb",
+    "/components/bubble",
+    "/components/button",
+    "/components/button-group",
+    "/components/calendar",
+    "/components/card",
+    "/components/carousel",
+    "/components/chart",
+    "/components/checkbox",
+    "/components/collapsible",
+    "/components/combobox",
+    "/components/command",
+    "/components/context-menu",
+    "/components/data-table",
+    "/components/date-picker",
+    "/components/dialog",
+    "/components/direction",
+    "/components/drawer",
+    "/components/dropdown-menu",
+    "/components/empty",
+    "/components/field",
+    "/components/form",
+    "/components/hover-card",
+    "/components/input",
+    "/components/input-group",
+    "/components/input-otp",
+    "/components/item",
+    "/components/kbd",
+    "/components/label",
+    "/components/marker",
+    "/components/menubar",
+    "/components/message",
+    "/components/message-scroller",
+    "/components/native-select",
+    "/components/navigation-menu",
+    "/components/notifications",
+    "/components/pagination",
+    "/components/popover",
+    "/components/progress",
+    "/components/radio-group",
+    "/components/resizable",
+    "/components/scroll-area",
+    "/components/select",
+    "/components/separator",
+    "/components/sheet",
+    "/components/sidebar",
+    "/components/skeleton",
+    "/components/slider",
+    "/components/sonner",
+    "/components/spinner",
+    "/components/stack",
+    "/components/switch",
+    "/components/table",
+    "/components/tabs",
+    "/components/textarea",
+    "/components/toast",
+    "/components/toggle",
+    "/components/toggle-group",
+    "/components/tooltip",
+    "/components/typography",
+};
+
 static Seobeo_Request_Entry *Get_Component_Catalog(
     Seobeo_Request_Entry *request,
     Dowa_Arena *arena)
@@ -71,13 +141,17 @@
   Seobeo_Router_Init();
   Seobeo_Router_Register("GET", "/", Get_Component_Catalog);
   Seobeo_Router_Register("GET", "/tokens", Get_Component_Catalog);
+  Seobeo_Router_Register("GET", "/icons", Get_Component_Catalog);
   Seobeo_Router_Register("GET", "/components", Get_Component_Catalog);
-  Seobeo_Router_Register("GET", "/components/button", Get_Component_Catalog);
-  Seobeo_Router_Register("GET", "/components/card", Get_Component_Catalog);
-  Seobeo_Router_Register("GET", "/components/alert", Get_Component_Catalog);
-  Seobeo_Router_Register("GET", "/components/field", Get_Component_Catalog);
-  Seobeo_Router_Register("GET", "/components/notifications", Get_Component_Catalog);
-  Seobeo_Router_Register("GET", "/components/stack", Get_Component_Catalog);
+  for (size_t i = 0;
+       i < sizeof(COMPONENT_PATHS) / sizeof(COMPONENT_PATHS[0]);
+       i++)
+  {
+    Seobeo_Router_Register(
+        "GET",
+        COMPONENT_PATHS[i],
+        Get_Component_Catalog);
+  }
 
   const char *port = getenv("DESIGN_SYSTEM_PORT");
   if (!port || port[0] == '\0')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/catalog.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,732 @@
+/** @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>`,
+  },
+];
+
+/** @const {number} Number of mapped shadcn component concepts. */
+export const shadcnComponentCount = componentCatalog.length;
--- a/design_system/src/components/alert.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/alert.js	Tue Aug 04 15:12:09 2026 -0700
@@ -1,3 +1,8 @@
+/**
+ * Presents a semantic status message with optional dismissal.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenAlert extends HTMLElement {
   static get observedAttributes() {
     return ["dismissible", "tone"];
@@ -50,7 +55,9 @@
       dismiss.dataset.zenDismiss = "";
       dismiss.dataset.zenGenerated = "true";
       dismiss.setAttribute("aria-label", "Dismiss message");
-      dismiss.textContent = "×";
+      const icon = document.createElement("zen-icon");
+      icon.setAttribute("name", "close");
+      dismiss.append(icon);
       this.append(dismiss);
     }
     if (dismiss === this._dismissControl) return;
--- a/design_system/src/components/button.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/button.js	Tue Aug 04 15:12:09 2026 -0700
@@ -1,3 +1,8 @@
+/**
+ * Enhances a native button or link with disabled and loading states.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenButton extends HTMLElement {
   static get observedAttributes() {
     return ["disabled", "loading"];
--- a/design_system/src/components/card.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/card.js	Tue Aug 04 15:12:09 2026 -0700
@@ -1,3 +1,8 @@
+/**
+ * Provides presentation for a native article or section.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenCard extends HTMLElement {}
 
 if (!customElements.get("zen-card")) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/collections.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,579 @@
+const HTMLElementBase = globalThis.HTMLElement || class {};
+
+function rememberAttribute(state, element, name) {
+  let attributes = state.get(element);
+  if (!attributes) {
+    attributes = new Map();
+    state.set(element, attributes);
+  }
+  if (!attributes.has(name)) {
+    attributes.set(name, element.getAttribute(name));
+  }
+}
+
+function setManagedAttribute(state, element, name, value) {
+  rememberAttribute(state, element, name);
+  if (value === null) element.removeAttribute(name);
+  else element.setAttribute(name, value);
+}
+
+function originalAttribute(state, element, name) {
+  const attributes = state.get(element);
+  return attributes?.has(name)
+    ? attributes.get(name)
+    : element.getAttribute(name);
+}
+
+function restoreElement(state, element) {
+  const attributes = state.get(element);
+  if (!attributes) return;
+  for (const [name, value] of attributes) {
+    if (value === null) element.removeAttribute(name);
+    else element.setAttribute(name, value);
+  }
+  state.delete(element);
+}
+
+function restoreAttributes(state) {
+  for (const element of [...state.keys()]) restoreElement(state, element);
+}
+
+function pruneAttributes(state, retained) {
+  for (const element of [...state.keys()]) {
+    if (!retained.has(element)) restoreElement(state, element);
+  }
+}
+
+function setDefaultAttribute(state, element, name, value) {
+  if (!element.hasAttribute(name) || state.get(element)?.has(name)) {
+    setManagedAttribute(state, element, name, value);
+  }
+}
+
+function eventElement(event) {
+  const target = event.target;
+  if (target?.nodeType === 1) return target;
+  return target?.parentElement || null;
+}
+
+function ownedElement(host, selector) {
+  return [...host.querySelectorAll(selector)].find(
+    element => element.closest(host.localName) === host,
+  ) || null;
+}
+
+function emit(element, type, detail) {
+  element.dispatchEvent(new CustomEvent(type, {
+    bubbles: true,
+    detail,
+  }));
+}
+
+function isDisabled(control) {
+  return Boolean(control?.disabled) ||
+    control?.getAttribute("aria-disabled") === "true";
+}
+
+/**
+ * Enhances a native scroll-snap viewport with navigation controls.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenCarousel extends HTMLElementBase {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onClick ||= event => {
+      const control = eventElement(event)?.closest(
+        "[data-zen-prev], [data-zen-next]",
+      );
+      if (control === this._prev && !isDisabled(control)) this.move(-1);
+      else if (control === this._next && !isDisabled(control)) this.move(1);
+    };
+    this._onKeydown ||= event => {
+      if (event.altKey || event.ctrlKey || event.metaKey ||
+          !["ArrowLeft", "ArrowRight"].includes(event.key)) {
+        return;
+      }
+      const target = eventElement(event);
+      if (target?.closest("input, textarea, select, [contenteditable]")) return;
+      event.preventDefault();
+      this.move(event.key === "ArrowLeft" ? -1 : 1);
+    };
+    this._onScroll ||= () => {
+      globalThis.clearTimeout(this._scrollTimer);
+      this._scrollTimer = globalThis.setTimeout(() => {
+        this._scrollTimer = null;
+        this.setIndex(this.currentIndex(), true);
+      }, 100);
+    };
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("keydown", this._onKeydown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("keydown", this._onKeydown);
+    this._viewport?.removeEventListener("scroll", this._onScroll);
+    globalThis.clearTimeout(this._scrollTimer);
+    restoreAttributes(this._managed);
+    this._viewport = null;
+    this._slides = [];
+    this._prev = null;
+    this._next = null;
+    this._index = null;
+    this._scrollTimer = null;
+  }
+
+  sync() {
+    const viewport = ownedElement(this, "[data-zen-viewport]");
+    if (viewport !== this._viewport) {
+      this._viewport?.removeEventListener("scroll", this._onScroll);
+      this._viewport = viewport;
+      viewport?.addEventListener("scroll", this._onScroll, { passive: true });
+    }
+    this._slides = viewport ? [...viewport.children] : [];
+    this._prev = ownedElement(this, "[data-zen-prev]");
+    this._next = ownedElement(this, "[data-zen-next]");
+
+    const retained = new Set([
+      this,
+      viewport,
+      this._prev,
+      this._next,
+      ...this._slides,
+    ].filter(Boolean));
+    pruneAttributes(this._managed, retained);
+    setDefaultAttribute(this._managed, this, "role", "region");
+    setDefaultAttribute(
+      this._managed,
+      this,
+      "aria-roledescription",
+      "carousel",
+    );
+    setDefaultAttribute(this._managed, this, "aria-label", "Carousel");
+    if (viewport) {
+      setDefaultAttribute(this._managed, viewport, "tabindex", "0");
+    }
+    for (const [index, slide] of this._slides.entries()) {
+      setDefaultAttribute(this._managed, slide, "role", "group");
+      setDefaultAttribute(
+        this._managed,
+        slide,
+        "aria-roledescription",
+        "slide",
+      );
+      setDefaultAttribute(
+        this._managed,
+        slide,
+        "aria-label",
+        `Slide ${index + 1} of ${this._slides.length}`,
+      );
+    }
+
+    const index = this.currentIndex();
+    this._index = index;
+    this.render();
+  }
+
+  currentIndex() {
+    if (!this._viewport || !this._slides.length) return 0;
+    const viewportLeft = this._viewport.getBoundingClientRect().left;
+    let closest = 0;
+    let distance = Infinity;
+    for (const [index, slide] of this._slides.entries()) {
+      const current = Math.abs(slide.getBoundingClientRect().left - viewportLeft);
+      if (current < distance) {
+        closest = index;
+        distance = current;
+      }
+    }
+    return closest;
+  }
+
+  move(offset) {
+    if (!this._slides.length) return;
+    const current = Number.isInteger(this._index)
+      ? this._index
+      : this.currentIndex();
+    this.scrollTo(Math.max(0, Math.min(this._slides.length - 1, current + offset)));
+  }
+
+  scrollTo(index) {
+    const slide = this._slides[index];
+    if (!this._viewport || !slide || index === this._index) return;
+    const viewportRect = this._viewport.getBoundingClientRect();
+    const slideRect = slide.getBoundingClientRect();
+    const left = this._viewport.scrollLeft + slideRect.left - viewportRect.left;
+    if (typeof this._viewport.scrollTo === "function") {
+      this._viewport.scrollTo({ left, behavior: "smooth" });
+    } else if (typeof slide.scrollIntoView === "function") {
+      slide.scrollIntoView({
+        behavior: "smooth",
+        block: "nearest",
+        inline: "start",
+      });
+    }
+    this.setIndex(index, true);
+  }
+
+  setIndex(index, notify) {
+    const next = Math.max(
+      0,
+      Math.min(this._slides.length ? this._slides.length - 1 : 0, index),
+    );
+    if (next === this._index) {
+      this.render();
+      return;
+    }
+    this._index = next;
+    this.render();
+    if (notify) emit(this, "zen-change", { index: next });
+  }
+
+  render() {
+    const last = Math.max(0, this._slides.length - 1);
+    this.syncDisabled(this._prev, !this._slides.length || this._index <= 0);
+    this.syncDisabled(
+      this._next,
+      !this._slides.length || this._index >= last,
+    );
+  }
+
+  syncDisabled(control, disabled) {
+    if (!control) return;
+    const authored = originalAttribute(this._managed, control, "disabled");
+    setManagedAttribute(
+      this._managed,
+      control,
+      "disabled",
+      disabled || authored !== null ? "" : null,
+    );
+  }
+}
+
+/**
+ * Keeps a message viewport pinned while the reader remains near its end.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenMessageScroller extends HTMLElementBase {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onScroll ||= () => {
+      this._nearEnd = this.isNearEnd();
+      this.render();
+    };
+    this._onClick ||= event => {
+      const button = eventElement(event)?.closest("[data-zen-scroll-end]");
+      if (button === this._button && !isDisabled(button)) this.scrollEnd(true);
+    };
+    this._viewport = ownedElement(this, "[data-zen-viewport]") || this;
+    this._button = ownedElement(this, "[data-zen-scroll-end]");
+    this._nearEnd = this.isNearEnd();
+    this.addEventListener("click", this._onClick);
+    this._viewport.addEventListener("scroll", this._onScroll, { passive: true });
+    this._observer ||= new MutationObserver(records => {
+      if (!records.some(record => record.addedNodes.length)) return;
+      const wasNearEnd = this._nearEnd;
+      if (wasNearEnd) this.scrollEnd(false);
+      else this.render();
+    });
+    this._observer.observe(this._viewport, { childList: true, subtree: true });
+    this.render();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    this._viewport?.removeEventListener("scroll", this._onScroll);
+    restoreAttributes(this._managed);
+    this._viewport = null;
+    this._button = null;
+  }
+
+  isNearEnd() {
+    if (!this._viewport) return true;
+    return this._viewport.scrollHeight - this._viewport.scrollTop -
+      this._viewport.clientHeight <= 24;
+  }
+
+  scrollEnd(smooth) {
+    if (!this._viewport) return;
+    if (typeof this._viewport.scrollTo === "function") {
+      this._viewport.scrollTo({
+        top: this._viewport.scrollHeight,
+        behavior: smooth ? "smooth" : "auto",
+      });
+    } else {
+      this._viewport.scrollTop = this._viewport.scrollHeight;
+    }
+    this._nearEnd = true;
+    this.render();
+  }
+
+  render() {
+    if (!this._button) return;
+    setManagedAttribute(
+      this._managed,
+      this._button,
+      "hidden",
+      this._nearEnd ? "" : null,
+    );
+  }
+}
+
+/**
+ * Adds pointer and keyboard resizing to two native content panels.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenResizable extends HTMLElementBase {
+  static get observedAttributes() {
+    return ["min", "max"];
+  }
+
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onPointerDown ||= event => {
+      const handle = eventElement(event)?.closest("[data-zen-handle]");
+      if (handle !== this._handle || (event.button !== 0 && event.button !== -1)) {
+        return;
+      }
+      event.preventDefault();
+      this._pointerId = event.pointerId;
+      this._handle.setPointerCapture?.(event.pointerId);
+    };
+    this._onPointerMove ||= event => {
+      if (event.pointerId !== this._pointerId) return;
+      const rect = this.getBoundingClientRect();
+      if (!rect.width) return;
+      this.setPercent((event.clientX - rect.left) / rect.width * 100, true);
+    };
+    this._onPointerEnd ||= event => {
+      if (event.pointerId !== this._pointerId) return;
+      if (this._handle?.hasPointerCapture?.(event.pointerId)) {
+        this._handle.releasePointerCapture(event.pointerId);
+      }
+      this._pointerId = null;
+    };
+    this._onKeydown ||= event => {
+      const handle = eventElement(event)?.closest("[data-zen-handle]");
+      if (handle !== this._handle ||
+          !["ArrowLeft", "ArrowRight"].includes(event.key)) {
+        return;
+      }
+      event.preventDefault();
+      const step = Number(this.getAttribute("step"));
+      const amount = Number.isFinite(step) && step > 0 ? step : 1;
+      this.setPercent(
+        this._percent + (event.key === "ArrowLeft" ? -amount : amount),
+        true,
+      );
+    };
+    this.addEventListener("pointerdown", this._onPointerDown);
+    this.addEventListener("pointermove", this._onPointerMove);
+    this.addEventListener("pointerup", this._onPointerEnd);
+    this.addEventListener("pointercancel", this._onPointerEnd);
+    this.addEventListener("keydown", this._onKeydown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("pointerdown", this._onPointerDown);
+    this.removeEventListener("pointermove", this._onPointerMove);
+    this.removeEventListener("pointerup", this._onPointerEnd);
+    this.removeEventListener("pointercancel", this._onPointerEnd);
+    this.removeEventListener("keydown", this._onKeydown);
+    restoreAttributes(this._managed);
+    this._first = null;
+    this._second = null;
+    this._handle = null;
+    this._pointerId = null;
+    this._percent = null;
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected && Number.isFinite(this._percent)) {
+      this.setPercent(this._percent, false);
+    }
+  }
+
+  limits() {
+    const minimum = this.getAttribute("min");
+    const maximum = this.getAttribute("max");
+    const min = minimum !== null && Number.isFinite(Number(minimum))
+      ? Math.max(0, Math.min(100, Number(minimum)))
+      : 0;
+    const max = maximum !== null && Number.isFinite(Number(maximum))
+      ? Math.max(min, Math.min(100, Number(maximum)))
+      : 100;
+    return { min, max };
+  }
+
+  sync() {
+    const children = [...this.children];
+    const handle = children.find(child => child.hasAttribute("data-zen-handle"));
+    const handleIndex = children.indexOf(handle);
+    const first = children.slice(0, handleIndex).reverse().find(
+      child => child.hasAttribute("data-zen-panel"),
+    );
+    const second = children.slice(handleIndex + 1).find(
+      child => child.hasAttribute("data-zen-panel"),
+    );
+
+    if (!first || !second || !handle) {
+      if (this._first) restoreElement(this._managed, this._first);
+      if (this._handle) restoreElement(this._managed, this._handle);
+      this._first = null;
+      this._second = null;
+      this._handle = null;
+      this._percent = null;
+      return;
+    }
+    if (this._first && this._first !== first) restoreElement(this._managed, this._first);
+    if (this._handle && this._handle !== handle) {
+      restoreElement(this._managed, this._handle);
+    }
+    this._first = first;
+    this._second = second;
+    this._handle = handle;
+
+    setManagedAttribute(this._managed, this._handle, "role", "separator");
+    setManagedAttribute(
+      this._managed,
+      this._handle,
+      "aria-orientation",
+      "vertical",
+    );
+    setDefaultAttribute(this._managed, this._handle, "tabindex", "0");
+
+    if (!Number.isFinite(this._percent)) {
+      const containerWidth = this.getBoundingClientRect().width;
+      const rendered = containerWidth
+        ? this._first.getBoundingClientRect().width / containerWidth * 100
+        : Number.parseFloat(this._first.style.flexBasis);
+      this._percent = Number.isFinite(rendered) ? rendered : 50;
+    }
+    this.setPercent(this._percent, false);
+  }
+
+  setPercent(percent, notify) {
+    if (!this._first || !this._handle) return;
+    const { min, max } = this.limits();
+    const next = Math.round(Math.max(min, Math.min(max, percent)) * 100) / 100;
+    const changed = next !== this._percent;
+    this._percent = next;
+    rememberAttribute(this._managed, this._first, "style");
+    this._first.style.flexBasis = `${next}%`;
+    setManagedAttribute(this._managed, this._handle, "aria-valuemin", String(min));
+    setManagedAttribute(this._managed, this._handle, "aria-valuemax", String(max));
+    setManagedAttribute(this._managed, this._handle, "aria-valuenow", String(next));
+    if (notify && changed) emit(this, "zen-resize", { percent: next });
+  }
+}
+
+/**
+ * Adds stable client-side sorting to a native HTML table.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenDataTable extends HTMLElementBase {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onClick ||= event => {
+      const button = eventElement(event)?.closest("button[data-zen-sort]");
+      if (!this._buttons.includes(button) || isDisabled(button)) return;
+      this.sort(button);
+    };
+    this.addEventListener("click", this._onClick);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    restoreAttributes(this._managed);
+    this._table = null;
+    this._buttons = [];
+  }
+
+  sync() {
+    this._table =
+      this.querySelector(":scope > table") || this.querySelector("table");
+    this._buttons = this._table
+      ? [...this._table.querySelectorAll("button[data-zen-sort]")].filter(
+        button => button.closest("table") === this._table &&
+          button.closest("th"),
+      )
+      : [];
+    pruneAttributes(
+      this._managed,
+      new Set(this._buttons.map(button => button.closest("th"))),
+    );
+  }
+
+  sort(button) {
+    const key = button.getAttribute("data-zen-sort");
+    const header = button.closest("th");
+    if (!this._table || !key || !header) return;
+    const direction =
+      header.getAttribute("aria-sort") === "ascending"
+        ? "descending"
+        : "ascending";
+
+    for (const candidate of this._buttons) {
+      const candidateHeader = candidate.closest("th");
+      setManagedAttribute(
+        this._managed,
+        candidateHeader,
+        "aria-sort",
+        candidateHeader === header ? direction : null,
+      );
+    }
+
+    for (const body of this._table.tBodies) {
+      const entries = [...body.rows].map((row, index) => {
+        const cell = [...row.cells].find(
+          candidate => candidate.getAttribute("data-key") === key,
+        );
+        return { index, row, value: cell?.textContent?.trim() ?? "" };
+      });
+      const numeric = entries.every(
+        entry => Number.isFinite(Number(entry.value)),
+      );
+      const factor = direction === "ascending" ? 1 : -1;
+      entries.sort((left, right) => {
+        const compared = numeric
+          ? Number(left.value) - Number(right.value)
+          : left.value.localeCompare(right.value);
+        return compared ? compared * factor : left.index - right.index;
+      });
+      body.append(...entries.map(entry => entry.row));
+    }
+    emit(this, "zen-sort", { column: key, direction });
+  }
+}
+
+const definitions = {
+  "zen-carousel": ZenCarousel,
+  "zen-data-table": ZenDataTable,
+  "zen-message-scroller": ZenMessageScroller,
+  "zen-resizable": ZenResizable,
+};
+
+if (globalThis.customElements) {
+  for (const [name, definition] of Object.entries(definitions)) {
+    if (!globalThis.customElements.get(name)) {
+      globalThis.customElements.define(name, definition);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/disclosure.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,800 @@
+let nextDisclosureId = 1;
+
+const HTMLElementBase = globalThis.HTMLElement || class {};
+
+function rememberAttribute(state, element, name) {
+  let attributes = state.get(element);
+  if (!attributes) {
+    attributes = new Map();
+    state.set(element, attributes);
+  }
+  if (!attributes.has(name)) {
+    attributes.set(name, element.getAttribute(name));
+  }
+}
+
+function setManagedAttribute(state, element, name, value) {
+  rememberAttribute(state, element, name);
+  if (value === null) {
+    if (element.hasAttribute(name)) element.removeAttribute(name);
+  } else if (element.getAttribute(name) !== value) {
+    element.setAttribute(name, value);
+  }
+}
+
+function restoreAttribute(state, element, name) {
+  const attributes = state.get(element);
+  if (!attributes?.has(name)) return;
+  const value = attributes.get(name);
+  if (value === null) element.removeAttribute(name);
+  else element.setAttribute(name, value);
+  attributes.delete(name);
+  if (!attributes.size) state.delete(element);
+}
+
+function restoreElement(state, element) {
+  const attributes = state.get(element);
+  if (!attributes) return;
+  for (const [name, value] of attributes) {
+    if (value === null) element.removeAttribute(name);
+    else element.setAttribute(name, value);
+  }
+  state.delete(element);
+}
+
+function restoreAttributes(state) {
+  for (const element of [...state.keys()]) restoreElement(state, element);
+}
+
+function pruneAttributes(state, retained) {
+  for (const element of [...state.keys()]) {
+    if (!retained.has(element)) restoreElement(state, element);
+  }
+}
+
+function uniqueId(element, prefix) {
+  const document = element.ownerDocument;
+  let id;
+  do id = `${prefix}-${nextDisclosureId++}`;
+  while ([...document.querySelectorAll("[id]")].some(item => item.id === id));
+  return id;
+}
+
+function ensureId(state, element, prefix) {
+  const document = element.ownerDocument;
+  const duplicate = element.id &&
+    [...document.querySelectorAll("[id]")].some(
+      item => item !== element && item.id === element.id,
+    );
+  if (!element.id || duplicate) {
+    setManagedAttribute(state, element, "id", uniqueId(element, prefix));
+  }
+  return element.id;
+}
+
+function eventElement(event) {
+  const target = event.target;
+  if (target?.nodeType === 1) return target;
+  return target?.parentElement || null;
+}
+
+function isDisabled(control) {
+  return Boolean(control.disabled) ||
+    control.getAttribute("aria-disabled") === "true";
+}
+
+function emitChange(element, detail) {
+  element.dispatchEvent(new CustomEvent("zen-change", {
+    bubbles: true,
+    detail,
+  }));
+}
+
+function ownedElements(host, selector) {
+  return [...host.querySelectorAll(selector)].filter(
+    element => element.closest(host.localName) === host,
+  );
+}
+
+function syncDisclosureIcon(details) {
+  const summary = details.querySelector(":scope > summary");
+  if (!summary) return;
+  let icon = summary.querySelector(
+    ":scope > zen-icon[data-zen-disclosure-icon]",
+  );
+  if (!icon) {
+    icon = document.createElement("zen-icon");
+    icon.dataset.zenDisclosureIcon = "";
+    icon.dataset.zenGenerated = "true";
+    summary.append(icon);
+  }
+  if (!icon.hasAttribute("name")) icon.setAttribute("name", "chevron-down");
+}
+
+function removeGeneratedDisclosureIcons(host) {
+  for (const icon of host.querySelectorAll(
+    'zen-icon[data-zen-disclosure-icon][data-zen-generated="true"]',
+  )) {
+    icon.remove();
+  }
+}
+
+/**
+ * Coordinates native details elements and summary keyboard navigation.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenAccordion extends HTMLElementBase {
+  static get observedAttributes() {
+    return ["multiple"];
+  }
+
+  connectedCallback() {
+    this._details ||= new Set();
+    this._onToggle ||= event => {
+      const opened = event.currentTarget;
+      if (!opened.open || this.hasAttribute("multiple")) return;
+      for (const details of this._details) {
+        if (details !== opened) details.open = false;
+      }
+    };
+    this._onKeydown ||= event => {
+      if (!["ArrowUp", "ArrowDown", "Home", "End"].includes(event.key)) {
+        return;
+      }
+      const summary = eventElement(event)?.closest("summary");
+      const summaries = this.summaries();
+      const index = summaries.indexOf(summary);
+      if (index < 0) return;
+      event.preventDefault();
+      let next = event.key === "Home" ? 0 : summaries.length - 1;
+      if (event.key === "ArrowUp") {
+        next = (index - 1 + summaries.length) % summaries.length;
+      } else if (event.key === "ArrowDown") {
+        next = (index + 1) % summaries.length;
+      }
+      summaries[next]?.focus();
+    };
+    this.addEventListener("keydown", this._onKeydown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("keydown", this._onKeydown);
+    for (const details of this._details || []) {
+      details.removeEventListener("toggle", this._onToggle);
+    }
+    removeGeneratedDisclosureIcons(this);
+    this._details?.clear();
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected && this._details) this.sync();
+  }
+
+  summaries() {
+    return [...this._details]
+      .map(details => details.querySelector(":scope > summary"))
+      .filter(Boolean);
+  }
+
+  sync() {
+    const current = new Set(
+      ownedElements(this, "details").filter(details => {
+        const parent = details.parentElement?.closest("details");
+        return !parent || parent.closest("zen-accordion") !== this;
+      }),
+    );
+    for (const details of this._details) {
+      if (!current.has(details)) {
+        details.removeEventListener("toggle", this._onToggle);
+      }
+    }
+    for (const details of current) {
+      if (!this._details.has(details)) {
+        details.addEventListener("toggle", this._onToggle);
+      }
+      syncDisclosureIcon(details);
+    }
+    this._details = current;
+
+    if (!this.hasAttribute("multiple")) {
+      const opened = [...current].filter(details => details.open);
+      for (const details of opened.slice(1)) details.open = false;
+    }
+  }
+}
+
+/**
+ * Styles a single native details disclosure without replacing its behavior.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenCollapsible extends HTMLElementBase {
+  connectedCallback() {
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    removeGeneratedDisclosureIcons(this);
+  }
+
+  sync() {
+    for (const details of ownedElements(this, "details")) {
+      syncDisclosureIcon(details);
+    }
+  }
+}
+
+/**
+ * Connects an ARIA tablist with its native content panels.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenTabs extends HTMLElementBase {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onClick ||= event => {
+      const tab = eventElement(event)?.closest('[role="tab"]');
+      if (!this.isTab(tab) || isDisabled(tab)) return;
+      this.activate(tab, true);
+    };
+    this._onKeydown ||= event => {
+      const tab = eventElement(event)?.closest('[role="tab"]');
+      if (!this.isTab(tab)) return;
+      const tabs = this._tabs.filter(candidate => !isDisabled(candidate));
+      const index = tabs.indexOf(tab);
+      if (index < 0) return;
+
+      let next;
+      if (event.key === "Home") next = tabs[0];
+      else if (event.key === "End") next = tabs[tabs.length - 1];
+      else if (event.key === "ArrowLeft") {
+        next = tabs[(index - 1 + tabs.length) % tabs.length];
+      } else if (event.key === "ArrowRight") {
+        next = tabs[(index + 1) % tabs.length];
+      } else {
+        return;
+      }
+
+      event.preventDefault();
+      this._focusTab = next;
+      this.render();
+      next.focus();
+      if (this.getAttribute("activation") !== "manual") {
+        this.activate(next, true);
+      }
+    };
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("keydown", this._onKeydown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, {
+      attributeFilter: ["aria-controls", "aria-disabled", "disabled", "id"],
+      attributes: true,
+      childList: true,
+      subtree: true,
+    });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("keydown", this._onKeydown);
+    restoreAttributes(this._managed);
+    this._tablist = null;
+    this._tabs = [];
+    this._panels = [];
+    this._pairs = new Map();
+    this._active = null;
+    this._focusTab = null;
+  }
+
+  isTab(tab) {
+    return Boolean(
+      tab && this._tabs?.includes(tab) && this._tablist?.contains(tab),
+    );
+  }
+
+  sync() {
+    this._tablist = ownedElements(this, '[role="tablist"]')[0] || null;
+    this._tabs = this._tablist
+      ? [...this._tablist.querySelectorAll('[role="tab"]')].filter(
+        tab => tab.closest("zen-tabs") === this,
+      )
+      : [];
+    this._panels = ownedElements(this, '[role="tabpanel"]');
+    pruneAttributes(
+      this._managed,
+      new Set([...this._tabs, ...this._panels]),
+    );
+
+    for (const tab of this._tabs) {
+      ensureId(this._managed, tab, "zen-tab");
+    }
+    for (const panel of this._panels) {
+      ensureId(this._managed, panel, "zen-tabpanel");
+    }
+
+    const available = new Set(this._panels);
+    this._pairs = new Map();
+    for (const [index, tab] of this._tabs.entries()) {
+      const controlled = tab.getAttribute("aria-controls");
+      let panel = this._panels.find(
+        candidate => available.has(candidate) && candidate.id === controlled,
+      );
+      if (!panel && available.has(this._panels[index])) {
+        panel = this._panels[index];
+      }
+      panel ||= [...available][0] || null;
+      if (panel) {
+        available.delete(panel);
+        this._pairs.set(tab, panel);
+        setManagedAttribute(
+          this._managed,
+          tab,
+          "aria-controls",
+          panel.id,
+        );
+        setManagedAttribute(
+          this._managed,
+          panel,
+          "aria-labelledby",
+          tab.id,
+        );
+      } else {
+        restoreAttribute(this._managed, tab, "aria-controls");
+      }
+    }
+    for (const panel of available) {
+      restoreAttribute(this._managed, panel, "aria-labelledby");
+    }
+
+    if (!this._tabs.includes(this._active) || isDisabled(this._active)) {
+      this._active = this._tabs.find(
+        tab => !isDisabled(tab) && tab.getAttribute("aria-selected") === "true",
+      ) || this._tabs.find(tab => !isDisabled(tab)) || this._tabs[0] || null;
+    }
+    if (!this._tabs.includes(this._focusTab) || isDisabled(this._focusTab)) {
+      this._focusTab = this._active;
+    }
+    this.render();
+  }
+
+  render() {
+    for (const tab of this._tabs) {
+      const active = tab === this._active;
+      setManagedAttribute(
+        this._managed,
+        tab,
+        "aria-selected",
+        String(active),
+      );
+      setManagedAttribute(
+        this._managed,
+        tab,
+        "tabindex",
+        tab === this._focusTab && !isDisabled(tab) ? "0" : "-1",
+      );
+    }
+    const activePanel = this._pairs.get(this._active);
+    for (const panel of this._panels) {
+      setManagedAttribute(
+        this._managed,
+        panel,
+        "hidden",
+        panel === activePanel ? null : "",
+      );
+    }
+  }
+
+  activate(tab, notify) {
+    if (!this.isTab(tab) || isDisabled(tab)) return;
+    this._focusTab = tab;
+    if (tab === this._active) {
+      this.render();
+      return;
+    }
+    this._active = tab;
+    this.render();
+    if (notify) {
+      emitChange(this, {
+        value: tab.dataset.value ?? tab.getAttribute("value") ?? tab.id,
+      });
+    }
+  }
+}
+
+/**
+ * Manages the pressed state of one direct native button.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenToggle extends HTMLElementBase {
+  static get observedAttributes() {
+    return ["pressed"];
+  }
+
+  get pressed() {
+    return this.hasAttribute("pressed");
+  }
+
+  set pressed(value) {
+    this.toggleAttribute("pressed", Boolean(value));
+  }
+
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onClick ||= event => {
+      const button = eventElement(event)?.closest("button");
+      if (button !== this._button || isDisabled(button)) return;
+      this.pressed = !this.pressed;
+      emitChange(this, { pressed: this.pressed });
+    };
+    this.addEventListener("click", this._onClick);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    restoreAttributes(this._managed);
+    this._button = null;
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected && this._managed) this.sync();
+  }
+
+  sync() {
+    const button = this.querySelector(":scope > button");
+    if (button !== this._button) {
+      if (this._button) restoreElement(this._managed, this._button);
+      this._button = button;
+    }
+    if (button) {
+      setManagedAttribute(
+        this._managed,
+        button,
+        "aria-pressed",
+        String(this.pressed),
+      );
+    }
+  }
+}
+
+function buttonValue(button) {
+  return button.getAttribute("value") ?? button.dataset.value ?? "";
+}
+
+function parseMultipleValue(value) {
+  if (!value) return [];
+  if (value.trim().startsWith("[")) {
+    try {
+      const parsed = JSON.parse(value);
+      if (Array.isArray(parsed)) return parsed.map(String);
+    } catch {
+      // Fall through to token parsing.
+    }
+  }
+  return value.trim().split(/[\s,]+/).filter(Boolean);
+}
+
+/**
+ * Manages single or multiple pressed buttons with roving focus.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenToggleGroup extends HTMLElementBase {
+  static get observedAttributes() {
+    return ["type", "value"];
+  }
+
+  get values() {
+    return [...(this._values || [])];
+  }
+
+  set values(values) {
+    this.setValues(Array.isArray(values) ? values.map(String) : [], false);
+  }
+
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._buttons ||= [];
+    if (!this._initialized) {
+      this._values = this.initialValues();
+      this._initialized = true;
+    }
+    this._hasConnected = true;
+    this._onClick ||= event => {
+      const button = eventElement(event)?.closest("button");
+      if (!this._buttons.includes(button) || isDisabled(button)) return;
+      const value = buttonValue(button);
+      this._focusButton = button;
+      let values;
+      if (this.multiple) {
+        values = this._values.includes(value)
+          ? this._values.filter(item => item !== value)
+          : [...this._values, value];
+      } else {
+        values = this._values.includes(value) ? [] : [value];
+      }
+      this.setValues(values, true);
+    };
+    this._onKeydown ||= event => {
+      const button = eventElement(event)?.closest("button");
+      const buttons = this._buttons.filter(candidate => !isDisabled(candidate));
+      const index = buttons.indexOf(button);
+      if (index < 0) return;
+
+      let next;
+      if (event.key === "Home") next = buttons[0];
+      else if (event.key === "End") next = buttons[buttons.length - 1];
+      else if (event.key === "ArrowLeft" || event.key === "ArrowUp") {
+        next = buttons[(index - 1 + buttons.length) % buttons.length];
+      } else if (event.key === "ArrowRight" || event.key === "ArrowDown") {
+        next = buttons[(index + 1) % buttons.length];
+      } else {
+        return;
+      }
+      event.preventDefault();
+      this._focusButton = next;
+      this.render();
+      next.focus();
+    };
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("keydown", this._onKeydown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, {
+      attributeFilter: ["aria-disabled", "data-value", "disabled", "value"],
+      attributes: true,
+      childList: true,
+      subtree: true,
+    });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("keydown", this._onKeydown);
+    restoreAttributes(this._managed);
+    this._buttons = [];
+    this._focusButton = null;
+  }
+
+  attributeChangedCallback(name) {
+    if (name === "value" && !this._settingValue &&
+        this.hasAttribute("value")) {
+      this._values = this.readValue();
+      this._initialized = true;
+    } else if (name === "value" && !this._settingValue) {
+      this._values = [];
+      this._initialized = true;
+    } else if (name === "type" && !this._hasConnected &&
+               this.hasAttribute("value")) {
+      this._values = this.readValue();
+      this._initialized = true;
+    }
+    if (this.isConnected && this._managed) this.sync();
+  }
+
+  get multiple() {
+    return this.getAttribute("type") === "multiple";
+  }
+
+  readValue() {
+    const value = this.getAttribute("value");
+    if (value === null) return [];
+    return this.multiple ? parseMultipleValue(value) : [value];
+  }
+
+  initialValues() {
+    if (this.hasAttribute("value")) return this.readValue();
+    const pressed = [...this.querySelectorAll(":scope > button")]
+      .filter(button => button.getAttribute("aria-pressed") === "true");
+    return pressed.map(buttonValue);
+  }
+
+  sync() {
+    const buttons = [...this.querySelectorAll(":scope > button")];
+    pruneAttributes(this._managed, new Set([this, ...buttons]));
+    this._buttons = buttons;
+    if (!this.hasAttribute("role")) {
+      setManagedAttribute(this._managed, this, "role", "group");
+    }
+    if (!this.multiple && this._values.length > 1) {
+      this._values = this._values.slice(0, 1);
+      this.writeValue();
+    }
+    if (!buttons.includes(this._focusButton) ||
+        isDisabled(this._focusButton)) {
+      this._focusButton = buttons.find(
+        button =>
+          !isDisabled(button) &&
+          button.getAttribute("tabindex") === "0",
+      ) || buttons.find(
+        button =>
+          !isDisabled(button) && this._values.includes(buttonValue(button)),
+      ) || buttons.find(button => !isDisabled(button)) || null;
+    }
+    this.render();
+  }
+
+  render() {
+    for (const button of this._buttons) {
+      setManagedAttribute(
+        this._managed,
+        button,
+        "aria-pressed",
+        String(this._values.includes(buttonValue(button))),
+      );
+      setManagedAttribute(
+        this._managed,
+        button,
+        "tabindex",
+        button === this._focusButton ? "0" : "-1",
+      );
+    }
+  }
+
+  writeValue() {
+    this._settingValue = true;
+    const value = this.multiple
+      ? (this._values.some(item => /[\s,]/.test(item))
+        ? JSON.stringify(this._values)
+        : this._values.join(" "))
+      : this._values[0];
+    if (value === undefined || value === "") this.removeAttribute("value");
+    else this.setAttribute("value", value);
+    this._settingValue = false;
+  }
+
+  setValues(values, notify) {
+    const unique = [...new Set(values.map(String))];
+    this._values = this.multiple ? unique : unique.slice(0, 1);
+    this.writeValue();
+    if (this.isConnected) this.render();
+    if (notify) emitChange(this, { values: this.values });
+  }
+}
+
+/**
+ * Controls a responsive native sidebar region and its trigger.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenSidebar extends HTMLElementBase {
+  static get observedAttributes() {
+    return ["open"];
+  }
+
+  get open() {
+    return this.hasAttribute("open");
+  }
+
+  set open(value) {
+    this.toggleAttribute("open", Boolean(value));
+  }
+
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onClick ||= event => {
+      const trigger = eventElement(event)?.closest(
+        "[data-zen-sidebar-trigger]",
+      );
+      if (trigger !== this._trigger || isDisabled(trigger)) return;
+      this.setOpen(!this.open, true);
+    };
+    this._onKeydown ||= event => {
+      if (event.key !== "Escape" || !this.open) return;
+      event.preventDefault();
+      this.setOpen(false, true);
+      this._trigger?.focus();
+    };
+    this._onMediaChange ||= () => this.syncState();
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("keydown", this._onKeydown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true });
+    this._media = globalThis.matchMedia?.("(max-width: 640px)") || null;
+    if (this._media?.addEventListener) {
+      this._media.addEventListener("change", this._onMediaChange);
+    } else {
+      this._media?.addListener?.(this._onMediaChange);
+    }
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("keydown", this._onKeydown);
+    if (this._media?.removeEventListener) {
+      this._media.removeEventListener("change", this._onMediaChange);
+    } else {
+      this._media?.removeListener?.(this._onMediaChange);
+    }
+    restoreAttributes(this._managed);
+    this._trigger = null;
+    this._panel = null;
+    this._media = null;
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected) this.syncState();
+  }
+
+  sync() {
+    const trigger = ownedElements(
+      this,
+      "[data-zen-sidebar-trigger]",
+    )[0] || null;
+    const panel = ownedElements(
+      this,
+      "[data-zen-sidebar-panel]",
+    )[0] || null;
+    if (trigger !== this._trigger || panel !== this._panel) {
+      if (this._trigger) restoreElement(this._managed, this._trigger);
+      if (this._panel) restoreElement(this._managed, this._panel);
+      this._trigger = trigger;
+      this._panel = panel;
+    }
+    if (!trigger || !panel) return;
+    const panelId = ensureId(this._managed, panel, "zen-sidebar-panel");
+    setManagedAttribute(
+      this._managed,
+      trigger,
+      "aria-controls",
+      panelId,
+    );
+    this.syncState();
+  }
+
+  syncState() {
+    if (!this._trigger || !this._panel) return;
+    setManagedAttribute(
+      this._managed,
+      this._panel,
+      "hidden",
+      this.open ? null : "",
+    );
+    setManagedAttribute(
+      this._managed,
+      this._trigger,
+      "aria-expanded",
+      String(this.open),
+    );
+  }
+
+  setOpen(open, notify) {
+    if (this.open === open) return;
+    this.open = open;
+    this.syncState();
+    if (notify) emitChange(this, { open });
+  }
+}
+
+const definitions = {
+  "zen-accordion": ZenAccordion,
+  "zen-collapsible": ZenCollapsible,
+  "zen-sidebar": ZenSidebar,
+  "zen-tabs": ZenTabs,
+  "zen-toggle": ZenToggle,
+  "zen-toggle-group": ZenToggleGroup,
+};
+
+const registry = globalThis.customElements;
+if (registry) {
+  for (const [name, definition] of Object.entries(definitions)) {
+    if (!registry.get(name)) registry.define(name, definition);
+  }
+}
--- a/design_system/src/components/field.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/field.js	Tue Aug 04 15:12:09 2026 -0700
@@ -9,6 +9,11 @@
   return candidate;
 }
 
+/**
+ * Associates a label, native form control, and descriptive help text.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenField extends HTMLElement {
   connectedCallback() {
     if (!this._observer) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/forms.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,1240 @@
+let nextFormId = 1;
+
+function uniqueId(prefix) {
+  let id;
+  do id = `${prefix}-${nextFormId++}`;
+  while (document.getElementById(id));
+  return id;
+}
+
+function rememberAttribute(state, element, name) {
+  let attributes = state.get(element);
+  if (!attributes) {
+    attributes = new Map();
+    state.set(element, attributes);
+  }
+  if (!attributes.has(name)) {
+    attributes.set(name, element.getAttribute(name));
+  }
+}
+
+function setManagedAttribute(state, element, name, value) {
+  rememberAttribute(state, element, name);
+  if (value === null) element.removeAttribute(name);
+  else element.setAttribute(name, value);
+}
+
+function restoreElement(state, element) {
+  const attributes = state.get(element);
+  if (!attributes) return;
+  for (const [name, value] of attributes) {
+    if (value === null) element.removeAttribute(name);
+    else element.setAttribute(name, value);
+  }
+  state.delete(element);
+}
+
+function restoreAttribute(state, element, name) {
+  const attributes = state.get(element);
+  if (!attributes?.has(name)) return;
+  const value = attributes.get(name);
+  if (value === null) element.removeAttribute(name);
+  else element.setAttribute(name, value);
+  attributes.delete(name);
+  if (!attributes.size) state.delete(element);
+}
+
+function restoreAttributes(state) {
+  for (const element of [...state.keys()]) restoreElement(state, element);
+}
+
+function originalAttribute(state, element, name) {
+  const attributes = state.get(element);
+  return attributes?.has(name)
+    ? attributes.get(name)
+    : element.getAttribute(name);
+}
+
+function ensureId(state, element, prefix) {
+  const owner = element.id && document.getElementById(element.id);
+  if (!element.id || (owner && owner !== element)) {
+    setManagedAttribute(state, element, "id", uniqueId(prefix));
+  }
+  return element.id;
+}
+
+function emit(element, type, detail) {
+  element.dispatchEvent(new CustomEvent(type, {
+    bubbles: true,
+    detail,
+  }));
+}
+
+class NativeControl extends HTMLElement {
+  connectedCallback() {
+    if (!this._observer) {
+      this._observer = new MutationObserver(() => this.sync());
+    }
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this._control = null;
+  }
+
+  sync() {
+    this._control = this.querySelector(this.controlSelector);
+  }
+}
+
+/**
+ * Provides presentation around a native checkbox input.
+ *
+ * @extends {NativeControl}
+ */
+export class ZenCheckbox extends NativeControl {
+  get controlSelector() {
+    return 'input[type="checkbox"]';
+  }
+}
+
+/**
+ * Provides presentation around a native select control.
+ *
+ * @extends {NativeControl}
+ */
+export class ZenSelect extends NativeControl {
+  get controlSelector() {
+    return "select";
+  }
+
+  sync() {
+    super.sync();
+    if (!this._control) return;
+    let icon = this.querySelector(
+      ":scope > zen-icon[data-zen-select-icon]",
+    );
+    if (!icon) {
+      icon = document.createElement("zen-icon");
+      icon.dataset.zenSelectIcon = "";
+      icon.dataset.zenGenerated = "true";
+      icon.setAttribute("name", "chevron-down");
+      this.append(icon);
+    }
+  }
+
+  disconnectedCallback() {
+    this.querySelector(
+      ':scope > zen-icon[data-zen-select-icon][data-zen-generated="true"]',
+    )?.remove();
+    super.disconnectedCallback();
+  }
+}
+
+/**
+ * Provides presentation around a native range input.
+ *
+ * @extends {NativeControl}
+ */
+export class ZenSlider extends NativeControl {
+  get controlSelector() {
+    return 'input[type="range"]';
+  }
+}
+
+function createDate(year, month, day) {
+  const date = new Date(0);
+  date.setHours(0, 0, 0, 0);
+  date.setFullYear(year, month, day);
+  return date;
+}
+
+function parseDate(value) {
+  const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value || "");
+  if (!match) return null;
+  const year = Number(match[1]);
+  const month = Number(match[2]) - 1;
+  const day = Number(match[3]);
+  const date = createDate(year, month, day);
+  if (date.getFullYear() !== year ||
+      date.getMonth() !== month ||
+      date.getDate() !== day) return null;
+  return date;
+}
+
+function dateKey(date) {
+  const year = String(date.getFullYear()).padStart(4, "0");
+  const month = String(date.getMonth() + 1).padStart(2, "0");
+  const day = String(date.getDate()).padStart(2, "0");
+  return `${year}-${month}-${day}`;
+}
+
+function addDays(date, amount) {
+  return createDate(
+    date.getFullYear(),
+    date.getMonth(),
+    date.getDate() + amount,
+  );
+}
+
+function addMonths(date, amount) {
+  const first = createDate(date.getFullYear(), date.getMonth() + amount, 1);
+  const last = createDate(
+    first.getFullYear(),
+    first.getMonth() + 1,
+    0,
+  ).getDate();
+  return createDate(
+    first.getFullYear(),
+    first.getMonth(),
+    Math.min(date.getDate(), last),
+  );
+}
+
+/**
+ * Renders a tokenized calendar backed by a native date input.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenCalendar extends HTMLElement {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onClick ||= event => this.onClick(event);
+    this._onKeydown ||= event => this.onKeydown(event);
+    this._onInput ||= event => {
+      if (event.target !== this._input) return;
+      this.readInput();
+      if (this._input.validity.valid) this.setInvalid(false);
+      this.render();
+    };
+    this._onInvalid ||= event => {
+      if (event.target !== this._input) return;
+      event.preventDefault();
+      this.setInvalid(true);
+      queueMicrotask(() => {
+        if (!this.isConnected) return;
+        const target = this._trigger ||
+          this._grid?.querySelector('[tabindex="0"]:not(:disabled)');
+        target?.focus();
+      });
+    };
+    this._onDocumentPointerDown ||= event => {
+      if (this.isPicker && this._open && !this.contains(event.target)) {
+        this.setOpen(false);
+      }
+    };
+    this._onReset ||= () => queueMicrotask(() => {
+      if (!this.isConnected) return;
+      this.readInput();
+      this.render();
+    });
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("keydown", this._onKeydown);
+    this.addEventListener("input", this._onInput);
+    this.addEventListener("change", this._onInput);
+    this.addEventListener("invalid", this._onInvalid, true);
+    document.addEventListener("pointerdown", this._onDocumentPointerDown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true });
+    this._inputObserver ||= new MutationObserver(() => {
+      this.readInput();
+      this.render();
+    });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this._inputObserver?.disconnect();
+    this._form?.removeEventListener("reset", this._onReset);
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("keydown", this._onKeydown);
+    this.removeEventListener("input", this._onInput);
+    this.removeEventListener("change", this._onInput);
+    this.removeEventListener("invalid", this._onInvalid, true);
+    document.removeEventListener("pointerdown", this._onDocumentPointerDown);
+    this.release();
+  }
+
+  get isPicker() {
+    return this.localName === "zen-date-picker";
+  }
+
+  sync() {
+    const input = [...this.children].find(
+      child => child.matches?.('input[type="date"]'),
+    ) || null;
+    if (input === this._input) return;
+    this.release();
+    this._input = input;
+    if (!input) return;
+
+    setManagedAttribute(
+      this._managed,
+      input,
+      "data-zen-calendar-input",
+      "",
+    );
+    setManagedAttribute(this._managed, input, "tabindex", "-1");
+    setManagedAttribute(this._managed, input, "aria-hidden", "true");
+    this._inputObserver.observe(input, {
+      attributes: true,
+      attributeFilter: ["disabled", "max", "min", "readonly", "value"],
+    });
+    this._form = input.form;
+    this._form?.addEventListener("reset", this._onReset);
+    this.readInput();
+    this.createView();
+    this.render();
+  }
+
+  release() {
+    this._inputObserver?.disconnect();
+    this._form?.removeEventListener("reset", this._onReset);
+    this._generated?.remove();
+    this._generated = null;
+    this._view = null;
+    this._grid = null;
+    this._heading = null;
+    this._trigger = null;
+    this._panel = null;
+    this._labelText = "";
+    this._labelIds = [];
+    this._form = null;
+    this._open = false;
+    restoreAttributes(this._managed || new Map());
+    this._input = null;
+  }
+
+  readInput() {
+    const selected = parseDate(this._input?.value);
+    const today = new Date();
+    this._selected = selected;
+    this._focusDate = selected || this._focusDate || today;
+    this._month = createDate(
+      (selected || this._focusDate).getFullYear(),
+      (selected || this._focusDate).getMonth(),
+      1,
+    );
+  }
+
+  limits() {
+    return {
+      maximum: parseDate(this._input?.max),
+      minimum: parseDate(this._input?.min),
+    };
+  }
+
+  isEditable() {
+    return Boolean(this._input) &&
+      !this._input.disabled &&
+      !this._input.readOnly;
+  }
+
+  isAllowed(date) {
+    if (!date) return false;
+    const { maximum, minimum } = this.limits();
+    return (!minimum || date >= minimum) && (!maximum || date <= maximum);
+  }
+
+  clampDate(date) {
+    const { maximum, minimum } = this.limits();
+    if (minimum && date < minimum) return minimum;
+    if (maximum && date > maximum) return maximum;
+    return date;
+  }
+
+  setInvalid(invalid) {
+    setManagedAttribute(
+      this._managed,
+      this,
+      "data-invalid",
+      invalid ? "" : null,
+    );
+    if (this._trigger) {
+      this._trigger.setAttribute("aria-invalid", String(invalid));
+    }
+    if (this._grid) {
+      this._grid.setAttribute("aria-invalid", String(invalid));
+    }
+  }
+
+  createIcon(name) {
+    const icon = document.createElement("zen-icon");
+    icon.setAttribute("name", name);
+    return icon;
+  }
+
+  createControl(name, label) {
+    const button = document.createElement("button");
+    button.type = "button";
+    button.dataset[name] = "";
+    button.setAttribute("aria-label", label);
+    return button;
+  }
+
+  createView() {
+    const generated = document.createElement("div");
+    generated.dataset.zenGenerated = "calendar";
+    this._generated = generated;
+    const labels = [...this._input.labels];
+    const authoredLabelIds = (this._input.getAttribute("aria-labelledby") || "")
+      .split(/\s+/)
+      .filter(id => id && document.getElementById(id));
+    const associatedLabelIds = labels.map(label =>
+      ensureId(this._managed, label, "zen-date-label")
+    );
+    this._labelIds = authoredLabelIds.length
+      ? authoredLabelIds
+      : associatedLabelIds;
+    this._labelText = this._labelIds.map(id =>
+      document.getElementById(id)?.textContent.trim()
+    )
+      .filter(Boolean)
+      .join(", ") ||
+      labels.map(label => label.textContent.trim())
+      .filter(Boolean)
+      .join(", ") ||
+      this._input.getAttribute("aria-label") ||
+      "Date";
+
+    if (this.isPicker) {
+      const trigger = this.createControl(
+        "zenDateTrigger",
+        "Choose date",
+      );
+      trigger.id = uniqueId("zen-date-picker-trigger");
+      trigger.append(this.createIcon("calendar"));
+      const triggerText = document.createElement("span");
+      triggerText.dataset.zenDateValue = "";
+      triggerText.id = uniqueId("zen-date-picker-value");
+      trigger.append(triggerText);
+      this._trigger = trigger;
+
+      const panel = document.createElement("div");
+      panel.dataset.zenCalendarPanel = "";
+      panel.id = uniqueId("zen-date-picker-panel");
+      panel.setAttribute("role", "dialog");
+      panel.setAttribute("aria-label", `${this._labelText} calendar`);
+      panel.hidden = true;
+      trigger.setAttribute("aria-haspopup", "dialog");
+      trigger.setAttribute("aria-controls", panel.id);
+      if (this._input.hasAttribute("aria-describedby")) {
+        trigger.setAttribute(
+          "aria-describedby",
+          this._input.getAttribute("aria-describedby"),
+        );
+      }
+      if (this._labelIds.length) {
+        trigger.setAttribute(
+          "aria-labelledby",
+          [...this._labelIds, triggerText.id].join(" "),
+        );
+      }
+      for (const label of labels) {
+        if (label.htmlFor === this._input.id) {
+          setManagedAttribute(this._managed, label, "for", trigger.id);
+        }
+      }
+      this._panel = panel;
+      generated.append(trigger, panel);
+    }
+
+    const view = document.createElement("div");
+    view.dataset.zenCalendarView = "";
+    const header = document.createElement("header");
+    const previous = this.createControl(
+      "zenCalendarPrevious",
+      "Previous month",
+    );
+    previous.append(this.createIcon("chevron-left"));
+    const heading = document.createElement("strong");
+    heading.setAttribute("aria-live", "polite");
+    const next = this.createControl("zenCalendarNext", "Next month");
+    next.append(this.createIcon("chevron-right"));
+    header.append(previous, heading, next);
+
+    const weekdays = document.createElement("div");
+    weekdays.dataset.zenCalendarWeekdays = "";
+    weekdays.setAttribute("aria-hidden", "true");
+    const formatter = new Intl.DateTimeFormat(undefined, {
+      weekday: "narrow",
+    });
+    for (let day = 4; day < 11; day++) {
+      const label = document.createElement("span");
+      label.textContent = formatter.format(new Date(2026, 0, day));
+      weekdays.append(label);
+    }
+
+    const grid = document.createElement("div");
+    grid.dataset.zenCalendarGrid = "";
+    grid.setAttribute("role", "grid");
+    grid.setAttribute(
+      "aria-label",
+      this._labelText ? `${this._labelText} calendar` : "Calendar",
+    );
+    view.append(header, weekdays, grid);
+    this._view = view;
+    this._heading = heading;
+    this._grid = grid;
+    (this._panel || generated).append(view);
+    this.append(generated);
+    if (this.isPicker) this.setOpen(false);
+  }
+
+  render() {
+    if (!this._grid || !this._month) return;
+    this._focusDate = this.clampDate(this._focusDate);
+    this._heading.textContent = new Intl.DateTimeFormat(undefined, {
+      month: "long",
+      year: "numeric",
+    }).format(this._month);
+
+    if (this._trigger) {
+      const text = this._trigger.querySelector("[data-zen-date-value]");
+      text.textContent = this._selected
+        ? new Intl.DateTimeFormat(undefined, {
+          dateStyle: "medium",
+        }).format(this._selected)
+        : "Choose date";
+      if (this._labelIds.length) {
+        this._trigger.removeAttribute("aria-label");
+      } else {
+        this._trigger.setAttribute(
+          "aria-label",
+          `${this._labelText}, ${text.textContent}`,
+        );
+      }
+      this._trigger.disabled = !this.isEditable();
+    }
+    for (const control of this._view.querySelectorAll(
+      "[data-zen-calendar-previous], [data-zen-calendar-next]",
+    )) {
+      control.disabled = !this.isEditable();
+    }
+
+    const first = createDate(
+      this._month.getFullYear(),
+      this._month.getMonth(),
+      1,
+    );
+    const start = addDays(first, -first.getDay());
+    const { maximum, minimum } = this.limits();
+    const today = dateKey(new Date());
+    const selected = this._selected ? dateKey(this._selected) : "";
+    const focused = dateKey(this._focusDate);
+    const fragment = document.createDocumentFragment();
+    const formatter = new Intl.DateTimeFormat(undefined, {
+      dateStyle: "full",
+    });
+
+    for (let week = 0; week < 6; week++) {
+      const row = document.createElement("div");
+      row.setAttribute("role", "row");
+      for (let day = 0; day < 7; day++) {
+        const date = addDays(start, week * 7 + day);
+        const key = dateKey(date);
+        const button = document.createElement("button");
+        button.type = "button";
+        button.dataset.zenCalendarDay = key;
+        button.setAttribute("role", "gridcell");
+        button.setAttribute("aria-label", formatter.format(date));
+        button.setAttribute("aria-selected", String(key === selected));
+        const disabled = !this.isEditable() ||
+          Boolean((minimum && date < minimum) || (maximum && date > maximum));
+        button.tabIndex = key === focused && !disabled ? 0 : -1;
+        button.textContent = String(date.getDate());
+        button.toggleAttribute(
+          "data-outside",
+          date.getMonth() !== this._month.getMonth(),
+        );
+        button.toggleAttribute("data-today", key === today);
+        button.disabled = disabled;
+        row.append(button);
+      }
+      fragment.append(row);
+    }
+    this._grid.replaceChildren(fragment);
+  }
+
+  onClick(event) {
+    const target = event.target instanceof Element ? event.target : null;
+    if (!target) return;
+    if (target.closest("[data-zen-date-trigger]") === this._trigger) {
+      if (!this.isEditable()) return;
+      this.setOpen(!this._open);
+      return;
+    }
+    if (target.closest("[data-zen-calendar-previous]")) {
+      if (!this.isEditable()) return;
+      this.changeMonth(-1);
+      return;
+    }
+    if (target.closest("[data-zen-calendar-next]")) {
+      if (!this.isEditable()) return;
+      this.changeMonth(1);
+      return;
+    }
+    const day = target.closest("[data-zen-calendar-day]");
+    if (day && !day.disabled) this.selectDate(parseDate(day.dataset.zenCalendarDay));
+  }
+
+  onKeydown(event) {
+    if (event.key === "Escape" && this.isPicker && this._open) {
+      event.preventDefault();
+      this.setOpen(false);
+      this._trigger.focus();
+      return;
+    }
+    const day = event.target instanceof Element
+      ? event.target.closest("[data-zen-calendar-day]")
+      : null;
+    if (!day) return;
+    const current = parseDate(day.dataset.zenCalendarDay);
+    let next = null;
+    if (event.key === "ArrowLeft") next = addDays(current, -1);
+    else if (event.key === "ArrowRight") next = addDays(current, 1);
+    else if (event.key === "ArrowUp") next = addDays(current, -7);
+    else if (event.key === "ArrowDown") next = addDays(current, 7);
+    else if (event.key === "Home") next = addDays(current, -current.getDay());
+    else if (event.key === "End") next = addDays(current, 6 - current.getDay());
+    else if (event.key === "PageUp") next = addMonths(current, -1);
+    else if (event.key === "PageDown") next = addMonths(current, 1);
+    if (!next) return;
+    next = this.clampDate(next);
+    event.preventDefault();
+    this._focusDate = next;
+    this._month = createDate(next.getFullYear(), next.getMonth(), 1);
+    this.render();
+    this._grid.querySelector(
+      `[data-zen-calendar-day="${dateKey(next)}"]`,
+    )?.focus();
+  }
+
+  changeMonth(amount) {
+    if (!this.isEditable()) return;
+    this._month = addMonths(this._month, amount);
+    this._focusDate = this.clampDate(createDate(
+      this._month.getFullYear(),
+      this._month.getMonth(),
+      1,
+    ));
+    this._month = createDate(
+      this._focusDate.getFullYear(),
+      this._focusDate.getMonth(),
+      1,
+    );
+    this.render();
+    this._grid.querySelector('[tabindex="0"]')?.focus();
+  }
+
+  selectDate(date) {
+    if (!this.isEditable() || !this.isAllowed(date)) return;
+    this._selected = date;
+    this._focusDate = date;
+    this._month = createDate(date.getFullYear(), date.getMonth(), 1);
+    this._input.value = dateKey(date);
+    this._input.dispatchEvent(new Event("input", {
+      bubbles: true,
+      composed: true,
+    }));
+    this._input.dispatchEvent(new Event("change", { bubbles: true }));
+    emit(this, "zen-change", { value: this._input.value });
+    this.render();
+    if (this.isPicker) {
+      this.setOpen(false);
+      this._trigger.focus();
+    }
+  }
+
+  setOpen(open) {
+    if (!this.isPicker || !this._panel || !this._trigger) return;
+    this._open = Boolean(open) && this.isEditable();
+    this._panel.hidden = !this._open;
+    this._trigger.setAttribute("aria-expanded", String(this._open));
+    if (this._open) {
+      this._grid.querySelector('[tabindex="0"]')?.focus();
+    }
+  }
+}
+
+/**
+ * Presents the first-party calendar behind a tokenized disclosure trigger.
+ *
+ * @extends {ZenCalendar}
+ */
+export class ZenDatePicker extends ZenCalendar {}
+
+/**
+ * Adds radiogroup semantics when no native fieldset owns the radios.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenRadioGroup extends HTMLElement {
+  connectedCallback() {
+    this._managed ||= new Map();
+    if (!this._observer) {
+      this._observer = new MutationObserver(() => this.sync());
+    }
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    restoreAttributes(this._managed);
+  }
+
+  sync() {
+    const radios = this.querySelectorAll('input[type="radio"]');
+    const needsRole = radios.length > 0 && !this.querySelector("fieldset");
+    if (needsRole && !this.hasAttribute("role")) {
+      setManagedAttribute(this._managed, this, "role", "radiogroup");
+    } else if (!needsRole) {
+      restoreElement(this._managed, this);
+    }
+  }
+}
+
+/**
+ * Synchronizes switch semantics onto a native checkbox.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenSwitch extends HTMLElement {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._onStateChange ||= event => {
+      if (event.target === this._control) this.updateState();
+    };
+    this._onReset ||= () => {
+      queueMicrotask(() => {
+        if (this.isConnected) this.updateState();
+      });
+    };
+    this.addEventListener("input", this._onStateChange);
+    this.addEventListener("change", this._onStateChange);
+    if (!this._observer) {
+      this._observer = new MutationObserver(() => this.sync());
+    }
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("input", this._onStateChange);
+    this.removeEventListener("change", this._onStateChange);
+    this._form?.removeEventListener("reset", this._onReset);
+    restoreAttributes(this._managed);
+    this._control = null;
+    this._form = null;
+  }
+
+  sync() {
+    const control = this.querySelector('input[type="checkbox"]');
+    const form = control?.form || null;
+    if (control !== this._control) {
+      if (this._control) restoreElement(this._managed, this._control);
+      this._control = control;
+    }
+    if (form !== this._form) {
+      this._form?.removeEventListener("reset", this._onReset);
+      this._form = form;
+      form?.addEventListener("reset", this._onReset);
+    }
+    this.updateState();
+  }
+
+  updateState() {
+    if (!this._control) return;
+    setManagedAttribute(this._managed, this._control, "role", "switch");
+    setManagedAttribute(
+      this._managed,
+      this._control,
+      "aria-checked",
+      String(this._control.checked),
+    );
+  }
+}
+
+/**
+ * Reflects native form validity on the component boundary.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenForm extends HTMLElement {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._syncValidity ||= () => {
+      if (!this._form) return;
+      setManagedAttribute(
+        this._managed,
+        this,
+        "data-invalid",
+        this._form.checkValidity() ? null : "",
+      );
+    };
+    this._markInvalid ||= () => {
+      setManagedAttribute(this._managed, this, "data-invalid", "");
+    };
+    this._onReset ||= () => queueMicrotask(this._syncValidity);
+    if (!this._observer) {
+      this._observer = new MutationObserver(() => this.sync());
+    }
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.releaseForm();
+    restoreAttributes(this._managed);
+  }
+
+  releaseForm() {
+    this._form?.removeEventListener("submit", this._syncValidity);
+    this._form?.removeEventListener("input", this._syncValidity);
+    this._form?.removeEventListener("invalid", this._markInvalid, true);
+    this._form?.removeEventListener("reset", this._onReset);
+    this._form = null;
+  }
+
+  sync() {
+    const form = this.querySelector("form");
+    if (form === this._form) return;
+    this.releaseForm();
+    restoreElement(this._managed, this);
+    this._form = form;
+    form?.addEventListener("submit", this._syncValidity);
+    form?.addEventListener("input", this._syncValidity);
+    form?.addEventListener("invalid", this._markInvalid, true);
+    form?.addEventListener("reset", this._onReset);
+  }
+}
+
+class FilterableList extends HTMLElement {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._active = null;
+    this._onInput ||= event => {
+      if (event.target !== this._input) return;
+      if (this.isCombobox) this.setOpen(true);
+      this.filter();
+    };
+    this._onKeydown ||= event => this.onKeydown(event);
+    this._onClick ||= event => this.onClick(event);
+    this._onFocus ||= event => {
+      if (this.isCombobox && event.target === this._input) {
+        this.setOpen(true);
+        this.filter();
+      }
+    };
+    this.addEventListener("input", this._onInput);
+    this.addEventListener("keydown", this._onKeydown);
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("focusin", this._onFocus);
+    if (!this._observer) {
+      this._observer = new MutationObserver(() => this.sync());
+    }
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("input", this._onInput);
+    this.removeEventListener("keydown", this._onKeydown);
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("focusin", this._onFocus);
+    restoreAttributes(this._managed);
+    this._input = null;
+    this._list = null;
+    this._items = [];
+    this._active = null;
+  }
+
+  get isCombobox() {
+    return false;
+  }
+
+  get listRole() {
+    return "menu";
+  }
+
+  get itemRole() {
+    return "menuitem";
+  }
+
+  sync() {
+    const input = this.querySelector("input");
+    const list = this.querySelector(`[role="${this.listRole}"]`);
+    if (input !== this._input || list !== this._list) {
+      restoreAttributes(this._managed);
+      this._input = input;
+      this._list = list;
+      this._items = [];
+      this._active = null;
+      this._open = false;
+    }
+    if (!input || !list) return;
+
+    const items = [...list.querySelectorAll(`[role="${this.itemRole}"]`)];
+    for (const item of this._items) {
+      if (!items.includes(item)) restoreElement(this._managed, item);
+    }
+    this._items = items;
+
+    const listId = ensureId(
+      this._managed,
+      list,
+      this.isCombobox ? "zen-listbox" : "zen-command-menu",
+    );
+    if (!input.hasAttribute("aria-controls")) {
+      setManagedAttribute(this._managed, input, "aria-controls", listId);
+    }
+    if (this.isCombobox) {
+      if (!input.hasAttribute("role")) {
+        setManagedAttribute(this._managed, input, "role", "combobox");
+      }
+      if (!input.hasAttribute("aria-autocomplete")) {
+        setManagedAttribute(
+          this._managed,
+          input,
+          "aria-autocomplete",
+          "list",
+        );
+      }
+      this.setOpen(this._open);
+    }
+    this.filter();
+  }
+
+  filter() {
+    if (!this._input || !this._list) return;
+    const query = this._input.value.trim().toLowerCase();
+    for (const item of this._items) {
+      const originallyHidden =
+        originalAttribute(this._managed, item, "hidden") !== null;
+      const matches = item.textContent.toLowerCase().includes(query);
+      setManagedAttribute(
+        this._managed,
+        item,
+        "hidden",
+        originallyHidden || !matches ? "" : null,
+      );
+    }
+    if (this._active?.hidden) this.setActive(null);
+  }
+
+  visibleItems() {
+    return this._items.filter(item => {
+      if (item.hidden || item.closest("[hidden]")) return false;
+      if (item.getAttribute("aria-disabled") === "true") return false;
+      return !("disabled" in item && item.disabled);
+    });
+  }
+
+  setActive(item) {
+    this._active = item;
+    for (const candidate of this._items) {
+      if (this.isCombobox) {
+        setManagedAttribute(
+          this._managed,
+          candidate,
+          "aria-selected",
+          String(candidate === item),
+        );
+      } else {
+        restoreAttribute(this._managed, candidate, "aria-selected");
+      }
+    }
+    if (!this._input) return;
+    if (item) {
+      setManagedAttribute(
+        this._managed,
+        this._input,
+        "aria-activedescendant",
+        ensureId(this._managed, item, "zen-option"),
+      );
+      item.scrollIntoView?.({ block: "nearest" });
+    } else {
+      setManagedAttribute(
+        this._managed,
+        this._input,
+        "aria-activedescendant",
+        null,
+      );
+    }
+  }
+
+  moveActive(offset) {
+    const items = this.visibleItems();
+    if (!items.length) {
+      this.setActive(null);
+      return;
+    }
+    const current = items.indexOf(this._active);
+    const index = current < 0
+      ? (offset > 0 ? 0 : items.length - 1)
+      : (current + offset + items.length) % items.length;
+    this.setActive(items[index]);
+  }
+
+  onKeydown(event) {
+    if (event.target !== this._input) return;
+    if (event.key === "ArrowDown" || event.key === "ArrowUp") {
+      event.preventDefault();
+      if (this.isCombobox) this.setOpen(true);
+      this.moveActive(event.key === "ArrowDown" ? 1 : -1);
+      return;
+    }
+    if (event.key === "Enter") {
+      const item = this._active || this.visibleItems()[0];
+      if (!item) return;
+      event.preventDefault();
+      this.choose(item);
+    }
+  }
+
+  onClick(event) {
+    const target = event.target instanceof Element
+      ? event.target.closest(`[role="${this.itemRole}"]`)
+      : null;
+    if (!target || !this._list?.contains(target) || target.hidden) return;
+    if (target.getAttribute("aria-disabled") === "true" ||
+        ("disabled" in target && target.disabled)) return;
+    this.choose(target);
+  }
+
+  valueFor(item) {
+    return item.dataset.value ?? item.getAttribute("value") ??
+      item.textContent.trim();
+  }
+}
+
+/**
+ * Filters and selects native option elements from a text input.
+ *
+ * @extends {FilterableList}
+ */
+export class ZenCombobox extends FilterableList {
+  get isCombobox() {
+    return true;
+  }
+
+  get listRole() {
+    return "listbox";
+  }
+
+  get itemRole() {
+    return "option";
+  }
+
+  setOpen(open) {
+    this._open = Boolean(open);
+    if (!this._input || !this._list) return;
+    setManagedAttribute(
+      this._managed,
+      this._input,
+      "aria-expanded",
+      String(this._open),
+    );
+    setManagedAttribute(
+      this._managed,
+      this._list,
+      "hidden",
+      this._open ? null : "",
+    );
+    if (!this._open) this.setActive(null);
+  }
+
+  onKeydown(event) {
+    if (event.target === this._input && event.key === "Escape") {
+      if (this._open) event.preventDefault();
+      this.setOpen(false);
+      return;
+    }
+    super.onKeydown(event);
+  }
+
+  choose(item) {
+    const value = this.valueFor(item);
+    this._input.value = value;
+    this._input.dispatchEvent(new Event("input", {
+      bubbles: true,
+      composed: true,
+    }));
+    this._input.dispatchEvent(new Event("change", { bubbles: true }));
+    emit(this, "zen-change", { value });
+    this.setOpen(false);
+  }
+}
+
+/**
+ * Filters a keyboard-oriented command menu and emits selected commands.
+ *
+ * @extends {FilterableList}
+ */
+export class ZenCommand extends FilterableList {
+  choose(item) {
+    emit(this, "zen-command", { value: this.valueFor(item) });
+  }
+}
+
+/**
+ * Enhances one native one-time-code input with visual slots.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenInputOtp extends HTMLElement {
+  connectedCallback() {
+    this._managed ||= new Map();
+    this._complete ??= false;
+    this._onInput ||= event => {
+      if (event.target === this._input) this.update(true);
+    };
+    this.addEventListener("input", this._onInput);
+    if (!this._observer) {
+      this._observer = new MutationObserver(() => this.sync());
+    }
+    this._observer.observe(this, {
+      attributes: true,
+      attributeFilter: ["allow", "maxlength", "pattern"],
+      childList: true,
+      subtree: true,
+    });
+    this.sync();
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("input", this._onInput);
+    const input = this._input;
+    const complete = this._complete;
+    this.release();
+    this._previousInput = input;
+    this._complete = complete;
+  }
+
+  release() {
+    restoreAttributes(this._managed);
+    if (this._slots && this._originalSlots) {
+      this._slots.replaceChildren(...this._originalSlots);
+    }
+    this._input = null;
+    this._slots = null;
+    this._originalSlots = null;
+    this._complete = false;
+  }
+
+  sync() {
+    const inputs = [...this.querySelectorAll("input")];
+    const input = inputs.length === 1 ? inputs[0] : null;
+    const slots = this.querySelector("[data-zen-otp-slots]");
+    if (input !== this._input || slots !== this._slots) {
+      const remainedComplete =
+        (input === this._input || input === this._previousInput) &&
+        this._complete;
+      this.release();
+      this._input = input;
+      this._slots = slots;
+      this._originalSlots = slots ? [...slots.childNodes] : null;
+      this._complete = remainedComplete;
+      this._previousInput = null;
+    }
+    if (!this._input) return;
+
+    if (!this._input.hasAttribute("maxlength")) {
+      setManagedAttribute(this._managed, this._input, "maxlength", "6");
+    }
+    if (this.numericOnly() && !this._input.hasAttribute("inputmode")) {
+      setManagedAttribute(this._managed, this._input, "inputmode", "numeric");
+    } else if (!this.numericOnly()) {
+      restoreAttribute(this._managed, this._input, "inputmode");
+    }
+    this.update(true);
+  }
+
+  numericOnly() {
+    return !this.hasAttribute("allow") &&
+      !this.hasAttribute("pattern") &&
+      !this._input.hasAttribute("allow") &&
+      !this._input.hasAttribute("pattern");
+  }
+
+  length() {
+    const value = Number.parseInt(this._input.getAttribute("maxlength"), 10);
+    return Number.isFinite(value) && value > 0 ? value : 6;
+  }
+
+  update(notify) {
+    const length = this.length();
+    const before = this._input.value;
+    let value = this.numericOnly() ? before.replace(/\D/g, "") : before;
+    value = [...value].slice(0, length).join("");
+    if (value !== before) {
+      const selection = this._input.selectionStart;
+      this._input.value = value;
+      if (selection !== null) {
+        const preceding = before.slice(0, selection);
+        const position = this.numericOnly()
+          ? preceding.replace(/\D/g, "").length
+          : [...preceding].slice(0, length).join("").length;
+        try {
+          this._input.setSelectionRange(position, position);
+        } catch {
+          // Some native input types do not expose text selection.
+        }
+      }
+    }
+    this.renderSlots(value, length);
+
+    const complete = [...value].length === length;
+    if (notify && complete && !this._complete) {
+      emit(this, "zen-complete", { value });
+    }
+    this._complete = complete;
+  }
+
+  renderSlots(value, length) {
+    if (!this._slots) return;
+    const characters = [...value];
+    const current = [...this._slots.children];
+    const unchanged = current.length === length &&
+      current.every((slot, index) =>
+        slot.localName === "span" &&
+        slot.textContent === (characters[index] || ""));
+    if (unchanged) return;
+
+    const fragment = document.createDocumentFragment();
+    for (let index = 0; index < length; index++) {
+      const slot = document.createElement("span");
+      slot.textContent = characters[index] || "";
+      fragment.append(slot);
+    }
+    this._slots.replaceChildren(fragment);
+  }
+}
+
+const definitions = {
+  "zen-calendar": ZenCalendar,
+  "zen-checkbox": ZenCheckbox,
+  "zen-combobox": ZenCombobox,
+  "zen-command": ZenCommand,
+  "zen-date-picker": ZenDatePicker,
+  "zen-form": ZenForm,
+  "zen-input-otp": ZenInputOtp,
+  "zen-radio-group": ZenRadioGroup,
+  "zen-select": ZenSelect,
+  "zen-slider": ZenSlider,
+  "zen-switch": ZenSwitch,
+};
+
+if (globalThis.customElements) {
+  for (const [name, definition] of Object.entries(definitions)) {
+    if (!customElements.get(name)) customElements.define(name, definition);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/icon.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,109 @@
+const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
+
+const paths = {
+  add: ["M12 5v14", "M5 12h14"],
+  alert: ["M12 3 2.8 20h18.4L12 3Z", "M12 9v5", "M12 17h.01"],
+  archive: ["M4 7h16v13H4Z", "M3 3h18v4H3Z", "M9 11h6"],
+  "arrow-down": ["M12 4v16", "m6 14-6 6-6-6"],
+  "arrow-left": ["M20 12H4", "m10 6-6-6 6-6"],
+  "arrow-right": ["M4 12h16", "m-6-6 6 6-6 6"],
+  "arrow-up": ["M12 20V4", "m-6 6 6-6 6 6"],
+  check: ["m5 12 4 4L19 6"],
+  "chevron-down": ["m5 9 7 7 7-7"],
+  "chevron-left": ["m15 5-7 7 7 7"],
+  "chevron-right": ["m9 5 7 7-7 7"],
+  "chevron-up": ["m5 15 7-7 7 7"],
+  close: ["M6 6l12 12", "M18 6 6 18"],
+  code: ["m9 6-6 6 6 6", "m6-12 6 6-6 6"],
+  copy: ["M8 8h12v12H8Z", "M4 16V4h12"],
+  download: ["M12 3v12", "m7-7 5 5 5-5", "M5 21h14"],
+  error: ["M5 5l14 14", "M19 5 5 19"],
+  external: ["M14 5h5v5", "m19 5-8 8", "M19 13v6H5V5h6"],
+  file: ["M6 3h8l4 4v14H6Z", "M14 3v5h4"],
+  folder: ["M3 6h7l2 2h9v12H3Z"],
+  branch: ["M7 5v10a4 4 0 0 0 4 4h6", "M7 9h7a3 3 0 0 0 3-3V5"],
+  calendar: ["M5 4h14v17H5Z", "M8 2v4", "M16 2v4", "M5 9h14"],
+  history: ["M4 5v5h5", "M5 9a8 8 0 1 0 2-4", "M12 7v5l3 2"],
+  info: ["M12 11v6", "M12 7h.01", "M3 12a9 9 0 1 0 18 0 9 9 0 1 0-18 0"],
+  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"],
+  pause: ["M8 5v14", "M16 5v14"],
+  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"],
+  search: ["M4 11a7 7 0 1 0 14 0 7 7 0 1 0-14 0", "m16 16 4 4"],
+  settings: [
+    "M9.5 4.2 10 2h4l.5 2.2 2 .8 2-1.2 2.8 2.8-1.2 2 .8 2L22 10v4l-2.2.5-.8 2 1.2 2-2.8 2.8-2-1.2-2 .8-.5 2.2h-4L9.5 20l-2-.8-2 1.2-2.8-2.8 1.2-2-.8-2L2 14v-4l2.2-.5.8-2-1.2-2 2.8-2.8 2 1.2Z",
+    "M9 12a3 3 0 1 0 6 0 3 3 0 1 0-6 0",
+  ],
+  sun: ["M12 2v3", "M12 19v3", "M2 12h3", "M19 12h3", "m5 5 2 2", "m17 17 2 2", "m19 5-2 2", "M7 17l-2 2", "M8 12a4 4 0 1 0 8 0 4 4 0 1 0-8 0"],
+  trash: ["M4 7h16", "M9 3h6l1 4H8Z", "m6 7 1 14h10l1-14", "M10 11v6", "M14 11v6"],
+  upload: ["M12 21V9", "m5 14 5-5 5 5", "M5 3h14"],
+  user: ["M8 8a4 4 0 1 0 8 0 4 4 0 1 0-8 0", "M4 21a8 8 0 0 1 16 0"],
+};
+
+/** @const {!ReadonlyArray<string>} Names in the first-party icon registry. */
+export const ICON_NAMES = Object.freeze(Object.keys(paths).sort());
+
+function safeSize(value) {
+  if (/^\d+(?:\.\d+)?(?:px|rem|em)?$/.test(value || "")) return value;
+  return "1em";
+}
+
+/**
+ * Renders validated first-party SVG geometry with inherited color.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenIcon extends HTMLElement {
+  static get observedAttributes() {
+    return ["label", "name", "size"];
+  }
+
+  connectedCallback() {
+    this.render();
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected) this.render();
+  }
+
+  render() {
+    const requested = this.getAttribute("name") || "info";
+    const known = Object.hasOwn(paths, requested);
+    const definition = known ? paths[requested] : paths.alert;
+    const svg = document.createElementNS(SVG_NAMESPACE, "svg");
+    svg.setAttribute("viewBox", "0 0 24 24");
+    svg.setAttribute("fill", "none");
+    svg.setAttribute("stroke", "currentColor");
+    svg.setAttribute("stroke-width", "2");
+    svg.setAttribute("stroke-linecap", "round");
+    svg.setAttribute("stroke-linejoin", "round");
+    svg.setAttribute("focusable", "false");
+
+    for (const data of definition) {
+      const path = document.createElementNS(SVG_NAMESPACE, "path");
+      path.setAttribute("d", data);
+      svg.append(path);
+    }
+
+    const label = this.getAttribute("label");
+    if (label) {
+      this.setAttribute("role", "img");
+      this.setAttribute("aria-label", label);
+      this.removeAttribute("aria-hidden");
+    } else {
+      this.removeAttribute("role");
+      this.removeAttribute("aria-label");
+      this.setAttribute("aria-hidden", "true");
+    }
+    this.dataset.zenIcon = known ? requested : "alert";
+    this.style.setProperty("--zen-icon-size", safeSize(this.getAttribute("size")));
+    this.replaceChildren(svg);
+  }
+}
+
+if (!customElements.get("zen-icon")) {
+  customElements.define("zen-icon", ZenIcon);
+}
--- a/design_system/src/components/index.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/index.js	Tue Aug 04 15:12:09 2026 -0700
@@ -1,11 +1,56 @@
 export { ZenAlert } from "./alert.js";
 export { ZenButton } from "./button.js";
 export { ZenCard } from "./card.js";
+export {
+  ZenCarousel,
+  ZenDataTable,
+  ZenMessageScroller,
+  ZenResizable,
+} from "./collections.js";
+export {
+  ZenAccordion,
+  ZenCollapsible,
+  ZenSidebar,
+  ZenTabs,
+  ZenToggle,
+  ZenToggleGroup,
+} from "./disclosure.js";
 export { ZenField } from "./field.js";
 export {
+  ZenCalendar,
+  ZenCheckbox,
+  ZenCombobox,
+  ZenCommand,
+  ZenDatePicker,
+  ZenForm,
+  ZenInputOtp,
+  ZenRadioGroup,
+  ZenSelect,
+  ZenSlider,
+  ZenSwitch,
+} from "./forms.js";
+export { ICON_NAMES, ZenIcon } from "./icon.js";
+export {
   ZenNotifications,
   validateNotification,
   validateNotificationDismiss,
 } from "./notifications.js";
+export {
+  ZenAlertDialog,
+  ZenContextMenu,
+  ZenDialog,
+  ZenDrawer,
+  ZenDropdownMenu,
+  ZenHoverCard,
+  ZenMenubar,
+  ZenNavigationMenu,
+  ZenPopover,
+  ZenSheet,
+  ZenTooltip,
+} from "./overlays.js";
+export {
+  ZEN_PRIMITIVE_ELEMENTS,
+  ZenPrimitive,
+} from "./primitives.js";
 export { ZenStack } from "./stack.js";
 export { ZenStory } from "./story.js";
--- a/design_system/src/components/notifications.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/notifications.js	Tue Aug 04 15:12:09 2026 -0700
@@ -13,6 +13,12 @@
     (allowEmpty || value.trim().length > 0);
 }
 
+/**
+ * Validates and normalizes a notification event record.
+ *
+ * @param {*} value Candidate event detail.
+ * @return {?Object} Frozen normalized record, or null when invalid.
+ */
 export function validateNotification(value) {
   if (!value ||
       value.version !== 1 ||
@@ -53,6 +59,12 @@
   });
 }
 
+/**
+ * Validates a programmatic notification dismissal record.
+ *
+ * @param {*} value Candidate event detail.
+ * @return {?string} Valid notification ID, or null when invalid.
+ */
 export function validateNotificationDismiss(value) {
   if (!value ||
       value.version !== 1 ||
@@ -72,6 +84,11 @@
   };
 }
 
+/**
+ * Renders a bounded, scoped, Sonner-like notification queue.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenNotifications extends HTMLElement {
   static version = 1;
 
@@ -363,6 +380,8 @@
       const tone = document.createElement("span");
       tone.className = "zen-notification-tone";
       tone.setAttribute("aria-hidden", "true");
+      const toneIcon = document.createElement("zen-icon");
+      tone.append(toneIcon);
 
       const content = document.createElement("div");
       content.className = "zen-notification-content";
@@ -373,7 +392,9 @@
       const dismiss = document.createElement("button");
       dismiss.type = "button";
       dismiss.className = "zen-notification-dismiss";
-      dismiss.textContent = "×";
+      const dismissIcon = document.createElement("zen-icon");
+      dismissIcon.setAttribute("name", "close");
+      dismiss.append(dismissIcon);
       dismiss.addEventListener("click", () => {
         this.dismiss(record.id, "dismissed");
       });
@@ -402,18 +423,19 @@
         dismiss,
         message,
         tone,
+        toneIcon,
       };
       this.#resizeObserver?.observe(article);
     }
 
     const view = record.view;
     view.article.dataset.tone = record.tone;
-    view.tone.textContent = {
-      info: "i",
-      success: "✓",
-      warning: "!",
-      error: "×",
-    }[record.tone];
+    view.toneIcon.setAttribute("name", {
+      info: "info",
+      success: "check",
+      warning: "alert",
+      error: "error",
+    }[record.tone]);
     view.message.textContent = record.message;
     view.dismiss.setAttribute(
       "aria-label",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/overlays.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,865 @@
+let nextOverlayId = 1;
+
+function uniqueId(prefix) {
+  let id;
+  do id = `${prefix}-${nextOverlayId++}`;
+  while (document.getElementById(id));
+  return id;
+}
+
+function rememberAttribute(state, element, name) {
+  let attributes = state.get(element);
+  if (!attributes) {
+    attributes = new Map();
+    state.set(element, attributes);
+  }
+  if (!attributes.has(name)) {
+    attributes.set(name, element.getAttribute(name));
+  }
+}
+
+function setManagedAttribute(state, element, name, value) {
+  rememberAttribute(state, element, name);
+  if (value === null) element.removeAttribute(name);
+  else element.setAttribute(name, value);
+}
+
+function restoreAttributes(state) {
+  for (const [element, attributes] of state) {
+    for (const [name, value] of attributes) {
+      if (value === null) element.removeAttribute(name);
+      else element.setAttribute(name, value);
+    }
+  }
+  state.clear();
+}
+
+function resetManagedAttribute(state, element, name) {
+  const attributes = state.get(element);
+  if (!attributes?.has(name)) return;
+  const value = attributes.get(name);
+  if (value === null) element.removeAttribute(name);
+  else element.setAttribute(name, value);
+}
+
+function ensureId(state, element, prefix) {
+  const existing = element.id && document.getElementById(element.id);
+  if (!element.id || (existing && existing !== element)) {
+    setManagedAttribute(state, element, "id", uniqueId(prefix));
+  }
+  return element.id;
+}
+
+function eventElement(event) {
+  return event.target instanceof Element ? event.target : null;
+}
+
+const OVERLAY_COMPONENTS = [
+  "zen-dialog",
+  "zen-alert-dialog",
+  "zen-sheet",
+  "zen-drawer",
+  "zen-popover",
+  "zen-hover-card",
+  "zen-tooltip",
+].join(",");
+
+function ownedElement(host, selector) {
+  return [...host.querySelectorAll(selector)].find(
+    element => element.closest(OVERLAY_COMPONENTS) === host,
+  ) || null;
+}
+
+/**
+ * Wires a native modal dialog to explicit trigger and close controls.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenDialog extends HTMLElement {
+  static dialogRole = null;
+
+  constructor() {
+    super();
+    this._managed = new Map();
+    this._open = false;
+    this._openedByComponent = false;
+    this._onTriggerClick = event => {
+      event.preventDefault();
+      this.open();
+    };
+    this._onDialogClick = event => {
+      const control = eventElement(event)?.closest("[data-zen-close]");
+      if (!control || !this._dialog?.contains(control)) return;
+      const value = control.hasAttribute("value")
+        ? control.getAttribute("value")
+        : undefined;
+      this.close(value);
+    };
+    this._onNativeClose = () => this.syncOpen(false);
+  }
+
+  connectedCallback() {
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  sync() {
+    const trigger = ownedElement(this, "button[data-zen-trigger]");
+    const dialog = ownedElement(this, "dialog");
+    if (trigger === this._trigger && dialog === this._dialog) return;
+    if (this._openedByComponent) this.close();
+    this.unbind();
+    this._trigger = trigger;
+    this._dialog = dialog;
+    if (!this._trigger || !this._dialog) return;
+
+    const id = ensureId(this._managed, this._dialog, this.localName);
+    setManagedAttribute(
+      this._managed,
+      this._trigger,
+      "aria-haspopup",
+      "dialog",
+    );
+    setManagedAttribute(this._managed, this._trigger, "aria-controls", id);
+    if (this.constructor.dialogRole) {
+      setManagedAttribute(
+        this._managed,
+        this._dialog,
+        "role",
+        this.constructor.dialogRole,
+      );
+    }
+    this._trigger.addEventListener("click", this._onTriggerClick);
+    this._dialog.addEventListener("click", this._onDialogClick);
+    this._dialog.addEventListener("close", this._onNativeClose);
+    this.syncOpen(this._dialog.open);
+  }
+
+  unbind() {
+    this._trigger?.removeEventListener("click", this._onTriggerClick);
+    this._dialog?.removeEventListener("click", this._onDialogClick);
+    this._dialog?.removeEventListener("close", this._onNativeClose);
+    restoreAttributes(this._managed);
+    this._trigger = null;
+    this._dialog = null;
+    this._open = false;
+    this._openedByComponent = false;
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    if (this._openedByComponent) this.close();
+    this.unbind();
+  }
+
+  open() {
+    if (!this._dialog || this._dialog.open || this._open) return;
+    try {
+      if (typeof this._dialog.showModal === "function") {
+        this._dialog.showModal();
+      } else {
+        setManagedAttribute(this._managed, this._dialog, "open", "");
+      }
+      this._openedByComponent = true;
+      this.syncOpen(true);
+    } catch {
+      this.syncOpen(Boolean(this._dialog.open));
+    }
+  }
+
+  close(returnValue) {
+    if (!this._dialog || (!this._dialog.open && !this._open)) return;
+    if (typeof this._dialog.close === "function") {
+      if (returnValue === undefined) this._dialog.close();
+      else this._dialog.close(returnValue);
+    } else {
+      setManagedAttribute(this._managed, this._dialog, "open", null);
+    }
+    this.syncOpen(false);
+  }
+
+  syncOpen(open) {
+    this._open = open;
+    if (!open) this._openedByComponent = false;
+    if (this._trigger) {
+      setManagedAttribute(
+        this._managed,
+        this._trigger,
+        "aria-expanded",
+        String(open),
+      );
+    }
+  }
+}
+
+/**
+ * Presents a native modal with alert-dialog semantics.
+ *
+ * @extends {ZenDialog}
+ */
+export class ZenAlertDialog extends ZenDialog {
+  static dialogRole = "alertdialog";
+}
+
+/**
+ * Presents a native dialog as an edge-aligned sheet.
+ *
+ * @extends {ZenDialog}
+ */
+export class ZenSheet extends ZenDialog {}
+
+/**
+ * Presents a native dialog as a drawer.
+ *
+ * @extends {ZenDialog}
+ */
+export class ZenDrawer extends ZenDialog {}
+
+function isPopoverOpen(element) {
+  try {
+    return element.matches(":popover-open");
+  } catch {
+    return false;
+  }
+}
+
+/**
+ * Connects a trigger to a native popover with an accessible fallback.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenPopover extends HTMLElement {
+  constructor() {
+    super();
+    this._managed = new Map();
+    this._open = false;
+    this._onClick = event => {
+      const target = eventElement(event);
+      if (!target) return;
+      if (this._trigger?.contains(target)) {
+        event.preventDefault();
+        this.toggle();
+      } else if (this._content?.contains(target) &&
+                 target.closest("[data-zen-close]")) {
+        this.hide();
+      }
+    };
+    this._onToggle = event => {
+      this.syncOpen(event.newState
+        ? event.newState === "open"
+        : isPopoverOpen(this._content));
+    };
+    this._onDocumentPointerDown = event => {
+      if (!this._native && this._open && !this.contains(event.target)) {
+        this.hide();
+      }
+    };
+    this._onDocumentKeyDown = event => {
+      if (!this._native && this._open && event.key === "Escape") {
+        this.hide();
+        this._trigger?.focus();
+      }
+    };
+  }
+
+  connectedCallback() {
+    this.addEventListener("click", this._onClick);
+    document.addEventListener("pointerdown", this._onDocumentPointerDown);
+    document.addEventListener("keydown", this._onDocumentKeyDown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  sync() {
+    const trigger = ownedElement(this, "[data-zen-trigger]");
+    const content = ownedElement(
+      this,
+      "[data-zen-content], [popover]",
+    );
+    if (trigger === this._trigger && content === this._content) return;
+    if (this._open) this.hide();
+    this.unbindElements();
+    this._trigger = trigger;
+    this._content = content;
+    if (!this._trigger || !this._content) return;
+
+    const id = ensureId(this._managed, this._content, "zen-popover");
+    setManagedAttribute(this._managed, this._trigger, "aria-controls", id);
+    this._native = typeof this._content.showPopover === "function" &&
+      typeof this._content.hidePopover === "function";
+    if (this._native && !this._content.hasAttribute("popover")) {
+      setManagedAttribute(this._managed, this._content, "popover", "auto");
+    }
+    if (this._native && "popoverTargetElement" in this._trigger) {
+      this._originalPopoverTarget = this._trigger.popoverTargetElement;
+      this._trigger.popoverTargetElement = this._content;
+    }
+    if (this._native) {
+      setManagedAttribute(this._managed, this._content, "hidden", null);
+    } else {
+      setManagedAttribute(this._managed, this._content, "hidden", "");
+    }
+
+    this._content.addEventListener("toggle", this._onToggle);
+    this.syncOpen(this._native && isPopoverOpen(this._content));
+  }
+
+  unbindElements() {
+    this._content?.removeEventListener("toggle", this._onToggle);
+    if (this._trigger && "popoverTargetElement" in this._trigger) {
+      this._trigger.popoverTargetElement = this._originalPopoverTarget || null;
+    }
+    restoreAttributes(this._managed);
+    this._trigger = null;
+    this._content = null;
+    this._native = false;
+    this._open = false;
+    this._originalPopoverTarget = null;
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    document.removeEventListener("pointerdown", this._onDocumentPointerDown);
+    document.removeEventListener("keydown", this._onDocumentKeyDown);
+    if (this._open) this.hide();
+    this.unbindElements();
+  }
+
+  toggle() {
+    if (this._open || isPopoverOpen(this._content)) this.hide();
+    else this.show();
+  }
+
+  show() {
+    if (!this._content || this._open) return;
+    if (this._native) {
+      try {
+        this._content.showPopover();
+      } catch {
+        this._native = false;
+        setManagedAttribute(this._managed, this._content, "hidden", null);
+      }
+    } else {
+      setManagedAttribute(this._managed, this._content, "hidden", null);
+    }
+    this.syncOpen(true);
+  }
+
+  hide() {
+    if (!this._content || !this._open) return;
+    if (this._native) {
+      try {
+        this._content.hidePopover();
+      } catch {
+        this._native = false;
+        setManagedAttribute(this._managed, this._content, "hidden", "");
+      }
+    } else {
+      setManagedAttribute(this._managed, this._content, "hidden", "");
+    }
+    this.syncOpen(false);
+  }
+
+  syncOpen(open) {
+    this._open = open;
+    if (this._trigger) {
+      setManagedAttribute(
+        this._managed,
+        this._trigger,
+        "aria-expanded",
+        String(open),
+      );
+    }
+    if (!this._native && this._content) {
+      setManagedAttribute(
+        this._managed,
+        this._content,
+        "hidden",
+        open ? null : "",
+      );
+    }
+  }
+}
+
+class ZenTimedOverlay extends HTMLElement {
+  static delay = 150;
+  static tooltip = false;
+
+  constructor() {
+    super();
+    this._managed = new Map();
+    this._timer = null;
+    this._open = false;
+    this._pointerWithin = false;
+    this._focusWithin = false;
+    this._onPointerEnter = () => {
+      this._pointerWithin = true;
+      this.schedule(true);
+    };
+    this._onPointerLeave = event => {
+      if (event.relatedTarget instanceof Node &&
+          this.contains(event.relatedTarget)) return;
+      this._pointerWithin = false;
+      this.schedule(this._focusWithin);
+    };
+    this._onFocusIn = () => {
+      this._focusWithin = true;
+      this.schedule(true);
+    };
+    this._onFocusOut = event => {
+      if (event.relatedTarget instanceof Node &&
+          this.contains(event.relatedTarget)) return;
+      this._focusWithin = false;
+      this.schedule(this._pointerWithin);
+    };
+    this._onKeyDown = event => {
+      if (event.key !== "Escape" || !this._open) return;
+      clearTimeout(this._timer);
+      this._timer = null;
+      this.setOpen(false);
+    };
+  }
+
+  connectedCallback() {
+    this.addEventListener("keydown", this._onKeyDown);
+    this._observer ||= new MutationObserver(() => this.sync());
+    this._observer.observe(this, { childList: true, subtree: true });
+    this.sync();
+  }
+
+  sync() {
+    const trigger = ownedElement(this, "[data-zen-trigger]");
+    const content = ownedElement(this, "[data-zen-content]");
+    if (trigger === this._trigger && content === this._content) return;
+    this.unbindElements();
+    this._trigger = trigger;
+    this._content = content;
+    if (!this._trigger || !this._content) return;
+
+    const id = ensureId(this._managed, this._content, this.localName);
+    setManagedAttribute(this._managed, this._content, "hidden", "");
+    if (this.constructor.tooltip) {
+      setManagedAttribute(this._managed, this._content, "role", "tooltip");
+      const ids = new Set(
+        (this._trigger.getAttribute("aria-describedby") || "")
+          .split(/\s+/)
+          .filter(Boolean),
+      );
+      ids.add(id);
+      setManagedAttribute(
+        this._managed,
+        this._trigger,
+        "aria-describedby",
+        [...ids].join(" "),
+      );
+    } else {
+      setManagedAttribute(this._managed, this._trigger, "aria-controls", id);
+      setManagedAttribute(
+        this._managed,
+        this._trigger,
+        "aria-expanded",
+        "false",
+      );
+    }
+
+    for (const element of [this._trigger, this._content]) {
+      element.addEventListener("pointerenter", this._onPointerEnter);
+      element.addEventListener("pointerleave", this._onPointerLeave);
+      element.addEventListener("focusin", this._onFocusIn);
+      element.addEventListener("focusout", this._onFocusOut);
+    }
+  }
+
+  unbindElements() {
+    clearTimeout(this._timer);
+    this._timer = null;
+    for (const element of [this._trigger, this._content]) {
+      element?.removeEventListener("pointerenter", this._onPointerEnter);
+      element?.removeEventListener("pointerleave", this._onPointerLeave);
+      element?.removeEventListener("focusin", this._onFocusIn);
+      element?.removeEventListener("focusout", this._onFocusOut);
+    }
+    restoreAttributes(this._managed);
+    this._trigger = null;
+    this._content = null;
+    this._open = false;
+    this._pointerWithin = false;
+    this._focusWithin = false;
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("keydown", this._onKeyDown);
+    this.unbindElements();
+  }
+
+  schedule(open) {
+    clearTimeout(this._timer);
+    this._timer = setTimeout(
+      () => this.setOpen(open),
+      this.constructor.delay,
+    );
+  }
+
+  setOpen(open) {
+    if (!this._content || open === this._open) return;
+    this._open = open;
+    setManagedAttribute(
+      this._managed,
+      this._content,
+      "hidden",
+      open ? null : "",
+    );
+    if (!this.constructor.tooltip) {
+      setManagedAttribute(
+        this._managed,
+        this._trigger,
+        "aria-expanded",
+        String(open),
+      );
+    }
+  }
+}
+
+/**
+ * Shows supplemental interactive content on hover or focus.
+ *
+ * @extends {ZenTimedOverlay}
+ */
+export class ZenHoverCard extends ZenTimedOverlay {
+  static delay = 150;
+}
+
+/**
+ * Shows a delayed non-interactive description on hover or focus.
+ *
+ * @extends {ZenTimedOverlay}
+ */
+export class ZenTooltip extends ZenTimedOverlay {
+  static delay = 350;
+  static tooltip = true;
+}
+
+const MENU_COMPONENTS = [
+  "zen-dropdown-menu",
+  "zen-context-menu",
+  "zen-menubar",
+  "zen-navigation-menu",
+].join(",");
+const MENU_SELECTOR = "[data-zen-menu], [role='menu'], [data-zen-content]";
+const ITEM_SELECTOR = [
+  "[role='menuitem']",
+  "[role='menuitemcheckbox']",
+  "[role='menuitemradio']",
+  "[data-zen-menu-item]",
+  "a[href]",
+  "button",
+  "input[type='button']",
+  "input[type='submit']",
+].join(",");
+
+class ZenMenu extends HTMLElement {
+  static contextMenu = false;
+  static menubar = false;
+  static multiple = false;
+
+  constructor() {
+    super();
+    this._managed = new Map();
+    this._pairs = [];
+    this._openPair = null;
+    this._onClick = event => {
+      const target = eventElement(event);
+      if (!target) return;
+      const pair = this._pairs.find(({ trigger }) =>
+        trigger.contains(target));
+      if (pair) {
+        event.preventDefault();
+        if (this._openPair === pair) this.close(false);
+        else this.open(pair, 0, this.constructor.contextMenu ? event : null);
+        return;
+      }
+      const item = target.closest(ITEM_SELECTOR);
+      if (this._openPair?.menu.contains(target) &&
+          item &&
+          !item.hasAttribute("disabled") &&
+          item.getAttribute("aria-disabled") !== "true") {
+        this.close(true);
+      }
+    };
+    this._onContextMenu = event => {
+      if (!this.constructor.contextMenu ||
+          this._pairs.some(({ menu }) => menu.contains(event.target))) return;
+      event.preventDefault();
+      this.open(this._pairs[0], 0, event);
+    };
+    this._onKeyDown = event => this.handleKeyDown(event);
+    this._onDocumentPointerDown = event => {
+      if (!this._openPair) return;
+      const { trigger, menu } = this._openPair;
+      if (!trigger.contains(event.target) && !menu.contains(event.target)) {
+        this.close(false);
+      }
+    };
+  }
+
+  connectedCallback() {
+    this.setupPairs();
+    this.addEventListener("click", this._onClick);
+    this.addEventListener("contextmenu", this._onContextMenu);
+    this.addEventListener("keydown", this._onKeyDown);
+    document.addEventListener("pointerdown", this._onDocumentPointerDown);
+    this._observer ||= new MutationObserver(() => this.refreshPairs());
+    this._observer.observe(this, { childList: true, subtree: true });
+  }
+
+  disconnectedCallback() {
+    this._observer?.disconnect();
+    this.removeEventListener("click", this._onClick);
+    this.removeEventListener("contextmenu", this._onContextMenu);
+    this.removeEventListener("keydown", this._onKeyDown);
+    document.removeEventListener("pointerdown", this._onDocumentPointerDown);
+    this._openPair = null;
+    restoreAttributes(this._managed);
+    this._pairs = [];
+  }
+
+  refreshPairs() {
+    if (this._openPair) this.close(false);
+    restoreAttributes(this._managed);
+    this._pairs = [];
+    this.setupPairs();
+  }
+
+  ownedElements(selector) {
+    return [...this.querySelectorAll(selector)].filter(element =>
+      element.closest(MENU_COMPONENTS) === this);
+  }
+
+  setupPairs() {
+    let triggers = this.ownedElements("[data-zen-trigger]");
+    const menus = this.ownedElements(MENU_SELECTOR);
+    triggers = triggers.filter(trigger =>
+      !menus.some(menu => menu.contains(trigger)));
+    if (!this.constructor.multiple) triggers = triggers.slice(0, 1);
+
+    const unused = new Set(menus);
+    for (const trigger of triggers) {
+      const controlled = trigger.getAttribute("aria-controls");
+      let menu = controlled
+        ? menus.find(candidate => candidate.id === controlled)
+        : null;
+      if (!menu) menu = [...unused][0];
+      if (!menu) continue;
+      unused.delete(menu);
+
+      const triggerId = ensureId(this._managed, trigger, `${this.localName}-trigger`);
+      const menuId = ensureId(this._managed, menu, `${this.localName}-menu`);
+      setManagedAttribute(this._managed, trigger, "aria-haspopup", "menu");
+      setManagedAttribute(this._managed, trigger, "aria-controls", menuId);
+      setManagedAttribute(this._managed, trigger, "aria-expanded", "false");
+      setManagedAttribute(this._managed, menu, "role", "menu");
+      setManagedAttribute(this._managed, menu, "aria-labelledby", triggerId);
+      setManagedAttribute(this._managed, menu, "hidden", "");
+      if (this.constructor.menubar) {
+        setManagedAttribute(this._managed, trigger, "role", "menuitem");
+      }
+      const pair = { trigger, menu };
+      this._pairs.push(pair);
+      this.prepareItems(pair);
+    }
+    if (this.constructor.menubar) {
+      setManagedAttribute(this._managed, this, "role", "menubar");
+      this.setMenubarTabStop(this._pairs[0]);
+    }
+  }
+
+  prepareItems(pair) {
+    const items = [...pair.menu.querySelectorAll(ITEM_SELECTOR)].filter(item =>
+      item.closest(MENU_SELECTOR) === pair.menu &&
+      !item.hidden &&
+      !item.hasAttribute("disabled") &&
+      item.getAttribute("aria-disabled") !== "true");
+    for (const item of items) {
+      if (!item.hasAttribute("role")) {
+        setManagedAttribute(this._managed, item, "role", "menuitem");
+      }
+      setManagedAttribute(this._managed, item, "tabindex", "-1");
+    }
+    return items;
+  }
+
+  open(pair, itemIndex = 0, pointerEvent = null) {
+    if (!pair) return;
+    if (this._openPair && this._openPair !== pair) this.close(false);
+    this._openPair = pair;
+    if (this.constructor.menubar) this.setMenubarTabStop(pair);
+    if (pointerEvent) {
+      rememberAttribute(this._managed, pair.menu, "style");
+      pair.menu.style.position = "fixed";
+      pair.menu.style.left = `${Number(pointerEvent.clientX) || 0}px`;
+      pair.menu.style.top = `${Number(pointerEvent.clientY) || 0}px`;
+    } else {
+      resetManagedAttribute(this._managed, pair.menu, "style");
+    }
+    setManagedAttribute(this._managed, pair.menu, "hidden", null);
+    setManagedAttribute(this._managed, pair.trigger, "aria-expanded", "true");
+    const items = this.prepareItems(pair);
+    if (items.length) {
+      const index = itemIndex < 0 ? items.length - 1 : itemIndex;
+      setManagedAttribute(this._managed, items[index], "tabindex", "0");
+      items[index].focus();
+    } else {
+      setManagedAttribute(this._managed, pair.menu, "tabindex", "-1");
+      pair.menu.focus();
+    }
+  }
+
+  close(restoreFocus) {
+    if (!this._openPair) return;
+    const pair = this._openPair;
+    this._openPair = null;
+    setManagedAttribute(this._managed, pair.menu, "hidden", "");
+    setManagedAttribute(this._managed, pair.trigger, "aria-expanded", "false");
+    resetManagedAttribute(this._managed, pair.menu, "style");
+    if (restoreFocus) pair.trigger.focus();
+  }
+
+  moveItem(pair, offset, edge = null) {
+    const active = document.activeElement;
+    const items = this.prepareItems(pair);
+    if (!items.length) return;
+    let index = items.indexOf(active);
+    if (edge === "first") index = 0;
+    else if (edge === "last") index = items.length - 1;
+    else index = (Math.max(index, 0) + offset + items.length) % items.length;
+    setManagedAttribute(this._managed, items[index], "tabindex", "0");
+    items[index].focus();
+  }
+
+  moveMenubarTrigger(pair, offset, openMenu) {
+    const index = this._pairs.indexOf(pair);
+    const next = this._pairs[
+      (index + offset + this._pairs.length) % this._pairs.length
+    ];
+    this.setMenubarTabStop(next);
+    if (openMenu) this.open(next);
+    else next.trigger.focus();
+  }
+
+  setMenubarTabStop(activePair) {
+    for (const pair of this._pairs) {
+      setManagedAttribute(
+        this._managed,
+        pair.trigger,
+        "tabindex",
+        pair === activePair ? "0" : "-1",
+      );
+    }
+  }
+
+  handleKeyDown(event) {
+    const target = eventElement(event);
+    if (!target) return;
+    const triggerPair = this._pairs.find(({ trigger }) =>
+      trigger.contains(target));
+    if (triggerPair) {
+      if (this.constructor.menubar &&
+          (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
+        event.preventDefault();
+        this.moveMenubarTrigger(
+          triggerPair,
+          event.key === "ArrowRight" ? 1 : -1,
+          false,
+        );
+      } else if (["Enter", " ", "ArrowDown", "ArrowUp"].includes(event.key)) {
+        event.preventDefault();
+        this.open(triggerPair, event.key === "ArrowUp" ? -1 : 0);
+      } else if (event.key === "Escape" && this._openPair) {
+        event.preventDefault();
+        this.close(true);
+      }
+      return;
+    }
+
+    const pair = this._pairs.find(({ menu }) => menu.contains(target));
+    if (!pair || this._openPair !== pair) return;
+    if (event.key === "ArrowDown") {
+      event.preventDefault();
+      this.moveItem(pair, 1);
+    } else if (event.key === "ArrowUp") {
+      event.preventDefault();
+      this.moveItem(pair, -1);
+    } else if (event.key === "Home" || event.key === "End") {
+      event.preventDefault();
+      this.moveItem(pair, 0, event.key === "Home" ? "first" : "last");
+    } else if (event.key === "Escape") {
+      event.preventDefault();
+      this.close(true);
+    } else if (event.key === "Tab") {
+      this.close(false);
+    } else if (this.constructor.menubar &&
+               (event.key === "ArrowRight" || event.key === "ArrowLeft")) {
+      event.preventDefault();
+      this.moveMenubarTrigger(
+        pair,
+        event.key === "ArrowRight" ? 1 : -1,
+        true,
+      );
+    }
+  }
+}
+
+/**
+ * Provides an accessible action menu opened from a native trigger.
+ *
+ * @extends {ZenMenu}
+ */
+export class ZenDropdownMenu extends ZenMenu {}
+
+/**
+ * Opens an accessible action menu at the pointer location.
+ *
+ * @extends {ZenMenu}
+ */
+export class ZenContextMenu extends ZenMenu {
+  static contextMenu = true;
+}
+
+/**
+ * Coordinates multiple keyboard-accessible application menus.
+ *
+ * @extends {ZenMenu}
+ */
+export class ZenMenubar extends ZenMenu {
+  static menubar = true;
+  static multiple = true;
+}
+
+/**
+ * Provides keyboard-accessible navigation flyouts.
+ *
+ * @extends {ZenMenu}
+ */
+export class ZenNavigationMenu extends ZenMenu {}
+
+const definitions = {
+  "zen-dialog": ZenDialog,
+  "zen-alert-dialog": ZenAlertDialog,
+  "zen-sheet": ZenSheet,
+  "zen-drawer": ZenDrawer,
+  "zen-popover": ZenPopover,
+  "zen-hover-card": ZenHoverCard,
+  "zen-tooltip": ZenTooltip,
+  "zen-dropdown-menu": ZenDropdownMenu,
+  "zen-context-menu": ZenContextMenu,
+  "zen-menubar": ZenMenubar,
+  "zen-navigation-menu": ZenNavigationMenu,
+};
+
+for (const [name, constructor] of Object.entries(definitions)) {
+  if (!customElements.get(name)) customElements.define(name, constructor);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/components/primitives.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,143 @@
+/** @const {!ReadonlyArray<string>} Registered presentation-only elements. */
+export const ZEN_PRIMITIVE_ELEMENTS = [
+  "zen-aspect-ratio",
+  "zen-attachment",
+  "zen-avatar",
+  "zen-badge",
+  "zen-breadcrumb",
+  "zen-bubble",
+  "zen-button-group",
+  "zen-chart",
+  "zen-direction",
+  "zen-empty",
+  "zen-input",
+  "zen-input-group",
+  "zen-item",
+  "zen-kbd",
+  "zen-label",
+  "zen-marker",
+  "zen-message",
+  "zen-native-select",
+  "zen-pagination",
+  "zen-progress",
+  "zen-scroll-area",
+  "zen-separator",
+  "zen-skeleton",
+  "zen-spinner",
+  "zen-table",
+  "zen-textarea",
+  "zen-typography",
+];
+
+function parseRatio(value) {
+  const [width, height] = String(value || "16/9")
+    .split("/")
+    .map(Number);
+  if (!Number.isFinite(width) || !Number.isFinite(height) ||
+      width <= 0 || height <= 0) return "16 / 9";
+  return `${width} / ${height}`;
+}
+
+/**
+ * Applies small semantic enhancements shared by presentation primitives.
+ *
+ * @extends {HTMLElement}
+ */
+export class ZenPrimitive extends HTMLElement {
+  connectedCallback() {
+    this.sync();
+  }
+
+  static get observedAttributes() {
+    return ["dir", "ratio", "value", "width"];
+  }
+
+  attributeChangedCallback() {
+    if (this.isConnected) this.sync();
+  }
+
+  sync() {
+    switch (this.localName) {
+      case "zen-aspect-ratio":
+        this.style.setProperty(
+          "--zen-aspect-ratio",
+          parseRatio(this.getAttribute("ratio")),
+        );
+        break;
+      case "zen-breadcrumb": {
+        const navigation = this.querySelector(":scope > nav");
+        if (navigation && !navigation.hasAttribute("aria-label")) {
+          navigation.setAttribute("aria-label", "Breadcrumb");
+        }
+        break;
+      }
+      case "zen-chart":
+        if (!this.hasAttribute("role")) this.setAttribute("role", "img");
+        break;
+      case "zen-direction":
+        if (!this.hasAttribute("dir") && this.hasAttribute("value")) {
+          this.dir = this.getAttribute("value");
+        }
+        break;
+      case "zen-pagination": {
+        const navigation = this.querySelector(":scope > nav");
+        if (navigation && !navigation.hasAttribute("aria-label")) {
+          navigation.setAttribute("aria-label", "Pagination");
+        }
+        break;
+      }
+      case "zen-native-select": {
+        if (!this.querySelector("select")) break;
+        let icon = this.querySelector(
+          ":scope > zen-icon[data-zen-select-icon]",
+        );
+        if (!icon) {
+          icon = document.createElement("zen-icon");
+          icon.dataset.zenSelectIcon = "";
+          icon.dataset.zenGenerated = "true";
+          icon.setAttribute("name", "chevron-down");
+          this.append(icon);
+        }
+        break;
+      }
+      case "zen-separator":
+        if (!this.querySelector(":scope > hr")) {
+          if (!this.hasAttribute("role")) {
+            this.setAttribute("role", "separator");
+          }
+          if (!this.hasAttribute("aria-orientation")) {
+            this.setAttribute(
+              "aria-orientation",
+              this.getAttribute("orientation") === "vertical"
+                ? "vertical"
+                : "horizontal",
+            );
+          }
+        }
+        break;
+      case "zen-skeleton":
+        if (this.hasAttribute("width")) {
+          this.style.setProperty(
+            "--zen-skeleton-width",
+            this.getAttribute("width"),
+          );
+        } else {
+          this.style.removeProperty("--zen-skeleton-width");
+        }
+        if (!this.hasAttribute("role")) this.setAttribute("aria-hidden", "true");
+        break;
+      case "zen-spinner":
+        if (!this.hasAttribute("role")) this.setAttribute("role", "status");
+        if (!this.hasAttribute("aria-label")) {
+          this.setAttribute("aria-label", "Loading");
+        }
+        break;
+    }
+  }
+}
+
+for (const name of ZEN_PRIMITIVE_ELEMENTS) {
+  if (!customElements.get(name)) {
+    customElements.define(name, class extends ZenPrimitive {});
+  }
+}
--- a/design_system/src/components/stack.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/stack.js	Tue Aug 04 15:12:09 2026 -0700
@@ -1,3 +1,8 @@
+/**
+ * Provides a token-driven flex layout around arbitrary native HTML.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenStack extends HTMLElement {}
 
 if (!customElements.get("zen-stack")) {
--- a/design_system/src/components/story.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/components/story.js	Tue Aug 04 15:12:09 2026 -0700
@@ -9,6 +9,11 @@
   return lines.map(line => line.slice(minimum)).join("\n");
 }
 
+/**
+ * Renders a declarative component example and its copyable HTML source.
+ *
+ * @extends {HTMLElement}
+ */
 export class ZenStory extends HTMLElement {
   connectedCallback() {
     if (this.dataset.ready === "true") return;
--- a/design_system/src/index.html	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/index.html	Tue Aug 04 15:12:09 2026 -0700
@@ -18,10 +18,25 @@
           Zenbu UI
         </a>
 
+        <zen-input-group class="catalog-search">
+          <zen-icon name="search"></zen-icon>
+          <input
+            id="componentSearch"
+            type="search"
+            placeholder="Search components"
+            aria-label="Search components"
+            aria-describedby="componentSearchStatus"
+            autocomplete="off"
+          />
+          <kbd aria-hidden="true">/</kbd>
+        </zen-input-group>
+        <p id="componentSearchStatus" class="search-status" role="status"></p>
+
         <h2>Foundations</h2>
         <nav class="catalog-nav" aria-label="Foundations">
           <a href="/" data-catalog-link>Overview</a>
           <a href="/tokens" data-catalog-link>Tokens</a>
+          <a href="/icons" data-catalog-link>Icons</a>
         </nav>
 
         <h2>Components</h2>
@@ -97,14 +112,58 @@
           </header>
           <div class="token-grid">
             <section class="token-group">
-              <h2>Color</h2>
+              <h2>Semantic color</h2>
               <dl class="swatch-list">
-                <div><span class="swatch" style="--swatch: var(--zen-color-accent)"></span><div><dt>--zen-color-accent</dt><dd>Primary action</dd></div></div>
-                <div><span class="swatch" style="--swatch: var(--zen-color-info)"></span><div><dt>--zen-color-info</dt><dd>Informational state</dd></div></div>
-                <div><span class="swatch" style="--swatch: var(--zen-color-success)"></span><div><dt>--zen-color-success</dt><dd>Successful state</dd></div></div>
-                <div><span class="swatch" style="--swatch: var(--zen-color-danger)"></span><div><dt>--zen-color-danger</dt><dd>Dangerous state</dd></div></div>
+                <div><span class="swatch" style="--zen-color-swatch: var(--zen-color-accent)"></span><div><dt>--zen-color-accent</dt><dd>Primary action</dd></div></div>
+                <div><span class="swatch" style="--zen-color-swatch: var(--zen-color-info)"></span><div><dt>--zen-color-info</dt><dd>Informational state</dd></div></div>
+                <div><span class="swatch" style="--zen-color-swatch: var(--zen-color-success)"></span><div><dt>--zen-color-success</dt><dd>Successful state</dd></div></div>
+                <div><span class="swatch" style="--zen-color-swatch: var(--zen-color-danger)"></span><div><dt>--zen-color-danger</dt><dd>Dangerous state</dd></div></div>
               </dl>
             </section>
+            <section class="token-group token-group-wide">
+              <h2>Material palette</h2>
+              <p>Warm, quiet colors inspired by paper, natural dye, clay, and wood.</p>
+              <div class="palette-grid">
+                <div><span style="--zen-color-swatch: var(--zen-color-paper)"></span><code>paper</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-washi)"></span><code>washi</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-linen)"></span><code>linen</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-sumi)"></span><code>sumi</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-brick)"></span><code>brick</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-persimmon)"></span><code>persimmon</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-ochre)"></span><code>ochre</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-moss)"></span><code>moss</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-patina)"></span><code>patina</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-indigo)"></span><code>indigo</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-plum)"></span><code>plum</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-clay)"></span><code>clay</code></div>
+                <div><span style="--zen-color-swatch: var(--zen-color-wood)"></span><code>wood</code></div>
+              </div>
+            </section>
+            <section class="token-group token-group-wide">
+              <h2>Data palette</h2>
+              <p>Ten distinct aliases for charts and categorical comparisons.</p>
+              <div class="data-palette" aria-label="Data color tokens">
+                <span style="--zen-color-swatch: var(--zen-color-data-1)" title="--zen-color-data-1"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-2)" title="--zen-color-data-2"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-3)" title="--zen-color-data-3"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-4)" title="--zen-color-data-4"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-5)" title="--zen-color-data-5"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-6)" title="--zen-color-data-6"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-7)" title="--zen-color-data-7"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-8)" title="--zen-color-data-8"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-9)" title="--zen-color-data-9"></span>
+                <span style="--zen-color-swatch: var(--zen-color-data-10)" title="--zen-color-data-10"></span>
+              </div>
+            </section>
+            <section class="token-group">
+              <h2>Color ramps</h2>
+              <zen-stack gap="tight">
+                <code>neutral · red · orange · amber</code>
+                <code>green · teal · blue · violet</code>
+                <code>rose · brown</code>
+                <small>Each ramp includes 50–900 plus 950.</small>
+              </zen-stack>
+            </section>
             <section class="token-group">
               <h2>Spacing</h2>
               <zen-stack gap="tight">
@@ -126,6 +185,15 @@
           </div>
         </section>
 
+        <section class="catalog-page" data-catalog-page="icons" hidden>
+          <header class="page-heading">
+            <p class="eyebrow">Foundations</p>
+            <h1>Icons</h1>
+            <p>First-party SVG icons rendered by <code>zen-icon</code>. Icons inherit color and never depend on emoji, fonts, or an external package.</p>
+          </header>
+          <div id="iconGrid" class="icon-grid" aria-label="Zenbu icon names"></div>
+        </section>
+
         <section class="catalog-page" data-catalog-page="button" hidden>
           <header class="page-heading">
             <p class="eyebrow">Component</p>
--- a/design_system/src/storybook.css	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/storybook.css	Tue Aug 04 15:12:09 2026 -0700
@@ -47,6 +47,34 @@
   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;
@@ -55,7 +83,7 @@
   border: var(--zen-border-width) solid var(--zen-color-border);
   border-radius: 50%;
   background: var(--zen-color-accent);
-  color: #171a21;
+  color: var(--zen-color-on-accent);
 }
 
 .catalog-sidebar h2 {
@@ -78,10 +106,15 @@
   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: #171a21;
+  color: var(--zen-color-on-accent);
 }
 
 .theme-toggle {
@@ -97,10 +130,15 @@
 
 .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;
 }
@@ -160,6 +198,15 @@
   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);
@@ -185,11 +232,81 @@
   height: 2rem;
   border: 1px solid var(--zen-color-border);
   border-radius: 50%;
-  background: var(--swatch);
+  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);
@@ -223,8 +340,8 @@
   min-height: 8rem;
   padding: clamp(1rem, 4vw, 3rem);
   background:
-    linear-gradient(90deg, rgba(127, 127, 127, 0.08) 1px, transparent 1px),
-    linear-gradient(rgba(127, 127, 127, 0.08) 1px, transparent 1px);
+    linear-gradient(90deg, var(--zen-color-gridline) 1px, transparent 1px),
+    linear-gradient(var(--zen-color-gridline) 1px, transparent 1px);
   background-size: 1rem 1rem;
 }
 
@@ -234,8 +351,8 @@
   margin: 0;
   padding: var(--zen-space-4);
   border-top: 1px solid var(--zen-color-border);
-  background: #111318;
-  color: #f4f4f5;
+  background: var(--zen-color-code-surface);
+  color: var(--zen-color-code-text);
   font: var(--zen-font-size-sm)/1.55 var(--zen-font-mono);
 }
 
@@ -265,4 +382,12 @@
   .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 12:21:19 2026 -0700
+++ b/design_system/src/storybook.js	Tue Aug 04 15:12:09 2026 -0700
@@ -1,9 +1,22 @@
 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"],
@@ -12,6 +25,160 @@
   ["/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]")) {
@@ -31,6 +198,9 @@
 }
 
 window.addEventListener("DOMContentLoaded", () => {
+  installComponentCatalog();
+  installIconCatalog();
+  installComponentSearch();
   const root = document.documentElement;
   const systemTheme = matchMedia("(prefers-color-scheme: dark)");
   const storedTheme = localStorage.getItem("zen-theme");
--- a/design_system/src/styles/components.css	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/styles/components.css	Tue Aug 04 15:12:09 2026 -0700
@@ -1,3 +1,5 @@
+@import url("./shadcn.css");
+
 :where(
   zen-button,
   zen-card,
@@ -27,7 +29,7 @@
   border-radius: var(--zen-radius-md);
   box-shadow: var(--zen-shadow-sm);
   background: var(--zen-color-accent);
-  color: #171a21;
+  color: var(--zen-color-on-accent);
   font: 700 var(--zen-font-size-md)/1 var(--zen-font-sans);
   text-decoration: none;
   cursor: pointer;
@@ -40,7 +42,7 @@
 zen-button > :where(button, a):hover {
   background: var(--zen-color-accent-hover);
   transform: translate(-1px, -1px);
-  box-shadow: 5px 5px 0 rgba(23, 26, 33, 0.18);
+  box-shadow: var(--zen-shadow-hover);
 }
 
 zen-button > :where(button, a):active {
@@ -49,12 +51,15 @@
 }
 
 zen-button > :where(button, a):focus-visible,
-zen-alert [data-zen-dismiss]:focus-visible,
-zen-field :where(input, select, textarea):focus-visible {
+zen-alert [data-zen-dismiss]:focus-visible {
   outline: 3px solid var(--zen-color-focus);
   outline-offset: 3px;
 }
 
+zen-field :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);
@@ -108,7 +113,7 @@
 
 zen-card[interactive] > :where(article, section):hover {
   transform: translate(-2px, -2px);
-  box-shadow: 10px 10px 0 rgba(23, 26, 33, 0.18);
+  box-shadow: var(--zen-shadow-lifted);
 }
 
 zen-card :where(h2, h3, p) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/src/styles/shadcn.css	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,1744 @@
+: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/tokens.css	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/src/styles/tokens.css	Tue Aug 04 15:12:09 2026 -0700
@@ -1,6 +1,143 @@
 :root {
   color-scheme: light;
 
+  /* Warm primitive ramps: restrained enough for large surfaces, distinct
+     enough for data and status work. */
+  --zen-color-neutral-50: #fffdf7;
+  --zen-color-neutral-100: #f7f3e8;
+  --zen-color-neutral-200: #ece5d5;
+  --zen-color-neutral-300: #ddd2bd;
+  --zen-color-neutral-400: #b9aa90;
+  --zen-color-neutral-500: #8e8069;
+  --zen-color-neutral-600: #6f6351;
+  --zen-color-neutral-700: #564c3e;
+  --zen-color-neutral-800: #3b352d;
+  --zen-color-neutral-900: #27241f;
+  --zen-color-neutral-950: #171613;
+
+  --zen-color-red-50: #fff8f5;
+  --zen-color-red-100: #f9e9e2;
+  --zen-color-red-200: #efd1c5;
+  --zen-color-red-300: #dda995;
+  --zen-color-red-400: #c77c63;
+  --zen-color-red-500: #a9553f;
+  --zen-color-red-600: #8f4132;
+  --zen-color-red-700: #71342a;
+  --zen-color-red-800: #5b2e27;
+  --zen-color-red-900: #4b2924;
+  --zen-color-red-950: #291411;
+
+  --zen-color-orange-50: #fff8ed;
+  --zen-color-orange-100: #fcebd1;
+  --zen-color-orange-200: #f7d4a1;
+  --zen-color-orange-300: #efb670;
+  --zen-color-orange-400: #de8d3f;
+  --zen-color-orange-500: #c76a26;
+  --zen-color-orange-600: #a94f1c;
+  --zen-color-orange-700: #873d1b;
+  --zen-color-orange-800: #6d331c;
+  --zen-color-orange-900: #5b2d1d;
+  --zen-color-orange-950: #32160c;
+
+  --zen-color-amber-50: #fffbea;
+  --zen-color-amber-100: #f6efc6;
+  --zen-color-amber-200: #ebde8b;
+  --zen-color-amber-300: #d9c455;
+  --zen-color-amber-400: #bfa332;
+  --zen-color-amber-500: #9e8124;
+  --zen-color-amber-600: #80651e;
+  --zen-color-amber-700: #664e1d;
+  --zen-color-amber-800: #55411e;
+  --zen-color-amber-900: #49391e;
+  --zen-color-amber-950: #291e0c;
+
+  --zen-color-green-50: #f6f8ed;
+  --zen-color-green-100: #e9edd5;
+  --zen-color-green-200: #d0d9aa;
+  --zen-color-green-300: #afbf79;
+  --zen-color-green-400: #8da053;
+  --zen-color-green-500: #6d8139;
+  --zen-color-green-600: #55672d;
+  --zen-color-green-700: #424f27;
+  --zen-color-green-800: #374124;
+  --zen-color-green-900: #303923;
+  --zen-color-green-950: #181f10;
+
+  --zen-color-teal-50: #eff9f5;
+  --zen-color-teal-100: #dcefe8;
+  --zen-color-teal-200: #b9ded1;
+  --zen-color-teal-300: #8cc6b4;
+  --zen-color-teal-400: #5fa793;
+  --zen-color-teal-500: #438878;
+  --zen-color-teal-600: #356d61;
+  --zen-color-teal-700: #2d574f;
+  --zen-color-teal-800: #28463f;
+  --zen-color-teal-900: #243b36;
+  --zen-color-teal-950: #10221f;
+
+  --zen-color-blue-50: #f3f6fa;
+  --zen-color-blue-100: #e4eaf2;
+  --zen-color-blue-200: #cbd7e6;
+  --zen-color-blue-300: #a6bad2;
+  --zen-color-blue-400: #7b99b8;
+  --zen-color-blue-500: #5c7d9d;
+  --zen-color-blue-600: #48647f;
+  --zen-color-blue-700: #3c5167;
+  --zen-color-blue-800: #354655;
+  --zen-color-blue-900: #303c49;
+  --zen-color-blue-950: #1c252e;
+
+  --zen-color-violet-50: #f8f5f8;
+  --zen-color-violet-100: #eee7ee;
+  --zen-color-violet-200: #dfd1df;
+  --zen-color-violet-300: #c9b1c8;
+  --zen-color-violet-400: #ad8dad;
+  --zen-color-violet-500: #916f91;
+  --zen-color-violet-600: #755774;
+  --zen-color-violet-700: #5e465d;
+  --zen-color-violet-800: #4e3b4d;
+  --zen-color-violet-900: #423541;
+  --zen-color-violet-950: #281d27;
+
+  --zen-color-rose-50: #fff6f6;
+  --zen-color-rose-100: #f8e7e7;
+  --zen-color-rose-200: #efcfd0;
+  --zen-color-rose-300: #dfa9ad;
+  --zen-color-rose-400: #ca7d84;
+  --zen-color-rose-500: #ae5b65;
+  --zen-color-rose-600: #924550;
+  --zen-color-rose-700: #763943;
+  --zen-color-rose-800: #63333b;
+  --zen-color-rose-900: #552f36;
+  --zen-color-rose-950: #30171c;
+
+  --zen-color-brown-50: #faf7f2;
+  --zen-color-brown-100: #efe8dd;
+  --zen-color-brown-200: #ddcebb;
+  --zen-color-brown-300: #c5ac91;
+  --zen-color-brown-400: #a8896c;
+  --zen-color-brown-500: #8d6d52;
+  --zen-color-brown-600: #725641;
+  --zen-color-brown-700: #5b4436;
+  --zen-color-brown-800: #4d3a31;
+  --zen-color-brown-900: #42332c;
+  --zen-color-brown-950: #251b17;
+
+  /* Material names are stable aliases for the palette's visual character. */
+  --zen-color-paper: var(--zen-color-neutral-50);
+  --zen-color-washi: var(--zen-color-neutral-100);
+  --zen-color-linen: var(--zen-color-neutral-200);
+  --zen-color-sumi: var(--zen-color-neutral-950);
+  --zen-color-brick: var(--zen-color-red-600);
+  --zen-color-persimmon: var(--zen-color-orange-500);
+  --zen-color-ochre: var(--zen-color-amber-500);
+  --zen-color-moss: var(--zen-color-green-600);
+  --zen-color-patina: var(--zen-color-teal-600);
+  --zen-color-indigo: var(--zen-color-blue-700);
+  --zen-color-plum: var(--zen-color-violet-700);
+  --zen-color-clay: var(--zen-color-rose-500);
+  --zen-color-wood: var(--zen-color-brown-600);
+
   --zen-color-canvas: #f7f3e8;
   --zen-color-surface: #fffdf6;
   --zen-color-surface-raised: #ffffff;
@@ -9,6 +146,7 @@
   --zen-color-border: #272b35;
   --zen-color-accent: #ffb000;
   --zen-color-accent-hover: #ffca4a;
+  --zen-color-on-accent: #171a21;
   --zen-color-info: #2764d7;
   --zen-color-on-info: #ffffff;
   --zen-color-success: #18794e;
@@ -18,6 +156,34 @@
   --zen-color-danger: #c62f3e;
   --zen-color-on-danger: #ffffff;
   --zen-color-focus: #7c3aed;
+  --zen-color-surface-muted: var(--zen-color-neutral-100);
+  --zen-color-surface-sunken: var(--zen-color-neutral-200);
+  --zen-color-surface-overlay: rgba(23, 22, 19, 0.56);
+  --zen-color-text-subtle: var(--zen-color-neutral-600);
+  --zen-color-text-inverse: var(--zen-color-neutral-50);
+  --zen-color-border-muted: var(--zen-color-neutral-300);
+  --zen-color-border-strong: var(--zen-color-neutral-800);
+  --zen-color-accent-muted: var(--zen-color-amber-100);
+  --zen-color-info-muted: var(--zen-color-blue-100);
+  --zen-color-success-muted: var(--zen-color-green-100);
+  --zen-color-warning-muted: var(--zen-color-orange-100);
+  --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-code-surface: #111318;
+  --zen-color-code-text: #f4f4f5;
+  --zen-color-gridline: rgba(127, 127, 127, 0.08);
+
+  --zen-color-data-1: var(--zen-color-indigo);
+  --zen-color-data-2: var(--zen-color-persimmon);
+  --zen-color-data-3: var(--zen-color-moss);
+  --zen-color-data-4: var(--zen-color-plum);
+  --zen-color-data-5: var(--zen-color-ochre);
+  --zen-color-data-6: var(--zen-color-patina);
+  --zen-color-data-7: var(--zen-color-brick);
+  --zen-color-data-8: var(--zen-color-wood);
+  --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;
@@ -42,6 +208,8 @@
   --zen-border-width: 2px;
   --zen-shadow-sm: 3px 3px 0 rgba(23, 26, 33, 0.16);
   --zen-shadow-md: 7px 7px 0 rgba(23, 26, 33, 0.16);
+  --zen-shadow-hover: 5px 5px 0 rgba(23, 26, 33, 0.18);
+  --zen-shadow-lifted: 10px 10px 0 rgba(23, 26, 33, 0.18);
   --zen-motion-fast: 120ms;
   --zen-content-width: 76rem;
 }
@@ -56,6 +224,7 @@
   --zen-color-border: #f5f1e8;
   --zen-color-accent: #ffc247;
   --zen-color-accent-hover: #ffd77d;
+  --zen-color-on-accent: #171a21;
   --zen-color-info: #8ab4ff;
   --zen-color-on-info: #171a21;
   --zen-color-success: #65d6a3;
@@ -65,8 +234,37 @@
   --zen-color-danger: #ff8792;
   --zen-color-on-danger: #171a21;
   --zen-color-focus: #c4a5ff;
+  --zen-color-surface-muted: var(--zen-color-neutral-800);
+  --zen-color-surface-sunken: var(--zen-color-neutral-900);
+  --zen-color-surface-overlay: rgba(0, 0, 0, 0.68);
+  --zen-color-text-subtle: var(--zen-color-neutral-400);
+  --zen-color-text-inverse: var(--zen-color-neutral-950);
+  --zen-color-border-muted: var(--zen-color-neutral-700);
+  --zen-color-border-strong: var(--zen-color-neutral-200);
+  --zen-color-accent-muted: var(--zen-color-amber-800);
+  --zen-color-info-muted: var(--zen-color-blue-800);
+  --zen-color-success-muted: var(--zen-color-green-800);
+  --zen-color-warning-muted: var(--zen-color-orange-800);
+  --zen-color-danger-muted: var(--zen-color-red-800);
+  --zen-color-disabled: var(--zen-color-neutral-700);
+  --zen-color-selection: var(--zen-color-amber-800);
+  --zen-color-code-surface: #0b0d12;
+  --zen-color-code-text: #f4f4f5;
+  --zen-color-gridline: rgba(255, 255, 255, 0.06);
+  --zen-color-data-1: var(--zen-color-blue-300);
+  --zen-color-data-2: var(--zen-color-orange-300);
+  --zen-color-data-3: var(--zen-color-green-300);
+  --zen-color-data-4: var(--zen-color-violet-300);
+  --zen-color-data-5: var(--zen-color-amber-300);
+  --zen-color-data-6: var(--zen-color-teal-300);
+  --zen-color-data-7: var(--zen-color-red-300);
+  --zen-color-data-8: var(--zen-color-brown-300);
+  --zen-color-data-9: var(--zen-color-rose-300);
+  --zen-color-data-10: var(--zen-color-blue-200);
   --zen-shadow-sm: 3px 3px 0 rgba(0, 0, 0, 0.5);
   --zen-shadow-md: 7px 7px 0 rgba(0, 0, 0, 0.5);
+  --zen-shadow-hover: 5px 5px 0 rgba(0, 0, 0, 0.55);
+  --zen-shadow-lifted: 10px 10px 0 rgba(0, 0, 0, 0.55);
 }
 
 @media (prefers-color-scheme: dark) {
@@ -80,6 +278,7 @@
     --zen-color-border: #f5f1e8;
     --zen-color-accent: #ffc247;
     --zen-color-accent-hover: #ffd77d;
+    --zen-color-on-accent: #171a21;
     --zen-color-info: #8ab4ff;
     --zen-color-on-info: #171a21;
     --zen-color-success: #65d6a3;
@@ -89,5 +288,36 @@
     --zen-color-danger: #ff8792;
     --zen-color-on-danger: #171a21;
     --zen-color-focus: #c4a5ff;
+    --zen-color-surface-muted: var(--zen-color-neutral-800);
+    --zen-color-surface-sunken: var(--zen-color-neutral-900);
+    --zen-color-surface-overlay: rgba(0, 0, 0, 0.68);
+    --zen-color-text-subtle: var(--zen-color-neutral-400);
+    --zen-color-text-inverse: var(--zen-color-neutral-950);
+    --zen-color-border-muted: var(--zen-color-neutral-700);
+    --zen-color-border-strong: var(--zen-color-neutral-200);
+    --zen-color-accent-muted: var(--zen-color-amber-800);
+    --zen-color-info-muted: var(--zen-color-blue-800);
+    --zen-color-success-muted: var(--zen-color-green-800);
+    --zen-color-warning-muted: var(--zen-color-orange-800);
+    --zen-color-danger-muted: var(--zen-color-red-800);
+    --zen-color-disabled: var(--zen-color-neutral-700);
+    --zen-color-selection: var(--zen-color-amber-800);
+    --zen-color-code-surface: #0b0d12;
+    --zen-color-code-text: #f4f4f5;
+    --zen-color-gridline: rgba(255, 255, 255, 0.06);
+    --zen-color-data-1: var(--zen-color-blue-300);
+    --zen-color-data-2: var(--zen-color-orange-300);
+    --zen-color-data-3: var(--zen-color-green-300);
+    --zen-color-data-4: var(--zen-color-violet-300);
+    --zen-color-data-5: var(--zen-color-amber-300);
+    --zen-color-data-6: var(--zen-color-teal-300);
+    --zen-color-data-7: var(--zen-color-red-300);
+    --zen-color-data-8: var(--zen-color-brown-300);
+    --zen-color-data-9: var(--zen-color-rose-300);
+    --zen-color-data-10: var(--zen-color-blue-200);
+    --zen-shadow-sm: 3px 3px 0 rgba(0, 0, 0, 0.5);
+    --zen-shadow-md: 7px 7px 0 rgba(0, 0, 0, 0.5);
+    --zen-shadow-hover: 5px 5px 0 rgba(0, 0, 0, 0.55);
+    --zen-shadow-lifted: 10px 10px 0 rgba(0, 0, 0, 0.55);
   }
 }
--- a/design_system/test/BUILD	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/test/BUILD	Tue Aug 04 15:12:09 2026 -0700
@@ -1,6 +1,13 @@
 load("@aspect_rules_js//js:defs.bzl", "js_test")
 
 js_test(
+  name = "design_system_policy_test",
+  entry_point = "design_system_policy_test.js",
+  data = ["//design_system:policy_sources"],
+  no_copy_to_bin = ["//design_system:policy_sources"],
+)
+
+js_test(
   name = "storybook_test",
   entry_point = "storybook_test.js",
   data = [
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/design_system/test/design_system_policy_test.js	Tue Aug 04 15:12:09 2026 -0700
@@ -0,0 +1,311 @@
+const assert = require('node:assert/strict');
+const fs = require('node:fs');
+const path = require('node:path');
+
+const RUNFILES = process.env.JS_BINARY__RUNFILES;
+const WORKSPACE = process.env.JS_BINARY__WORKSPACE;
+assert.ok(RUNFILES);
+assert.ok(WORKSPACE);
+
+const sourceRoot = path.join(RUNFILES, WORKSPACE, 'design_system/src');
+const files = [];
+
+function walk(directory) {
+  for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
+    const entryPath = path.join(directory, entry.name);
+    if (entry.isDirectory()) walk(entryPath);
+    else if (/\.(?:css|html|js)$/.test(entry.name)) files.push(entryPath);
+  }
+}
+
+walk(sourceRoot);
+
+function validateCallableDocumentation(
+  relative,
+  source,
+  index,
+  name,
+  parameterSource,
+  failures,
+) {
+  const prefix = source.slice(0, index);
+  const comment = prefix.match(/\/\*\*([\s\S]*?)\*\/\s*$/);
+  const body = comment?.[1] || '';
+  const parameters = parameterSource
+    .split(',')
+    .map(parameter => parameter.trim()
+      .replace(/^\.\.\./, '')
+      .split('=')[0].trim())
+    .filter(Boolean);
+  if (!/@return\s+\{[^}]+\}/.test(body)) {
+    failures.push(`${relative} exported callable ${name} lacks @return`);
+  }
+  const documented = [...body.matchAll(
+    /@param\s+\{[^}]+\}\s+([A-Za-z0-9_$]+)/g,
+  )].map(parameter => parameter[1]);
+  for (const parameter of parameters) {
+    if (!documented.includes(parameter)) {
+      failures.push(
+        `${relative} exported callable ${name} lacks @param for ${parameter}`,
+      );
+    }
+  }
+}
+
+const rawColor = new RegExp([
+  '#[0-9a-fA-F]{3,8}\\b',
+  '\\b(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch)\\s*\\(',
+].join('|'), 'gi');
+const forbiddenGlyph = /[×←→↑↓+◆◇✓✔✕✖★☆⚠]/gu;
+const pictographic = /\p{Extended_Pictographic}/gu;
+const failures = [];
+
+for (const file of files) {
+  const relative = path.relative(sourceRoot, file);
+  const source = fs.readFileSync(file, 'utf8');
+
+  if (relative !== 'styles/tokens.css') {
+    for (const match of source.matchAll(rawColor)) {
+      failures.push(
+        `${relative}:${source.slice(0, match.index).split('\n').length} ` +
+        `raw color ${JSON.stringify(match[0])}`,
+      );
+    }
+    if (relative.endsWith('.css')) {
+      const css = source.replace(/\/\*[\s\S]*?\*\//g, '');
+      const allowedWords = new Set([
+        'none',
+        'transparent',
+        'currentcolor',
+        'inherit',
+        'initial',
+        'unset',
+        'revert',
+        'solid',
+        'dashed',
+        'dotted',
+        'double',
+        'groove',
+        'ridge',
+        'inset',
+        'outset',
+        'canvas',
+        'canvastext',
+        'linktext',
+        'visitedtext',
+        'activetext',
+        'buttonface',
+        'buttontext',
+        'field',
+        'fieldtext',
+        'highlight',
+        'highlighttext',
+        'graytext',
+        'mark',
+        'marktext',
+        'selecteditem',
+        'selecteditemtext',
+        'accentcolor',
+        'accentcolortext',
+        'color-mix',
+        'in',
+        'srgb',
+        'linear-gradient',
+        'radial-gradient',
+        'conic-gradient',
+        'to',
+        'top',
+        'right',
+        'bottom',
+        'left',
+        'at',
+        'circle',
+        'ellipse',
+        'px',
+        'rem',
+        'em',
+        'vh',
+        'vw',
+        'vi',
+        'vb',
+        'vmin',
+        'vmax',
+        'deg',
+        'rad',
+        'turn',
+      ]);
+      for (const declaration of css.matchAll(
+        /(^|[;{])\s*([-\w]+)\s*:\s*([^;{}]+)/gm,
+      )) {
+        const property = declaration[2].toLowerCase();
+        const value = declaration[3];
+        const colorProperty = [
+          'accent-color',
+          'background',
+          'background-color',
+          'box-shadow',
+          'caret-color',
+          'color',
+          'fill',
+          'outline',
+          'outline-color',
+          'scrollbar-color',
+          'stroke',
+          'text-shadow',
+        ].includes(property) ||
+          (property.startsWith('border') &&
+           !/(?:collapse|image|radius|spacing|style|width)/.test(property));
+        if (!colorProperty) continue;
+        const withoutTokens = value.replace(
+          /var\(\s*--zen-[\w-]+\s*\)/g,
+          '',
+        );
+        const words = withoutTokens.toLowerCase()
+          .match(/[a-z][a-z-]*/g) || [];
+        if (words.some(word => !allowedWords.has(word)) &&
+            !/^\s*(?:0|none|transparent|currentColor|inherit)\s*$/i.test(
+              value,
+            )) {
+          failures.push(
+            `${relative}:${css.slice(0, declaration.index).split('\n').length} ` +
+            `${property} must use a --zen-* token`,
+          );
+        }
+      }
+    }
+  }
+
+  for (const pattern of [forbiddenGlyph, pictographic]) {
+    for (const match of source.matchAll(pattern)) {
+      failures.push(
+        `${relative}:${source.slice(0, match.index).split('\n').length} ` +
+        `icon glyph ${JSON.stringify(match[0])}; use <zen-icon>`,
+      );
+    }
+  }
+  if (relative !== 'components/icon.js' &&
+      /<svg\b|createElementNS\([^)]*["']svg["']/i.test(source)) {
+    failures.push(`${relative} defines SVG outside components/icon.js`);
+  }
+  if (relative.endsWith('.js')) {
+    if (/\bimport\s*\/[/*]/.test(source)) {
+      failures.push(`${relative} places comments inside import syntax`);
+    }
+    const importPattern =
+      /(?:import\s+(?:[^'"]+\s+from\s+)?|export\s+[^'"]+\s+from\s+)["']([^"']+)["']/g;
+    for (const match of source.matchAll(importPattern)) {
+      if (!match[1].startsWith('.')) {
+        failures.push(
+          `${relative} imports external runtime ${JSON.stringify(match[1])}`,
+        );
+      }
+    }
+    if (/\bimport\s*\(/.test(source)) {
+      failures.push(`${relative} uses forbidden dynamic import()`);
+    }
+  }
+  if (relative.endsWith('.css') &&
+      /@font-face|(?:font|font-family)\s*:[^;]*(?:icon|awesome|material)/i.test(
+        source,
+      )) {
+    failures.push(`${relative} declares an icon font`);
+  }
+  if (relative.endsWith('.css')) {
+    for (const match of source.matchAll(
+      /@import\s+(?:url\(\s*)?["']?([^"')\s;]+)["']?\s*\)?/g,
+    )) {
+      if (!match[1].startsWith('.')) {
+        failures.push(
+          `${relative} imports external stylesheet ${JSON.stringify(match[1])}`,
+        );
+      }
+    }
+  }
+}
+
+for (const file of files.filter(file =>
+  file.endsWith('.js')
+)) {
+  const relative = path.relative(sourceRoot, file);
+  const source = fs.readFileSync(file, 'utf8');
+  const declaration =
+    /^export\s+(?:default\s+)?(?:async\s+)?(class|const|let|var|function)\s+([A-Za-z0-9_]+)/gm;
+  for (const match of source.matchAll(declaration)) {
+    const prefix = source.slice(0, match.index);
+    const comment = prefix.match(/\/\*\*([\s\S]*?)\*\/\s*$/);
+    const line = prefix.split('\n').length;
+    if (!comment) {
+      failures.push(`${relative}:${line} ${match[2]} lacks Google-style JSDoc`);
+      continue;
+    }
+    const body = comment[1];
+    if (match[1] === 'class' && !/@extends\s+\{[^}]+\}/.test(body)) {
+      failures.push(`${relative}:${line} ${match[2]} lacks @extends`);
+    } else if (['const', 'let', 'var'].includes(match[1]) &&
+               !/@(?:const|type)\b/.test(body)) {
+      failures.push(`${relative}:${line} ${match[2]} lacks @const/@type`);
+    } else if (match[1] === 'function' &&
+               (!/@param\s+\{[^}]+\}/.test(body) ||
+                !/@return\s+\{[^}]+\}/.test(body))) {
+      failures.push(`${relative}:${line} ${match[2]} lacks @param/@return`);
+    } else if (match[1] === 'function') {
+      const signature = source.slice(match.index).match(
+        /^export\s+(?:default\s+)?(?:async\s+)?function\s+[A-Za-z0-9_]+\s*\(([^)]*)\)/,
+      );
+      const parameters = (signature?.[1] || '')
+        .split(',')
+        .map(parameter => parameter.trim()
+          .replace(/^\.\.\./, '')
+          .split('=')[0].trim())
+        .filter(Boolean);
+      const documented = [...body.matchAll(
+        /@param\s+\{[^}]+\}\s+([A-Za-z0-9_$]+)/g,
+      )].map(parameter => parameter[1]);
+      for (const parameter of parameters) {
+        if (!documented.includes(parameter)) {
+          failures.push(
+            `${relative}:${line} ${match[2]} lacks @param for ${parameter}`,
+          );
+        }
+      }
+    }
+  }
+  for (const match of source.matchAll(
+    /^export\s+const\s+([A-Za-z0-9_]+)\s*=\s*(?:async\s*)?(?:\(([^)]*)\)|([A-Za-z0-9_$]+))\s*=>/gm,
+  )) {
+    validateCallableDocumentation(
+      relative,
+      source,
+      match.index,
+      match[1],
+      match[2] || match[3] || '',
+      failures,
+    );
+  }
+  for (const match of source.matchAll(
+    /^export\s+const\s+([A-Za-z0-9_]+)\s*=\s*(?:async\s*)?function(?:\s+[A-Za-z0-9_]+)?\s*\(([^)]*)\)/gm,
+  )) {
+    validateCallableDocumentation(
+      relative,
+      source,
+      match.index,
+      match[1],
+      match[2],
+      failures,
+    );
+  }
+  for (const match of source.matchAll(
+    /export\s*\{[\s\S]*?\}\s*(?!from\b)(?:;|$)/g,
+  )) {
+    failures.push(
+      `${relative}:${source.slice(0, match.index).split('\n').length} ` +
+      "uses an undocumented local export list",
+    );
+  }
+}
+
+assert.deepEqual(
+  failures,
+  [],
+  `Design-system policy violations:\n${failures.join('\n')}`,
+);
--- a/design_system/test/storybook_test.js	Tue Aug 04 12:21:19 2026 -0700
+++ b/design_system/test/storybook_test.js	Tue Aug 04 15:12:09 2026 -0700
@@ -120,6 +120,7 @@
     for (const route of [
       '/',
       '/tokens',
+      '/icons',
       '/components',
       '/components/button',
       '/components/card',
@@ -138,7 +139,10 @@
     for (const asset of [
       '/styles/tokens.css',
       '/styles/components.css',
+      '/styles/shadcn.css',
       '/components/index.js',
+      '/components/icon.js',
+      '/catalog.js',
       '/storybook.js',
     ]) {
       const response = await fetch(`${baseUrl}${asset}`);
@@ -154,9 +158,23 @@
     const context = await browser.newContext({ colorScheme: 'light' });
     const page = await context.newPage();
     const errors = [];
-    page.on('pageerror', error => errors.push(error.message));
+    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') errors.push(message.text());
+      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) {
@@ -167,10 +185,121 @@
     await page.goto(`${baseUrl}/components/button`, {
       waitUntil: 'networkidle',
     });
-    await page.waitForFunction(() =>
-      customElements.get('zen-button') &&
-      customElements.get('zen-story')
+    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,
@@ -265,6 +394,114 @@
     });
     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}`),
+      );
+      delete root.dataset.zenTheme;
+      return {
+        darkData,
+        darkMuted,
+        data,
+        lightMuted,
+        materials,
+        rampsComplete,
+      };
+    });
+    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.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',
     });
@@ -285,6 +522,13 @@
     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');
@@ -351,6 +595,519 @@
     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',
     });
@@ -846,6 +1603,74 @@
     );
     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);