{
  "$schema": "https://aihu.dev/registry/schema-v1.json",
  "schemaVersion": 1,
  "name": "aihu",
  "stability": "experimental",
  "contributions": "closed",
  "homepage": "https://aihu.dev/registry",
  "repository": "https://github.com/aihu-project/aihu",
  "items": [
    {
      "name": "ascii-hero",
      "type": "ui",
      "files": [
        {
          "path": "registry/ascii-hero/ascii-hero.aihu",
          "type": "component",
          "source": "<!--\n  aihu-ascii-hero — presentational styled recipe (performativeUI port,\n  Slice 10 — docs/plans/2026-08-01-performative-ui-port.md §Tier-C batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md. The upstream\n  demo file was NOT read for this port: the effect below is written from the\n  behavioral description in the slice brief plus the composable's own API.\n\n  A hero-section text-field effect: a monospaced grid of glyphs shimmering\n  behind (or in front of) hero copy, built directly on `@aihu/use/motion`'s\n  `useCharacterField` (Track B Slice 8), which is itself built on\n  `useCanvasSurface`. Unlike its Slice-10 sibling `node-graph-background`\n  — which had to drop a level because `useParticleField` exposes no draw\n  seam — this component needs nothing the composable does not already do, so\n  it stays at the higher level: the grid, the reflow-on-resize, the three\n  animation modes and the reduced-motion at-rest composition are all\n  `useCharacterField`'s, and this file only maps attributes onto its options.\n\n  `useCanvasSurface` OWNS canvas creation (see its header comment: measuring\n  and styling the same node would feed a `ResizeObserver` a resize loop, so\n  it measures the HOST and styles a canvas it creates itself). This\n  component's `@template` is therefore a plain container — `ref={hostEl}`\n  feeds that host to `useCharacterField`, which mounts its own `<canvas>`\n  inside it; nothing here reaches for a `<canvas>` element directly.\n\n  ── Props ────────────────────────────────────────────────────────────────\n\n  chars:    the glyph set, as a plain string split per code unit. Default\n            \"01\" — a binary rain reads as \"hero for a dev tool\", which is\n            what this component is for; the composable's own default\n            (\" .:-=+*#%@\", a luminance ramp) is the right default for an\n            ASCII-art renderer and the wrong one for a hero backdrop.\n  density:  fraction of grid cells that carry a glyph at all, [0, 1],\n            string-encoded number. Default \"0.6\". Deliberately below 1: the\n            composable notes that \"below 1 the field is sparse, which reads\n            as texture rather than a filled block\", and a hero background\n            that renders as a solid block of characters fights the headline\n            sitting on top of it.\n  mode:     drift (default) | pulse | reveal — `useCharacterField`'s closed\n            mode enum, surfaced rather than hard-coded because all three are\n            legitimate hero treatments. `drift` is the default because it is\n            the only continuously AMBIENT one: `reveal` is a one-shot\n            typewriter wipe that finishes in ~1.5s and then sits static\n            forever (right for an entrance, wrong for a persistent\n            backdrop), and `pulse` breathes the whole field's opacity in a\n            way that pulls the eye off the copy. An unrecognized value falls\n            back to `drift` rather than throwing — attributes are untrusted\n            strings and a decorative layer must not be able to break a page.\n  color:    fill color for the glyphs. Default \"#ffffff\". This is a LITERAL\n            CSS color string, not a `--color-*` token reference — identical\n            constraint to `floating-sparkles` (Slice 9) and\n            `node-graph-background`: a canvas 2D context's `fillStyle` is not\n            part of the CSS cascade and cannot resolve a custom property, so\n            it needs an already-resolved value. Exposed (beyond the three\n            props the slice brief named) for parity with the rest of the\n            Tier-C batch — a decorative canvas layer with no color control is\n            unusable on half the surfaces it would be dropped onto.\n\n  Not exposed: `cellSize`, `fontSize`, `fontFamily`, `speed`, `opacity`,\n  `revealDuration`. Every one of them is an internal look-and-feel constant\n  at this altitude, and the composable's defaults (14px pitch, monospace,\n  0.85 alpha) are already the hero-appropriate values. Widening the surface\n  ahead of a real need is the over-engineering this port keeps declining.\n\n  ── Layout ───────────────────────────────────────────────────────────────\n\n  A standalone, full-bleed, absolutely-positioned decorative layer\n  (`position: absolute; inset: 0`), no slot — the same \"decorative background\n  layer\" contract `floating-sparkles`, `aurora` and `node-graph-background`\n  carry, for consistency across the Tier-C batch. The consumer places it as\n  the first child of a `position: relative` hero section and stacks the real\n  headline above it with `z-index` (see `useCanvasSurface`'s header: \"the\n  host must be positioned\" for its owned canvas to land at the host's\n  top-left, which `position: absolute` already satisfies).\n\n  ── Reduced motion / off-screen ──────────────────────────────────────────\n\n  Neither is reimplemented here, and — importantly — neither is FOUGHT here:\n  no local `prefers-reduced-motion` branch is layered on top, because\n  `useCharacterField` already owns a per-mode at-rest composition that a\n  naive component-level override would be strictly worse than. Under\n  `prefers-reduced-motion: reduce`, `useCanvasSurface` paints exactly one\n  frame with `reducedMotion: true` and never arms the rAF loop; the field's\n  `onFrame` then calls its `atRest()` instead of `step()`, which resets every\n  cell to its seeded glyph at full base opacity. That means `drift` freezes\n  on its seeded glyphs, `pulse` holds full opacity, and `reveal` shows the\n  wipe's END state — every cell already revealed, never a frozen half-wipe.\n  A populated field in all three modes, never a blank box.\n  `isVisible`-gated pausing while scrolled off-screen is inherited for free.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let chars = prop({ default: '01' })\n  let density = prop({ default: '0.6' })\n  let mode = prop({ default: 'drift' })\n  let color = prop({ default: '#ffffff' })\n\n  let hostEl = state(null)\n\n  // Read every prop into a differently-named local before use — an\n  // options-object key textually identical to a prop name (`mode: mode`,\n  // `density: density`, `color: color`) trips the compiler's prop-auto-unwrap\n  // rewriter (see token-stream.aihu's header for the exact failure mode).\n  const glyphs = chars.length > 0 ? chars : '01'\n  const cellDensity = Math.min(1, Math.max(0, Number(density) || 0))\n  const fieldMode = mode === 'pulse' || mode === 'reveal' ? mode : 'drift'\n  const inkColor = color\n\n  useCharacterField(() => hostEl, {\n    characters: glyphs,\n    density: cellDensity,\n    mode: fieldMode,\n    color: inkColor,\n  })\n}\n\n@template {\n  <div\n    ref={hostEl}\n    data-slot=\"ascii-hero\"\n    aria-hidden=\"true\"\n    class={cn('aihu-ascii-hero')}></div>\n}\n\n@style {\n  .aihu-ascii-hero {\n    display: block;\n    position: absolute;\n    inset: 0;\n    overflow: hidden;\n    pointer-events: none;\n  }\n}\n"
        }
      ],
      "description": "Decorative hero-section character field — a monospaced grid of glyphs drifting, pulsing, or wiping in on a managed canvas, built on useCharacterField.",
      "variants": {
        "mode": ["drift", "pulse", "reveal"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "aurora",
      "type": "ui",
      "files": [
        {
          "path": "registry/aurora/aurora.aihu",
          "type": "component",
          "source": "<!--\n  aihu-aurora — presentational styled recipe (performativeUI port,\n  Slice 9 — docs/plans/2026-08-01-performative-ui-port.md §Tier-C batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A decorative animated aurora-borealis-style background wash — PURE CSS, no\n  canvas, no `@aihu/use/motion` composable. The roadmap's explicit\n  instruction for this slice was \"try pure CSS gradients + `@keyframes` for\n  `aurora` first; only fall back to canvas if that fails\" (to prove Slice 8's\n  canvas infra was worth building for the genuinely hard remaining Tier-C\n  pairs — `node-graph-background`/`ascii-hero`, `goldeneye` — by spending\n  nothing on the cheap one). The pure-CSS attempt succeeded convincingly on\n  the first pass and is what ships:\n\n  - One real DOM node. The base element itself is one drifting layer\n    (`background-image: var(--gradient-brand)` animated via\n    `background-position`); `::before`/`::after` supply two more soft-edged\n    blurred blobs. Three independently-animated layers from a single\n    element — no extra `<span>`s needed, because CSS pseudo-elements are\n    \"free\" DOM nodes.\n  - `filter: blur(...)` on every layer is what turns flat gradients into the\n    soft, out-of-focus aurora look; `mix-blend-mode: screen` on the two\n    pseudo-element blobs is what makes them glow into and through the base\n    layer and each other instead of sitting as flat opaque discs.\n    `isolation: isolate` on the root scopes that blending to this\n    component's own paint so it never blends with page content behind it.\n  - Color: `--gradient-brand` (already a 3-stop warm gradient) for the base\n    layer, plus exactly ONE additional token for a cool counterpoint —\n    `--color-info` (blue) — via `color-mix(in oklab, var(--color-info) 65%,\n    transparent)`, the same `color-mix` translucency technique `glass-card`\n    (Slice 5, E-P3) already established. `--color-accent` (already inside\n    the gradient) is reused at low opacity for the second blob rather than\n    reaching for a second semantic token. No new tokens — everything here\n    already exists in the pack.\n  - Reduced motion: the mandatory `@media (prefers-reduced-motion: reduce)`\n    guard sets `animation: none` on the root and both pseudo-elements. This\n    trivially satisfies the port's \"paint once, never loop\" convention\n    (Slice 8's canvas composables enforce the same contract in JS) — with no\n    keyframes running, every layer falls back to its own PLAIN declared\n    state, which is why `transform`/`opacity` on `.aihu-aurora::before`/\n    `::after` are declared as normal (non-keyframe) properties on those\n    selectors too, set to each layer's own mid-cycle (50%) keyframe values —\n    a genuinely calm rest frame, not the unstyled CSS default. (An earlier\n    revision left `transform`/`opacity` declared ONLY inside the two\n    `@keyframes` blocks; under `animation: none` that resolves to\n    `transform: none` + `opacity: 1` — both blobs full-opacity and\n    dead-center — which, combined with `mix-blend-mode: screen`, is the\n    BRIGHTEST, most centrally-stacked render the component can produce,\n    the opposite of \"calm.\" Fixed by giving both pseudo-elements their own\n    static mid-cycle declaration below.) The base layer's\n    `background-position: 0% 50%` was never keyframe-only — it was already a\n    real declared value on `.aihu-aurora` itself — so it needed no change.\n    There is no JS branch to trace here; the whole guard is 5 lines of CSS.\n\n  Fully decorative, slot-free, self-contained: `position: absolute; inset: 0`\n  meant to sit BEHIND other content. The consumer places it as the first\n  child of a `position: relative` ancestor and stacks real content above it\n  with `z-index` — the same layout contract `floating-sparkles` (this\n  slice's sibling) documents, for consistency across the Tier-C batch.\n\n  No props — every knob here (gradient, second color, blur radii, timings)\n  is an internal implementation detail, not a per-instance variant.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n}\n\n@template {\n  <div data-slot=\"aurora\" aria-hidden=\"true\" class={cn('aihu-aurora')}></div>\n}\n\n@style {\n  .aihu-aurora {\n    display: block;\n    position: absolute;\n    inset: 0;\n    overflow: hidden;\n    isolation: isolate;\n    pointer-events: none;\n    background-image: var(--gradient-brand);\n    background-size: 200% 200%;\n    background-position: 0% 50%;\n    filter: blur(60px) saturate(1.4);\n    opacity: 0.6;\n    animation: aihu-aurora-drift-base 20s var(--ease-brand) infinite alternate;\n  }\n  .aihu-aurora::before,\n  .aihu-aurora::after {\n    content: '';\n    position: absolute;\n    inset: -30%;\n    border-radius: 50%;\n    mix-blend-mode: screen;\n  }\n  .aihu-aurora::before {\n    background: radial-gradient(\n      closest-side,\n      color-mix(in oklab, var(--color-info) 65%, transparent),\n      transparent 70%\n    );\n    filter: blur(50px);\n    /* Static rest frame — the `50%` keyframe of aihu-aurora-drift-cool below.\n       Reduced motion sets `animation: none` and lets THIS show; without it,\n       transform/opacity would fall back to the CSS default (`none` / `1`),\n       not a calm mid-cycle pose. See this file's header comment. */\n    transform: translate(10%, 15%) scale(1.15);\n    opacity: 0.9;\n    animation: aihu-aurora-drift-cool 24s var(--ease-brand) infinite alternate;\n  }\n  .aihu-aurora::after {\n    background: radial-gradient(\n      closest-side,\n      color-mix(in oklab, var(--color-accent) 55%, transparent),\n      transparent 70%\n    );\n    filter: blur(70px);\n    /* Static rest frame — the `50%` keyframe of aihu-aurora-drift-warm below.\n       Same reduced-motion role as ::before's, above. */\n    transform: translate(-10%, -15%) scale(1.1);\n    opacity: 0.85;\n    animation: aihu-aurora-drift-warm 28s var(--ease-brand) infinite alternate-reverse;\n  }\n  @keyframes aihu-aurora-drift-base {\n    0% {\n      background-position: 0% 30%;\n    }\n    50% {\n      background-position: 100% 70%;\n    }\n    100% {\n      background-position: 30% 100%;\n    }\n  }\n  @keyframes aihu-aurora-drift-cool {\n    0% {\n      transform: translate(-15%, -10%) scale(1);\n      opacity: 0.7;\n    }\n    50% {\n      transform: translate(10%, 15%) scale(1.15);\n      opacity: 0.9;\n    }\n    100% {\n      transform: translate(-5%, 20%) scale(0.95);\n      opacity: 0.6;\n    }\n  }\n  @keyframes aihu-aurora-drift-warm {\n    0% {\n      transform: translate(15%, 10%) scale(1);\n      opacity: 0.6;\n    }\n    50% {\n      transform: translate(-10%, -15%) scale(1.1);\n      opacity: 0.85;\n    }\n    100% {\n      transform: translate(5%, -20%) scale(0.9);\n      opacity: 0.5;\n    }\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .aihu-aurora,\n    .aihu-aurora::before,\n    .aihu-aurora::after {\n      animation: none;\n    }\n  }\n}\n"
        }
      ],
      "description": "Decorative animated aurora-borealis-style background wash — pure CSS layered gradients, blur, and mix-blend-mode, no canvas.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "badge",
      "type": "ui",
      "files": [
        {
          "path": "registry/badge/badge.aihu",
          "type": "component",
          "source": "<!--\n  aihu-badge — presentational styled recipe (Plan 5 Task 5, master spec §9.7).\n\n  Standalone styled custom element — NO primitive import. Inline-flex pill with\n  a variant matrix. `aihu add` rewrites the `aihu-` prefix at copy time.\n\n  variant: default | secondary | destructive | outline\n  (Variant matrix is the registry catalog contract — see meta.json — reflected\n  as `data-variant` and matched in @style below.)\n\n  CSS attachment (R2): the compiled `@style` block below IS the shared\n  Constructable StyleSheet — see `card.aihu`'s header. A recipe writes no\n  registration and no `adoptedStyleSheets` code of its own.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  let variant = prop({ default: 'default' })\n}\n\n@template {\n  <span data-slot=\"badge\" data-variant={variant} class={cn('aihu-badge')}>\n    <slot />\n  </span>\n}\n\n@style {\n  .aihu-badge {\n    display: inline-flex;\n    align-items: center;\n    border-radius: 9999px;\n    padding-inline: 0.625rem;\n    padding-block: 0.125rem;\n    font-size: 0.75rem;\n    font-weight: 500;\n    line-height: 1rem;\n  }\n  .aihu-badge[data-variant=\"default\"] {\n    background-color: var(--color-primary);\n    color: var(--color-primary-foreground);\n  }\n  .aihu-badge[data-variant=\"secondary\"] {\n    background-color: var(--color-secondary);\n    color: var(--color-secondary-foreground);\n  }\n  .aihu-badge[data-variant=\"destructive\"] {\n    background-color: var(--color-destructive);\n    color: var(--color-destructive-foreground);\n  }\n  .aihu-badge[data-variant=\"outline\"] {\n    border: 1px solid var(--color-border);\n    color: var(--color-foreground);\n  }\n}\n"
        }
      ],
      "description": "Presentational badge recipe — inline-flex pill with a variant matrix.",
      "variants": {
        "variant": ["default", "secondary", "destructive", "outline"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "before-after",
      "type": "ui",
      "files": [
        {
          "path": "registry/before-after/before-after.aihu",
          "type": "component",
          "source": "<!--\n  aihu-before-after — Phase-2 styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  Drag-to-reveal image comparison, built on the new `AihuSliderRoot` primitive\n  (Track B Slice 5's new minimal single-thumb slider). Named\n  `<slot name=\"before\">` / `<slot name=\"after\">` hold the two images (or any\n  content); a draggable divider bound to the slider's value (0-100 = reveal\n  percentage of the \"after\" layer) drives a `clip-path: inset(...)` on the\n  after-layer wrapper.\n\n  COMPOSE, NOT EXTEND — the deliberate choice here, and why: every other\n  Phase-2 recipe in this registry (dialog-content, switch, checkbox, ...) IS\n  its primitive — `<aihu-switch>` literally extends `AihuSwitchRoot` because a\n  styled switch is nothing more than a styled switch. `before-after` is not a\n  styled slider; it's a two-image comparator that happens to use a slider\n  internally to drive a divider, the same way a native `<input type=range>`\n  might power a bigger widget without becoming that widget's public identity.\n  Extending `AihuSliderRoot` here would make `<aihu-before-after>` itself\n  `role=\"slider\"` with `aria-valuenow` etc, which is the WRONG accessibility\n  tree for what is actually a two-panel image region with an interior slider\n  control. So the primitive is composed as a CHILD element instead: registered\n  via the primitive package's own `defineSlider()` (imported as a side effect,\n  same registration entry point `switch.stories.ts`/`radio-group.stories.ts`\n  call at module scope) and mounted as a real `<aihu-slider-root>` in the\n  template, with its `value-change` event listened to via `ref` + `onMount`\n  (the FEL-441-guaranteed ordering: `ref` lands before `@state`'s `onMount`\n  runs, so the listener attaches on a live element, not `null`).\n\n  value:    initial reveal percentage (0-100 = % of the after layer\n            revealed), string-encoded number. Default \"50\".\n  disabled: off (default) | on — forwarded to the composed slider once at\n            mount (custom-element attrs are strings, read once at setup —\n            same read-once convention this port already uses for e.g.\n            rotator's `items`; this is not meant to be toggled live).\n\n  IMPORTANT — `value`/`disabled` are forwarded to `<aihu-slider-root>`\n  IMPERATIVELY (`el.setAttribute(...)` inside `onMount`), never as a REACTIVE\n  template attribute binding (`value={value}` in `@template`). Reason: the\n  compiled template's reactive-attrs path does `key in el` to decide\n  property-set vs `setAttribute` (arbor's `_applyAttrs`), and `AihuSliderRoot`\n  exposes a getter-only `value` accessor (`get value(): Read<number>`) — a\n  reactive `value={value}` binding would resolve `asProp = true` and then\n  throw (\"Cannot set property value ... which has only a getter\") the moment\n  the effect tried `el.value = ...`. Every existing primitive/recipe pairing\n  in this registry sidesteps this because they either EXTEND the primitive\n  (`base:`, so there's no separate child element to bind attrs onto) or are\n  only ever instantiated from raw HTML strings in `.stories.ts` (which parse\n  attributes, never touch this reactive-attrs code path) — `before-after` is\n  the first recipe to mount a primitive as a plain templated CHILD, which is\n  what surfaces this. Imperative `setAttribute` avoids the collision\n  entirely (same DOM entry point `AihuSliderRoot.attributeChangedCallback`\n  reads from either way).\n\n  `shadow: 'light'` — see the parent execution plan's theming decision; also\n  required here so the composed `<aihu-slider-root>` sits in light DOM where\n  `defineSlider()`'s customElements.define takes effect on it directly (a true\n  shadow-root boundary would not change custom-element upgrade semantics, but\n  light DOM keeps this component's whole composition on one consistent theming\n  model with the rest of the port).\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n  import { defineSlider } from '@aihu/primitives/slider'\n\n  shadow: 'light'\n\n  defineSlider()\n\n  let value = prop({ default: '50' })\n  let disabled = prop({ default: 'off' })\n\n  let sliderEl = state(null)\n  let reveal = state(Number(value))\n\n  onMount(() => {\n    if (!sliderEl) return\n    const el = sliderEl\n    // Imperative, one-time forward (see the header comment above for the\n    // getter-collision note on why this is NOT a reactive template binding).\n    el.setAttribute('value', value)\n    if (disabled === 'on') el.setAttribute('disabled', '')\n    const sync = () => {\n      reveal = Number(el.getAttribute('value') ?? '50')\n    }\n    // Pick up any clamp/round the primitive applied to the initial value.\n    sync()\n    el.addEventListener('value-change', sync)\n  })\n}\n\n@template {\n  <div data-slot=\"before-after\" class={cn('aihu-before-after')}>\n    <div class=\"aihu-before-after-layer aihu-before-after-before\">\n      <slot name=\"before\" />\n    </div>\n    <div\n      class=\"aihu-before-after-layer aihu-before-after-after\"\n      style={`clip-path: inset(0 ${100 - reveal}% 0 0);`}>\n      <slot name=\"after\" />\n    </div>\n    <aihu-slider-root\n      ref={sliderEl}\n      class=\"aihu-before-after-handle\"\n      aria-label=\"Comparison position\"\n      style={`left: ${reveal}%;`}>\n      <span class=\"aihu-before-after-handle-grip\" aria-hidden=\"true\"></span>\n    </aihu-slider-root>\n  </div>\n}\n\n@style {\n  .aihu-before-after {\n    position: relative;\n    display: block;\n    overflow: hidden;\n    border-radius: var(--radius-lg);\n    isolation: isolate;\n    user-select: none;\n  }\n  .aihu-before-after-layer {\n    position: absolute;\n    inset: 0;\n  }\n  /* shadow: 'light' has no real ShadowRoot, so slotted content is projected\n     as plain light-DOM children — style it with an ordinary descendant\n     selector, not `::slotted()` (a native-shadow-only pseudo-class that\n     would silently match nothing here). */\n  .aihu-before-after-layer img {\n    display: block;\n    width: 100%;\n    height: 100%;\n    object-fit: cover;\n  }\n  .aihu-before-after-before {\n    z-index: 1;\n  }\n  .aihu-before-after-after {\n    z-index: 2;\n  }\n  .aihu-before-after-handle {\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    z-index: 3;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 2.5rem;\n    margin-left: -1.25rem;\n    background: transparent;\n    cursor: ew-resize;\n    touch-action: none;\n  }\n  .aihu-before-after-handle::before {\n    content: '';\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 50%;\n    width: 2px;\n    background-color: var(--color-background);\n    box-shadow: 0 0 0 1px color-mix(in oklab, var(--color-foreground) 20%, transparent);\n    transform: translateX(-50%);\n  }\n  .aihu-before-after-handle-grip {\n    position: relative;\n    z-index: 1;\n    display: inline-flex;\n    width: 1.75rem;\n    height: 1.75rem;\n    border-radius: 9999px;\n    background-color: var(--color-background);\n    box-shadow: 0 1px 3px color-mix(in oklab, var(--color-foreground) 30%, transparent);\n  }\n  .aihu-before-after-handle:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  .aihu-before-after-handle[data-disabled] {\n    cursor: not-allowed;\n    opacity: 0.6;\n  }\n}\n"
        }
      ],
      "description": "Drag-to-reveal image comparison, built on the AihuSliderRoot primitive — keyboard-operable divider between named before/after slots.",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "keyboard": true,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "big-back",
      "type": "ui",
      "files": [
        {
          "path": "registry/big-back/big-back.aihu",
          "type": "component",
          "source": "<!--\n  aihu-big-back — presentational styled recipe (performativeUI port,\n  Slice 2 — docs/plans/2026-08-01-performative-ui-port.md).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  Oversized, low-opacity watermark-style text — typically the wordmark\n  bleeding off the edge of a footer. Purely decorative; hidden from the\n  accessibility tree. `aihu add` rewrites the `aihu-` prefix at copy time.\n\n  weight: bold (default) | black\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let weight = prop({ default: 'bold' })\n}\n\n@template {\n  <span\n    data-slot=\"big-back\"\n    data-weight={weight}\n    aria-hidden=\"true\"\n    class={cn('aihu-big-back')}>\n    <slot />\n  </span>\n}\n\n@style {\n  .aihu-big-back {\n    display: block;\n    width: 100%;\n    overflow: hidden;\n    white-space: nowrap;\n    line-height: 0.85;\n    letter-spacing: -0.03em;\n    font-size: clamp(4rem, 18vw, 14rem);\n    color: var(--color-foreground);\n    opacity: 0.06;\n    user-select: none;\n    pointer-events: none;\n  }\n  .aihu-big-back[data-weight=\"bold\"] {\n    font-weight: 700;\n  }\n  .aihu-big-back[data-weight=\"black\"] {\n    font-weight: 900;\n  }\n}\n"
        }
      ],
      "description": "Presentational oversized watermark-style text, typically a footer wordmark. Decorative, hidden from the accessibility tree.",
      "variants": {
        "weight": ["bold", "black"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "button",
      "type": "ui",
      "files": [
        {
          "path": "registry/button/button.aihu",
          "type": "component",
          "source": "<!--\n  aihu-button — styled recipe (Plan 5 Task 5, master spec §9.2 / §9.4).\n\n  Wraps a NATIVE <button> and forwards props. NO `$extends` — same rule as\n  `input.aihu` / `textarea.aihu` / `label.aihu`: the native control already\n  carries the role, the tab stop, Enter/Space activation and the disabled\n  semantics, so extending `AihuButton` would FIGHT the template-rendered native\n  element rather than add to it. Measured, not assumed: with `base: AihuButton`\n  the HOST gains `role=\"button\"` + `tabindex=\"0\"` while still containing the\n  focusable native `<button>` in its shadow root — nested interactive controls,\n  two tab stops, and Enter activating twice (the base's keydown handler calls\n  `this.click()` on the host, the inner button activates natively).\n\n  `AihuButton` remains the right base for a host-as-button element that renders\n  no inner control — use `@aihu/primitives/button` directly for that shape. For\n  a worked class-extension recipe see `checkbox.aihu` / `switch.aihu`, which\n  DO use `$extends:` because their hosts carry the behavior themselves.\n\n  `aihu add` rewrites the `aihu-` prefix to the consumer's chosen prefix at copy\n  time; after copy the consumer owns this source.\n\n  variant: default | destructive | outline | ghost | link\n  size:    sm | md | lg | icon\n  slots:   button\n  (The variant/size matrix is the registry catalog contract — see meta.json.\n  These are reflected as `data-variant` / `data-size` and matched in @style below.)\n\n  CSS attachment (R2): the compiled `@style` block below IS the shared\n  Constructable StyleSheet — see `card.aihu`'s header. A recipe writes no\n  registration and no `adoptedStyleSheets` code of its own.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  let variant = prop({ default: 'default' })\n  let size = prop({ default: 'md' })\n  let disabled = prop({ default: false })\n}\n\n@template {\n  <button\n    type=\"button\"\n    data-slot=\"button\"\n    data-variant={variant}\n    data-size={size}\n    disabled={disabled}\n    class={cn('aihu-button')}>\n    <slot />\n  </button>\n}\n\n@style {\n  /* Base — semantic utilities (no raw colors). */\n  .aihu-button {\n    @apply inline-flex items-center justify-center rounded-md font-medium select-none\n           transition-colors disabled:opacity-50 disabled:pointer-events-none;\n  }\n\n  /* Variant matrix — semantic tokens via var(--color-*); pack-invariant (R4). */\n  .aihu-button[data-variant=\"default\"] {\n    background-color: var(--color-primary);\n    color: var(--color-primary-foreground);\n  }\n  .aihu-button[data-variant=\"default\"]:hover {\n    background-color: var(--color-primary);\n  }\n  .aihu-button[data-variant=\"destructive\"] {\n    background-color: var(--color-destructive);\n    color: var(--color-destructive-foreground);\n  }\n  .aihu-button[data-variant=\"destructive\"]:hover {\n    background-color: var(--color-destructive);\n  }\n  .aihu-button[data-variant=\"outline\"] {\n    border: 1px solid var(--color-border);\n    background-color: var(--color-background);\n  }\n  .aihu-button[data-variant=\"outline\"]:hover {\n    background-color: var(--color-accent);\n  }\n  .aihu-button[data-variant=\"ghost\"] {\n    background-color: transparent;\n  }\n  .aihu-button[data-variant=\"ghost\"]:hover {\n    background-color: var(--color-accent);\n    color: var(--color-accent-foreground);\n  }\n  .aihu-button[data-variant=\"link\"] {\n    background-color: transparent;\n    color: var(--color-primary);\n    text-underline-offset: 4px;\n  }\n  .aihu-button[data-variant=\"link\"]:hover {\n    text-decoration: underline;\n  }\n\n  /* Size matrix. */\n  .aihu-button[data-size=\"sm\"] {\n    height: 2rem;\n    padding-inline: 0.75rem;\n    font-size: 0.75rem;\n  }\n  .aihu-button[data-size=\"md\"] {\n    height: 2.25rem;\n    padding-inline: 1rem;\n    font-size: 0.875rem;\n  }\n  .aihu-button[data-size=\"lg\"] {\n    height: 2.5rem;\n    padding-inline: 2rem;\n    font-size: 0.875rem;\n  }\n  .aihu-button[data-size=\"icon\"] {\n    height: 2.25rem;\n    width: 2.25rem;\n  }\n}\n"
        }
      ],
      "description": "Styled button recipe wrapping a native <button> (variants + sizes).",
      "dependencies": [],
      "registryDependencies": [],
      "variants": {
        "variant": ["default", "destructive", "outline", "ghost", "link"],
        "size": ["sm", "md", "lg", "icon"]
      },
      "meta": {
        "capabilities": {
          "interactive": true,
          "keyboard": true,
          "form": false,
          "overlay": false,
          "directional": false,
          "hoverable": true
        }
      }
    },
    {
      "name": "card",
      "type": "ui",
      "files": [
        {
          "path": "registry/card/card.aihu",
          "type": "component",
          "source": "<!--\n  aihu-card — presentational styled recipe (Plan 5 Task 5, master spec §9.7).\n\n  Standalone styled custom element — NO primitive import (card has no headless\n  behavior base; it is purely visual). Slotted header / body / footer regions.\n  `aihu add` rewrites the `aihu-` prefix at copy time.\n\n  CSS attachment (R2): the compiled `@style` block below IS the shared\n  Constructable StyleSheet — the compiler emits `const __style__ = new\n  CSSStyleSheet()` at MODULE scope (constructed once for the whole module) and\n  adopts it into each instance's shadow root from the setup body. Authoring the\n  `@style` block is the whole of the contract; a recipe writes no registration\n  and no `adoptedStyleSheets` code of its own. See `packages/ui/README.md`\n  §\"CSS attachment (R2): the compiler owns it\".\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n}\n\n@template {\n  <div data-slot=\"card\" class={cn('aihu-card')}>\n    <div class=\"aihu-card-header\" part=\"header\"><slot name=\"header\" /></div>\n    <div class=\"aihu-card-body\" part=\"body\"><slot /></div>\n    <div class=\"aihu-card-footer\" part=\"footer\"><slot name=\"footer\" /></div>\n  </div>\n}\n\n@style {\n  .aihu-card {\n    display: block;\n    border: 1px solid var(--color-border);\n    border-radius: 0.5rem;\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n    box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n  }\n  .aihu-card-header {\n    padding: 1.5rem 1.5rem 0;\n  }\n  .aihu-card-body {\n    padding: 1.5rem;\n  }\n  .aihu-card-footer {\n    padding: 0 1.5rem 1.5rem;\n  }\n}\n"
        }
      ],
      "description": "Presentational card recipe with slotted header, body, and footer regions.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "chat-bubble",
      "type": "ui",
      "files": [
        {
          "path": "registry/chat-bubble/chat-bubble.aihu",
          "type": "component",
          "source": "<!--\n  aihu-chat-bubble — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A single chat message bubble. `speaker` controls alignment (assistant =\n  left, neutral surface; user = right, primary-tinted) and the initials\n  avatar's accent. `avatar` is a plain string prop (initials, e.g. \"SM\")\n  rather than a slot — this catalog's chat surfaces are marketing-demo\n  dressing, not a real chat widget, so a simple text prop covers it without\n  the extra API surface a slotted avatar would add. Default slot = message\n  content.\n\n  NOT NAMED `role`: a prop's name IS its host attribute, and `role` is the\n  reserved global ARIA attribute — `<aihu-chat-bubble role=\"user\">` puts an\n  invalid ARIA role on the host, which axe flags as a critical `aria-roles`\n  violation. The value is still stamped as `data-role` on the inner element,\n  which is what the styles key off.\n\n  speaker: assistant (default) | user\n  avatar:  optional initials string, e.g. \"AI\" or \"SM\".\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let speaker = prop({ default: 'assistant' })\n  let avatar = prop({ default: '' })\n}\n\n@template {\n  <div data-slot=\"chat-bubble\" data-role={speaker} class={cn('aihu-chat-bubble')}>\n    <span if={avatar} class=\"aihu-chat-bubble-avatar\" aria-hidden=\"true\">{avatar}</span>\n    <div class=\"aihu-chat-bubble-content\">\n      <slot />\n    </div>\n  </div>\n}\n\n@style {\n  .aihu-chat-bubble {\n    display: flex;\n    align-items: flex-end;\n    gap: 0.5rem;\n    max-width: 32rem;\n  }\n  .aihu-chat-bubble[data-role=\"user\"] {\n    flex-direction: row-reverse;\n    margin-inline-start: auto;\n  }\n  .aihu-chat-bubble-avatar {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    flex: none;\n    width: 1.75rem;\n    height: 1.75rem;\n    border-radius: 9999px;\n    font-size: 0.6875rem;\n    font-weight: 600;\n    /* `--color-muted` fill under `--color-muted-foreground` text is 1.9:1 in\n       aihu-default light — the two tokens are neighbours on the ramp, not a\n       fill/ink pair. `--color-secondary` / `--color-secondary-foreground` IS\n       such a pair and holds >=5.9:1 in every pack x mode at this 0.6875rem\n       size. */\n    background-color: var(--color-secondary);\n    color: var(--color-secondary-foreground);\n  }\n  .aihu-chat-bubble[data-role=\"user\"] .aihu-chat-bubble-avatar {\n    background-color: var(--color-primary);\n    color: var(--color-primary-foreground);\n  }\n  .aihu-chat-bubble-content {\n    padding: 0.625rem 0.875rem;\n    border-radius: var(--radius-lg);\n    font-size: 0.875rem;\n    line-height: 1.5;\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n    border: 1px solid var(--color-border);\n  }\n  .aihu-chat-bubble[data-role=\"user\"] .aihu-chat-bubble-content {\n    background-color: var(--color-primary);\n    color: var(--color-primary-foreground);\n    border-color: var(--color-primary);\n  }\n}\n"
        }
      ],
      "description": "Presentational single chat message bubble — speaker-aware alignment and accent, optional initials avatar.",
      "variants": {
        "speaker": ["user", "assistant"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "chat-fab",
      "type": "ui",
      "files": [
        {
          "path": "registry/chat-fab/chat-fab.aihu",
          "type": "component",
          "source": "<!--\n  aihu-chat-fab — styled recipe (Phase 2, performativeUI port Slice 7 —\n  docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  Roadmap: \"= button + popover, deliberately avoiding a toast primitive.\" A\n  fixed-position circular floating-action button that toggles a small panel —\n  a generic chat-launcher SHELL. No chat logic lives here: the panel content\n  is a plain default `<slot>`, left entirely to the consumer.\n\n  COMPOSE, NOT EXTEND — same rationale `before-after.aihu`'s header documents:\n  `aihu-chat-fab` is not itself a styled popover, it's a FAB that happens to\n  use one internally, so it composes the `popover-{root,trigger,content}`\n  STYLED RECIPE pieces (this slice's item #1) as children in its own\n  `@template`, rather than extending `AihuPopoverRoot` directly. Using the\n  STYLED recipe tags (not the raw `@aihu/primitives/popover` primitive under\n  the default `aihu-` prefix) is deliberate: `popover-root.aihu` already\n  registers `aihu-popover-root`/`-trigger`/`-content` via the compiler's\n  `$extends:` macro, and calling `definePopover('aihu')` again here would be a\n  SECOND `customElements.define` for the same tag names — a real collision the\n  moment both this recipe and the popover recipe are loaded in the same page\n  (as they are, e.g., in this very Storybook). `registryDependencies:\n  [\"popover\"]` (see meta.json) documents the real dependency, matching the\n  established `eyebrow-pill` + `status-dot` composition precedent: the child\n  tags are used directly in markup, and whichever entry point loads first\n  registers them (this recipe's own `.stories.ts` imports both, same as\n  `eyebrow-pill.stories.ts` imports `status-dot.aihu`).\n\n  label:  accessible name for the icon-only trigger button. Default \"Chat\".\n  placement: forwarded to the composed `<aihu-popover-root placement=...>` —\n             default \"top\" (the panel opens ABOVE a corner-anchored button).\n  corner: bottom-right (default) | bottom-left | top-right | top-left — fixed-\n          position anchor corner. A `position` prop was considered per the\n          roadmap note, but a closed vocabulary of corners is what a FAB\n          actually needs (arbitrary `top`/`left`/`right`/`bottom` coordinates\n          would just invite fighting the built-in `position: fixed` anchor,\n          which is not a real use case for a launcher button).\n\n  `shadow: 'light'` so the composed popover pieces sit in one continuous\n  light-DOM tree — required for `injectContext`'s ancestor walk to find the\n  root's provided context from the trigger/content descendants.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let label = prop({ default: 'Chat' })\n  let placement = prop({ default: 'top' })\n  let corner = prop({ default: 'bottom-right' })\n}\n\n@template {\n  <div class={cn('aihu-chat-fab-anchor')} data-corner={corner}>\n    <aihu-popover-root placement={placement}>\n      <aihu-popover-trigger class=\"aihu-chat-fab-trigger\" aria-label={label}>\n        <span class=\"aihu-chat-fab-icon\" aria-hidden=\"true\">\n          <slot name=\"icon\">\n            <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n              <path d=\"M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z\" />\n            </svg>\n          </slot>\n        </span>\n      </aihu-popover-trigger>\n      <aihu-popover-content class=\"aihu-chat-fab-panel\">\n        <slot></slot>\n      </aihu-popover-content>\n    </aihu-popover-root>\n  </div>\n}\n\n@style {\n  aihu-chat-fab {\n    display: contents;\n  }\n  .aihu-chat-fab-anchor {\n    position: fixed;\n    z-index: 40;\n  }\n  .aihu-chat-fab-anchor[data-corner=\"bottom-right\"] {\n    bottom: 1.5rem;\n    right: 1.5rem;\n  }\n  .aihu-chat-fab-anchor[data-corner=\"bottom-left\"] {\n    bottom: 1.5rem;\n    left: 1.5rem;\n  }\n  .aihu-chat-fab-anchor[data-corner=\"top-right\"] {\n    top: 1.5rem;\n    right: 1.5rem;\n  }\n  .aihu-chat-fab-anchor[data-corner=\"top-left\"] {\n    top: 1.5rem;\n    left: 1.5rem;\n  }\n\n  /* Overrides `aihu-popover-trigger`'s pill-button shape with a circular FAB.\n     Class-selector specificity (0,1,0) beats the base recipe's element/attr\n     rules (0,0,1 / 0,0,2), so these win regardless of stylesheet order. */\n  .aihu-chat-fab-trigger {\n    width: 3.5rem;\n    height: 3.5rem;\n    padding: 0;\n    border: none;\n    border-radius: 9999px;\n    background-color: var(--color-primary);\n    color: var(--color-primary-foreground);\n    box-shadow: 0 4px 14px color-mix(in oklab, var(--color-foreground) 30%, transparent);\n  }\n  .aihu-chat-fab-trigger:hover {\n    background-color: var(--color-primary);\n    filter: brightness(1.08);\n  }\n  .aihu-chat-fab-trigger[data-state=\"open\"] {\n    background-color: var(--color-primary);\n  }\n  .aihu-chat-fab-icon {\n    display: inline-flex;\n  }\n\n  /* Overrides `aihu-popover-content`'s default panel sizing with a chat-panel\n     shape — same specificity argument as the trigger override above. */\n  .aihu-chat-fab-panel {\n    width: min(22rem, calc(100vw - 3rem));\n    max-width: none;\n    min-height: 16rem;\n    max-height: min(28rem, calc(100vh - 8rem));\n    overflow: auto;\n  }\n}\n"
        }
      ],
      "description": "Floating action button + non-modal popover panel shell — a generic chat-launcher, deliberately with no chat logic (panel content is a plain slot).",
      "dependencies": ["@aihu/primitives"],
      "registryDependencies": ["popover"],
      "variants": {
        "corner": ["bottom-right", "bottom-left", "top-right", "top-left"]
      },
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": false,
          "overlay": true,
          "trapsFocus": false,
          "directional": false
        }
      }
    },
    {
      "name": "checkbox",
      "type": "ui",
      "files": [
        {
          "path": "registry/checkbox/checkbox.aihu",
          "type": "component",
          "source": "<!--\n  aihu-checkbox — styled recipe (Phase 2, master spec §9.4 / §9.7).\n\n  The LIGHT-DOM class-extension recipe: the registered `<aihu-checkbox>` element\n  EXTENDS the headless `AihuCheckboxRoot` primitive (role=checkbox, tri-state\n  aria-checked, Space toggle, form participation via a sibling hidden input) via\n  the compiler's `$extends:` macro, so the host inherits all behavior. The host\n  renders in LIGHT DOM (`$shadow: 'light'`) so the hidden input joins the outer\n  <form> and the recipe's class-scoped CSS reaches the global cascade.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n  No `$prop` is declared: AihuCheckboxRoot owns every attribute\n  (checked / disabled / required / name / value), surfaced via the runtime's\n  unioned observedAttributes.\n-->\n\n@state {\n  import { AihuCheckboxRoot } from '@aihu/primitives/checkbox'\n\n  base: AihuCheckboxRoot\n  shadow: 'light'\n}\n\n@template {\n  <span class=\"aihu-checkbox-indicator\" part=\"indicator\" aria-hidden=\"true\">\n    <svg viewBox=\"0 0 16 16\" width=\"12\" height=\"12\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n      <path class=\"aihu-checkbox-check\" d=\"M3 8.5l3.5 3.5L13 4.5\" />\n      <path class=\"aihu-checkbox-dash\" d=\"M4 8h8\" />\n    </svg>\n  </span>\n}\n\n@style {\n  aihu-checkbox {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: 1rem;\n    height: 1rem;\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-sm);\n    background-color: transparent;\n    color: var(--color-primary-foreground);\n    cursor: pointer;\n    transition: background-color 0.15s, border-color 0.15s;\n  }\n  aihu-checkbox:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  aihu-checkbox[data-state=\"checked\"],\n  aihu-checkbox[data-state=\"indeterminate\"] {\n    background-color: var(--color-primary);\n    border-color: var(--color-primary);\n  }\n  aihu-checkbox[data-disabled] {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n  aihu-checkbox[aria-invalid=\"true\"] {\n    border-color: var(--color-destructive);\n  }\n\n  .aihu-checkbox-indicator {\n    display: inline-flex;\n    opacity: 0;\n    transition: opacity 0.15s;\n  }\n  aihu-checkbox[data-state=\"checked\"] .aihu-checkbox-indicator,\n  aihu-checkbox[data-state=\"indeterminate\"] .aihu-checkbox-indicator {\n    opacity: 1;\n  }\n\n  /* Show the check for `checked`, the dash for `indeterminate`. */\n  .aihu-checkbox-dash { display: none; }\n  aihu-checkbox[data-state=\"indeterminate\"] .aihu-checkbox-check { display: none; }\n  aihu-checkbox[data-state=\"indeterminate\"] .aihu-checkbox-dash { display: inline; }\n}\n"
        }
      ],
      "description": "Styled checkbox recipe — light-DOM element extending the headless AihuCheckboxRoot primitive (tri-state, Space toggle, native form participation).",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": true,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "community-badge",
      "type": "ui",
      "files": [
        {
          "path": "registry/community-badge/community-badge.aihu",
          "type": "component",
          "source": "<!--\n  aihu-community-badge — presentational styled recipe (performativeUI port,\n  Slice 2 — docs/plans/2026-08-01-performative-ui-port.md).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A small social-proof pill combining a status-dot-style accent mark with\n  a metric slot, e.g. \"1,204 builders online\". Composes with aihu-status-dot\n  in its `lead` slot, same as eyebrow-pill. `aihu add` rewrites the `aihu-`\n  prefix at copy time.\n\n  tone: neutral (default) | accent\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let tone = prop({ default: 'neutral' })\n}\n\n@template {\n  <span data-slot=\"community-badge\" data-tone={tone} class={cn('aihu-community-badge')}>\n    <slot name=\"lead\" />\n    <span class=\"aihu-community-badge-text\"><slot /></span>\n  </span>\n}\n\n@style {\n  .aihu-community-badge {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.5rem;\n    border-radius: var(--radius-pill);\n    padding-block: 0.375rem;\n    padding-inline: 0.875rem;\n    border: var(--border) solid var(--color-border);\n    background-color: var(--color-surface);\n    color: var(--color-foreground);\n  }\n  .aihu-community-badge-text {\n    font-size: 0.8125rem;\n    font-weight: 500;\n  }\n  .aihu-community-badge[data-tone=\"accent\"] {\n    border-color: color-mix(in oklab, var(--color-accent) 40%, var(--color-border));\n  }\n  /* Raw `--color-accent` is only 4.14:1 on `--color-surface` in aihu-default\n     light — under the 4.5:1 WCAG 2 AA floor for this 0.8125rem label. Mixing\n     30% of `--color-foreground` into it keeps the accent hue while lifting\n     every pack x mode to >=6.4:1. */\n  .aihu-community-badge[data-tone=\"accent\"] .aihu-community-badge-text {\n    color: color-mix(in oklab, var(--color-accent) 70%, var(--color-foreground));\n  }\n}\n"
        }
      ],
      "description": "Presentational social-proof pill — pairs a status-dot-style lead slot with a metric.",
      "registryDependencies": ["status-dot"],
      "variants": {
        "tone": ["neutral", "accent"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "dialog",
      "type": "ui",
      "files": [
        {
          "path": "registry/dialog/dialog-backdrop.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-backdrop — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-dialog-backdrop>` EXTENDS the headless AihuDialogBackdrop primitive\n  (click-outside dismissal, reflects `data-state`) via the compiler's\n  `$extends:` macro. Light DOM (`$shadow: 'light'`). The translucent scrim covers\n  the viewport while open and fades out on close.\n\n  MOTION (tailwind-animations port, Track A Slice 12). This is aihu's stand-in\n  for the vendor's `.animate-dialog::backdrop` rules: `::backdrop` is a\n  pseudo-element that exists only on a native `<dialog>`/fullscreen element, and\n  aihu's dialog is a headless JS primitive over plain positioned elements — so\n  the backdrop is a REAL element carrying the same `data-state`, and the fade is\n  ported onto that instead. Animation is on by default; the\n  `animate-dialog-duration-*` / `animate-dialog-easing-[…]` utilities retune it\n  via the shared `--aihu-anim-dialog-*` custom properties. Full decision record:\n  `packages/css-engine/crates/aihu-css-core/recipes/dialog.css`.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogBackdrop } from '@aihu/primitives/dialog'\n\n  base: AihuDialogBackdrop\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-backdrop {\n    position: fixed;\n    inset: 0;\n    z-index: 40;\n    background: color-mix(in oklab, var(--color-foreground) 50%, transparent);\n    opacity: 1;\n    visibility: visible;\n    will-change: opacity;\n    transition:\n      opacity var(--aihu-anim-dialog-duration, 350ms) ease,\n      visibility 0s;\n  }\n  /* `visibility: hidden`, not `display: none` — see dialog-content.aihu's\n     closed-state comment for why (the primitive never unmounts these elements,\n     and `display` cannot be transitioned into without `allow-discrete`). The\n     delayed `visibility` slot keeps the scrim painted for its whole fade-out. */\n  aihu-dialog-backdrop[data-state=\"closed\"] {\n    opacity: 0;\n    visibility: hidden;\n    pointer-events: none;\n    transition-delay: 0s, var(--aihu-anim-dialog-duration, 350ms);\n  }\n  @media (prefers-reduced-motion: reduce) {\n    aihu-dialog-backdrop:not([data-motion=\"always\"]),\n    aihu-dialog-backdrop[data-state=\"closed\"]:not([data-motion=\"always\"]) {\n      transition-duration: 1ms;\n      transition-delay: 0s;\n    }\n  }\n}\n"
        },
        {
          "path": "registry/dialog/dialog-close.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-close — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-dialog-close>` EXTENDS the headless AihuDialogClose primitive (closes\n  the dialog on activation, `role=button` when not a native button) via the\n  compiler's `$extends:` macro. Light DOM (`$shadow: 'light'`). Positioned at the\n  top-right corner of the content panel.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogClose } from '@aihu/primitives/dialog'\n\n  base: AihuDialogClose\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-close {\n    position: absolute;\n    top: var(--space-4);\n    right: var(--space-4);\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    width: 1.5rem;\n    height: 1.5rem;\n    border-radius: var(--radius-sm);\n    color: var(--color-surface-foreground);\n    opacity: 0.7;\n    cursor: pointer;\n    transition: opacity 0.15s;\n  }\n  aihu-dialog-close:hover {\n    opacity: 1;\n  }\n  aihu-dialog-close:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n}\n"
        },
        {
          "path": "registry/dialog/dialog-content.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-content — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-dialog-content>` EXTENDS the headless AihuDialogContent primitive\n  (`role=dialog`, `aria-modal`, focus-trap + return-focus, Escape-to-close,\n  `aria-labelledby`/`aria-describedby`) via the compiler's `$extends:` macro.\n  Light DOM (`$shadow: 'light'`) is required so the focus trap can see the\n  consumer's children. Only the DEFAULT `<slot/>` projects in light DOM, so the\n  consumer composes the title/description/close as plain children.\n\n  MOTION (tailwind-animations port, Track A Slice 12). The panel animates in and\n  out — it is NOT an instant `display` cutover any more. The animation is ON BY\n  DEFAULT rather than opt-in behind an `animate-dialog-*` class: a modal that\n  snaps into existence is the anomaly, not the enhancement, and the registry's\n  job is to ship the good default. The `animate-dialog-*` UTILITIES stay the\n  opt-in half — they only reconfigure this built-in motion by overriding the\n  `--aihu-anim-dialog-*` custom properties it reads, so\n  `<aihu-dialog-content class=\"animate-dialog-from-left animate-dialog-duration-200\">`\n  works without the component knowing anything about those classes. The full\n  decision record for the family lives in\n  `packages/css-engine/crates/aihu-css-core/recipes/dialog.css`.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogContent } from '@aihu/primitives/dialog'\n\n  base: AihuDialogContent\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-content {\n    position: fixed;\n    left: 50%;\n    top: 50%;\n    /* Centering rides on the INDIVIDUAL `translate` property, not on\n       `transform: translate(-50%, -50%)`. The entrance uses the individual\n       `scale` property, and the platform composes those as\n       `translate · rotate · scale · transform`, all about one shared\n       transform-origin — so a centering offset parked in `transform` gets\n       scaled by the entrance, drifting the panel by (1 − scale) · width / 2\n       (~10px on a 32rem panel at scale 0.96) for the whole animation. With the\n       centering in `translate` instead, `scale` resolves about the panel's true\n       centre and nothing drifts. This is also why the family's start offset is\n       two SCALAR custom properties rather than upstream's packed pair: only\n       scalars compose into the `calc()`s below. */\n    translate: -50% -50%;\n    scale: 1;\n    z-index: 50;\n    width: 100%;\n    max-width: 32rem;\n    display: flex;\n    flex-direction: column;\n    gap: var(--space-4);\n    padding: var(--space-6);\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-lg);\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n    box-shadow: 0 10px 30px color-mix(in oklab, var(--color-foreground) 25%, transparent);\n    opacity: 1;\n    visibility: visible;\n    will-change: opacity, translate, scale;\n    /* `visibility 0s` is a real slot in the list, not a no-op — the closed rule\n       below delays exactly that slot so the panel stays rendered for its whole\n       fade-out and only then leaves the a11y tree / tab order. */\n    transition:\n      opacity var(--aihu-anim-dialog-duration, 350ms) ease,\n      translate var(--aihu-anim-dialog-duration, 350ms) var(--aihu-anim-dialog-easing, cubic-bezier(0.22, 1, 0.36, 1)),\n      scale var(--aihu-anim-dialog-duration, 350ms) var(--aihu-anim-dialog-easing, cubic-bezier(0.22, 1, 0.36, 1)),\n      visibility 0s;\n  }\n  /* The closed state is `visibility: hidden`, NOT `display: none`. The headless\n     primitive never unmounts this element (it only flips `data-state`), so a\n     permanently-rendered element needs neither `@starting-style` nor\n     `transition-behavior: allow-discrete` nor `<aihu-presence-gate>` — but it\n     DOES need a closed state that can be transitioned INTO, which `display`\n     cannot be. `visibility` is the discrete property the platform transitions\n     specially: delayed to the end of the fade, it holds the panel rendered\n     throughout the exit and still removes it from the accessibility tree and\n     the tab order once it lands. */\n  aihu-dialog-content[data-state=\"closed\"] {\n    opacity: var(--aihu-anim-dialog-start-opacity, 0);\n    translate:\n      calc(-50% + var(--aihu-anim-dialog-start-x, 0px))\n      calc(-50% + var(--aihu-anim-dialog-start-y, 1.5rem));\n    scale: var(--aihu-anim-dialog-start-scale, 0.96);\n    visibility: hidden;\n    pointer-events: none;\n    transition-delay: 0s, 0s, 0s, var(--aihu-anim-dialog-duration, 350ms);\n  }\n  aihu-dialog-content:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  /* Reduced motion is a hard requirement of this port. `animations.rs`'s\n     `reduced_motion_guard` only covers keyframe-backed `animate-*` utilities,\n     so a transition-driven surface carries its own guard — same\n     `[data-motion=\"always\"]` per-element escape hatch, and the duration is\n     COLLAPSED rather than set to `transition: none` so `transitionend` still\n     fires for anything listening. The `[data-state=\"closed\"]` arm is load-\n     bearing: without it the closed rule's `transition-delay` would still hold\n     `visibility` for the full 350ms. */\n  @media (prefers-reduced-motion: reduce) {\n    aihu-dialog-content:not([data-motion=\"always\"]),\n    aihu-dialog-content[data-state=\"closed\"]:not([data-motion=\"always\"]) {\n      transition-duration: 1ms;\n      transition-delay: 0s;\n    }\n  }\n}\n"
        },
        {
          "path": "registry/dialog/dialog-description.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-description — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-dialog-description>` EXTENDS the headless AihuDialogDescription primitive\n  (registers its id as the content's `aria-describedby`) via the compiler's\n  `$extends:` macro. Light DOM (`$shadow: 'light'`).\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogDescription } from '@aihu/primitives/dialog'\n\n  base: AihuDialogDescription\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-description {\n    display: block;\n    font-size: 0.875rem;\n    line-height: 1.5;\n    /* Muted secondary text that still clears WCAG AA on the surface panel:\n       bias the muted token toward the panel's own foreground. The raw\n       --color-muted-foreground (#8a8880) fails AA on --color-surface\n       (#faf8f4); blending toward --color-surface-foreground restores it\n       while preserving the secondary-text hierarchy. */\n    color: color-mix(in oklab, var(--color-surface-foreground) 70%, var(--color-muted-foreground));\n  }\n}\n"
        },
        {
          "path": "registry/dialog/dialog-root.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-root — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  The state owner of the modal-dialog machine. `<aihu-dialog-root>` EXTENDS the\n  headless AihuDialogRoot primitive (owns `open`/`modal`, provides the dialog\n  context to descendant pieces, reflects `data-state`) via the compiler's\n  `$extends:` macro. Renders in LIGHT DOM (`$shadow: 'light'`) so the pieces it\n  wraps inject the context through the real DOM tree, and `display: contents`\n  keeps the root visually transparent.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogRoot } from '@aihu/primitives/dialog'\n\n  base: AihuDialogRoot\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-root {\n    display: contents;\n  }\n}\n"
        },
        {
          "path": "registry/dialog/dialog-title.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-title — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-dialog-title>` EXTENDS the headless AihuDialogTitle primitive (registers\n  its id as the content's `aria-labelledby`) via the compiler's `$extends:`\n  macro. Light DOM (`$shadow: 'light'`).\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogTitle } from '@aihu/primitives/dialog'\n\n  base: AihuDialogTitle\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-title {\n    display: block;\n    font-size: 1.125rem;\n    font-weight: 600;\n    line-height: 1.4;\n    color: var(--color-surface-foreground);\n  }\n}\n"
        },
        {
          "path": "registry/dialog/dialog-trigger.aihu",
          "type": "component",
          "source": "<!--\n  aihu-dialog-trigger — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-dialog-trigger>` EXTENDS the headless AihuDialogTrigger primitive\n  (toggles the dialog, wires `aria-haspopup`/`aria-expanded`/`aria-controls`)\n  via the compiler's `$extends:` macro. Light DOM (`$shadow: 'light'`) so the\n  context injection reaches the ancestor root. The trigger is usually the\n  consumer's own button — styling is intentionally minimal.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuDialogTrigger } from '@aihu/primitives/dialog'\n\n  base: AihuDialogTrigger\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-dialog-trigger {\n    display: inline-flex;\n    cursor: pointer;\n  }\n}\n"
        }
      ],
      "description": "Styled modal dialog recipe — light-DOM pieces extending the headless AihuDialog primitives (focus-trap + return-focus, Escape-to-close, aria-modal, click-outside dismissal).",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": false,
          "overlay": true,
          "directional": false
        }
      }
    },
    {
      "name": "eyebrow-pill",
      "type": "ui",
      "files": [
        {
          "path": "registry/eyebrow-pill/eyebrow-pill.aihu",
          "type": "component",
          "source": "<!--\n  aihu-eyebrow-pill — presentational styled recipe (performativeUI port,\n  Slice 1 — docs/plans/2026-08-01-performative-ui-port.md §3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A small uppercase label pill, typically preceding a heading. Composes with\n  aihu-status-dot in its `lead` slot — this deliberately exercises\n  `registryDependencies` (see meta.json), which no other shipped recipe uses\n  yet. `aihu add` rewrites the `aihu-` prefix at copy time.\n\n  tone: neutral (default) | accent | success | warning\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let tone = prop({ default: 'neutral' })\n}\n\n@template {\n  <span data-slot=\"eyebrow-pill\" data-tone={tone} class={cn('aihu-eyebrow-pill')}>\n    <slot name=\"lead\" />\n    <slot />\n  </span>\n}\n\n@style {\n  .aihu-eyebrow-pill {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.375rem;\n    border-radius: var(--radius-pill);\n    padding-block: 0.125rem;\n    padding-inline: 0.625rem;\n    font-size: 0.75rem;\n    font-weight: 500;\n    letter-spacing: 0.02em;\n    text-transform: uppercase;\n    border: var(--border) solid var(--color-border);\n  }\n  /* Each tone's raw token as label text over its own 12% tint lands under the\n     4.5:1 WCAG 2 AA floor for this 0.75rem label in at least one pack x mode\n     (accent 3.56:1 in aihu-default light, neutral 3.00:1 in aihu-default\n     dark). Mixing 40% `--color-foreground` into the label keeps the tone's\n     hue against the unchanged tint and lifts every tone x pack x mode to\n     >=5.8:1. */\n  .aihu-eyebrow-pill[data-tone=\"neutral\"] {\n    color: color-mix(in oklab, var(--color-neutral) 60%, var(--color-foreground));\n    background-color: color-mix(in oklab, var(--color-neutral) 12%, transparent);\n  }\n  .aihu-eyebrow-pill[data-tone=\"accent\"] {\n    color: color-mix(in oklab, var(--color-accent) 60%, var(--color-foreground));\n    background-color: color-mix(in oklab, var(--color-accent) 12%, transparent);\n  }\n  .aihu-eyebrow-pill[data-tone=\"success\"] {\n    color: color-mix(in oklab, var(--color-success) 60%, var(--color-foreground));\n    background-color: color-mix(in oklab, var(--color-success) 12%, transparent);\n  }\n  .aihu-eyebrow-pill[data-tone=\"warning\"] {\n    color: color-mix(in oklab, var(--color-warning) 60%, var(--color-foreground));\n    background-color: color-mix(in oklab, var(--color-warning) 12%, transparent);\n  }\n}\n"
        }
      ],
      "description": "Presentational label pill, typically preceding a heading. Composes with status-dot in its lead slot.",
      "registryDependencies": ["status-dot"],
      "variants": {
        "tone": ["neutral", "accent", "success", "warning"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "floating-sparkles",
      "type": "ui",
      "files": [
        {
          "path": "registry/floating-sparkles/floating-sparkles.aihu",
          "type": "component",
          "source": "<!--\n  aihu-floating-sparkles — presentational styled recipe (performativeUI port,\n  Slice 9 — docs/plans/2026-08-01-performative-ui-port.md §Tier-C batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A decorative ambient particle field — small glowing dots drifting and\n  twinkling — built directly on `@aihu/use/motion`'s `useParticleField`\n  (Track B Slice 8), which is itself built on `useCanvasSurface`.\n  `useCanvasSurface` OWNS canvas creation (see its header comment: measuring\n  and styling the same node would feed a `ResizeObserver` a resize loop, so\n  it measures the HOST and styles a canvas it creates itself). This\n  component's `@template` is therefore a plain container — `ref={hostEl}`\n  feeds that host to `useParticleField`, which mounts its own `<canvas>`\n  inside it; nothing here reaches for a `<canvas>` element directly.\n\n  count: how many particles, string-encoded number. Default \"30\".\n  color: a single fill color for every particle, default \"#ffffff\". This is\n         a LITERAL CSS color string, not a `--color-*` token reference — every\n         other decorative recipe in this port writes `color: var(--color-*)`\n         in `@style`, but a canvas 2D context's `fillStyle` is not part of\n         the CSS cascade and cannot resolve a custom property; it needs an\n         already-resolved value. `useParticleField`'s `colors` option already\n         accepts an array (for a future multi-color field); per the roadmap\n         this component deliberately does NOT parse a comma-separated string\n         into that array yet (over-engineering ahead of a real need) — a\n         single-element array is passed instead.\n\n  Layout: a standalone, full-bleed, absolutely-positioned decorative layer\n  (`position: absolute; inset: 0`), no slot — meant to sit BEHIND other\n  content the same way `aurora` (this slice's sibling component) does, for a\n  consistent Tier-C \"decorative background layer\" contract across the batch.\n  The consumer places it as the first child of a `position: relative`\n  ancestor and stacks real content above it with `z-index` (see\n  `useCanvasSurface`'s header: \"the host must be positioned\" for its owned\n  canvas to land at the host's top-left, which `position: absolute` already\n  satisfies here).\n\n  Reduced motion and off-screen pausing are NOT reimplemented here — both are\n  the composable family's job. `useCanvasSurface`'s \"paint once, never loop\"\n  contract means `prefersReduced()` true renders one static seeded starfield\n  frame instead of looping (traced in `useParticleField`'s `onFrame`: `if\n  (!reducedMotion) step(...)` is skipped, `draw(..., !reducedMotion)` turns\n  off the twinkle modulation, so the field freezes on its seeded positions —\n  never blank). `isVisible`-gated pausing while scrolled off-screen is\n  likewise inherited for free.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let count = prop({ default: '30' })\n  let color = prop({ default: '#ffffff' })\n\n  let hostEl = state(null)\n\n  // Read into a differently-named local before use — an options-object key\n  // textually identical to a prop name (`count: count`) trips the compiler's\n  // prop-auto-unwrap rewriter (see token-stream.aihu's header for the exact\n  // failure mode this sidesteps).\n  const particleCount = Number(count)\n\n  useParticleField(() => hostEl, {\n    count: particleCount,\n    colors: [color],\n  })\n}\n\n@template {\n  <div\n    ref={hostEl}\n    data-slot=\"floating-sparkles\"\n    aria-hidden=\"true\"\n    class={cn('aihu-floating-sparkles')}></div>\n}\n\n@style {\n  .aihu-floating-sparkles {\n    display: block;\n    position: absolute;\n    inset: 0;\n    overflow: hidden;\n    pointer-events: none;\n  }\n}\n"
        }
      ],
      "description": "Decorative ambient particle field — small glowing dots drifting and twinkling on a managed canvas, built on useParticleField.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "glass-card",
      "type": "ui",
      "files": [
        {
          "path": "registry/glass-card/glass-card.aihu",
          "type": "component",
          "source": "<!--\n  aihu-glass-card — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A frosted-glass surface: a translucent, color-mixed background behind a\n  `backdrop-filter: blur(...)`. No new tokens (E-P3 ruling) — derived\n  per-recipe via `color-mix()` + a literal `blur(12px)`. Default slot holds\n  the card body.\n\n  padding: sm | md | lg (default)\n  (Variant matrix is the registry catalog contract — see meta.json — reflected\n  as data-padding and matched in @style below.)\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let padding = prop({ default: 'md' })\n}\n\n@template {\n  <div data-slot=\"glass-card\" data-padding={padding} class={cn('aihu-glass-card')}>\n    <slot />\n  </div>\n}\n\n@style {\n  .aihu-glass-card {\n    display: block;\n    background-color: color-mix(in oklab, var(--color-surface) 70%, transparent);\n    backdrop-filter: blur(12px);\n    -webkit-backdrop-filter: blur(12px);\n    border: 1px solid color-mix(in oklab, var(--color-border) 60%, transparent);\n    border-radius: var(--radius-lg);\n    color: var(--color-surface-foreground);\n  }\n  .aihu-glass-card[data-padding=\"sm\"] {\n    padding: 0.75rem;\n  }\n  .aihu-glass-card[data-padding=\"md\"] {\n    padding: 1.25rem;\n  }\n  .aihu-glass-card[data-padding=\"lg\"] {\n    padding: 2rem;\n  }\n  @supports not (backdrop-filter: blur(1px)) {\n    .aihu-glass-card {\n      background-color: color-mix(in oklab, var(--color-surface) 92%, transparent);\n    }\n  }\n}\n"
        }
      ],
      "description": "Presentational frosted-glass surface card — backdrop-filter blur over a translucent, color-mixed background.",
      "variants": {
        "padding": ["sm", "md", "lg"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "goldeneye",
      "type": "ui",
      "files": [
        {
          "path": "registry/goldeneye/goldeneye.aihu",
          "type": "component",
          "source": "<!--\n  aihu-goldeneye — presentational styled recipe (performativeUI port,\n  Slice 11 — docs/plans/2026-08-01-performative-ui-port.md §Tier-C tail).\n  \"Isolated deliberately so it can be cut without blocking anything else\" per\n  the roadmap note; this is the last Tier-C decorative recipe in the batch.\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md. The upstream\n  demo file was neither fetched nor read for this port (no network access,\n  and this port's binding provenance rule forbids transcribing upstream\n  source on sight regardless): the effect below is written from the\n  behavioral description in the slice brief plus ordinary, widely-known\n  AI/tech marketing-site visual-effect conventions.\n\n  ── Interpreting \"goldeneye\" ────────────────────────────────────────────\n\n  The brief named three plausible readings for a component with this name in\n  an AI-marketing-UI catalog: a Matrix-style digital-rain cascade, a\n  scanning/targeting-reticle sweep, or a single glowing eye/orb. This recipe\n  picks the third and treats it as the correct reading, not a coin flip:\n\n    - The name decomposes literally as \"gold\" + \"eye\" — an eye, in a golden\n      hue, not a rain of glyphs or a crosshair. Digital rain is also already\n      this batch's `ascii-hero` territory (binary drift on a character\n      field); a second glyph-cascade recipe this late in Tier-C would be a\n      near-duplicate, not a new visual.\n    - A single watchful eye is a genuinely common personification in\n      AI-product marketing — \"the system is perceiving/attending to you\" —\n      distinct from anything else in this batch (`floating-sparkles` is\n      ambient texture, `node-graph-background` is a network metaphor,\n      `ascii-hero` is a hero backdrop). It is also the reading that most\n      naturally SUBSUMES the scanning-reticle idea rather than competing\n      with it: this eye's pupil autonomously sweeps a slow scan path (see\n      below), which reads as \"scanning\" without needing a separate\n      crosshair motif.\n    - The sweep is autonomous (a fixed Lissajous path driven by elapsed\n      time), deliberately NOT pointer-tracking. A tracking eye would need a\n      pointer listener and would blur the line into \"interactive,\" but the\n      brief is explicit that this is a decorative recipe with no\n      interactive/keyboard/form/overlay capabilities (mirrored exactly in\n      `meta.json`) — so \"watchful\" is expressed as a self-directed scan, not\n      as attention paid to the visitor's cursor.\n\n  ── Architecture: built directly on `useCanvasSurface` ──────────────────\n\n  Neither `useParticleField` nor `useCharacterField` is the right fit here,\n  and for a DIFFERENT reason than `node-graph-background`'s (Slice 10) case\n  for dropping to the same level — that one needed a second draw pass over\n  shared state and hit a missing draw hook. This recipe has no such\n  workaround to make because it was never a fit for the \"N-item field\"\n  abstraction those composables model in the first place:\n\n    - `useParticleField` and `useCharacterField` both own a SEEDED ARRAY of\n      many independent items (particles / glyph cells), each with its own\n      position and (for particles) velocity, that must be seeded on first\n      size, integrated every frame, and rescaled or rebuilt on resize. That\n      machinery is the point of those composables.\n    - This eye draws exactly ONE continuously-shaded feature — a radial\n      glow, a solid iris disc, one sweeping pupil, one glint — whose\n      geometry is a pure function of `(elapsed time, host width, host\n      height)`, recomputed from scratch every frame. There is no seeded\n      state to own, so there is also no `onResize` hook below: unlike every\n      other Tier-C recipe in this port, a resize needs no rescale pass\n      because nothing persists between frames to rescale.\n\n  `useCanvasSurface` is explicitly \"the substrate every canvas-based visual\n  effect sits on … future canvas effects are expected to [sit on it] as\n  well\" (its own header), so entering at this level is the sanctioned\n  choice for a custom single-feature draw, not a bypass — same verdict\n  `node-graph-background` reached, arrived at independently here because\n  this recipe's shape never matched a field composable's grain to begin\n  with.\n\n  ── The `globalAlpha` + `'transparent'`-stop idiom ──────────────────────\n\n  The glow halo needs to fade from a caller-chosen `color` at some alpha\n  down to nothing at its edge — but `color` is an arbitrary literal CSS\n  string (hex/rgb/hsl/named; see below), and computing an alpha-adjusted\n  variant of an unknown format would mean parsing it. Two things sidestep\n  that entirely: `'transparent'` is a valid gradient color-stop regardless\n  of the OTHER stop's format, so the far stop needs no relation to `color`\n  at all; and the glow's overall peak brightness is carried by\n  `ctx.globalAlpha` (reset to `1` after, same discipline `node-graph-background`\n  and `useParticleField`'s `draw()` already follow), not by a baked-in alpha\n  channel on the gradient itself. The iris disc, for the same reason, is\n  drawn as a FLAT fill in `color` rather than a light-core/dark-rim\n  gradient — a rim shade would need a lightened or darkened variant of an\n  unparsed color string, which is exactly the constraint this idiom avoids.\n\n  ── Props ────────────────────────────────────────────────────────────────\n\n  color:       the iris and glow color. Default \"#ffd700\" (gold — the\n               component's namesake hue). A LITERAL CSS color string, not a\n               `--color-*` token reference — identical constraint to every\n               other canvas recipe in this port (`floating-sparkles`,\n               `node-graph-background`, `ascii-hero`): a canvas 2D context's\n               `fillStyle` is not part of the CSS cascade and cannot resolve\n               a custom property.\n  pupil-color: the pupil's fill color. Default \"#1c1408\" (a near-black warm\n               brown, legible against the default gold without reading as\n               pure black-on-yellow). Also a literal CSS color string.\n               (Declared `pupilColor`; the runtime derives the observed\n               attribute as kebab-case, so consumers write `pupil-color`.)\n  speed:       sweep/pulse rate multiplier, string-encoded number. Default\n               \"1\". \"0\" freezes the sweep and glow at their `t=0` pose\n               (still painted — see Reduced motion below — not blanked);\n               this is a legitimate use, not an error case, so it is not\n               coerced back up to a nonzero default.\n\n  Not exposed: individual radii, glow strength, sweep amplitude, glint\n  opacity. Every one of them is an internal look-and-feel constant at this\n  altitude — widening the surface ahead of a real need is the\n  over-engineering `ascii-hero`'s header already declined for this port.\n\n  ── Layout ───────────────────────────────────────────────────────────────\n\n  A standalone, full-bleed, absolutely-positioned decorative layer\n  (`position: absolute; inset: 0`), no slot — the same \"decorative\n  background layer\" contract every Tier-C recipe in this port carries. The\n  eye's own geometry is derived from the HOST's box (`Math.min(width,\n  height)` sets the iris radius, `width/2, height/2` its center), so unlike\n  a texture-fill recipe this also composes naturally as a compact element:\n  a consumer can either drop it as the first child of a large\n  `position: relative` hero (an ambient background eye) or size the host to\n  a small square/circle wrapper for a compact \"eye\" placement — both are\n  the same recipe, just a differently-sized host.\n\n  ── Reduced motion / off-screen ─────────────────────────────────────────\n\n  Neither is reimplemented here; both are `useCanvasSurface`'s job. Every\n  animated term in `draw()` — the glow's pulse and both axes of the pupil's\n  sweep — is a bare `Math.sin(t * frequency * TAU)` with NO phase offset, so\n  at `t = 0` every one of them evaluates to exactly `0`: the pupil sits\n  precisely centered in the iris and the glow sits at its baseline (not\n  peak, not trough) brightness. `handleFrame` below maps\n  `frame.reducedMotion` to `t = 0` for exactly this reason. Traced through\n  `useCanvasSurface`'s \"paint once, never loop\" contract: under\n  `prefers-reduced-motion: reduce`, `start()` invokes `onFrame` exactly once\n  with `reducedMotion: true` and never arms the rAF loop, so `handleFrame`\n  computes `t = 0`, `draw()` renders that centered-pupil / baseline-glow\n  frame, and nothing further is painted — a settled, watchful eye at rest,\n  never a blank box and never frozen mid-sweep. `isVisible`-gated pausing\n  while scrolled off-screen is inherited for free.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let color = prop({ default: '#ffd700' })\n  let pupilColor = prop({ default: '#1c1408' })\n  let speed = prop({ default: '1' })\n\n  let hostEl = state(null)\n\n  // Read every prop into a differently-named local before use — an\n  // options-object key textually identical to a prop name trips the\n  // compiler's prop-auto-unwrap rewriter (see token-stream.aihu's header for\n  // the exact failure mode).\n  const irisColor = color\n  const pupilColorValue = pupilColor\n  const rateMultiplier = Math.max(0, Number(speed) || 0)\n\n  const TAU = Math.PI * 2\n  /** Iris radius as a fraction of the host's shorter side. */\n  const IRIS_RADIUS_RATIO = 0.32\n  /** Glow halo radius as a multiple of the iris radius. */\n  const GLOW_RADIUS_RATIO = 2.2\n  /** Glow's breathing alpha ranges [BASE - AMPLITUDE, BASE + AMPLITUDE]. */\n  const GLOW_ALPHA_BASE = 0.28\n  const GLOW_ALPHA_AMPLITUDE = 0.18\n  /** Cycles per second (pre-`rateMultiplier`) for the glow's breathing and\n   * each axis of the pupil's sweep. X and Y differ so the sweep traces a\n   * Lissajous path rather than a degenerate straight line. */\n  const PULSE_FREQ = 0.15\n  const SWEEP_FREQ_X = 0.12\n  const SWEEP_FREQ_Y = 0.19\n  /** Pupil wander radius as a fraction of the iris radius; Y is scaled down\n   * further so the scan reads as mostly side-to-side, like a search. */\n  const PUPIL_SWEEP_RATIO = 0.45\n  const PUPIL_SWEEP_Y_RATIO = 0.6\n  const PUPIL_RADIUS_RATIO = 0.42\n  const GLINT_ALPHA = 0.85\n\n  const draw = (ctx, width, height, t) => {\n    ctx.clearRect(0, 0, width, height)\n\n    const cx = width / 2\n    const cy = height / 2\n    const irisRadius = Math.min(width, height) * IRIS_RADIUS_RATIO\n    if (irisRadius <= 0) return\n\n    // Ambient glow: see the header's `globalAlpha` + `'transparent'`-stop\n    // note — the far stop needs no relation to `irisColor`'s format, and the\n    // pulse's peak brightness rides on `globalAlpha`, not a baked-in alpha.\n    const pulse = GLOW_ALPHA_BASE + GLOW_ALPHA_AMPLITUDE * Math.sin(t * PULSE_FREQ * TAU)\n    const glowRadius = irisRadius * GLOW_RADIUS_RATIO\n    const glow = ctx.createRadialGradient(cx, cy, 0, cx, cy, glowRadius)\n    glow.addColorStop(0, irisColor)\n    glow.addColorStop(1, 'transparent')\n    ctx.globalAlpha = pulse\n    ctx.fillStyle = glow\n    ctx.beginPath()\n    ctx.arc(cx, cy, glowRadius, 0, TAU)\n    ctx.fill()\n    ctx.globalAlpha = 1\n\n    // Iris: a flat solid disc — see the header for why this is not a\n    // light-core/dark-rim gradient.\n    ctx.fillStyle = irisColor\n    ctx.beginPath()\n    ctx.arc(cx, cy, irisRadius, 0, TAU)\n    ctx.fill()\n\n    // Pupil: a Lissajous sweep, pure `sin` with no phase offset on either\n    // axis, so `t = 0` is always a centered gaze (see the header's reduced\n    // motion note).\n    const sweep = irisRadius * PUPIL_SWEEP_RATIO\n    const px = cx + Math.sin(t * SWEEP_FREQ_X * TAU) * sweep\n    const py = cy + Math.sin(t * SWEEP_FREQ_Y * TAU) * sweep * PUPIL_SWEEP_Y_RATIO\n    const pupilRadius = irisRadius * PUPIL_RADIUS_RATIO\n    ctx.fillStyle = pupilColorValue\n    ctx.beginPath()\n    ctx.arc(px, py, pupilRadius, 0, TAU)\n    ctx.fill()\n\n    // Glint: a small fixed highlight offset up-left from the pupil's center,\n    // so the eye reads as glossy rather than a flat dot.\n    ctx.globalAlpha = GLINT_ALPHA\n    ctx.fillStyle = '#ffffff'\n    ctx.beginPath()\n    ctx.arc(px - pupilRadius * 0.35, py - pupilRadius * 0.35, pupilRadius * 0.3, 0, TAU)\n    ctx.fill()\n    ctx.globalAlpha = 1\n  }\n\n  const handleFrame = (frame) => {\n    const t = frame.reducedMotion ? 0 : (frame.timestamp / 1000) * rateMultiplier\n    draw(frame.ctx, frame.width, frame.height, t)\n  }\n\n  useCanvasSurface(() => hostEl, {\n    onFrame: handleFrame,\n  })\n}\n\n@template {\n  <div\n    ref={hostEl}\n    data-slot=\"goldeneye\"\n    aria-hidden=\"true\"\n    class={cn('aihu-goldeneye')}></div>\n}\n\n@style {\n  .aihu-goldeneye {\n    display: block;\n    position: absolute;\n    inset: 0;\n    overflow: hidden;\n    pointer-events: none;\n  }\n}\n"
        }
      ],
      "description": "Decorative watchful eye — a glowing iris with a pupil that autonomously sweeps a slow Lissajous scan, built directly on useCanvasSurface.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "gradient-text",
      "type": "ui",
      "files": [
        {
          "path": "registry/gradient-text/gradient-text.aihu",
          "type": "component",
          "source": "<!--\n  aihu-gradient-text — presentational styled recipe (performativeUI port,\n  Slice 1 — docs/plans/2026-08-01-performative-ui-port.md §3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  Applies the pack's brand gradient (--gradient-brand) as text fill, with an\n  opt-in serif variant. `aihu add` rewrites the `aihu-` prefix at copy time.\n\n  weight: normal | medium | semibold (default) | bold\n  font:   sans (default) | serif\n\n  This component is also the token layer's own acceptance test: if\n  --gradient-brand or --font-serif failed to reach :root (this component's\n  shadow: 'light' scope), it renders transparent or visibly falls back — see\n  the @supports guard below.\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let weight = prop({ default: 'semibold' })\n  let font = prop({ default: 'sans' })\n}\n\n@template {\n  <span\n    data-slot=\"gradient-text\"\n    data-weight={weight}\n    data-font={font}\n    class={cn('aihu-gradient-text')}>\n    <slot />\n  </span>\n}\n\n@style {\n  .aihu-gradient-text {\n    background-image: var(--gradient-brand);\n    background-clip: text;\n    -webkit-background-clip: text;\n    color: transparent;\n  }\n  @supports not (background-clip: text) {\n    .aihu-gradient-text {\n      background-image: none;\n      color: var(--color-accent);\n    }\n  }\n  .aihu-gradient-text[data-font=\"sans\"] {\n    font-family: var(--font-sans);\n  }\n  .aihu-gradient-text[data-font=\"serif\"] {\n    font-family: var(--font-serif);\n  }\n  .aihu-gradient-text[data-weight=\"normal\"] {\n    font-weight: 400;\n  }\n  .aihu-gradient-text[data-weight=\"medium\"] {\n    font-weight: 500;\n  }\n  .aihu-gradient-text[data-weight=\"semibold\"] {\n    font-weight: 600;\n  }\n  .aihu-gradient-text[data-weight=\"bold\"] {\n    font-weight: 700;\n  }\n}\n"
        }
      ],
      "description": "Presentational text decoration — applies the pack's brand gradient as text fill.",
      "variants": {
        "weight": ["normal", "medium", "semibold", "bold"],
        "font": ["sans", "serif"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "input",
      "type": "ui",
      "files": [
        {
          "path": "registry/input/input.aihu",
          "type": "component",
          "source": "<!--\n  aihu-input — presentational styled recipe (Phase 2, master spec §9.7).\n\n  Wraps a NATIVE <input> and forwards props. NO `$extends` — the native control\n  plus light DOM is enough for forms; extending a primitive would fight the\n  template-rendered native element. `$shadow: 'light'` so the native <input>\n  joins the outer <form>, and the recipe's class-scoped CSS reaches the global\n  cascade. `aihu add` rewrites the `aihu-` prefix at copy time.\n-->\n\n@state {\n  shadow: 'light'\n\n  let type = prop({ default: 'text' })\n  let placeholder = prop({ default: '' })\n  let name = prop({ default: '' })\n  let value = prop({ default: '' })\n  const ariaLabel = prop({ default: '' })\n  let disabled = prop({ default: false })\n  let required = prop({ default: false })\n}\n\n@template {\n  <input\n    class=\"aihu-input\"\n    type={type}\n    placeholder={placeholder}\n    name={name}\n    value={value}\n    aria-label={ariaLabel}\n    disabled={disabled}\n    required={required} />\n}\n\n@style {\n  .aihu-input {\n    height: 2.25rem;\n    width: 100%;\n    padding: var(--space-1) var(--space-3);\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    line-height: 1.25rem;\n    color: var(--color-foreground);\n    background-color: transparent;\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-md);\n    transition: border-color 0.15s, box-shadow 0.15s;\n  }\n  .aihu-input::placeholder {\n    color: var(--color-muted-foreground);\n  }\n  .aihu-input:focus-visible {\n    outline: none;\n    border-color: var(--color-ring);\n    box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-ring) 35%, transparent);\n  }\n  .aihu-input:disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n  .aihu-input[aria-invalid=\"true\"] {\n    border-color: var(--color-destructive);\n  }\n}\n"
        }
      ],
      "description": "Presentational input recipe — light-DOM custom element wrapping a native <input> that joins the outer form, with token-driven styling.",
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": false,
          "form": true,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "label",
      "type": "ui",
      "files": [
        {
          "path": "registry/label/label.aihu",
          "type": "component",
          "source": "<!--\n  aihu-label — presentational styled recipe (Phase 2, master spec §9.7).\n\n  Wraps a NATIVE <label> and forwards its `for` association. NO `$extends`.\n  `$shadow: 'light'` so the recipe's class-scoped CSS reaches the global cascade.\n  `aihu add` rewrites the `aihu-` prefix at copy time.\n-->\n\n@state {\n  shadow: 'light'\n\n  const htmlFor = prop({ default: '' })\n}\n\n@template {\n  <label class=\"aihu-label\" for={htmlFor}><slot /></label>\n}\n\n@style {\n  .aihu-label {\n    display: inline-flex;\n    align-items: center;\n    gap: var(--space-2);\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    font-weight: 500;\n    line-height: 1;\n    color: var(--color-foreground);\n    user-select: none;\n  }\n  .aihu-label[data-disabled] {\n    opacity: 0.5;\n  }\n}\n"
        }
      ],
      "description": "Presentational label recipe — light-DOM custom element wrapping a native <label> with a forwarded `for` association and token-driven styling.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "hoverable": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "logo-marquee",
      "type": "ui",
      "files": [
        {
          "path": "registry/logo-marquee/logo-marquee.aihu",
          "type": "component",
          "source": "<!--\n  aihu-logo-marquee — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  An infinite horizontal auto-scrolling logo row. CSS-only: a single track\n  animates `translateX(0)` -> `translateX(-50%)` on an infinite loop. Native\n  `<slot>` cannot render the same light-DOM children twice for a seamless\n  duplicate-track loop, so — matching the common upstream marquee pattern —\n  THE CONSUMER IS EXPECTED TO DUPLICATE THEIR OWN LOGO LIST TWICE as children\n  (e.g. render the same 6 `<img>`s back to back, 12 total): at the halfway\n  point (-50%) the second copy is pixel-aligned with where the first started,\n  so the loop reads as continuous. A single, non-duplicated list will visibly\n  jump at the loop boundary.\n\n  The animation pauses on `:hover`/`:focus-within` so a user can read a logo\n  without it sliding away, and honors `prefers-reduced-motion: reduce` (this\n  is a HARD rule for every animated component in this catalog, no exceptions\n  — mirrors status-dot.aihu's reduced-motion idiom exactly).\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n}\n\n@template {\n  <div data-slot=\"logo-marquee\" class={cn('aihu-logo-marquee')}>\n    <div class=\"aihu-logo-marquee-track\">\n      <slot />\n    </div>\n  </div>\n}\n\n@style {\n  .aihu-logo-marquee {\n    display: block;\n    overflow: hidden;\n    -webkit-mask-image: linear-gradient(\n      to right,\n      transparent,\n      black 10%,\n      black 90%,\n      transparent\n    );\n    mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);\n  }\n  .aihu-logo-marquee-track {\n    display: flex;\n    align-items: center;\n    gap: 3rem;\n    width: max-content;\n    animation: aihu-logo-marquee-scroll 24s linear infinite;\n  }\n  .aihu-logo-marquee:hover .aihu-logo-marquee-track,\n  .aihu-logo-marquee:focus-within .aihu-logo-marquee-track {\n    animation-play-state: paused;\n  }\n  @keyframes aihu-logo-marquee-scroll {\n    from {\n      transform: translateX(0);\n    }\n    to {\n      transform: translateX(-50%);\n    }\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .aihu-logo-marquee-track {\n      animation: none;\n    }\n  }\n}\n"
        }
      ],
      "description": "Infinite horizontal auto-scrolling row of logos — CSS-only, pauses on hover/focus and honors reduced motion.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "hoverable": true,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "logo-row",
      "type": "ui",
      "files": [
        {
          "path": "registry/logo-row/logo-row.aihu",
          "type": "component",
          "source": "<!--\n  aihu-logo-row — presentational styled recipe (performativeUI port,\n  Slice 2 — docs/plans/2026-08-01-performative-ui-port.md).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A flex row for partner/press logos — muted+grayscale at rest, full color\n  on hover. Consumers project their own logo images/SVGs as children.\n  `aihu add` rewrites the `aihu-` prefix at copy time.\n\n  align: start (default) | center\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let align = prop({ default: 'start' })\n}\n\n@template {\n  <div data-slot=\"logo-row\" data-align={align} class={cn('aihu-logo-row')}>\n    <slot />\n  </div>\n}\n\n@style {\n  .aihu-logo-row {\n    display: flex;\n    flex-wrap: wrap;\n    align-items: center;\n    gap: 2rem;\n  }\n  .aihu-logo-row[data-align=\"center\"] {\n    justify-content: center;\n  }\n  .aihu-logo-row ::slotted(*) {\n    filter: grayscale(1);\n    opacity: 0.6;\n    transition:\n      filter 0.2s var(--ease-brand),\n      opacity 0.2s var(--ease-brand);\n    max-height: 1.5rem;\n    width: auto;\n  }\n  .aihu-logo-row ::slotted(*:hover) {\n    filter: grayscale(0);\n    opacity: 1;\n  }\n}\n"
        }
      ],
      "description": "Presentational flex row for partner/press logos — muted+grayscale at rest, full color on hover.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false,
          "hoverable": true
        }
      }
    },
    {
      "name": "mock-ide",
      "type": "ui",
      "files": [
        {
          "path": "registry/mock-ide/mock-ide.aihu",
          "type": "component",
          "source": "<!--\n  aihu-mock-ide — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A decorative fake code-editor window: three macOS-style traffic-light dots\n  (pure CSS circles — NOT real window controls, no click handlers, no\n  window-management behavior of any kind) + an optional title bar label + a\n  default slot for the code body. No syntax highlighting — the consumer wraps\n  their own `<pre><code>...</code></pre>` in the default slot.\n\n  title: optional filename/label shown in the title bar, e.g. \"index.ts\".\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let title = prop({ default: '' })\n}\n\n@template {\n  <div data-slot=\"mock-ide\" class={cn('aihu-mock-ide')}>\n    <div class=\"aihu-mock-ide-titlebar\" aria-hidden=\"true\">\n      <span class=\"aihu-mock-ide-dots\">\n        <span class=\"aihu-mock-ide-dot aihu-mock-ide-dot-red\"></span>\n        <span class=\"aihu-mock-ide-dot aihu-mock-ide-dot-yellow\"></span>\n        <span class=\"aihu-mock-ide-dot aihu-mock-ide-dot-green\"></span>\n      </span>\n      <span if={title} class=\"aihu-mock-ide-title\">{title}</span>\n    </div>\n    <div class=\"aihu-mock-ide-body\">\n      <slot />\n    </div>\n  </div>\n}\n\n@style {\n  .aihu-mock-ide {\n    display: block;\n    overflow: hidden;\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-lg);\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n  }\n  .aihu-mock-ide-titlebar {\n    display: flex;\n    align-items: center;\n    gap: 0.75rem;\n    padding: 0.625rem 0.875rem;\n    background-color: color-mix(in oklab, var(--color-foreground) 4%, var(--color-surface));\n    border-bottom: 1px solid var(--color-border);\n  }\n  .aihu-mock-ide-dots {\n    display: inline-flex;\n    gap: 0.4rem;\n    flex: none;\n  }\n  .aihu-mock-ide-dot {\n    width: 0.65rem;\n    height: 0.65rem;\n    border-radius: 9999px;\n  }\n  .aihu-mock-ide-dot-red {\n    background-color: var(--color-destructive);\n  }\n  .aihu-mock-ide-dot-yellow {\n    background-color: var(--color-warning);\n  }\n  .aihu-mock-ide-dot-green {\n    background-color: var(--color-success);\n  }\n  /* `--color-secondary`, not `--color-muted-foreground`: the latter fails\n     WCAG 2 AA for normal text against the tinted titlebar (3.3:1 in\n     aihu-default light). `--color-secondary` holds >=5.4:1 in every\n     pack x mode while reading just as de-emphasized. */\n  .aihu-mock-ide-title {\n    font-family: var(--font-mono);\n    font-size: 0.75rem;\n    color: var(--color-secondary);\n  }\n  .aihu-mock-ide-body {\n    padding: 1rem;\n    font-family: var(--font-mono);\n    font-size: 0.8125rem;\n    line-height: 1.6;\n    overflow-x: auto;\n  }\n}\n"
        }
      ],
      "description": "Decorative fake code-editor window chrome — traffic-light dots + title bar over a slotted code body.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "node-graph-background",
      "type": "ui",
      "files": [
        {
          "path": "registry/node-graph-background/node-graph-background.aihu",
          "type": "component",
          "source": "<!--\n  aihu-node-graph-background — presentational styled recipe (performativeUI\n  port, Slice 10 — docs/plans/2026-08-01-performative-ui-port.md §Tier-C\n  batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md. The upstream\n  demo file was NOT read for this port: the effect below is written from the\n  behavioral description in the slice brief plus the ordinary, widely-known\n  \"particle network\" pattern.\n\n  A decorative animated network/graph background — N small nodes drift across\n  a managed canvas and any two nodes closer than `connection-distance` are\n  joined by a line whose opacity fades to zero as that distance is\n  approached (closer = more opaque).\n\n  ── Architectural note: why this does NOT use `useParticleField` ──────────\n\n  The obvious composition — \"let `useParticleField` (Track B Slice 8) own the\n  N drifting points and just add a line pass on top\" — is not available, and\n  the reason is in that composable's source, not a matter of taste:\n\n    1. `useParticleField` has NO custom-draw hook. `UseParticleFieldOptions`\n       exposes simulation knobs only (count, colors, radii, speed, gravity,\n       pointerAttraction, twinkle, …). There is no `onFrame`/`draw` option\n       and no flag to suppress its own painting: its private `draw()` is\n       hard-wired into the single `onFrame` it hands `useCanvasSurface`, and\n       that `draw()` opens with an unconditional\n       `ctx.clearRect(0, 0, width, height)`. Anything this component painted\n       onto that same surface would be erased at the top of the next frame.\n    2. `particles()` is documented as the live backing array \"exposed for\n       tests and for effects that want to seed or perturb the field directly\"\n       — deliberately NOT reactive, because (its words) \"the canvas IS the\n       render\". It is a state handle, not a render seam.\n    3. So the only compositional route left is a SECOND `useCanvasSurface`\n       for the line layer, reading `particles()` for positions. That buys a\n       second `<canvas>`, a second rAF loop, and a second\n       ResizeObserver/IntersectionObserver pair on one host — and, worse, two\n       independently-scheduled paints: the line layer would render whatever\n       positions the dot layer last integrated, so on any frame the two loops\n       interleave, line endpoints visibly detach from the nodes they connect.\n       Correctness here requires lines and nodes to be painted from ONE\n       snapshot, in ONE frame, in ONE draw call sequence.\n\n  Verdict: option (b) — drop to `useCanvasSurface` directly and hand-roll the\n  minimal node drift. `useCanvasSurface` is explicitly \"the substrate every\n  canvas-based visual effect sits on … future canvas effects are expected to\n  [sit on it] as well\", so this is the sanctioned level to enter at, not a\n  bypass. The duplicated logic is ~25 lines of Euler integration and\n  edge-wrapping; every hard part — canvas ownership, HiDPI backing store,\n  the resize dance that would otherwise feed a ResizeObserver loop, the\n  off-screen pause, the rAF driver, the reduced-motion contract — is still\n  inherited, not re-derived. Nothing is reimplemented that Slice 8 owns.\n\n  ── Props ────────────────────────────────────────────────────────────────\n\n  count:                how many nodes, string-encoded number. Default \"40\".\n                        The pair pass is O(n²) per frame, which is the reason\n                        this default is a few dozen and not a few hundred.\n  color:                the single stroke/fill color for BOTH nodes and their\n                        connecting lines. Default \"#ffffff\". This is a\n                        LITERAL CSS color string, not a `--color-*` token\n                        reference — identical constraint to\n                        `floating-sparkles` (Slice 9): a canvas 2D context's\n                        `fillStyle`/`strokeStyle` is not part of the CSS\n                        cascade and cannot resolve a custom property, so it\n                        needs an already-resolved value.\n  connection-distance:  px threshold under which two nodes are joined,\n                        string-encoded number. Default \"120\". (The prop is\n                        declared `connectionDistance`; the runtime derives\n                        the observed attribute as kebab-case, so consumers\n                        write `connection-distance`.)\n\n  ── Layout ───────────────────────────────────────────────────────────────\n\n  A standalone, full-bleed, absolutely-positioned decorative layer\n  (`position: absolute; inset: 0`), no slot — the same \"decorative background\n  layer\" contract `floating-sparkles` and `aurora` carry, for consistency\n  across the Tier-C batch. The consumer places it as the first child of a\n  `position: relative` ancestor and stacks real content above it with\n  `z-index` (see `useCanvasSurface`'s header: \"the host must be positioned\"\n  for its owned canvas to land at the host's top-left, which\n  `position: absolute` already satisfies).\n\n  ── Reduced motion / off-screen ──────────────────────────────────────────\n\n  Neither is reimplemented here; both are `useCanvasSurface`'s job. Under\n  `prefers-reduced-motion: reduce` that composable's \"paint once, never loop\"\n  contract calls `onFrame` exactly once with `reducedMotion: true` and never\n  arms the rAF loop. `onFrame` below therefore skips `step()` and runs the\n  identical `draw()` — so the frozen frame is a fully-populated graph at\n  rest, nodes AND connections, never a blank box and never in motion.\n  `isVisible`-gated pausing while scrolled off-screen is inherited for free.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let count = prop({ default: '40' })\n  let color = prop({ default: '#ffffff' })\n  let connectionDistance = prop({ default: '120' })\n\n  let hostEl = state(null)\n\n  // Read every prop into a differently-named local before use — an\n  // options-object key textually identical to a prop name trips the\n  // compiler's prop-auto-unwrap rewriter (see token-stream.aihu's header for\n  // the exact failure mode). Snapshotting here also matches the composable\n  // family's convention: attributes are read once at setup, not live.\n  const nodeCount = Math.max(0, Math.floor(Number(count) || 0))\n  const inkColor = color\n  const linkDistance = Math.max(0, Number(connectionDistance) || 0)\n\n  const TAU = Math.PI * 2\n  /** Peak drift speed, px/sec, seeded per node in [-SPEED, SPEED] per axis. */\n  const SPEED = 14\n  const NODE_RADIUS = 2\n  const NODE_ALPHA = 0.85\n  /** Alpha of a connection at zero distance; it fades linearly to 0 at\n   * `linkDistance`. */\n  const LINE_ALPHA = 0.45\n\n  const nodes = []\n  // Mutable scalars live on a const holder rather than as top-level `let`s:\n  // `@state`'s reactive declarations are explicit (`state(...)`), and these\n  // are deliberately plain frame-local bookkeeping that nothing renders from.\n  const seeded = { width: 0, height: 0 }\n\n  const seed = (width, height) => {\n    nodes.length = 0\n    for (let i = 0; i < nodeCount; i++) {\n      nodes.push({\n        x: Math.random() * width,\n        y: Math.random() * height,\n        vx: (Math.random() * 2 - 1) * SPEED,\n        vy: (Math.random() * 2 - 1) * SPEED,\n      })\n    }\n    seeded.width = width\n    seeded.height = height\n  }\n\n  /** Integrate one step. `dt` is SECONDS, clamped for the same reason\n   * `useParticleField` clamps: a backgrounded tab resumes with a multi-second\n   * delta and integrating that unclamped teleports the whole graph away in a\n   * single frame. Nodes WRAP rather than bounce — a bouncing graph reads as\n   * trapped, a wrapping one reads as ambient drift. */\n  const step = (dt, width, height) => {\n    const clamped = dt > 0.05 ? 0.05 : dt\n    for (const n of nodes) {\n      n.x += n.vx * clamped\n      n.y += n.vy * clamped\n      if (n.x < -NODE_RADIUS) n.x += width + NODE_RADIUS * 2\n      else if (n.x > width + NODE_RADIUS) n.x -= width + NODE_RADIUS * 2\n      if (n.y < -NODE_RADIUS) n.y += height + NODE_RADIUS * 2\n      else if (n.y > height + NODE_RADIUS) n.y -= height + NODE_RADIUS * 2\n    }\n  }\n\n  /** Connections first, then nodes, so the dots sit ON TOP of the web rather\n   * than being bisected by every line that terminates on them. */\n  const draw = (ctx, width, height) => {\n    ctx.clearRect(0, 0, width, height)\n\n    if (linkDistance > 0) {\n      const maxSq = linkDistance * linkDistance\n      ctx.strokeStyle = inkColor\n      ctx.lineWidth = 1\n      for (let i = 0; i < nodes.length; i++) {\n        const a = nodes[i]\n        for (let j = i + 1; j < nodes.length; j++) {\n          const b = nodes[j]\n          const dx = a.x - b.x\n          const dy = a.y - b.y\n          const distSq = dx * dx + dy * dy\n          // Compare SQUARED distances to reject the vast majority of pairs\n          // without a sqrt; only survivors pay for the real distance, which\n          // the opacity ramp needs.\n          if (distSq >= maxSq) continue\n          ctx.globalAlpha = LINE_ALPHA * (1 - Math.sqrt(distSq) / linkDistance)\n          ctx.beginPath()\n          ctx.moveTo(a.x, a.y)\n          ctx.lineTo(b.x, b.y)\n          ctx.stroke()\n        }\n      }\n    }\n\n    ctx.globalAlpha = NODE_ALPHA\n    ctx.fillStyle = inkColor\n    for (const n of nodes) {\n      ctx.beginPath()\n      ctx.arc(n.x, n.y, NODE_RADIUS, 0, TAU)\n      ctx.fill()\n    }\n    // Leave the context as we found it — a later `redraw()` must not inherit\n    // the last node's alpha.\n    ctx.globalAlpha = 1\n  }\n\n  /** Re-seed only on the FIRST real size; re-randomizing on every resize tick\n   * would make a window drag look like static. Later sizes rescale\n   * proportionally so no node is stranded outside the new box. */\n  const handleResize = (width, height) => {\n    if (nodes.length === 0) {\n      seed(width, height)\n      return\n    }\n    const sx = seeded.width > 0 ? width / seeded.width : 1\n    const sy = seeded.height > 0 ? height / seeded.height : 1\n    for (const n of nodes) {\n      n.x *= sx\n      n.y *= sy\n    }\n    seeded.width = width\n    seeded.height = height\n  }\n\n  const handleFrame = (frame) => {\n    if (nodes.length === 0) seed(frame.width, frame.height)\n    // The reduced-motion contract: paint the graph, never integrate it.\n    if (!frame.reducedMotion) step(frame.delta / 1000, frame.width, frame.height)\n    draw(frame.ctx, frame.width, frame.height)\n  }\n\n  // Both callbacks are hoisted to named consts rather than written inline as\n  // `onResize: (w, h) => { … }`. An options-object entry whose VALUE is a\n  // multi-line arrow function is mis-parsed by the compiler's @state\n  // macro/prop rewriter — it reads the `key:` as a state-macro declaration\n  // and emits `let onResize: (width, height) => {`, which is not valid TS\n  // (`Expected \"}\" but found \"onResize\"`). Same family of rewriter hazard as\n  // the prop-name/option-key collision documented in token-stream.aihu; the\n  // fix is the same shape — keep the object literal's values to bare\n  // identifiers whose names differ from their keys.\n  useCanvasSurface(() => hostEl, {\n    onResize: handleResize,\n    onFrame: handleFrame,\n  })\n}\n\n@template {\n  <div\n    ref={hostEl}\n    data-slot=\"node-graph-background\"\n    aria-hidden=\"true\"\n    class={cn('aihu-node-graph-background')}></div>\n}\n\n@style {\n  .aihu-node-graph-background {\n    display: block;\n    position: absolute;\n    inset: 0;\n    overflow: hidden;\n    pointer-events: none;\n  }\n}\n"
        }
      ],
      "description": "Decorative animated network background — drifting nodes joined by distance-faded connecting lines on a managed canvas, built on useCanvasSurface.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "popover",
      "type": "ui",
      "files": [
        {
          "path": "registry/popover/popover-content.aihu",
          "type": "component",
          "source": "<!--\n  aihu-popover-content — styled recipe piece (Phase 2, master spec §9.4 / §9.7,\n  performativeUI port Slice 7).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  `<aihu-popover-content>` EXTENDS the headless AihuPopoverContent primitive\n  (`role=\"dialog\"` WITHOUT `aria-modal`, positions against the trigger via the\n  REUSED css-engine `position()` shim, reflects `data-state` /\n  `data-placement`) via the compiler's `$extends:` macro. Light DOM\n  (`$shadow: 'light'`). No side/align variants here — placement positioning is\n  the primitive's job (inline `left`/`top`, read back off `coords`).\n\n  MOTION. The panel animates in/out on by default, same technique as\n  `dialog-content.aihu` (Track A Slice 12): the primitive never unmounts this\n  element (only flips `data-state`), so the closed state uses a delayed\n  `visibility: hidden` rather than `display: none` — no `@starting-style`/\n  `allow-discrete` needed, and the panel stays rendered (and transitionable)\n  for its whole exit.\n\n  DELIBERATELY A SEPARATE `--aihu-anim-popover-*` custom-property family, NOT\n  a reuse of `--aihu-anim-dialog-*`: reusing the dialog family's literal custom\n  properties would let a consumer's `animate-dialog-*` utility class silently\n  retune an unrelated component, and semantically a popover is not a dialog\n  (see the primitive's accessibility.md \"Not a dialog\"). The entrance is also\n  simpler than dialog's four-direction family — fade + zoom only, no directional\n  offset — because `data-placement` is not yet known on the very FIRST open\n  (the primitive sets `data-state=\"open\"` and calls `_position()` in the same\n  synchronous effect, but only the value written before that tick is what the\n  transition animates FROM); a directional slide keyed off `data-placement`\n  would silently do nothing on a component's first open and only start working\n  from its second, which is a worse default than a placement-agnostic fade+zoom\n  that is correct every time.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuPopoverContent } from '@aihu/primitives/popover'\n\n  base: AihuPopoverContent\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-popover-content {\n    position: fixed;\n    z-index: 50;\n    display: flex;\n    flex-direction: column;\n    gap: var(--space-2);\n    min-width: 12rem;\n    max-width: 20rem;\n    padding: var(--space-4);\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-lg);\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n    box-shadow: 0 10px 30px color-mix(in oklab, var(--color-foreground) 20%, transparent);\n    opacity: 1;\n    scale: 1;\n    visibility: visible;\n    will-change: opacity, scale;\n    /* `visibility 0s` is a real slot in the list — see dialog-content.aihu's\n       comment on the same trick. The closed rule below delays exactly that\n       slot so the panel stays rendered (and reachable by its own transition)\n       for the whole fade-out, only then leaving the a11y tree / tab order. */\n    transition:\n      opacity var(--aihu-anim-popover-duration, 180ms) ease,\n      scale var(--aihu-anim-popover-duration, 180ms) var(--aihu-anim-popover-easing, cubic-bezier(0.22, 1, 0.36, 1)),\n      visibility 0s;\n  }\n  aihu-popover-content[data-state=\"closed\"] {\n    opacity: var(--aihu-anim-popover-start-opacity, 0);\n    scale: var(--aihu-anim-popover-start-scale, 0.96);\n    visibility: hidden;\n    pointer-events: none;\n    transition-delay: 0s, 0s, var(--aihu-anim-popover-duration, 180ms);\n  }\n  aihu-popover-content:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  /* Reduced motion is a hard requirement of this port (see status-dot.aihu).\n     The `[data-state=\"closed\"]` arm is load-bearing — without it the closed\n     rule's `transition-delay` would still hold `visibility` for the full\n     duration. */\n  @media (prefers-reduced-motion: reduce) {\n    aihu-popover-content:not([data-motion=\"always\"]),\n    aihu-popover-content[data-state=\"closed\"]:not([data-motion=\"always\"]) {\n      transition-duration: 1ms;\n      transition-delay: 0s;\n    }\n  }\n}\n"
        },
        {
          "path": "registry/popover/popover-root.aihu",
          "type": "component",
          "source": "<!--\n  aihu-popover-root — styled recipe piece (Phase 2, master spec §9.4 / §9.7,\n  performativeUI port Slice 7 — docs/plans/2026-08-01-performative-ui-port.md\n  §Tier-B batch 3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  The state owner of the non-modal popover machine. `<aihu-popover-root>`\n  EXTENDS the headless AihuPopoverRoot primitive (owns `open`/`placement`,\n  provides the popover context, reflects `data-state`, binds the outside-\n  pointerdown dismissal) via the compiler's `$extends:` macro — same shape as\n  `dialog-root`/`tooltip-root`. Light DOM (`$shadow: 'light'`) so descendant\n  pieces inject the context; `display: contents` keeps the root visually\n  transparent.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuPopoverRoot } from '@aihu/primitives/popover'\n\n  base: AihuPopoverRoot\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-popover-root {\n    display: contents;\n  }\n}\n"
        },
        {
          "path": "registry/popover/popover-trigger.aihu",
          "type": "component",
          "source": "<!--\n  aihu-popover-trigger — styled recipe piece (Phase 2, master spec §9.4 / §9.7,\n  performativeUI port Slice 7).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  `<aihu-popover-trigger>` EXTENDS the headless AihuPopoverTrigger primitive\n  (toggles the popover, wires `aria-haspopup=\"dialog\"` / `aria-expanded` /\n  `aria-controls`, Enter/Space activation, Escape-dismiss) via the compiler's\n  `$extends:` macro. Light DOM (`$shadow: 'light'`) so context injection\n  reaches the ancestor root.\n\n  UNLIKE `dialog-trigger` (deliberately unstyled — dialog openers are usually\n  the consumer's own button), the trigger here carries REAL button-shaped\n  styling: a popover is very often invoked from a bare icon or label with no\n  other button around it, so shipping a good default affordance out of the box\n  is the honest default. Styling mirrors `aihu-button`'s `outline` variant\n  (border + background, not the `default` variant's solid primary fill) —\n  a popover disclosure is a secondary action, not a primary CTA.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuPopoverTrigger } from '@aihu/primitives/popover'\n\n  base: AihuPopoverTrigger\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-popover-trigger {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    gap: var(--space-2);\n    height: 2.25rem;\n    padding-inline: 1rem;\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    font-weight: 500;\n    color: var(--color-foreground);\n    background-color: var(--color-background);\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-md);\n    cursor: pointer;\n    user-select: none;\n    transition: background-color 0.15s, border-color 0.15s;\n  }\n  /* MEASURED, not assumed: `--color-accent` (#c8543a) as a SOLID fill\n     against EITHER `--color-accent-foreground` (4.13:1) or `--color-foreground`\n     (3.84:1) fails the 4.5:1 AA floor for this 14px/500-weight label — a real\n     violation caught by `check-storybook-a11y.sh` on the `Open` story (the\n     `[data-state=\"open\"]` rule, not a `:hover` pseudo-class the gate happens\n     to observe). Same 12%-tint-background + 60/40-color-mix-ink formula\n     `eyebrow-pill.aihu`'s `tone=\"accent\"` rule already measured and documents\n     as fixing this exact token's contrast (its header comment: \"accent\n     3.56:1... lifts... to >=5.8:1\"). */\n  aihu-popover-trigger:hover {\n    background-color: color-mix(in oklab, var(--color-accent) 12%, var(--color-background));\n    color: color-mix(in oklab, var(--color-accent) 60%, var(--color-foreground));\n  }\n  aihu-popover-trigger:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  aihu-popover-trigger[data-state=\"open\"] {\n    border-color: var(--color-accent);\n    background-color: color-mix(in oklab, var(--color-accent) 12%, var(--color-background));\n    color: color-mix(in oklab, var(--color-accent) 60%, var(--color-foreground));\n  }\n  aihu-popover-trigger[aria-disabled=\"true\"] {\n    opacity: 0.5;\n    cursor: not-allowed;\n    pointer-events: none;\n  }\n}\n"
        }
      ],
      "description": "Styled non-modal popover recipe — light-DOM pieces extending the headless AihuPopover primitives (disclosure trigger, positioned panel, outside-pointerdown + Escape dismissal, no focus trap).",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": false,
          "overlay": true,
          "trapsFocus": false,
          "directional": false
        }
      }
    },
    {
      "name": "pricing-card",
      "type": "ui",
      "files": [
        {
          "path": "registry/pricing-card/pricing-card.aihu",
          "type": "component",
          "source": "<!--\n  aihu-pricing-card — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A pricing tier card. Default slot holds the consumer's own feature list\n  (`<ul>/<li>`) — this recipe renders no list markup of its own.\n\n  tier:     tier name, e.g. \"Pro\".\n  price:    price string, e.g. \"$29\".\n  period:   billing period suffix, e.g. \"/mo\". Default \"\" (one-time/no suffix).\n  featured: off (default) | on — accent border + elevation via\n            --color-primary when \"on\".\n  (`featured`'s variant matrix is the registry catalog contract — see\n  meta.json — reflected as data-featured and matched in @style below.)\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let tier = prop({ default: 'Pro' })\n  let price = prop({ default: '$0' })\n  let period = prop({ default: '' })\n  let featured = prop({ default: 'off' })\n}\n\n@template {\n  <div data-slot=\"pricing-card\" data-featured={featured} class={cn('aihu-pricing-card')}>\n    <p class=\"aihu-pricing-card-tier\">{tier}</p>\n    <p class=\"aihu-pricing-card-price\">\n      {price}<span if={period} class=\"aihu-pricing-card-period\">{period}</span>\n    </p>\n    <div class=\"aihu-pricing-card-features\">\n      <slot />\n    </div>\n  </div>\n}\n\n@style {\n  .aihu-pricing-card {\n    display: flex;\n    flex-direction: column;\n    gap: 1rem;\n    padding: 1.5rem;\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-lg);\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n  }\n  .aihu-pricing-card[data-featured=\"on\"] {\n    border-color: var(--color-primary);\n    box-shadow: 0 0 0 1px var(--color-primary), 0 10px 30px color-mix(in oklab, var(--color-primary) 25%, transparent);\n  }\n  /* `--color-secondary`, not `--color-muted-foreground`, on both the tier\n     label and the price period: the latter fails WCAG 2 AA for normal text\n     on `--color-surface` (3.35:1 aihu-default light, 3.06:1 dark).\n     `--color-secondary` stays de-emphasized at >=5.9:1 in every\n     pack x mode. */\n  .aihu-pricing-card-tier {\n    margin: 0;\n    font-size: 0.875rem;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: 0.02em;\n    color: var(--color-secondary);\n  }\n  .aihu-pricing-card[data-featured=\"on\"] .aihu-pricing-card-tier {\n    color: var(--color-primary);\n  }\n  .aihu-pricing-card-price {\n    margin: 0;\n    font-size: 2.25rem;\n    font-weight: 700;\n    line-height: 1;\n  }\n  .aihu-pricing-card-period {\n    margin-left: 0.25rem;\n    font-size: 1rem;\n    font-weight: 400;\n    color: var(--color-secondary);\n  }\n  .aihu-pricing-card-features {\n    font-size: 0.875rem;\n    color: var(--color-surface-foreground);\n  }\n}\n"
        }
      ],
      "description": "Pricing tier card — tier/price/period, an optional featured accent border/elevation, and a default slot for the consumer's feature list.",
      "variants": {
        "featured": ["off", "on"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "prompt",
      "type": "ui",
      "files": [
        {
          "path": "registry/prompt/prompt.aihu",
          "type": "component",
          "source": "<!--\n  aihu-prompt — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  DELIBERATELY NOT A REAL FORM INPUT — this is the \"AI prompt bar\" LOOK for\n  marketing surfaces (hero sections, feature callouts), not a functioning\n  text field. `placeholder` renders as a literal muted-colored `<span>`, not\n  an editable `<input>`/`<textarea>` value. A consumer who needs a real,\n  submittable prompt field should compose `@aihu/primitives/input` (or\n  `@aihu/primitives/textarea`) themselves — wiring a real headless input into\n  this look is explicitly out of scope for this presentational recipe, to\n  avoid the a11y/form-participation surface area a fake-looking-real input\n  would otherwise obligate.\n\n  placeholder: literal text shown in the pill, e.g. \"Ask anything...\".\n  `<slot name=\"icon\">` — optional leading decorative icon/element.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let placeholder = prop({ default: 'Ask anything...' })\n}\n\n@template {\n  <div data-slot=\"prompt\" class={cn('aihu-prompt')}>\n    <span class=\"aihu-prompt-icon\" aria-hidden=\"true\">\n      <slot name=\"icon\">\n        <span class=\"aihu-prompt-dot\"></span>\n      </slot>\n    </span>\n    <span class=\"aihu-prompt-placeholder\">{placeholder}</span>\n  </div>\n}\n\n@style {\n  .aihu-prompt {\n    display: inline-flex;\n    align-items: center;\n    gap: 0.625rem;\n    width: 100%;\n    max-width: 28rem;\n    padding: 0.75rem 1.125rem;\n    border-radius: var(--radius-pill);\n    border: 1px solid var(--color-border);\n    background-color: var(--color-surface);\n  }\n  .aihu-prompt-icon {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    flex: none;\n  }\n  .aihu-prompt-dot {\n    display: inline-block;\n    width: 0.5rem;\n    height: 0.5rem;\n    border-radius: 9999px;\n    background-color: var(--color-accent);\n  }\n  /* `--color-secondary`, not `--color-muted-foreground`: the latter is the\n     pack's lowest-contrast text token (3.35:1 on `--color-surface` in\n     aihu-default light, 3.06:1 dark) and fails WCAG 2 AA for normal text.\n     `--color-secondary` keeps the de-emphasized look at 5.9:1 or better in\n     every pack x mode. */\n  .aihu-prompt-placeholder {\n    font-size: 0.875rem;\n    color: var(--color-secondary);\n  }\n}\n"
        }
      ],
      "description": "Presentational single-line AI-prompt-bar look — a rounded pill with a leading icon slot and a placeholder text span; not a real form input.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "prompt-hero",
      "type": "ui",
      "files": [
        {
          "path": "registry/prompt-hero/prompt-hero.aihu",
          "type": "component",
          "source": "<!--\n  aihu-prompt-hero — presentational styled recipe (performativeUI port,\n  Slice 5 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 2).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A larger hero variant: a gradient-text heading centered above a `prompt`\n  bar. Composes TWO other registry recipes as children in its default\n  template — `aihu-gradient-text` for the heading, `aihu-prompt` for the bar\n  — exercising `registryDependencies` on both (see meta.json), the same\n  pattern `eyebrow-pill` established on `status-dot` in Slice 1.\n\n  heading:     the hero heading text, rendered through <aihu-gradient-text>.\n  placeholder: forwarded to the nested <aihu-prompt>'s `placeholder`.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let heading = prop({ default: 'Ask anything' })\n  let placeholder = prop({ default: 'Ask anything...' })\n}\n\n@template {\n  <div data-slot=\"prompt-hero\" class={cn('aihu-prompt-hero')}>\n    <aihu-gradient-text weight=\"bold\" class=\"aihu-prompt-hero-heading\">\n      {heading}\n    </aihu-gradient-text>\n    <aihu-prompt placeholder={placeholder}></aihu-prompt>\n  </div>\n}\n\n@style {\n  .aihu-prompt-hero {\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    gap: 1.5rem;\n    text-align: center;\n  }\n  .aihu-prompt-hero-heading {\n    font-size: clamp(1.75rem, 4vw, 3rem);\n    line-height: 1.1;\n  }\n}\n"
        }
      ],
      "description": "Larger hero variant composing gradient-text (heading) above a prompt bar, centered layout.",
      "registryDependencies": ["gradient-text", "prompt"],
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "quest-text",
      "type": "ui",
      "files": [
        {
          "path": "registry/quest-text/quest-text.aihu",
          "type": "component",
          "source": "<!--\n  aihu-quest-text — presentational styled recipe (performativeUI port,\n  Slice 2 — docs/plans/2026-08-01-performative-ui-port.md).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  Emphasized inline text treatment for prompts/callouts — an underline-style\n  accent rule beneath the text plus an optional blinking caret, evoking an\n  \"ask me anything\" prompt affordance. `aihu add` rewrites the `aihu-`\n  prefix at copy time.\n\n  tone:  neutral (default) | accent\n  caret: off (default) | on\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let tone = prop({ default: 'neutral' })\n  let caret = prop({ default: 'off' })\n}\n\n@template {\n  <span data-slot=\"quest-text\" data-tone={tone} data-caret={caret} class={cn('aihu-quest-text')}>\n    <slot />\n  </span>\n}\n\n@style {\n  .aihu-quest-text {\n    display: inline;\n    position: relative;\n    font-weight: 500;\n    padding-bottom: 0.125rem;\n    background-image: linear-gradient(to right, currentColor, currentColor);\n    background-repeat: no-repeat;\n    background-position: 0 100%;\n    background-size: 100% 2px;\n    color: var(--color-foreground);\n  }\n  .aihu-quest-text[data-tone=\"accent\"] {\n    color: var(--color-accent);\n  }\n  .aihu-quest-text[data-caret=\"on\"]::after {\n    content: \"\";\n    display: inline-block;\n    width: 0.5em;\n    height: 1em;\n    margin-inline-start: 0.125em;\n    vertical-align: text-bottom;\n    background-color: currentColor;\n    animation: aihu-quest-text-caret 1s steps(1) infinite;\n  }\n  @keyframes aihu-quest-text-caret {\n    0%,\n    49% {\n      opacity: 1;\n    }\n    50%,\n    100% {\n      opacity: 0;\n    }\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .aihu-quest-text[data-caret=\"on\"]::after {\n      animation: none;\n      opacity: 1;\n    }\n  }\n}\n"
        }
      ],
      "description": "Presentational inline text emphasis for prompts/callouts — underline accent with an optional blinking caret.",
      "variants": {
        "tone": ["neutral", "accent"],
        "caret": ["off", "on"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "rotator",
      "type": "ui",
      "files": [
        {
          "path": "registry/rotator/rotator.aihu",
          "type": "component",
          "source": "<!--\n  aihu-rotator — presentational styled recipe (performativeUI port,\n  Slice 4 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A rotating single-word/phrase headline slot — cycles through `items` on a\n  fixed interval, cross-fading each change. Built on `@aihu/use/motion`'s\n  `useSequence` (Track B Slice 3) rather than a hand-rolled interval.\n\n  items:    comma-separated string, e.g. \"Design,Build,Ship\" (custom-element\n            attrs are strings — read once at setup, not reactive to later\n            attribute changes, same constraint as every array-valued prop in\n            this port).\n  interval: milliseconds per word, string-encoded number. Default \"2000\".\n  tone:     neutral (default) | accent\n\n  `shadow: 'light'` for live retheming — see the parent execution plan's\n  theming decision.\n\n  The `<group each key>` wrapper forces a fresh DOM node per cycle (`key`\n  changes -> re-mount), which is what makes the `animate-fade-in` utility\n  class (tailwind-animations port, Track A) restart on every word change\n  instead of playing once and going static.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let items = prop({ default: 'Design,Build,Ship' })\n  let interval = prop({ default: '2000' })\n  let tone = prop({ default: 'neutral' })\n\n  const words = items\n    .split(',')\n    .map((w) => w.trim())\n    .filter(Boolean)\n\n  const { current, index } = useSequence(words, { interval: Number(interval) })\n}\n\n@template {\n  <span data-slot=\"rotator\" data-tone={tone} class={cn('aihu-rotator')}>\n    <group each={item of [current()]} key={index()}>\n      <span class={cn('aihu-rotator-word', 'animate-fade-in')}>{item}</span>\n    </group>\n  </span>\n}\n\n@style {\n  .aihu-rotator {\n    display: inline-block;\n    position: relative;\n    font-weight: 600;\n    color: var(--color-foreground);\n  }\n  /* Raw `--color-accent` is only 4.14:1 on `--color-background` in\n     aihu-default light — under the 4.5:1 WCAG 2 AA floor for this\n     normal-weight (600) word. Mixing 30% `--color-foreground` into it keeps\n     the accent hue while lifting every pack x mode to >=6.4:1. */\n  .aihu-rotator[data-tone=\"accent\"] {\n    color: color-mix(in oklab, var(--color-accent) 70%, var(--color-foreground));\n  }\n  .aihu-rotator-word {\n    display: inline-block;\n  }\n}\n"
        }
      ],
      "description": "Presentational rotating headline word/phrase — cycles through a comma-separated item list on a fixed interval, cross-fading each change.",
      "variants": {
        "tone": ["neutral", "accent"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "separator",
      "type": "ui",
      "files": [
        {
          "path": "registry/separator/separator.aihu",
          "type": "component",
          "source": "<!--\n  aihu-separator — presentational styled recipe (Plan 5 Task 5, master spec §9.7).\n\n  Standalone styled custom element — NO primitive import. A 1px token-colored\n  rule. Reflects an `orientation` attribute (horizontal | vertical), exposes\n  `role=\"separator\"` + `aria-orientation`. `aihu add` rewrites the `aihu-`\n  prefix at copy time.\n\n  orientation: horizontal (default) | vertical\n\n  CSS attachment (R2): the compiled `@style` block below IS the shared\n  Constructable StyleSheet — see `card.aihu`'s header. A recipe writes no\n  registration and no `adoptedStyleSheets` code of its own.\n\n  ARIA lives on the TEMPLATE element, not the host. `role=\"separator\"` +\n  `aria-orientation` are authored on the rendered `[data-slot=\"separator\"]`\n  div, which is inside the shadow root and therefore in the accessibility tree.\n  This recipe deliberately does NOT `$extends:` the headless `AihuSeparator`\n  from `@aihu/primitives/separator` — that primitive puts the role on the HOST\n  and renders nothing, which is a different (also valid) shape. Consumers who\n  want the host-as-separator shape should use the primitive directly.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  let orientation = prop({ default: 'horizontal' })\n}\n\n@template {\n  <div\n    data-slot=\"separator\"\n    role=\"separator\"\n    aria-orientation={orientation}\n    data-orientation={orientation}\n    class={cn('aihu-separator')}></div>\n}\n\n@style {\n  .aihu-separator {\n    display: block;\n    background-color: var(--color-border);\n    flex-shrink: 0;\n  }\n  .aihu-separator[data-orientation=\"horizontal\"] {\n    height: 1px;\n    width: 100%;\n  }\n  .aihu-separator[data-orientation=\"vertical\"] {\n    width: 1px;\n    height: 100%;\n  }\n}\n"
        }
      ],
      "description": "Presentational separator recipe — token-colored 1px rule with role=separator + aria-orientation.",
      "variants": {
        "orientation": ["horizontal", "vertical"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "slippy-words",
      "type": "ui",
      "files": [
        {
          "path": "registry/slippy-words/slippy-words.aihu",
          "type": "component",
          "source": "<!--\n  aihu-slippy-words — presentational styled recipe (performativeUI port,\n  Slice 4 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A static sentence where exactly one word \"wiggles\" for attention at a\n  time, the highlighted word advancing left to right, looping. Built on\n  `@aihu/use/motion`'s `useSequence` cycling over word INDICES (not the\n  words themselves) — every word stays mounted the whole time, so this\n  needs no keyed re-mount trick (unlike `aihu-rotator`/`aihu-word-roll`).\n  What restarts the ported `animate-jiggle` utility (tailwind-animations\n  port, Track A) each pass is `cn()` adding/removing the CLASS on the\n  active word's `class` binding below — `data-active` is plain state for\n  the `@style` selector, it carries no animation itself.\n\n  text:     space-separated sentence, e.g. \"Ship it before you overthink\n            it\". Read once at setup (custom-element attrs are strings, not\n            reactive to later attribute changes).\n  interval: milliseconds per word, string-encoded number. Default \"600\".\n  tone:     neutral (default) | accent — the active word's highlight color.\n\n  `shadow: 'light'` for live retheming — see the parent execution plan's\n  theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let text = prop({ default: 'Ship it before you overthink it' })\n  let interval = prop({ default: '600' })\n  let tone = prop({ default: 'neutral' })\n\n  const words = text.split(' ').filter(Boolean)\n  // Carries its own index rather than relying on `each`'s idx alias — the\n  // compiler's key-expr closure only binds the item alias, not the idx\n  // alias (`key={idx}` compiles to `(item) => idx`, an out-of-scope read).\n  // Folding the index into the item itself keeps `key` single-alias, the\n  // supported shape (see `each={item, idx of items} key={item.id}` in the\n  // compiler's own test fixtures).\n  const indexedWords = words.map((word, i) => ({ word, i }))\n\n  const { current: activeIndex } = useSequence(\n    words.map((_, i) => i),\n    { interval: Number(interval) },\n  )\n}\n\n@template {\n  <span data-slot=\"slippy-words\" data-tone={tone} class={cn('aihu-slippy-words')}>\n    <group each={entry of indexedWords} key={entry.i}>\n      <span\n        data-active={entry.i === activeIndex() ? 'on' : 'off'}\n        class={cn('aihu-slippy-word', entry.i === activeIndex() && 'animate-jiggle')}>\n        {entry.word}\n      </span>\n    </group>\n  </span>\n}\n\n@style {\n  .aihu-slippy-words {\n    display: inline-flex;\n    flex-wrap: wrap;\n    gap: 0.3em;\n    font-weight: 600;\n    color: var(--color-foreground);\n  }\n  .aihu-slippy-word {\n    display: inline-block;\n    transform-origin: 50% 100%;\n  }\n  .aihu-slippy-word[data-active=\"on\"] {\n    color: var(--color-neutral);\n  }\n  /* Raw `--color-accent` is only 4.14:1 on `--color-background` in\n     aihu-default light — under the 4.5:1 WCAG 2 AA floor for this\n     normal-weight (600) word. Mixing 30% `--color-foreground` into it keeps\n     the accent hue while lifting every pack x mode to >=6.4:1. */\n  .aihu-slippy-words[data-tone=\"accent\"] .aihu-slippy-word[data-active=\"on\"] {\n    color: color-mix(in oklab, var(--color-accent) 70%, var(--color-foreground));\n  }\n}\n"
        }
      ],
      "description": "Presentational sentence where one word wiggles for attention at a time, the highlight advancing left to right, looping.",
      "variants": {
        "tone": ["neutral", "accent"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "sparkle",
      "type": "ui",
      "files": [
        {
          "path": "registry/sparkle/sparkle.aihu",
          "type": "component",
          "source": "<!--\n  aihu-sparkle — presentational styled recipe (performativeUI port,\n  Slice 2 — docs/plans/2026-08-01-performative-ui-port.md).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A small decorative four-pointed accent mark, drawn in CSS (no icon font/\n  SVG import). Optional shimmer. `aihu add` rewrites the `aihu-` prefix at\n  copy time.\n\n  size:   sm | md (default) | lg\n  tone:   neutral (default) | accent\n  shimmer: off (default) | on\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let size = prop({ default: 'md' })\n  let tone = prop({ default: 'neutral' })\n  let shimmer = prop({ default: 'off' })\n}\n\n@template {\n  <span\n    data-slot=\"sparkle\"\n    data-size={size}\n    data-tone={tone}\n    data-shimmer={shimmer}\n    aria-hidden=\"true\"\n    class={cn('aihu-sparkle')}></span>\n}\n\n@style {\n  .aihu-sparkle {\n    display: inline-block;\n    flex: none;\n    color: var(--color-neutral);\n    /* Four-pointed star, drawn with a conic gradient mask — no SVG asset. */\n    background-color: currentColor;\n    -webkit-mask-image: conic-gradient(\n      from 0deg,\n      transparent 0deg 40deg,\n      currentColor 40deg 50deg,\n      transparent 50deg 130deg,\n      currentColor 130deg 140deg,\n      transparent 140deg 220deg,\n      currentColor 220deg 230deg,\n      transparent 230deg 310deg,\n      currentColor 310deg 320deg,\n      transparent 320deg 360deg\n    );\n    mask-image: conic-gradient(\n      from 0deg,\n      transparent 0deg 40deg,\n      currentColor 40deg 50deg,\n      transparent 50deg 130deg,\n      currentColor 130deg 140deg,\n      transparent 140deg 220deg,\n      currentColor 220deg 230deg,\n      transparent 230deg 310deg,\n      currentColor 310deg 320deg,\n      transparent 320deg 360deg\n    );\n  }\n  .aihu-sparkle[data-size=\"sm\"] {\n    width: 0.625rem;\n    height: 0.625rem;\n  }\n  .aihu-sparkle[data-size=\"md\"] {\n    width: 1rem;\n    height: 1rem;\n  }\n  .aihu-sparkle[data-size=\"lg\"] {\n    width: 1.5rem;\n    height: 1.5rem;\n  }\n  .aihu-sparkle[data-tone=\"accent\"] {\n    color: var(--color-accent);\n  }\n  .aihu-sparkle[data-shimmer=\"on\"] {\n    animation: aihu-sparkle-shimmer 1.6s var(--ease-brand) infinite;\n  }\n  @keyframes aihu-sparkle-shimmer {\n    0%,\n    100% {\n      opacity: 0.5;\n      transform: scale(0.85);\n    }\n    50% {\n      opacity: 1;\n      transform: scale(1.05);\n    }\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .aihu-sparkle[data-shimmer=\"on\"] {\n      animation: none;\n    }\n  }\n}\n"
        }
      ],
      "description": "Presentational decorative accent mark — a four-pointed star with an optional shimmer.",
      "variants": {
        "size": ["sm", "md", "lg"],
        "tone": ["neutral", "accent"],
        "shimmer": ["off", "on"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "stat-counter",
      "type": "ui",
      "files": [
        {
          "path": "registry/stat-counter/stat-counter.aihu",
          "type": "component",
          "source": "<!--\n  aihu-stat-counter — presentational styled recipe (performativeUI port,\n  Slice 4 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A number that counts up to `to` the first time it scrolls into view —\n  built on `@aihu/use/motion`'s `useCountTo` (Track B Slice 3) gated by the\n  pre-existing `useIntersectionObserver` (CORE @aihu/use), per the roadmap's\n  explicit instruction: fire on scroll-in, not on mount. `ref={hostEl}`\n  feeds the observed element; the observer permanently `stop()`s itself\n  after the first intersection — this counts up exactly once, it does not\n  re-trigger on scroll-out/scroll-back-in.\n\n  to:       target value, string-encoded number. Default \"100\".\n  from:     starting value, string-encoded number. Default \"0\".\n  duration: tween duration in ms, string-encoded number. Default \"1200\".\n  label:    optional caption below the number.\n  prefix / suffix: optional strings around the number (e.g. prefix=\"$\",\n            suffix=\"%\" or suffix=\"+\").\n\n  `shadow: 'light'` for live retheming — see the parent execution plan's\n  theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let to = prop({ default: '100' })\n  let from = prop({ default: '0' })\n  let duration = prop({ default: '1200' })\n  let label = prop({ default: '' })\n  let prefix = prop({ default: '' })\n  let suffix = prop({ default: '' })\n\n  let hostEl = state(null)\n\n  const { value, start } = useCountTo({ from: Number(from), duration: Number(duration) })\n\n  const { stop } = useIntersectionObserver(\n    () => hostEl,\n    (entries) => {\n      if (entries.some((entry) => entry.isIntersecting)) {\n        start(Number(to))\n        stop()\n      }\n    },\n    { threshold: 0.4 },\n  )\n}\n\n@template {\n  <span ref={hostEl} data-slot=\"stat-counter\" class={cn('aihu-stat-counter')}>\n    <span class=\"aihu-stat-counter-value\">{prefix}{value()}{suffix}</span>\n    <span if={label} class=\"aihu-stat-counter-label\">{label}</span>\n  </span>\n}\n\n@style {\n  .aihu-stat-counter {\n    display: inline-flex;\n    flex-direction: column;\n    align-items: flex-start;\n    gap: 0.15rem;\n  }\n  .aihu-stat-counter-value {\n    font-family: var(--font-sans);\n    font-weight: 700;\n    font-size: 2.25rem;\n    line-height: 1;\n    color: var(--color-foreground);\n    font-variant-numeric: tabular-nums;\n  }\n  /* `--color-muted-foreground` is the packs' lowest-contrast text token and\n     fails AA for normal text here (3.35:1 light / 3.06:1 dark on\n     `--color-surface` in aihu-default). Swapped to `--color-secondary`\n     (>=5.4:1 everywhere), matching the fix already applied to\n     .aihu-prompt-placeholder / .aihu-mock-ide-title / .aihu-pricing-card\n     tier+period. */\n  .aihu-stat-counter-label {\n    font-size: 0.875rem;\n    color: var(--color-secondary);\n  }\n}\n"
        }
      ],
      "description": "Presentational number that counts up to a target the first time it scrolls into view.",
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "status-dot",
      "type": "ui",
      "files": [
        {
          "path": "registry/status-dot/status-dot.aihu",
          "type": "component",
          "source": "<!--\n  aihu-status-dot — presentational styled recipe (performativeUI port,\n  Slice 1 — docs/plans/2026-08-01-performative-ui-port.md §3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A small circular status indicator whose fill communicates a semantic state,\n  with an optional pulsing \"liveness\" ring. `aihu add` rewrites the `aihu-`\n  prefix at copy time.\n\n  status: neutral (default) | online | busy | away | info | offline\n  size:   sm | md (default) | lg\n  pulse:  off (default) | on\n  (Variant matrix is the registry catalog contract — see meta.json — reflected\n  as data-status/data-size/data-pulse and matched in @style below.)\n\n  `shadow: 'light'` (not true shadow DOM, unlike the older badge/separator\n  shape): this component's --color-* token references retheme live against\n  runtime dark-mode/theme-catalog switching, per the light-DOM token-scope\n  guarantee (@layer aihu.tokens at :root always outranks a stale per-component\n  :host snapshot). See the parent execution plan's theming decision.\n\n  `role=\"img\"` needs an accessible name (WCAG 1.1.1) — with the default empty\n  `label` (the shape every composed usage in `eyebrow-pill`/`community-badge`\n  uses today, pairing the dot with adjacent visible text instead) this dot has\n  none. `aria-hidden` tracks whether `label` is non-empty: when it's empty the\n  dot drops out of the accessibility tree entirely (matching `sparkle`'s\n  decorative-by-default pattern), so `role=\"img\"`/`aria-label=\"\"` are never\n  exposed to assistive tech in the first place — the compiler's attribute\n  binding always calls `setAttribute` (no removal path for `undefined`), so\n  conditionally OMITTING `role`/`aria-label` isn't an option here; gating\n  exposure via `aria-hidden` is.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let status = prop({ default: 'neutral' })\n  let size = prop({ default: 'md' })\n  let pulse = prop({ default: 'off' })\n  let label = prop({ default: '' })\n}\n\n@template {\n  <span\n    data-slot=\"status-dot\"\n    data-status={status}\n    data-size={size}\n    data-pulse={pulse}\n    role=\"img\"\n    aria-label={label}\n    aria-hidden={label ? 'false' : 'true'}\n    class={cn('aihu-status-dot')}>\n    <span class=\"aihu-status-dot-ring\" aria-hidden=\"true\"></span>\n  </span>\n}\n\n@style {\n  .aihu-status-dot {\n    display: inline-block;\n    position: relative;\n    flex: none;\n    border-radius: var(--radius-pill);\n    color: var(--color-neutral);\n    background-color: currentColor;\n  }\n  .aihu-status-dot[data-size=\"sm\"] {\n    width: 0.375rem;\n    height: 0.375rem;\n  }\n  .aihu-status-dot[data-size=\"md\"] {\n    width: 0.5rem;\n    height: 0.5rem;\n  }\n  .aihu-status-dot[data-size=\"lg\"] {\n    width: 0.625rem;\n    height: 0.625rem;\n  }\n  .aihu-status-dot[data-status=\"neutral\"] {\n    color: var(--color-neutral);\n  }\n  .aihu-status-dot[data-status=\"online\"] {\n    color: var(--color-success);\n  }\n  .aihu-status-dot[data-status=\"busy\"] {\n    color: var(--color-destructive);\n  }\n  .aihu-status-dot[data-status=\"away\"] {\n    color: var(--color-warning);\n  }\n  .aihu-status-dot[data-status=\"info\"] {\n    color: var(--color-info);\n  }\n  .aihu-status-dot[data-status=\"offline\"] {\n    color: var(--color-muted-foreground);\n  }\n  .aihu-status-dot-ring {\n    position: absolute;\n    inset: 0;\n    border-radius: var(--radius-pill);\n    background-color: currentColor;\n    opacity: 0;\n    pointer-events: none;\n  }\n  .aihu-status-dot[data-pulse=\"on\"] .aihu-status-dot-ring {\n    animation: aihu-status-dot-pulse 1.8s var(--ease-brand) infinite;\n  }\n  @keyframes aihu-status-dot-pulse {\n    from {\n      transform: scale(1);\n      opacity: 0.55;\n    }\n    to {\n      transform: scale(2.6);\n      opacity: 0;\n    }\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .aihu-status-dot[data-pulse=\"on\"] .aihu-status-dot-ring {\n      animation: none;\n    }\n  }\n}\n"
        }
      ],
      "description": "Presentational status indicator — a semantic-colored dot with an optional pulsing liveness ring.",
      "variants": {
        "status": ["neutral", "online", "busy", "away", "info", "offline"],
        "size": ["sm", "md", "lg"],
        "pulse": ["off", "on"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "sticky-banner",
      "type": "ui",
      "files": [
        {
          "path": "registry/sticky-banner/sticky-banner.aihu",
          "type": "component",
          "source": "<!--\n  aihu-sticky-banner — presentational styled recipe (performativeUI port,\n  Slice 2 — docs/plans/2026-08-01-performative-ui-port.md).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A full-width announcement bar. Presentational-only in this slice — no\n  dismiss affordance (if one is added later this becomes a Tier-B/Phase-2\n  component per the roadmap's authoring-pattern rule). `aihu add` rewrites\n  the `aihu-` prefix at copy time.\n\n  tone: neutral (default) | accent | warning\n\n  `shadow: 'light'` — see status-dot.aihu's header for why.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let tone = prop({ default: 'neutral' })\n}\n\n@template {\n  <div data-slot=\"sticky-banner\" data-tone={tone} class={cn('aihu-sticky-banner')}>\n    <slot />\n  </div>\n}\n\n@style {\n  .aihu-sticky-banner {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 0.5rem;\n    width: 100%;\n    padding-block: 0.5rem;\n    padding-inline: 1rem;\n    font-size: 0.875rem;\n    font-weight: 500;\n    text-align: center;\n    background-color: var(--color-neutral);\n    color: var(--color-neutral-foreground);\n  }\n  /* `--color-accent-foreground` on raw `--color-accent` is only 4.14:1 in\n     aihu-default light — under the 4.5:1 WCAG 2 AA floor for this 0.875rem\n     banner text. Deepening the fill with 20% `--color-foreground` keeps the\n     accent read and lifts every pack x mode to >=5.5:1. */\n  .aihu-sticky-banner[data-tone=\"accent\"] {\n    background-color: color-mix(in oklab, var(--color-accent) 80%, var(--color-foreground));\n    color: var(--color-accent-foreground);\n  }\n  .aihu-sticky-banner[data-tone=\"warning\"] {\n    background-color: var(--color-warning);\n    color: var(--color-warning-foreground);\n  }\n}\n"
        }
      ],
      "description": "Presentational full-width announcement bar. No dismiss affordance in this slice.",
      "variants": {
        "tone": ["neutral", "accent", "warning"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "switch",
      "type": "ui",
      "files": [
        {
          "path": "registry/switch/switch.aihu",
          "type": "component",
          "source": "<!--\n  aihu-switch — styled recipe (Phase 2, master spec §9.4 / §9.7).\n\n  The LIGHT-DOM class-extension recipe: the registered `<aihu-switch>` element\n  EXTENDS the headless `AihuSwitchRoot` primitive (role=switch, binary\n  aria-checked, Space/Enter toggle, form participation via a sibling hidden\n  input) via the compiler's `$extends:` macro, so the host inherits all\n  behavior. The host renders in LIGHT DOM (`$shadow: 'light'`) so the hidden\n  input joins the outer <form> and the recipe's tag/class-scoped CSS reaches\n  the global cascade.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n  No `$prop` is declared: AihuSwitchRoot owns every attribute\n  (checked / disabled / required / name / value), surfaced via the runtime's\n  unioned observedAttributes.\n-->\n\n@state {\n  import { AihuSwitchRoot } from '@aihu/primitives/switch'\n\n  base: AihuSwitchRoot\n  shadow: 'light'\n}\n\n@template {\n  <span class=\"aihu-switch-thumb\" part=\"thumb\" aria-hidden=\"true\"></span>\n}\n\n@style {\n  aihu-switch {\n    display: inline-flex;\n    align-items: center;\n    width: 2rem;\n    height: 1.15rem;\n    padding: 2px;\n    border-radius: var(--radius-pill);\n    background-color: var(--color-border);\n    cursor: pointer;\n    transition: background-color 0.15s;\n  }\n  aihu-switch:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  aihu-switch[data-state=\"unchecked\"] {\n    background-color: var(--color-border);\n  }\n  aihu-switch[data-state=\"checked\"] {\n    background-color: var(--color-primary);\n  }\n  aihu-switch[data-disabled] {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n  aihu-switch[aria-invalid=\"true\"] {\n    outline: 2px solid var(--color-destructive);\n    outline-offset: 2px;\n  }\n\n  .aihu-switch-thumb {\n    width: 0.85rem;\n    height: 0.85rem;\n    border-radius: var(--radius-pill);\n    background-color: var(--color-background);\n    transition: transform 0.15s;\n  }\n  aihu-switch[data-state=\"checked\"] .aihu-switch-thumb {\n    transform: translateX(0.85rem);\n  }\n}\n"
        }
      ],
      "description": "Styled switch recipe — light-DOM element extending the headless AihuSwitchRoot primitive (binary toggle, Space/Enter activation, native form participation).",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": true,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "temperature",
      "type": "ui",
      "files": [
        {
          "path": "registry/temperature/temperature.aihu",
          "type": "component",
          "source": "<!--\n  aihu-temperature — styled recipe (Phase 2, performativeUI port Slice 7 —\n  docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  An AI-marketing \"response temperature\" segmented preset picker — three\n  fixed values (Precise / Balanced / Creative), not a literal range input.\n\n  DESIGN DECISION (roadmap: \"builds on existing roving-focus + collection, no\n  new menu primitive needed\"): read as option (a) — a single-select group of\n  buttons is *exactly* what `AihuRadioGroupRoot` already is (itself built on\n  `roving-focus` + `collection`, per that primitive's own header comment), so\n  `<aihu-temperature>` EXTENDS it directly via the compiler's `$extends:`\n  macro, the same \"IS its primitive\" shape `switch.aihu`/`checkbox.aihu` use —\n  no popover, no new menu primitive, no dropdown. The fixed three items are\n  NOT a `<slot>`-composed, consumer-supplied list (this is deliberately a\n  3-value PRESET control, not a general-purpose radio group recipe — see the\n  roadmap's \"keep it a 3-value fixed preset control unless you have good\n  reason otherwise\"); the three `<aihu-radio-group-item>` children are\n  hardcoded in `@template`, registered via the primitive package's own\n  `defineRadioGroup()` (imported as a side effect, same registration entry\n  point `before-after.aihu`'s `defineSlider()` call uses).\n\n  No `$prop` is declared: `AihuRadioGroupRoot` owns every attribute this needs\n  (`value` / `default-value` / `name` / `disabled` / `required`, plus the\n  inherited roving-focus `orientation` / `loop` / `dir`) — same \"No $prop\"\n  convention `switch.aihu`/`checkbox.aihu` document. Nothing is selected by\n  default (native radio-group parity: no selection submits nothing); set\n  `default-value=\"balanced\"` to seed one. The control has no built-in\n  accessible name of its own — set `aria-label` directly on the host, e.g.\n  `<aihu-temperature aria-label=\"Response style\">`, same as any plain\n  `role=\"radiogroup\"` element would need.\n\n  `shadow: 'light'` so the composed `<aihu-radio-group-item>` children sit in\n  light DOM where `defineRadioGroup()`'s `customElements.define` takes effect\n  on them directly (same rationale `before-after.aihu`'s header documents for\n  its composed `<aihu-slider-root>`).\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { defineRadioGroup, AihuRadioGroupRoot } from '@aihu/primitives/radio-group'\n\n  base: AihuRadioGroupRoot\n  shadow: 'light'\n\n  defineRadioGroup()\n}\n\n@template {\n  <aihu-radio-group-item class=\"aihu-temperature-item\" value=\"precise\">Precise</aihu-radio-group-item>\n  <aihu-radio-group-item class=\"aihu-temperature-item\" value=\"balanced\">Balanced</aihu-radio-group-item>\n  <aihu-radio-group-item class=\"aihu-temperature-item\" value=\"creative\">Creative</aihu-radio-group-item>\n}\n\n@style {\n  aihu-temperature {\n    display: inline-flex;\n    align-items: center;\n    gap: 2px;\n    padding: 2px;\n    border-radius: var(--radius-pill);\n    /* `--color-secondary` / `--color-secondary-foreground` is a real fill/ink\n       pair (unlike `--color-muted` / `--color-muted-foreground`, which are\n       ramp neighbours, not a pair — see `chat-bubble.aihu`'s header comment\n       for the measured 1.9:1 failure that token combination produces). */\n    background-color: var(--color-secondary);\n  }\n  aihu-temperature[aria-disabled=\"true\"] {\n    opacity: 0.6;\n  }\n  .aihu-temperature-item {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    padding-block: 0.375rem;\n    padding-inline: 0.875rem;\n    border-radius: var(--radius-pill);\n    font-family: var(--font-sans);\n    font-size: 0.8125rem;\n    font-weight: 500;\n    color: var(--color-secondary-foreground);\n    cursor: pointer;\n    user-select: none;\n    transition: background-color 0.15s, color 0.15s, box-shadow 0.15s;\n  }\n  .aihu-temperature-item:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  .aihu-temperature-item[data-state=\"checked\"] {\n    background-color: var(--color-surface);\n    color: var(--color-surface-foreground);\n    box-shadow: 0 1px 2px color-mix(in oklab, var(--color-foreground) 15%, transparent);\n  }\n  .aihu-temperature-item[data-disabled] {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n}\n"
        }
      ],
      "description": "Styled 3-value response-temperature preset picker (Precise / Balanced / Creative) — light-DOM element extending the headless AihuRadioGroupRoot primitive (roving tabindex, arrow-key selection, native form participation).",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": true,
          "overlay": false,
          "directional": true
        }
      }
    },
    {
      "name": "textarea",
      "type": "ui",
      "files": [
        {
          "path": "registry/textarea/textarea.aihu",
          "type": "component",
          "source": "<!--\n  aihu-textarea — presentational styled recipe (Phase 2, master spec §9.7).\n\n  Wraps a NATIVE <textarea> and forwards props. NO `$extends` — the native\n  control plus light DOM is enough for forms. `$shadow: 'light'` so the native\n  <textarea> joins the outer <form>, and the recipe's class-scoped CSS reaches\n  the global cascade. `aihu add` rewrites the `aihu-` prefix at copy time.\n-->\n\n@state {\n  shadow: 'light'\n\n  let placeholder = prop({ default: '' })\n  let name = prop({ default: '' })\n  let value = prop({ default: '' })\n  let rows = prop({ default: '3' })\n  const ariaLabel = prop({ default: '' })\n  let disabled = prop({ default: false })\n  let required = prop({ default: false })\n}\n\n@template {\n  <textarea\n    class=\"aihu-textarea\"\n    placeholder={placeholder}\n    name={name}\n    value={value}\n    rows={rows}\n    aria-label={ariaLabel}\n    disabled={disabled}\n    required={required}></textarea>\n}\n\n@style {\n  .aihu-textarea {\n    min-height: 4rem;\n    width: 100%;\n    padding: var(--space-2) var(--space-3);\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    line-height: 1.25rem;\n    color: var(--color-foreground);\n    background-color: transparent;\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-md);\n    resize: vertical;\n    transition: border-color 0.15s, box-shadow 0.15s;\n  }\n  .aihu-textarea::placeholder {\n    color: var(--color-muted-foreground);\n  }\n  .aihu-textarea:focus-visible {\n    outline: none;\n    border-color: var(--color-ring);\n    box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-ring) 35%, transparent);\n  }\n  .aihu-textarea:disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n  .aihu-textarea[aria-invalid=\"true\"] {\n    border-color: var(--color-destructive);\n  }\n}\n"
        }
      ],
      "description": "Presentational textarea recipe — light-DOM custom element wrapping a native <textarea> that joins the outer form, with token-driven styling.",
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": false,
          "form": true,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "token-stream",
      "type": "ui",
      "files": [
        {
          "path": "registry/token-stream/token-stream.aihu",
          "type": "component",
          "source": "<!--\n  aihu-token-stream — presentational styled recipe (performativeUI port,\n  Slice 4 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  The LLM-response-streaming look: reveals a sentence word by word with a\n  blinking caret at the leading edge, built directly on `@aihu/use/motion`'s\n  `useTokenStream` (Track B Slice 3) — the composable this component exists\n  to showcase.\n\n  text:     space-separated sentence, e.g. \"Reading the whole codebase in\n            under a second.\" Read once at setup (custom-element attrs are\n            strings, not reactive to later attribute changes).\n  interval: milliseconds per token, string-encoded number. Default \"80\".\n  loop:     off (default) | on — restream forever once fully revealed.\n\n  `shadow: 'light'` for live retheming — see the parent execution plan's\n  theming decision. The caret is CSS-only (`quest-text`'s pattern, Slice 1),\n  not driven by JS — it just stops blinking once `isDone()` is true.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let text = prop({ default: 'Reading the whole codebase in under a second.' })\n  let interval = prop({ default: '80' })\n  let loop = prop({ default: 'off' })\n\n  const words = text.split(' ').filter(Boolean)\n  // Read into a differently-named local before use — an options-object key\n  // that's textually identical to a prop name (`loop: loop === 'on'`) trips\n  // the compiler's prop-auto-unwrap rewriter (it misreads the key as a\n  // shorthand-property expansion and emits invalid `let loop: …` output).\n  const shouldLoop = loop === 'on'\n\n  const { tokens, isDone } = useTokenStream(words, {\n    interval: Number(interval),\n    loop: shouldLoop,\n  })\n}\n\n@template {\n  <span\n    data-slot=\"token-stream\"\n    data-done={isDone() ? 'on' : 'off'}\n    class={cn('aihu-token-stream')}>\n    {tokens().join(' ')}\n  </span>\n}\n\n@style {\n  .aihu-token-stream {\n    display: inline;\n    font-family: var(--font-mono);\n    color: var(--color-foreground);\n  }\n  .aihu-token-stream::after {\n    content: '';\n    display: inline-block;\n    width: 0.5em;\n    height: 1em;\n    margin-left: 0.15em;\n    background-color: var(--color-accent);\n    vertical-align: text-bottom;\n    animation: aihu-token-stream-blink 1s step-end infinite;\n  }\n  .aihu-token-stream[data-done=\"on\"]::after {\n    animation: none;\n    opacity: 0;\n  }\n  @keyframes aihu-token-stream-blink {\n    0%,\n    100% {\n      opacity: 1;\n    }\n    50% {\n      opacity: 0;\n    }\n  }\n  @media (prefers-reduced-motion: reduce) {\n    .aihu-token-stream::after {\n      animation: none;\n    }\n  }\n}\n"
        }
      ],
      "description": "Presentational LLM-response-streaming look — reveals a sentence word by word with a blinking caret.",
      "variants": {
        "loop": ["off", "on"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "tooltip",
      "type": "ui",
      "files": [
        {
          "path": "registry/tooltip/tooltip-content.aihu",
          "type": "component",
          "source": "<!--\n  aihu-tooltip-content — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-tooltip-content>` EXTENDS the headless AihuTooltipContent primitive\n  (`role=tooltip`, positions against the trigger via the css-engine shim,\n  reflects `data-state`) via the compiler's `$extends:` macro. Light DOM\n  (`$shadow: 'light'`). Placement positioning is the primitive's job — no\n  side/align variants here.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuTooltipContent } from '@aihu/primitives/tooltip'\n\n  base: AihuTooltipContent\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-tooltip-content {\n    position: fixed;\n    z-index: 50;\n    border-radius: var(--radius-md);\n    background-color: var(--color-primary);\n    color: var(--color-primary-foreground);\n    padding: 0.375rem var(--space-3);\n    font-size: 0.75rem;\n    line-height: 1.4;\n    max-width: 18rem;\n  }\n  aihu-tooltip-content[data-state=\"closed\"] {\n    display: none;\n  }\n}\n"
        },
        {
          "path": "registry/tooltip/tooltip-root.aihu",
          "type": "component",
          "source": "<!--\n  aihu-tooltip-root — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  The state owner of the tooltip machine. `<aihu-tooltip-root>` EXTENDS the\n  headless AihuTooltipRoot primitive (owns `open`/`placement`/delays, provides\n  the tooltip context, reflects `data-state`) via the compiler's `$extends:`\n  macro. Light DOM (`$shadow: 'light'`) so descendant pieces inject the context;\n  `display: contents` keeps the root visually transparent.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuTooltipRoot } from '@aihu/primitives/tooltip'\n\n  base: AihuTooltipRoot\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-tooltip-root {\n    display: contents;\n  }\n}\n"
        },
        {
          "path": "registry/tooltip/tooltip-trigger.aihu",
          "type": "component",
          "source": "<!--\n  aihu-tooltip-trigger — styled recipe piece (Phase 2, master spec §9.4 / §9.7).\n\n  `<aihu-tooltip-trigger>` EXTENDS the headless AihuTooltipTrigger primitive\n  (hover/focus open, Escape dismiss, `aria-describedby` the content) via the\n  compiler's `$extends:` macro. Light DOM (`$shadow: 'light'`) so context\n  injection reaches the ancestor root.\n\n  `aihu add` rewrites the `aihu-` prefix (tag + selectors) at copy time.\n-->\n\n@state {\n  import { AihuTooltipTrigger } from '@aihu/primitives/tooltip'\n\n  base: AihuTooltipTrigger\n  shadow: 'light'\n}\n\n@template {\n  <slot></slot>\n}\n\n@style {\n  aihu-tooltip-trigger {\n    display: inline-flex;\n  }\n}\n"
        }
      ],
      "description": "Styled tooltip recipe — light-DOM pieces extending the headless AihuTooltip primitives (hover/focus open, Escape dismiss, aria-describedby, placement positioning). Non-focus-trapping overlay.",
      "dependencies": ["@aihu/primitives"],
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": false,
          "keyboard": true,
          "form": false,
          "overlay": true,
          "trapsFocus": false,
          "directional": false
        }
      }
    },
    {
      "name": "waitlist-form",
      "type": "ui",
      "files": [
        {
          "path": "registry/waitlist-form/waitlist-form.aihu",
          "type": "component",
          "source": "<!--\n  aihu-waitlist-form — styled recipe (Phase 2, performativeUI port Slice 7 —\n  docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 3).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  An email-capture form with an inline success state after submit.\n\n  NO NETWORK LOGIC HERE — submitting dispatches `waitlist-submit` (detail\n  `{ email: string }`, bubbles, composed) and swaps to the success message;\n  the consumer owns the actual request (and can call `setAttribute('submitted',\n  '')` — see below — or just let the component's own optimistic swap stand,\n  their call).\n\n  DESIGN DECISION — inline state swap, NOT a popover. The roadmap flags this\n  as \"overlay-dependent\"-adjacent and floats a popover for the success state,\n  but a form's own success message is not a disclosure over something else —\n  it doesn't need `role=\"dialog\"`, positioning, outside-dismissal, or any of\n  the overlay primitive's machinery. A `<group if=...>` swap between the form\n  and a `role=\"status\"` message is the honest, simpler surface: it works with\n  zero JS beyond the swap itself, needs no z-index/portal reasoning, and reads\n  correctly to a screen reader via the SAME live-region mechanism a toast\n  would use anyway. Building the popover-backed version here would be pure\n  ceremony over a plain \"swap this text\" requirement.\n\n  DESIGN DECISION — plain native `<input type=\"email\">` / `<button>`, NOT the\n  registry's `input`/`button` recipes and NOT `@aihu/primitives/input` +\n  `@aihu/primitives/form-control`. Three reasons: (1) the registry's OWN\n  `input.aihu` recipe is itself just a styled native `<input>` wrapper with NO\n  `$extends` (\"the native control plus light DOM is enough for forms\" — see\n  its header) — reusing it here would add a cross-recipe dependency for zero\n  behavioral gain over writing the same native element locally; (2)\n  `@aihu/primitives/input`'s `AihuInput` registers under the SAME default\n  `aihu-input` tag the registry's `input.aihu` recipe also compiles to — a\n  real double-registration collision the moment both are loaded together (the\n  same hazard `chat-fab.aihu`'s header documents for popover), avoidable\n  entirely by not registering a custom element for the field at all; (3) a\n  single email field needs exactly the a11y that a real `<label>` WRAPPING a\n  real `<input>` already gives it for free (implicit label association, no id\n  bookkeeping) — `@aihu/primitives/form-control`'s slotted `aria-describedby`/\n  `for` wiring solves a harder problem (multi-piece coordination) this\n  single-field form doesn't have.\n\n  No `submitting` signal: there is no real async operation in this component\n  (the actual network call is the consumer's job, wired off `waitlist-submit`)\n  — the form→success swap is synchronous, so there is no in-flight window a\n  disabled/submitting state would ever cover. `disabled` IS supported (a\n  consumer showing their OWN pending state can set it) — forwarded to both the\n  input and the submit button.\n\n  `shadow: 'light'` — see the parent execution plan's theming decision.\n\n  REAL DEFECTS FOUND AND WORKED AROUND, not framework fixes in scope for this\n  slice:\n\n  1. A bare `required` attribute (no `={...}`) on a template element compiles\n     to the static primitive `required: ''` (`packages/arbor/src/attrs.ts`\n     `_setAttrOrProp`'s \"static primitive\" path). Because `'required' in\n     HTMLInputElement.prototype` is true, that path assigns the DOM PROPERTY\n     (`el.required = ''`), and `required` is a boolean IDL attribute — `''`\n     coerces to `false`, so the constraint SILENTLY NEVER APPLIES. Every other\n     boolean-property attribute in this registry (`disabled`, `checked`, …) is\n     always bound through a real `prop()` boolean (`disabled={disabled}`),\n     which never hits this trap — `required` is only ever written here as a\n     literal `required={true}` for exactly that reason.\n     (`cookbook/form-validation.aihu` has the same bare-`required` shape and\n     is very likely affected too, but fixing a cookbook doc is out of scope\n     here.)\n\n  2. `ref={...}` on an element inside a `<group if=...>` populates its signal\n     LATE — through a SEPARATE `onMount` the compiler registers only once the\n     conditional branch is actually grown, not the synchronous ref-before-\n     onMount assignment `before-after.aihu`'s header documents for an\n     UNconditional top-level ref. A first attempt put `ref={formEl}` on the\n     `<form>` itself (which only exists while `!submitted`) and read it back\n     in an `effect()` — in principle reactive-enough to attach once the ref\n     lands, but it never actually did (empirically verified with a direct\n     `dispatchEvent(new Event('submit', {cancelable:true}))` probe:\n     `defaultPrevented` stayed `false` no matter what). Root-caused as a real,\n     narrow gap in this specific ref-inside-`<group if>`-plus-`effect()`\n     combination — not a framework fix in scope here. WORKED AROUND instead by\n     moving `ref={containerEl}` to the ALWAYS-PRESENT outer `<div>` (never\n     conditional, so it gets the proven synchronous top-level-ref path) and\n     listening for `submit` there: the event BUBBLES up from the\n     conditionally-rendered `<form>` through the light-DOM tree regardless\n     (`shadow: 'light'` has no real ShadowRoot to stop it), so a single\n     container-level listener sees every submit without ever needing a ref\n     into the conditional branch at all.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let label = prop({ default: 'Email' })\n  let placeholder = prop({ default: 'you@example.com' })\n  let buttonLabel = prop({ default: 'Join the waitlist' })\n  let successMessage = prop({ default: \"You're on the list — we'll be in touch.\" })\n  let disabled = prop({ default: false })\n\n  let containerEl = state(null)\n  let submitted = state(false)\n\n  onMount(() => {\n    if (!containerEl) return\n    const container = containerEl\n    const onSubmit = (ev) => {\n      const form = ev.target\n      if (!(form instanceof HTMLFormElement)) return\n      ev.preventDefault()\n      const input = form.querySelector('input[type=\"email\"]')\n      const email = input ? input.value.trim() : ''\n      if (!email) return\n      submitted = true\n      container.dispatchEvent(\n        new CustomEvent('waitlist-submit', {\n          detail: { email },\n          bubbles: true,\n          composed: true,\n        }),\n      )\n    }\n    container.addEventListener('submit', onSubmit)\n  })\n}\n\n@template {\n  <div ref={containerEl} data-slot=\"waitlist-form\" class={cn('aihu-waitlist-form')}>\n    <group if={!submitted}>\n      <form class=\"aihu-waitlist-form-form\">\n        <label class=\"aihu-waitlist-form-label\">\n          <span class=\"aihu-waitlist-form-label-text\">{label}</span>\n          <input\n            type=\"email\"\n            class=\"aihu-waitlist-form-input\"\n            name=\"email\"\n            placeholder={placeholder}\n            required={true}\n            disabled={disabled}\n            autocomplete=\"email\" />\n        </label>\n        <button type=\"submit\" class=\"aihu-waitlist-form-submit\" disabled={disabled}>\n          {buttonLabel}\n        </button>\n      </form>\n    </group>\n    <group if={submitted}>\n      <p class=\"aihu-waitlist-form-success\" role=\"status\">{successMessage}</p>\n    </group>\n  </div>\n}\n\n@style {\n  .aihu-waitlist-form {\n    display: flex;\n    flex-direction: column;\n    gap: var(--space-3);\n    max-width: 24rem;\n  }\n  .aihu-waitlist-form-form {\n    display: flex;\n    flex-wrap: wrap;\n    align-items: flex-end;\n    gap: var(--space-2);\n  }\n  .aihu-waitlist-form-label {\n    display: flex;\n    flex: 1 1 12rem;\n    flex-direction: column;\n    gap: var(--space-1);\n    font-family: var(--font-sans);\n  }\n  .aihu-waitlist-form-label-text {\n    font-size: 0.8125rem;\n    font-weight: 500;\n    color: var(--color-foreground);\n  }\n  .aihu-waitlist-form-input {\n    height: 2.25rem;\n    padding: var(--space-1) var(--space-3);\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    line-height: 1.25rem;\n    color: var(--color-foreground);\n    background-color: var(--color-background);\n    border: 1px solid var(--color-border);\n    border-radius: var(--radius-md);\n    transition: border-color 0.15s, box-shadow 0.15s;\n  }\n  .aihu-waitlist-form-input::placeholder {\n    /* --color-muted-foreground is the packs' lowest-contrast text token\n       (3.14-3.35:1 against this input's --color-background across all four\n       pack x mode combos — fails AA's 4.5:1 floor everywhere) — the same\n       failing token commits 2362b5ea/bc0b0a59 systematically removed from\n       every other registry component. --color-secondary is the same house\n       remedy those commits used for this exact token on prompt/mock-ide/\n       pricing-card's placeholder-shaped text: 6.39-7.23:1 here, comfortably\n       AA in all four combos (see this component's PR for the hand\n       computation against packages/css-engine/styles/aihu-default.css /\n       aihu-graphite.css). */\n    color: var(--color-secondary);\n  }\n  .aihu-waitlist-form-input:focus-visible {\n    outline: none;\n    border-color: var(--color-ring);\n    box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-ring) 35%, transparent);\n  }\n  .aihu-waitlist-form-input:disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n  .aihu-waitlist-form-input:invalid:not(:placeholder-shown) {\n    border-color: var(--color-destructive);\n  }\n  .aihu-waitlist-form-submit {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    height: 2.25rem;\n    padding-inline: 1.25rem;\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    font-weight: 500;\n    color: var(--color-primary-foreground);\n    background-color: var(--color-primary);\n    border: none;\n    border-radius: var(--radius-md);\n    cursor: pointer;\n    white-space: nowrap;\n    transition: filter 0.15s;\n  }\n  .aihu-waitlist-form-submit:hover {\n    filter: brightness(1.06);\n  }\n  .aihu-waitlist-form-submit:focus-visible {\n    outline: 2px solid var(--color-ring);\n    outline-offset: 2px;\n  }\n  .aihu-waitlist-form-submit:disabled {\n    opacity: 0.5;\n    cursor: not-allowed;\n  }\n  .aihu-waitlist-form-success {\n    margin: 0;\n    padding: var(--space-3) var(--space-4);\n    font-family: var(--font-sans);\n    font-size: 0.875rem;\n    /* `--color-success-foreground` is a solid-fill pairing (cream-on-green) —\n       wrong ink for a light TINTED background. `color-mix` toward\n       `--color-foreground` is the same tinted-surface pattern\n       `eyebrow-pill.aihu`'s `tone=\"success\"` rule uses. */\n    color: color-mix(in oklab, var(--color-success) 60%, var(--color-foreground));\n    background-color: color-mix(in oklab, var(--color-success) 12%, transparent);\n    border: 1px solid var(--color-success);\n    border-radius: var(--radius-md);\n  }\n}\n"
        }
      ],
      "description": "Email-capture form with an inline success state — dispatches `waitlist-submit` ({ email }) for the consumer to wire the real request; no popover, no network logic.",
      "meta": {
        "capabilities": {
          "interactive": true,
          "hoverable": true,
          "keyboard": true,
          "form": true,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "wibbling-spinner",
      "type": "ui",
      "files": [
        {
          "path": "registry/wibbling-spinner/wibbling-spinner.aihu",
          "type": "component",
          "source": "<!--\n  aihu-wibbling-spinner — presentational styled recipe (performativeUI port,\n  Slice 4 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  A tiny braille-glyph loading spinner — cycles through a fixed frame set on\n  a short interval via `@aihu/use/motion`'s `useSequence` (Track B Slice 3),\n  rather than a CSS `@keyframes` rotation. Glyph frames read as motion even\n  fully static (each frame's dot pattern implies rotation), so under\n  `prefers-reduced-motion: reduce` it freezes on the first frame instead of\n  cycling — `useSequence` already does this (auto-advance never fires while\n  `prefersReduced()` is true), no extra work needed here.\n\n  `role=\"status\"` on the OUTER element carries an implicit `aria-live=\"polite\"`\n  — applying it to an element whose entire content is the 80ms-churning glyph\n  would announce a content change roughly 12 times per second. The glyph is\n  therefore `aria-hidden=\"true\"` (purely decorative), and the accessible name\n  comes from a separate `sr-only` \"Loading\" span that never changes — the live\n  region only ever announces once, on mount.\n\n  size: sm | md (default) | lg\n  tone: neutral (default) | accent\n\n  `shadow: 'light'` for live retheming — see the parent execution plan's\n  theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let size = prop({ default: 'md' })\n  let tone = prop({ default: 'neutral' })\n\n  const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']\n\n  const { current } = useSequence(FRAMES, { interval: 80 })\n}\n\n@template {\n  <span\n    data-slot=\"wibbling-spinner\"\n    data-size={size}\n    data-tone={tone}\n    role=\"status\"\n    class={cn('aihu-wibbling-spinner')}>\n    <span aria-hidden=\"true\">{current()}</span>\n    <span class=\"sr-only\">Loading</span>\n  </span>\n}\n\n@style {\n  .aihu-wibbling-spinner {\n    display: inline-block;\n    font-family: var(--font-mono);\n    line-height: 1;\n    color: var(--color-neutral);\n  }\n  .aihu-wibbling-spinner[data-tone=\"accent\"] {\n    color: var(--color-accent);\n  }\n  .aihu-wibbling-spinner[data-size=\"sm\"] {\n    font-size: 1rem;\n  }\n  .aihu-wibbling-spinner[data-size=\"md\"] {\n    font-size: 1.5rem;\n  }\n  .aihu-wibbling-spinner[data-size=\"lg\"] {\n    font-size: 2rem;\n  }\n}\n"
        }
      ],
      "description": "Presentational braille-glyph loading spinner — cycles through a fixed frame set on a short interval.",
      "variants": {
        "size": ["sm", "md", "lg"],
        "tone": ["neutral", "accent"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    },
    {
      "name": "word-roll",
      "type": "ui",
      "files": [
        {
          "path": "registry/word-roll/word-roll.aihu",
          "type": "component",
          "source": "<!--\n  aihu-word-roll — presentational styled recipe (performativeUI port,\n  Slice 4 — docs/plans/2026-08-01-performative-ui-port.md §Tier-B batch 1).\n\n  Design and behavior transcribed in spirit from performativeUI (MIT); no\n  source text or `pui-` class names vendored — see NOTICES.md.\n\n  Like `aihu-rotator`, but the new word rolls DOWN into a fixed-height,\n  clipped window instead of cross-fading — `overflow: hidden` + the\n  ported `animate-slide-in-top` utility (tailwind-animations port, Track A)\n  on a freshly-keyed node, rather than `animate-fade-in`.\n\n  items:    comma-separated string, e.g. \"faster,smarter,together\". Read\n            once at setup (custom-element attrs are strings, not reactive\n            to later attribute changes).\n  interval: milliseconds per word, string-encoded number. Default \"1800\".\n  tone:     neutral (default) | accent\n\n  `shadow: 'light'` for live retheming — see the parent execution plan's\n  theming decision.\n-->\n\n@state {\n  import { cn } from '@aihu/css-engine/runtime/cn'\n\n  shadow: 'light'\n\n  let items = prop({ default: 'faster,smarter,together' })\n  let interval = prop({ default: '1800' })\n  let tone = prop({ default: 'neutral' })\n\n  const words = items\n    .split(',')\n    .map((w) => w.trim())\n    .filter(Boolean)\n\n  const { current, index } = useSequence(words, { interval: Number(interval) })\n}\n\n@template {\n  <span data-slot=\"word-roll\" data-tone={tone} class={cn('aihu-word-roll')}>\n    <group each={item of [current()]} key={index()}>\n      <span class={cn('aihu-word-roll-word', 'animate-slide-in-top')}>{item}</span>\n    </group>\n  </span>\n}\n\n@style {\n  .aihu-word-roll {\n    display: inline-block;\n    position: relative;\n    overflow: hidden;\n    height: 1.3em;\n    vertical-align: bottom;\n    font-weight: 600;\n    color: var(--color-foreground);\n  }\n  /* Raw `--color-accent` is only 4.14:1 on `--color-background` in\n     aihu-default light — under the 4.5:1 WCAG 2 AA floor for this\n     normal-weight (600) word. Mixing 30% `--color-foreground` into it keeps\n     the accent hue while lifting every pack x mode to >=6.4:1. */\n  .aihu-word-roll[data-tone=\"accent\"] {\n    color: color-mix(in oklab, var(--color-accent) 70%, var(--color-foreground));\n  }\n  .aihu-word-roll-word {\n    display: inline-block;\n  }\n}\n"
        }
      ],
      "description": "Presentational rolling headline word — cycles through a comma-separated item list, rolling each new word down into a clipped window.",
      "variants": {
        "tone": ["neutral", "accent"]
      },
      "meta": {
        "capabilities": {
          "interactive": false,
          "keyboard": false,
          "form": false,
          "overlay": false,
          "directional": false
        }
      }
    }
  ],
  "extensions": [
    {
      "name": "@aihu-plugin/agent-readiness",
      "version": "2.4.1",
      "description": "Discovery + readiness manifest emitter so agents can introspect aihu apps.",
      "kind": "plugin",
      "provides": ["agent-readiness"],
      "installation": "opt-in",
      "command": "bun add @aihu-plugin/agent-readiness",
      "npm": "https://www.npmjs.com/package/@aihu-plugin/agent-readiness"
    },
    {
      "name": "@aihu-plugin/data",
      "version": "2.0.5",
      "description": "Reactive data loaders and resource primitives for aihu.",
      "kind": "plugin",
      "provides": ["data"],
      "installation": "opt-in",
      "command": "bun add @aihu-plugin/data",
      "npm": "https://www.npmjs.com/package/@aihu-plugin/data"
    },
    {
      "name": "@aihu-plugin/drizzle",
      "version": "0.1.8",
      "description": "Drizzle ORM data adapter for aihu — typed createResource fetchers and defineLoader helpers (Postgres / SQLite / libSQL).",
      "kind": "plugin",
      "provides": ["database"],
      "installation": "opt-in",
      "command": "bun add @aihu-plugin/drizzle",
      "npm": "https://www.npmjs.com/package/@aihu-plugin/drizzle"
    },
    {
      "name": "@aihu-plugin/kindly-note",
      "version": "0.2.4",
      "description": "Runtime syntax highlighting + markdown rendering for aihu — <aihu-code>/<aihu-markdown> custom elements + signal-aware highlight()/renderMarkdown() helpers, powered by published @kindly-note/* packages with lazy loading.",
      "kind": "plugin",
      "provides": ["notes"],
      "installation": "opt-in",
      "command": "bun add @aihu-plugin/kindly-note",
      "npm": "https://www.npmjs.com/package/@aihu-plugin/kindly-note"
    },
    {
      "name": "@aihu/css-engine",
      "version": "0.7.2",
      "description": "aihu CSS engine — Tailwind v4 hard fork with WC-native scoped output.",
      "kind": "provider",
      "provides": ["styling"],
      "installation": "opt-in",
      "command": "bun add @aihu/css-engine",
      "npm": "https://www.npmjs.com/package/@aihu/css-engine"
    },
    {
      "name": "@aihu/plugin",
      "version": "0.1.2",
      "description": "Plugin substrate shared by @aihu/server and the meta-framework — runtime hook surface.",
      "kind": "plugin",
      "provides": ["extension-authoring"],
      "installation": "opt-in",
      "command": "bun add @aihu/plugin",
      "npm": "https://www.npmjs.com/package/@aihu/plugin"
    },
    {
      "name": "@aihu/plugin-demo",
      "version": "0.1.5",
      "description": "Canonical proof-of-life for the @aihu/plugin API — exercises macros, middleware, and transforms.",
      "kind": "plugin",
      "provides": ["example"],
      "installation": "opt-in",
      "command": "bun add @aihu/plugin-demo",
      "npm": "https://www.npmjs.com/package/@aihu/plugin-demo"
    },
    {
      "name": "@aihu/router",
      "version": "0.5.4",
      "description": "File-based router for the aihu meta-framework.",
      "kind": "provider",
      "provides": ["routing"],
      "installation": "opt-in",
      "command": "bun add @aihu/router",
      "npm": "https://www.npmjs.com/package/@aihu/router"
    }
  ]
}
